blob: 2420b639d678b05eab74970f9fd4cee465b1662a [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;
Dan Cashman1dbe6d02018-01-23 11:18:28 -080081import android.util.ByteStringUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070083import android.util.Log;
Dan Cashman1dbe6d02018-01-23 11:18:28 -080084import android.util.PackageUtils;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070085import android.util.Pair;
Kenny Rootd2d29252011-08-08 11:27:57 -070086import android.util.Slog;
Adam Lesinski1665d0f2017-03-10 14:46:57 -080087import android.util.SparseArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088import android.util.TypedValue;
Dan Cashmane92f8422017-12-08 14:02:51 -080089import android.util.apk.ApkSignatureVerifier;
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -070090import android.view.Gravity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070092import com.android.internal.R;
93import com.android.internal.annotations.VisibleForTesting;
Narayan Kamathf9419f02017-06-15 11:35:38 +010094import com.android.internal.os.ClassLoaderFactory;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070095import com.android.internal.util.ArrayUtils;
96import com.android.internal.util.XmlUtils;
97
98import libcore.io.IoUtils;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -070099import libcore.util.EmptyArray;
Svet Ganov087dce22017-09-07 15:42:16 -0700100
Jeff Sharkey9bc89af2017-01-11 11:25:50 -0700101import org.xmlpull.v1.XmlPullParser;
102import org.xmlpull.v1.XmlPullParserException;
103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import java.io.File;
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700105import java.io.FileDescriptor;
Narayan Kamath988149c2016-12-01 13:32:59 +0000106import java.io.FileOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import java.io.IOException;
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -0700108import java.io.PrintWriter;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800109import java.lang.annotation.Retention;
110import java.lang.annotation.RetentionPolicy;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000111import java.lang.reflect.Constructor;
Kenny Root05ca4c92011-09-15 10:36:25 -0700112import java.security.KeyFactory;
113import java.security.NoSuchAlgorithmException;
114import java.security.PublicKey;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800115import java.security.cert.CertificateException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700116import java.security.spec.EncodedKeySpec;
117import java.security.spec.InvalidKeySpecException;
118import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119import java.util.ArrayList;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700120import java.util.Arrays;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700121import java.util.Collections;
122import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -0700124import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800125import java.util.Set;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -0600126import java.util.UUID;
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700127import java.util.concurrent.atomic.AtomicInteger;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128
129/**
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700130 * Parser for package files (APKs) on disk. This supports apps packaged either
131 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
132 * APKs in a single directory.
133 * <p>
134 * Apps packaged as multiple APKs always consist of a single "base" APK (with a
135 * {@code null} split name) and zero or more "split" APKs (with unique split
136 * names). Any subset of those split APKs are a valid install, as long as the
137 * following constraints are met:
138 * <ul>
139 * <li>All APKs must have the exact same package name, version code, and signing
140 * certificates.
141 * <li>All APKs must have unique split names.
142 * <li>All installations must contain a single base APK.
143 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700145 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 */
147public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -0700148 private static final boolean DEBUG_JAR = false;
149 private static final boolean DEBUG_PARSER = false;
150 private static final boolean DEBUG_BACKUP = false;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -0700151 private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE;
152 private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100;
Kenny Rootd2d29252011-08-08 11:27:57 -0700153
Svet Ganova3c4eb32017-04-19 23:51:33 -0700154 private static final String PROPERTY_CHILD_PACKAGES_ENABLED =
155 "persist.sys.child_packages_enabled";
156
Jeff Sharkey3f1790d2017-04-25 18:56:17 -0600157 private static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE &&
Garrett Boyer17041532017-08-01 14:11:02 -0700158 SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false);
Svet Ganova3c4eb32017-04-19 23:51:33 -0700159
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700160 private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
161
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700162 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700163 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700164
Kenny Rootbcc954d2011-08-08 16:19:08 -0700165 /** File name in an APK for the Android manifest. */
Dan Cashmane92f8422017-12-08 14:02:51 -0800166 public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
Kenny Rootbcc954d2011-08-08 16:19:08 -0700167
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700168 /** Path prefix for apps on expanded storage */
169 private static final String MNT_EXPAND = "/mnt/expand/";
170
Svet Ganov354cd3c2015-12-17 11:35:04 -0800171 private static final String TAG_MANIFEST = "manifest";
172 private static final String TAG_APPLICATION = "application";
Adam Lesinski4e862812016-11-21 16:02:24 -0800173 private static final String TAG_PACKAGE_VERIFIER = "package-verifier";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800174 private static final String TAG_OVERLAY = "overlay";
175 private static final String TAG_KEY_SETS = "key-sets";
176 private static final String TAG_PERMISSION_GROUP = "permission-group";
177 private static final String TAG_PERMISSION = "permission";
178 private static final String TAG_PERMISSION_TREE = "permission-tree";
179 private static final String TAG_USES_PERMISSION = "uses-permission";
180 private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
181 private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
182 private static final String TAG_USES_CONFIGURATION = "uses-configuration";
183 private static final String TAG_USES_FEATURE = "uses-feature";
184 private static final String TAG_FEATURE_GROUP = "feature-group";
185 private static final String TAG_USES_SDK = "uses-sdk";
186 private static final String TAG_SUPPORT_SCREENS = "supports-screens";
187 private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
188 private static final String TAG_INSTRUMENTATION = "instrumentation";
189 private static final String TAG_ORIGINAL_PACKAGE = "original-package";
190 private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
191 private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
192 private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
193 private static final String TAG_SUPPORTS_INPUT = "supports-input";
194 private static final String TAG_EAT_COMMENT = "eat-comment";
195 private static final String TAG_PACKAGE = "package";
Todd Kennedyfdd241a2016-04-28 12:26:53 -0700196 private static final String TAG_RESTRICT_UPDATE = "restrict-update";
Adam Lesinski4e862812016-11-21 16:02:24 -0800197 private static final String TAG_USES_SPLIT = "uses-split";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800198
Bryce Lee22571db2017-07-07 15:54:18 -0700199 private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
200
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800201 /**
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700202 * Bit mask of all the valid bits that can be set in recreateOnConfigChanges.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800203 * @hide
204 */
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700205 private static final int RECREATE_ON_CONFIG_CHANGES_MASK =
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800206 ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
207
Svet Ganov354cd3c2015-12-17 11:35:04 -0800208 // These are the tags supported by child packages
209 private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
210 static {
211 CHILD_PACKAGE_TAGS.add(TAG_APPLICATION);
212 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION);
213 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M);
214 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23);
215 CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
216 CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
217 CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
218 CHILD_PACKAGE_TAGS.add(TAG_USES_SDK);
219 CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
220 CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
221 CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE);
222 CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS);
223 CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
224 CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
225 }
226
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700227 private static final boolean LOG_UNSAFE_BROADCASTS = false;
228
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700229 /**
230 * Total number of packages that were read from the cache. We use it only for logging.
231 */
232 public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger();
233
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700234 // Set of broadcast actions that are safe for manifest receivers
235 private static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
236 static {
237 SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
238 }
239
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700240 /** @hide */
Calin Juravle3fc56c32017-12-11 18:26:13 -0800241 public static final String APK_FILE_EXTENSION = ".apk";
242
243 /** @hide */
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700244 public static class NewPermissionInfo {
245 public final String name;
246 public final int sdkVersion;
247 public final int fileVersion;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700248
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700249 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
250 this.name = name;
251 this.sdkVersion = sdkVersion;
252 this.fileVersion = fileVersion;
253 }
254 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700255
256 /** @hide */
257 public static class SplitPermissionInfo {
258 public final String rootPerm;
259 public final String[] newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700260 public final int targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700261
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700262 public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
Dianne Hackborn79245122012-03-12 10:51:26 -0700263 this.rootPerm = rootPerm;
264 this.newPerms = newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700265 this.targetSdk = targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700266 }
267 }
268
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700269 /**
270 * List of new permissions that have been added since 1.0.
271 * NOTE: These must be declared in SDK version order, with permissions
272 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700273 * If sdkVersion is 0, then this is not a permission that we want to
274 * automatically add to older apps, but we do want to allow it to be
275 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700276 * @hide
277 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700278 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
279 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700280 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700281 android.os.Build.VERSION_CODES.DONUT, 0),
282 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
283 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700284 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285
Dianne Hackborn79245122012-03-12 10:51:26 -0700286 /**
287 * List of permissions that have been split into more granular or dependent
288 * permissions.
289 * @hide
290 */
291 public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
292 new PackageParser.SplitPermissionInfo[] {
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700293 // READ_EXTERNAL_STORAGE is always required when an app requests
294 // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
295 // write access without read access. The hack here with the target
296 // target SDK version ensures that this grant is always done.
Dianne Hackborn79245122012-03-12 10:51:26 -0700297 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700298 new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700299 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700300 new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
301 new String[] { android.Manifest.permission.READ_CALL_LOG },
302 android.os.Build.VERSION_CODES.JELLY_BEAN),
303 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
304 new String[] { android.Manifest.permission.WRITE_CALL_LOG },
305 android.os.Build.VERSION_CODES.JELLY_BEAN)
Dianne Hackborn79245122012-03-12 10:51:26 -0700306 };
307
Jeff Sharkey275e0852014-06-17 18:18:49 -0700308 /**
309 * @deprecated callers should move to explicitly passing around source path.
310 */
311 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700315 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700316 private DisplayMetrics mMetrics;
Dianne Hackborncd154e92017-02-28 17:37:35 -0800317 private Callback mCallback;
Narayan Kamath988149c2016-12-01 13:32:59 +0000318 private File mCacheDir;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700319
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700320 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700321 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322
323 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
324
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700325 private static boolean sCompatibilityModeEnabled = true;
Amith Yamasani655d0e22013-06-12 14:19:10 -0700326 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
327 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Todd Kennedy11e45072017-01-25 13:24:21 -0800328 private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700329
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700330 static class ParsePackageItemArgs {
331 final Package owner;
332 final String[] outError;
333 final int nameRes;
334 final int labelRes;
335 final int iconRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700336 final int roundIconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700337 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800338 final int bannerRes;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700339
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700340 String tag;
341 TypedArray sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700342
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700343 ParsePackageItemArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700344 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
345 int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700346 owner = _owner;
347 outError = _outError;
348 nameRes = _nameRes;
349 labelRes = _labelRes;
350 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700351 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800352 bannerRes = _bannerRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700353 roundIconRes = _roundIconRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700354 }
355 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700356
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000357 /** @hide */
358 @VisibleForTesting
359 public static class ParseComponentArgs extends ParsePackageItemArgs {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700360 final String[] sepProcesses;
361 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800362 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700363 final int enabledRes;
364 int flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700365
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000366 public ParseComponentArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700367 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
368 int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800369 String[] _sepProcesses, int _processRes,
370 int _descriptionRes, int _enabledRes) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700371 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes,
372 _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700373 sepProcesses = _sepProcesses;
374 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800375 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700376 enabledRes = _enabledRes;
377 }
378 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800379
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700380 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700381 * Lightweight parsed details about a single package.
382 */
383 public static class PackageLite {
384 public final String packageName;
385 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700386 public final int versionCodeMajor;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700387 public final int installLocation;
388 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700389
390 /** Names of any split APKs, ordered by parsed splitName */
391 public final String[] splitNames;
392
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800393 /** Names of any split APKs that are features. Ordered by splitName */
394 public final boolean[] isFeatureSplits;
395
Adam Lesinski4e862812016-11-21 16:02:24 -0800396 /** Dependencies of any split APKs, ordered by parsed splitName */
397 public final String[] usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800398 public final String[] configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800399
Jeff Sharkey73767b92014-07-04 20:18:13 -0700400 /**
401 * Path where this package was found on disk. For monolithic packages
402 * this is path to single base APK file; for cluster packages this is
403 * path to the cluster directory.
404 */
405 public final String codePath;
406
407 /** Path of base APK */
408 public final String baseCodePath;
409 /** Paths of any split APKs, ordered by parsed splitName */
410 public final String[] splitCodePaths;
411
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800412 /** Revision code of base APK */
413 public final int baseRevisionCode;
414 /** Revision codes of any split APKs, ordered by parsed splitName */
415 public final int[] splitRevisionCodes;
416
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700417 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100418 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100419 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800420 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700421 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800422 public final boolean isolatedSplits;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100423
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700424 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800425 boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100426 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700427 this.packageName = baseApk.packageName;
428 this.versionCode = baseApk.versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700429 this.versionCodeMajor = baseApk.versionCodeMajor;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700430 this.installLocation = baseApk.installLocation;
431 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700432 this.splitNames = splitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800433 this.isFeatureSplits = isFeatureSplits;
Adam Lesinski4e862812016-11-21 16:02:24 -0800434 this.usesSplitNames = usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800435 this.configForSplit = configForSplit;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700436 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700437 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700438 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800439 this.baseRevisionCode = baseApk.revisionCode;
440 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700441 this.coreApp = baseApk.coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100442 this.debuggable = baseApk.debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100443 this.multiArch = baseApk.multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800444 this.use32bitAbi = baseApk.use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700445 this.extractNativeLibs = baseApk.extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800446 this.isolatedSplits = baseApk.isolatedSplits;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700447 }
448
449 public List<String> getAllCodePaths() {
450 ArrayList<String> paths = new ArrayList<>();
451 paths.add(baseCodePath);
452 if (!ArrayUtils.isEmpty(splitCodePaths)) {
453 Collections.addAll(paths, splitCodePaths);
454 }
455 return paths;
456 }
457 }
458
459 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700460 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800461 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700462 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700463 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700464 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700465 public final String splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800466 public boolean isFeatureSplit;
467 public final String configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800468 public final String usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700469 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700470 public final int versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800471 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700472 public final int installLocation;
473 public final VerifierInfo[] verifiers;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800474 public final SigningDetails signingDetails;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700475 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100476 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100477 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800478 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700479 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800480 public final boolean isolatedSplits;
Kenny Root05ca4c92011-09-15 10:36:25 -0700481
Patrick Baumann47117fc2017-12-19 10:17:21 -0800482 public ApkLite(String codePath, String packageName, String splitName,
483 boolean isFeatureSplit,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700484 String configForSplit, String usesSplitName, int versionCode, int versionCodeMajor,
485 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Patrick Baumann47117fc2017-12-19 10:17:21 -0800486 SigningDetails signingDetails, boolean coreApp,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700487 boolean debuggable, boolean multiArch, boolean use32bitAbi,
488 boolean extractNativeLibs, boolean isolatedSplits) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700489 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800490 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700491 this.splitName = splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800492 this.isFeatureSplit = isFeatureSplit;
493 this.configForSplit = configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800494 this.usesSplitName = usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700495 this.versionCode = versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700496 this.versionCodeMajor = versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800497 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800498 this.installLocation = installLocation;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800499 this.signingDetails = signingDetails;
Kenny Root05ca4c92011-09-15 10:36:25 -0700500 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700501 this.coreApp = coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100502 this.debuggable = debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100503 this.multiArch = multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800504 this.use32bitAbi = use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700505 this.extractNativeLibs = extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800506 this.isolatedSplits = isolatedSplits;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800507 }
Dianne Hackborn3accca02013-09-20 09:32:11 -0700508
509 public long getLongVersionCode() {
510 return PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode);
511 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800512 }
513
Garrett Boyer52136662017-05-23 13:47:58 -0700514 /**
515 * Cached parse state for new components.
516 *
517 * Allows reuse of the same parse argument records to avoid GC pressure. Lifetime is carefully
518 * scoped to the parsing of a single application element.
519 */
520 private static class CachedComponentArgs {
521 ParseComponentArgs mActivityArgs;
522 ParseComponentArgs mActivityAliasArgs;
523 ParseComponentArgs mServiceArgs;
524 ParseComponentArgs mProviderArgs;
525 }
526
527 /**
528 * Cached state for parsing instrumentation to avoid GC pressure.
529 *
530 * Must be manually reset to null for each new manifest.
531 */
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700532 private ParsePackageItemArgs mParseInstrumentationArgs;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 /** If set to true, we will only allow package files that exactly match
535 * the DTD. Otherwise, we try to get as much from the package as we
536 * can without failing. This should normally be set to false, to
537 * support extensions to the DTD in future versions. */
538 private static final boolean RIGID_PARSER = false;
539
540 private static final String TAG = "PackageParser";
541
Jeff Sharkey275e0852014-06-17 18:18:49 -0700542 public PackageParser() {
543 mMetrics = new DisplayMetrics();
544 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700545 }
546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547 public void setSeparateProcesses(String[] procs) {
548 mSeparateProcesses = procs;
549 }
550
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700551 /**
552 * Flag indicating this parser should only consider apps with
553 * {@code coreApp} manifest attribute to be valid apps. This is useful when
554 * creating a minimalist boot environment.
555 */
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700556 public void setOnlyCoreApps(boolean onlyCoreApps) {
557 mOnlyCoreApps = onlyCoreApps;
558 }
559
Jeff Sharkey275e0852014-06-17 18:18:49 -0700560 public void setDisplayMetrics(DisplayMetrics metrics) {
561 mMetrics = metrics;
562 }
563
Narayan Kamath988149c2016-12-01 13:32:59 +0000564 /**
565 * Sets the cache directory for this package parser.
566 */
567 public void setCacheDir(File cacheDir) {
568 mCacheDir = cacheDir;
569 }
570
Dianne Hackborncd154e92017-02-28 17:37:35 -0800571 /**
572 * Callback interface for retrieving information that may be needed while parsing
573 * a package.
574 */
575 public interface Callback {
576 boolean hasFeature(String feature);
Jaekyun Seok30dc2a02017-04-11 09:41:11 +0900577 String[] getOverlayPaths(String targetPackageName, String targetPath);
578 String[] getOverlayApks(String targetPackageName);
Dianne Hackborncd154e92017-02-28 17:37:35 -0800579 }
580
581 /**
582 * Standard implementation of {@link Callback} on top of the public {@link PackageManager}
583 * class.
584 */
585 public static final class CallbackImpl implements Callback {
586 private final PackageManager mPm;
587
588 public CallbackImpl(PackageManager pm) {
589 mPm = pm;
590 }
591
592 @Override public boolean hasFeature(String feature) {
593 return mPm.hasSystemFeature(feature);
594 }
Jaekyun Seok30dc2a02017-04-11 09:41:11 +0900595
596 @Override public String[] getOverlayPaths(String targetPackageName, String targetPath) {
597 return null;
598 }
599
600 @Override public String[] getOverlayApks(String targetPackageName) {
601 return null;
602 }
Dianne Hackborncd154e92017-02-28 17:37:35 -0800603 }
604
605 /**
606 * Set the {@link Callback} that can be used while parsing.
607 */
608 public void setCallback(Callback cb) {
609 mCallback = cb;
610 }
611
Jeff Sharkey73767b92014-07-04 20:18:13 -0700612 public static final boolean isApkFile(File file) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700613 return isApkPath(file.getName());
614 }
615
Adam Lesinski4e862812016-11-21 16:02:24 -0800616 public static boolean isApkPath(String path) {
Calin Juravle3fc56c32017-12-11 18:26:13 -0800617 return path.endsWith(APK_FILE_EXTENSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 }
619
620 /**
621 * Generate and return the {@link PackageInfo} for a parsed package.
622 *
623 * @param p the parsed package.
624 * @param flags indicating which optional information is included.
625 */
626 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800627 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svet Ganov3695b8a2015-03-24 16:30:25 -0700628 Set<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629
Amith Yamasani483f3b02012-03-13 16:08:00 -0700630 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700631 grantedPermissions, state, UserHandle.getCallingUserId());
632 }
633
Amith Yamasani655d0e22013-06-12 14:19:10 -0700634 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700635 * Returns true if the package is installed and not hidden, or if the caller
636 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700637 * @param appInfo The applicationInfo of the app being checked.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700638 */
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700639 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
640 ApplicationInfo appInfo) {
641 // If available for the target user, or trying to match uninstalled packages and it's
642 // a system app.
643 return state.isAvailable(flags)
644 || (appInfo != null && appInfo.isSystemApp()
645 && (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0);
Amith Yamasani483f3b02012-03-13 16:08:00 -0700646 }
647
Christopher Tateba629da2013-11-13 17:42:28 -0800648 public static boolean isAvailable(PackageUserState state) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700649 return checkUseInstalledOrHidden(0, state, null);
Christopher Tateba629da2013-11-13 17:42:28 -0800650 }
651
Amith Yamasani13593602012-03-22 16:16:17 -0700652 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700653 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800654 Set<String> grantedPermissions, PackageUserState state, int userId) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700655 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700656 return null;
657 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800658 PackageInfo pi = new PackageInfo();
659 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700660 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661 pi.versionCode = p.mVersionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700662 pi.versionCodeMajor = p.mVersionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800663 pi.baseRevisionCode = p.baseRevisionCode;
664 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665 pi.versionName = p.mVersionName;
666 pi.sharedUserId = p.mSharedUserId;
667 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700668 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800669 pi.installLocation = p.installLocation;
Todd Kennedy7c8addf2017-06-27 14:13:55 -0700670 pi.isStub = p.isStub;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700671 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700672 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
673 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
674 pi.requiredForAllUsers = p.mRequiredForAllUsers;
675 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700676 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700677 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100678 pi.overlayTarget = p.mOverlayTarget;
Adrian Roosc84df772018-01-19 21:20:22 +0100679 pi.overlayCategory = p.mOverlayCategory;
Jaekyun Seok42d53f62017-04-10 13:48:58 +0900680 pi.overlayPriority = p.mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -0800681 pi.mOverlayIsStatic = p.mOverlayIsStatic;
Alan Viveretteb6a25732017-11-21 14:49:24 -0500682 pi.compileSdkVersion = p.mCompileSdkVersion;
683 pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700684 pi.firstInstallTime = firstInstallTime;
685 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686 if ((flags&PackageManager.GET_GIDS) != 0) {
687 pi.gids = gids;
688 }
689 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700690 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 if (N > 0) {
692 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700693 p.configPreferences.toArray(pi.configPreferences);
694 }
695 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
696 if (N > 0) {
697 pi.reqFeatures = new FeatureInfo[N];
698 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800699 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700700 N = p.featureGroups != null ? p.featureGroups.size() : 0;
701 if (N > 0) {
702 pi.featureGroups = new FeatureGroupInfo[N];
703 p.featureGroups.toArray(pi.featureGroups);
704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700706 if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
707 final int N = p.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700709 int num = 0;
710 final ActivityInfo[] res = new ActivityInfo[N];
711 for (int i = 0; i < N; i++) {
712 final Activity a = p.activities.get(i);
713 if (state.isMatch(a.info, flags)) {
714 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715 }
716 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700717 pi.activities = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718 }
719 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700720 if ((flags & PackageManager.GET_RECEIVERS) != 0) {
721 final int N = p.receivers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800722 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700723 int num = 0;
724 final ActivityInfo[] res = new ActivityInfo[N];
725 for (int i = 0; i < N; i++) {
726 final Activity a = p.receivers.get(i);
727 if (state.isMatch(a.info, flags)) {
728 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 }
730 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700731 pi.receivers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 }
733 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700734 if ((flags & PackageManager.GET_SERVICES) != 0) {
735 final int N = p.services.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700737 int num = 0;
738 final ServiceInfo[] res = new ServiceInfo[N];
739 for (int i = 0; i < N; i++) {
740 final Service s = p.services.get(i);
741 if (state.isMatch(s.info, flags)) {
742 res[num++] = generateServiceInfo(s, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 }
744 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700745 pi.services = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 }
747 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700748 if ((flags & PackageManager.GET_PROVIDERS) != 0) {
749 final int N = p.providers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700751 int num = 0;
752 final ProviderInfo[] res = new ProviderInfo[N];
753 for (int i = 0; i < N; i++) {
754 final Provider pr = p.providers.get(i);
755 if (state.isMatch(pr.info, flags)) {
756 res[num++] = generateProviderInfo(pr, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800757 }
758 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700759 pi.providers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 }
761 }
762 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
763 int N = p.instrumentation.size();
764 if (N > 0) {
765 pi.instrumentation = new InstrumentationInfo[N];
766 for (int i=0; i<N; i++) {
767 pi.instrumentation[i] = generateInstrumentationInfo(
768 p.instrumentation.get(i), flags);
769 }
770 }
771 }
772 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
773 int N = p.permissions.size();
774 if (N > 0) {
775 pi.permissions = new PermissionInfo[N];
776 for (int i=0; i<N; i++) {
777 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
778 }
779 }
780 N = p.requestedPermissions.size();
781 if (N > 0) {
782 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800783 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 for (int i=0; i<N; i++) {
Dianne Hackborne639da72012-02-21 15:11:13 -0800785 final String perm = p.requestedPermissions.get(i);
786 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700787 // The notion of required permissions is deprecated but for compatibility.
Svetoslavc6d1c342015-02-26 14:44:43 -0800788 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800789 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
790 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792 }
793 }
794 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800795 // deprecated method of getting signing certificates
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Daniel Cashman5cdda342018-01-19 07:22:52 -0800797 if (p.mSigningDetails.hasPastSigningCertificates()) {
798 // Package has included signing certificate rotation information. Return the oldest
799 // cert so that programmatic checks keep working even if unaware of key rotation.
800 pi.signatures = new Signature[1];
801 pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0];
802 } else if (p.mSigningDetails.hasSignatures()) {
803 // otherwise keep old behavior
Patrick Baumann47117fc2017-12-19 10:17:21 -0800804 int numberOfSigs = p.mSigningDetails.signatures.length;
805 pi.signatures = new Signature[numberOfSigs];
806 System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 }
808 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800809
810 // replacement for GET_SIGNATURES
811 if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
812 if (p.mSigningDetails.hasPastSigningCertificates()) {
813 // Package has included signing certificate rotation information. Convert each
814 // entry to an array
815 int numberOfSigs = p.mSigningDetails.pastSigningCertificates.length;
816 pi.signingCertificateHistory = new Signature[numberOfSigs][];
817 for (int i = 0; i < numberOfSigs; i++) {
818 pi.signingCertificateHistory[i] =
819 new Signature[] { p.mSigningDetails.pastSigningCertificates[i] };
820 }
821 } else if (p.mSigningDetails.hasSignatures()) {
822 // otherwise keep old behavior
823 int numberOfSigs = p.mSigningDetails.signatures.length;
824 pi.signingCertificateHistory = new Signature[1][numberOfSigs];
825 System.arraycopy(p.mSigningDetails.signatures, 0,
826 pi.signingCertificateHistory[0], 0, numberOfSigs);
827 }
828 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 return pi;
830 }
831
Todd Kennedy232d29e2017-11-06 14:45:53 -0800832 public static final int PARSE_MUST_BE_APK = 1 << 0;
833 public static final int PARSE_IGNORE_PROCESSES = 1 << 1;
Todd Kennedy30a23a52018-01-04 13:27:49 -0800834 /** @deprecated forward lock no longer functional. remove. */
835 @Deprecated
Todd Kennedy232d29e2017-11-06 14:45:53 -0800836 public static final int PARSE_FORWARD_LOCK = 1 << 2;
837 public static final int PARSE_EXTERNAL_STORAGE = 1 << 3;
838 public static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
839 public static final int PARSE_COLLECT_CERTIFICATES = 1 << 5;
840 public static final int PARSE_ENFORCE_CODE = 1 << 6;
841 public static final int PARSE_FORCE_SDK = 1 << 7;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800842 public static final int PARSE_CHATTY = 1 << 31;
843
844 @IntDef(flag = true, prefix = { "PARSE_" }, value = {
845 PARSE_CHATTY,
846 PARSE_COLLECT_CERTIFICATES,
847 PARSE_ENFORCE_CODE,
848 PARSE_EXTERNAL_STORAGE,
849 PARSE_FORCE_SDK,
850 PARSE_FORWARD_LOCK,
851 PARSE_IGNORE_PROCESSES,
Todd Kennedy232d29e2017-11-06 14:45:53 -0800852 PARSE_IS_SYSTEM_DIR,
853 PARSE_MUST_BE_APK,
854 })
855 @Retention(RetentionPolicy.SOURCE)
856 public @interface ParseFlags {}
Jeff Sharkey275e0852014-06-17 18:18:49 -0700857
858 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700860 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700861 * Used to sort a set of APKs based on their split names, always placing the
862 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700863 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700864 private static class SplitNameComparator implements Comparator<String> {
865 @Override
866 public int compare(String lhs, String rhs) {
867 if (lhs == null) {
868 return -1;
869 } else if (rhs == null) {
870 return 1;
871 } else {
872 return lhs.compareTo(rhs);
873 }
874 }
875 }
876
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700877 /**
878 * Parse only lightweight details about the package at the given location.
879 * Automatically detects if the package is a monolithic style (single APK
880 * file) or cluster style (directory of APKs).
881 * <p>
882 * This performs sanity checking on cluster style packages, such as
883 * requiring identical package name and version codes, a single base APK,
884 * and unique split names.
885 *
886 * @see PackageParser#parsePackage(File, int)
887 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700888 public static PackageLite parsePackageLite(File packageFile, int flags)
889 throws PackageParserException {
890 if (packageFile.isDirectory()) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800891 return parseClusterPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700892 } else {
Adam Lesinski4e862812016-11-21 16:02:24 -0800893 return parseMonolithicPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700894 }
895 }
896
Adam Lesinski4e862812016-11-21 16:02:24 -0800897 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
898 throws PackageParserException {
Todd Kennedycd029da2016-07-21 07:41:09 -0700899 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Adam Lesinski4e862812016-11-21 16:02:24 -0800900 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700901 final String packagePath = packageFile.getAbsolutePath();
Todd Kennedycd029da2016-07-21 07:41:09 -0700902 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Narayan Kamath96c11c52017-08-09 13:07:21 +0100903 return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700904 }
905
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800906 static PackageLite parseClusterPackageLite(File packageDir, int flags)
Adam Lesinski4e862812016-11-21 16:02:24 -0800907 throws PackageParserException {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700908 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700909 if (ArrayUtils.isEmpty(files)) {
910 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
911 "No packages found in split");
912 }
913
Jeff Sharkey275e0852014-06-17 18:18:49 -0700914 String packageName = null;
915 int versionCode = 0;
916
Todd Kennedycd029da2016-07-21 07:41:09 -0700917 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700918 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700919 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700920 if (isApkFile(file)) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800921 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700922
923 // Assert that all package names and version codes are
924 // consistent with the first one we encounter.
925 if (packageName == null) {
926 packageName = lite.packageName;
927 versionCode = lite.versionCode;
928 } else {
929 if (!packageName.equals(lite.packageName)) {
930 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
931 "Inconsistent package " + lite.packageName + " in " + file
932 + "; expected " + packageName);
933 }
934 if (versionCode != lite.versionCode) {
935 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
936 "Inconsistent version " + lite.versionCode + " in " + file
937 + "; expected " + versionCode);
938 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700939 }
940
Jeff Sharkey275e0852014-06-17 18:18:49 -0700941 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700942 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700943 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
944 "Split name " + lite.splitName
945 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700946 }
947 }
948 }
Todd Kennedycd029da2016-07-21 07:41:09 -0700949 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700950
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700951 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700952 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700953 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700954 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700955 }
956
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700957 // Always apply deterministic ordering based on splitName
958 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700959
Jeff Sharkey73767b92014-07-04 20:18:13 -0700960 String[] splitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800961 boolean[] isFeatureSplits = null;
Adam Lesinski4e862812016-11-21 16:02:24 -0800962 String[] usesSplitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800963 String[] configForSplits = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700964 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800965 int[] splitRevisionCodes = null;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100966 String[] splitClassLoaderNames = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700967 if (size > 0) {
968 splitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800969 isFeatureSplits = new boolean[size];
Adam Lesinski4e862812016-11-21 16:02:24 -0800970 usesSplitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800971 configForSplits = new String[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700972 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800973 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700974
975 splitNames = apks.keySet().toArray(splitNames);
976 Arrays.sort(splitNames, sSplitNameComparator);
977
978 for (int i = 0; i < size; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800979 final ApkLite apk = apks.get(splitNames[i]);
980 usesSplitNames[i] = apk.usesSplitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800981 isFeatureSplits[i] = apk.isFeatureSplit;
982 configForSplits[i] = apk.configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800983 splitCodePaths[i] = apk.codePath;
984 splitRevisionCodes[i] = apk.revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700985 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700986 }
987
Jeff Sharkey73767b92014-07-04 20:18:13 -0700988 final String codePath = packageDir.getAbsolutePath();
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800989 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100990 configForSplits, splitCodePaths, splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700991 }
992
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700993 /**
994 * Parse the package at the given location. Automatically detects if the
995 * package is a monolithic style (single APK file) or cluster style
996 * (directory of APKs).
997 * <p>
998 * This performs sanity checking on cluster style packages, such as
999 * requiring identical package name and version codes, a single base APK,
1000 * and unique split names.
1001 * <p>
1002 * Note that this <em>does not</em> perform signature verification; that
1003 * must be done separately in {@link #collectCertificates(Package, int)}.
1004 *
Narayan Kamath988149c2016-12-01 13:32:59 +00001005 * If {@code useCaches} is true, the package parser might return a cached
1006 * result from a previous parse of the same {@code packageFile} with the same
1007 * {@code flags}. Note that this method does not check whether {@code packageFile}
1008 * has changed since the last parse, it's up to callers to do so.
1009 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001010 * @see #parsePackageLite(File, int)
1011 */
Narayan Kamath988149c2016-12-01 13:32:59 +00001012 public Package parsePackage(File packageFile, int flags, boolean useCaches)
1013 throws PackageParserException {
1014 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
1015 if (parsed != null) {
1016 return parsed;
1017 }
1018
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001019 long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Jeff Sharkey73767b92014-07-04 20:18:13 -07001020 if (packageFile.isDirectory()) {
Narayan Kamath988149c2016-12-01 13:32:59 +00001021 parsed = parseClusterPackage(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001022 } else {
Narayan Kamath988149c2016-12-01 13:32:59 +00001023 parsed = parseMonolithicPackage(packageFile, flags);
1024 }
1025
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001026 long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Narayan Kamath988149c2016-12-01 13:32:59 +00001027 cacheResult(packageFile, flags, parsed);
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001028 if (LOG_PARSE_TIMINGS) {
1029 parseTime = cacheTime - parseTime;
1030 cacheTime = SystemClock.uptimeMillis() - cacheTime;
1031 if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
1032 Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
1033 + "ms, update_cache=" + cacheTime + " ms");
1034 }
1035 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001036 return parsed;
1037 }
1038
1039 /**
1040 * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}.
1041 */
1042 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
1043 return parsePackage(packageFile, flags, false /* useCaches */);
1044 }
1045
1046 /**
1047 * Returns the cache key for a specificied {@code packageFile} and {@code flags}.
1048 */
1049 private String getCacheKey(File packageFile, int flags) {
1050 StringBuilder sb = new StringBuilder(packageFile.getName());
1051 sb.append('-');
1052 sb.append(flags);
1053
1054 return sb.toString();
1055 }
1056
1057 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001058 protected Package fromCacheEntry(byte[] bytes) {
1059 return fromCacheEntryStatic(bytes);
1060 }
1061
1062 /** static version of {@link #fromCacheEntry} for unit tests. */
1063 @VisibleForTesting
1064 public static Package fromCacheEntryStatic(byte[] bytes) {
1065 final Parcel p = Parcel.obtain();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001066 p.unmarshall(bytes, 0, bytes.length);
1067 p.setDataPosition(0);
1068
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001069 final ReadHelper helper = new ReadHelper(p);
1070 helper.startAndInstall();
1071
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001072 PackageParser.Package pkg = new PackageParser.Package(p);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001073
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001074 p.recycle();
1075
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001076 sCachedPackageReadCount.incrementAndGet();
1077
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001078 return pkg;
Narayan Kamath988149c2016-12-01 13:32:59 +00001079 }
1080
1081 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001082 protected byte[] toCacheEntry(Package pkg) {
1083 return toCacheEntryStatic(pkg);
1084
1085 }
1086
1087 /** static version of {@link #toCacheEntry} for unit tests. */
1088 @VisibleForTesting
1089 public static byte[] toCacheEntryStatic(Package pkg) {
1090 final Parcel p = Parcel.obtain();
1091 final WriteHelper helper = new WriteHelper(p);
1092
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001093 pkg.writeToParcel(p, 0 /* flags */);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001094
1095 helper.finishAndUninstall();
1096
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001097 byte[] serialized = p.marshall();
1098 p.recycle();
1099
1100 return serialized;
Narayan Kamath988149c2016-12-01 13:32:59 +00001101 }
1102
1103 /**
1104 * Given a {@code packageFile} and a {@code cacheFile} returns whether the
1105 * cache file is up to date based on the mod-time of both files.
1106 */
1107 private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
1108 try {
1109 // NOTE: We don't use the File.lastModified API because it has the very
1110 // non-ideal failure mode of returning 0 with no excepions thrown.
1111 // The nio2 Files API is a little better but is considerably more expensive.
1112 final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
1113 final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
1114 return pkg.st_mtime < cache.st_mtime;
1115 } catch (ErrnoException ee) {
1116 // The most common reason why stat fails is that a given cache file doesn't
1117 // exist. We ignore that here. It's easy to reason that it's safe to say the
1118 // cache isn't up to date if we see any sort of exception here.
1119 //
1120 // (1) Exception while stating the package file : This should never happen,
1121 // and if it does, we do a full package parse (which is likely to throw the
1122 // same exception).
1123 // (2) Exception while stating the cache file : If the file doesn't exist, the
1124 // cache is obviously out of date. If the file *does* exist, we can't read it.
1125 // We will attempt to delete and recreate it after parsing the package.
1126 if (ee.errno != OsConstants.ENOENT) {
1127 Slog.w("Error while stating package cache : ", ee);
1128 }
1129
1130 return false;
1131 }
1132 }
1133
1134 /**
1135 * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
1136 * or {@code null} if no cached result exists.
1137 */
1138 private Package getCachedResult(File packageFile, int flags) {
1139 if (mCacheDir == null) {
1140 return null;
1141 }
1142
1143 final String cacheKey = getCacheKey(packageFile, flags);
1144 final File cacheFile = new File(mCacheDir, cacheKey);
1145
Narayan Kamath988149c2016-12-01 13:32:59 +00001146 try {
Makoto Onuki48e93162017-08-18 11:00:19 -07001147 // If the cache is not up to date, return null.
1148 if (!isCacheUpToDate(packageFile, cacheFile)) {
1149 return null;
1150 }
1151
Narayan Kamath988149c2016-12-01 13:32:59 +00001152 final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001153 Package p = fromCacheEntry(bytes);
1154 if (mCallback != null) {
1155 String[] overlayApks = mCallback.getOverlayApks(p.packageName);
1156 if (overlayApks != null && overlayApks.length > 0) {
1157 for (String overlayApk : overlayApks) {
1158 // If a static RRO is updated, return null.
1159 if (!isCacheUpToDate(new File(overlayApk), cacheFile)) {
1160 return null;
1161 }
1162 }
1163 }
1164 }
1165 return p;
Makoto Onuki48e93162017-08-18 11:00:19 -07001166 } catch (Throwable e) {
Narayan Kamath21a28382017-01-13 10:34:29 +00001167 Slog.w(TAG, "Error reading package cache: ", e);
Narayan Kamath988149c2016-12-01 13:32:59 +00001168
1169 // If something went wrong while reading the cache entry, delete the cache file
1170 // so that we regenerate it the next time.
1171 cacheFile.delete();
1172 return null;
1173 }
1174 }
1175
1176 /**
1177 * Caches the parse result for {@code packageFile} with flags {@code flags}.
1178 */
1179 private void cacheResult(File packageFile, int flags, Package parsed) {
1180 if (mCacheDir == null) {
1181 return;
1182 }
1183
Makoto Onuki48e93162017-08-18 11:00:19 -07001184 try {
1185 final String cacheKey = getCacheKey(packageFile, flags);
1186 final File cacheFile = new File(mCacheDir, cacheKey);
Narayan Kamath988149c2016-12-01 13:32:59 +00001187
Makoto Onuki48e93162017-08-18 11:00:19 -07001188 if (cacheFile.exists()) {
1189 if (!cacheFile.delete()) {
1190 Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
1191 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001192 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001193
Makoto Onuki48e93162017-08-18 11:00:19 -07001194 final byte[] cacheEntry = toCacheEntry(parsed);
Narayan Kamath988149c2016-12-01 13:32:59 +00001195
Makoto Onuki48e93162017-08-18 11:00:19 -07001196 if (cacheEntry == null) {
1197 return;
1198 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001199
Makoto Onuki48e93162017-08-18 11:00:19 -07001200 try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
1201 fos.write(cacheEntry);
1202 } catch (IOException ioe) {
1203 Slog.w(TAG, "Error writing cache entry.", ioe);
1204 cacheFile.delete();
1205 }
1206 } catch (Throwable e) {
1207 Slog.w(TAG, "Error saving package cache.", e);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001208 }
1209 }
1210
1211 /**
1212 * Parse all APKs contained in the given directory, treating them as a
1213 * single package. This also performs sanity checking, such as requiring
1214 * identical package name and version codes, a single base APK, and unique
1215 * split names.
1216 * <p>
1217 * Note that this <em>does not</em> perform signature verification; that
1218 * must be done separately in {@link #collectCertificates(Package, int)}.
1219 */
1220 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001221 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001222 if (mOnlyCoreApps && !lite.coreApp) {
1223 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1224 "Not a coreApp: " + packageDir);
1225 }
1226
Adam Lesinski4e862812016-11-21 16:02:24 -08001227 // Build the split dependency tree.
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001228 SparseArray<int[]> splitDependencies = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001229 final SplitAssetLoader assetLoader;
1230 if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001231 try {
1232 splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
1233 assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
1234 } catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
1235 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
1236 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001237 } else {
1238 assetLoader = new DefaultSplitAssetLoader(lite, flags);
1239 }
1240
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001241 try {
Adam Lesinski4e862812016-11-21 16:02:24 -08001242 final AssetManager assets = assetLoader.getBaseAssetManager();
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001243 final File baseApk = new File(lite.baseCodePath);
1244 final Package pkg = parseBaseApk(baseApk, assets, flags);
1245 if (pkg == null) {
1246 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1247 "Failed to parse base APK: " + baseApk);
1248 }
1249
1250 if (!ArrayUtils.isEmpty(lite.splitNames)) {
1251 final int num = lite.splitNames.length;
1252 pkg.splitNames = lite.splitNames;
1253 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001254 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001255 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001256 pkg.splitPrivateFlags = new int[num];
Adam Lesinski4e862812016-11-21 16:02:24 -08001257 pkg.applicationInfo.splitNames = pkg.splitNames;
1258 pkg.applicationInfo.splitDependencies = splitDependencies;
Narayan Kamath96c11c52017-08-09 13:07:21 +01001259 pkg.applicationInfo.splitClassLoaderNames = new String[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001260
1261 for (int i = 0; i < num; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -08001262 final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
1263 parseSplitApk(pkg, i, splitAssets, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001264 }
1265 }
1266
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001267 pkg.setCodePath(packageDir.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001268 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001269 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001270 } catch (IOException e) {
1271 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1272 "Failed to get path: " + lite.baseCodePath, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001273 } finally {
Adam Lesinski4e862812016-11-21 16:02:24 -08001274 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001276 }
1277
Jeff Sharkey275e0852014-06-17 18:18:49 -07001278 /**
1279 * Parse the given APK file, treating it as as a single monolithic package.
1280 * <p>
1281 * Note that this <em>does not</em> perform signature verification; that
1282 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001283 *
1284 * @deprecated external callers should move to
1285 * {@link #parsePackage(File, int)}. Eventually this method will
1286 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -07001287 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001288 @Deprecated
Jeff Sharkey275e0852014-06-17 18:18:49 -07001289 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Adam Lesinski56c82be2018-02-09 11:02:04 -08001290 final AssetManager assets = newConfiguredAssetManager();
Adam Lesinski4e862812016-11-21 16:02:24 -08001291 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001292 if (mOnlyCoreApps) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001293 if (!lite.coreApp) {
1294 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1295 "Not a coreApp: " + apkFile);
1296 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001297 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001298
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001299 try {
Adam Lesinski56c82be2018-02-09 11:02:04 -08001300 final Package pkg = parseBaseApk(apkFile, assets, flags);
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001301 pkg.setCodePath(apkFile.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001302 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001303 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001304 } catch (IOException e) {
1305 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1306 "Failed to get path: " + apkFile, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001307 } finally {
Adam Lesinski56c82be2018-02-09 11:02:04 -08001308 IoUtils.closeQuietly(assets);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001309 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001310 }
1311
Adam Lesinski56c82be2018-02-09 11:02:04 -08001312 private static int loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags)
1313 throws PackageParserException {
1314 if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkPath(apkPath)) {
1315 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1316 "Invalid package file: " + apkPath);
1317 }
1318
1319 // The AssetManager guarantees uniqueness for asset paths, so if this asset path
1320 // already exists in the AssetManager, addAssetPath will only return the cookie
1321 // assigned to it.
1322 int cookie = assets.addAssetPath(apkPath);
1323 if (cookie == 0) {
1324 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1325 "Failed adding asset path: " + apkPath);
1326 }
1327 return cookie;
1328 }
1329
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001330 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
1331 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001332 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001333
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07001334 String volumeUuid = null;
1335 if (apkPath.startsWith(MNT_EXPAND)) {
1336 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
1337 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
1338 }
1339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001341 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001342
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001343 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344
Adam Lesinski56c82be2018-02-09 11:02:04 -08001345 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
1346
1347 Resources res = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001348 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 try {
Adam Lesinski56c82be2018-02-09 11:02:04 -08001350 res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001351 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
1352
1353 final String[] outError = new String[1];
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001354 final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001355 if (pkg == null) {
1356 throw new PackageParserException(mParseError,
1357 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001359
Svet Ganov354cd3c2015-12-17 11:35:04 -08001360 pkg.setVolumeUuid(volumeUuid);
1361 pkg.setApplicationVolumeUuid(volumeUuid);
1362 pkg.setBaseCodePath(apkPath);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001363 pkg.setSigningDetails(SigningDetails.UNKNOWN);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001364
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001365 return pkg;
1366
1367 } catch (PackageParserException e) {
1368 throw e;
1369 } catch (Exception e) {
1370 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001371 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001372 } finally {
1373 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 }
1376
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001377 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001378 throws PackageParserException {
1379 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -07001380
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001381 mParseError = PackageManager.INSTALL_SUCCEEDED;
1382 mArchiveSourcePath = apkPath;
1383
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001384 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
1385
Adam Lesinski56c82be2018-02-09 11:02:04 -08001386 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
1387
Adam Lesinski4e862812016-11-21 16:02:24 -08001388 final Resources res;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001389 XmlResourceParser parser = null;
1390 try {
Adam Lesinski63308542017-12-01 18:22:37 -08001391 res = new Resources(assets, mMetrics, null);
Adam Lesinski56c82be2018-02-09 11:02:04 -08001392 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1393 Build.VERSION.RESOURCES_SDK_INT);
1394 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001395
1396 final String[] outError = new String[1];
1397 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
1398 if (pkg == null) {
1399 throw new PackageParserException(mParseError,
1400 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
1401 }
1402
1403 } catch (PackageParserException e) {
1404 throw e;
1405 } catch (Exception e) {
1406 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001407 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001408 } finally {
1409 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001410 }
1411 }
1412
1413 /**
1414 * Parse the manifest of a <em>split APK</em>.
1415 * <p>
1416 * Note that split APKs have many more restrictions on what they're capable
1417 * of doing, so many valid features of a base APK have been carefully
1418 * omitted here.
1419 */
1420 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001421 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
1422 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001423 AttributeSet attrs = parser;
1424
Jeff Sharkey78a13012014-07-15 20:18:34 -07001425 // We parsed manifest tag earlier; just skip past it
Svet Ganov354cd3c2015-12-17 11:35:04 -08001426 parsePackageSplitNames(parser, attrs);
Jeff Sharkey78a13012014-07-15 20:18:34 -07001427
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001428 mParseInstrumentationArgs = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001429
1430 int type;
1431
1432 boolean foundApp = false;
1433
1434 int outerDepth = parser.getDepth();
1435 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1436 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1437 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1438 continue;
1439 }
1440
1441 String tagName = parser.getName();
Adam Lesinski4e862812016-11-21 16:02:24 -08001442 if (tagName.equals(TAG_APPLICATION)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001443 if (foundApp) {
1444 if (RIGID_PARSER) {
1445 outError[0] = "<manifest> has more than one <application>";
1446 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1447 return null;
1448 } else {
1449 Slog.w(TAG, "<manifest> has more than one <application>");
1450 XmlUtils.skipCurrentTag(parser);
1451 continue;
1452 }
1453 }
1454
1455 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001456 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001457 return null;
1458 }
1459
1460 } else if (RIGID_PARSER) {
1461 outError[0] = "Bad element under <manifest>: "
1462 + parser.getName();
1463 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1464 return null;
1465
1466 } else {
1467 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1468 + " at " + mArchiveSourcePath + " "
1469 + parser.getPositionDescription());
1470 XmlUtils.skipCurrentTag(parser);
1471 continue;
1472 }
1473 }
1474
1475 if (!foundApp) {
1476 outError[0] = "<manifest> does not contain an <application>";
1477 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1478 }
1479
1480 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001481 }
1482
Patrick Baumann47117fc2017-12-19 10:17:21 -08001483 /** Parses the public keys from the set of signatures. */
1484 public static ArraySet<PublicKey> toSigningKeys(Signature[] signatures)
1485 throws CertificateException {
1486 ArraySet<PublicKey> keys = new ArraySet<>(signatures.length);
1487 for (int i = 0; i < signatures.length; i++) {
1488 keys.add(signatures[i].getPublicKey());
Todd Kennedy66c55532016-02-26 16:22:11 -08001489 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001490 return keys;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001491 }
1492
1493 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -07001494 * Collect certificates from all the APKs described in the given package,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001495 * populating {@link Package#mSigningDetails}. Also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001496 * contents are signed correctly and consistently.
1497 */
Victor Hsieh5f761242018-01-20 10:30:12 -08001498 public static void collectCertificates(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001499 throws PackageParserException {
Victor Hsieh5f761242018-01-20 10:30:12 -08001500 collectCertificatesInternal(pkg, skipVerify);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001501 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1502 for (int i = 0; i < childCount; i++) {
1503 Package childPkg = pkg.childPackages.get(i);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001504 childPkg.mSigningDetails = pkg.mSigningDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001505 }
1506 }
1507
Victor Hsieh5f761242018-01-20 10:30:12 -08001508 private static void collectCertificatesInternal(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001509 throws PackageParserException {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001510 pkg.mSigningDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001511
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001512 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1513 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001514 collectCertificates(pkg, new File(pkg.baseCodePath), skipVerify);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001515
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001516 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1517 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
Victor Hsieh5f761242018-01-20 10:30:12 -08001518 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001519 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001520 }
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001521 } finally {
1522 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001523 }
1524 }
1525
Victor Hsieh5f761242018-01-20 10:30:12 -08001526 private static void collectCertificates(Package pkg, File apkFile, boolean skipVerify)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001527 throws PackageParserException {
1528 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529
Patrick Baumann47117fc2017-12-19 10:17:21 -08001530 int minSignatureScheme = SigningDetails.SignatureSchemeVersion.JAR;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001531 if (pkg.applicationInfo.isStaticSharedLibrary()) {
Dan Cashmane92f8422017-12-08 14:02:51 -08001532 // must use v2 signing scheme
Patrick Baumann47117fc2017-12-19 10:17:21 -08001533 minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;
Dan Cashmane92f8422017-12-08 14:02:51 -08001534 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001535 SigningDetails verified;
Victor Hsieh5f761242018-01-20 10:30:12 -08001536 if (skipVerify) {
Dan Cashman636ea5e2017-12-18 10:38:20 -08001537 // systemDir APKs are already trusted, save time by not verifying
1538 verified = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts(
1539 apkPath, minSignatureScheme);
1540 } else {
1541 verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme);
1542 }
Dan Cashman636ea5e2017-12-18 10:38:20 -08001543
1544 // Verify that entries are signed consistently with the first pkg
1545 // we encountered. Note that for splits, certificates may have
1546 // already been populated during an earlier parse of a base APK.
Patrick Baumann47117fc2017-12-19 10:17:21 -08001547 if (pkg.mSigningDetails == SigningDetails.UNKNOWN) {
1548 pkg.mSigningDetails = verified;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001549 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001550 if (!Signature.areExactMatch(pkg.mSigningDetails.signatures, verified.signatures)) {
Patrick Baumann9ff55742017-12-14 10:50:18 -08001551 throw new PackageParserException(
1552 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
1553 apkPath + " has mismatched certificates");
1554 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001556 }
1557
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001558 private static AssetManager newConfiguredAssetManager() {
1559 AssetManager assetManager = new AssetManager();
Romain Guy408afbf2017-01-25 10:23:03 -08001560 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 -07001561 Build.VERSION.RESOURCES_SDK_INT);
1562 return assetManager;
1563 }
1564
Jeff Sharkey275e0852014-06-17 18:18:49 -07001565 /**
1566 * Utility method that retrieves lightweight details about a single APK
1567 * file, including package name, split name, and install location.
1568 *
1569 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001570 * @param flags optional parse flags, such as
1571 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001572 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001573 public static ApkLite parseApkLite(File apkFile, int flags)
1574 throws PackageParserException {
Dianne Hackbornca3872c2017-10-30 14:19:32 -07001575 return parseApkLiteInner(apkFile, null, null, flags);
1576 }
1577
1578 /**
1579 * Utility method that retrieves lightweight details about a single APK
1580 * file, including package name, split name, and install location.
1581 *
1582 * @param fd already open file descriptor of an apk file
1583 * @param debugPathName arbitrary text name for this file, for debug output
1584 * @param flags optional parse flags, such as
1585 * {@link #PARSE_COLLECT_CERTIFICATES}
1586 */
1587 public static ApkLite parseApkLite(FileDescriptor fd, String debugPathName, int flags)
1588 throws PackageParserException {
1589 return parseApkLiteInner(null, fd, debugPathName, flags);
1590 }
1591
1592 private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName,
1593 int flags) throws PackageParserException {
1594 final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001595
Adam Lesinskibde1df22018-02-09 11:12:22 -08001596 AssetManager assets = null;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001597 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 try {
Adam Lesinskibde1df22018-02-09 11:12:22 -08001599 assets = newConfiguredAssetManager();
1600 int cookie = fd != null
1601 ? assets.addAssetFd(fd, debugPathName) : assets.addAssetPath(apkPath);
1602 if (cookie == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001603 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1604 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001605 }
1606
Adam Lesinskibde1df22018-02-09 11:12:22 -08001607 final DisplayMetrics metrics = new DisplayMetrics();
1608 metrics.setToDefaults();
1609
1610 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001611
Patrick Baumann47117fc2017-12-19 10:17:21 -08001612 final SigningDetails signingDetails;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001613 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1614 // TODO: factor signature related items out of Package object
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001615 final Package tempPkg = new Package((String) null);
Victor Hsieh5f761242018-01-20 10:30:12 -08001616 final boolean skipVerify = (flags & PARSE_IS_SYSTEM_DIR) != 0;
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001617 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1618 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001619 collectCertificates(tempPkg, apkFile, skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001620 } finally {
1621 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1622 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001623 signingDetails = tempPkg.mSigningDetails;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001624 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001625 signingDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001626 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001627
Jeff Sharkey275e0852014-06-17 18:18:49 -07001628 final AttributeSet attrs = parser;
Patrick Baumann47117fc2017-12-19 10:17:21 -08001629 return parseApkLite(apkPath, parser, attrs, signingDetails);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001630
1631 } catch (XmlPullParserException | IOException | RuntimeException e) {
Dianne Hackborn34041732017-01-31 15:27:13 -08001632 Slog.w(TAG, "Failed to parse " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001633 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1634 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001636 IoUtils.closeQuietly(parser);
Adam Lesinskibde1df22018-02-09 11:12:22 -08001637 IoUtils.closeQuietly(assets);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 }
1640
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001641 private static String validateName(String name, boolean requireSeparator,
1642 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 final int N = name.length();
1644 boolean hasSep = false;
1645 boolean front = true;
1646 for (int i=0; i<N; i++) {
1647 final char c = name.charAt(i);
1648 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1649 front = false;
1650 continue;
1651 }
1652 if (!front) {
1653 if ((c >= '0' && c <= '9') || c == '_') {
1654 continue;
1655 }
1656 }
1657 if (c == '.') {
1658 hasSep = true;
1659 front = true;
1660 continue;
1661 }
1662 return "bad character '" + c + "'";
1663 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001664 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1665 return "Invalid filename";
1666 }
1667 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 ? null : "must have at least one '.' separator";
1669 }
1670
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001671 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
Svet Ganov354cd3c2015-12-17 11:35:04 -08001672 AttributeSet attrs) throws IOException, XmlPullParserException,
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001673 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674
1675 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001676 while ((type = parser.next()) != XmlPullParser.START_TAG
1677 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 }
1679
Kenny Rootd2d29252011-08-08 11:27:57 -07001680 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001681 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1682 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001684 if (!parser.getName().equals(TAG_MANIFEST)) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001685 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1686 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 }
1688
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001689 final String packageName = attrs.getAttributeValue(null, "package");
1690 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001691 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001692 if (error != null) {
1693 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1694 "Invalid manifest package: " + error);
1695 }
1696 }
1697
Jeff Sharkey275e0852014-06-17 18:18:49 -07001698 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001699 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001700 if (splitName.length() == 0) {
1701 splitName = null;
1702 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001703 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001704 if (error != null) {
1705 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1706 "Invalid manifest split: " + error);
1707 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001708 }
1709 }
1710
1711 return Pair.create(packageName.intern(),
1712 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 }
1714
Adam Lesinski4e862812016-11-21 16:02:24 -08001715 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001716 SigningDetails signingDetails)
Adam Lesinski4e862812016-11-21 16:02:24 -08001717 throws IOException, XmlPullParserException, PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001718 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001719
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001720 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001721 int versionCode = 0;
Dianne Hackborn3accca02013-09-20 09:32:11 -07001722 int versionCodeMajor = 0;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001723 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001724 boolean coreApp = false;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001725 boolean debuggable = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001726 boolean multiArch = false;
Selim Gurun2d291d82016-02-05 17:50:53 -08001727 boolean use32bitAbi = false;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001728 boolean extractNativeLibs = true;
Adam Lesinski4e862812016-11-21 16:02:24 -08001729 boolean isolatedSplits = false;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001730 boolean isFeatureSplit = false;
1731 String configForSplit = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001732 String usesSplitName = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001733
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001734 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001735 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001736 if (attr.equals("installLocation")) {
1737 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001738 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001739 } else if (attr.equals("versionCode")) {
1740 versionCode = attrs.getAttributeIntValue(i, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001741 } else if (attr.equals("versionCodeMajor")) {
1742 versionCodeMajor = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001743 } else if (attr.equals("revisionCode")) {
1744 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001745 } else if (attr.equals("coreApp")) {
1746 coreApp = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski4e862812016-11-21 16:02:24 -08001747 } else if (attr.equals("isolatedSplits")) {
1748 isolatedSplits = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001749 } else if (attr.equals("configForSplit")) {
1750 configForSplit = attrs.getAttributeValue(i);
1751 } else if (attr.equals("isFeatureSplit")) {
1752 isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001753 }
1754 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001755
1756 // Only search the tree when the tag is directly below <manifest>
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001757 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001758 final int searchDepth = parser.getDepth() + 1;
1759
1760 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1761 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1762 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1763 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1764 continue;
1765 }
1766
Adam Lesinski4e862812016-11-21 16:02:24 -08001767 if (parser.getDepth() != searchDepth) {
1768 continue;
1769 }
1770
1771 if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
1772 final VerifierInfo verifier = parseVerifier(attrs);
Kenny Root05ca4c92011-09-15 10:36:25 -07001773 if (verifier != null) {
1774 verifiers.add(verifier);
1775 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001776 } else if (TAG_APPLICATION.equals(parser.getName())) {
Narayan Kamatha8755a82014-07-15 12:26:35 +01001777 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1778 final String attr = attrs.getAttributeName(i);
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001779 if ("debuggable".equals(attr)) {
1780 debuggable = attrs.getAttributeBooleanValue(i, false);
1781 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001782 if ("multiArch".equals(attr)) {
1783 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001784 }
Selim Gurun2d291d82016-02-05 17:50:53 -08001785 if ("use32bitAbi".equals(attr)) {
1786 use32bitAbi = attrs.getAttributeBooleanValue(i, false);
Tao Baic9a02372016-01-12 15:02:24 -08001787 }
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001788 if ("extractNativeLibs".equals(attr)) {
1789 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001790 }
1791 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001792 } else if (TAG_USES_SPLIT.equals(parser.getName())) {
1793 if (usesSplitName != null) {
1794 Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
1795 continue;
1796 }
1797
1798 usesSplitName = attrs.getAttributeValue(ANDROID_RESOURCES, "name");
1799 if (usesSplitName == null) {
1800 throw new PackageParserException(
1801 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1802 "<uses-split> tag requires 'android:name' attribute");
1803 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001804 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001805 }
1806
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001807 return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
Dianne Hackborn3accca02013-09-20 09:32:11 -07001808 configForSplit, usesSplitName, versionCode, versionCodeMajor, revisionCode,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001809 installLocation, verifiers, signingDetails, coreApp, debuggable,
Dianne Hackborn3accca02013-09-20 09:32:11 -07001810 multiArch, use32bitAbi, extractNativeLibs, isolatedSplits);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 }
1812
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001813 /**
Svet Ganov354cd3c2015-12-17 11:35:04 -08001814 * Parses a child package and adds it to the parent if successful. If you add
1815 * new tags that need to be supported by child packages make sure to add them
1816 * to {@link #CHILD_PACKAGE_TAGS}.
1817 *
1818 * @param parentPkg The parent that contains the child
1819 * @param res Resources against which to resolve values
1820 * @param parser Parser of the manifest
1821 * @param flags Flags about how to parse
1822 * @param outError Human readable error if parsing fails
1823 * @return True of parsing succeeded.
1824 *
1825 * @throws XmlPullParserException
1826 * @throws IOException
1827 */
1828 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
1829 int flags, String[] outError) throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001830 // Make sure we have a valid child package name
1831 String childPackageName = parser.getAttributeValue(null, "package");
1832 if (validateName(childPackageName, true, false) != null) {
1833 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1834 return false;
1835 }
1836
1837 // Child packages must be unique
1838 if (childPackageName.equals(parentPkg.packageName)) {
1839 String message = "Child package name cannot be equal to parent package name: "
1840 + parentPkg.packageName;
1841 Slog.w(TAG, message);
1842 outError[0] = message;
1843 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1844 return false;
1845 }
1846
1847 // Child packages must be unique
1848 if (parentPkg.hasChildPackage(childPackageName)) {
1849 String message = "Duplicate child package:" + childPackageName;
1850 Slog.w(TAG, message);
1851 outError[0] = message;
1852 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1853 return false;
1854 }
1855
1856 // Go ahead and parse the child
1857 Package childPkg = new Package(childPackageName);
1858
1859 // Child package inherits parent version code/name/target SDK
1860 childPkg.mVersionCode = parentPkg.mVersionCode;
1861 childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
1862 childPkg.mVersionName = parentPkg.mVersionName;
1863 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
Todd Kennedy89d60182016-03-11 11:18:32 -08001864 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001865
1866 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
1867 if (childPkg == null) {
1868 // If we got null then error was set during child parsing
1869 return false;
1870 }
1871
1872 // Set the parent-child relation
1873 if (parentPkg.childPackages == null) {
1874 parentPkg.childPackages = new ArrayList<>();
1875 }
1876 parentPkg.childPackages.add(childPkg);
1877 childPkg.parentPackage = parentPkg;
1878
1879 return true;
1880 }
1881
1882 /**
1883 * Parse the manifest of a <em>base APK</em>. When adding new features you
1884 * need to consider whether they should be supported by split APKs and child
1885 * packages.
1886 *
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001887 * @param apkPath The package apk file path
Svet Ganov354cd3c2015-12-17 11:35:04 -08001888 * @param res The resources from which to resolve values
1889 * @param parser The manifest parser
1890 * @param flags Flags how to parse
1891 * @param outError Human readable error message
1892 * @return Parsed package or null on error.
1893 *
1894 * @throws XmlPullParserException
1895 * @throws IOException
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001896 */
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001897 private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001898 String[] outError) throws XmlPullParserException, IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001899 final String splitName;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001900 final String pkgName;
1901
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001902 try {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001903 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001904 pkgName = packageSplit.first;
1905 splitName = packageSplit.second;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001906
1907 if (!TextUtils.isEmpty(splitName)) {
1908 outError[0] = "Expected base APK, but found split " + splitName;
1909 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1910 return null;
1911 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001912 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1914 return null;
1915 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001916
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001917 if (mCallback != null) {
1918 String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
1919 if (overlayPaths != null && overlayPaths.length > 0) {
1920 for (String overlayPath : overlayPaths) {
1921 res.getAssets().addOverlayPath(overlayPath);
1922 }
1923 }
1924 }
1925
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001926 final Package pkg = new Package(pkgName);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001927
Svet Ganov354cd3c2015-12-17 11:35:04 -08001928 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001929 com.android.internal.R.styleable.AndroidManifest);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001930
Dianne Hackborn3accca02013-09-20 09:32:11 -07001931 pkg.mVersionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001932 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001933 pkg.mVersionCodeMajor = sa.getInteger(
1934 com.android.internal.R.styleable.AndroidManifest_versionCodeMajor, 0);
1935 pkg.applicationInfo.versionCode = pkg.getLongVersionCode();
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001936 pkg.baseRevisionCode = sa.getInteger(
1937 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001938 pkg.mVersionName = sa.getNonConfigurationString(
1939 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001940 if (pkg.mVersionName != null) {
1941 pkg.mVersionName = pkg.mVersionName.intern();
1942 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001943
1944 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
1945
Alan Viveretteb6a25732017-11-21 14:49:24 -05001946 pkg.mCompileSdkVersion = sa.getInteger(
1947 com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0);
1948 pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion;
1949 pkg.mCompileSdkVersionCodename = sa.getNonConfigurationString(
1950 com.android.internal.R.styleable.AndroidManifest_compileSdkVersionCodename, 0);
1951 if (pkg.mCompileSdkVersionCodename != null) {
1952 pkg.mCompileSdkVersionCodename = pkg.mCompileSdkVersionCodename.intern();
1953 }
1954 pkg.applicationInfo.compileSdkVersionCodename = pkg.mCompileSdkVersionCodename;
1955
Svet Ganov354cd3c2015-12-17 11:35:04 -08001956 sa.recycle();
1957
1958 return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
1959 }
1960
1961 /**
1962 * This is the common parsing routing for handling parent and child
1963 * packages in a base APK. The difference between parent and child
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001964 * parsing is that some tags are not supported by child packages as
Svet Ganov354cd3c2015-12-17 11:35:04 -08001965 * well as some manifest attributes are ignored. The implementation
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001966 * assumes the calling code has already handled the manifest tag if needed
Svet Ganov354cd3c2015-12-17 11:35:04 -08001967 * (this applies to the parent only).
1968 *
1969 * @param pkg The package which to populate
1970 * @param acceptedTags Which tags to handle, null to handle all
1971 * @param res Resources against which to resolve values
1972 * @param parser Parser of the manifest
1973 * @param flags Flags about how to parse
1974 * @param outError Human readable error if parsing fails
1975 * @return The package if parsing succeeded or null.
1976 *
1977 * @throws XmlPullParserException
1978 * @throws IOException
1979 */
1980 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
1981 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
1982 IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001983 mParseInstrumentationArgs = null;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001984
1985 int type;
1986 boolean foundApp = false;
1987
1988 TypedArray sa = res.obtainAttributes(parser,
1989 com.android.internal.R.styleable.AndroidManifest);
1990
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001991 String str = sa.getNonConfigurationString(
1992 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
1993 if (str != null && str.length() > 0) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001994 String nameError = validateName(str, true, false);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001995 if (nameError != null && !"android".equals(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001996 outError[0] = "<manifest> specifies bad sharedUserId name \""
1997 + str + "\": " + nameError;
1998 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
1999 return null;
2000 }
2001 pkg.mSharedUserId = str.intern();
2002 pkg.mSharedUserLabel = sa.getResourceId(
2003 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
2004 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08002005
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08002006 pkg.installLocation = sa.getInteger(
2007 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07002008 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002009 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07002010
Todd Kennedy11e45072017-01-25 13:24:21 -08002011 final int targetSandboxVersion = sa.getInteger(
2012 com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion,
2013 PARSE_DEFAULT_TARGET_SANDBOX);
2014 pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion;
Alan Viverettefd274a02014-03-27 15:39:15 -07002015
Kenny Root7cb9be22012-05-30 15:30:37 -07002016 /* Set the global "forward lock" flag */
2017 if ((flags & PARSE_FORWARD_LOCK) != 0) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002018 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
Kenny Root7cb9be22012-05-30 15:30:37 -07002019 }
2020
2021 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07002022 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07002023 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
2024 }
2025
Adam Lesinski4e862812016-11-21 16:02:24 -08002026 if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
2027 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
2028 }
2029
Dianne Hackborn723738c2009-06-25 19:48:04 -07002030 // Resource boolean are -1, so 1 means we don't know the value.
2031 int supportsSmallScreens = 1;
2032 int supportsNormalScreens = 1;
2033 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002034 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002035 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002036 int anyDensity = 1;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002038 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07002039 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2040 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2041 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002042 continue;
2043 }
2044
2045 String tagName = parser.getName();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002046
2047 if (acceptedTags != null && !acceptedTags.contains(tagName)) {
2048 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
2049 + tagName + " at " + mArchiveSourcePath + " "
2050 + parser.getPositionDescription());
2051 XmlUtils.skipCurrentTag(parser);
2052 continue;
2053 }
2054
2055 if (tagName.equals(TAG_APPLICATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002056 if (foundApp) {
2057 if (RIGID_PARSER) {
2058 outError[0] = "<manifest> has more than one <application>";
2059 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2060 return null;
2061 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002062 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002063 XmlUtils.skipCurrentTag(parser);
2064 continue;
2065 }
2066 }
2067
2068 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002069 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002070 return null;
2071 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002072 } else if (tagName.equals(TAG_OVERLAY)) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002073 sa = res.obtainAttributes(parser,
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002074 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
2075 pkg.mOverlayTarget = sa.getString(
2076 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
Adrian Roosc84df772018-01-19 21:20:22 +01002077 pkg.mOverlayCategory = sa.getString(
2078 com.android.internal.R.styleable.AndroidManifestResourceOverlay_category);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002079 pkg.mOverlayPriority = sa.getInt(
2080 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
2081 0);
Adam Lesinskie7334972018-01-17 16:13:52 -08002082 pkg.mOverlayIsStatic = sa.getBoolean(
Jaekyun Seok04342892017-03-02 15:24:19 +09002083 com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
2084 false);
Todd Leeea2f3be2017-03-16 14:00:52 -07002085 final String propName = sa.getString(
2086 com.android.internal.R.styleable
2087 .AndroidManifestResourceOverlay_requiredSystemPropertyName);
2088 final String propValue = sa.getString(
2089 com.android.internal.R.styleable
2090 .AndroidManifestResourceOverlay_requiredSystemPropertyValue);
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002091 sa.recycle();
2092
2093 if (pkg.mOverlayTarget == null) {
2094 outError[0] = "<overlay> does not specify a target package";
2095 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2096 return null;
2097 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002098
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002099 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
2100 outError[0] = "<overlay> priority must be between 0 and 9999";
2101 mParseError =
2102 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2103 return null;
2104 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002105
2106 // check to see if overlay should be excluded based on system property condition
2107 if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
2108 Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
2109 + pkg.baseCodePath+ ": overlay ignored due to required system property: "
2110 + propName + " with value: " + propValue);
2111 return null;
Jaekyun Seok04342892017-03-02 15:24:19 +09002112 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002113
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002114 XmlUtils.skipCurrentTag(parser);
2115
Svet Ganov354cd3c2015-12-17 11:35:04 -08002116 } else if (tagName.equals(TAG_KEY_SETS)) {
2117 if (!parseKeySets(pkg, res, parser, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08002118 return null;
2119 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002120 } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002121 if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002122 return null;
2123 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002124 } else if (tagName.equals(TAG_PERMISSION)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002125 if (!parsePermission(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 return null;
2127 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002128 } else if (tagName.equals(TAG_PERMISSION_TREE)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002129 if (!parsePermissionTree(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002130 return null;
2131 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002132 } else if (tagName.equals(TAG_USES_PERMISSION)) {
2133 if (!parseUsesPermission(pkg, res, parser)) {
Svetoslav96a77162015-04-03 13:58:33 -07002134 return null;
2135 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002136 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
2137 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
2138 if (!parseUsesPermission(pkg, res, parser)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002139 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002140 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002141 } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 ConfigurationInfo cPref = new ConfigurationInfo();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002143 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
2145 cPref.reqTouchScreen = sa.getInt(
2146 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
2147 Configuration.TOUCHSCREEN_UNDEFINED);
2148 cPref.reqKeyboardType = sa.getInt(
2149 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
2150 Configuration.KEYBOARD_UNDEFINED);
2151 if (sa.getBoolean(
2152 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
2153 false)) {
2154 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
2155 }
2156 cPref.reqNavigation = sa.getInt(
2157 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
2158 Configuration.NAVIGATION_UNDEFINED);
2159 if (sa.getBoolean(
2160 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
2161 false)) {
2162 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
2163 }
2164 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002165 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166
2167 XmlUtils.skipCurrentTag(parser);
2168
Svet Ganov354cd3c2015-12-17 11:35:04 -08002169 } else if (tagName.equals(TAG_USES_FEATURE)) {
2170 FeatureInfo fi = parseUsesFeature(res, parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002171 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
2172
Dianne Hackborn49237342009-08-27 20:08:01 -07002173 if (fi.name == null) {
2174 ConfigurationInfo cPref = new ConfigurationInfo();
2175 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002176 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07002177 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07002178
2179 XmlUtils.skipCurrentTag(parser);
2180
Svet Ganov354cd3c2015-12-17 11:35:04 -08002181 } else if (tagName.equals(TAG_FEATURE_GROUP)) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002182 FeatureGroupInfo group = new FeatureGroupInfo();
2183 ArrayList<FeatureInfo> features = null;
2184 final int innerDepth = parser.getDepth();
2185 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2186 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2187 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2188 continue;
2189 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07002190
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002191 final String innerTagName = parser.getName();
2192 if (innerTagName.equals("uses-feature")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002193 FeatureInfo featureInfo = parseUsesFeature(res, parser);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002194 // FeatureGroups are stricter and mandate that
2195 // any <uses-feature> declared are mandatory.
2196 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
2197 features = ArrayUtils.add(features, featureInfo);
2198 } else {
2199 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
2200 " at " + mArchiveSourcePath + " " +
2201 parser.getPositionDescription());
2202 }
2203 XmlUtils.skipCurrentTag(parser);
2204 }
2205
2206 if (features != null) {
2207 group.features = new FeatureInfo[features.size()];
2208 group.features = features.toArray(group.features);
2209 }
2210 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07002211
Svet Ganov354cd3c2015-12-17 11:35:04 -08002212 } else if (tagName.equals(TAG_USES_SDK)) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07002213 if (SDK_VERSION > 0) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002214 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215 com.android.internal.R.styleable.AndroidManifestUsesSdk);
2216
Todd Kennedy4f657082016-06-28 10:31:05 -07002217 int minVers = 1;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002218 String minCode = null;
2219 int targetVers = 0;
2220 String targetCode = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002221
Dianne Hackborn851a5412009-05-08 12:06:44 -07002222 TypedValue val = sa.peekValue(
2223 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
2224 if (val != null) {
2225 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
2226 targetCode = minCode = val.string.toString();
2227 } else {
2228 // If it's not a string, it's an integer.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002229 targetVers = minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002230 }
2231 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002232
Dianne Hackborn851a5412009-05-08 12:06:44 -07002233 val = sa.peekValue(
2234 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
2235 if (val != null) {
2236 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
Todd Kennedy89d60182016-03-11 11:18:32 -08002237 targetCode = val.string.toString();
2238 if (minCode == null) {
2239 minCode = targetCode;
2240 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002241 } else {
2242 // If it's not a string, it's an integer.
2243 targetVers = val.data;
2244 }
2245 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247 sa.recycle();
2248
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002249 final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode,
2250 SDK_VERSION, SDK_CODENAMES, outError);
2251 if (minSdkVersion < 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002252 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2253 return null;
2254 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002255
Patrick Baumannccb20b82018-01-08 13:22:46 -08002256 boolean defaultToCurrentDevBranch = (flags & PARSE_FORCE_SDK) != 0;
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002257 final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002258 targetCode, SDK_CODENAMES, outError, defaultToCurrentDevBranch);
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002259 if (targetSdkVersion < 0) {
2260 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2261 return null;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002262 }
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002263
2264 pkg.applicationInfo.minSdkVersion = minSdkVersion;
2265 pkg.applicationInfo.targetSdkVersion = targetSdkVersion;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266 }
2267
2268 XmlUtils.skipCurrentTag(parser);
2269
Svet Ganov354cd3c2015-12-17 11:35:04 -08002270 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
2271 sa = res.obtainAttributes(parser,
Dianne Hackborn723738c2009-06-25 19:48:04 -07002272 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
2273
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002274 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
2275 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
2276 0);
2277 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
2278 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
2279 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07002280 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
2281 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
2282 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002283
Dianne Hackborn723738c2009-06-25 19:48:04 -07002284 // This is a trick to get a boolean and still able to detect
2285 // if a value was actually set.
2286 supportsSmallScreens = sa.getInteger(
2287 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
2288 supportsSmallScreens);
2289 supportsNormalScreens = sa.getInteger(
2290 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
2291 supportsNormalScreens);
2292 supportsLargeScreens = sa.getInteger(
2293 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
2294 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002295 supportsXLargeScreens = sa.getInteger(
2296 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
2297 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002298 resizeable = sa.getInteger(
2299 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002300 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002301 anyDensity = sa.getInteger(
2302 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
2303 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07002304
2305 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002306
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002307 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002308
Svet Ganov354cd3c2015-12-17 11:35:04 -08002309 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
2310 sa = res.obtainAttributes(parser,
Dianne Hackborn854060af2009-07-09 18:14:31 -07002311 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
2312
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002313 // Note: don't allow this value to be a reference to a resource
2314 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07002315 String name = sa.getNonResourceString(
2316 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
2317
2318 sa.recycle();
2319
Todd Kennedy232d29e2017-11-06 14:45:53 -08002320 if (name != null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002321 if (pkg.protectedBroadcasts == null) {
2322 pkg.protectedBroadcasts = new ArrayList<String>();
2323 }
2324 if (!pkg.protectedBroadcasts.contains(name)) {
2325 pkg.protectedBroadcasts.add(name.intern());
2326 }
2327 }
2328
2329 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002330
Svet Ganov354cd3c2015-12-17 11:35:04 -08002331 } else if (tagName.equals(TAG_INSTRUMENTATION)) {
2332 if (parseInstrumentation(pkg, res, parser, outError) == null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002333 return null;
2334 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002335 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
2336 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002337 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2338
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002339 String orig =sa.getNonConfigurationString(
2340 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002341 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002342 if (pkg.mOriginalPackages == null) {
2343 pkg.mOriginalPackages = new ArrayList<String>();
2344 pkg.mRealPackage = pkg.packageName;
2345 }
2346 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002347 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002348
2349 sa.recycle();
2350
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002351 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002352
Svet Ganov354cd3c2015-12-17 11:35:04 -08002353 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
2354 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002355 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2356
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002357 String name = sa.getNonConfigurationString(
2358 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002359
2360 sa.recycle();
2361
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002362 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002363 if (pkg.mAdoptPermissions == null) {
2364 pkg.mAdoptPermissions = new ArrayList<String>();
2365 }
2366 pkg.mAdoptPermissions.add(name);
2367 }
2368
2369 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002370
Svet Ganov354cd3c2015-12-17 11:35:04 -08002371 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002372 // Just skip this tag
2373 XmlUtils.skipCurrentTag(parser);
2374 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002375
Svet Ganov354cd3c2015-12-17 11:35:04 -08002376 } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002377 // Just skip this tag
2378 XmlUtils.skipCurrentTag(parser);
2379 continue;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002380 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
Michael Wrighteaeb1902013-09-05 18:15:57 -07002381 XmlUtils.skipCurrentTag(parser);
2382 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002383
Svet Ganov354cd3c2015-12-17 11:35:04 -08002384 } else if (tagName.equals(TAG_EAT_COMMENT)) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002385 // Just skip this tag
2386 XmlUtils.skipCurrentTag(parser);
2387 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002388
Svet Ganov354cd3c2015-12-17 11:35:04 -08002389 } else if (tagName.equals(TAG_PACKAGE)) {
Svet Ganova7532cf2016-05-02 08:13:17 -07002390 if (!MULTI_PACKAGE_APK_ENABLED) {
2391 XmlUtils.skipCurrentTag(parser);
2392 continue;
2393 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002394 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
2395 // If parsing a child failed the error is already set
2396 return null;
2397 }
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002398
2399 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
2400 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
2401 sa = res.obtainAttributes(parser,
2402 com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
2403 final String hash = sa.getNonConfigurationString(
2404 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
2405 sa.recycle();
2406
2407 pkg.restrictUpdateHash = null;
2408 if (hash != null) {
2409 final int hashLength = hash.length();
2410 final byte[] hashBytes = new byte[hashLength / 2];
2411 for (int i = 0; i < hashLength; i += 2){
2412 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
2413 + Character.digit(hash.charAt(i + 1), 16));
2414 }
2415 pkg.restrictUpdateHash = hashBytes;
2416 }
2417 }
2418
2419 XmlUtils.skipCurrentTag(parser);
2420
Dianne Hackborn854060af2009-07-09 18:14:31 -07002421 } else if (RIGID_PARSER) {
2422 outError[0] = "Bad element under <manifest>: "
2423 + parser.getName();
2424 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2425 return null;
2426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002427 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002428 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002429 + " at " + mArchiveSourcePath + " "
2430 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002431 XmlUtils.skipCurrentTag(parser);
2432 continue;
2433 }
2434 }
2435
2436 if (!foundApp && pkg.instrumentation.size() == 0) {
2437 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
2438 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
2439 }
2440
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002441 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002442 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002443 for (int ip=0; ip<NP; ip++) {
2444 final PackageParser.NewPermissionInfo npi
2445 = PackageParser.NEW_PERMISSIONS[ip];
2446 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
2447 break;
2448 }
2449 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002450 if (implicitPerms == null) {
2451 implicitPerms = new StringBuilder(128);
2452 implicitPerms.append(pkg.packageName);
2453 implicitPerms.append(": compat added ");
2454 } else {
2455 implicitPerms.append(' ');
2456 }
2457 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002458 pkg.requestedPermissions.add(npi.name);
2459 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002460 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002461 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002462 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002463 }
Dianne Hackborn79245122012-03-12 10:51:26 -07002464
2465 final int NS = PackageParser.SPLIT_PERMISSIONS.length;
2466 for (int is=0; is<NS; is++) {
2467 final PackageParser.SplitPermissionInfo spi
2468 = PackageParser.SPLIT_PERMISSIONS[is];
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -07002469 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
2470 || !pkg.requestedPermissions.contains(spi.rootPerm)) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07002471 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07002472 }
2473 for (int in=0; in<spi.newPerms.length; in++) {
2474 final String perm = spi.newPerms[in];
2475 if (!pkg.requestedPermissions.contains(perm)) {
2476 pkg.requestedPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07002477 }
2478 }
2479 }
2480
Dianne Hackborn723738c2009-06-25 19:48:04 -07002481 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
2482 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002483 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002484 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
2485 }
2486 if (supportsNormalScreens != 0) {
2487 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
2488 }
2489 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
2490 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002491 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002492 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
2493 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002494 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
2495 && pkg.applicationInfo.targetSdkVersion
2496 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
2497 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
2498 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002499 if (resizeable < 0 || (resizeable > 0
2500 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002501 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002502 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
2503 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002504 if (anyDensity < 0 || (anyDensity > 0
2505 && pkg.applicationInfo.targetSdkVersion
2506 >= android.os.Build.VERSION_CODES.DONUT)) {
2507 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07002508 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07002509
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002510 // At this point we can check if an application is not supporting densities and hence
2511 // cannot be windowed / resized. Note that an SDK version of 0 is common for
2512 // pre-Doughnut applications.
2513 if (pkg.applicationInfo.usesCompatibilityMode()) {
Winson Chungd3395382016-12-13 11:49:09 -08002514 adjustPackageToBeUnresizeableAndUnpipable(pkg);
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516 return pkg;
2517 }
2518
Todd Leeea2f3be2017-03-16 14:00:52 -07002519 private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
2520
2521 if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
2522 if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
2523 // malformed condition - incomplete
2524 Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
2525 + "=" + propValue + "' - require both requiredSystemPropertyName"
2526 + " AND requiredSystemPropertyValue to be specified.");
2527 return false;
2528 }
2529 // no valid condition set - so no exclusion criteria, overlay will be included.
2530 return true;
2531 }
2532
2533 // check property value - make sure it is both set and equal to expected value
2534 final String currValue = SystemProperties.get(propName);
2535 return (currValue != null && currValue.equals(propValue));
2536 }
2537
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002538 /**
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002539 * This is a pre-density application which will get scaled - instead of being pixel perfect.
2540 * This type of application is not resizable.
2541 *
2542 * @param pkg The package which needs to be marked as unresizable.
2543 */
Winson Chungd3395382016-12-13 11:49:09 -08002544 private void adjustPackageToBeUnresizeableAndUnpipable(Package pkg) {
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002545 for (Activity a : pkg.activities) {
2546 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -08002547 a.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE;
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002548 }
2549 }
2550
2551 /**
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002552 * Computes the targetSdkVersion to use at runtime. If the package is not
2553 * compatible with this platform, populates {@code outError[0]} with an
2554 * error message.
2555 * <p>
2556 * If {@code targetCode} is not specified, e.g. the value is {@code null},
2557 * then the {@code targetVers} will be returned unmodified.
2558 * <p>
2559 * Otherwise, the behavior varies based on whether the current platform
2560 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2561 * has length > 0:
2562 * <ul>
2563 * <li>If this is a pre-release platform and the value specified by
2564 * {@code targetCode} is contained within the array of allowed pre-release
2565 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2566 * <li>If this is a released platform, this method will return -1 to
2567 * indicate that the package is not compatible with this platform.
2568 * </ul>
2569 *
2570 * @param targetVers targetSdkVersion number, if specified in the
2571 * application manifest, or 0 otherwise
2572 * @param targetCode targetSdkVersion code, if specified in the application
2573 * manifest, or {@code null} otherwise
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002574 * @param platformSdkCodenames array of allowed pre-release SDK codenames
2575 * for this platform
2576 * @param outError output array to populate with error, if applicable
Patrick Baumannccb20b82018-01-08 13:22:46 -08002577 * @param forceCurrentDev if development target code is not available, use the current
2578 * development version by default.
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002579 * @return the targetSdkVersion to use at runtime, or -1 if the package is
2580 * not compatible with this platform
2581 * @hide Exposed for unit testing only.
2582 */
2583 @TestApi
2584 public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002585 @Nullable String targetCode, @NonNull String[] platformSdkCodenames,
2586 @NonNull String[] outError, boolean forceCurrentDev) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002587 // If it's a release SDK, return the version number unmodified.
2588 if (targetCode == null) {
2589 return targetVers;
2590 }
2591
2592 // If it's a pre-release SDK and the codename matches this platform, it
2593 // definitely targets this SDK.
Patrick Baumannccb20b82018-01-08 13:22:46 -08002594 if (ArrayUtils.contains(platformSdkCodenames, targetCode) || forceCurrentDev) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002595 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2596 }
2597
2598 // Otherwise, we're looking at an incompatible pre-release SDK.
2599 if (platformSdkCodenames.length > 0) {
2600 outError[0] = "Requires development platform " + targetCode
2601 + " (current platform is any of "
2602 + Arrays.toString(platformSdkCodenames) + ")";
2603 } else {
2604 outError[0] = "Requires development platform " + targetCode
2605 + " but this is a release platform.";
2606 }
2607 return -1;
2608 }
2609
2610 /**
2611 * Computes the minSdkVersion to use at runtime. If the package is not
2612 * compatible with this platform, populates {@code outError[0]} with an
2613 * error message.
2614 * <p>
2615 * If {@code minCode} is not specified, e.g. the value is {@code null},
2616 * then behavior varies based on the {@code platformSdkVersion}:
2617 * <ul>
2618 * <li>If the platform SDK version is greater than or equal to the
2619 * {@code minVers}, returns the {@code mniVers} unmodified.
2620 * <li>Otherwise, returns -1 to indicate that the package is not
2621 * compatible with this platform.
2622 * </ul>
2623 * <p>
2624 * Otherwise, the behavior varies based on whether the current platform
2625 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2626 * has length > 0:
2627 * <ul>
2628 * <li>If this is a pre-release platform and the value specified by
2629 * {@code targetCode} is contained within the array of allowed pre-release
2630 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2631 * <li>If this is a released platform, this method will return -1 to
2632 * indicate that the package is not compatible with this platform.
2633 * </ul>
2634 *
2635 * @param minVers minSdkVersion number, if specified in the application
2636 * manifest, or 1 otherwise
2637 * @param minCode minSdkVersion code, if specified in the application
2638 * manifest, or {@code null} otherwise
2639 * @param platformSdkVersion platform SDK version number, typically
2640 * Build.VERSION.SDK_INT
2641 * @param platformSdkCodenames array of allowed prerelease SDK codenames
2642 * for this platform
2643 * @param outError output array to populate with error, if applicable
2644 * @return the minSdkVersion to use at runtime, or -1 if the package is not
2645 * compatible with this platform
2646 * @hide Exposed for unit testing only.
2647 */
2648 @TestApi
2649 public static int computeMinSdkVersion(@IntRange(from = 1) int minVers,
2650 @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion,
2651 @NonNull String[] platformSdkCodenames, @NonNull String[] outError) {
2652 // If it's a release SDK, make sure we meet the minimum SDK requirement.
2653 if (minCode == null) {
2654 if (minVers <= platformSdkVersion) {
2655 return minVers;
2656 }
2657
2658 // We don't meet the minimum SDK requirement.
2659 outError[0] = "Requires newer sdk version #" + minVers
2660 + " (current version is #" + platformSdkVersion + ")";
2661 return -1;
2662 }
2663
2664 // If it's a pre-release SDK and the codename matches this platform, we
2665 // definitely meet the minimum SDK requirement.
2666 if (ArrayUtils.contains(platformSdkCodenames, minCode)) {
2667 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2668 }
2669
2670 // Otherwise, we're looking at an incompatible pre-release SDK.
2671 if (platformSdkCodenames.length > 0) {
2672 outError[0] = "Requires development platform " + minCode
2673 + " (current platform is any of "
2674 + Arrays.toString(platformSdkCodenames) + ")";
2675 } else {
2676 outError[0] = "Requires development platform " + minCode
2677 + " but this is a release platform.";
2678 }
2679 return -1;
2680 }
2681
Todd Kennedy27c24fb2015-09-17 16:49:25 -07002682 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002683 FeatureInfo fi = new FeatureInfo();
2684 TypedArray sa = res.obtainAttributes(attrs,
2685 com.android.internal.R.styleable.AndroidManifestUsesFeature);
2686 // Note: don't allow this value to be a reference to a resource
2687 // that may change.
2688 fi.name = sa.getNonResourceString(
2689 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
Jeff Sharkey115d2c12016-02-15 17:25:57 -07002690 fi.version = sa.getInt(
2691 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002692 if (fi.name == null) {
2693 fi.reqGlEsVersion = sa.getInt(
2694 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
2695 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2696 }
2697 if (sa.getBoolean(
2698 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
2699 fi.flags |= FeatureInfo.FLAG_REQUIRED;
2700 }
2701 sa.recycle();
2702 return fi;
2703 }
2704
Svet Ganov67882122016-12-11 16:36:34 -08002705 private boolean parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser,
2706 String[] outError) throws XmlPullParserException, IOException {
2707 TypedArray sa = res.obtainAttributes(parser,
2708 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary);
2709
2710 // Note: don't allow this value to be a reference to a resource that may change.
2711 String lname = sa.getNonResourceString(
2712 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
2713 final int version = sa.getInt(
2714 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002715 String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable
Svet Ganov67882122016-12-11 16:36:34 -08002716 .AndroidManifestUsesStaticLibrary_certDigest);
2717 sa.recycle();
2718
2719 // Since an APK providing a static shared lib can only provide the lib - fail if malformed
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002720 if (lname == null || version < 0 || certSha256Digest == null) {
Svet Ganov67882122016-12-11 16:36:34 -08002721 outError[0] = "Bad uses-static-library declaration name: " + lname + " version: "
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002722 + version + " certDigest" + certSha256Digest;
Svet Ganov67882122016-12-11 16:36:34 -08002723 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2724 XmlUtils.skipCurrentTag(parser);
2725 return false;
2726 }
2727
2728 // Can depend only on one version of the same library
2729 if (pkg.usesStaticLibraries != null && pkg.usesStaticLibraries.contains(lname)) {
2730 outError[0] = "Depending on multiple versions of static library " + lname;
2731 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2732 XmlUtils.skipCurrentTag(parser);
2733 return false;
2734 }
2735
2736 lname = lname.intern();
2737 // We allow ":" delimiters in the SHA declaration as this is the format
2738 // emitted by the certtool making it easy for developers to copy/paste.
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002739 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2740
2741 // Fot apps targeting O-MR1 we require explicit enumeration of all certs.
2742 String[] additionalCertSha256Digests = EmptyArray.STRING;
2743 if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.O) {
2744 additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError);
2745 if (additionalCertSha256Digests == null) {
2746 return false;
2747 }
2748 } else {
2749 XmlUtils.skipCurrentTag(parser);
2750 }
2751
2752 final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1];
2753 certSha256Digests[0] = certSha256Digest;
2754 System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
2755 1, additionalCertSha256Digests.length);
2756
Svet Ganov67882122016-12-11 16:36:34 -08002757 pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname);
Dianne Hackborn3accca02013-09-20 09:32:11 -07002758 pkg.usesStaticLibrariesVersions = ArrayUtils.appendLong(
Svet Ganov8a10ef52017-02-16 20:58:09 -08002759 pkg.usesStaticLibrariesVersions, version, true);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002760 pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
2761 pkg.usesStaticLibrariesCertDigests, certSha256Digests, true);
Svet Ganov67882122016-12-11 16:36:34 -08002762
2763 return true;
2764 }
2765
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002766 private String[] parseAdditionalCertificates(Resources resources, XmlResourceParser parser,
2767 String[] outError) throws XmlPullParserException, IOException {
2768 String[] certSha256Digests = EmptyArray.STRING;
2769
2770 int outerDepth = parser.getDepth();
2771 int type;
2772 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2773 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2774 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2775 continue;
2776 }
2777
2778 final String nodeName = parser.getName();
2779 if (nodeName.equals("additional-certificate")) {
2780 final TypedArray sa = resources.obtainAttributes(parser, com.android.internal.
2781 R.styleable.AndroidManifestAdditionalCertificate);
2782 String certSha256Digest = sa.getNonResourceString(com.android.internal.
2783 R.styleable.AndroidManifestAdditionalCertificate_certDigest);
2784 sa.recycle();
2785
2786 if (TextUtils.isEmpty(certSha256Digest)) {
2787 outError[0] = "Bad additional-certificate declaration with empty"
2788 + " certDigest:" + certSha256Digest;
2789 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2790 XmlUtils.skipCurrentTag(parser);
2791 sa.recycle();
2792 return null;
2793 }
2794
2795 // We allow ":" delimiters in the SHA declaration as this is the format
2796 // emitted by the certtool making it easy for developers to copy/paste.
2797 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2798 certSha256Digests = ArrayUtils.appendElement(String.class,
2799 certSha256Digests, certSha256Digest);
2800 } else {
2801 XmlUtils.skipCurrentTag(parser);
2802 }
2803 }
2804
2805 return certSha256Digests;
2806 }
2807
Svet Ganov354cd3c2015-12-17 11:35:04 -08002808 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
2809 throws XmlPullParserException, IOException {
2810 TypedArray sa = res.obtainAttributes(parser,
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002811 com.android.internal.R.styleable.AndroidManifestUsesPermission);
2812
2813 // Note: don't allow this value to be a reference to a resource
2814 // that may change.
2815 String name = sa.getNonResourceString(
2816 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002817
Christopher Tatefb0676a2013-09-16 16:34:52 -07002818 int maxSdkVersion = 0;
2819 TypedValue val = sa.peekValue(
2820 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
2821 if (val != null) {
2822 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
2823 maxSdkVersion = val.data;
2824 }
2825 }
2826
Dianne Hackborncd154e92017-02-28 17:37:35 -08002827 final String requiredFeature = sa.getNonConfigurationString(
2828 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
2829
2830 final String requiredNotfeature = sa.getNonConfigurationString(
2831 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
2832
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002833 sa.recycle();
2834
Dianne Hackborncd154e92017-02-28 17:37:35 -08002835 XmlUtils.skipCurrentTag(parser);
2836
2837 if (name == null) {
2838 return true;
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002839 }
2840
Dianne Hackborncd154e92017-02-28 17:37:35 -08002841 if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
2842 return true;
2843 }
2844
2845 // Only allow requesting this permission if the platform supports the given feature.
2846 if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
2847 return true;
2848 }
2849
2850 // Only allow requesting this permission if the platform doesn't support the given feature.
2851 if (requiredNotfeature != null && mCallback != null
2852 && mCallback.hasFeature(requiredNotfeature)) {
2853 return true;
2854 }
2855
2856 int index = pkg.requestedPermissions.indexOf(name);
2857 if (index == -1) {
2858 pkg.requestedPermissions.add(name.intern());
2859 } else {
2860 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
2861 + name + " in package: " + pkg.packageName + " at: "
2862 + parser.getPositionDescription());
2863 }
2864
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002865 return true;
2866 }
2867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002868 private static String buildClassName(String pkg, CharSequence clsSeq,
2869 String[] outError) {
2870 if (clsSeq == null || clsSeq.length() <= 0) {
2871 outError[0] = "Empty class name in package " + pkg;
2872 return null;
2873 }
2874 String cls = clsSeq.toString();
2875 char c = cls.charAt(0);
2876 if (c == '.') {
Narayan Kamath07ac1442017-02-10 15:08:07 +00002877 return pkg + cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002878 }
2879 if (cls.indexOf('.') < 0) {
2880 StringBuilder b = new StringBuilder(pkg);
2881 b.append('.');
2882 b.append(cls);
Narayan Kamath07ac1442017-02-10 15:08:07 +00002883 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002884 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002885 return cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002886 }
2887
2888 private static String buildCompoundName(String pkg,
2889 CharSequence procSeq, String type, String[] outError) {
2890 String proc = procSeq.toString();
2891 char c = proc.charAt(0);
2892 if (pkg != null && c == ':') {
2893 if (proc.length() < 2) {
2894 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
2895 + ": must be at least two characters";
2896 return null;
2897 }
2898 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002899 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002900 if (nameError != null) {
2901 outError[0] = "Invalid " + type + " name " + proc + " in package "
2902 + pkg + ": " + nameError;
2903 return null;
2904 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002905 return pkg + proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002906 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002907 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002908 if (nameError != null && !"system".equals(proc)) {
2909 outError[0] = "Invalid " + type + " name " + proc + " in package "
2910 + pkg + ": " + nameError;
2911 return null;
2912 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002913 return proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002914 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002916 private static String buildProcessName(String pkg, String defProc,
2917 CharSequence procSeq, int flags, String[] separateProcesses,
2918 String[] outError) {
2919 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
2920 return defProc != null ? defProc : pkg;
2921 }
2922 if (separateProcesses != null) {
2923 for (int i=separateProcesses.length-1; i>=0; i--) {
2924 String sp = separateProcesses[i];
2925 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
2926 return pkg;
2927 }
2928 }
2929 }
2930 if (procSeq == null || procSeq.length() <= 0) {
2931 return defProc;
2932 }
Makoto Onuki812d188a2017-08-07 09:58:23 -07002933 return TextUtils.safeIntern(buildCompoundName(pkg, procSeq, "process", outError));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002934 }
2935
2936 private static String buildTaskAffinityName(String pkg, String defProc,
2937 CharSequence procSeq, String[] outError) {
2938 if (procSeq == null) {
2939 return defProc;
2940 }
2941 if (procSeq.length() <= 0) {
2942 return null;
2943 }
2944 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
2945 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002946
dcashman989eb3712014-06-17 12:56:12 -07002947 private boolean parseKeySets(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002948 XmlResourceParser parser, String[] outError)
Geremy Condraf1bcca82013-01-07 22:35:24 -08002949 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07002950 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08002951 // all the keys and keysets that we want must be defined here
2952 // so we're going to iterate over the parser and pull out the things we want
2953 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07002954 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002955 int type;
dcashman989eb3712014-06-17 12:56:12 -07002956 String currentKeySet = null;
2957 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
2958 ArraySet<String> upgradeKeySets = new ArraySet<String>();
2959 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
2960 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08002961 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2962 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2963 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07002964 if (parser.getDepth() == currentKeySetDepth) {
2965 currentKeySet = null;
2966 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07002967 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002968 continue;
2969 }
dcashman989eb3712014-06-17 12:56:12 -07002970 String tagName = parser.getName();
2971 if (tagName.equals("key-set")) {
2972 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07002973 outError[0] = "Improperly nested 'key-set' tag at "
2974 + parser.getPositionDescription();
2975 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002976 return false;
2977 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002978 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002979 com.android.internal.R.styleable.AndroidManifestKeySet);
2980 final String keysetName = sa.getNonResourceString(
2981 com.android.internal.R.styleable.AndroidManifestKeySet_name);
2982 definedKeySets.put(keysetName, new ArraySet<String>());
2983 currentKeySet = keysetName;
2984 currentKeySetDepth = parser.getDepth();
2985 sa.recycle();
2986 } else if (tagName.equals("public-key")) {
2987 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002988 outError[0] = "Improperly nested 'key-set' tag at "
2989 + parser.getPositionDescription();
2990 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002991 return false;
2992 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002993 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002994 com.android.internal.R.styleable.AndroidManifestPublicKey);
2995 final String publicKeyName = sa.getNonResourceString(
2996 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002997 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07002998 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
2999 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07003000 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
3001 + " on first use at " + parser.getPositionDescription();
3002 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07003003 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003004 return false;
3005 } else if (encodedKey != null) {
3006 PublicKey currentKey = parsePublicKey(encodedKey);
3007 if (currentKey == null) {
3008 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
3009 + parser.getPositionDescription() + " key-set " + currentKeySet
3010 + " will not be added to the package's defined key-sets.");
3011 sa.recycle();
3012 improperKeySets.add(currentKeySet);
3013 XmlUtils.skipCurrentTag(parser);
3014 continue;
3015 }
3016 if (publicKeys.get(publicKeyName) == null
3017 || publicKeys.get(publicKeyName).equals(currentKey)) {
3018
3019 /* public-key first definition, or matches old definition */
3020 publicKeys.put(publicKeyName, currentKey);
3021 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003022 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07003023 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07003024 + parser.getPositionDescription();
3025 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003026 sa.recycle();
3027 return false;
3028 }
Kenny Root37dca152013-07-10 14:01:49 -07003029 }
dcashman989eb3712014-06-17 12:56:12 -07003030 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003031 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003032 XmlUtils.skipCurrentTag(parser);
3033 } else if (tagName.equals("upgrade-key-set")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003034 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003035 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
3036 String name = sa.getNonResourceString(
3037 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
3038 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003039 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003040 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003041 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07003042 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003043 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07003044 + parser.getPositionDescription();
3045 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003046 return false;
3047 } else {
dcashman989eb3712014-06-17 12:56:12 -07003048 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003049 + " at " + mArchiveSourcePath + " "
3050 + parser.getPositionDescription());
3051 XmlUtils.skipCurrentTag(parser);
3052 continue;
3053 }
3054 }
dcashman989eb3712014-06-17 12:56:12 -07003055 Set<String> publicKeyNames = publicKeys.keySet();
3056 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07003057 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
3058 + "'key-set' and 'public-key' names must be distinct.";
3059 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003060 return false;
3061 }
3062 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
3063 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
3064 final String keySetName = e.getKey();
3065 if (e.getValue().size() == 0) {
3066 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3067 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
3068 + " Not including in package's defined key-sets.");
3069 continue;
3070 } else if (improperKeySets.contains(keySetName)) {
3071 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3072 + "'key-set' " + keySetName + " contained improper 'public-key'"
3073 + " tags. Not including in package's defined key-sets.");
3074 continue;
3075 }
3076 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
3077 for (String s : e.getValue()) {
3078 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08003079 }
3080 }
dcashman989eb3712014-06-17 12:56:12 -07003081 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
3082 owner.mUpgradeKeySets = upgradeKeySets;
3083 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003084 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
3085 + "does not define all 'upgrade-key-set's .";
3086 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003087 return false;
3088 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003089 return true;
3090 }
3091
Dianne Hackborncd154e92017-02-28 17:37:35 -08003092 private boolean parsePermissionGroup(Package owner, int flags, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003093 XmlResourceParser parser, String[] outError)
3094 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003095 PermissionGroup perm = new PermissionGroup(owner);
3096
Svet Ganov354cd3c2015-12-17 11:35:04 -08003097 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003098 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003099 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003100 "<permission-group>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
3102 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003103 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003104 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003105 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
3106 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003107 sa.recycle();
3108 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003109 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003110 }
3111
3112 perm.info.descriptionRes = sa.getResourceId(
3113 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
3114 0);
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003115 perm.info.requestRes = sa.getResourceId(
3116 com.android.internal.R.styleable.AndroidManifestPermissionGroup_request, 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07003117 perm.info.flags = sa.getInt(
3118 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07003119 perm.info.priority = sa.getInt(
3120 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121
3122 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003123
Svet Ganov354cd3c2015-12-17 11:35:04 -08003124 if (!parseAllMetaData(res, parser, "<permission-group>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003125 outError)) {
3126 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003127 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003128 }
3129
3130 owner.permissionGroups.add(perm);
3131
Dianne Hackborncd154e92017-02-28 17:37:35 -08003132 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003133 }
3134
Dianne Hackborncd154e92017-02-28 17:37:35 -08003135 private boolean parsePermission(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003136 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003137 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003138
Svet Ganov354cd3c2015-12-17 11:35:04 -08003139 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003140 com.android.internal.R.styleable.AndroidManifestPermission);
3141
Dianne Hackborncd154e92017-02-28 17:37:35 -08003142 Permission perm = new Permission(owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003143 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003144 "<permission>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 com.android.internal.R.styleable.AndroidManifestPermission_name,
3146 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003147 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003148 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003149 com.android.internal.R.styleable.AndroidManifestPermission_logo,
3150 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003151 sa.recycle();
3152 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003153 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003154 }
3155
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003156 // Note: don't allow this value to be a reference to a resource
3157 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003158 perm.info.group = sa.getNonResourceString(
3159 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
3160 if (perm.info.group != null) {
3161 perm.info.group = perm.info.group.intern();
3162 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003164 perm.info.descriptionRes = sa.getResourceId(
3165 com.android.internal.R.styleable.AndroidManifestPermission_description,
3166 0);
3167
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003168 perm.info.requestRes = sa.getResourceId(
3169 com.android.internal.R.styleable.AndroidManifestPermission_request, 0);
3170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003171 perm.info.protectionLevel = sa.getInt(
3172 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
3173 PermissionInfo.PROTECTION_NORMAL);
3174
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07003175 perm.info.flags = sa.getInt(
3176 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
3177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08003179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180 if (perm.info.protectionLevel == -1) {
3181 outError[0] = "<permission> does not specify protectionLevel";
3182 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003183 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003184 }
Dianne Hackborne639da72012-02-21 15:11:13 -08003185
3186 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
3187
Makoto Onuki700feef2018-02-15 10:59:41 -08003188 if (perm.info.getProtectionFlags() != 0) {
Todd Kennedyc247fa12017-06-02 10:29:22 -07003189 if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_INSTANT) == 0
Chad Brubakera5d70a12017-03-23 11:04:50 -07003190 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0
Chad Brubakerc19706a2016-10-13 15:44:59 -07003191 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
Dianne Hackborne639da72012-02-21 15:11:13 -08003192 PermissionInfo.PROTECTION_SIGNATURE) {
Todd Kennedyc247fa12017-06-02 10:29:22 -07003193 outError[0] = "<permission> protectionLevel specifies a non-instnat flag but is "
Dianne Hackborne639da72012-02-21 15:11:13 -08003194 + "not based on signature type";
3195 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003196 return false;
Dianne Hackborne639da72012-02-21 15:11:13 -08003197 }
3198 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003199
Svet Ganov354cd3c2015-12-17 11:35:04 -08003200 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003201 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003202 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003203 }
3204
3205 owner.permissions.add(perm);
3206
Dianne Hackborncd154e92017-02-28 17:37:35 -08003207 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003208 }
3209
Dianne Hackborncd154e92017-02-28 17:37:35 -08003210 private boolean parsePermissionTree(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003211 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003212 throws XmlPullParserException, IOException {
3213 Permission perm = new Permission(owner);
3214
Svet Ganov354cd3c2015-12-17 11:35:04 -08003215 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003216 com.android.internal.R.styleable.AndroidManifestPermissionTree);
3217
3218 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003219 "<permission-tree>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003220 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
3221 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003222 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003223 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003224 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
3225 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226 sa.recycle();
3227 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003228 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003229 }
3230
3231 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003233 int index = perm.info.name.indexOf('.');
3234 if (index > 0) {
3235 index = perm.info.name.indexOf('.', index+1);
3236 }
3237 if (index < 0) {
3238 outError[0] = "<permission-tree> name has less than three segments: "
3239 + perm.info.name;
3240 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003241 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003242 }
3243
3244 perm.info.descriptionRes = 0;
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003245 perm.info.requestRes = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003246 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
3247 perm.tree = true;
3248
Svet Ganov354cd3c2015-12-17 11:35:04 -08003249 if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003250 outError)) {
3251 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003252 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253 }
3254
3255 owner.permissions.add(perm);
3256
Dianne Hackborncd154e92017-02-28 17:37:35 -08003257 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 }
3259
3260 private Instrumentation parseInstrumentation(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003261 XmlResourceParser parser, String[] outError)
3262 throws XmlPullParserException, IOException {
3263 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003264 com.android.internal.R.styleable.AndroidManifestInstrumentation);
3265
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003266 if (mParseInstrumentationArgs == null) {
3267 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
3268 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
3269 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003270 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003271 com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003272 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
3273 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003274 mParseInstrumentationArgs.tag = "<instrumentation>";
3275 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003276
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003277 mParseInstrumentationArgs.sa = sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003278
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003279 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
3280 new InstrumentationInfo());
3281 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003282 sa.recycle();
3283 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3284 return null;
3285 }
3286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003287 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003288 // Note: don't allow this value to be a reference to a resource
3289 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003290 str = sa.getNonResourceString(
3291 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
3292 a.info.targetPackage = str != null ? str.intern() : null;
3293
Dianne Hackborn34041732017-01-31 15:27:13 -08003294 str = sa.getNonResourceString(
Dianne Hackborn1be53542017-04-28 13:36:00 -07003295 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcesses);
3296 a.info.targetProcesses = str != null ? str.intern() : null;
Dianne Hackborn34041732017-01-31 15:27:13 -08003297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003298 a.info.handleProfiling = sa.getBoolean(
3299 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
3300 false);
3301
3302 a.info.functionalTest = sa.getBoolean(
3303 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
3304 false);
3305
3306 sa.recycle();
3307
3308 if (a.info.targetPackage == null) {
3309 outError[0] = "<instrumentation> does not specify targetPackage";
3310 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3311 return null;
3312 }
3313
Svet Ganov354cd3c2015-12-17 11:35:04 -08003314 if (!parseAllMetaData(res, parser, "<instrumentation>", a,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 outError)) {
3316 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3317 return null;
3318 }
3319
3320 owner.instrumentation.add(a);
3321
3322 return a;
3323 }
3324
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003325 /**
3326 * Parse the {@code application} XML tree at the current parse location in a
3327 * <em>base APK</em> manifest.
3328 * <p>
3329 * When adding new features, carefully consider if they should also be
3330 * supported by split APKs.
3331 */
3332 private boolean parseBaseApplication(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003333 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003334 throws XmlPullParserException, IOException {
3335 final ApplicationInfo ai = owner.applicationInfo;
3336 final String pkgName = owner.applicationInfo.packageName;
3337
Svet Ganov354cd3c2015-12-17 11:35:04 -08003338 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 com.android.internal.R.styleable.AndroidManifestApplication);
3340
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003341 if (!parsePackageItemInfo(owner, ai, outError,
3342 "<application>", sa, false /*nameRequired*/,
3343 com.android.internal.R.styleable.AndroidManifestApplication_name,
3344 com.android.internal.R.styleable.AndroidManifestApplication_label,
3345 com.android.internal.R.styleable.AndroidManifestApplication_icon,
3346 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
3347 com.android.internal.R.styleable.AndroidManifestApplication_logo,
3348 com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
3349 sa.recycle();
3350 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3351 return false;
3352 }
3353
3354 if (ai.name != null) {
Todd Kennedyafb52692016-08-22 15:44:00 -07003355 ai.className = ai.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003356 }
3357
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003358 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003359 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
3360 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003361 if (manageSpaceActivity != null) {
3362 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
3363 outError);
3364 }
3365
Christopher Tate181fafa2009-05-14 11:12:14 -07003366 boolean allowBackup = sa.getBoolean(
3367 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
3368 if (allowBackup) {
3369 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07003370
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003371 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
3372 // and restoreAnyVersion are only relevant if backup is possible for the
3373 // given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003374 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003375 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
3376 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07003377 if (backupAgent != null) {
3378 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07003379 if (DEBUG_BACKUP) {
3380 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003381 + " from " + pkgName + "+" + backupAgent);
3382 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003383
3384 if (sa.getBoolean(
3385 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
3386 true)) {
3387 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
3388 }
3389 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08003390 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
3391 false)) {
3392 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
3393 }
Christopher Tated1de2562014-06-17 17:12:35 -07003394 if (sa.getBoolean(
3395 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
3396 false)) {
3397 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
3398 }
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003399 if (sa.getBoolean(
3400 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
3401 false)) {
3402 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
3403 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003404 }
Matthew Williams303650c2015-04-17 18:22:51 -07003405
3406 TypedValue v = sa.peekValue(
3407 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
3408 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
3409 if (DEBUG_BACKUP) {
3410 Slog.v(TAG, "fullBackupContent specified as boolean=" +
3411 (v.data == 0 ? "false" : "true"));
3412 }
3413 // "false" => -1, "true" => 0
3414 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
3415 }
3416 if (DEBUG_BACKUP) {
3417 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
3418 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003419 }
Christopher Tate4a627c72011-04-01 14:43:32 -07003420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003421 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08003422 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003423 ai.descriptionRes = sa.getResourceId(
3424 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
3425
Todd Kennedy232d29e2017-11-06 14:45:53 -08003426 if (sa.getBoolean(
3427 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
3428 false)) {
3429 // Check if persistence is based on a feature being present
3430 final String requiredFeature = sa.getNonResourceString(com.android.internal.R.styleable
3431 .AndroidManifestApplication_persistentWhenFeatureAvailable);
3432 if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
3433 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003434 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07003435 }
3436
3437 if (sa.getBoolean(
3438 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
3439 false)) {
3440 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07003441 }
3442
3443 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
3444 .AndroidManifestApplication_restrictedAccountType);
3445 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
3446 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003447 }
3448
Amith Yamasaniccbe3892013-04-12 17:52:42 -07003449 String requiredAccountType = sa.getString(com.android.internal.R.styleable
3450 .AndroidManifestApplication_requiredAccountType);
3451 if (requiredAccountType != null && requiredAccountType.length() > 0) {
3452 owner.mRequiredAccountType = requiredAccountType;
3453 }
3454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003455 if (sa.getBoolean(
3456 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
3457 false)) {
3458 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
3459 }
3460
3461 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07003462 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08003463 false)) {
3464 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
3465 }
3466
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003467 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07003468 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07003469 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07003470 if (owner.baseHardwareAccelerated) {
3471 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
3472 }
Romain Guy812ccbe2010-06-01 14:07:24 -07003473
3474 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003475 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
3476 true)) {
3477 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
3478 }
3479
3480 if (sa.getBoolean(
3481 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
3482 false)) {
3483 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
3484 }
3485
3486 if (sa.getBoolean(
3487 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
3488 true)) {
3489 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
3490 }
3491
Svet Ganov354cd3c2015-12-17 11:35:04 -08003492 // The parent package controls installation, hence specify test only installs.
3493 if (owner.parentPackage == null) {
3494 if (sa.getBoolean(
3495 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
3496 false)) {
3497 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
3498 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003499 }
3500
Jason parksa3cdaa52011-01-13 14:15:43 -06003501 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003502 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06003503 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003504 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06003505 }
3506
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003507 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07003508 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
3509 true)) {
3510 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
3511 }
3512
3513 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003514 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
3515 false /* default is no RTL support*/)) {
3516 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
3517 }
3518
Narayan Kamath589a1bc2014-07-03 14:43:26 +01003519 if (sa.getBoolean(
3520 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
3521 false)) {
3522 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
3523 }
3524
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07003525 if (sa.getBoolean(
3526 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
3527 true)) {
3528 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
3529 }
3530
Todd Kennedyd022ac22016-04-13 10:49:29 -07003531 if (sa.getBoolean(
3532 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
3533 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003534 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003535 }
Todd Kennedyd022ac22016-04-13 10:49:29 -07003536 if (sa.getBoolean(
3537 R.styleable.AndroidManifestApplication_directBootAware,
3538 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003539 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003540 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003541
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003542 if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
3543 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003544 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
3545 } else {
3546 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003547 }
3548 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003549 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwale6afdf912016-01-30 13:01:33 -08003550 }
3551
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07003552 ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
3553
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003554 ai.networkSecurityConfigRes = sa.getResourceId(
3555 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
3556 0);
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07003557 ai.category = sa.getInt(
3558 com.android.internal.R.styleable.AndroidManifestApplication_appCategory,
3559 ApplicationInfo.CATEGORY_UNDEFINED);
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003561 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003562 str = sa.getNonConfigurationString(
3563 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003564 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
3565
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003566 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3567 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003568 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
3569 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003570 } else {
3571 // Some older apps have been seen to use a resource reference
3572 // here that on older builds was ignored (with a warning). We
3573 // need to continue to do this for them so they don't break.
3574 str = sa.getNonResourceString(
3575 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
3576 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
3578 str, outError);
Jason Monka80bfb52017-11-16 17:15:37 -05003579 String factory = sa.getNonResourceString(
3580 com.android.internal.R.styleable.AndroidManifestApplication_appComponentFactory);
3581 if (factory != null) {
3582 ai.appComponentFactory = buildClassName(ai.packageName, factory, outError);
3583 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003584
3585 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003586 CharSequence pname;
3587 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3588 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003589 com.android.internal.R.styleable.AndroidManifestApplication_process,
3590 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003591 } else {
3592 // Some older apps have been seen to use a resource reference
3593 // here that on older builds was ignored (with a warning). We
3594 // need to continue to do this for them so they don't break.
3595 pname = sa.getNonResourceString(
3596 com.android.internal.R.styleable.AndroidManifestApplication_process);
3597 }
3598 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599 flags, mSeparateProcesses, outError);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003600
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003601 ai.enabled = sa.getBoolean(
3602 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003603
Jose Lima12d0b4c2014-03-14 16:55:12 -07003604 if (sa.getBoolean(
3605 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
3606 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
3607 }
3608
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003609 if (sa.getBoolean(
3610 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
3611 false)) {
3612 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07003613
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003614 // A heavy-weight application can not be in a custom process.
3615 // We can do direct compare because we intern all strings.
3616 if (ai.processName != null && !ai.processName.equals(ai.packageName)) {
3617 outError[0] = "cantSaveState applications can not use custom processes";
Dianne Hackborn860755f2010-06-03 18:47:52 -07003618 }
3619 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003620 }
3621
Adam Powell269248d2011-08-02 10:26:54 -07003622 ai.uiOptions = sa.getInt(
3623 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
3624
Narayan Kamath96c11c52017-08-09 13:07:21 +01003625 ai.classLoaderName = sa.getString(
3626 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3627 if (ai.classLoaderName != null
3628 && !ClassLoaderFactory.isValidClassLoaderName(ai.classLoaderName)) {
3629 outError[0] = "Invalid class loader name: " + ai.classLoaderName;
3630 }
3631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003632 sa.recycle();
3633
3634 if (outError[0] != null) {
3635 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3636 return false;
3637 }
3638
3639 final int innerDepth = parser.getDepth();
Garrett Boyer52136662017-05-23 13:47:58 -07003640 // IMPORTANT: These must only be cached for a single <application> to avoid components
3641 // getting added to the wrong package.
3642 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003643 int type;
Bryce Lee22571db2017-07-07 15:54:18 -07003644
Kenny Rootd2d29252011-08-08 11:27:57 -07003645 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3646 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3647 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003648 continue;
3649 }
3650
3651 String tagName = parser.getName();
3652 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003653 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003654 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003655 if (a == null) {
3656 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3657 return false;
3658 }
3659
3660 owner.activities.add(a);
3661
3662 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003663 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3664 true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003665 if (a == null) {
3666 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3667 return false;
3668 }
3669
3670 owner.receivers.add(a);
3671
3672 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003673 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003674 if (s == null) {
3675 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3676 return false;
3677 }
3678
3679 owner.services.add(s);
3680
3681 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003682 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003683 if (p == null) {
3684 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3685 return false;
3686 }
3687
3688 owner.providers.add(p);
3689
3690 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003691 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003692 if (a == null) {
3693 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3694 return false;
3695 }
3696
3697 owner.activities.add(a);
3698
3699 } else if (parser.getName().equals("meta-data")) {
3700 // note: application meta-data is stored off to the side, so it can
3701 // remain null in the primary copy (we like to avoid extra copies because
3702 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003703 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003704 outError)) == null) {
3705 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3706 return false;
3707 }
Svet Ganov67882122016-12-11 16:36:34 -08003708 } else if (tagName.equals("static-library")) {
3709 sa = res.obtainAttributes(parser,
3710 com.android.internal.R.styleable.AndroidManifestStaticLibrary);
3711
3712 // Note: don't allow this value to be a reference to a resource
3713 // that may change.
3714 final String lname = sa.getNonResourceString(
3715 com.android.internal.R.styleable.AndroidManifestStaticLibrary_name);
3716 final int version = sa.getInt(
3717 com.android.internal.R.styleable.AndroidManifestStaticLibrary_version, -1);
Dianne Hackborn3accca02013-09-20 09:32:11 -07003718 final int versionMajor = sa.getInt(
3719 com.android.internal.R.styleable.AndroidManifestStaticLibrary_versionMajor,
3720 0);
Svet Ganov67882122016-12-11 16:36:34 -08003721
3722 sa.recycle();
3723
3724 // Since the app canot run without a static lib - fail if malformed
3725 if (lname == null || version < 0) {
3726 outError[0] = "Bad static-library declaration name: " + lname
3727 + " version: " + version;
3728 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3729 XmlUtils.skipCurrentTag(parser);
3730 return false;
3731 }
3732
3733 if (owner.mSharedUserId != null) {
3734 outError[0] = "sharedUserId not allowed in static shared library";
3735 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
3736 XmlUtils.skipCurrentTag(parser);
3737 return false;
3738 }
3739
3740 if (owner.staticSharedLibName != null) {
3741 outError[0] = "Multiple static-shared libs for package " + pkgName;
3742 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3743 XmlUtils.skipCurrentTag(parser);
3744 return false;
3745 }
3746
3747 owner.staticSharedLibName = lname.intern();
Dianne Hackborn3accca02013-09-20 09:32:11 -07003748 if (version >= 0) {
3749 owner.staticSharedLibVersion =
3750 PackageInfo.composeLongVersionCode(versionMajor, version);
3751 } else {
3752 owner.staticSharedLibVersion = version;
3753 }
Svet Ganov67882122016-12-11 16:36:34 -08003754 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
3755
3756 XmlUtils.skipCurrentTag(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003757
Dianne Hackbornc895be72013-03-11 17:48:43 -07003758 } else if (tagName.equals("library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003759 sa = res.obtainAttributes(parser,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003760 com.android.internal.R.styleable.AndroidManifestLibrary);
3761
3762 // Note: don't allow this value to be a reference to a resource
3763 // that may change.
3764 String lname = sa.getNonResourceString(
3765 com.android.internal.R.styleable.AndroidManifestLibrary_name);
3766
3767 sa.recycle();
3768
3769 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003770 lname = lname.intern();
3771 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
Svet Ganov67882122016-12-11 16:36:34 -08003772 owner.libraryNames = ArrayUtils.add(
3773 owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07003774 }
3775 }
3776
3777 XmlUtils.skipCurrentTag(parser);
3778
Svet Ganov67882122016-12-11 16:36:34 -08003779 } else if (tagName.equals("uses-static-library")) {
3780 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3781 return false;
3782 }
3783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003784 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003785 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003786 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3787
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003788 // Note: don't allow this value to be a reference to a resource
3789 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003790 String lname = sa.getNonResourceString(
3791 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07003792 boolean req = sa.getBoolean(
3793 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3794 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003795
3796 sa.recycle();
3797
Dianne Hackborn49237342009-08-27 20:08:01 -07003798 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003799 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07003800 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003801 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003802 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003803 owner.usesOptionalLibraries = ArrayUtils.add(
3804 owner.usesOptionalLibraries, lname);
3805 }
3806 }
3807
3808 XmlUtils.skipCurrentTag(parser);
3809
3810 } else if (tagName.equals("uses-package")) {
3811 // Dependencies for app installers; we don't currently try to
3812 // enforce this.
3813 XmlUtils.skipCurrentTag(parser);
3814
3815 } else {
3816 if (!RIGID_PARSER) {
3817 Slog.w(TAG, "Unknown element under <application>: " + tagName
3818 + " at " + mArchiveSourcePath + " "
3819 + parser.getPositionDescription());
3820 XmlUtils.skipCurrentTag(parser);
3821 continue;
3822 } else {
3823 outError[0] = "Bad element under <application>: " + tagName;
3824 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3825 return false;
3826 }
3827 }
3828 }
3829
Bryce Lee22571db2017-07-07 15:54:18 -07003830 // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
3831 // every activity info has had a chance to set it from its attributes.
3832 setMaxAspectRatio(owner);
3833
Paul Duffin855d7022017-07-10 15:16:07 +01003834 PackageBackwardCompatibility.modifySharedLibraries(owner);
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003835
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003836 if (hasDomainURLs(owner)) {
3837 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3838 } else {
3839 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3840 }
3841
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003842 return true;
3843 }
3844
3845 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003846 * 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 -07003847 */
3848 private static boolean hasDomainURLs(Package pkg) {
3849 if (pkg == null || pkg.activities == null) return false;
3850 final ArrayList<Activity> activities = pkg.activities;
3851 final int countActivities = activities.size();
3852 for (int n=0; n<countActivities; n++) {
3853 Activity activity = activities.get(n);
3854 ArrayList<ActivityIntentInfo> filters = activity.intents;
3855 if (filters == null) continue;
3856 final int countFilters = filters.size();
3857 for (int m=0; m<countFilters; m++) {
3858 ActivityIntentInfo aii = filters.get(m);
3859 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003860 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003861 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
3862 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
3863 return true;
3864 }
3865 }
3866 }
3867 return false;
3868 }
3869
3870 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003871 * Parse the {@code application} XML tree at the current parse location in a
3872 * <em>split APK</em> manifest.
3873 * <p>
3874 * Note that split APKs have many more restrictions on what they're capable
3875 * of doing, so many valid features of a base APK have been carefully
3876 * omitted here.
3877 */
Svet Ganov354cd3c2015-12-17 11:35:04 -08003878 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
3879 int flags, int splitIndex, String[] outError)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003880 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003881 TypedArray sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003882 com.android.internal.R.styleable.AndroidManifestApplication);
3883
3884 if (sa.getBoolean(
3885 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
3886 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
3887 }
3888
Narayan Kamath96c11c52017-08-09 13:07:21 +01003889 final String classLoaderName = sa.getString(
3890 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3891 if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
3892 owner.applicationInfo.splitClassLoaderNames[splitIndex] = classLoaderName;
3893 } else {
3894 outError[0] = "Invalid class loader name: " + classLoaderName;
3895 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3896 return false;
3897 }
3898
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003899 final int innerDepth = parser.getDepth();
3900 int type;
3901 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3902 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3903 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3904 continue;
3905 }
3906
Adam Lesinski4e862812016-11-21 16:02:24 -08003907 ComponentInfo parsedComponent = null;
3908
Garrett Boyer52136662017-05-23 13:47:58 -07003909 // IMPORTANT: These must only be cached for a single <application> to avoid components
3910 // getting added to the wrong package.
3911 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003912 String tagName = parser.getName();
3913 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003914 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003915 owner.baseHardwareAccelerated);
3916 if (a == null) {
3917 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3918 return false;
3919 }
3920
3921 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003922 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003923
3924 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003925 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3926 true, false);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003927 if (a == null) {
3928 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3929 return false;
3930 }
3931
3932 owner.receivers.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003933 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003934
3935 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003936 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003937 if (s == null) {
3938 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3939 return false;
3940 }
3941
3942 owner.services.add(s);
Adam Lesinski4e862812016-11-21 16:02:24 -08003943 parsedComponent = s.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003944
3945 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003946 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003947 if (p == null) {
3948 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3949 return false;
3950 }
3951
3952 owner.providers.add(p);
Adam Lesinski4e862812016-11-21 16:02:24 -08003953 parsedComponent = p.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003954
3955 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003956 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003957 if (a == null) {
3958 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3959 return false;
3960 }
3961
3962 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003963 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003964
3965 } else if (parser.getName().equals("meta-data")) {
3966 // note: application meta-data is stored off to the side, so it can
3967 // remain null in the primary copy (we like to avoid extra copies because
3968 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003969 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003970 outError)) == null) {
3971 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3972 return false;
3973 }
3974
Svet Ganov67882122016-12-11 16:36:34 -08003975 } else if (tagName.equals("uses-static-library")) {
3976 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3977 return false;
3978 }
3979
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003980 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003981 sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003982 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3983
3984 // Note: don't allow this value to be a reference to a resource
3985 // that may change.
3986 String lname = sa.getNonResourceString(
3987 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
3988 boolean req = sa.getBoolean(
3989 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3990 true);
3991
3992 sa.recycle();
3993
3994 if (lname != null) {
3995 lname = lname.intern();
3996 if (req) {
3997 // Upgrade to treat as stronger constraint
3998 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
3999 owner.usesOptionalLibraries = ArrayUtils.remove(
4000 owner.usesOptionalLibraries, lname);
4001 } else {
4002 // Ignore if someone already defined as required
4003 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
4004 owner.usesOptionalLibraries = ArrayUtils.add(
4005 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07004006 }
4007 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004008 }
4009
4010 XmlUtils.skipCurrentTag(parser);
4011
Dianne Hackborncef65ee2010-09-30 18:27:22 -07004012 } else if (tagName.equals("uses-package")) {
4013 // Dependencies for app installers; we don't currently try to
4014 // enforce this.
4015 XmlUtils.skipCurrentTag(parser);
4016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004017 } else {
4018 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004019 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004020 + " at " + mArchiveSourcePath + " "
4021 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004022 XmlUtils.skipCurrentTag(parser);
4023 continue;
4024 } else {
4025 outError[0] = "Bad element under <application>: " + tagName;
4026 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4027 return false;
4028 }
4029 }
Adam Lesinski4e862812016-11-21 16:02:24 -08004030
4031 if (parsedComponent != null && parsedComponent.splitName == null) {
4032 // If the loaded component did not specify a split, inherit the split name
4033 // based on the split it is defined in.
4034 // This is used to later load the correct split when starting this
4035 // component.
4036 parsedComponent.splitName = owner.splitNames[splitIndex];
4037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004038 }
4039
4040 return true;
4041 }
4042
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004043 private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
4044 String[] outError, String tag, TypedArray sa, boolean nameRequired,
4045 int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00004046 // This case can only happen in unit tests where we sometimes need to create fakes
4047 // of various package parser data structures.
4048 if (sa == null) {
4049 outError[0] = tag + " does not contain any attributes";
4050 return false;
4051 }
4052
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004053 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004054 if (name == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004055 if (nameRequired) {
4056 outError[0] = tag + " does not specify android:name";
4057 return false;
4058 }
4059 } else {
4060 outInfo.name
4061 = buildClassName(owner.applicationInfo.packageName, name, outError);
4062 if (outInfo.name == null) {
4063 return false;
4064 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004065 }
4066
Todd Kennedya83bfca2016-06-03 07:52:17 -07004067 final boolean useRoundIcon =
4068 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
4069 int roundIconVal = useRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004070 if (roundIconVal != 0) {
4071 outInfo.icon = roundIconVal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004072 outInfo.nonLocalizedLabel = null;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004073 } else {
4074 int iconVal = sa.getResourceId(iconRes, 0);
4075 if (iconVal != 0) {
4076 outInfo.icon = iconVal;
4077 outInfo.nonLocalizedLabel = null;
4078 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004079 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004080
Adam Powell81cd2e92010-04-21 16:35:18 -07004081 int logoVal = sa.getResourceId(logoRes, 0);
4082 if (logoVal != 0) {
4083 outInfo.logo = logoVal;
4084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004085
Jose Limaf78e3122014-03-06 12:13:15 -08004086 int bannerVal = sa.getResourceId(bannerRes, 0);
4087 if (bannerVal != 0) {
4088 outInfo.banner = bannerVal;
4089 }
4090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004091 TypedValue v = sa.peekValue(labelRes);
4092 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4093 outInfo.nonLocalizedLabel = v.coerceToString();
4094 }
4095
4096 outInfo.packageName = owner.packageName;
4097
4098 return true;
4099 }
4100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004101 private Activity parseActivity(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004102 XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
Romain Guy529b60a2010-08-03 18:05:47 -07004103 boolean receiver, boolean hardwareAccelerated)
4104 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004105 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004106
Garrett Boyer52136662017-05-23 13:47:58 -07004107 if (cachedArgs.mActivityArgs == null) {
4108 cachedArgs.mActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004109 R.styleable.AndroidManifestActivity_name,
4110 R.styleable.AndroidManifestActivity_label,
4111 R.styleable.AndroidManifestActivity_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004112 R.styleable.AndroidManifestActivity_roundIcon,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004113 R.styleable.AndroidManifestActivity_logo,
4114 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004115 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004116 R.styleable.AndroidManifestActivity_process,
4117 R.styleable.AndroidManifestActivity_description,
4118 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004119 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004120
Garrett Boyer52136662017-05-23 13:47:58 -07004121 cachedArgs.mActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
4122 cachedArgs.mActivityArgs.sa = sa;
4123 cachedArgs.mActivityArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004124
Garrett Boyer52136662017-05-23 13:47:58 -07004125 Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004126 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004127 sa.recycle();
4128 return null;
4129 }
4130
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004131 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004133 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004134 }
4135
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004136 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004137
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004138 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07004139 a.info.applicationInfo.uiOptions);
4140
Adam Powelldd8fab22012-03-22 17:47:27 -07004141 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004142 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004143 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004144 if (parentName != null) {
4145 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4146 if (outError[0] == null) {
4147 a.info.parentActivityName = parentClassName;
4148 } else {
4149 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
4150 parentName);
4151 outError[0] = null;
4152 }
4153 }
4154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004155 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004156 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004157 if (str == null) {
4158 a.info.permission = owner.applicationInfo.permission;
4159 } else {
4160 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4161 }
4162
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004163 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004164 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004165 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004166 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
4167 owner.applicationInfo.taskAffinity, str, outError);
4168
Todd Kennedye9d0d272017-01-23 06:49:29 -08004169 a.info.splitName =
4170 sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0);
4171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 a.info.flags = 0;
4173 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004174 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004175 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
4176 }
4177
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004178 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
4180 }
4181
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004182 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004183 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
4184 }
4185
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004186 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004187 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
4188 }
4189
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004190 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004191 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
4192 }
4193
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004194 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004195 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
4196 }
4197
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004198 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004199 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
4200 }
4201
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004202 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004203 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
4204 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
4205 }
4206
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004207 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07004208 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
4209 }
4210
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07004211 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
4212 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
4213 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07004214 }
4215
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004216 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04004217 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
4218 }
Craig Mautner5962b122012-10-05 14:45:52 -07004219
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07004220 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
4221 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08004222 }
4223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004224 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004225 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07004226 hardwareAccelerated)) {
4227 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
4228 }
4229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004230 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004231 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07004232 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004233 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07004234 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07004235 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004236 R.styleable.AndroidManifestActivity_maxRecents,
Dianne Hackborn852975d2014-08-22 17:42:43 -07004237 ActivityManager.getDefaultAppRecentsLimitStatic());
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004238 a.info.configChanges = getActivityConfigChanges(
4239 sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004240 sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004241 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004242 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07004243
Craig Mautner43e52ed2014-06-16 17:18:52 -07004244 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004245 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07004246 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07004247
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004248 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004249 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
4250 }
4251
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004252 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004253 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
4254 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004255
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004256 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004257 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
4258 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004259
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004260 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004261 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
4262 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004263
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004264 a.info.screenOrientation = sa.getInt(
4265 R.styleable.AndroidManifestActivity_screenOrientation,
4266 SCREEN_ORIENTATION_UNSPECIFIED);
Wale Ogunwale6a591362015-10-05 20:18:27 -07004267
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004268 setActivityResizeMode(a.info, sa, owner);
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004269
Winson Chungd3395382016-12-13 11:49:09 -08004270 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
4271 false)) {
4272 a.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE;
4273 }
4274
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004275 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004276 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004277 }
Wale Ogunwaleb60692e2015-10-24 12:35:56 -07004278
Bryce Lee22571db2017-07-07 15:54:18 -07004279 if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio)
4280 && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio)
4281 == TypedValue.TYPE_FLOAT) {
4282 a.setMaxAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio,
4283 0 /*default*/));
4284 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004285
Craig Mautner15df08a2015-04-01 12:17:18 -07004286 a.info.lockTaskLaunchMode =
4287 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004288
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004289 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4290 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004291 false);
Ruben Brunkf56c9f42016-04-22 18:20:55 -07004292
4293 a.info.requestedVrComponent =
4294 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
Robert Carr0f5d7532016-10-17 16:39:17 -07004295
4296 a.info.rotationAnimation =
Robert Carr427ba4f2017-07-17 18:37:06 -07004297 sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_UNSPECIFIED);
Romain Guy48327452017-01-23 17:03:35 -08004298
4299 a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
4300 ActivityInfo.COLOR_MODE_DEFAULT);
chaviw59b98852017-06-13 12:05:44 -07004301
4302 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) {
4303 a.info.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
4304 }
4305
4306 if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) {
4307 a.info.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON;
4308 }
4309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 } else {
4311 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4312 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004313
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004314 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07004315 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004316 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004317
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004318 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4319 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004320 false);
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004321 }
4322
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004323 if (a.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004324 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004325 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004326 }
4327
Todd Kennedy752fb702017-03-21 16:28:10 -07004328 // can't make this final; we may set it later via meta-data
4329 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08004330 sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004331 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004332 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004333 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004334 }
4335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004336 sa.recycle();
4337
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004338 if (receiver && (owner.applicationInfo.privateFlags
4339 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004340 // A heavy-weight application can not have receives in its main process
4341 // We can do direct compare because we intern all strings.
4342 if (a.info.processName == owner.packageName) {
4343 outError[0] = "Heavy-weight applications can not have receivers in main process";
4344 }
4345 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004346
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004347 if (outError[0] != null) {
4348 return null;
4349 }
4350
4351 int outerDepth = parser.getDepth();
4352 int type;
4353 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4354 && (type != XmlPullParser.END_TAG
4355 || parser.getDepth() > outerDepth)) {
4356 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4357 continue;
4358 }
4359
4360 if (parser.getName().equals("intent-filter")) {
4361 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004362 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4363 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004364 return null;
4365 }
4366 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004367 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004368 + mArchiveSourcePath + " "
4369 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004370 } else {
4371 a.intents.add(intent);
4372 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004373 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004374 final int visibility = visibleToEphemeral
4375 ? IntentFilter.VISIBILITY_EXPLICIT
4376 : !receiver && isImplicitlyExposedIntent(intent)
4377 ? IntentFilter.VISIBILITY_IMPLICIT
4378 : IntentFilter.VISIBILITY_NONE;
4379 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004380 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004381 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4382 }
4383 if (intent.isImplicitlyVisibleToInstantApp()) {
4384 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004385 }
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -07004386 if (LOG_UNSAFE_BROADCASTS && receiver
4387 && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
4388 for (int i = 0; i < intent.countActions(); i++) {
4389 final String action = intent.getAction(i);
4390 if (action == null || !action.startsWith("android.")) continue;
4391 if (!SAFE_BROADCASTS.contains(action)) {
4392 Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
4393 + owner.packageName + " as requested at: "
4394 + parser.getPositionDescription());
4395 }
4396 }
4397 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004398 } else if (!receiver && parser.getName().equals("preferred")) {
4399 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004400 if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
4401 intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004402 return null;
4403 }
4404 if (intent.countActions() == 0) {
4405 Slog.w(TAG, "No actions in preferred at "
4406 + mArchiveSourcePath + " "
4407 + parser.getPositionDescription());
4408 } else {
4409 if (owner.preferredActivityFilters == null) {
4410 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
4411 }
4412 owner.preferredActivityFilters.add(intent);
4413 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004414 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004415 final int visibility = visibleToEphemeral
4416 ? IntentFilter.VISIBILITY_EXPLICIT
4417 : !receiver && isImplicitlyExposedIntent(intent)
4418 ? IntentFilter.VISIBILITY_IMPLICIT
4419 : IntentFilter.VISIBILITY_NONE;
4420 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004421 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004422 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4423 }
4424 if (intent.isImplicitlyVisibleToInstantApp()) {
4425 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004427 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004428 if ((a.metaData = parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004429 outError)) == null) {
4430 return null;
4431 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004432 } else if (!receiver && parser.getName().equals("layout")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004433 parseLayout(res, parser, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004434 } else {
4435 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004436 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004437 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004438 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004439 + " at " + mArchiveSourcePath + " "
4440 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004441 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004442 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004443 + " at " + mArchiveSourcePath + " "
4444 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004445 }
4446 XmlUtils.skipCurrentTag(parser);
4447 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004448 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004449 if (receiver) {
4450 outError[0] = "Bad element under <receiver>: " + parser.getName();
4451 } else {
4452 outError[0] = "Bad element under <activity>: " + parser.getName();
4453 }
4454 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004455 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004456 }
4457 }
4458
4459 if (!setExported) {
4460 a.info.exported = a.intents.size() > 0;
4461 }
4462
4463 return a;
4464 }
4465
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004466 private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004467 final boolean appExplicitDefault = (owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004468 & (PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
4469 | PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004470
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004471 if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
4472 || appExplicitDefault) {
4473 // Activity or app explicitly set if it is resizeable or not;
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004474 final boolean appResizeable = (owner.applicationInfo.privateFlags
4475 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004476 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004477 appResizeable)) {
Winson Chungd3395382016-12-13 11:49:09 -08004478 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004479 } else {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004480 aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004481 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004482 return;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004483 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004484
4485 if ((owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004486 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) != 0) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004487 // The activity or app didn't explicitly set the resizing option, however we want to
4488 // make it resize due to the sdk version it is targeting.
4489 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4490 return;
4491 }
4492
4493 // resize preference isn't set and target sdk version doesn't support resizing apps by
4494 // default. For the app to be resizeable if it isn't fixed orientation or immersive.
skuhne@google.com322347b2016-12-02 12:54:03 -08004495 if (aInfo.isFixedOrientationPortrait()) {
4496 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
4497 } else if (aInfo.isFixedOrientationLandscape()) {
4498 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
4499 } else if (aInfo.isFixedOrientation()) {
4500 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
4501 } else {
4502 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4503 }
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004504 }
4505
Bryce Lee22571db2017-07-07 15:54:18 -07004506 /**
4507 * Sets every the max aspect ratio of every child activity that doesn't already have an aspect
4508 * ratio set.
4509 */
4510 private void setMaxAspectRatio(Package owner) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004511 // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
4512 // 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 -07004513 float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004514 ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
Bryce Lee22571db2017-07-07 15:54:18 -07004515
4516 if (owner.applicationInfo.maxAspectRatio != 0) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004517 // Use the application max aspect ration as default if set.
Bryce Lee22571db2017-07-07 15:54:18 -07004518 maxAspectRatio = owner.applicationInfo.maxAspectRatio;
4519 } else if (owner.mAppMetaData != null
4520 && owner.mAppMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) {
4521 maxAspectRatio = owner.mAppMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004522 }
4523
Bryce Lee22571db2017-07-07 15:54:18 -07004524 for (Activity activity : owner.activities) {
4525 // If the max aspect ratio for the activity has already been set, skip.
4526 if (activity.hasMaxAspectRatio()) {
4527 continue;
4528 }
4529
4530 // By default we prefer to use a values defined on the activity directly than values
4531 // defined on the application. We do not check the styled attributes on the activity
4532 // as it would have already been set when we processed the activity. We wait to process
4533 // the meta data here since this method is called at the end of processing the
4534 // application and all meta data is guaranteed.
4535 final float activityAspectRatio = activity.metaData != null
4536 ? activity.metaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio)
4537 : maxAspectRatio;
4538
4539 activity.setMaxAspectRatio(activityAspectRatio);
Wale Ogunwale0cb70ac2017-03-27 09:16:38 -07004540 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004541 }
4542
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004543 /**
4544 * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004545 * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from
4546 * AndroidManifest.xml.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004547 * @hide Exposed for unit testing only.
4548 */
4549 @TestApi
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004550 public static int getActivityConfigChanges(int configChanges, int recreateOnConfigChanges) {
4551 return configChanges | ((~recreateOnConfigChanges) & RECREATE_ON_CONFIG_CHANGES_MASK);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004552 }
4553
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004554 private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004555 TypedArray sw = res.obtainAttributes(attrs,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004556 com.android.internal.R.styleable.AndroidManifestLayout);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004557 int width = -1;
4558 float widthFraction = -1f;
4559 int height = -1;
4560 float heightFraction = -1f;
4561 final int widthType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004562 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004563 if (widthType == TypedValue.TYPE_FRACTION) {
4564 widthFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004565 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004566 1, 1, -1);
4567 } else if (widthType == TypedValue.TYPE_DIMENSION) {
4568 width = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004569 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004570 -1);
4571 }
4572 final int heightType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004573 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004574 if (heightType == TypedValue.TYPE_FRACTION) {
4575 heightFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004576 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004577 1, 1, -1);
4578 } else if (heightType == TypedValue.TYPE_DIMENSION) {
4579 height = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004580 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004581 -1);
4582 }
4583 int gravity = sw.getInt(
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004584 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004585 Gravity.CENTER);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004586 int minWidth = sw.getDimensionPixelSize(
4587 com.android.internal.R.styleable.AndroidManifestLayout_minWidth,
Andrii Kulian2e751b82016-03-16 16:59:32 -07004588 -1);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004589 int minHeight = sw.getDimensionPixelSize(
4590 com.android.internal.R.styleable.AndroidManifestLayout_minHeight,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004591 -1);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004592 sw.recycle();
Andrii Kulian2e751b82016-03-16 16:59:32 -07004593 a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction,
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004594 height, heightFraction, gravity, minWidth, minHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004595 }
4596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004597 private Activity parseActivityAlias(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004598 XmlResourceParser parser, int flags, String[] outError,
4599 CachedComponentArgs cachedArgs)
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004600 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004601 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 com.android.internal.R.styleable.AndroidManifestActivityAlias);
4603
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004604 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004605 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
4606 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607 if (targetActivity == null) {
4608 outError[0] = "<activity-alias> does not specify android:targetActivity";
4609 sa.recycle();
4610 return null;
4611 }
4612
4613 targetActivity = buildClassName(owner.applicationInfo.packageName,
4614 targetActivity, outError);
4615 if (targetActivity == null) {
4616 sa.recycle();
4617 return null;
4618 }
4619
Garrett Boyer52136662017-05-23 13:47:58 -07004620 if (cachedArgs.mActivityAliasArgs == null) {
4621 cachedArgs.mActivityAliasArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004622 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
4623 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
4624 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004625 com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004626 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004627 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004628 mSeparateProcesses,
4629 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004630 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004631 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004632 cachedArgs.mActivityAliasArgs.tag = "<activity-alias>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004633 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004634
Garrett Boyer52136662017-05-23 13:47:58 -07004635 cachedArgs.mActivityAliasArgs.sa = sa;
4636 cachedArgs.mActivityAliasArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004638 Activity target = null;
4639
4640 final int NA = owner.activities.size();
4641 for (int i=0; i<NA; i++) {
4642 Activity t = owner.activities.get(i);
4643 if (targetActivity.equals(t.info.name)) {
4644 target = t;
4645 break;
4646 }
4647 }
4648
4649 if (target == null) {
4650 outError[0] = "<activity-alias> target activity " + targetActivity
4651 + " not found in manifest";
4652 sa.recycle();
4653 return null;
4654 }
4655
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004656 ActivityInfo info = new ActivityInfo();
4657 info.targetActivity = targetActivity;
4658 info.configChanges = target.info.configChanges;
4659 info.flags = target.info.flags;
4660 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07004661 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08004662 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004663 info.labelRes = target.info.labelRes;
4664 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
4665 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07004666 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004667 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004668 if (info.descriptionRes == 0) {
4669 info.descriptionRes = target.info.descriptionRes;
4670 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004671 info.screenOrientation = target.info.screenOrientation;
4672 info.taskAffinity = target.info.taskAffinity;
4673 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07004674 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07004675 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07004676 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07004677 info.maxRecents = target.info.maxRecents;
Andrii Kulian2e751b82016-03-16 16:59:32 -07004678 info.windowLayout = target.info.windowLayout;
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004679 info.resizeMode = target.info.resizeMode;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004680 info.maxAspectRatio = target.info.maxAspectRatio;
Bryce Lee22571db2017-07-07 15:54:18 -07004681
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004682 info.encryptionAware = info.directBootAware = target.info.directBootAware;
Craig Mautner8307ea72014-09-11 15:03:53 -07004683
Garrett Boyer52136662017-05-23 13:47:58 -07004684 Activity a = new Activity(cachedArgs.mActivityAliasArgs, info);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004685 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004686 sa.recycle();
4687 return null;
4688 }
4689
4690 final boolean setExported = sa.hasValue(
4691 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
4692 if (setExported) {
4693 a.info.exported = sa.getBoolean(
4694 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
4695 }
4696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004698 str = sa.getNonConfigurationString(
4699 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004700 if (str != null) {
4701 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4702 }
4703
Adam Powelldd8fab22012-03-22 17:47:27 -07004704 String parentName = sa.getNonConfigurationString(
4705 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004706 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004707 if (parentName != null) {
4708 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4709 if (outError[0] == null) {
4710 a.info.parentActivityName = parentClassName;
4711 } else {
4712 Log.e(TAG, "Activity alias " + a.info.name +
4713 " specified invalid parentActivityName " + parentName);
4714 outError[0] = null;
4715 }
4716 }
4717
Chad Brubaker699c7712017-01-20 13:53:42 -08004718 // TODO add visibleToInstantApps attribute to activity alias
Todd Kennedybe0b8892017-02-15 14:13:52 -08004719 final boolean visibleToEphemeral =
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004720 ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004722 sa.recycle();
4723
4724 if (outError[0] != null) {
4725 return null;
4726 }
4727
4728 int outerDepth = parser.getDepth();
4729 int type;
4730 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4731 && (type != XmlPullParser.END_TAG
4732 || parser.getDepth() > outerDepth)) {
4733 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4734 continue;
4735 }
4736
4737 if (parser.getName().equals("intent-filter")) {
4738 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004739 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4740 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004741 return null;
4742 }
4743 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004744 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004745 + mArchiveSourcePath + " "
4746 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 } else {
4748 a.intents.add(intent);
4749 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004750 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004751 final int visibility = visibleToEphemeral
4752 ? IntentFilter.VISIBILITY_EXPLICIT
4753 : isImplicitlyExposedIntent(intent)
4754 ? IntentFilter.VISIBILITY_IMPLICIT
4755 : IntentFilter.VISIBILITY_NONE;
4756 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004757 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004758 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4759 }
4760 if (intent.isImplicitlyVisibleToInstantApp()) {
4761 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004763 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004764 if ((a.metaData=parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004765 outError)) == null) {
4766 return null;
4767 }
4768 } else {
4769 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004770 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004771 + " at " + mArchiveSourcePath + " "
4772 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 XmlUtils.skipCurrentTag(parser);
4774 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004775 } else {
4776 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
4777 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004778 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004779 }
4780 }
4781
4782 if (!setExported) {
4783 a.info.exported = a.intents.size() > 0;
4784 }
4785
4786 return a;
4787 }
4788
4789 private Provider parseProvider(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004790 XmlResourceParser parser, int flags, String[] outError,
4791 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004792 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004793 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004794 com.android.internal.R.styleable.AndroidManifestProvider);
4795
Garrett Boyer52136662017-05-23 13:47:58 -07004796 if (cachedArgs.mProviderArgs == null) {
4797 cachedArgs.mProviderArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004798 com.android.internal.R.styleable.AndroidManifestProvider_name,
4799 com.android.internal.R.styleable.AndroidManifestProvider_label,
4800 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004801 com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004802 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004803 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004804 mSeparateProcesses,
4805 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004806 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004807 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004808 cachedArgs.mProviderArgs.tag = "<provider>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004809 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004810
Garrett Boyer52136662017-05-23 13:47:58 -07004811 cachedArgs.mProviderArgs.sa = sa;
4812 cachedArgs.mProviderArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004813
Garrett Boyer52136662017-05-23 13:47:58 -07004814 Provider p = new Provider(cachedArgs.mProviderArgs, new ProviderInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004815 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004816 sa.recycle();
4817 return null;
4818 }
4819
Nick Kralevichf097b162012-07-28 12:43:48 -07004820 boolean providerExportedDefault = false;
4821
4822 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
4823 // For compatibility, applications targeting API level 16 or lower
4824 // should have their content providers exported by default, unless they
4825 // specify otherwise.
4826 providerExportedDefault = true;
4827 }
4828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004829 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07004830 com.android.internal.R.styleable.AndroidManifestProvider_exported,
4831 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004833 String cpname = sa.getNonConfigurationString(
4834 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835
4836 p.info.isSyncable = sa.getBoolean(
4837 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
4838 false);
4839
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004840 String permission = sa.getNonConfigurationString(
4841 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
4842 String str = sa.getNonConfigurationString(
4843 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004844 if (str == null) {
4845 str = permission;
4846 }
4847 if (str == null) {
4848 p.info.readPermission = owner.applicationInfo.permission;
4849 } else {
4850 p.info.readPermission =
4851 str.length() > 0 ? str.toString().intern() : null;
4852 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004853 str = sa.getNonConfigurationString(
4854 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004855 if (str == null) {
4856 str = permission;
4857 }
4858 if (str == null) {
4859 p.info.writePermission = owner.applicationInfo.permission;
4860 } else {
4861 p.info.writePermission =
4862 str.length() > 0 ? str.toString().intern() : null;
4863 }
4864
4865 p.info.grantUriPermissions = sa.getBoolean(
4866 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
4867 false);
4868
4869 p.info.multiprocess = sa.getBoolean(
4870 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
4871 false);
4872
4873 p.info.initOrder = sa.getInt(
4874 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
4875 0);
4876
Todd Kennedye9d0d272017-01-23 06:49:29 -08004877 p.info.splitName =
4878 sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0);
4879
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004880 p.info.flags = 0;
4881
4882 if (sa.getBoolean(
4883 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
4884 false)) {
4885 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004886 }
4887
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004888 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
4889 R.styleable.AndroidManifestProvider_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004890 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004891 if (p.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004892 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004893 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004894 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004895
Todd Kennedybe0b8892017-02-15 14:13:52 -08004896 final boolean visibleToEphemeral =
4897 sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004898 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004899 p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004900 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004901 }
4902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004903 sa.recycle();
4904
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004905 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
4906 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004907 // A heavy-weight application can not have providers in its main process
4908 // We can do direct compare because we intern all strings.
4909 if (p.info.processName == owner.packageName) {
4910 outError[0] = "Heavy-weight applications can not have providers in main process";
4911 return null;
4912 }
4913 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004915 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07004916 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004917 return null;
4918 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08004919 if (cpname.length() <= 0) {
4920 outError[0] = "<provider> has empty authorities attribute";
4921 return null;
4922 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004923 p.info.authority = cpname.intern();
4924
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004925 if (!parseProviderTags(
Patrick Baumanna2900392018-02-05 15:30:43 -08004926 res, parser, visibleToEphemeral, p, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004927 return null;
4928 }
4929
4930 return p;
4931 }
4932
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004933 private boolean parseProviderTags(Resources res, XmlResourceParser parser,
Patrick Baumanna2900392018-02-05 15:30:43 -08004934 boolean visibleToEphemeral, Provider outInfo, String[] outError)
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004935 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004936 int outerDepth = parser.getDepth();
4937 int type;
4938 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4939 && (type != XmlPullParser.END_TAG
4940 || parser.getDepth() > outerDepth)) {
4941 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4942 continue;
4943 }
4944
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004945 if (parser.getName().equals("intent-filter")) {
4946 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004947 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
4948 intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004949 return false;
4950 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004951 if (visibleToEphemeral) {
4952 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
4953 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004954 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004955 outInfo.intents.add(intent);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004956
4957 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004958 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 outInfo.metaData, outError)) == null) {
4960 return false;
4961 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963 } else if (parser.getName().equals("grant-uri-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004964 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004965 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
4966
4967 PatternMatcher pa = null;
4968
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004969 String str = sa.getNonConfigurationString(
4970 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004971 if (str != null) {
4972 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
4973 }
4974
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004975 str = sa.getNonConfigurationString(
4976 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 if (str != null) {
4978 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
4979 }
4980
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004981 str = sa.getNonConfigurationString(
4982 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004983 if (str != null) {
4984 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4985 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004987 sa.recycle();
4988
4989 if (pa != null) {
4990 if (outInfo.info.uriPermissionPatterns == null) {
4991 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
4992 outInfo.info.uriPermissionPatterns[0] = pa;
4993 } else {
4994 final int N = outInfo.info.uriPermissionPatterns.length;
4995 PatternMatcher[] newp = new PatternMatcher[N+1];
4996 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
4997 newp[N] = pa;
4998 outInfo.info.uriPermissionPatterns = newp;
4999 }
5000 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005001 } else {
5002 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005003 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005004 + parser.getName() + " at " + mArchiveSourcePath + " "
5005 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005006 XmlUtils.skipCurrentTag(parser);
5007 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005008 } else {
5009 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5010 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005011 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005012 }
5013 XmlUtils.skipCurrentTag(parser);
5014
5015 } else if (parser.getName().equals("path-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005016 TypedArray sa = res.obtainAttributes(parser,
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005017 com.android.internal.R.styleable.AndroidManifestPathPermission);
5018
5019 PathPermission pa = null;
5020
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005021 String permission = sa.getNonConfigurationString(
5022 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
5023 String readPermission = sa.getNonConfigurationString(
5024 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005025 if (readPermission == null) {
5026 readPermission = permission;
5027 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005028 String writePermission = sa.getNonConfigurationString(
5029 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005030 if (writePermission == null) {
5031 writePermission = permission;
5032 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005033
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005034 boolean havePerm = false;
5035 if (readPermission != null) {
5036 readPermission = readPermission.intern();
5037 havePerm = true;
5038 }
5039 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00005040 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005041 havePerm = true;
5042 }
5043
5044 if (!havePerm) {
5045 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005046 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005047 + parser.getName() + " at " + mArchiveSourcePath + " "
5048 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005049 XmlUtils.skipCurrentTag(parser);
5050 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005051 } else {
5052 outError[0] = "No readPermission or writePermssion for <path-permission>";
5053 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005054 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005055 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005056
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005057 String path = sa.getNonConfigurationString(
5058 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005059 if (path != null) {
5060 pa = new PathPermission(path,
5061 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
5062 }
5063
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005064 path = sa.getNonConfigurationString(
5065 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005066 if (path != null) {
5067 pa = new PathPermission(path,
5068 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
5069 }
5070
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005071 path = sa.getNonConfigurationString(
5072 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005073 if (path != null) {
5074 pa = new PathPermission(path,
5075 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
5076 }
5077
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005078 path = sa.getNonConfigurationString(
5079 com.android.internal.R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
5080 if (path != null) {
5081 pa = new PathPermission(path,
5082 PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission);
5083 }
5084
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005085 sa.recycle();
5086
5087 if (pa != null) {
5088 if (outInfo.info.pathPermissions == null) {
5089 outInfo.info.pathPermissions = new PathPermission[1];
5090 outInfo.info.pathPermissions[0] = pa;
5091 } else {
5092 final int N = outInfo.info.pathPermissions.length;
5093 PathPermission[] newp = new PathPermission[N+1];
5094 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
5095 newp[N] = pa;
5096 outInfo.info.pathPermissions = newp;
5097 }
5098 } else {
5099 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005100 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005101 + parser.getName() + " at " + mArchiveSourcePath + " "
5102 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005103 XmlUtils.skipCurrentTag(parser);
5104 continue;
5105 }
5106 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5107 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005108 }
5109 XmlUtils.skipCurrentTag(parser);
5110
5111 } else {
5112 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005113 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005114 + parser.getName() + " at " + mArchiveSourcePath + " "
5115 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005116 XmlUtils.skipCurrentTag(parser);
5117 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005118 } else {
5119 outError[0] = "Bad element under <provider>: " + parser.getName();
5120 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005122 }
5123 }
5124 return true;
5125 }
5126
5127 private Service parseService(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07005128 XmlResourceParser parser, int flags, String[] outError,
5129 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005131 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005132 com.android.internal.R.styleable.AndroidManifestService);
5133
Garrett Boyer52136662017-05-23 13:47:58 -07005134 if (cachedArgs.mServiceArgs == null) {
5135 cachedArgs.mServiceArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005136 com.android.internal.R.styleable.AndroidManifestService_name,
5137 com.android.internal.R.styleable.AndroidManifestService_label,
5138 com.android.internal.R.styleable.AndroidManifestService_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005139 com.android.internal.R.styleable.AndroidManifestService_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07005140 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08005141 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005142 mSeparateProcesses,
5143 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005144 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005145 com.android.internal.R.styleable.AndroidManifestService_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07005146 cachedArgs.mServiceArgs.tag = "<service>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005147 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005148
Garrett Boyer52136662017-05-23 13:47:58 -07005149 cachedArgs.mServiceArgs.sa = sa;
5150 cachedArgs.mServiceArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005151
Garrett Boyer52136662017-05-23 13:47:58 -07005152 Service s = new Service(cachedArgs.mServiceArgs, new ServiceInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005153 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005154 sa.recycle();
5155 return null;
5156 }
5157
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005158 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005159 com.android.internal.R.styleable.AndroidManifestService_exported);
5160 if (setExported) {
5161 s.info.exported = sa.getBoolean(
5162 com.android.internal.R.styleable.AndroidManifestService_exported, false);
5163 }
5164
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005165 String str = sa.getNonConfigurationString(
5166 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005167 if (str == null) {
5168 s.info.permission = owner.applicationInfo.permission;
5169 } else {
5170 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
5171 }
5172
Todd Kennedye9d0d272017-01-23 06:49:29 -08005173 s.info.splitName =
5174 sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0);
5175
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005176 s.info.flags = 0;
5177 if (sa.getBoolean(
5178 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
5179 false)) {
5180 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
5181 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08005182 if (sa.getBoolean(
5183 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
5184 false)) {
5185 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
5186 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005187 if (sa.getBoolean(
Robert Sesekb9a86662015-12-09 16:22:45 -05005188 com.android.internal.R.styleable.AndroidManifestService_externalService,
5189 false)) {
5190 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
5191 }
5192 if (sa.getBoolean(
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005193 com.android.internal.R.styleable.AndroidManifestService_singleUser,
5194 false)) {
5195 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005196 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005197
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005198 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
5199 R.styleable.AndroidManifestService_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005200 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005201 if (s.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005202 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005203 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005204 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005205
Todd Kennedy752fb702017-03-21 16:28:10 -07005206 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08005207 sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005208 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005209 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005210 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005211 }
5212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005213 sa.recycle();
5214
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005215 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5216 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005217 // A heavy-weight application can not have services in its main process
5218 // We can do direct compare because we intern all strings.
5219 if (s.info.processName == owner.packageName) {
5220 outError[0] = "Heavy-weight applications can not have services in main process";
5221 return null;
5222 }
5223 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 int outerDepth = parser.getDepth();
5226 int type;
5227 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5228 && (type != XmlPullParser.END_TAG
5229 || parser.getDepth() > outerDepth)) {
5230 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5231 continue;
5232 }
5233
5234 if (parser.getName().equals("intent-filter")) {
5235 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005236 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5237 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005238 return null;
5239 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005240 if (visibleToEphemeral) {
5241 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5242 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005243 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005244 s.intents.add(intent);
5245 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005246 if ((s.metaData=parseMetaData(res, parser, s.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005247 outError)) == null) {
5248 return null;
5249 }
5250 } else {
5251 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005252 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005253 + parser.getName() + " at " + mArchiveSourcePath + " "
5254 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005255 XmlUtils.skipCurrentTag(parser);
5256 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005257 } else {
5258 outError[0] = "Bad element under <service>: " + parser.getName();
5259 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005260 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005261 }
5262 }
5263
5264 if (!setExported) {
5265 s.info.exported = s.intents.size() > 0;
5266 }
5267
5268 return s;
5269 }
5270
Chad Brubaker49414832017-04-13 16:13:23 -07005271 private boolean isImplicitlyExposedIntent(IntentInfo intent) {
5272 return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
5273 || intent.hasAction(Intent.ACTION_SEND)
5274 || intent.hasAction(Intent.ACTION_SENDTO)
5275 || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005276 }
5277
Svet Ganov354cd3c2015-12-17 11:35:04 -08005278 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
5279 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 int outerDepth = parser.getDepth();
5281 int type;
5282 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5283 && (type != XmlPullParser.END_TAG
5284 || parser.getDepth() > outerDepth)) {
5285 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5286 continue;
5287 }
5288
5289 if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005290 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005291 outInfo.metaData, outError)) == null) {
5292 return false;
5293 }
5294 } else {
5295 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005296 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005297 + parser.getName() + " at " + mArchiveSourcePath + " "
5298 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 XmlUtils.skipCurrentTag(parser);
5300 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005301 } else {
5302 outError[0] = "Bad element under " + tag + ": " + parser.getName();
5303 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005305 }
5306 }
5307 return true;
5308 }
5309
5310 private Bundle parseMetaData(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08005311 XmlResourceParser parser, Bundle data, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005312 throws XmlPullParserException, IOException {
5313
Svet Ganov354cd3c2015-12-17 11:35:04 -08005314 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005315 com.android.internal.R.styleable.AndroidManifestMetaData);
5316
5317 if (data == null) {
5318 data = new Bundle();
5319 }
5320
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005321 String name = sa.getNonConfigurationString(
5322 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 if (name == null) {
5324 outError[0] = "<meta-data> requires an android:name attribute";
5325 sa.recycle();
5326 return null;
5327 }
5328
Dianne Hackborn854060af2009-07-09 18:14:31 -07005329 name = name.intern();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 TypedValue v = sa.peekValue(
5332 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
5333 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005334 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 data.putInt(name, v.resourceId);
5336 } else {
5337 v = sa.peekValue(
5338 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07005339 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005340 if (v != null) {
5341 if (v.type == TypedValue.TYPE_STRING) {
5342 CharSequence cs = v.coerceToString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00005343 data.putString(name, cs != null ? cs.toString() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005344 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
5345 data.putBoolean(name, v.data != 0);
5346 } else if (v.type >= TypedValue.TYPE_FIRST_INT
5347 && v.type <= TypedValue.TYPE_LAST_INT) {
5348 data.putInt(name, v.data);
5349 } else if (v.type == TypedValue.TYPE_FLOAT) {
5350 data.putFloat(name, v.getFloat());
5351 } else {
5352 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005353 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005354 + parser.getName() + " at " + mArchiveSourcePath + " "
5355 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005356 } else {
5357 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
5358 data = null;
5359 }
5360 }
5361 } else {
5362 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
5363 data = null;
5364 }
5365 }
5366
5367 sa.recycle();
5368
5369 XmlUtils.skipCurrentTag(parser);
5370
5371 return data;
5372 }
5373
Adam Lesinski4e862812016-11-21 16:02:24 -08005374 private static VerifierInfo parseVerifier(AttributeSet attrs) {
5375 String packageName = null;
5376 String encodedPublicKey = null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005377
Adam Lesinski4e862812016-11-21 16:02:24 -08005378 final int attrCount = attrs.getAttributeCount();
5379 for (int i = 0; i < attrCount; i++) {
5380 final int attrResId = attrs.getAttributeNameResource(i);
5381 switch (attrResId) {
5382 case com.android.internal.R.attr.name:
5383 packageName = attrs.getAttributeValue(i);
5384 break;
Kenny Root05ca4c92011-09-15 10:36:25 -07005385
Adam Lesinski4e862812016-11-21 16:02:24 -08005386 case com.android.internal.R.attr.publicKey:
5387 encodedPublicKey = attrs.getAttributeValue(i);
5388 break;
5389 }
5390 }
Kenny Root05ca4c92011-09-15 10:36:25 -07005391
5392 if (packageName == null || packageName.length() == 0) {
5393 Slog.i(TAG, "verifier package name was null; skipping");
5394 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005395 }
5396
Christopher Tate30147332014-04-15 12:57:47 -07005397 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
5398 if (publicKey == null) {
5399 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
5400 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08005401 }
5402
Christopher Tate30147332014-04-15 12:57:47 -07005403 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08005404 }
5405
Christopher Tate30147332014-04-15 12:57:47 -07005406 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
5407 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07005408 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07005409 return null;
5410 }
5411
Kenny Root05ca4c92011-09-15 10:36:25 -07005412 EncodedKeySpec keySpec;
5413 try {
5414 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
5415 keySpec = new X509EncodedKeySpec(encoded);
5416 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07005417 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07005418 return null;
5419 }
5420
5421 /* First try the key as an RSA key. */
5422 try {
5423 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005424 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005425 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005426 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005427 } catch (InvalidKeySpecException e) {
5428 // Not a RSA public key.
5429 }
5430
dcashman1616f302015-05-29 14:47:23 -07005431 /* Now try it as a ECDSA key. */
5432 try {
5433 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
5434 return keyFactory.generatePublic(keySpec);
5435 } catch (NoSuchAlgorithmException e) {
5436 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
5437 } catch (InvalidKeySpecException e) {
5438 // Not a ECDSA public key.
5439 }
5440
Kenny Root05ca4c92011-09-15 10:36:25 -07005441 /* Now try it as a DSA key. */
5442 try {
5443 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005444 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005445 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005446 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005447 } catch (InvalidKeySpecException e) {
5448 // Not a DSA public key.
5449 }
5450
dcashman1616f302015-05-29 14:47:23 -07005451 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07005452 return null;
5453 }
5454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005455 private static final String ANDROID_RESOURCES
5456 = "http://schemas.android.com/apk/res/android";
5457
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005458 private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs,
5459 boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
5460 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005461
Svet Ganov354cd3c2015-12-17 11:35:04 -08005462 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005463 com.android.internal.R.styleable.AndroidManifestIntentFilter);
5464
5465 int priority = sa.getInt(
5466 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005467 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08005468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005469 TypedValue v = sa.peekValue(
5470 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
5471 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
5472 outInfo.nonLocalizedLabel = v.coerceToString();
5473 }
5474
Todd Kennedya83bfca2016-06-03 07:52:17 -07005475 final boolean useRoundIcon =
5476 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
5477 int roundIconVal = useRoundIcon ? sa.getResourceId(
5478 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
5479 if (roundIconVal != 0) {
5480 outInfo.icon = roundIconVal;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005481 } else {
5482 outInfo.icon = sa.getResourceId(
5483 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
5484 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005485
Adam Powell81cd2e92010-04-21 16:35:18 -07005486 outInfo.logo = sa.getResourceId(
5487 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005488
Jose Limaf78e3122014-03-06 12:13:15 -08005489 outInfo.banner = sa.getResourceId(
5490 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
5491
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08005492 if (allowAutoVerify) {
5493 outInfo.setAutoVerify(sa.getBoolean(
5494 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
5495 false));
5496 }
5497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005498 sa.recycle();
5499
5500 int outerDepth = parser.getDepth();
5501 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07005502 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
5503 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
5504 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005505 continue;
5506 }
5507
5508 String nodeName = parser.getName();
5509 if (nodeName.equals("action")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005510 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005511 ANDROID_RESOURCES, "name");
5512 if (value == null || value == "") {
5513 outError[0] = "No value supplied for <android:name>";
5514 return false;
5515 }
5516 XmlUtils.skipCurrentTag(parser);
5517
5518 outInfo.addAction(value);
5519 } else if (nodeName.equals("category")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005520 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005521 ANDROID_RESOURCES, "name");
5522 if (value == null || value == "") {
5523 outError[0] = "No value supplied for <android:name>";
5524 return false;
5525 }
5526 XmlUtils.skipCurrentTag(parser);
5527
5528 outInfo.addCategory(value);
5529
5530 } else if (nodeName.equals("data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005531 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005532 com.android.internal.R.styleable.AndroidManifestData);
5533
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005534 String str = sa.getNonConfigurationString(
5535 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005536 if (str != null) {
5537 try {
5538 outInfo.addDataType(str);
5539 } catch (IntentFilter.MalformedMimeTypeException e) {
5540 outError[0] = e.toString();
5541 sa.recycle();
5542 return false;
5543 }
5544 }
5545
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005546 str = sa.getNonConfigurationString(
5547 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005548 if (str != null) {
5549 outInfo.addDataScheme(str);
5550 }
5551
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005552 str = sa.getNonConfigurationString(
5553 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
5554 if (str != null) {
5555 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
5556 }
5557
5558 str = sa.getNonConfigurationString(
5559 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
5560 if (str != null) {
5561 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
5562 }
5563
5564 str = sa.getNonConfigurationString(
5565 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
5566 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005567 if (!allowGlobs) {
5568 outError[0] = "sspPattern not allowed here; ssp must be literal";
5569 return false;
5570 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005571 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5572 }
5573
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005574 String host = sa.getNonConfigurationString(
5575 com.android.internal.R.styleable.AndroidManifestData_host, 0);
5576 String port = sa.getNonConfigurationString(
5577 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005578 if (host != null) {
5579 outInfo.addDataAuthority(host, port);
5580 }
5581
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005582 str = sa.getNonConfigurationString(
5583 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005584 if (str != null) {
5585 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
5586 }
5587
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005588 str = sa.getNonConfigurationString(
5589 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005590 if (str != null) {
5591 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
5592 }
5593
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005594 str = sa.getNonConfigurationString(
5595 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005596 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005597 if (!allowGlobs) {
5598 outError[0] = "pathPattern not allowed here; path must be literal";
5599 return false;
5600 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005601 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5602 }
5603
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005604 str = sa.getNonConfigurationString(
5605 com.android.internal.R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
5606 if (str != null) {
5607 if (!allowGlobs) {
5608 outError[0] = "pathAdvancedPattern not allowed here; path must be literal";
5609 return false;
5610 }
5611 outInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
5612 }
5613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005614 sa.recycle();
5615 XmlUtils.skipCurrentTag(parser);
5616 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005617 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005618 + parser.getName() + " at " + mArchiveSourcePath + " "
5619 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005620 XmlUtils.skipCurrentTag(parser);
5621 } else {
5622 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
5623 return false;
5624 }
5625 }
5626
5627 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07005628
5629 if (DEBUG_PARSER) {
5630 final StringBuilder cats = new StringBuilder("Intent d=");
5631 cats.append(outInfo.hasDefault);
5632 cats.append(", cat=");
5633
5634 final Iterator<String> it = outInfo.categoriesIterator();
5635 if (it != null) {
5636 while (it.hasNext()) {
5637 cats.append(' ');
5638 cats.append(it.next());
5639 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005640 }
Kenny Rootd2d29252011-08-08 11:27:57 -07005641 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005642 }
5643
5644 return true;
5645 }
5646
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005647 /**
5648 * A container for signing-related data of an application package.
5649 * @hide
5650 */
Patrick Baumann47117fc2017-12-19 10:17:21 -08005651 public static final class SigningDetails implements Parcelable {
5652
5653 @IntDef({SigningDetails.SignatureSchemeVersion.UNKNOWN,
5654 SigningDetails.SignatureSchemeVersion.JAR,
5655 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2,
5656 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3})
5657 public @interface SignatureSchemeVersion {
5658 int UNKNOWN = 0;
5659 int JAR = 1;
5660 int SIGNING_BLOCK_V2 = 2;
5661 int SIGNING_BLOCK_V3 = 3;
5662 }
5663
5664 @Nullable
5665 public final Signature[] signatures;
5666 @SignatureSchemeVersion
5667 public final int signatureSchemeVersion;
5668 @Nullable
5669 public final ArraySet<PublicKey> publicKeys;
5670
Daniel Cashman77029c52018-01-18 16:19:29 -08005671 /**
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005672 * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
5673 * contains two pieces of information:
5674 * 1) the past signing certificates
5675 * 2) the flags that APK wants to assign to each of the past signing certificates.
5676 *
5677 * This collection of {@code Signature} objects, each of which is formed from a former
5678 * signing certificate of this APK before it was changed by signing certificate rotation,
5679 * represents the first piece of information. It is the APK saying to the rest of the
5680 * world: "hey if you trust the old cert, you can trust me!" This is useful, if for
5681 * instance, the platform would like to determine whether or not to allow this APK to do
5682 * something it would've allowed it to do under the old cert (like upgrade).
Daniel Cashman77029c52018-01-18 16:19:29 -08005683 */
5684 @Nullable
5685 public final Signature[] pastSigningCertificates;
5686
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005687 /** special value used to see if cert is in package - not exposed to callers */
5688 private static final int PAST_CERT_EXISTS = 0;
5689
5690 @IntDef(
5691 flag = true,
5692 value = {CertCapabilities.INSTALLED_DATA,
5693 CertCapabilities.SHARED_USER_ID,
5694 CertCapabilities.PERMISSION })
5695 public @interface CertCapabilities {
5696
5697 /** accept data from already installed pkg with this cert */
5698 int INSTALLED_DATA = 1;
5699
5700 /** accept sharedUserId with pkg with this cert */
5701 int SHARED_USER_ID = 2;
5702
5703 /** grant SIGNATURE permissions to pkgs with this cert */
5704 int PERMISSION = 4;
5705 }
5706
Daniel Cashman77029c52018-01-18 16:19:29 -08005707 /**
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005708 * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
5709 * contains two pieces of information:
5710 * 1) the past signing certificates
5711 * 2) the flags that APK wants to assign to each of the past signing certificates.
5712 *
5713 * These flags, which have a one-to-one relationship for the {@code pastSigningCertificates}
5714 * collection, represent the second piece of information and are viewed as capabilities.
5715 * They are an APK's way of telling the platform: "this is how I want to trust my old certs,
5716 * please enforce that." This is useful for situation where this app itself is using its
5717 * signing certificate as an authorization mechanism, like whether or not to allow another
5718 * app to have its SIGNATURE permission. An app could specify whether to allow other apps
5719 * signed by its old cert 'X' to still get a signature permission it defines, for example.
Daniel Cashman77029c52018-01-18 16:19:29 -08005720 */
5721 @Nullable
5722 public final int[] pastSigningCertificatesFlags;
5723
Patrick Baumann47117fc2017-12-19 10:17:21 -08005724 /** A representation of unknown signing details. Use instead of null. */
5725 public static final SigningDetails UNKNOWN =
Daniel Cashman77029c52018-01-18 16:19:29 -08005726 new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null, null);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005727
5728 @VisibleForTesting
5729 public SigningDetails(Signature[] signatures,
5730 @SignatureSchemeVersion int signatureSchemeVersion,
Daniel Cashman77029c52018-01-18 16:19:29 -08005731 ArraySet<PublicKey> keys, Signature[] pastSigningCertificates,
5732 int[] pastSigningCertificatesFlags) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08005733 this.signatures = signatures;
5734 this.signatureSchemeVersion = signatureSchemeVersion;
5735 this.publicKeys = keys;
Daniel Cashman77029c52018-01-18 16:19:29 -08005736 this.pastSigningCertificates = pastSigningCertificates;
5737 this.pastSigningCertificatesFlags = pastSigningCertificatesFlags;
5738 }
5739
5740 public SigningDetails(Signature[] signatures,
5741 @SignatureSchemeVersion int signatureSchemeVersion,
5742 Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags)
5743 throws CertificateException {
5744 this(signatures, signatureSchemeVersion, toSigningKeys(signatures),
5745 pastSigningCertificates, pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005746 }
5747
5748 public SigningDetails(Signature[] signatures,
5749 @SignatureSchemeVersion int signatureSchemeVersion)
5750 throws CertificateException {
Daniel Cashman77029c52018-01-18 16:19:29 -08005751 this(signatures, signatureSchemeVersion,
5752 null, null);
5753 }
5754
5755 public SigningDetails(SigningDetails orig) {
5756 if (orig != null) {
5757 if (orig.signatures != null) {
5758 this.signatures = orig.signatures.clone();
5759 } else {
5760 this.signatures = null;
5761 }
5762 this.signatureSchemeVersion = orig.signatureSchemeVersion;
5763 this.publicKeys = new ArraySet<>(orig.publicKeys);
5764 if (orig.pastSigningCertificates != null) {
5765 this.pastSigningCertificates = orig.pastSigningCertificates.clone();
5766 this.pastSigningCertificatesFlags = orig.pastSigningCertificatesFlags.clone();
5767 } else {
5768 this.pastSigningCertificates = null;
5769 this.pastSigningCertificatesFlags = null;
5770 }
5771 } else {
5772 this.signatures = null;
5773 this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
5774 this.publicKeys = null;
5775 this.pastSigningCertificates = null;
5776 this.pastSigningCertificatesFlags = null;
5777 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08005778 }
5779
5780 /** Returns true if the signing details have one or more signatures. */
5781 public boolean hasSignatures() {
5782 return signatures != null && signatures.length > 0;
5783 }
5784
Daniel Cashman5cdda342018-01-19 07:22:52 -08005785 /** Returns true if the signing details have past signing certificates. */
5786 public boolean hasPastSigningCertificates() {
5787 return pastSigningCertificates != null && pastSigningCertificates.length > 0;
5788 }
5789
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005790 /**
5791 * Determines if the provided {@code oldDetails} is an ancestor of or the same as this one.
5792 * If the {@code oldDetails} signing certificate appears in our pastSigningCertificates,
5793 * then that means it has authorized a signing certificate rotation, which eventually leads
5794 * to our certificate, and thus can be trusted. If this method evaluates to true, this
5795 * SigningDetails object should be trusted if the previous one is.
5796 */
5797 public boolean hasAncestorOrSelf(SigningDetails oldDetails) {
5798 if (this == UNKNOWN || oldDetails == UNKNOWN) {
5799 return false;
5800 }
5801 if (oldDetails.signatures.length > 1) {
5802
5803 // multiple-signer packages cannot rotate signing certs, so we just compare current
5804 // signers for an exact match
5805 return signaturesMatchExactly(oldDetails);
5806 } else {
5807
5808 // we may have signing certificate rotation history, check to see if the oldDetails
5809 // was one of our old signing certificates
5810 return hasCertificate(oldDetails.signatures[0]);
5811 }
5812 }
5813
5814 /**
5815 * Similar to {@code hasAncestorOrSelf}. Returns true only if this {@code SigningDetails}
5816 * is a descendant of {@code oldDetails}, not if they're the same. This is used to
5817 * determine if this object is newer than the provided one.
5818 */
5819 public boolean hasAncestor(SigningDetails oldDetails) {
5820 if (this == UNKNOWN || oldDetails == UNKNOWN) {
5821 return false;
5822 }
5823 if (this.hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
5824
5825 // the last entry in pastSigningCertificates is the current signer, ignore it
5826 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
5827 if (pastSigningCertificates[i].equals(oldDetails.signatures[i])) {
5828 return true;
5829 }
5830 }
5831 }
5832 return false;
5833 }
5834
5835 /**
5836 * Determines if the provided {@code oldDetails} is an ancestor of this one, and whether or
5837 * not this one grants it the provided capability, represented by the {@code flags}
5838 * parameter. In the event of signing certificate rotation, a package may still interact
5839 * with entities signed by its old signing certificate and not want to break previously
5840 * functioning behavior. The {@code flags} value determines which capabilities the app
5841 * signed by the newer signing certificate would like to continue to give to its previous
5842 * signing certificate(s).
5843 */
5844 public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) {
5845 if (this == UNKNOWN || oldDetails == UNKNOWN) {
5846 return false;
5847 }
5848 if (oldDetails.signatures.length > 1) {
5849
5850 // multiple-signer packages cannot rotate signing certs, so we must have an exact
5851 // match, which also means all capabilities are granted
5852 return signaturesMatchExactly(oldDetails);
5853 } else {
5854
5855 // we may have signing certificate rotation history, check to see if the oldDetails
5856 // was one of our old signing certificates, and if we grant it the capability it's
5857 // requesting
5858 return hasCertificate(oldDetails.signatures[0], flags);
5859 }
5860 }
5861
5862 /**
5863 * A special case of {@code checkCapability} which re-encodes both sets of signing
5864 * certificates to counteract a previous re-encoding.
5865 */
5866 public boolean checkCapabilityRecover(SigningDetails oldDetails,
5867 @CertCapabilities int flags) throws CertificateException {
5868 if (oldDetails == UNKNOWN || this == UNKNOWN) {
5869 return false;
5870 }
5871 if (hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
5872
5873 // signing certificates may have rotated, check entire history for effective match
5874 for (int i = 0; i < pastSigningCertificates.length; i++) {
5875 if (Signature.areEffectiveMatch(
5876 oldDetails.signatures[0],
5877 pastSigningCertificates[i])
5878 && pastSigningCertificatesFlags[i] == flags) {
5879 return true;
5880 }
5881 }
5882 } else {
5883 return Signature.areEffectiveMatch(oldDetails.signatures, signatures);
5884 }
5885 return false;
5886 }
5887
5888 /**
5889 * Determine if {@code signature} is in this SigningDetails' signing certificate history,
5890 * including the current signer. Automatically returns false if this object has multiple
5891 * signing certificates, since rotation is only supported for single-signers; this is
5892 * enforced by {@code hasCertificateInternal}.
5893 */
5894 public boolean hasCertificate(Signature signature) {
5895 return hasCertificateInternal(signature, PAST_CERT_EXISTS);
5896 }
5897
5898 /**
5899 * Determine if {@code signature} is in this SigningDetails' signing certificate history,
5900 * including the current signer, and whether or not it has the given permission.
5901 * Certificates which match our current signer automatically get all capabilities.
5902 * Automatically returns false if this object has multiple signing certificates, since
5903 * rotation is only supported for single-signers.
5904 */
5905 public boolean hasCertificate(Signature signature, @CertCapabilities int flags) {
5906 return hasCertificateInternal(signature, flags);
5907 }
5908
5909 /** Convenient wrapper for calling {@code hasCertificate} with certificate's raw bytes. */
5910 public boolean hasCertificate(byte[] certificate) {
5911 Signature signature = new Signature(certificate);
5912 return hasCertificate(signature);
5913 }
5914
5915 private boolean hasCertificateInternal(Signature signature, int flags) {
5916 if (this == UNKNOWN) {
5917 return false;
5918 }
5919
5920 // only single-signed apps can have pastSigningCertificates
5921 if (hasPastSigningCertificates()) {
5922
5923 // check all past certs, except for the current one, which automatically gets all
5924 // capabilities, since it is the same as the current signature
5925 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
5926 if (pastSigningCertificates[i].equals(signature)) {
5927 if (flags == PAST_CERT_EXISTS
5928 || (flags & pastSigningCertificatesFlags[i]) == flags) {
5929 return true;
5930 }
5931 }
5932 }
5933 }
5934
5935 // not in previous certs signing history, just check the current signer and make sure
5936 // we are singly-signed
5937 return signatures.length == 1 && signatures[0].equals(signature);
5938 }
5939
5940 /**
5941 * Determines if the provided {@code sha256String} is an ancestor of this one, and whether
5942 * or not this one grants it the provided capability, represented by the {@code flags}
5943 * parameter. In the event of signing certificate rotation, a package may still interact
5944 * with entities signed by its old signing certificate and not want to break previously
5945 * functioning behavior. The {@code flags} value determines which capabilities the app
5946 * signed by the newer signing certificate would like to continue to give to its previous
5947 * signing certificate(s).
5948 *
5949 * @param sha256String A hex-encoded representation of a sha256 digest. In the case of an
5950 * app with multiple signers, this represents the hex-encoded sha256
5951 * digest of the combined hex-encoded sha256 digests of each individual
5952 * signing certificate according to {@link
5953 * PackageUtils#computeSignaturesSha256Digest(Signature[])}
5954 */
5955 public boolean checkCapability(String sha256String, @CertCapabilities int flags) {
5956 if (this == UNKNOWN) {
5957 return false;
5958 }
5959
5960 // first see if the hash represents a single-signer in our signing history
5961 byte[] sha256Bytes = ByteStringUtils.fromHexToByteArray(sha256String);
5962 if (hasSha256Certificate(sha256Bytes, flags)) {
5963 return true;
5964 }
5965
5966 // Not in signing history, either represents multiple signatures or not a match.
5967 // Multiple signers can't rotate, so no need to check flags, just see if the SHAs match.
5968 // We already check the single-signer case above as part of hasSha256Certificate, so no
5969 // need to verify we have multiple signers, just run the old check
5970 // just consider current signing certs
5971 final String[] mSignaturesSha256Digests =
5972 PackageUtils.computeSignaturesSha256Digests(signatures);
5973 final String mSignaturesSha256Digest =
5974 PackageUtils.computeSignaturesSha256Digest(mSignaturesSha256Digests);
5975 return mSignaturesSha256Digest.equals(sha256String);
5976 }
5977
5978 /**
5979 * Determine if the {@code sha256Certificate} is in this SigningDetails' signing certificate
5980 * history, including the current signer. Automatically returns false if this object has
5981 * multiple signing certificates, since rotation is only supported for single-signers.
5982 */
5983 public boolean hasSha256Certificate(byte[] sha256Certificate) {
5984 return hasSha256CertificateInternal(sha256Certificate, PAST_CERT_EXISTS);
5985 }
5986
5987 /**
5988 * Determine if the {@code sha256Certificate} certificate hash corresponds to a signing
5989 * certificate in this SigningDetails' signing certificate history, including the current
5990 * signer, and whether or not it has the given permission. Certificates which match our
5991 * current signer automatically get all capabilities. Automatically returns false if this
5992 * object has multiple signing certificates, since rotation is only supported for
5993 * single-signers.
5994 */
5995 public boolean hasSha256Certificate(byte[] sha256Certificate, @CertCapabilities int flags) {
5996 return hasSha256CertificateInternal(sha256Certificate, flags);
5997 }
5998
5999 private boolean hasSha256CertificateInternal(byte[] sha256Certificate, int flags) {
6000 if (this == UNKNOWN) {
6001 return false;
6002 }
6003 if (hasPastSigningCertificates()) {
6004
6005 // check all past certs, except for the last one, which automatically gets all
6006 // capabilities, since it is the same as the current signature, and is checked below
6007 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
6008 byte[] digest = PackageUtils.computeSha256DigestBytes(
6009 pastSigningCertificates[i].toByteArray());
6010 if (Arrays.equals(sha256Certificate, digest)) {
6011 if (flags == PAST_CERT_EXISTS
6012 || (flags & pastSigningCertificatesFlags[i]) == flags) {
6013 return true;
6014 }
6015 }
6016 }
6017 }
6018
6019 // not in previous certs signing history, just check the current signer
6020 if (signatures.length == 1) {
6021 byte[] digest =
6022 PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray());
6023 return Arrays.equals(sha256Certificate, digest);
6024 }
6025 return false;
6026 }
6027
Patrick Baumann47117fc2017-12-19 10:17:21 -08006028 /** Returns true if the signatures in this and other match exactly. */
6029 public boolean signaturesMatchExactly(SigningDetails other) {
6030 return Signature.areExactMatch(this.signatures, other.signatures);
6031 }
6032
6033 @Override
6034 public int describeContents() {
6035 return 0;
6036 }
6037
6038 @Override
6039 public void writeToParcel(Parcel dest, int flags) {
6040 boolean isUnknown = UNKNOWN == this;
6041 dest.writeBoolean(isUnknown);
6042 if (isUnknown) {
6043 return;
6044 }
6045 dest.writeTypedArray(this.signatures, flags);
6046 dest.writeInt(this.signatureSchemeVersion);
6047 dest.writeArraySet(this.publicKeys);
Daniel Cashman77029c52018-01-18 16:19:29 -08006048 dest.writeTypedArray(this.pastSigningCertificates, flags);
6049 dest.writeIntArray(this.pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006050 }
6051
6052 protected SigningDetails(Parcel in) {
6053 final ClassLoader boot = Object.class.getClassLoader();
6054 this.signatures = in.createTypedArray(Signature.CREATOR);
6055 this.signatureSchemeVersion = in.readInt();
6056 this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot);
Daniel Cashman77029c52018-01-18 16:19:29 -08006057 this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR);
6058 this.pastSigningCertificatesFlags = in.createIntArray();
Patrick Baumann47117fc2017-12-19 10:17:21 -08006059 }
6060
6061 public static final Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() {
6062 @Override
6063 public SigningDetails createFromParcel(Parcel source) {
6064 if (source.readBoolean()) {
6065 return UNKNOWN;
6066 }
6067 return new SigningDetails(source);
6068 }
6069
6070 @Override
6071 public SigningDetails[] newArray(int size) {
6072 return new SigningDetails[size];
6073 }
6074 };
6075
6076 @Override
6077 public boolean equals(Object o) {
6078 if (this == o) return true;
6079 if (!(o instanceof SigningDetails)) return false;
6080
6081 SigningDetails that = (SigningDetails) o;
6082
6083 if (signatureSchemeVersion != that.signatureSchemeVersion) return false;
6084 if (!Signature.areExactMatch(signatures, that.signatures)) return false;
Daniel Cashman77029c52018-01-18 16:19:29 -08006085 if (publicKeys != null) {
6086 if (!publicKeys.equals((that.publicKeys))) {
6087 return false;
6088 }
6089 } else if (that.publicKeys != null) {
6090 return false;
6091 }
6092
6093 // can't use Signature.areExactMatch() because order matters with the past signing certs
6094 if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) {
6095 return false;
6096 }
6097 if (!Arrays.equals(pastSigningCertificatesFlags, that.pastSigningCertificatesFlags)) {
6098 return false;
6099 }
6100
6101 return true;
Patrick Baumann47117fc2017-12-19 10:17:21 -08006102 }
6103
6104 @Override
6105 public int hashCode() {
6106 int result = +Arrays.hashCode(signatures);
6107 result = 31 * result + signatureSchemeVersion;
6108 result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0);
Daniel Cashman77029c52018-01-18 16:19:29 -08006109 result = 31 * result + Arrays.hashCode(pastSigningCertificates);
6110 result = 31 * result + Arrays.hashCode(pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006111 return result;
6112 }
Daniel Cashman77029c52018-01-18 16:19:29 -08006113
6114 /**
6115 * Builder of {@code SigningDetails} instances.
6116 */
6117 public static class Builder {
6118 private Signature[] mSignatures;
6119 private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
6120 private Signature[] mPastSigningCertificates;
6121 private int[] mPastSigningCertificatesFlags;
6122
6123 public Builder() {
6124 }
6125
6126 /** get signing certificates used to sign the current APK */
6127 public Builder setSignatures(Signature[] signatures) {
6128 mSignatures = signatures;
6129 return this;
6130 }
6131
6132 /** set the signature scheme version used to sign the APK */
6133 public Builder setSignatureSchemeVersion(int signatureSchemeVersion) {
6134 mSignatureSchemeVersion = signatureSchemeVersion;
6135 return this;
6136 }
6137
6138 /** set the signing certificates by which the APK proved it can be authenticated */
6139 public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
6140 mPastSigningCertificates = pastSigningCertificates;
6141 return this;
6142 }
6143
6144 /** set the flags for the {@code pastSigningCertificates} */
6145 public Builder setPastSigningCertificatesFlags(int[] pastSigningCertificatesFlags) {
6146 mPastSigningCertificatesFlags = pastSigningCertificatesFlags;
6147 return this;
6148 }
6149
6150 private void checkInvariants() {
6151 // must have signatures and scheme version set
6152 if (mSignatures == null) {
6153 throw new IllegalStateException("SigningDetails requires the current signing"
6154 + " certificates.");
6155 }
6156
6157 // pastSigningCerts and flags must match up
6158 boolean pastMismatch = false;
6159 if (mPastSigningCertificates != null && mPastSigningCertificatesFlags != null) {
6160 if (mPastSigningCertificates.length != mPastSigningCertificatesFlags.length) {
6161 pastMismatch = true;
6162 }
6163 } else if (!(mPastSigningCertificates == null
6164 && mPastSigningCertificatesFlags == null)) {
6165 pastMismatch = true;
6166 }
6167 if (pastMismatch) {
6168 throw new IllegalStateException("SigningDetails must have a one to one mapping "
6169 + "between pastSigningCertificates and pastSigningCertificatesFlags");
6170 }
6171 }
6172 /** build a {@code SigningDetails} object */
6173 public SigningDetails build()
6174 throws CertificateException {
6175 checkInvariants();
6176 return new SigningDetails(mSignatures, mSignatureSchemeVersion,
6177 mPastSigningCertificates, mPastSigningCertificatesFlags);
6178 }
6179 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08006180 }
6181
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006182 /**
6183 * Representation of a full package parsed from APK files on disk. A package
6184 * consists of a single base APK, and zero or more split APKs.
6185 */
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006186 public final static class Package implements Parcelable {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006187
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006188 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006189
Svet Ganov67882122016-12-11 16:36:34 -08006190 // The package name declared in the manifest as the package can be
6191 // renamed, for example static shared libs use synthetic package names.
6192 public String manifestPackageName;
6193
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006194 /** Names of any split APKs, ordered by parsed splitName */
6195 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006196
6197 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07006198
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07006199 public String volumeUuid;
6200
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006201 /**
6202 * Path where this package was found on disk. For monolithic packages
6203 * this is path to single base APK file; for cluster packages this is
6204 * path to the cluster directory.
6205 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006206 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006207
6208 /** Path of base APK */
6209 public String baseCodePath;
6210 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006211 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006212
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006213 /** Revision code of base APK */
6214 public int baseRevisionCode;
6215 /** Revision codes of any split APKs, ordered by parsed splitName */
6216 public int[] splitRevisionCodes;
6217
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006218 /** Flags of any split APKs; ordered by parsed splitName */
6219 public int[] splitFlags;
6220
Alex Klyubinb9f8a522015-02-03 11:12:59 -08006221 /**
6222 * Private flags of any split APKs; ordered by parsed splitName.
6223 *
6224 * {@hide}
6225 */
6226 public int[] splitPrivateFlags;
6227
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006228 public boolean baseHardwareAccelerated;
6229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006230 // For now we only support one application per package.
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006231 public ApplicationInfo applicationInfo = new ApplicationInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006232
6233 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
6234 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
6235 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
6236 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
6237 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
6238 public final ArrayList<Service> services = new ArrayList<Service>(0);
6239 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
6240
6241 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
6242
Dianne Hackborn854060af2009-07-09 18:14:31 -07006243 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006244
Svet Ganov354cd3c2015-12-17 11:35:04 -08006245 public Package parentPackage;
6246 public ArrayList<Package> childPackages;
6247
Svet Ganov67882122016-12-11 16:36:34 -08006248 public String staticSharedLibName = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006249 public long staticSharedLibVersion = 0;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006250 public ArrayList<String> libraryNames = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07006251 public ArrayList<String> usesLibraries = null;
Svet Ganov67882122016-12-11 16:36:34 -08006252 public ArrayList<String> usesStaticLibraries = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006253 public long[] usesStaticLibrariesVersions = null;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006254 public String[][] usesStaticLibrariesCertDigests = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07006255 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006256 public String[] usesLibraryFiles = null;
6257
Dianne Hackbornb09491f2013-07-22 15:30:11 -07006258 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
6259
Dianne Hackbornc1552392010-03-03 16:19:01 -08006260 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006261 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006262 public ArrayList<String> mAdoptPermissions = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006264 // We store the application meta-data independently to avoid multiple unwanted references
6265 public Bundle mAppMetaData = null;
6266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006267 // The version code declared for this package.
6268 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006269
Dianne Hackborn3accca02013-09-20 09:32:11 -07006270 // The major version code declared for this package.
6271 public int mVersionCodeMajor;
6272
6273 // Return long containing mVersionCode and mVersionCodeMajor.
6274 public long getLongVersionCode() {
6275 return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
6276 }
6277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006278 // The version name declared for this package.
6279 public String mVersionName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006281 // The shared user id that this package wants to use.
6282 public String mSharedUserId;
6283
6284 // The shared user label that this package wants to use.
6285 public int mSharedUserLabel;
6286
6287 // Signatures that were read from the package.
Patrick Baumann47117fc2017-12-19 10:17:21 -08006288 @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006289
6290 // For use by package manager service for quick lookup of
6291 // preferred up order.
6292 public int mPreferredOrder = 0;
6293
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006294 // For use by package manager to keep track of when a package was last used.
Brian Carlstromca82e612016-04-19 23:16:08 -07006295 public long[] mLastPackageUsageTimeInMills =
6296 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006297
Amith Yamasani13593602012-03-22 16:16:17 -07006298 // // User set enabled state.
6299 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
6300 //
6301 // // Whether the package has been stopped.
6302 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08006303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006304 // Additional data supplied by callers.
6305 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07006306
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006307 // Applications hardware preferences
6308 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006309
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006310 // Applications requested features
Dianne Hackborn49237342009-08-27 20:08:01 -07006311 public ArrayList<FeatureInfo> reqFeatures = null;
6312
Adam Lesinskid3edfde2014-08-08 17:32:44 -07006313 // Applications requested feature groups
6314 public ArrayList<FeatureGroupInfo> featureGroups = null;
6315
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08006316 public int installLocation;
6317
Jeff Hao272bf3a2014-10-08 13:34:43 -07006318 public boolean coreApp;
6319
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08006320 /* An app that's required for all users and cannot be uninstalled for a user */
6321 public boolean mRequiredForAllUsers;
6322
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006323 /* The restricted account authenticator type that is used by this application */
6324 public String mRestrictedAccountType;
6325
Amith Yamasaniccbe3892013-04-12 17:52:42 -07006326 /* The required account type without which this application will not function */
6327 public String mRequiredAccountType;
6328
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006329 public String mOverlayTarget;
Adrian Roosc84df772018-01-19 21:20:22 +01006330 public String mOverlayCategory;
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006331 public int mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -08006332 public boolean mOverlayIsStatic;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006333
Alan Viveretteb6a25732017-11-21 14:49:24 -05006334 public int mCompileSdkVersion;
6335 public String mCompileSdkVersionCodename;
6336
Geremy Condraf1bcca82013-01-07 22:35:24 -08006337 /**
dcashman989eb3712014-06-17 12:56:12 -07006338 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08006339 */
dcashman989eb3712014-06-17 12:56:12 -07006340 public ArraySet<String> mUpgradeKeySets;
6341 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08006342
Narayan Kamath4903f642014-08-11 13:33:45 +01006343 /**
6344 * The install time abi override for this package, if any.
6345 *
6346 * TODO: This seems like a horrible place to put the abiOverride because
6347 * this isn't something the packageParser parsers. However, this fits in with
6348 * the rest of the PackageManager where package scanning randomly pushes
6349 * and prods fields out of {@code this.applicationInfo}.
6350 */
6351 public String cpuAbiOverride;
Selim Gurun2d291d82016-02-05 17:50:53 -08006352 /**
6353 * The install time abi override to choose 32bit abi's when multiple abi's
6354 * are present. This is only meaningfull for multiarch applications.
6355 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
6356 */
6357 public boolean use32bitAbi;
Narayan Kamath4903f642014-08-11 13:33:45 +01006358
Todd Kennedyfdd241a2016-04-28 12:26:53 -07006359 public byte[] restrictUpdateHash;
6360
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006361 /** Set if the app or any of its components are visible to instant applications. */
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006362 public boolean visibleToInstantApps;
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006363 /** Whether or not the package is a stub and must be replaced by the full version. */
6364 public boolean isStub;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006365
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006366 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006367 this.packageName = packageName;
Svet Ganov67882122016-12-11 16:36:34 -08006368 this.manifestPackageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006369 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006370 applicationInfo.uid = -1;
6371 }
6372
Svet Ganov354cd3c2015-12-17 11:35:04 -08006373 public void setApplicationVolumeUuid(String volumeUuid) {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006374 final UUID storageUuid = StorageManager.convert(volumeUuid);
Svet Ganov354cd3c2015-12-17 11:35:04 -08006375 this.applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006376 this.applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006377 if (childPackages != null) {
6378 final int packageCount = childPackages.size();
6379 for (int i = 0; i < packageCount; i++) {
6380 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006381 childPackages.get(i).applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006382 }
6383 }
6384 }
6385
6386 public void setApplicationInfoCodePath(String codePath) {
6387 this.applicationInfo.setCodePath(codePath);
6388 if (childPackages != null) {
6389 final int packageCount = childPackages.size();
6390 for (int i = 0; i < packageCount; i++) {
6391 childPackages.get(i).applicationInfo.setCodePath(codePath);
6392 }
6393 }
6394 }
6395
Todd Kennedy30a23a52018-01-04 13:27:49 -08006396 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6397 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006398 public void setApplicationInfoResourcePath(String resourcePath) {
6399 this.applicationInfo.setResourcePath(resourcePath);
6400 if (childPackages != null) {
6401 final int packageCount = childPackages.size();
6402 for (int i = 0; i < packageCount; i++) {
6403 childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
6404 }
6405 }
6406 }
6407
Todd Kennedy30a23a52018-01-04 13:27:49 -08006408 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6409 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006410 public void setApplicationInfoBaseResourcePath(String resourcePath) {
6411 this.applicationInfo.setBaseResourcePath(resourcePath);
6412 if (childPackages != null) {
6413 final int packageCount = childPackages.size();
6414 for (int i = 0; i < packageCount; i++) {
6415 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
6416 }
6417 }
6418 }
6419
6420 public void setApplicationInfoBaseCodePath(String baseCodePath) {
6421 this.applicationInfo.setBaseCodePath(baseCodePath);
6422 if (childPackages != null) {
6423 final int packageCount = childPackages.size();
6424 for (int i = 0; i < packageCount; i++) {
6425 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
6426 }
6427 }
6428 }
6429
Todd Kennedy13715d52016-08-01 13:38:57 -07006430 public List<String> getChildPackageNames() {
6431 if (childPackages == null) {
6432 return null;
6433 }
6434 final int childCount = childPackages.size();
6435 final List<String> childPackageNames = new ArrayList<>(childCount);
6436 for (int i = 0; i < childCount; i++) {
6437 String childPackageName = childPackages.get(i).packageName;
6438 childPackageNames.add(childPackageName);
6439 }
6440 return childPackageNames;
6441 }
6442
Svet Ganov354cd3c2015-12-17 11:35:04 -08006443 public boolean hasChildPackage(String packageName) {
6444 final int childCount = (childPackages != null) ? childPackages.size() : 0;
6445 for (int i = 0; i < childCount; i++) {
6446 if (childPackages.get(i).packageName.equals(packageName)) {
6447 return true;
6448 }
6449 }
6450 return false;
6451 }
6452
6453 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
6454 this.applicationInfo.setSplitCodePaths(splitCodePaths);
6455 // Children have no splits
6456 }
6457
Todd Kennedy30a23a52018-01-04 13:27:49 -08006458 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6459 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006460 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
6461 this.applicationInfo.setSplitResourcePaths(resroucePaths);
6462 // Children have no splits
6463 }
6464
6465 public void setSplitCodePaths(String[] codePaths) {
6466 this.splitCodePaths = codePaths;
6467 }
6468
6469 public void setCodePath(String codePath) {
6470 this.codePath = codePath;
6471 if (childPackages != null) {
6472 final int packageCount = childPackages.size();
6473 for (int i = 0; i < packageCount; i++) {
6474 childPackages.get(i).codePath = codePath;
6475 }
6476 }
6477 }
6478
6479 public void setBaseCodePath(String baseCodePath) {
6480 this.baseCodePath = baseCodePath;
6481 if (childPackages != null) {
6482 final int packageCount = childPackages.size();
6483 for (int i = 0; i < packageCount; i++) {
6484 childPackages.get(i).baseCodePath = baseCodePath;
6485 }
6486 }
6487 }
6488
Patrick Baumann47117fc2017-12-19 10:17:21 -08006489 /** Sets signing details on the package and any of its children. */
6490 public void setSigningDetails(@NonNull SigningDetails signingDetails) {
6491 mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006492 if (childPackages != null) {
6493 final int packageCount = childPackages.size();
6494 for (int i = 0; i < packageCount; i++) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08006495 childPackages.get(i).mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006496 }
6497 }
6498 }
6499
6500 public void setVolumeUuid(String volumeUuid) {
6501 this.volumeUuid = volumeUuid;
6502 if (childPackages != null) {
6503 final int packageCount = childPackages.size();
6504 for (int i = 0; i < packageCount; i++) {
6505 childPackages.get(i).volumeUuid = volumeUuid;
6506 }
6507 }
6508 }
6509
6510 public void setApplicationInfoFlags(int mask, int flags) {
6511 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
6512 if (childPackages != null) {
6513 final int packageCount = childPackages.size();
6514 for (int i = 0; i < packageCount; i++) {
6515 childPackages.get(i).applicationInfo.flags =
6516 (applicationInfo.flags & ~mask) | (mask & flags);
6517 }
6518 }
6519 }
6520
Selim Gurun75827b22016-02-09 10:55:33 -08006521 public void setUse32bitAbi(boolean use32bitAbi) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006522 this.use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006523 if (childPackages != null) {
6524 final int packageCount = childPackages.size();
6525 for (int i = 0; i < packageCount; i++) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006526 childPackages.get(i).use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006527 }
6528 }
6529 }
6530
Svetoslav Ganov40610e32017-06-20 19:35:51 -07006531 public boolean isLibrary() {
6532 return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
6533 }
6534
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006535 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07006536 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006537 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07006538 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6539 Collections.addAll(paths, splitCodePaths);
6540 }
6541 return paths;
6542 }
6543
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006544 /**
6545 * Filtered set of {@link #getAllCodePaths()} that excludes
6546 * resource-only APKs.
6547 */
6548 public List<String> getAllCodePathsExcludingResourceOnly() {
6549 ArrayList<String> paths = new ArrayList<>();
6550 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6551 paths.add(baseCodePath);
6552 }
6553 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6554 for (int i = 0; i < splitCodePaths.length; i++) {
6555 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6556 paths.add(splitCodePaths[i]);
6557 }
6558 }
6559 }
6560 return paths;
6561 }
6562
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006563 public void setPackageName(String newName) {
6564 packageName = newName;
6565 applicationInfo.packageName = newName;
6566 for (int i=permissions.size()-1; i>=0; i--) {
6567 permissions.get(i).setPackageName(newName);
6568 }
6569 for (int i=permissionGroups.size()-1; i>=0; i--) {
6570 permissionGroups.get(i).setPackageName(newName);
6571 }
6572 for (int i=activities.size()-1; i>=0; i--) {
6573 activities.get(i).setPackageName(newName);
6574 }
6575 for (int i=receivers.size()-1; i>=0; i--) {
6576 receivers.get(i).setPackageName(newName);
6577 }
6578 for (int i=providers.size()-1; i>=0; i--) {
6579 providers.get(i).setPackageName(newName);
6580 }
6581 for (int i=services.size()-1; i>=0; i--) {
6582 services.get(i).setPackageName(newName);
6583 }
6584 for (int i=instrumentation.size()-1; i>=0; i--) {
6585 instrumentation.get(i).setPackageName(newName);
6586 }
6587 }
Dianne Hackborn65696252012-03-05 18:49:21 -08006588
6589 public boolean hasComponentClassName(String name) {
6590 for (int i=activities.size()-1; i>=0; i--) {
6591 if (name.equals(activities.get(i).className)) {
6592 return true;
6593 }
6594 }
6595 for (int i=receivers.size()-1; i>=0; i--) {
6596 if (name.equals(receivers.get(i).className)) {
6597 return true;
6598 }
6599 }
6600 for (int i=providers.size()-1; i>=0; i--) {
6601 if (name.equals(providers.get(i).className)) {
6602 return true;
6603 }
6604 }
6605 for (int i=services.size()-1; i>=0; i--) {
6606 if (name.equals(services.get(i).className)) {
6607 return true;
6608 }
6609 }
6610 for (int i=instrumentation.size()-1; i>=0; i--) {
6611 if (name.equals(instrumentation.get(i).className)) {
6612 return true;
6613 }
6614 }
6615 return false;
6616 }
6617
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006618 /** @hide */
6619 public boolean isExternal() {
6620 return applicationInfo.isExternal();
6621 }
6622
6623 /** @hide */
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08006624 public boolean isForwardLocked() {
6625 return applicationInfo.isForwardLocked();
6626 }
6627
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006628 /** @hide */
6629 public boolean isOem() {
6630 return applicationInfo.isOem();
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006631 }
6632
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006633 /** @hide */
Jiyong Park002fdbd2017-02-13 20:50:31 +09006634 public boolean isVendor() {
6635 return applicationInfo.isVendor();
6636 }
6637
6638 /** @hide */
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09006639 public boolean isProduct() {
6640 return applicationInfo.isProduct();
6641 }
6642
6643 /** @hide */
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006644 public boolean isPrivileged() {
Svet Ganovadc1cf42015-06-15 16:36:24 -07006645 return applicationInfo.isPrivilegedApp();
6646 }
6647
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006648 /** @hide */
6649 public boolean isSystem() {
6650 return applicationInfo.isSystemApp();
6651 }
6652
6653 /** @hide */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006654 public boolean isUpdatedSystemApp() {
6655 return applicationInfo.isUpdatedSystemApp();
6656 }
6657
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006658 /** @hide */
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006659 public boolean canHaveOatDir() {
6660 // The following app types CANNOT have oat directory
6661 // - non-updated system apps
6662 // - forward-locked apps or apps installed in ASEC containers
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006663 return (!isSystem() || isUpdatedSystemApp())
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006664 && !isForwardLocked() && !applicationInfo.isExternalAsec();
6665 }
6666
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006667 public boolean isMatch(int flags) {
6668 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006669 return isSystem();
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006670 }
6671 return true;
6672 }
6673
Brian Carlstromca82e612016-04-19 23:16:08 -07006674 public long getLatestPackageUseTimeInMills() {
6675 long latestUse = 0L;
6676 for (long use : mLastPackageUsageTimeInMills) {
6677 latestUse = Math.max(latestUse, use);
6678 }
6679 return latestUse;
6680 }
6681
David Brazdil90e26992016-04-18 14:08:52 +01006682 public long getLatestForegroundPackageUseTimeInMills() {
6683 int[] foregroundReasons = {
6684 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
6685 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
6686 };
6687
6688 long latestUse = 0L;
6689 for (int reason : foregroundReasons) {
6690 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
6691 }
6692 return latestUse;
6693 }
6694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006695 public String toString() {
6696 return "Package{"
6697 + Integer.toHexString(System.identityHashCode(this))
6698 + " " + packageName + "}";
6699 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006700
6701 @Override
6702 public int describeContents() {
6703 return 0;
6704 }
6705
6706 public Package(Parcel dest) {
6707 // We use the boot classloader for all classes that we load.
6708 final ClassLoader boot = Object.class.getClassLoader();
6709
Narayan Kamath07ac1442017-02-10 15:08:07 +00006710 packageName = dest.readString().intern();
Svet Ganov67882122016-12-11 16:36:34 -08006711 manifestPackageName = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006712 splitNames = dest.readStringArray();
6713 volumeUuid = dest.readString();
6714 codePath = dest.readString();
6715 baseCodePath = dest.readString();
6716 splitCodePaths = dest.readStringArray();
6717 baseRevisionCode = dest.readInt();
6718 splitRevisionCodes = dest.createIntArray();
6719 splitFlags = dest.createIntArray();
6720 splitPrivateFlags = dest.createIntArray();
6721 baseHardwareAccelerated = (dest.readInt() == 1);
6722 applicationInfo = dest.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006723 if (applicationInfo.permission != null) {
6724 applicationInfo.permission = applicationInfo.permission.intern();
6725 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006726
6727 // We don't serialize the "owner" package and the application info object for each of
6728 // these components, in order to save space and to avoid circular dependencies while
6729 // serialization. We need to fix them all up here.
6730 dest.readParcelableList(permissions, boot);
6731 fixupOwner(permissions);
6732 dest.readParcelableList(permissionGroups, boot);
6733 fixupOwner(permissionGroups);
6734 dest.readParcelableList(activities, boot);
6735 fixupOwner(activities);
6736 dest.readParcelableList(receivers, boot);
6737 fixupOwner(receivers);
6738 dest.readParcelableList(providers, boot);
6739 fixupOwner(providers);
6740 dest.readParcelableList(services, boot);
6741 fixupOwner(services);
6742 dest.readParcelableList(instrumentation, boot);
6743 fixupOwner(instrumentation);
6744
6745 dest.readStringList(requestedPermissions);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006746 internStringArrayList(requestedPermissions);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006747 protectedBroadcasts = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006748 internStringArrayList(protectedBroadcasts);
6749
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006750 parentPackage = dest.readParcelable(boot);
6751
6752 childPackages = new ArrayList<>();
6753 dest.readParcelableList(childPackages, boot);
6754 if (childPackages.size() == 0) {
6755 childPackages = null;
6756 }
6757
Svet Ganov67882122016-12-11 16:36:34 -08006758 staticSharedLibName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006759 if (staticSharedLibName != null) {
6760 staticSharedLibName = staticSharedLibName.intern();
6761 }
Dianne Hackborn3accca02013-09-20 09:32:11 -07006762 staticSharedLibVersion = dest.readLong();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006763 libraryNames = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006764 internStringArrayList(libraryNames);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006765 usesLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006766 internStringArrayList(usesLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006767 usesOptionalLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006768 internStringArrayList(usesOptionalLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006769 usesLibraryFiles = dest.readStringArray();
6770
Svet Ganov67882122016-12-11 16:36:34 -08006771 final int libCount = dest.readInt();
6772 if (libCount > 0) {
6773 usesStaticLibraries = new ArrayList<>(libCount);
6774 dest.readStringList(usesStaticLibraries);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006775 internStringArrayList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006776 usesStaticLibrariesVersions = new long[libCount];
6777 dest.readLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006778 usesStaticLibrariesCertDigests = new String[libCount][];
6779 for (int i = 0; i < libCount; i++) {
6780 usesStaticLibrariesCertDigests[i] = dest.createStringArray();
6781 }
Svet Ganov67882122016-12-11 16:36:34 -08006782 }
6783
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006784 preferredActivityFilters = new ArrayList<>();
6785 dest.readParcelableList(preferredActivityFilters, boot);
6786 if (preferredActivityFilters.size() == 0) {
6787 preferredActivityFilters = null;
6788 }
6789
6790 mOriginalPackages = dest.createStringArrayList();
6791 mRealPackage = dest.readString();
6792 mAdoptPermissions = dest.createStringArrayList();
6793 mAppMetaData = dest.readBundle();
6794 mVersionCode = dest.readInt();
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08006795 mVersionCodeMajor = dest.readInt();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006796 mVersionName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006797 if (mVersionName != null) {
6798 mVersionName = mVersionName.intern();
6799 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006800 mSharedUserId = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006801 if (mSharedUserId != null) {
6802 mSharedUserId = mSharedUserId.intern();
6803 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006804 mSharedUserLabel = dest.readInt();
6805
Patrick Baumann47117fc2017-12-19 10:17:21 -08006806 mSigningDetails = dest.readParcelable(boot);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006807
6808 mPreferredOrder = dest.readInt();
6809
6810 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6811 // is parsed from the APK.
6812
6813 // Object mExtras is not persisted because it is not information that is read from
6814 // the APK, rather, it is supplied by callers.
6815
6816
6817 configPreferences = new ArrayList<>();
6818 dest.readParcelableList(configPreferences, boot);
6819 if (configPreferences.size() == 0) {
6820 configPreferences = null;
6821 }
6822
6823 reqFeatures = new ArrayList<>();
6824 dest.readParcelableList(reqFeatures, boot);
6825 if (reqFeatures.size() == 0) {
6826 reqFeatures = null;
6827 }
6828
6829 featureGroups = new ArrayList<>();
6830 dest.readParcelableList(featureGroups, boot);
6831 if (featureGroups.size() == 0) {
6832 featureGroups = null;
6833 }
6834
6835 installLocation = dest.readInt();
6836 coreApp = (dest.readInt() == 1);
6837 mRequiredForAllUsers = (dest.readInt() == 1);
6838 mRestrictedAccountType = dest.readString();
6839 mRequiredAccountType = dest.readString();
6840 mOverlayTarget = dest.readString();
Adrian Roosc84df772018-01-19 21:20:22 +01006841 mOverlayCategory = dest.readString();
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006842 mOverlayPriority = dest.readInt();
Adam Lesinskie7334972018-01-17 16:13:52 -08006843 mOverlayIsStatic = (dest.readInt() == 1);
Alan Viveretteb6a25732017-11-21 14:49:24 -05006844 mCompileSdkVersion = dest.readInt();
6845 mCompileSdkVersionCodename = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006846 mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
6847
6848 mKeySetMapping = readKeySetMapping(dest);
6849
6850 cpuAbiOverride = dest.readString();
6851 use32bitAbi = (dest.readInt() == 1);
6852 restrictUpdateHash = dest.createByteArray();
Chad Brubaker49f24c62017-04-05 13:08:21 -07006853 visibleToInstantApps = dest.readInt() == 1;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006854 }
6855
Narayan Kamath07ac1442017-02-10 15:08:07 +00006856 private static void internStringArrayList(List<String> list) {
6857 if (list != null) {
6858 final int N = list.size();
6859 for (int i = 0; i < N; ++i) {
6860 list.set(i, list.get(i).intern());
6861 }
6862 }
6863 }
6864
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006865 /**
6866 * Sets the package owner and the the {@code applicationInfo} for every component
6867 * owner by this package.
6868 */
6869 private void fixupOwner(List<? extends Component<?>> list) {
6870 if (list != null) {
6871 for (Component<?> c : list) {
6872 c.owner = this;
6873 if (c instanceof Activity) {
6874 ((Activity) c).info.applicationInfo = this.applicationInfo;
6875 } else if (c instanceof Service) {
6876 ((Service) c).info.applicationInfo = this.applicationInfo;
6877 } else if (c instanceof Provider) {
6878 ((Provider) c).info.applicationInfo = this.applicationInfo;
6879 }
6880 }
6881 }
6882 }
6883
6884 @Override
6885 public void writeToParcel(Parcel dest, int flags) {
6886 dest.writeString(packageName);
Svet Ganov67882122016-12-11 16:36:34 -08006887 dest.writeString(manifestPackageName);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006888 dest.writeStringArray(splitNames);
6889 dest.writeString(volumeUuid);
6890 dest.writeString(codePath);
6891 dest.writeString(baseCodePath);
6892 dest.writeStringArray(splitCodePaths);
6893 dest.writeInt(baseRevisionCode);
6894 dest.writeIntArray(splitRevisionCodes);
6895 dest.writeIntArray(splitFlags);
6896 dest.writeIntArray(splitPrivateFlags);
6897 dest.writeInt(baseHardwareAccelerated ? 1 : 0);
6898 dest.writeParcelable(applicationInfo, flags);
6899
6900 dest.writeParcelableList(permissions, flags);
6901 dest.writeParcelableList(permissionGroups, flags);
6902 dest.writeParcelableList(activities, flags);
6903 dest.writeParcelableList(receivers, flags);
6904 dest.writeParcelableList(providers, flags);
6905 dest.writeParcelableList(services, flags);
6906 dest.writeParcelableList(instrumentation, flags);
6907
6908 dest.writeStringList(requestedPermissions);
6909 dest.writeStringList(protectedBroadcasts);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07006910
6911 // TODO: This doesn't work: b/64295061
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006912 dest.writeParcelable(parentPackage, flags);
6913 dest.writeParcelableList(childPackages, flags);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07006914
Svet Ganov67882122016-12-11 16:36:34 -08006915 dest.writeString(staticSharedLibName);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006916 dest.writeLong(staticSharedLibVersion);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006917 dest.writeStringList(libraryNames);
6918 dest.writeStringList(usesLibraries);
6919 dest.writeStringList(usesOptionalLibraries);
6920 dest.writeStringArray(usesLibraryFiles);
6921
Svet Ganov67882122016-12-11 16:36:34 -08006922 if (ArrayUtils.isEmpty(usesStaticLibraries)) {
6923 dest.writeInt(-1);
6924 } else {
6925 dest.writeInt(usesStaticLibraries.size());
6926 dest.writeStringList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006927 dest.writeLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006928 for (String[] usesStaticLibrariesCertDigest : usesStaticLibrariesCertDigests) {
6929 dest.writeStringArray(usesStaticLibrariesCertDigest);
6930 }
Svet Ganov67882122016-12-11 16:36:34 -08006931 }
6932
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006933 dest.writeParcelableList(preferredActivityFilters, flags);
6934
6935 dest.writeStringList(mOriginalPackages);
6936 dest.writeString(mRealPackage);
6937 dest.writeStringList(mAdoptPermissions);
6938 dest.writeBundle(mAppMetaData);
6939 dest.writeInt(mVersionCode);
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08006940 dest.writeInt(mVersionCodeMajor);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006941 dest.writeString(mVersionName);
6942 dest.writeString(mSharedUserId);
6943 dest.writeInt(mSharedUserLabel);
6944
Patrick Baumann47117fc2017-12-19 10:17:21 -08006945 dest.writeParcelable(mSigningDetails, flags);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006946
6947 dest.writeInt(mPreferredOrder);
6948
6949 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6950 // is parsed from the APK.
6951
6952 // Object mExtras is not persisted because it is not information that is read from
6953 // the APK, rather, it is supplied by callers.
6954
6955 dest.writeParcelableList(configPreferences, flags);
6956 dest.writeParcelableList(reqFeatures, flags);
6957 dest.writeParcelableList(featureGroups, flags);
6958
6959 dest.writeInt(installLocation);
6960 dest.writeInt(coreApp ? 1 : 0);
6961 dest.writeInt(mRequiredForAllUsers ? 1 : 0);
6962 dest.writeString(mRestrictedAccountType);
6963 dest.writeString(mRequiredAccountType);
6964 dest.writeString(mOverlayTarget);
Adrian Roosc84df772018-01-19 21:20:22 +01006965 dest.writeString(mOverlayCategory);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006966 dest.writeInt(mOverlayPriority);
Adam Lesinskie7334972018-01-17 16:13:52 -08006967 dest.writeInt(mOverlayIsStatic ? 1 : 0);
Alan Viveretteb6a25732017-11-21 14:49:24 -05006968 dest.writeInt(mCompileSdkVersion);
6969 dest.writeString(mCompileSdkVersionCodename);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006970 dest.writeArraySet(mUpgradeKeySets);
6971 writeKeySetMapping(dest, mKeySetMapping);
6972 dest.writeString(cpuAbiOverride);
6973 dest.writeInt(use32bitAbi ? 1 : 0);
6974 dest.writeByteArray(restrictUpdateHash);
Chad Brubaker49f24c62017-04-05 13:08:21 -07006975 dest.writeInt(visibleToInstantApps ? 1 : 0);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006976 }
6977
6978
6979 /**
6980 * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
6981 */
6982 private static void writeKeySetMapping(
6983 Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
6984 if (keySetMapping == null) {
6985 dest.writeInt(-1);
6986 return;
6987 }
6988
6989 final int N = keySetMapping.size();
6990 dest.writeInt(N);
6991
6992 for (int i = 0; i < N; i++) {
6993 dest.writeString(keySetMapping.keyAt(i));
6994 ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
6995 if (keys == null) {
6996 dest.writeInt(-1);
6997 continue;
6998 }
6999
7000 final int M = keys.size();
7001 dest.writeInt(M);
7002 for (int j = 0; j < M; j++) {
7003 dest.writeSerializable(keys.valueAt(j));
7004 }
7005 }
7006 }
7007
7008 /**
7009 * Reads a keyset mapping from the given parcel at the given data position. May return
7010 * {@code null} if the serialized mapping was {@code null}.
7011 */
7012 private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
7013 final int N = in.readInt();
7014 if (N == -1) {
7015 return null;
7016 }
7017
7018 ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
7019 for (int i = 0; i < N; ++i) {
7020 String key = in.readString();
7021 final int M = in.readInt();
7022 if (M == -1) {
7023 keySetMapping.put(key, null);
7024 continue;
7025 }
7026
7027 ArraySet<PublicKey> keys = new ArraySet<>(M);
7028 for (int j = 0; j < M; ++j) {
7029 PublicKey pk = (PublicKey) in.readSerializable();
7030 keys.add(pk);
7031 }
7032
7033 keySetMapping.put(key, keys);
7034 }
7035
7036 return keySetMapping;
7037 }
7038
7039 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
7040 public Package createFromParcel(Parcel in) {
7041 return new Package(in);
7042 }
7043
7044 public Package[] newArray(int size) {
7045 return new Package[size];
7046 }
7047 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007048 }
7049
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007050 public static abstract class Component<II extends IntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007051 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007052 public final String className;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007054 public Bundle metaData;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007055 public Package owner;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007056
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007057 ComponentName componentName;
7058 String componentShortName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007060 public Component(Package _owner) {
7061 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007062 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007063 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007064 }
7065
7066 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
7067 owner = args.owner;
7068 intents = new ArrayList<II>(0);
Todd Kennedybb8a42d2016-06-02 14:13:56 -07007069 if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
7070 true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
7071 args.roundIconRes, args.logoRes, args.bannerRes)) {
7072 className = outInfo.name;
7073 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007074 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007075 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007076 }
7077
7078 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
7079 this(args, (PackageItemInfo)outInfo);
7080 if (args.outError[0] != null) {
7081 return;
7082 }
7083
7084 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007085 CharSequence pname;
7086 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07007087 pname = args.sa.getNonConfigurationString(args.processRes,
7088 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007089 } else {
7090 // Some older apps have been seen to use a resource reference
7091 // here that on older builds was ignored (with a warning). We
7092 // need to continue to do this for them so they don't break.
7093 pname = args.sa.getNonResourceString(args.processRes);
7094 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007095 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007096 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007097 args.flags, args.sepProcesses, args.outError);
7098 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007099
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08007100 if (args.descriptionRes != 0) {
7101 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
7102 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007103
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007104 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007105 }
7106
7107 public Component(Component<II> clone) {
7108 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007109 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007110 className = clone.className;
7111 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007112 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007113 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007114
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007115 public ComponentName getComponentName() {
7116 if (componentName != null) {
7117 return componentName;
7118 }
7119 if (className != null) {
7120 componentName = new ComponentName(owner.applicationInfo.packageName,
7121 className);
7122 }
7123 return componentName;
7124 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007125
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007126 protected Component(Parcel in) {
7127 className = in.readString();
7128 metaData = in.readBundle();
7129 intents = createIntentsList(in);
7130
7131 owner = null;
7132 }
7133
7134 protected void writeToParcel(Parcel dest, int flags) {
7135 dest.writeString(className);
7136 dest.writeBundle(metaData);
7137
7138 writeIntentsList(intents, dest, flags);
7139 }
7140
7141 /**
7142 * <p>
7143 * Implementation note: The serialized form for the intent list also contains the name
7144 * of the concrete class that's stored in the list, and assumes that every element of the
7145 * list is of the same type. This is very similar to the original parcelable mechanism.
7146 * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
7147 * and is public API. It also declares Parcelable related methods as final which means
7148 * we can't extend them. The approach of using composition instead of inheritance leads to
7149 * a large set of cascading changes in the PackageManagerService, which seem undesirable.
7150 *
7151 * <p>
7152 * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
7153 * to make sure their owner fields are consistent. See {@code fixupOwner}.
7154 */
7155 private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out,
7156 int flags) {
7157 if (list == null) {
7158 out.writeInt(-1);
7159 return;
7160 }
7161
7162 final int N = list.size();
7163 out.writeInt(N);
7164
7165 // Don't bother writing the component name if the list is empty.
7166 if (N > 0) {
7167 IntentInfo info = list.get(0);
7168 out.writeString(info.getClass().getName());
7169
7170 for (int i = 0; i < N;i++) {
7171 list.get(i).writeIntentInfoToParcel(out, flags);
7172 }
7173 }
7174 }
7175
7176 private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) {
7177 int N = in.readInt();
7178 if (N == -1) {
7179 return null;
7180 }
7181
7182 if (N == 0) {
7183 return new ArrayList<>(0);
7184 }
7185
7186 String componentName = in.readString();
7187 final ArrayList<T> intentsList;
7188 try {
7189 final Class<T> cls = (Class<T>) Class.forName(componentName);
7190 final Constructor<T> cons = cls.getConstructor(Parcel.class);
7191
7192 intentsList = new ArrayList<>(N);
7193 for (int i = 0; i < N; ++i) {
7194 intentsList.add(cons.newInstance(in));
7195 }
7196 } catch (ReflectiveOperationException ree) {
7197 throw new AssertionError("Unable to construct intent list for: " + componentName);
7198 }
7199
7200 return intentsList;
7201 }
7202
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007203 public void appendComponentShortName(StringBuilder sb) {
7204 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007205 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007206
7207 public void printComponentShortName(PrintWriter pw) {
7208 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
7209 }
7210
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007211 public void setPackageName(String packageName) {
7212 componentName = null;
7213 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007214 }
7215 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007216
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007217 public final static class Permission extends Component<IntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007218 public final PermissionInfo info;
7219 public boolean tree;
7220 public PermissionGroup group;
7221
7222 public Permission(Package _owner) {
7223 super(_owner);
7224 info = new PermissionInfo();
7225 }
7226
7227 public Permission(Package _owner, PermissionInfo _info) {
7228 super(_owner);
7229 info = _info;
7230 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007231
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007232 public void setPackageName(String packageName) {
7233 super.setPackageName(packageName);
7234 info.packageName = packageName;
7235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007236
7237 public String toString() {
7238 return "Permission{"
7239 + Integer.toHexString(System.identityHashCode(this))
7240 + " " + info.name + "}";
7241 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007242
7243 @Override
7244 public int describeContents() {
7245 return 0;
7246 }
7247
7248 @Override
7249 public void writeToParcel(Parcel dest, int flags) {
7250 super.writeToParcel(dest, flags);
7251 dest.writeParcelable(info, flags);
7252 dest.writeInt(tree ? 1 : 0);
7253 dest.writeParcelable(group, flags);
7254 }
7255
Todd Kennedyc8423932017-10-05 08:58:36 -07007256 /** @hide */
7257 public boolean isAppOp() {
7258 return info.isAppOp();
7259 }
7260
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007261 private Permission(Parcel in) {
7262 super(in);
7263 final ClassLoader boot = Object.class.getClassLoader();
7264 info = in.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007265 if (info.group != null) {
7266 info.group = info.group.intern();
7267 }
7268
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007269 tree = (in.readInt() == 1);
7270 group = in.readParcelable(boot);
7271 }
7272
7273 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
7274 public Permission createFromParcel(Parcel in) {
7275 return new Permission(in);
7276 }
7277
7278 public Permission[] newArray(int size) {
7279 return new Permission[size];
7280 }
7281 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007282 }
7283
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007284 public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007285 public final PermissionGroupInfo info;
7286
7287 public PermissionGroup(Package _owner) {
7288 super(_owner);
7289 info = new PermissionGroupInfo();
7290 }
7291
7292 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
7293 super(_owner);
7294 info = _info;
7295 }
7296
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007297 public void setPackageName(String packageName) {
7298 super.setPackageName(packageName);
7299 info.packageName = packageName;
7300 }
7301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007302 public String toString() {
7303 return "PermissionGroup{"
7304 + Integer.toHexString(System.identityHashCode(this))
7305 + " " + info.name + "}";
7306 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007307
7308 @Override
7309 public int describeContents() {
7310 return 0;
7311 }
7312
7313 @Override
7314 public void writeToParcel(Parcel dest, int flags) {
7315 super.writeToParcel(dest, flags);
7316 dest.writeParcelable(info, flags);
7317 }
7318
7319 private PermissionGroup(Parcel in) {
7320 super(in);
7321 info = in.readParcelable(Object.class.getClassLoader());
7322 }
7323
7324 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
7325 public PermissionGroup createFromParcel(Parcel in) {
7326 return new PermissionGroup(in);
7327 }
7328
7329 public PermissionGroup[] newArray(int size) {
7330 return new PermissionGroup[size];
7331 }
7332 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007333 }
7334
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007335 private static boolean copyNeeded(int flags, Package p,
7336 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07007337 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007338 // We always need to copy for other users, since we need
7339 // to fix up the uid.
7340 return true;
7341 }
7342 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
7343 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07007344 if (p.applicationInfo.enabled != enabled) {
7345 return true;
7346 }
7347 }
Rubin Xubf67c9c2016-04-20 17:09:38 +01007348 boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
7349 if (state.suspended != suspended) {
7350 return true;
7351 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007352 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007353 return true;
7354 }
7355 if (state.stopped) {
7356 return true;
7357 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007358 if (state.instantApp != p.applicationInfo.isInstantApp()) {
7359 return true;
7360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007361 if ((flags & PackageManager.GET_META_DATA) != 0
7362 && (metaData != null || p.mAppMetaData != null)) {
7363 return true;
7364 }
7365 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7366 && p.usesLibraryFiles != null) {
7367 return true;
7368 }
Svet Ganov67882122016-12-11 16:36:34 -08007369 if (p.staticSharedLibName != null) {
7370 return true;
7371 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007372 return false;
7373 }
7374
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007375 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
7376 PackageUserState state) {
7377 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07007378 }
7379
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007380 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
7381 PackageUserState state) {
7382 // CompatibilityMode is global state.
7383 if (!sCompatibilityModeEnabled) {
7384 ai.disableCompatibilityMode();
7385 }
7386 if (state.installed) {
7387 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
7388 } else {
7389 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
7390 }
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00007391 if (state.suspended) {
7392 ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
7393 } else {
7394 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
7395 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007396 if (state.instantApp) {
7397 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
7398 } else {
7399 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
7400 }
Todd Kennedy5eb5a7d2017-08-01 07:42:47 -07007401 if (state.virtualPreload) {
7402 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7403 } else {
7404 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7405 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007406 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007407 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007408 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007409 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007410 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007411 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
7412 ai.enabled = true;
7413 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
7414 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
7415 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
7416 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
7417 ai.enabled = false;
7418 }
7419 ai.enabledSetting = state.enabled;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07007420 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7421 ai.category = state.categoryHint;
7422 }
Jeff Sharkey0078e1b2017-01-11 16:05:27 -07007423 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7424 ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
7425 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007426 ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
Todd Kennedyb2749472017-06-13 08:24:32 -07007427 ai.resourceDirs = state.overlayPaths;
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007428 }
7429
Amith Yamasani13593602012-03-22 16:16:17 -07007430 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007431 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007432 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007433 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007434 return null;
7435 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007436 if (!copyNeeded(flags, p, state, null, userId)
7437 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
7438 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
7439 // In this case it is safe to directly modify the internal ApplicationInfo state:
7440 // - CompatibilityMode is global state, so will be the same for every call.
7441 // - We only come in to here if the app should reported as installed; this is the
7442 // default state, and we will do a copy otherwise.
7443 // - The enable state will always be reported the same for the application across
7444 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
7445 // be doing a copy.
7446 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007447 return p.applicationInfo;
7448 }
7449
7450 // Make shallow copy so we can store the metadata/libraries safely
7451 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Jeff Sharkey15447792015-11-05 16:18:51 -08007452 ai.initForUser(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007453 if ((flags & PackageManager.GET_META_DATA) != 0) {
7454 ai.metaData = p.mAppMetaData;
7455 }
7456 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
7457 ai.sharedLibraryFiles = p.usesLibraryFiles;
7458 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007459 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007460 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007461 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007462 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007463 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007464 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007465 return ai;
7466 }
7467
Dianne Hackbornace27912014-09-18 18:38:30 -07007468 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
7469 PackageUserState state, int userId) {
7470 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007471 if (!checkUseInstalledOrHidden(flags, state, ai)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007472 return null;
7473 }
7474 // This is only used to return the ResolverActivity; we will just always
7475 // make a copy.
7476 ai = new ApplicationInfo(ai);
Jeff Sharkey15447792015-11-05 16:18:51 -08007477 ai.initForUser(userId);
Dianne Hackbornace27912014-09-18 18:38:30 -07007478 if (state.stopped) {
7479 ai.flags |= ApplicationInfo.FLAG_STOPPED;
7480 } else {
7481 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
7482 }
7483 updateApplicationInfo(ai, flags, state);
7484 return ai;
7485 }
7486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007487 public static final PermissionInfo generatePermissionInfo(
7488 Permission p, int flags) {
7489 if (p == null) return null;
7490 if ((flags&PackageManager.GET_META_DATA) == 0) {
7491 return p.info;
7492 }
7493 PermissionInfo pi = new PermissionInfo(p.info);
7494 pi.metaData = p.metaData;
7495 return pi;
7496 }
7497
7498 public static final PermissionGroupInfo generatePermissionGroupInfo(
7499 PermissionGroup pg, int flags) {
7500 if (pg == null) return null;
7501 if ((flags&PackageManager.GET_META_DATA) == 0) {
7502 return pg.info;
7503 }
7504 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
7505 pgi.metaData = pg.metaData;
7506 return pgi;
7507 }
7508
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007509 public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007510 public final ActivityInfo info;
Bryce Lee22571db2017-07-07 15:54:18 -07007511 private boolean mHasMaxAspectRatio;
7512
7513 private boolean hasMaxAspectRatio() {
7514 return mHasMaxAspectRatio;
7515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007516
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007517 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
7518 super(args, _info);
7519 info = _info;
7520 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007521 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007522
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007523 public void setPackageName(String packageName) {
7524 super.setPackageName(packageName);
7525 info.packageName = packageName;
7526 }
7527
Bryce Lee22571db2017-07-07 15:54:18 -07007528
7529 private void setMaxAspectRatio(float maxAspectRatio) {
7530 if (info.resizeMode == RESIZE_MODE_RESIZEABLE
7531 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
7532 // Resizeable activities can be put in any aspect ratio.
7533 return;
7534 }
7535
7536 if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
7537 // Ignore any value lesser than 1.0.
7538 return;
7539 }
7540
7541 info.maxAspectRatio = maxAspectRatio;
7542 mHasMaxAspectRatio = true;
7543 }
7544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007545 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007546 StringBuilder sb = new StringBuilder(128);
7547 sb.append("Activity{");
7548 sb.append(Integer.toHexString(System.identityHashCode(this)));
7549 sb.append(' ');
7550 appendComponentShortName(sb);
7551 sb.append('}');
7552 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007553 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007554
7555 @Override
7556 public int describeContents() {
7557 return 0;
7558 }
7559
7560 @Override
7561 public void writeToParcel(Parcel dest, int flags) {
7562 super.writeToParcel(dest, flags);
7563 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
Bryce Lee22571db2017-07-07 15:54:18 -07007564 dest.writeBoolean(mHasMaxAspectRatio);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007565 }
7566
7567 private Activity(Parcel in) {
7568 super(in);
7569 info = in.readParcelable(Object.class.getClassLoader());
Bryce Lee22571db2017-07-07 15:54:18 -07007570 mHasMaxAspectRatio = in.readBoolean();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007571
7572 for (ActivityIntentInfo aii : intents) {
7573 aii.activity = this;
7574 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007575
7576 if (info.permission != null) {
7577 info.permission = info.permission.intern();
7578 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007579 }
7580
7581 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
7582 public Activity createFromParcel(Parcel in) {
7583 return new Activity(in);
7584 }
7585
7586 public Activity[] newArray(int size) {
7587 return new Activity[size];
7588 }
7589 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007590 }
7591
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007592 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
7593 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007594 if (a == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007595 if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007596 return null;
7597 }
7598 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007599 updateApplicationInfo(a.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007600 return a.info;
7601 }
7602 // Make shallow copies so we can store the metadata safely
7603 ActivityInfo ai = new ActivityInfo(a.info);
7604 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007605 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007606 return ai;
7607 }
7608
Dianne Hackbornace27912014-09-18 18:38:30 -07007609 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
7610 PackageUserState state, int userId) {
7611 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007612 if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007613 return null;
7614 }
7615 // This is only used to return the ResolverActivity; we will just always
7616 // make a copy.
7617 ai = new ActivityInfo(ai);
7618 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
7619 return ai;
7620 }
7621
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007622 public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007623 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007624
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007625 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
7626 super(args, _info);
7627 info = _info;
7628 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007629 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007630
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007631 public void setPackageName(String packageName) {
7632 super.setPackageName(packageName);
7633 info.packageName = packageName;
7634 }
7635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007636 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007637 StringBuilder sb = new StringBuilder(128);
7638 sb.append("Service{");
7639 sb.append(Integer.toHexString(System.identityHashCode(this)));
7640 sb.append(' ');
7641 appendComponentShortName(sb);
7642 sb.append('}');
7643 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007644 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007645
7646 @Override
7647 public int describeContents() {
7648 return 0;
7649 }
7650
7651 @Override
7652 public void writeToParcel(Parcel dest, int flags) {
7653 super.writeToParcel(dest, flags);
7654 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7655 }
7656
7657 private Service(Parcel in) {
7658 super(in);
7659 info = in.readParcelable(Object.class.getClassLoader());
7660
7661 for (ServiceIntentInfo aii : intents) {
7662 aii.service = this;
7663 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007664
7665 if (info.permission != null) {
7666 info.permission = info.permission.intern();
7667 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007668 }
7669
7670 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
7671 public Service createFromParcel(Parcel in) {
7672 return new Service(in);
7673 }
7674
7675 public Service[] newArray(int size) {
7676 return new Service[size];
7677 }
7678 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007679 }
7680
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007681 public static final ServiceInfo generateServiceInfo(Service s, int flags,
7682 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007683 if (s == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007684 if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007685 return null;
7686 }
7687 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007688 updateApplicationInfo(s.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007689 return s.info;
7690 }
7691 // Make shallow copies so we can store the metadata safely
7692 ServiceInfo si = new ServiceInfo(s.info);
7693 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007694 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007695 return si;
7696 }
7697
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007698 public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007699 public final ProviderInfo info;
7700 public boolean syncable;
7701
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007702 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
7703 super(args, _info);
7704 info = _info;
7705 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007706 syncable = false;
7707 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007709 public Provider(Provider existingProvider) {
7710 super(existingProvider);
7711 this.info = existingProvider.info;
7712 this.syncable = existingProvider.syncable;
7713 }
7714
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007715 public void setPackageName(String packageName) {
7716 super.setPackageName(packageName);
7717 info.packageName = packageName;
7718 }
7719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007720 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007721 StringBuilder sb = new StringBuilder(128);
7722 sb.append("Provider{");
7723 sb.append(Integer.toHexString(System.identityHashCode(this)));
7724 sb.append(' ');
7725 appendComponentShortName(sb);
7726 sb.append('}');
7727 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007728 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007729
7730 @Override
7731 public int describeContents() {
7732 return 0;
7733 }
7734
7735 @Override
7736 public void writeToParcel(Parcel dest, int flags) {
7737 super.writeToParcel(dest, flags);
7738 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7739 dest.writeInt((syncable) ? 1 : 0);
7740 }
7741
7742 private Provider(Parcel in) {
7743 super(in);
7744 info = in.readParcelable(Object.class.getClassLoader());
7745 syncable = (in.readInt() == 1);
7746
7747 for (ProviderIntentInfo aii : intents) {
7748 aii.provider = this;
7749 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007750
7751 if (info.readPermission != null) {
7752 info.readPermission = info.readPermission.intern();
7753 }
7754
7755 if (info.writePermission != null) {
7756 info.writePermission = info.writePermission.intern();
7757 }
7758
7759 if (info.authority != null) {
7760 info.authority = info.authority.intern();
7761 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007762 }
7763
7764 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
7765 public Provider createFromParcel(Parcel in) {
7766 return new Provider(in);
7767 }
7768
7769 public Provider[] newArray(int size) {
7770 return new Provider[size];
7771 }
7772 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007773 }
7774
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007775 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
7776 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007777 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007778 if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007779 return null;
7780 }
7781 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007782 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007783 || p.info.uriPermissionPatterns == null)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007784 updateApplicationInfo(p.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007785 return p.info;
7786 }
7787 // Make shallow copies so we can store the metadata safely
7788 ProviderInfo pi = new ProviderInfo(p.info);
7789 pi.metaData = p.metaData;
7790 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
7791 pi.uriPermissionPatterns = null;
7792 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007793 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007794 return pi;
7795 }
7796
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007797 public final static class Instrumentation extends Component<IntentInfo> implements
7798 Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007799 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007801 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
7802 super(args, _info);
7803 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007804 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007805
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007806 public void setPackageName(String packageName) {
7807 super.setPackageName(packageName);
7808 info.packageName = packageName;
7809 }
7810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007811 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007812 StringBuilder sb = new StringBuilder(128);
7813 sb.append("Instrumentation{");
7814 sb.append(Integer.toHexString(System.identityHashCode(this)));
7815 sb.append(' ');
7816 appendComponentShortName(sb);
7817 sb.append('}');
7818 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007819 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007820
7821 @Override
7822 public int describeContents() {
7823 return 0;
7824 }
7825
7826 @Override
7827 public void writeToParcel(Parcel dest, int flags) {
7828 super.writeToParcel(dest, flags);
7829 dest.writeParcelable(info, flags);
7830 }
7831
7832 private Instrumentation(Parcel in) {
7833 super(in);
7834 info = in.readParcelable(Object.class.getClassLoader());
Narayan Kamath07ac1442017-02-10 15:08:07 +00007835
7836 if (info.targetPackage != null) {
7837 info.targetPackage = info.targetPackage.intern();
7838 }
7839
Dianne Hackborn1be53542017-04-28 13:36:00 -07007840 if (info.targetProcesses != null) {
7841 info.targetProcesses = info.targetProcesses.intern();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007842 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007843 }
7844
7845 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
7846 public Instrumentation createFromParcel(Parcel in) {
7847 return new Instrumentation(in);
7848 }
7849
7850 public Instrumentation[] newArray(int size) {
7851 return new Instrumentation[size];
7852 }
7853 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007854 }
7855
7856 public static final InstrumentationInfo generateInstrumentationInfo(
7857 Instrumentation i, int flags) {
7858 if (i == null) return null;
7859 if ((flags&PackageManager.GET_META_DATA) == 0) {
7860 return i.info;
7861 }
7862 InstrumentationInfo ii = new InstrumentationInfo(i.info);
7863 ii.metaData = i.metaData;
7864 return ii;
7865 }
7866
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007867 public static abstract class IntentInfo extends IntentFilter {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007868 public boolean hasDefault;
7869 public int labelRes;
7870 public CharSequence nonLocalizedLabel;
7871 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07007872 public int logo;
Jose Limaf78e3122014-03-06 12:13:15 -08007873 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07007874 public int preferred;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007875
7876 protected IntentInfo() {
7877 }
7878
7879 protected IntentInfo(Parcel dest) {
7880 super(dest);
7881 hasDefault = (dest.readInt() == 1);
7882 labelRes = dest.readInt();
7883 nonLocalizedLabel = dest.readCharSequence();
7884 icon = dest.readInt();
7885 logo = dest.readInt();
7886 banner = dest.readInt();
7887 preferred = dest.readInt();
7888 }
7889
7890
7891 public void writeIntentInfoToParcel(Parcel dest, int flags) {
7892 super.writeToParcel(dest, flags);
7893 dest.writeInt(hasDefault ? 1 : 0);
7894 dest.writeInt(labelRes);
7895 dest.writeCharSequence(nonLocalizedLabel);
7896 dest.writeInt(icon);
7897 dest.writeInt(logo);
7898 dest.writeInt(banner);
7899 dest.writeInt(preferred);
7900 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007901 }
7902
7903 public final static class ActivityIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007904 public Activity activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007905
7906 public ActivityIntentInfo(Activity _activity) {
7907 activity = _activity;
7908 }
7909
7910 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007911 StringBuilder sb = new StringBuilder(128);
7912 sb.append("ActivityIntentInfo{");
7913 sb.append(Integer.toHexString(System.identityHashCode(this)));
7914 sb.append(' ');
7915 activity.appendComponentShortName(sb);
7916 sb.append('}');
7917 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007918 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007919
7920 public ActivityIntentInfo(Parcel in) {
7921 super(in);
7922 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007923 }
7924
7925 public final static class ServiceIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007926 public Service service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007927
7928 public ServiceIntentInfo(Service _service) {
7929 service = _service;
7930 }
7931
7932 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007933 StringBuilder sb = new StringBuilder(128);
7934 sb.append("ServiceIntentInfo{");
7935 sb.append(Integer.toHexString(System.identityHashCode(this)));
7936 sb.append(' ');
7937 service.appendComponentShortName(sb);
7938 sb.append('}');
7939 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007940 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007941
7942 public ServiceIntentInfo(Parcel in) {
7943 super(in);
7944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007945 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007946
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007947 public static final class ProviderIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007948 public Provider provider;
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007949
7950 public ProviderIntentInfo(Provider provider) {
7951 this.provider = provider;
7952 }
7953
7954 public String toString() {
7955 StringBuilder sb = new StringBuilder(128);
7956 sb.append("ProviderIntentInfo{");
7957 sb.append(Integer.toHexString(System.identityHashCode(this)));
7958 sb.append(' ');
7959 provider.appendComponentShortName(sb);
7960 sb.append('}');
7961 return sb.toString();
7962 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007963
7964 public ProviderIntentInfo(Parcel in) {
7965 super(in);
7966 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007967 }
7968
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007969 /**
7970 * @hide
7971 */
7972 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
7973 sCompatibilityModeEnabled = compatibilityModeEnabled;
7974 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07007975
7976 public static class PackageParserException extends Exception {
7977 public final int error;
7978
7979 public PackageParserException(int error, String detailMessage) {
7980 super(detailMessage);
7981 this.error = error;
7982 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07007983
7984 public PackageParserException(int error, String detailMessage, Throwable throwable) {
7985 super(detailMessage, throwable);
7986 this.error = error;
7987 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07007988 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007989}