blob: f15b5d75d61695476b63c95a2044acfe11d53ede [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;
Adrian Roos917791e2018-11-28 16:30:44 +010033import static android.content.pm.PackageManager.FEATURE_WATCH;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070034import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
35import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070036import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
37import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
38import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070039import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -070040import static android.os.Build.VERSION_CODES.O;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070041import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
Robert Carr427ba4f2017-07-17 18:37:06 -070042import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070043
Todd Kennedy232d29e2017-11-06 14:45:53 -080044import android.annotation.IntDef;
Alan Viverette82f4b263a2016-12-19 15:40:05 -050045import android.annotation.IntRange;
46import android.annotation.NonNull;
Fyodor Kupolov965fa692016-10-28 18:20:25 -070047import android.annotation.Nullable;
Philip P. Moltmann0635dab2019-03-02 11:19:03 -080048import android.annotation.StringRes;
Alan Viverette82f4b263a2016-12-19 15:40:05 -050049import android.annotation.TestApi;
Mathew Inwood5c0d3542018-08-14 13:54:31 +010050import android.annotation.UnsupportedAppUsage;
Gavin Corkeryef441722019-05-09 17:02:10 +010051import android.apex.ApexInfo;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070052import android.app.ActivityTaskManager;
Hyunyoung Song929de7a2019-03-21 23:51:27 -070053import android.app.ActivityThread;
54import android.app.ResourcesManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.Intent;
57import android.content.IntentFilter;
Makoto Onuki4501c61d2017-07-27 15:56:40 -070058import android.content.pm.PackageParserCacheHelper.ReadHelper;
59import android.content.pm.PackageParserCacheHelper.WriteHelper;
Garrett Boyer52136662017-05-23 13:47:58 -070060import android.content.pm.split.DefaultSplitAssetLoader;
Adam Lesinski4e862812016-11-21 16:02:24 -080061import android.content.pm.split.SplitAssetDependencyLoader;
62import android.content.pm.split.SplitAssetLoader;
Adam Lesinskibebfcc42018-02-12 14:27:46 -080063import android.content.res.ApkAssets;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.content.res.AssetManager;
65import android.content.res.Configuration;
66import android.content.res.Resources;
67import android.content.res.TypedArray;
68import android.content.res.XmlResourceParser;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070069import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.os.Bundle;
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -070071import android.os.FileUtils;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070072import android.os.Parcel;
73import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074import android.os.PatternMatcher;
Hyunyoung Song929de7a2019-03-21 23:51:27 -070075import android.os.RemoteException;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -070076import android.os.SystemClock;
Todd Leeea2f3be2017-03-16 14:00:52 -070077import android.os.SystemProperties;
Todd Kennedy27c24fb2015-09-17 16:49:25 -070078import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070079import android.os.UserHandle;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -060080import android.os.storage.StorageManager;
Philip P. Moltmann039678e2018-09-18 13:04:38 -070081import android.permission.PermissionManager;
Narayan Kamath988149c2016-12-01 13:32:59 +000082import android.system.ErrnoException;
83import android.system.OsConstants;
84import android.system.StructStat;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -070085import android.text.TextUtils;
Jeff Sharkey275e0852014-06-17 18:18:49 -070086import android.util.ArrayMap;
87import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088import android.util.AttributeSet;
Kenny Root05ca4c92011-09-15 10:36:25 -070089import android.util.Base64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070091import android.util.Log;
Dan Cashman1dbe6d02018-01-23 11:18:28 -080092import android.util.PackageUtils;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070093import android.util.Pair;
Kenny Rootd2d29252011-08-08 11:27:57 -070094import android.util.Slog;
Adam Lesinski1665d0f2017-03-10 14:46:57 -080095import android.util.SparseArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.util.TypedValue;
Dan Cashmane92f8422017-12-08 14:02:51 -080097import android.util.apk.ApkSignatureVerifier;
Hyunyoung Song929de7a2019-03-21 23:51:27 -070098import android.view.Display;
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -070099import android.view.Gravity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100
Jeff Sharkey9bc89af2017-01-11 11:25:50 -0700101import com.android.internal.R;
102import com.android.internal.annotations.VisibleForTesting;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100103import com.android.internal.os.ClassLoaderFactory;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -0700104import com.android.internal.util.ArrayUtils;
105import com.android.internal.util.XmlUtils;
106
107import libcore.io.IoUtils;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -0700108import libcore.util.EmptyArray;
Neil Fuller2c7cc6e2019-04-11 11:04:06 +0100109import libcore.util.HexEncoding;
Svet Ganov087dce22017-09-07 15:42:16 -0700110
Jeff Sharkey9bc89af2017-01-11 11:25:50 -0700111import org.xmlpull.v1.XmlPullParser;
112import org.xmlpull.v1.XmlPullParserException;
113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import java.io.File;
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700115import java.io.FileDescriptor;
Narayan Kamath988149c2016-12-01 13:32:59 +0000116import java.io.FileOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import java.io.IOException;
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -0700118import java.io.PrintWriter;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800119import java.lang.annotation.Retention;
120import java.lang.annotation.RetentionPolicy;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000121import java.lang.reflect.Constructor;
Kenny Root05ca4c92011-09-15 10:36:25 -0700122import java.security.KeyFactory;
123import java.security.NoSuchAlgorithmException;
124import java.security.PublicKey;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800125import java.security.cert.CertificateException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700126import java.security.spec.EncodedKeySpec;
127import java.security.spec.InvalidKeySpecException;
128import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129import java.util.ArrayList;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700130import java.util.Arrays;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700131import java.util.Collections;
132import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -0700134import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800135import java.util.Set;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -0600136import java.util.UUID;
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700137import java.util.concurrent.atomic.AtomicInteger;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138
139/**
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700140 * Parser for package files (APKs) on disk. This supports apps packaged either
141 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
142 * APKs in a single directory.
143 * <p>
144 * Apps packaged as multiple APKs always consist of a single "base" APK (with a
145 * {@code null} split name) and zero or more "split" APKs (with unique split
146 * names). Any subset of those split APKs are a valid install, as long as the
147 * following constraints are met:
148 * <ul>
149 * <li>All APKs must have the exact same package name, version code, and signing
150 * certificates.
151 * <li>All APKs must have unique split names.
152 * <li>All installations must contain a single base APK.
153 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700155 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 */
157public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -0700158 private static final boolean DEBUG_JAR = false;
159 private static final boolean DEBUG_PARSER = false;
160 private static final boolean DEBUG_BACKUP = false;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -0700161 private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE;
162 private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100;
Kenny Rootd2d29252011-08-08 11:27:57 -0700163
Svet Ganova3c4eb32017-04-19 23:51:33 -0700164 private static final String PROPERTY_CHILD_PACKAGES_ENABLED =
165 "persist.sys.child_packages_enabled";
166
Jeff Sharkey3f1790d2017-04-25 18:56:17 -0600167 private static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE &&
Garrett Boyer17041532017-08-01 14:11:02 -0700168 SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false);
Svet Ganova3c4eb32017-04-19 23:51:33 -0700169
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700170 private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
Adrian Roos917791e2018-11-28 16:30:44 +0100171 private static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO = 1.333f;
172 private static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH = 1f;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700173
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +0000174 private static final int DEFAULT_MIN_SDK_VERSION = 1;
175 private static final int DEFAULT_TARGET_SDK_VERSION = 0;
176
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700177 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700178 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700179
Kenny Rootbcc954d2011-08-08 16:19:08 -0700180 /** File name in an APK for the Android manifest. */
Dan Cashmane92f8422017-12-08 14:02:51 -0800181 public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
Kenny Rootbcc954d2011-08-08 16:19:08 -0700182
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700183 /** Path prefix for apps on expanded storage */
184 private static final String MNT_EXPAND = "/mnt/expand/";
185
Svet Ganov354cd3c2015-12-17 11:35:04 -0800186 private static final String TAG_MANIFEST = "manifest";
187 private static final String TAG_APPLICATION = "application";
Adam Lesinski4e862812016-11-21 16:02:24 -0800188 private static final String TAG_PACKAGE_VERIFIER = "package-verifier";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800189 private static final String TAG_OVERLAY = "overlay";
190 private static final String TAG_KEY_SETS = "key-sets";
191 private static final String TAG_PERMISSION_GROUP = "permission-group";
192 private static final String TAG_PERMISSION = "permission";
193 private static final String TAG_PERMISSION_TREE = "permission-tree";
194 private static final String TAG_USES_PERMISSION = "uses-permission";
195 private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
196 private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
197 private static final String TAG_USES_CONFIGURATION = "uses-configuration";
198 private static final String TAG_USES_FEATURE = "uses-feature";
199 private static final String TAG_FEATURE_GROUP = "feature-group";
200 private static final String TAG_USES_SDK = "uses-sdk";
201 private static final String TAG_SUPPORT_SCREENS = "supports-screens";
202 private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
203 private static final String TAG_INSTRUMENTATION = "instrumentation";
204 private static final String TAG_ORIGINAL_PACKAGE = "original-package";
205 private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
206 private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
207 private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
208 private static final String TAG_SUPPORTS_INPUT = "supports-input";
209 private static final String TAG_EAT_COMMENT = "eat-comment";
210 private static final String TAG_PACKAGE = "package";
Todd Kennedyfdd241a2016-04-28 12:26:53 -0700211 private static final String TAG_RESTRICT_UPDATE = "restrict-update";
Adam Lesinski4e862812016-11-21 16:02:24 -0800212 private static final String TAG_USES_SPLIT = "uses-split";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800213
Bryce Lee22571db2017-07-07 15:54:18 -0700214 private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
215
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800216 /**
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700217 * Bit mask of all the valid bits that can be set in recreateOnConfigChanges.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800218 * @hide
219 */
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700220 private static final int RECREATE_ON_CONFIG_CHANGES_MASK =
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800221 ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
222
Svet Ganov354cd3c2015-12-17 11:35:04 -0800223 // These are the tags supported by child packages
224 private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
225 static {
226 CHILD_PACKAGE_TAGS.add(TAG_APPLICATION);
227 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION);
228 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M);
229 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23);
230 CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
231 CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
232 CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
233 CHILD_PACKAGE_TAGS.add(TAG_USES_SDK);
234 CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
235 CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
236 CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE);
237 CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS);
238 CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
239 CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
240 }
241
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700242 private static final boolean LOG_UNSAFE_BROADCASTS = false;
243
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700244 /**
245 * Total number of packages that were read from the cache. We use it only for logging.
246 */
247 public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger();
248
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700249 // Set of broadcast actions that are safe for manifest receivers
250 private static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
251 static {
252 SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
253 }
254
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700255 /** @hide */
Calin Juravle3fc56c32017-12-11 18:26:13 -0800256 public static final String APK_FILE_EXTENSION = ".apk";
257
258 /** @hide */
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700259 public static class NewPermissionInfo {
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100260 @UnsupportedAppUsage
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700261 public final String name;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100262 @UnsupportedAppUsage
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700263 public final int sdkVersion;
264 public final int fileVersion;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700265
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700266 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
267 this.name = name;
268 this.sdkVersion = sdkVersion;
269 this.fileVersion = fileVersion;
270 }
271 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700272
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700273 /**
274 * List of new permissions that have been added since 1.0.
275 * NOTE: These must be declared in SDK version order, with permissions
276 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700277 * If sdkVersion is 0, then this is not a permission that we want to
278 * automatically add to older apps, but we do want to allow it to be
279 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700280 * @hide
281 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100282 @UnsupportedAppUsage
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700283 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
284 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700285 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700286 android.os.Build.VERSION_CODES.DONUT, 0),
287 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
288 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700289 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
Dianne Hackborn79245122012-03-12 10:51:26 -0700291 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700292 * @deprecated callers should move to explicitly passing around source path.
293 */
294 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700298 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700299 private DisplayMetrics mMetrics;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100300 @UnsupportedAppUsage
Dianne Hackborncd154e92017-02-28 17:37:35 -0800301 private Callback mCallback;
Narayan Kamath988149c2016-12-01 13:32:59 +0000302 private File mCacheDir;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700303
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700304 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700305 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306
307 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
308
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700309 private static boolean sCompatibilityModeEnabled = true;
Hyunyoung Song929de7a2019-03-21 23:51:27 -0700310 private static boolean sUseRoundIcon = false;
311
Amith Yamasani655d0e22013-06-12 14:19:10 -0700312 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
313 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Todd Kennedy11e45072017-01-25 13:24:21 -0800314 private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700315
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700316 static class ParsePackageItemArgs {
317 final Package owner;
318 final String[] outError;
319 final int nameRes;
320 final int labelRes;
321 final int iconRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700322 final int roundIconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700323 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800324 final int bannerRes;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700325
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700326 String tag;
327 TypedArray sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700328
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700329 ParsePackageItemArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700330 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
331 int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700332 owner = _owner;
333 outError = _outError;
334 nameRes = _nameRes;
335 labelRes = _labelRes;
336 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700337 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800338 bannerRes = _bannerRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700339 roundIconRes = _roundIconRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700340 }
341 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700342
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000343 /** @hide */
344 @VisibleForTesting
345 public static class ParseComponentArgs extends ParsePackageItemArgs {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700346 final String[] sepProcesses;
347 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800348 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700349 final int enabledRes;
350 int flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700351
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000352 public ParseComponentArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700353 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
354 int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800355 String[] _sepProcesses, int _processRes,
356 int _descriptionRes, int _enabledRes) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700357 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes,
358 _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700359 sepProcesses = _sepProcesses;
360 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800361 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700362 enabledRes = _enabledRes;
363 }
364 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800365
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700366 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700367 * Lightweight parsed details about a single package.
368 */
369 public static class PackageLite {
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100370 @UnsupportedAppUsage
Jeff Sharkey73767b92014-07-04 20:18:13 -0700371 public final String packageName;
372 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700373 public final int versionCodeMajor;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100374 @UnsupportedAppUsage
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700375 public final int installLocation;
376 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700377
378 /** Names of any split APKs, ordered by parsed splitName */
379 public final String[] splitNames;
380
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800381 /** Names of any split APKs that are features. Ordered by splitName */
382 public final boolean[] isFeatureSplits;
383
Adam Lesinski4e862812016-11-21 16:02:24 -0800384 /** Dependencies of any split APKs, ordered by parsed splitName */
385 public final String[] usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800386 public final String[] configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800387
Jeff Sharkey73767b92014-07-04 20:18:13 -0700388 /**
389 * Path where this package was found on disk. For monolithic packages
390 * this is path to single base APK file; for cluster packages this is
391 * path to the cluster directory.
392 */
393 public final String codePath;
394
395 /** Path of base APK */
396 public final String baseCodePath;
397 /** Paths of any split APKs, ordered by parsed splitName */
398 public final String[] splitCodePaths;
399
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800400 /** Revision code of base APK */
401 public final int baseRevisionCode;
402 /** Revision codes of any split APKs, ordered by parsed splitName */
403 public final int[] splitRevisionCodes;
404
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700405 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100406 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100407 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800408 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700409 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800410 public final boolean isolatedSplits;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100411
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700412 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800413 boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100414 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700415 this.packageName = baseApk.packageName;
416 this.versionCode = baseApk.versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700417 this.versionCodeMajor = baseApk.versionCodeMajor;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700418 this.installLocation = baseApk.installLocation;
419 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700420 this.splitNames = splitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800421 this.isFeatureSplits = isFeatureSplits;
Adam Lesinski4e862812016-11-21 16:02:24 -0800422 this.usesSplitNames = usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800423 this.configForSplit = configForSplit;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700424 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700425 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700426 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800427 this.baseRevisionCode = baseApk.revisionCode;
428 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700429 this.coreApp = baseApk.coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100430 this.debuggable = baseApk.debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100431 this.multiArch = baseApk.multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800432 this.use32bitAbi = baseApk.use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700433 this.extractNativeLibs = baseApk.extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800434 this.isolatedSplits = baseApk.isolatedSplits;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700435 }
436
437 public List<String> getAllCodePaths() {
438 ArrayList<String> paths = new ArrayList<>();
439 paths.add(baseCodePath);
440 if (!ArrayUtils.isEmpty(splitCodePaths)) {
441 Collections.addAll(paths, splitCodePaths);
442 }
443 return paths;
444 }
445 }
446
447 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700448 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800449 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700450 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700451 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700452 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700453 public final String splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800454 public boolean isFeatureSplit;
455 public final String configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800456 public final String usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700457 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700458 public final int versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800459 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700460 public final int installLocation;
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +0000461 public final int minSdkVersion;
462 public final int targetSdkVersion;
Kenny Root05ca4c92011-09-15 10:36:25 -0700463 public final VerifierInfo[] verifiers;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800464 public final SigningDetails signingDetails;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700465 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100466 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100467 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800468 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700469 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800470 public final boolean isolatedSplits;
Todd Kennedy29cfa272018-09-26 10:25:24 -0700471 public final boolean isSplitRequired;
Victor Hsiehfa9df0b2019-01-29 12:48:36 -0800472 public final boolean useEmbeddedDex;
Kenny Root05ca4c92011-09-15 10:36:25 -0700473
Patrick Baumann47117fc2017-12-19 10:17:21 -0800474 public ApkLite(String codePath, String packageName, String splitName,
475 boolean isFeatureSplit,
Todd Kennedy29cfa272018-09-26 10:25:24 -0700476 String configForSplit, String usesSplitName, boolean isSplitRequired,
477 int versionCode, int versionCodeMajor,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700478 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Patrick Baumann47117fc2017-12-19 10:17:21 -0800479 SigningDetails signingDetails, boolean coreApp,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700480 boolean debuggable, boolean multiArch, boolean use32bitAbi,
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +0000481 boolean useEmbeddedDex, boolean extractNativeLibs, boolean isolatedSplits,
482 int minSdkVersion, int targetSdkVersion) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700483 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800484 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700485 this.splitName = splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800486 this.isFeatureSplit = isFeatureSplit;
487 this.configForSplit = configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800488 this.usesSplitName = usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700489 this.versionCode = versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700490 this.versionCodeMajor = versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800491 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800492 this.installLocation = installLocation;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800493 this.signingDetails = signingDetails;
Kenny Root05ca4c92011-09-15 10:36:25 -0700494 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700495 this.coreApp = coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100496 this.debuggable = debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100497 this.multiArch = multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800498 this.use32bitAbi = use32bitAbi;
Victor Hsiehfa9df0b2019-01-29 12:48:36 -0800499 this.useEmbeddedDex = useEmbeddedDex;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700500 this.extractNativeLibs = extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800501 this.isolatedSplits = isolatedSplits;
Todd Kennedy29cfa272018-09-26 10:25:24 -0700502 this.isSplitRequired = isSplitRequired;
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +0000503 this.minSdkVersion = minSdkVersion;
504 this.targetSdkVersion = targetSdkVersion;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800505 }
Dianne Hackborn3accca02013-09-20 09:32:11 -0700506
507 public long getLongVersionCode() {
508 return PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode);
509 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800510 }
511
Garrett Boyer52136662017-05-23 13:47:58 -0700512 /**
513 * Cached parse state for new components.
514 *
515 * Allows reuse of the same parse argument records to avoid GC pressure. Lifetime is carefully
516 * scoped to the parsing of a single application element.
517 */
518 private static class CachedComponentArgs {
519 ParseComponentArgs mActivityArgs;
520 ParseComponentArgs mActivityAliasArgs;
521 ParseComponentArgs mServiceArgs;
522 ParseComponentArgs mProviderArgs;
523 }
524
525 /**
526 * Cached state for parsing instrumentation to avoid GC pressure.
527 *
528 * Must be manually reset to null for each new manifest.
529 */
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700530 private ParsePackageItemArgs mParseInstrumentationArgs;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 /** If set to true, we will only allow package files that exactly match
533 * the DTD. Otherwise, we try to get as much from the package as we
534 * can without failing. This should normally be set to false, to
535 * support extensions to the DTD in future versions. */
536 private static final boolean RIGID_PARSER = false;
537
538 private static final String TAG = "PackageParser";
539
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100540 @UnsupportedAppUsage
Jeff Sharkey275e0852014-06-17 18:18:49 -0700541 public PackageParser() {
542 mMetrics = new DisplayMetrics();
543 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700544 }
545
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100546 @UnsupportedAppUsage
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);
Jack He61034792019-04-10 23:01:45 +0000577 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 }
Jack He61034792019-04-10 23:01:45 +0000595
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 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100626 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800627 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800628 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svet Ganov3695b8a2015-03-24 16:30:25 -0700629 Set<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630
Amith Yamasani483f3b02012-03-13 16:08:00 -0700631 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700632 grantedPermissions, state, UserHandle.getCallingUserId());
633 }
634
Amith Yamasani655d0e22013-06-12 14:19:10 -0700635 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700636 * Returns true if the package is installed and not hidden, or if the caller
637 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700638 * @param appInfo The applicationInfo of the app being checked.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700639 */
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700640 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
641 ApplicationInfo appInfo) {
Rhed Jaocd47c262018-06-13 11:16:16 +0800642 // Returns false if the package is hidden system app until installed.
643 if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
644 && !state.installed
645 && appInfo != null && appInfo.hiddenUntilInstalled) {
646 return false;
647 }
648
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700649 // If available for the target user, or trying to match uninstalled packages and it's
650 // a system app.
651 return state.isAvailable(flags)
652 || (appInfo != null && appInfo.isSystemApp()
Rhed Jaocd47c262018-06-13 11:16:16 +0800653 && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
654 || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
Amith Yamasani483f3b02012-03-13 16:08:00 -0700655 }
656
Christopher Tateba629da2013-11-13 17:42:28 -0800657 public static boolean isAvailable(PackageUserState state) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700658 return checkUseInstalledOrHidden(0, state, null);
Christopher Tateba629da2013-11-13 17:42:28 -0800659 }
660
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100661 @UnsupportedAppUsage
Amith Yamasani13593602012-03-22 16:16:17 -0700662 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700663 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800664 Set<String> grantedPermissions, PackageUserState state, int userId) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700665 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700666 return null;
667 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 PackageInfo pi = new PackageInfo();
669 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700670 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671 pi.versionCode = p.mVersionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700672 pi.versionCodeMajor = p.mVersionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800673 pi.baseRevisionCode = p.baseRevisionCode;
674 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675 pi.versionName = p.mVersionName;
676 pi.sharedUserId = p.mSharedUserId;
677 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700678 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800679 pi.installLocation = p.installLocation;
Todd Kennedy7c8addf2017-06-27 14:13:55 -0700680 pi.isStub = p.isStub;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700681 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700682 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
683 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
684 pi.requiredForAllUsers = p.mRequiredForAllUsers;
685 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700686 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700687 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100688 pi.overlayTarget = p.mOverlayTarget;
Ryan Mitchelld57fb1f2019-03-20 17:18:58 -0700689 pi.targetOverlayableName = p.mOverlayTargetName;
Adrian Roosc84df772018-01-19 21:20:22 +0100690 pi.overlayCategory = p.mOverlayCategory;
Jaekyun Seok42d53f62017-04-10 13:48:58 +0900691 pi.overlayPriority = p.mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -0800692 pi.mOverlayIsStatic = p.mOverlayIsStatic;
Alan Viveretteb6a25732017-11-21 14:49:24 -0500693 pi.compileSdkVersion = p.mCompileSdkVersion;
694 pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700695 pi.firstInstallTime = firstInstallTime;
696 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 if ((flags&PackageManager.GET_GIDS) != 0) {
698 pi.gids = gids;
699 }
700 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700701 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 if (N > 0) {
703 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700704 p.configPreferences.toArray(pi.configPreferences);
705 }
706 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
707 if (N > 0) {
708 pi.reqFeatures = new FeatureInfo[N];
709 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700711 N = p.featureGroups != null ? p.featureGroups.size() : 0;
712 if (N > 0) {
713 pi.featureGroups = new FeatureGroupInfo[N];
714 p.featureGroups.toArray(pi.featureGroups);
715 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700717 if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
718 final int N = p.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700720 int num = 0;
721 final ActivityInfo[] res = new ActivityInfo[N];
722 for (int i = 0; i < N; i++) {
723 final Activity a = p.activities.get(i);
724 if (state.isMatch(a.info, flags)) {
Ricky Wai905908f2019-01-29 15:19:52 +0000725 if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(a.className)) {
726 continue;
727 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700728 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.activities = 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_RECEIVERS) != 0) {
735 final int N = p.receivers.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 ActivityInfo[] res = new ActivityInfo[N];
739 for (int i = 0; i < N; i++) {
740 final Activity a = p.receivers.get(i);
741 if (state.isMatch(a.info, flags)) {
742 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 }
744 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700745 pi.receivers = 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_SERVICES) != 0) {
749 final int N = p.services.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 ServiceInfo[] res = new ServiceInfo[N];
753 for (int i = 0; i < N; i++) {
754 final Service s = p.services.get(i);
755 if (state.isMatch(s.info, flags)) {
756 res[num++] = generateServiceInfo(s, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800757 }
758 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700759 pi.services = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 }
761 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700762 if ((flags & PackageManager.GET_PROVIDERS) != 0) {
763 final int N = p.providers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800764 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700765 int num = 0;
766 final ProviderInfo[] res = new ProviderInfo[N];
767 for (int i = 0; i < N; i++) {
768 final Provider pr = p.providers.get(i);
769 if (state.isMatch(pr.info, flags)) {
770 res[num++] = generateProviderInfo(pr, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800771 }
772 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700773 pi.providers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 }
775 }
776 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
777 int N = p.instrumentation.size();
778 if (N > 0) {
779 pi.instrumentation = new InstrumentationInfo[N];
780 for (int i=0; i<N; i++) {
781 pi.instrumentation[i] = generateInstrumentationInfo(
782 p.instrumentation.get(i), flags);
783 }
784 }
785 }
786 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
787 int N = p.permissions.size();
788 if (N > 0) {
789 pi.permissions = new PermissionInfo[N];
790 for (int i=0; i<N; i++) {
791 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
792 }
793 }
Chad Brubakere2107312019-02-04 12:30:01 -0800794 N = p.requestedPermissions.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795 if (N > 0) {
796 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800797 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 for (int i=0; i<N; i++) {
Chad Brubakere2107312019-02-04 12:30:01 -0800799 final String perm = p.requestedPermissions.get(i);
Dianne Hackborne639da72012-02-21 15:11:13 -0800800 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700801 // The notion of required permissions is deprecated but for compatibility.
Chad Brubakere2107312019-02-04 12:30:01 -0800802 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800803 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
Chad Brubakere2107312019-02-04 12:30:01 -0800804 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 }
807 }
808 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800809 // deprecated method of getting signing certificates
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800810 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Daniel Cashman5cdda342018-01-19 07:22:52 -0800811 if (p.mSigningDetails.hasPastSigningCertificates()) {
812 // Package has included signing certificate rotation information. Return the oldest
813 // cert so that programmatic checks keep working even if unaware of key rotation.
814 pi.signatures = new Signature[1];
815 pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0];
816 } else if (p.mSigningDetails.hasSignatures()) {
817 // otherwise keep old behavior
Patrick Baumann47117fc2017-12-19 10:17:21 -0800818 int numberOfSigs = p.mSigningDetails.signatures.length;
819 pi.signatures = new Signature[numberOfSigs];
820 System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800821 }
822 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800823
824 // replacement for GET_SIGNATURES
825 if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
Dan Cashman5c9f527e2018-04-03 16:42:23 -0700826 if (p.mSigningDetails != SigningDetails.UNKNOWN) {
827 // only return a valid SigningInfo if there is signing information to report
828 pi.signingInfo = new SigningInfo(p.mSigningDetails);
829 } else {
830 pi.signingInfo = null;
Daniel Cashman5cdda342018-01-19 07:22:52 -0800831 }
832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833 return pi;
834 }
835
Todd Kennedy232d29e2017-11-06 14:45:53 -0800836 public static final int PARSE_MUST_BE_APK = 1 << 0;
837 public static final int PARSE_IGNORE_PROCESSES = 1 << 1;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800838 public static final int PARSE_EXTERNAL_STORAGE = 1 << 3;
839 public static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
840 public static final int PARSE_COLLECT_CERTIFICATES = 1 << 5;
841 public static final int PARSE_ENFORCE_CODE = 1 << 6;
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,
Todd Kennedy232d29e2017-11-06 14:45:53 -0800849 PARSE_IGNORE_PROCESSES,
Todd Kennedy232d29e2017-11-06 14:45:53 -0800850 PARSE_IS_SYSTEM_DIR,
851 PARSE_MUST_BE_APK,
852 })
853 @Retention(RetentionPolicy.SOURCE)
854 public @interface ParseFlags {}
Jeff Sharkey275e0852014-06-17 18:18:49 -0700855
856 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800857
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700858 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700859 * Used to sort a set of APKs based on their split names, always placing the
860 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700861 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700862 private static class SplitNameComparator implements Comparator<String> {
863 @Override
864 public int compare(String lhs, String rhs) {
865 if (lhs == null) {
866 return -1;
867 } else if (rhs == null) {
868 return 1;
869 } else {
870 return lhs.compareTo(rhs);
871 }
872 }
873 }
874
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700875 /**
876 * Parse only lightweight details about the package at the given location.
877 * Automatically detects if the package is a monolithic style (single APK
878 * file) or cluster style (directory of APKs).
879 * <p>
880 * This performs sanity checking on cluster style packages, such as
881 * requiring identical package name and version codes, a single base APK,
882 * and unique split names.
883 *
884 * @see PackageParser#parsePackage(File, int)
885 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100886 @UnsupportedAppUsage
Jeff Sharkey73767b92014-07-04 20:18:13 -0700887 public static PackageLite parsePackageLite(File packageFile, int flags)
888 throws PackageParserException {
889 if (packageFile.isDirectory()) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800890 return parseClusterPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700891 } else {
Adam Lesinski4e862812016-11-21 16:02:24 -0800892 return parseMonolithicPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700893 }
894 }
895
Adam Lesinski4e862812016-11-21 16:02:24 -0800896 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
897 throws PackageParserException {
Todd Kennedycd029da2016-07-21 07:41:09 -0700898 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Adam Lesinski4e862812016-11-21 16:02:24 -0800899 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700900 final String packagePath = packageFile.getAbsolutePath();
Todd Kennedycd029da2016-07-21 07:41:09 -0700901 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Narayan Kamath96c11c52017-08-09 13:07:21 +0100902 return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700903 }
904
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800905 static PackageLite parseClusterPackageLite(File packageDir, int flags)
Adam Lesinski4e862812016-11-21 16:02:24 -0800906 throws PackageParserException {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700907 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700908 if (ArrayUtils.isEmpty(files)) {
909 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
910 "No packages found in split");
911 }
912
Jeff Sharkey275e0852014-06-17 18:18:49 -0700913 String packageName = null;
914 int versionCode = 0;
915
Todd Kennedycd029da2016-07-21 07:41:09 -0700916 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700917 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700918 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700919 if (isApkFile(file)) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800920 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700921
922 // Assert that all package names and version codes are
923 // consistent with the first one we encounter.
924 if (packageName == null) {
925 packageName = lite.packageName;
926 versionCode = lite.versionCode;
927 } else {
928 if (!packageName.equals(lite.packageName)) {
929 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
930 "Inconsistent package " + lite.packageName + " in " + file
931 + "; expected " + packageName);
932 }
933 if (versionCode != lite.versionCode) {
934 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
935 "Inconsistent version " + lite.versionCode + " in " + file
936 + "; expected " + versionCode);
937 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700938 }
939
Jeff Sharkey275e0852014-06-17 18:18:49 -0700940 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700941 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700942 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
943 "Split name " + lite.splitName
944 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700945 }
946 }
947 }
Todd Kennedycd029da2016-07-21 07:41:09 -0700948 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700949
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700950 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700951 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700952 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700953 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700954 }
955
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700956 // Always apply deterministic ordering based on splitName
957 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700958
Jeff Sharkey73767b92014-07-04 20:18:13 -0700959 String[] splitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800960 boolean[] isFeatureSplits = null;
Adam Lesinski4e862812016-11-21 16:02:24 -0800961 String[] usesSplitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800962 String[] configForSplits = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700963 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800964 int[] splitRevisionCodes = null;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100965 String[] splitClassLoaderNames = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700966 if (size > 0) {
967 splitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800968 isFeatureSplits = new boolean[size];
Adam Lesinski4e862812016-11-21 16:02:24 -0800969 usesSplitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800970 configForSplits = new String[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700971 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800972 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700973
974 splitNames = apks.keySet().toArray(splitNames);
975 Arrays.sort(splitNames, sSplitNameComparator);
976
977 for (int i = 0; i < size; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800978 final ApkLite apk = apks.get(splitNames[i]);
979 usesSplitNames[i] = apk.usesSplitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800980 isFeatureSplits[i] = apk.isFeatureSplit;
981 configForSplits[i] = apk.configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800982 splitCodePaths[i] = apk.codePath;
983 splitRevisionCodes[i] = apk.revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700984 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700985 }
986
Jeff Sharkey73767b92014-07-04 20:18:13 -0700987 final String codePath = packageDir.getAbsolutePath();
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800988 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100989 configForSplits, splitCodePaths, splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700990 }
991
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700992 /**
993 * Parse the package at the given location. Automatically detects if the
994 * package is a monolithic style (single APK file) or cluster style
995 * (directory of APKs).
996 * <p>
997 * This performs sanity checking on cluster style packages, such as
998 * requiring identical package name and version codes, a single base APK,
999 * and unique split names.
1000 * <p>
1001 * Note that this <em>does not</em> perform signature verification; that
1002 * must be done separately in {@link #collectCertificates(Package, int)}.
1003 *
Narayan Kamath988149c2016-12-01 13:32:59 +00001004 * If {@code useCaches} is true, the package parser might return a cached
1005 * result from a previous parse of the same {@code packageFile} with the same
1006 * {@code flags}. Note that this method does not check whether {@code packageFile}
1007 * has changed since the last parse, it's up to callers to do so.
1008 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001009 * @see #parsePackageLite(File, int)
1010 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001011 @UnsupportedAppUsage
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 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001042 @UnsupportedAppUsage
Narayan Kamath988149c2016-12-01 13:32:59 +00001043 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
1044 return parsePackage(packageFile, flags, false /* useCaches */);
1045 }
1046
1047 /**
1048 * Returns the cache key for a specificied {@code packageFile} and {@code flags}.
1049 */
1050 private String getCacheKey(File packageFile, int flags) {
1051 StringBuilder sb = new StringBuilder(packageFile.getName());
1052 sb.append('-');
1053 sb.append(flags);
1054
1055 return sb.toString();
1056 }
1057
1058 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001059 protected Package fromCacheEntry(byte[] bytes) {
1060 return fromCacheEntryStatic(bytes);
1061 }
1062
1063 /** static version of {@link #fromCacheEntry} for unit tests. */
1064 @VisibleForTesting
1065 public static Package fromCacheEntryStatic(byte[] bytes) {
1066 final Parcel p = Parcel.obtain();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001067 p.unmarshall(bytes, 0, bytes.length);
1068 p.setDataPosition(0);
1069
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001070 final ReadHelper helper = new ReadHelper(p);
1071 helper.startAndInstall();
1072
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001073 PackageParser.Package pkg = new PackageParser.Package(p);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001074
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001075 p.recycle();
1076
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001077 sCachedPackageReadCount.incrementAndGet();
1078
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001079 return pkg;
Narayan Kamath988149c2016-12-01 13:32:59 +00001080 }
1081
1082 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001083 protected byte[] toCacheEntry(Package pkg) {
1084 return toCacheEntryStatic(pkg);
1085
1086 }
1087
1088 /** static version of {@link #toCacheEntry} for unit tests. */
1089 @VisibleForTesting
1090 public static byte[] toCacheEntryStatic(Package pkg) {
1091 final Parcel p = Parcel.obtain();
1092 final WriteHelper helper = new WriteHelper(p);
1093
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001094 pkg.writeToParcel(p, 0 /* flags */);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001095
1096 helper.finishAndUninstall();
1097
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001098 byte[] serialized = p.marshall();
1099 p.recycle();
1100
1101 return serialized;
Narayan Kamath988149c2016-12-01 13:32:59 +00001102 }
1103
1104 /**
1105 * Given a {@code packageFile} and a {@code cacheFile} returns whether the
1106 * cache file is up to date based on the mod-time of both files.
1107 */
1108 private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
1109 try {
1110 // NOTE: We don't use the File.lastModified API because it has the very
1111 // non-ideal failure mode of returning 0 with no excepions thrown.
1112 // The nio2 Files API is a little better but is considerably more expensive.
1113 final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
1114 final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
1115 return pkg.st_mtime < cache.st_mtime;
1116 } catch (ErrnoException ee) {
1117 // The most common reason why stat fails is that a given cache file doesn't
1118 // exist. We ignore that here. It's easy to reason that it's safe to say the
1119 // cache isn't up to date if we see any sort of exception here.
1120 //
1121 // (1) Exception while stating the package file : This should never happen,
1122 // and if it does, we do a full package parse (which is likely to throw the
1123 // same exception).
1124 // (2) Exception while stating the cache file : If the file doesn't exist, the
1125 // cache is obviously out of date. If the file *does* exist, we can't read it.
1126 // We will attempt to delete and recreate it after parsing the package.
1127 if (ee.errno != OsConstants.ENOENT) {
1128 Slog.w("Error while stating package cache : ", ee);
1129 }
1130
1131 return false;
1132 }
1133 }
1134
1135 /**
1136 * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
1137 * or {@code null} if no cached result exists.
1138 */
1139 private Package getCachedResult(File packageFile, int flags) {
1140 if (mCacheDir == null) {
1141 return null;
1142 }
1143
1144 final String cacheKey = getCacheKey(packageFile, flags);
1145 final File cacheFile = new File(mCacheDir, cacheKey);
1146
Narayan Kamath988149c2016-12-01 13:32:59 +00001147 try {
Makoto Onuki48e93162017-08-18 11:00:19 -07001148 // If the cache is not up to date, return null.
1149 if (!isCacheUpToDate(packageFile, cacheFile)) {
1150 return null;
1151 }
1152
Narayan Kamath988149c2016-12-01 13:32:59 +00001153 final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
Jack He61034792019-04-10 23:01:45 +00001154 Package p = fromCacheEntry(bytes);
1155 if (mCallback != null) {
1156 String[] overlayApks = mCallback.getOverlayApks(p.packageName);
1157 if (overlayApks != null && overlayApks.length > 0) {
1158 for (String overlayApk : overlayApks) {
1159 // If a static RRO is updated, return null.
1160 if (!isCacheUpToDate(new File(overlayApk), cacheFile)) {
1161 return null;
1162 }
1163 }
1164 }
1165 }
1166 return p;
Makoto Onuki48e93162017-08-18 11:00:19 -07001167 } catch (Throwable e) {
Narayan Kamath21a28382017-01-13 10:34:29 +00001168 Slog.w(TAG, "Error reading package cache: ", e);
Narayan Kamath988149c2016-12-01 13:32:59 +00001169
1170 // If something went wrong while reading the cache entry, delete the cache file
1171 // so that we regenerate it the next time.
1172 cacheFile.delete();
1173 return null;
1174 }
1175 }
1176
1177 /**
1178 * Caches the parse result for {@code packageFile} with flags {@code flags}.
1179 */
1180 private void cacheResult(File packageFile, int flags, Package parsed) {
1181 if (mCacheDir == null) {
1182 return;
1183 }
1184
Makoto Onuki48e93162017-08-18 11:00:19 -07001185 try {
1186 final String cacheKey = getCacheKey(packageFile, flags);
1187 final File cacheFile = new File(mCacheDir, cacheKey);
Narayan Kamath988149c2016-12-01 13:32:59 +00001188
Makoto Onuki48e93162017-08-18 11:00:19 -07001189 if (cacheFile.exists()) {
1190 if (!cacheFile.delete()) {
1191 Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
1192 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001193 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001194
Makoto Onuki48e93162017-08-18 11:00:19 -07001195 final byte[] cacheEntry = toCacheEntry(parsed);
Narayan Kamath988149c2016-12-01 13:32:59 +00001196
Makoto Onuki48e93162017-08-18 11:00:19 -07001197 if (cacheEntry == null) {
1198 return;
1199 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001200
Makoto Onuki48e93162017-08-18 11:00:19 -07001201 try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
1202 fos.write(cacheEntry);
1203 } catch (IOException ioe) {
1204 Slog.w(TAG, "Error writing cache entry.", ioe);
1205 cacheFile.delete();
1206 }
1207 } catch (Throwable e) {
1208 Slog.w(TAG, "Error saving package cache.", e);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001209 }
1210 }
1211
1212 /**
1213 * Parse all APKs contained in the given directory, treating them as a
1214 * single package. This also performs sanity checking, such as requiring
1215 * identical package name and version codes, a single base APK, and unique
1216 * split names.
1217 * <p>
1218 * Note that this <em>does not</em> perform signature verification; that
1219 * must be done separately in {@link #collectCertificates(Package, int)}.
1220 */
1221 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001222 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001223 if (mOnlyCoreApps && !lite.coreApp) {
1224 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1225 "Not a coreApp: " + packageDir);
1226 }
1227
Adam Lesinski4e862812016-11-21 16:02:24 -08001228 // Build the split dependency tree.
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001229 SparseArray<int[]> splitDependencies = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001230 final SplitAssetLoader assetLoader;
1231 if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001232 try {
1233 splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
1234 assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
1235 } catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
1236 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
1237 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001238 } else {
1239 assetLoader = new DefaultSplitAssetLoader(lite, flags);
1240 }
1241
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001242 try {
Adam Lesinski4e862812016-11-21 16:02:24 -08001243 final AssetManager assets = assetLoader.getBaseAssetManager();
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001244 final File baseApk = new File(lite.baseCodePath);
1245 final Package pkg = parseBaseApk(baseApk, assets, flags);
1246 if (pkg == null) {
1247 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1248 "Failed to parse base APK: " + baseApk);
1249 }
1250
1251 if (!ArrayUtils.isEmpty(lite.splitNames)) {
1252 final int num = lite.splitNames.length;
1253 pkg.splitNames = lite.splitNames;
1254 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001255 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001256 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001257 pkg.splitPrivateFlags = new int[num];
Adam Lesinski4e862812016-11-21 16:02:24 -08001258 pkg.applicationInfo.splitNames = pkg.splitNames;
1259 pkg.applicationInfo.splitDependencies = splitDependencies;
Narayan Kamath96c11c52017-08-09 13:07:21 +01001260 pkg.applicationInfo.splitClassLoaderNames = new String[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001261
1262 for (int i = 0; i < num; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -08001263 final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
1264 parseSplitApk(pkg, i, splitAssets, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001265 }
1266 }
1267
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001268 pkg.setCodePath(packageDir.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001269 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001270 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001271 } catch (IOException e) {
1272 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1273 "Failed to get path: " + lite.baseCodePath, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001274 } finally {
Adam Lesinski4e862812016-11-21 16:02:24 -08001275 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001277 }
1278
Jeff Sharkey275e0852014-06-17 18:18:49 -07001279 /**
1280 * Parse the given APK file, treating it as as a single monolithic package.
1281 * <p>
1282 * Note that this <em>does not</em> perform signature verification; that
1283 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001284 *
1285 * @deprecated external callers should move to
1286 * {@link #parsePackage(File, int)}. Eventually this method will
1287 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -07001288 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001289 @Deprecated
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001290 @UnsupportedAppUsage
Jeff Sharkey275e0852014-06-17 18:18:49 -07001291 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001292 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001293 if (mOnlyCoreApps) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001294 if (!lite.coreApp) {
1295 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1296 "Not a coreApp: " + apkFile);
1297 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001298 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001299
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001300 final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001301 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001302 final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001303 pkg.setCodePath(apkFile.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001304 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001305 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001306 } catch (IOException e) {
1307 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1308 "Failed to get path: " + apkFile, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001309 } finally {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001310 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001311 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001312 }
1313
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001314 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
1315 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001316 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001317
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07001318 String volumeUuid = null;
1319 if (apkPath.startsWith(MNT_EXPAND)) {
1320 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
1321 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
1322 }
1323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001325 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001326
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001327 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001329 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001331 final int cookie = assets.findCookieForPath(apkPath);
1332 if (cookie == 0) {
1333 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1334 "Failed adding asset path: " + apkPath);
1335 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001336 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001337 final Resources res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001338
1339 final String[] outError = new String[1];
Jack He61034792019-04-10 23:01:45 +00001340 final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001341 if (pkg == null) {
1342 throw new PackageParserException(mParseError,
1343 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001345
Svet Ganov354cd3c2015-12-17 11:35:04 -08001346 pkg.setVolumeUuid(volumeUuid);
1347 pkg.setApplicationVolumeUuid(volumeUuid);
1348 pkg.setBaseCodePath(apkPath);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001349 pkg.setSigningDetails(SigningDetails.UNKNOWN);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001350
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001351 return pkg;
1352
1353 } catch (PackageParserException e) {
1354 throw e;
1355 } catch (Exception e) {
1356 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001357 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001358 } finally {
1359 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361 }
1362
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001363 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001364 throws PackageParserException {
1365 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -07001366
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001367 mParseError = PackageManager.INSTALL_SUCCEEDED;
1368 mArchiveSourcePath = apkPath;
1369
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001370 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
1371
Adam Lesinski4e862812016-11-21 16:02:24 -08001372 final Resources res;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001373 XmlResourceParser parser = null;
1374 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001375 // This must always succeed, as the path has been added to the AssetManager before.
1376 final int cookie = assets.findCookieForPath(apkPath);
1377 if (cookie == 0) {
1378 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1379 "Failed adding asset path: " + apkPath);
1380 }
1381
Adam Lesinski56c82be2018-02-09 11:02:04 -08001382 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001383 res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001384
1385 final String[] outError = new String[1];
1386 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
1387 if (pkg == null) {
1388 throw new PackageParserException(mParseError,
1389 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
1390 }
1391
1392 } catch (PackageParserException e) {
1393 throw e;
1394 } catch (Exception e) {
1395 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001396 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001397 } finally {
1398 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001399 }
1400 }
1401
1402 /**
1403 * Parse the manifest of a <em>split APK</em>.
1404 * <p>
1405 * Note that split APKs have many more restrictions on what they're capable
1406 * of doing, so many valid features of a base APK have been carefully
1407 * omitted here.
1408 */
1409 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001410 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
1411 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001412 AttributeSet attrs = parser;
1413
Jeff Sharkey78a13012014-07-15 20:18:34 -07001414 // We parsed manifest tag earlier; just skip past it
Svet Ganov354cd3c2015-12-17 11:35:04 -08001415 parsePackageSplitNames(parser, attrs);
Jeff Sharkey78a13012014-07-15 20:18:34 -07001416
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001417 mParseInstrumentationArgs = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001418
1419 int type;
1420
1421 boolean foundApp = false;
1422
1423 int outerDepth = parser.getDepth();
1424 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1425 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1426 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1427 continue;
1428 }
1429
1430 String tagName = parser.getName();
Adam Lesinski4e862812016-11-21 16:02:24 -08001431 if (tagName.equals(TAG_APPLICATION)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001432 if (foundApp) {
1433 if (RIGID_PARSER) {
1434 outError[0] = "<manifest> has more than one <application>";
1435 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1436 return null;
1437 } else {
1438 Slog.w(TAG, "<manifest> has more than one <application>");
1439 XmlUtils.skipCurrentTag(parser);
1440 continue;
1441 }
1442 }
1443
1444 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001445 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001446 return null;
1447 }
1448
1449 } else if (RIGID_PARSER) {
1450 outError[0] = "Bad element under <manifest>: "
1451 + parser.getName();
1452 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1453 return null;
1454
1455 } else {
1456 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1457 + " at " + mArchiveSourcePath + " "
1458 + parser.getPositionDescription());
1459 XmlUtils.skipCurrentTag(parser);
1460 continue;
1461 }
1462 }
1463
1464 if (!foundApp) {
1465 outError[0] = "<manifest> does not contain an <application>";
1466 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1467 }
1468
1469 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001470 }
1471
Patrick Baumann47117fc2017-12-19 10:17:21 -08001472 /** Parses the public keys from the set of signatures. */
1473 public static ArraySet<PublicKey> toSigningKeys(Signature[] signatures)
1474 throws CertificateException {
1475 ArraySet<PublicKey> keys = new ArraySet<>(signatures.length);
1476 for (int i = 0; i < signatures.length; i++) {
1477 keys.add(signatures[i].getPublicKey());
Todd Kennedy66c55532016-02-26 16:22:11 -08001478 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001479 return keys;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001480 }
1481
1482 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -07001483 * Collect certificates from all the APKs described in the given package,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001484 * populating {@link Package#mSigningDetails}. Also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001485 * contents are signed correctly and consistently.
1486 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001487 @UnsupportedAppUsage
Victor Hsieh5f761242018-01-20 10:30:12 -08001488 public static void collectCertificates(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001489 throws PackageParserException {
Victor Hsieh5f761242018-01-20 10:30:12 -08001490 collectCertificatesInternal(pkg, skipVerify);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001491 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1492 for (int i = 0; i < childCount; i++) {
1493 Package childPkg = pkg.childPackages.get(i);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001494 childPkg.mSigningDetails = pkg.mSigningDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001495 }
1496 }
1497
Victor Hsieh5f761242018-01-20 10:30:12 -08001498 private static void collectCertificatesInternal(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001499 throws PackageParserException {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001500 pkg.mSigningDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001501
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001502 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1503 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001504 collectCertificates(pkg, new File(pkg.baseCodePath), skipVerify);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001505
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001506 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1507 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
Victor Hsieh5f761242018-01-20 10:30:12 -08001508 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001509 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001510 }
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001511 } finally {
1512 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001513 }
1514 }
1515
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001516 @UnsupportedAppUsage
Victor Hsieh5f761242018-01-20 10:30:12 -08001517 private static void collectCertificates(Package pkg, File apkFile, boolean skipVerify)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001518 throws PackageParserException {
1519 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520
Patrick Baumann47117fc2017-12-19 10:17:21 -08001521 int minSignatureScheme = SigningDetails.SignatureSchemeVersion.JAR;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001522 if (pkg.applicationInfo.isStaticSharedLibrary()) {
Dan Cashmane92f8422017-12-08 14:02:51 -08001523 // must use v2 signing scheme
Patrick Baumann47117fc2017-12-19 10:17:21 -08001524 minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;
Dan Cashmane92f8422017-12-08 14:02:51 -08001525 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001526 SigningDetails verified;
Victor Hsieh5f761242018-01-20 10:30:12 -08001527 if (skipVerify) {
Dan Cashman636ea5e2017-12-18 10:38:20 -08001528 // systemDir APKs are already trusted, save time by not verifying
Gavin Corkeryed521ab2019-01-31 16:59:41 +00001529 verified = ApkSignatureVerifier.unsafeGetCertsWithoutVerification(
Dan Cashman636ea5e2017-12-18 10:38:20 -08001530 apkPath, minSignatureScheme);
1531 } else {
1532 verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme);
1533 }
Dan Cashman636ea5e2017-12-18 10:38:20 -08001534
1535 // Verify that entries are signed consistently with the first pkg
1536 // we encountered. Note that for splits, certificates may have
1537 // already been populated during an earlier parse of a base APK.
Patrick Baumann47117fc2017-12-19 10:17:21 -08001538 if (pkg.mSigningDetails == SigningDetails.UNKNOWN) {
1539 pkg.mSigningDetails = verified;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001540 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001541 if (!Signature.areExactMatch(pkg.mSigningDetails.signatures, verified.signatures)) {
Patrick Baumann9ff55742017-12-14 10:50:18 -08001542 throw new PackageParserException(
1543 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
1544 apkPath + " has mismatched certificates");
1545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 }
1548
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001549 private static AssetManager newConfiguredAssetManager() {
1550 AssetManager assetManager = new AssetManager();
Romain Guy408afbf2017-01-25 10:23:03 -08001551 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 -07001552 Build.VERSION.RESOURCES_SDK_INT);
1553 return assetManager;
1554 }
1555
Jeff Sharkey275e0852014-06-17 18:18:49 -07001556 /**
1557 * Utility method that retrieves lightweight details about a single APK
1558 * file, including package name, split name, and install location.
1559 *
1560 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001561 * @param flags optional parse flags, such as
1562 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001563 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001564 public static ApkLite parseApkLite(File apkFile, int flags)
1565 throws PackageParserException {
Dianne Hackbornca3872c2017-10-30 14:19:32 -07001566 return parseApkLiteInner(apkFile, null, null, flags);
1567 }
1568
1569 /**
1570 * Utility method that retrieves lightweight details about a single APK
1571 * file, including package name, split name, and install location.
1572 *
1573 * @param fd already open file descriptor of an apk file
1574 * @param debugPathName arbitrary text name for this file, for debug output
1575 * @param flags optional parse flags, such as
1576 * {@link #PARSE_COLLECT_CERTIFICATES}
1577 */
1578 public static ApkLite parseApkLite(FileDescriptor fd, String debugPathName, int flags)
1579 throws PackageParserException {
1580 return parseApkLiteInner(null, fd, debugPathName, flags);
1581 }
1582
1583 private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName,
1584 int flags) throws PackageParserException {
1585 final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001586
Jeff Sharkey275e0852014-06-17 18:18:49 -07001587 XmlResourceParser parser = null;
Winson7a3d82a2019-03-07 12:54:24 -08001588 ApkAssets apkAssets = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001590 try {
1591 apkAssets = fd != null
1592 ? ApkAssets.loadFromFd(fd, debugPathName, false, false)
1593 : ApkAssets.loadFromPath(apkPath);
1594 } catch (IOException e) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001595 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1596 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001597 }
1598
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001599 parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001600
Patrick Baumann47117fc2017-12-19 10:17:21 -08001601 final SigningDetails signingDetails;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001602 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1603 // TODO: factor signature related items out of Package object
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001604 final Package tempPkg = new Package((String) null);
Victor Hsieh5f761242018-01-20 10:30:12 -08001605 final boolean skipVerify = (flags & PARSE_IS_SYSTEM_DIR) != 0;
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001606 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1607 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001608 collectCertificates(tempPkg, apkFile, skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001609 } finally {
1610 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1611 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001612 signingDetails = tempPkg.mSigningDetails;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001613 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001614 signingDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001615 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001616
Jeff Sharkey275e0852014-06-17 18:18:49 -07001617 final AttributeSet attrs = parser;
Victor Hsieh54305982019-03-12 10:09:39 -07001618 return parseApkLite(apkPath, parser, attrs, signingDetails);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001619
1620 } catch (XmlPullParserException | IOException | RuntimeException e) {
Dianne Hackborn34041732017-01-31 15:27:13 -08001621 Slog.w(TAG, "Failed to parse " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001622 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1623 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001625 IoUtils.closeQuietly(parser);
Winson7a3d82a2019-03-07 12:54:24 -08001626 if (apkAssets != null) {
1627 try {
1628 apkAssets.close();
1629 } catch (Throwable ignored) {
1630 }
1631 }
1632 // TODO(b/72056911): Implement AutoCloseable on ApkAssets.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 }
1635
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001636 private static String validateName(String name, boolean requireSeparator,
1637 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 final int N = name.length();
1639 boolean hasSep = false;
1640 boolean front = true;
1641 for (int i=0; i<N; i++) {
1642 final char c = name.charAt(i);
1643 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1644 front = false;
1645 continue;
1646 }
1647 if (!front) {
1648 if ((c >= '0' && c <= '9') || c == '_') {
1649 continue;
1650 }
1651 }
1652 if (c == '.') {
1653 hasSep = true;
1654 front = true;
1655 continue;
1656 }
1657 return "bad character '" + c + "'";
1658 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001659 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1660 return "Invalid filename";
1661 }
1662 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001663 ? null : "must have at least one '.' separator";
1664 }
1665
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001666 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
Svet Ganov354cd3c2015-12-17 11:35:04 -08001667 AttributeSet attrs) throws IOException, XmlPullParserException,
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001668 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001669
1670 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001671 while ((type = parser.next()) != XmlPullParser.START_TAG
1672 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 }
1674
Kenny Rootd2d29252011-08-08 11:27:57 -07001675 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001676 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1677 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001679 if (!parser.getName().equals(TAG_MANIFEST)) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001680 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1681 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 }
1683
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001684 final String packageName = attrs.getAttributeValue(null, "package");
1685 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001686 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001687 if (error != null) {
1688 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1689 "Invalid manifest package: " + error);
1690 }
1691 }
1692
Jeff Sharkey275e0852014-06-17 18:18:49 -07001693 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001694 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001695 if (splitName.length() == 0) {
1696 splitName = null;
1697 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001698 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001699 if (error != null) {
1700 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1701 "Invalid manifest split: " + error);
1702 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001703 }
1704 }
1705
1706 return Pair.create(packageName.intern(),
1707 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 }
1709
Adam Lesinski4e862812016-11-21 16:02:24 -08001710 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
Victor Hsieh54305982019-03-12 10:09:39 -07001711 SigningDetails signingDetails)
Adam Lesinski4e862812016-11-21 16:02:24 -08001712 throws IOException, XmlPullParserException, PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001713 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001714
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001715 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001716 int versionCode = 0;
Dianne Hackborn3accca02013-09-20 09:32:11 -07001717 int versionCodeMajor = 0;
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +00001718 int targetSdkVersion = DEFAULT_TARGET_SDK_VERSION;
1719 int minSdkVersion = DEFAULT_MIN_SDK_VERSION;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001720 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001721 boolean coreApp = false;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001722 boolean debuggable = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001723 boolean multiArch = false;
Selim Gurun2d291d82016-02-05 17:50:53 -08001724 boolean use32bitAbi = false;
Victor Hsieh54305982019-03-12 10:09:39 -07001725 boolean extractNativeLibs = true;
Adam Lesinski4e862812016-11-21 16:02:24 -08001726 boolean isolatedSplits = false;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001727 boolean isFeatureSplit = false;
Todd Kennedy29cfa272018-09-26 10:25:24 -07001728 boolean isSplitRequired = false;
Victor Hsiehfa9df0b2019-01-29 12:48:36 -08001729 boolean useEmbeddedDex = false;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001730 String configForSplit = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001731 String usesSplitName = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001732
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001733 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001734 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001735 if (attr.equals("installLocation")) {
1736 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001737 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001738 } else if (attr.equals("versionCode")) {
1739 versionCode = attrs.getAttributeIntValue(i, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001740 } else if (attr.equals("versionCodeMajor")) {
1741 versionCodeMajor = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001742 } else if (attr.equals("revisionCode")) {
1743 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001744 } else if (attr.equals("coreApp")) {
1745 coreApp = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski4e862812016-11-21 16:02:24 -08001746 } else if (attr.equals("isolatedSplits")) {
1747 isolatedSplits = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001748 } else if (attr.equals("configForSplit")) {
1749 configForSplit = attrs.getAttributeValue(i);
1750 } else if (attr.equals("isFeatureSplit")) {
1751 isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
Todd Kennedy29cfa272018-09-26 10:25:24 -07001752 } else if (attr.equals("isSplitRequired")) {
1753 isSplitRequired = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001754 }
1755 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001756
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +00001757 // Only search the tree when the tag is the direct child of <manifest> tag
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001758 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001759 final int searchDepth = parser.getDepth() + 1;
1760
1761 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1762 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1763 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1764 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1765 continue;
1766 }
1767
Adam Lesinski4e862812016-11-21 16:02:24 -08001768 if (parser.getDepth() != searchDepth) {
1769 continue;
1770 }
1771
1772 if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
1773 final VerifierInfo verifier = parseVerifier(attrs);
Kenny Root05ca4c92011-09-15 10:36:25 -07001774 if (verifier != null) {
1775 verifiers.add(verifier);
1776 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001777 } else if (TAG_APPLICATION.equals(parser.getName())) {
Narayan Kamatha8755a82014-07-15 12:26:35 +01001778 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1779 final String attr = attrs.getAttributeName(i);
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001780 if ("debuggable".equals(attr)) {
1781 debuggable = attrs.getAttributeBooleanValue(i, false);
1782 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001783 if ("multiArch".equals(attr)) {
1784 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001785 }
Selim Gurun2d291d82016-02-05 17:50:53 -08001786 if ("use32bitAbi".equals(attr)) {
1787 use32bitAbi = attrs.getAttributeBooleanValue(i, false);
Tao Baic9a02372016-01-12 15:02:24 -08001788 }
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001789 if ("extractNativeLibs".equals(attr)) {
Victor Hsieh54305982019-03-12 10:09:39 -07001790 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001791 }
Victor Hsiehfa9df0b2019-01-29 12:48:36 -08001792 if ("useEmbeddedDex".equals(attr)) {
1793 useEmbeddedDex = attrs.getAttributeBooleanValue(i, false);
Victor Hsiehe7b5a8d2018-11-16 10:27:06 -08001794 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001795 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001796 } else if (TAG_USES_SPLIT.equals(parser.getName())) {
1797 if (usesSplitName != null) {
1798 Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
1799 continue;
1800 }
1801
1802 usesSplitName = attrs.getAttributeValue(ANDROID_RESOURCES, "name");
1803 if (usesSplitName == null) {
1804 throw new PackageParserException(
1805 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1806 "<uses-split> tag requires 'android:name' attribute");
1807 }
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +00001808 } else if (TAG_USES_SDK.equals(parser.getName())) {
1809 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1810 final String attr = attrs.getAttributeName(i);
1811 if ("targetSdkVersion".equals(attr)) {
1812 targetSdkVersion = attrs.getAttributeIntValue(i,
1813 DEFAULT_TARGET_SDK_VERSION);
1814 }
1815 if ("minSdkVersion".equals(attr)) {
1816 minSdkVersion = attrs.getAttributeIntValue(i, DEFAULT_MIN_SDK_VERSION);
1817 }
1818 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001819 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001820 }
1821
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001822 return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
Todd Kennedy29cfa272018-09-26 10:25:24 -07001823 configForSplit, usesSplitName, isSplitRequired, versionCode, versionCodeMajor,
1824 revisionCode, installLocation, verifiers, signingDetails, coreApp, debuggable,
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +00001825 multiArch, use32bitAbi, useEmbeddedDex, extractNativeLibs, isolatedSplits,
1826 minSdkVersion, targetSdkVersion);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001827 }
1828
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001829 /**
Svet Ganov354cd3c2015-12-17 11:35:04 -08001830 * Parses a child package and adds it to the parent if successful. If you add
1831 * new tags that need to be supported by child packages make sure to add them
1832 * to {@link #CHILD_PACKAGE_TAGS}.
1833 *
1834 * @param parentPkg The parent that contains the child
1835 * @param res Resources against which to resolve values
1836 * @param parser Parser of the manifest
1837 * @param flags Flags about how to parse
1838 * @param outError Human readable error if parsing fails
1839 * @return True of parsing succeeded.
1840 *
1841 * @throws XmlPullParserException
1842 * @throws IOException
1843 */
1844 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
1845 int flags, String[] outError) throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001846 // Make sure we have a valid child package name
1847 String childPackageName = parser.getAttributeValue(null, "package");
1848 if (validateName(childPackageName, true, false) != null) {
1849 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1850 return false;
1851 }
1852
1853 // Child packages must be unique
1854 if (childPackageName.equals(parentPkg.packageName)) {
1855 String message = "Child package name cannot be equal to parent package name: "
1856 + parentPkg.packageName;
1857 Slog.w(TAG, message);
1858 outError[0] = message;
1859 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1860 return false;
1861 }
1862
1863 // Child packages must be unique
1864 if (parentPkg.hasChildPackage(childPackageName)) {
1865 String message = "Duplicate child package:" + childPackageName;
1866 Slog.w(TAG, message);
1867 outError[0] = message;
1868 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1869 return false;
1870 }
1871
1872 // Go ahead and parse the child
1873 Package childPkg = new Package(childPackageName);
1874
1875 // Child package inherits parent version code/name/target SDK
1876 childPkg.mVersionCode = parentPkg.mVersionCode;
1877 childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
1878 childPkg.mVersionName = parentPkg.mVersionName;
1879 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
Todd Kennedy89d60182016-03-11 11:18:32 -08001880 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001881
1882 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
1883 if (childPkg == null) {
1884 // If we got null then error was set during child parsing
1885 return false;
1886 }
1887
1888 // Set the parent-child relation
1889 if (parentPkg.childPackages == null) {
1890 parentPkg.childPackages = new ArrayList<>();
1891 }
1892 parentPkg.childPackages.add(childPkg);
1893 childPkg.parentPackage = parentPkg;
1894
1895 return true;
1896 }
1897
1898 /**
1899 * Parse the manifest of a <em>base APK</em>. When adding new features you
1900 * need to consider whether they should be supported by split APKs and child
1901 * packages.
1902 *
Jack He61034792019-04-10 23:01:45 +00001903 * @param apkPath The package apk file path
Svet Ganov354cd3c2015-12-17 11:35:04 -08001904 * @param res The resources from which to resolve values
1905 * @param parser The manifest parser
1906 * @param flags Flags how to parse
1907 * @param outError Human readable error message
1908 * @return Parsed package or null on error.
1909 *
1910 * @throws XmlPullParserException
1911 * @throws IOException
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001912 */
Jack He61034792019-04-10 23:01:45 +00001913 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1914 private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001915 String[] outError) throws XmlPullParserException, IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001916 final String splitName;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001917 final String pkgName;
1918
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001919 try {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001920 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001921 pkgName = packageSplit.first;
1922 splitName = packageSplit.second;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001923
1924 if (!TextUtils.isEmpty(splitName)) {
1925 outError[0] = "Expected base APK, but found split " + splitName;
1926 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1927 return null;
1928 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001929 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1931 return null;
1932 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001933
Jack He61034792019-04-10 23:01:45 +00001934 if (mCallback != null) {
1935 String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
1936 if (overlayPaths != null && overlayPaths.length > 0) {
1937 for (String overlayPath : overlayPaths) {
1938 res.getAssets().addOverlayPath(overlayPath);
1939 }
1940 }
1941 }
1942
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001943 final Package pkg = new Package(pkgName);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001944
Svet Ganov354cd3c2015-12-17 11:35:04 -08001945 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 com.android.internal.R.styleable.AndroidManifest);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001947
Dianne Hackborn3accca02013-09-20 09:32:11 -07001948 pkg.mVersionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001949 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001950 pkg.mVersionCodeMajor = sa.getInteger(
1951 com.android.internal.R.styleable.AndroidManifest_versionCodeMajor, 0);
Patrick Baumannc2def582018-04-04 12:14:15 -07001952 pkg.applicationInfo.setVersionCode(pkg.getLongVersionCode());
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001953 pkg.baseRevisionCode = sa.getInteger(
1954 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001955 pkg.mVersionName = sa.getNonConfigurationString(
1956 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001957 if (pkg.mVersionName != null) {
1958 pkg.mVersionName = pkg.mVersionName.intern();
1959 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001960
1961 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
1962
Alan Viveretteb6a25732017-11-21 14:49:24 -05001963 pkg.mCompileSdkVersion = sa.getInteger(
1964 com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0);
1965 pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion;
1966 pkg.mCompileSdkVersionCodename = sa.getNonConfigurationString(
1967 com.android.internal.R.styleable.AndroidManifest_compileSdkVersionCodename, 0);
1968 if (pkg.mCompileSdkVersionCodename != null) {
1969 pkg.mCompileSdkVersionCodename = pkg.mCompileSdkVersionCodename.intern();
1970 }
1971 pkg.applicationInfo.compileSdkVersionCodename = pkg.mCompileSdkVersionCodename;
1972
Svet Ganov354cd3c2015-12-17 11:35:04 -08001973 sa.recycle();
1974
1975 return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
1976 }
1977
1978 /**
1979 * This is the common parsing routing for handling parent and child
1980 * packages in a base APK. The difference between parent and child
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001981 * parsing is that some tags are not supported by child packages as
Svet Ganov354cd3c2015-12-17 11:35:04 -08001982 * well as some manifest attributes are ignored. The implementation
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001983 * assumes the calling code has already handled the manifest tag if needed
Svet Ganov354cd3c2015-12-17 11:35:04 -08001984 * (this applies to the parent only).
1985 *
1986 * @param pkg The package which to populate
1987 * @param acceptedTags Which tags to handle, null to handle all
1988 * @param res Resources against which to resolve values
1989 * @param parser Parser of the manifest
1990 * @param flags Flags about how to parse
1991 * @param outError Human readable error if parsing fails
1992 * @return The package if parsing succeeded or null.
1993 *
1994 * @throws XmlPullParserException
1995 * @throws IOException
1996 */
1997 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
1998 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
1999 IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002000 mParseInstrumentationArgs = null;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002001
2002 int type;
2003 boolean foundApp = false;
2004
2005 TypedArray sa = res.obtainAttributes(parser,
2006 com.android.internal.R.styleable.AndroidManifest);
2007
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002008 String str = sa.getNonConfigurationString(
2009 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
2010 if (str != null && str.length() > 0) {
Sudheer Shanka9c5079a2018-08-03 12:41:10 -07002011 String nameError = validateName(str, true, true);
Svet Ganov354cd3c2015-12-17 11:35:04 -08002012 if (nameError != null && !"android".equals(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002013 outError[0] = "<manifest> specifies bad sharedUserId name \""
2014 + str + "\": " + nameError;
2015 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
2016 return null;
2017 }
2018 pkg.mSharedUserId = str.intern();
2019 pkg.mSharedUserLabel = sa.getResourceId(
2020 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
2021 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08002022
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08002023 pkg.installLocation = sa.getInteger(
2024 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07002025 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002026 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07002027
Todd Kennedy11e45072017-01-25 13:24:21 -08002028 final int targetSandboxVersion = sa.getInteger(
2029 com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion,
2030 PARSE_DEFAULT_TARGET_SANDBOX);
2031 pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion;
Alan Viverettefd274a02014-03-27 15:39:15 -07002032
Kenny Root7cb9be22012-05-30 15:30:37 -07002033 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07002034 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07002035 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
2036 }
2037
Adam Lesinski4e862812016-11-21 16:02:24 -08002038 if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
2039 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
2040 }
2041
Dianne Hackborn723738c2009-06-25 19:48:04 -07002042 // Resource boolean are -1, so 1 means we don't know the value.
2043 int supportsSmallScreens = 1;
2044 int supportsNormalScreens = 1;
2045 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002046 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002047 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002048 int anyDensity = 1;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002050 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07002051 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2052 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2053 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054 continue;
2055 }
2056
2057 String tagName = parser.getName();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002058
2059 if (acceptedTags != null && !acceptedTags.contains(tagName)) {
2060 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
2061 + tagName + " at " + mArchiveSourcePath + " "
2062 + parser.getPositionDescription());
2063 XmlUtils.skipCurrentTag(parser);
2064 continue;
2065 }
2066
2067 if (tagName.equals(TAG_APPLICATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002068 if (foundApp) {
2069 if (RIGID_PARSER) {
2070 outError[0] = "<manifest> has more than one <application>";
2071 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2072 return null;
2073 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002074 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 XmlUtils.skipCurrentTag(parser);
2076 continue;
2077 }
2078 }
2079
2080 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002081 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082 return null;
2083 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002084 } else if (tagName.equals(TAG_OVERLAY)) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002085 sa = res.obtainAttributes(parser,
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002086 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
2087 pkg.mOverlayTarget = sa.getString(
2088 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
Ryan Mitchella3628462019-01-14 12:19:40 -08002089 pkg.mOverlayTargetName = sa.getString(
2090 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetName);
Adrian Roosc84df772018-01-19 21:20:22 +01002091 pkg.mOverlayCategory = sa.getString(
2092 com.android.internal.R.styleable.AndroidManifestResourceOverlay_category);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002093 pkg.mOverlayPriority = sa.getInt(
2094 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
2095 0);
Adam Lesinskie7334972018-01-17 16:13:52 -08002096 pkg.mOverlayIsStatic = sa.getBoolean(
Jaekyun Seok04342892017-03-02 15:24:19 +09002097 com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
2098 false);
Todd Leeea2f3be2017-03-16 14:00:52 -07002099 final String propName = sa.getString(
2100 com.android.internal.R.styleable
2101 .AndroidManifestResourceOverlay_requiredSystemPropertyName);
2102 final String propValue = sa.getString(
2103 com.android.internal.R.styleable
2104 .AndroidManifestResourceOverlay_requiredSystemPropertyValue);
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002105 sa.recycle();
2106
2107 if (pkg.mOverlayTarget == null) {
2108 outError[0] = "<overlay> does not specify a target package";
2109 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2110 return null;
2111 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002112
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002113 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
2114 outError[0] = "<overlay> priority must be between 0 and 9999";
2115 mParseError =
2116 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2117 return null;
2118 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002119
2120 // check to see if overlay should be excluded based on system property condition
2121 if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
2122 Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
2123 + pkg.baseCodePath+ ": overlay ignored due to required system property: "
2124 + propName + " with value: " + propValue);
2125 return null;
Jaekyun Seok04342892017-03-02 15:24:19 +09002126 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002127
Zoran Jovanovic946e32f2019-02-17 22:02:40 +01002128 pkg.applicationInfo.privateFlags |=
2129 ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY;
2130
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002131 XmlUtils.skipCurrentTag(parser);
2132
Svet Ganov354cd3c2015-12-17 11:35:04 -08002133 } else if (tagName.equals(TAG_KEY_SETS)) {
2134 if (!parseKeySets(pkg, res, parser, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08002135 return null;
2136 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002137 } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002138 if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002139 return null;
2140 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002141 } else if (tagName.equals(TAG_PERMISSION)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002142 if (!parsePermission(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002143 return null;
2144 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002145 } else if (tagName.equals(TAG_PERMISSION_TREE)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002146 if (!parsePermissionTree(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002147 return null;
2148 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002149 } else if (tagName.equals(TAG_USES_PERMISSION)) {
Chad Brubakere2107312019-02-04 12:30:01 -08002150 if (!parseUsesPermission(pkg, res, parser)) {
Svetoslav96a77162015-04-03 13:58:33 -07002151 return null;
2152 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002153 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
2154 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
Chad Brubakere2107312019-02-04 12:30:01 -08002155 if (!parseUsesPermission(pkg, res, parser)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002156 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002158 } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 ConfigurationInfo cPref = new ConfigurationInfo();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002160 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002161 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
2162 cPref.reqTouchScreen = sa.getInt(
2163 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
2164 Configuration.TOUCHSCREEN_UNDEFINED);
2165 cPref.reqKeyboardType = sa.getInt(
2166 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
2167 Configuration.KEYBOARD_UNDEFINED);
2168 if (sa.getBoolean(
2169 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
2170 false)) {
2171 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
2172 }
2173 cPref.reqNavigation = sa.getInt(
2174 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
2175 Configuration.NAVIGATION_UNDEFINED);
2176 if (sa.getBoolean(
2177 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
2178 false)) {
2179 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
2180 }
2181 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002182 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183
2184 XmlUtils.skipCurrentTag(parser);
2185
Svet Ganov354cd3c2015-12-17 11:35:04 -08002186 } else if (tagName.equals(TAG_USES_FEATURE)) {
2187 FeatureInfo fi = parseUsesFeature(res, parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002188 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
2189
Dianne Hackborn49237342009-08-27 20:08:01 -07002190 if (fi.name == null) {
2191 ConfigurationInfo cPref = new ConfigurationInfo();
2192 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002193 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07002194 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07002195
2196 XmlUtils.skipCurrentTag(parser);
2197
Svet Ganov354cd3c2015-12-17 11:35:04 -08002198 } else if (tagName.equals(TAG_FEATURE_GROUP)) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002199 FeatureGroupInfo group = new FeatureGroupInfo();
2200 ArrayList<FeatureInfo> features = null;
2201 final int innerDepth = parser.getDepth();
2202 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2203 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2204 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2205 continue;
2206 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07002207
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002208 final String innerTagName = parser.getName();
2209 if (innerTagName.equals("uses-feature")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002210 FeatureInfo featureInfo = parseUsesFeature(res, parser);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002211 // FeatureGroups are stricter and mandate that
2212 // any <uses-feature> declared are mandatory.
2213 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
2214 features = ArrayUtils.add(features, featureInfo);
2215 } else {
2216 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
2217 " at " + mArchiveSourcePath + " " +
2218 parser.getPositionDescription());
2219 }
2220 XmlUtils.skipCurrentTag(parser);
2221 }
2222
2223 if (features != null) {
2224 group.features = new FeatureInfo[features.size()];
2225 group.features = features.toArray(group.features);
2226 }
2227 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07002228
Svet Ganov354cd3c2015-12-17 11:35:04 -08002229 } else if (tagName.equals(TAG_USES_SDK)) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07002230 if (SDK_VERSION > 0) {
Victor Hsieh54305982019-03-12 10:09:39 -07002231 sa = res.obtainAttributes(parser,
2232 com.android.internal.R.styleable.AndroidManifestUsesSdk);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233
Victor Hsieh54305982019-03-12 10:09:39 -07002234 int minVers = 1;
2235 String minCode = null;
2236 int targetVers = 0;
2237 String targetCode = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002238
Victor Hsieh54305982019-03-12 10:09:39 -07002239 TypedValue val = sa.peekValue(
2240 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
2241 if (val != null) {
2242 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
2243 minCode = val.string.toString();
2244 } else {
2245 // If it's not a string, it's an integer.
2246 minVers = val.data;
2247 }
2248 }
Victor Hsieh4e54b522018-10-12 15:38:18 -07002249
Victor Hsieh54305982019-03-12 10:09:39 -07002250 val = sa.peekValue(
2251 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
2252 if (val != null) {
2253 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
2254 targetCode = val.string.toString();
2255 if (minCode == null) {
2256 minCode = targetCode;
2257 }
2258 } else {
2259 // If it's not a string, it's an integer.
2260 targetVers = val.data;
2261 }
2262 } else {
2263 targetVers = minVers;
2264 targetCode = minCode;
2265 }
Victor Hsieh4e54b522018-10-12 15:38:18 -07002266
Victor Hsieh54305982019-03-12 10:09:39 -07002267 sa.recycle();
Victor Hsieh4e54b522018-10-12 15:38:18 -07002268
Victor Hsieh54305982019-03-12 10:09:39 -07002269 final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode,
2270 SDK_VERSION, SDK_CODENAMES, outError);
2271 if (minSdkVersion < 0) {
Victor Hsieh4e54b522018-10-12 15:38:18 -07002272 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2273 return null;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002274 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002275
Victor Hsieh54305982019-03-12 10:09:39 -07002276 final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers,
2277 targetCode, SDK_CODENAMES, outError);
2278 if (targetSdkVersion < 0) {
2279 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2280 return null;
2281 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002282
Victor Hsieh54305982019-03-12 10:09:39 -07002283 pkg.applicationInfo.minSdkVersion = minSdkVersion;
2284 pkg.applicationInfo.targetSdkVersion = targetSdkVersion;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 }
Victor Hsieh54305982019-03-12 10:09:39 -07002286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002287 XmlUtils.skipCurrentTag(parser);
Victor Hsieh54305982019-03-12 10:09:39 -07002288
Svet Ganov354cd3c2015-12-17 11:35:04 -08002289 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
2290 sa = res.obtainAttributes(parser,
Dianne Hackborn723738c2009-06-25 19:48:04 -07002291 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
2292
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002293 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
2294 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
2295 0);
2296 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
2297 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
2298 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07002299 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
2300 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
2301 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002302
Dianne Hackborn723738c2009-06-25 19:48:04 -07002303 // This is a trick to get a boolean and still able to detect
2304 // if a value was actually set.
2305 supportsSmallScreens = sa.getInteger(
2306 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
2307 supportsSmallScreens);
2308 supportsNormalScreens = sa.getInteger(
2309 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
2310 supportsNormalScreens);
2311 supportsLargeScreens = sa.getInteger(
2312 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
2313 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002314 supportsXLargeScreens = sa.getInteger(
2315 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
2316 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002317 resizeable = sa.getInteger(
2318 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002319 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002320 anyDensity = sa.getInteger(
2321 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
2322 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07002323
2324 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002325
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002326 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002327
Svet Ganov354cd3c2015-12-17 11:35:04 -08002328 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
2329 sa = res.obtainAttributes(parser,
Dianne Hackborn854060af2009-07-09 18:14:31 -07002330 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
2331
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002332 // Note: don't allow this value to be a reference to a resource
2333 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07002334 String name = sa.getNonResourceString(
2335 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
2336
2337 sa.recycle();
2338
Todd Kennedy232d29e2017-11-06 14:45:53 -08002339 if (name != null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002340 if (pkg.protectedBroadcasts == null) {
2341 pkg.protectedBroadcasts = new ArrayList<String>();
2342 }
2343 if (!pkg.protectedBroadcasts.contains(name)) {
2344 pkg.protectedBroadcasts.add(name.intern());
2345 }
2346 }
2347
2348 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002349
Svet Ganov354cd3c2015-12-17 11:35:04 -08002350 } else if (tagName.equals(TAG_INSTRUMENTATION)) {
2351 if (parseInstrumentation(pkg, res, parser, outError) == null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002352 return null;
2353 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002354 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
2355 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002356 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2357
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002358 String orig =sa.getNonConfigurationString(
2359 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002360 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002361 if (pkg.mOriginalPackages == null) {
2362 pkg.mOriginalPackages = new ArrayList<String>();
2363 pkg.mRealPackage = pkg.packageName;
2364 }
2365 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002366 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002367
2368 sa.recycle();
2369
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002370 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002371
Svet Ganov354cd3c2015-12-17 11:35:04 -08002372 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
2373 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002374 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2375
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002376 String name = sa.getNonConfigurationString(
2377 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002378
2379 sa.recycle();
2380
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002381 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002382 if (pkg.mAdoptPermissions == null) {
2383 pkg.mAdoptPermissions = new ArrayList<String>();
2384 }
2385 pkg.mAdoptPermissions.add(name);
2386 }
2387
2388 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002389
Svet Ganov354cd3c2015-12-17 11:35:04 -08002390 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002391 // Just skip this tag
2392 XmlUtils.skipCurrentTag(parser);
2393 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002394
Svet Ganov354cd3c2015-12-17 11:35:04 -08002395 } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002396 // Just skip this tag
2397 XmlUtils.skipCurrentTag(parser);
2398 continue;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002399 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
Michael Wrighteaeb1902013-09-05 18:15:57 -07002400 XmlUtils.skipCurrentTag(parser);
2401 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002402
Svet Ganov354cd3c2015-12-17 11:35:04 -08002403 } else if (tagName.equals(TAG_EAT_COMMENT)) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002404 // Just skip this tag
2405 XmlUtils.skipCurrentTag(parser);
2406 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002407
Svet Ganov354cd3c2015-12-17 11:35:04 -08002408 } else if (tagName.equals(TAG_PACKAGE)) {
Svet Ganova7532cf2016-05-02 08:13:17 -07002409 if (!MULTI_PACKAGE_APK_ENABLED) {
2410 XmlUtils.skipCurrentTag(parser);
2411 continue;
2412 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002413 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
2414 // If parsing a child failed the error is already set
2415 return null;
2416 }
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002417
2418 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
2419 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
2420 sa = res.obtainAttributes(parser,
2421 com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
2422 final String hash = sa.getNonConfigurationString(
2423 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
2424 sa.recycle();
2425
2426 pkg.restrictUpdateHash = null;
2427 if (hash != null) {
2428 final int hashLength = hash.length();
2429 final byte[] hashBytes = new byte[hashLength / 2];
2430 for (int i = 0; i < hashLength; i += 2){
2431 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
2432 + Character.digit(hash.charAt(i + 1), 16));
2433 }
2434 pkg.restrictUpdateHash = hashBytes;
2435 }
2436 }
2437
2438 XmlUtils.skipCurrentTag(parser);
2439
Dianne Hackborn854060af2009-07-09 18:14:31 -07002440 } else if (RIGID_PARSER) {
2441 outError[0] = "Bad element under <manifest>: "
2442 + parser.getName();
2443 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2444 return null;
2445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002446 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002447 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002448 + " at " + mArchiveSourcePath + " "
2449 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002450 XmlUtils.skipCurrentTag(parser);
2451 continue;
2452 }
2453 }
2454
2455 if (!foundApp && pkg.instrumentation.size() == 0) {
2456 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
2457 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
2458 }
2459
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002460 final int NP = PackageParser.NEW_PERMISSIONS.length;
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002461 StringBuilder newPermsMsg = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002462 for (int ip=0; ip<NP; ip++) {
2463 final PackageParser.NewPermissionInfo npi
2464 = PackageParser.NEW_PERMISSIONS[ip];
2465 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
2466 break;
2467 }
2468 if (!pkg.requestedPermissions.contains(npi.name)) {
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002469 if (newPermsMsg == null) {
2470 newPermsMsg = new StringBuilder(128);
2471 newPermsMsg.append(pkg.packageName);
2472 newPermsMsg.append(": compat added ");
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002473 } else {
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002474 newPermsMsg.append(' ');
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002475 }
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002476 newPermsMsg.append(npi.name);
Chad Brubakere2107312019-02-04 12:30:01 -08002477 pkg.requestedPermissions.add(npi.name);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002478 pkg.implicitPermissions.add(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002479 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002480 }
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002481 if (newPermsMsg != null) {
2482 Slog.i(TAG, newPermsMsg.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002483 }
Dianne Hackborn79245122012-03-12 10:51:26 -07002484
Philip P. Moltmann039678e2018-09-18 13:04:38 -07002485
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -07002486 final int NS = PermissionManager.SPLIT_PERMISSIONS.size();
Dianne Hackborn79245122012-03-12 10:51:26 -07002487 for (int is=0; is<NS; is++) {
Philip P. Moltmann039678e2018-09-18 13:04:38 -07002488 final PermissionManager.SplitPermissionInfo spi =
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -07002489 PermissionManager.SPLIT_PERMISSIONS.get(is);
Philip P. Moltmann039678e2018-09-18 13:04:38 -07002490 if (pkg.applicationInfo.targetSdkVersion >= spi.getTargetSdk()
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -07002491 || !pkg.requestedPermissions.contains(spi.getSplitPermission())) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07002492 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07002493 }
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -07002494 final List<String> newPerms = spi.getNewPermissions();
2495 for (int in = 0; in < newPerms.size(); in++) {
2496 final String perm = newPerms.get(in);
Dianne Hackborn79245122012-03-12 10:51:26 -07002497 if (!pkg.requestedPermissions.contains(perm)) {
Chad Brubakere2107312019-02-04 12:30:01 -08002498 pkg.requestedPermissions.add(perm);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002499 pkg.implicitPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07002500 }
2501 }
2502 }
2503
Dianne Hackborn723738c2009-06-25 19:48:04 -07002504 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
2505 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002506 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002507 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
2508 }
2509 if (supportsNormalScreens != 0) {
2510 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
2511 }
2512 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
2513 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002514 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002515 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
2516 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002517 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
2518 && pkg.applicationInfo.targetSdkVersion
2519 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
2520 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
2521 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002522 if (resizeable < 0 || (resizeable > 0
2523 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002524 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002525 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
2526 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002527 if (anyDensity < 0 || (anyDensity > 0
2528 && pkg.applicationInfo.targetSdkVersion
2529 >= android.os.Build.VERSION_CODES.DONUT)) {
2530 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07002531 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07002532
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002533 // At this point we can check if an application is not supporting densities and hence
2534 // cannot be windowed / resized. Note that an SDK version of 0 is common for
2535 // pre-Doughnut applications.
2536 if (pkg.applicationInfo.usesCompatibilityMode()) {
Winson Chungd3395382016-12-13 11:49:09 -08002537 adjustPackageToBeUnresizeableAndUnpipable(pkg);
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002538 }
Jeff Sharkey4aacd8b2018-07-24 15:24:21 -06002539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002540 return pkg;
2541 }
2542
Todd Leeea2f3be2017-03-16 14:00:52 -07002543 private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
2544
2545 if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
2546 if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
2547 // malformed condition - incomplete
2548 Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
2549 + "=" + propValue + "' - require both requiredSystemPropertyName"
2550 + " AND requiredSystemPropertyValue to be specified.");
2551 return false;
2552 }
2553 // no valid condition set - so no exclusion criteria, overlay will be included.
2554 return true;
2555 }
2556
2557 // check property value - make sure it is both set and equal to expected value
2558 final String currValue = SystemProperties.get(propName);
2559 return (currValue != null && currValue.equals(propValue));
2560 }
2561
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002562 /**
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002563 * This is a pre-density application which will get scaled - instead of being pixel perfect.
2564 * This type of application is not resizable.
2565 *
2566 * @param pkg The package which needs to be marked as unresizable.
2567 */
Winson Chungd3395382016-12-13 11:49:09 -08002568 private void adjustPackageToBeUnresizeableAndUnpipable(Package pkg) {
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002569 for (Activity a : pkg.activities) {
2570 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -08002571 a.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE;
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002572 }
2573 }
2574
2575 /**
Chad Brubakera58ce392018-10-29 14:14:22 -07002576
2577 /**
Narayan Kamath71fcc142019-01-15 18:20:39 +00002578 * Matches a given {@code targetCode} against a set of release codeNames. Target codes can
2579 * either be of the form {@code [codename]}" (e.g {@code "Q"}) or of the form
2580 * {@code [codename].[fingerprint]} (e.g {@code "Q.cafebc561"}).
2581 */
2582 private static boolean matchTargetCode(@NonNull String[] codeNames,
2583 @NonNull String targetCode) {
2584 final String targetCodeName;
2585 final int targetCodeIdx = targetCode.indexOf('.');
2586 if (targetCodeIdx == -1) {
2587 targetCodeName = targetCode;
2588 } else {
2589 targetCodeName = targetCode.substring(0, targetCodeIdx);
2590 }
2591 return ArrayUtils.contains(codeNames, targetCodeName);
2592 }
2593
2594 /**
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002595 * Computes the targetSdkVersion to use at runtime. If the package is not
2596 * compatible with this platform, populates {@code outError[0]} with an
2597 * error message.
2598 * <p>
2599 * If {@code targetCode} is not specified, e.g. the value is {@code null},
2600 * then the {@code targetVers} will be returned unmodified.
2601 * <p>
2602 * Otherwise, the behavior varies based on whether the current platform
2603 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2604 * has length > 0:
2605 * <ul>
2606 * <li>If this is a pre-release platform and the value specified by
2607 * {@code targetCode} is contained within the array of allowed pre-release
2608 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2609 * <li>If this is a released platform, this method will return -1 to
2610 * indicate that the package is not compatible with this platform.
2611 * </ul>
2612 *
2613 * @param targetVers targetSdkVersion number, if specified in the
2614 * application manifest, or 0 otherwise
2615 * @param targetCode targetSdkVersion code, if specified in the application
2616 * manifest, or {@code null} otherwise
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002617 * @param platformSdkCodenames array of allowed pre-release SDK codenames
2618 * for this platform
2619 * @param outError output array to populate with error, if applicable
2620 * @return the targetSdkVersion to use at runtime, or -1 if the package is
2621 * not compatible with this platform
2622 * @hide Exposed for unit testing only.
2623 */
2624 @TestApi
2625 public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002626 @Nullable String targetCode, @NonNull String[] platformSdkCodenames,
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +00002627 @NonNull String[] outError) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002628 // If it's a release SDK, return the version number unmodified.
2629 if (targetCode == null) {
2630 return targetVers;
2631 }
2632
2633 // If it's a pre-release SDK and the codename matches this platform, it
2634 // definitely targets this SDK.
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +00002635 if (matchTargetCode(platformSdkCodenames, targetCode)) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002636 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2637 }
2638
2639 // Otherwise, we're looking at an incompatible pre-release SDK.
2640 if (platformSdkCodenames.length > 0) {
2641 outError[0] = "Requires development platform " + targetCode
2642 + " (current platform is any of "
2643 + Arrays.toString(platformSdkCodenames) + ")";
2644 } else {
2645 outError[0] = "Requires development platform " + targetCode
2646 + " but this is a release platform.";
2647 }
2648 return -1;
2649 }
2650
2651 /**
2652 * Computes the minSdkVersion to use at runtime. If the package is not
2653 * compatible with this platform, populates {@code outError[0]} with an
2654 * error message.
2655 * <p>
2656 * If {@code minCode} is not specified, e.g. the value is {@code null},
2657 * then behavior varies based on the {@code platformSdkVersion}:
2658 * <ul>
2659 * <li>If the platform SDK version is greater than or equal to the
2660 * {@code minVers}, returns the {@code mniVers} unmodified.
2661 * <li>Otherwise, returns -1 to indicate that the package is not
2662 * compatible with this platform.
2663 * </ul>
2664 * <p>
2665 * Otherwise, the behavior varies based on whether the current platform
2666 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2667 * has length > 0:
2668 * <ul>
2669 * <li>If this is a pre-release platform and the value specified by
2670 * {@code targetCode} is contained within the array of allowed pre-release
2671 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2672 * <li>If this is a released platform, this method will return -1 to
2673 * indicate that the package is not compatible with this platform.
2674 * </ul>
2675 *
2676 * @param minVers minSdkVersion number, if specified in the application
2677 * manifest, or 1 otherwise
2678 * @param minCode minSdkVersion code, if specified in the application
2679 * manifest, or {@code null} otherwise
2680 * @param platformSdkVersion platform SDK version number, typically
2681 * Build.VERSION.SDK_INT
2682 * @param platformSdkCodenames array of allowed prerelease SDK codenames
2683 * for this platform
2684 * @param outError output array to populate with error, if applicable
2685 * @return the minSdkVersion to use at runtime, or -1 if the package is not
2686 * compatible with this platform
2687 * @hide Exposed for unit testing only.
2688 */
2689 @TestApi
2690 public static int computeMinSdkVersion(@IntRange(from = 1) int minVers,
2691 @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion,
2692 @NonNull String[] platformSdkCodenames, @NonNull String[] outError) {
2693 // If it's a release SDK, make sure we meet the minimum SDK requirement.
2694 if (minCode == null) {
2695 if (minVers <= platformSdkVersion) {
2696 return minVers;
2697 }
2698
2699 // We don't meet the minimum SDK requirement.
2700 outError[0] = "Requires newer sdk version #" + minVers
2701 + " (current version is #" + platformSdkVersion + ")";
2702 return -1;
2703 }
2704
2705 // If it's a pre-release SDK and the codename matches this platform, we
2706 // definitely meet the minimum SDK requirement.
Narayan Kamath71fcc142019-01-15 18:20:39 +00002707 if (matchTargetCode(platformSdkCodenames, minCode)) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002708 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2709 }
2710
2711 // Otherwise, we're looking at an incompatible pre-release SDK.
2712 if (platformSdkCodenames.length > 0) {
2713 outError[0] = "Requires development platform " + minCode
2714 + " (current platform is any of "
2715 + Arrays.toString(platformSdkCodenames) + ")";
2716 } else {
2717 outError[0] = "Requires development platform " + minCode
2718 + " but this is a release platform.";
2719 }
2720 return -1;
2721 }
2722
Todd Kennedy27c24fb2015-09-17 16:49:25 -07002723 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002724 FeatureInfo fi = new FeatureInfo();
2725 TypedArray sa = res.obtainAttributes(attrs,
2726 com.android.internal.R.styleable.AndroidManifestUsesFeature);
2727 // Note: don't allow this value to be a reference to a resource
2728 // that may change.
2729 fi.name = sa.getNonResourceString(
2730 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
Jeff Sharkey115d2c12016-02-15 17:25:57 -07002731 fi.version = sa.getInt(
2732 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002733 if (fi.name == null) {
2734 fi.reqGlEsVersion = sa.getInt(
2735 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
2736 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2737 }
2738 if (sa.getBoolean(
2739 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
2740 fi.flags |= FeatureInfo.FLAG_REQUIRED;
2741 }
2742 sa.recycle();
2743 return fi;
2744 }
2745
Svet Ganov67882122016-12-11 16:36:34 -08002746 private boolean parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser,
2747 String[] outError) throws XmlPullParserException, IOException {
2748 TypedArray sa = res.obtainAttributes(parser,
2749 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary);
2750
2751 // Note: don't allow this value to be a reference to a resource that may change.
2752 String lname = sa.getNonResourceString(
2753 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
2754 final int version = sa.getInt(
2755 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002756 String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable
Svet Ganov67882122016-12-11 16:36:34 -08002757 .AndroidManifestUsesStaticLibrary_certDigest);
2758 sa.recycle();
2759
2760 // Since an APK providing a static shared lib can only provide the lib - fail if malformed
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002761 if (lname == null || version < 0 || certSha256Digest == null) {
Svet Ganov67882122016-12-11 16:36:34 -08002762 outError[0] = "Bad uses-static-library declaration name: " + lname + " version: "
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002763 + version + " certDigest" + certSha256Digest;
Svet Ganov67882122016-12-11 16:36:34 -08002764 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2765 XmlUtils.skipCurrentTag(parser);
2766 return false;
2767 }
2768
2769 // Can depend only on one version of the same library
2770 if (pkg.usesStaticLibraries != null && pkg.usesStaticLibraries.contains(lname)) {
2771 outError[0] = "Depending on multiple versions of static library " + lname;
2772 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2773 XmlUtils.skipCurrentTag(parser);
2774 return false;
2775 }
2776
2777 lname = lname.intern();
2778 // We allow ":" delimiters in the SHA declaration as this is the format
2779 // emitted by the certtool making it easy for developers to copy/paste.
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002780 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2781
2782 // Fot apps targeting O-MR1 we require explicit enumeration of all certs.
2783 String[] additionalCertSha256Digests = EmptyArray.STRING;
Jeff Sharkeyaa1a9112018-04-10 15:18:12 -06002784 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O_MR1) {
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002785 additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError);
2786 if (additionalCertSha256Digests == null) {
2787 return false;
2788 }
2789 } else {
2790 XmlUtils.skipCurrentTag(parser);
2791 }
2792
2793 final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1];
2794 certSha256Digests[0] = certSha256Digest;
2795 System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
2796 1, additionalCertSha256Digests.length);
2797
Svet Ganov67882122016-12-11 16:36:34 -08002798 pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname);
Dianne Hackborn3accca02013-09-20 09:32:11 -07002799 pkg.usesStaticLibrariesVersions = ArrayUtils.appendLong(
Svet Ganov8a10ef52017-02-16 20:58:09 -08002800 pkg.usesStaticLibrariesVersions, version, true);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002801 pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
2802 pkg.usesStaticLibrariesCertDigests, certSha256Digests, true);
Svet Ganov67882122016-12-11 16:36:34 -08002803
2804 return true;
2805 }
2806
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002807 private String[] parseAdditionalCertificates(Resources resources, XmlResourceParser parser,
2808 String[] outError) throws XmlPullParserException, IOException {
2809 String[] certSha256Digests = EmptyArray.STRING;
2810
2811 int outerDepth = parser.getDepth();
2812 int type;
2813 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2814 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2815 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2816 continue;
2817 }
2818
2819 final String nodeName = parser.getName();
2820 if (nodeName.equals("additional-certificate")) {
2821 final TypedArray sa = resources.obtainAttributes(parser, com.android.internal.
2822 R.styleable.AndroidManifestAdditionalCertificate);
2823 String certSha256Digest = sa.getNonResourceString(com.android.internal.
2824 R.styleable.AndroidManifestAdditionalCertificate_certDigest);
2825 sa.recycle();
2826
2827 if (TextUtils.isEmpty(certSha256Digest)) {
2828 outError[0] = "Bad additional-certificate declaration with empty"
2829 + " certDigest:" + certSha256Digest;
2830 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2831 XmlUtils.skipCurrentTag(parser);
2832 sa.recycle();
2833 return null;
2834 }
2835
2836 // We allow ":" delimiters in the SHA declaration as this is the format
2837 // emitted by the certtool making it easy for developers to copy/paste.
2838 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2839 certSha256Digests = ArrayUtils.appendElement(String.class,
2840 certSha256Digests, certSha256Digest);
2841 } else {
2842 XmlUtils.skipCurrentTag(parser);
2843 }
2844 }
2845
2846 return certSha256Digests;
2847 }
2848
Chad Brubakere2107312019-02-04 12:30:01 -08002849 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
2850 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002851 TypedArray sa = res.obtainAttributes(parser,
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002852 com.android.internal.R.styleable.AndroidManifestUsesPermission);
2853
2854 // Note: don't allow this value to be a reference to a resource
2855 // that may change.
2856 String name = sa.getNonResourceString(
2857 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002858
Christopher Tatefb0676a2013-09-16 16:34:52 -07002859 int maxSdkVersion = 0;
2860 TypedValue val = sa.peekValue(
2861 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
2862 if (val != null) {
2863 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
2864 maxSdkVersion = val.data;
2865 }
2866 }
2867
Dianne Hackborncd154e92017-02-28 17:37:35 -08002868 final String requiredFeature = sa.getNonConfigurationString(
2869 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
2870
2871 final String requiredNotfeature = sa.getNonConfigurationString(
2872 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
2873
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002874 sa.recycle();
2875
Dianne Hackborncd154e92017-02-28 17:37:35 -08002876 XmlUtils.skipCurrentTag(parser);
2877
2878 if (name == null) {
2879 return true;
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002880 }
2881
Dianne Hackborncd154e92017-02-28 17:37:35 -08002882 if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
2883 return true;
2884 }
2885
2886 // Only allow requesting this permission if the platform supports the given feature.
2887 if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
2888 return true;
2889 }
2890
2891 // Only allow requesting this permission if the platform doesn't support the given feature.
2892 if (requiredNotfeature != null && mCallback != null
2893 && mCallback.hasFeature(requiredNotfeature)) {
2894 return true;
2895 }
2896
2897 int index = pkg.requestedPermissions.indexOf(name);
2898 if (index == -1) {
2899 pkg.requestedPermissions.add(name.intern());
2900 } else {
2901 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
2902 + name + " in package: " + pkg.packageName + " at: "
2903 + parser.getPositionDescription());
2904 }
2905
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002906 return true;
2907 }
2908
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002909 private static String buildClassName(String pkg, CharSequence clsSeq,
2910 String[] outError) {
2911 if (clsSeq == null || clsSeq.length() <= 0) {
2912 outError[0] = "Empty class name in package " + pkg;
2913 return null;
2914 }
2915 String cls = clsSeq.toString();
2916 char c = cls.charAt(0);
2917 if (c == '.') {
Narayan Kamath07ac1442017-02-10 15:08:07 +00002918 return pkg + cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002919 }
2920 if (cls.indexOf('.') < 0) {
2921 StringBuilder b = new StringBuilder(pkg);
2922 b.append('.');
2923 b.append(cls);
Narayan Kamath07ac1442017-02-10 15:08:07 +00002924 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002925 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002926 return cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002927 }
2928
2929 private static String buildCompoundName(String pkg,
2930 CharSequence procSeq, String type, String[] outError) {
2931 String proc = procSeq.toString();
2932 char c = proc.charAt(0);
2933 if (pkg != null && c == ':') {
2934 if (proc.length() < 2) {
2935 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
2936 + ": must be at least two characters";
2937 return null;
2938 }
2939 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002940 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 if (nameError != null) {
2942 outError[0] = "Invalid " + type + " name " + proc + " in package "
2943 + pkg + ": " + nameError;
2944 return null;
2945 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002946 return pkg + proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002947 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002948 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002949 if (nameError != null && !"system".equals(proc)) {
2950 outError[0] = "Invalid " + type + " name " + proc + " in package "
2951 + pkg + ": " + nameError;
2952 return null;
2953 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002954 return proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002955 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002957 private static String buildProcessName(String pkg, String defProc,
2958 CharSequence procSeq, int flags, String[] separateProcesses,
2959 String[] outError) {
2960 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
2961 return defProc != null ? defProc : pkg;
2962 }
2963 if (separateProcesses != null) {
2964 for (int i=separateProcesses.length-1; i>=0; i--) {
2965 String sp = separateProcesses[i];
2966 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
2967 return pkg;
2968 }
2969 }
2970 }
2971 if (procSeq == null || procSeq.length() <= 0) {
2972 return defProc;
2973 }
Makoto Onuki812d188a2017-08-07 09:58:23 -07002974 return TextUtils.safeIntern(buildCompoundName(pkg, procSeq, "process", outError));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002975 }
2976
2977 private static String buildTaskAffinityName(String pkg, String defProc,
2978 CharSequence procSeq, String[] outError) {
2979 if (procSeq == null) {
2980 return defProc;
2981 }
2982 if (procSeq.length() <= 0) {
2983 return null;
2984 }
2985 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
2986 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002987
dcashman989eb3712014-06-17 12:56:12 -07002988 private boolean parseKeySets(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002989 XmlResourceParser parser, String[] outError)
Geremy Condraf1bcca82013-01-07 22:35:24 -08002990 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07002991 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08002992 // all the keys and keysets that we want must be defined here
2993 // so we're going to iterate over the parser and pull out the things we want
2994 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07002995 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002996 int type;
dcashman989eb3712014-06-17 12:56:12 -07002997 String currentKeySet = null;
2998 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
2999 ArraySet<String> upgradeKeySets = new ArraySet<String>();
3000 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
3001 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08003002 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3003 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
3004 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07003005 if (parser.getDepth() == currentKeySetDepth) {
3006 currentKeySet = null;
3007 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07003008 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003009 continue;
3010 }
dcashman989eb3712014-06-17 12:56:12 -07003011 String tagName = parser.getName();
3012 if (tagName.equals("key-set")) {
3013 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07003014 outError[0] = "Improperly nested 'key-set' tag at "
3015 + parser.getPositionDescription();
3016 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003017 return false;
3018 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08003019 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003020 com.android.internal.R.styleable.AndroidManifestKeySet);
3021 final String keysetName = sa.getNonResourceString(
3022 com.android.internal.R.styleable.AndroidManifestKeySet_name);
3023 definedKeySets.put(keysetName, new ArraySet<String>());
3024 currentKeySet = keysetName;
3025 currentKeySetDepth = parser.getDepth();
3026 sa.recycle();
3027 } else if (tagName.equals("public-key")) {
3028 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07003029 outError[0] = "Improperly nested 'key-set' tag at "
3030 + parser.getPositionDescription();
3031 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003032 return false;
3033 }
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.AndroidManifestPublicKey);
3036 final String publicKeyName = sa.getNonResourceString(
3037 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003038 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07003039 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
3040 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07003041 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
3042 + " on first use at " + parser.getPositionDescription();
3043 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07003044 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003045 return false;
3046 } else if (encodedKey != null) {
3047 PublicKey currentKey = parsePublicKey(encodedKey);
3048 if (currentKey == null) {
3049 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
3050 + parser.getPositionDescription() + " key-set " + currentKeySet
3051 + " will not be added to the package's defined key-sets.");
3052 sa.recycle();
3053 improperKeySets.add(currentKeySet);
3054 XmlUtils.skipCurrentTag(parser);
3055 continue;
3056 }
3057 if (publicKeys.get(publicKeyName) == null
3058 || publicKeys.get(publicKeyName).equals(currentKey)) {
3059
3060 /* public-key first definition, or matches old definition */
3061 publicKeys.put(publicKeyName, currentKey);
3062 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003063 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07003064 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07003065 + parser.getPositionDescription();
3066 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003067 sa.recycle();
3068 return false;
3069 }
Kenny Root37dca152013-07-10 14:01:49 -07003070 }
dcashman989eb3712014-06-17 12:56:12 -07003071 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003072 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003073 XmlUtils.skipCurrentTag(parser);
3074 } else if (tagName.equals("upgrade-key-set")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003075 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003076 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
3077 String name = sa.getNonResourceString(
3078 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
3079 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003080 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003081 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003082 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07003083 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003084 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07003085 + parser.getPositionDescription();
3086 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003087 return false;
3088 } else {
dcashman989eb3712014-06-17 12:56:12 -07003089 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003090 + " at " + mArchiveSourcePath + " "
3091 + parser.getPositionDescription());
3092 XmlUtils.skipCurrentTag(parser);
3093 continue;
3094 }
3095 }
dcashman989eb3712014-06-17 12:56:12 -07003096 Set<String> publicKeyNames = publicKeys.keySet();
3097 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07003098 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
3099 + "'key-set' and 'public-key' names must be distinct.";
3100 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003101 return false;
3102 }
3103 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
3104 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
3105 final String keySetName = e.getKey();
3106 if (e.getValue().size() == 0) {
3107 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3108 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
3109 + " Not including in package's defined key-sets.");
3110 continue;
3111 } else if (improperKeySets.contains(keySetName)) {
3112 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3113 + "'key-set' " + keySetName + " contained improper 'public-key'"
3114 + " tags. Not including in package's defined key-sets.");
3115 continue;
3116 }
3117 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
3118 for (String s : e.getValue()) {
3119 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08003120 }
3121 }
dcashman989eb3712014-06-17 12:56:12 -07003122 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
3123 owner.mUpgradeKeySets = upgradeKeySets;
3124 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003125 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
3126 + "does not define all 'upgrade-key-set's .";
3127 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003128 return false;
3129 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003130 return true;
3131 }
3132
Dianne Hackborncd154e92017-02-28 17:37:35 -08003133 private boolean parsePermissionGroup(Package owner, int flags, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003134 XmlResourceParser parser, String[] outError)
3135 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003136 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003137 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
Philip P. Moltmann0635dab2019-03-02 11:19:03 -08003138
3139 int requestDetailResourceId = sa.getResourceId(
3140 com.android.internal.R.styleable.AndroidManifestPermissionGroup_requestDetail, 0);
3141 int backgroundRequestResourceId = sa.getResourceId(
3142 com.android.internal.R.styleable.AndroidManifestPermissionGroup_backgroundRequest,
3143 0);
3144 int backgroundRequestDetailResourceId = sa.getResourceId(
3145 com.android.internal.R.styleable
3146 .AndroidManifestPermissionGroup_backgroundRequestDetail, 0);
3147
3148 PermissionGroup perm = new PermissionGroup(owner, requestDetailResourceId,
3149 backgroundRequestResourceId, backgroundRequestDetailResourceId);
3150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003151 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003152 "<permission-group>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003153 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
3154 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003155 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003156 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003157 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
3158 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003159 sa.recycle();
3160 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003161 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 }
3163
3164 perm.info.descriptionRes = sa.getResourceId(
3165 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
3166 0);
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003167 perm.info.requestRes = sa.getResourceId(
3168 com.android.internal.R.styleable.AndroidManifestPermissionGroup_request, 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07003169 perm.info.flags = sa.getInt(
3170 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07003171 perm.info.priority = sa.getInt(
3172 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003173
3174 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003175
Svet Ganov354cd3c2015-12-17 11:35:04 -08003176 if (!parseAllMetaData(res, parser, "<permission-group>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003177 outError)) {
3178 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003179 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180 }
3181
3182 owner.permissionGroups.add(perm);
3183
Dianne Hackborncd154e92017-02-28 17:37:35 -08003184 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003185 }
3186
Dianne Hackborncd154e92017-02-28 17:37:35 -08003187 private boolean parsePermission(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003188 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003189 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003190
Svet Ganov354cd3c2015-12-17 11:35:04 -08003191 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003192 com.android.internal.R.styleable.AndroidManifestPermission);
3193
Philip P. Moltmanna4844d12019-03-02 10:17:23 -08003194 String backgroundPermission = null;
3195 if (sa.hasValue(
3196 com.android.internal.R.styleable.AndroidManifestPermission_backgroundPermission)) {
3197 if ("android".equals(owner.packageName)) {
3198 backgroundPermission = sa.getNonResourceString(
3199 com.android.internal.R.styleable
3200 .AndroidManifestPermission_backgroundPermission);
3201 } else {
3202 Slog.w(TAG, owner.packageName + " defines a background permission. Only the "
3203 + "'android' package can do that.");
3204 }
3205 }
3206
3207 Permission perm = new Permission(owner, backgroundPermission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003208 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003209 "<permission>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003210 com.android.internal.R.styleable.AndroidManifestPermission_name,
3211 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003212 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003213 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003214 com.android.internal.R.styleable.AndroidManifestPermission_logo,
3215 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003216 sa.recycle();
3217 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003218 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003219 }
3220
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003221 // Note: don't allow this value to be a reference to a resource
3222 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003223 perm.info.group = sa.getNonResourceString(
3224 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
3225 if (perm.info.group != null) {
3226 perm.info.group = perm.info.group.intern();
3227 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003229 perm.info.descriptionRes = sa.getResourceId(
3230 com.android.internal.R.styleable.AndroidManifestPermission_description,
3231 0);
3232
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003233 perm.info.requestRes = sa.getResourceId(
3234 com.android.internal.R.styleable.AndroidManifestPermission_request, 0);
3235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003236 perm.info.protectionLevel = sa.getInt(
3237 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
3238 PermissionInfo.PROTECTION_NORMAL);
3239
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07003240 perm.info.flags = sa.getInt(
3241 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
3242
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003243 // For now only platform runtime permissions can be restricted
3244 if (!perm.info.isRuntime() || !"android".equals(perm.info.packageName)) {
3245 perm.info.flags &= ~PermissionInfo.FLAG_HARD_RESTRICTED;
3246 perm.info.flags &= ~PermissionInfo.FLAG_SOFT_RESTRICTED;
3247 } else {
3248 // The platform does not get to specify conflicting permissions
3249 if ((perm.info.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0
3250 && (perm.info.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0) {
3251 throw new IllegalStateException("Permission cannot be both soft and hard"
3252 + " restricted: " + perm.info.name);
3253 }
3254 }
3255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003256 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08003257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 if (perm.info.protectionLevel == -1) {
3259 outError[0] = "<permission> does not specify protectionLevel";
3260 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003261 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003262 }
Dianne Hackborne639da72012-02-21 15:11:13 -08003263
3264 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
3265
Makoto Onuki700feef2018-02-15 10:59:41 -08003266 if (perm.info.getProtectionFlags() != 0) {
Todd Kennedyc247fa12017-06-02 10:29:22 -07003267 if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_INSTANT) == 0
Chad Brubakera5d70a12017-03-23 11:04:50 -07003268 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0
Chad Brubakerc19706a2016-10-13 15:44:59 -07003269 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
Dianne Hackborne639da72012-02-21 15:11:13 -08003270 PermissionInfo.PROTECTION_SIGNATURE) {
Joe Maples39bb9e82018-01-11 11:09:46 -05003271 outError[0] = "<permission> protectionLevel specifies a non-instant flag but is "
Dianne Hackborne639da72012-02-21 15:11:13 -08003272 + "not based on signature type";
3273 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003274 return false;
Dianne Hackborne639da72012-02-21 15:11:13 -08003275 }
3276 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003277
Svet Ganov354cd3c2015-12-17 11:35:04 -08003278 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003279 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003280 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003281 }
3282
3283 owner.permissions.add(perm);
3284
Dianne Hackborncd154e92017-02-28 17:37:35 -08003285 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003286 }
3287
Dianne Hackborncd154e92017-02-28 17:37:35 -08003288 private boolean parsePermissionTree(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003289 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003290 throws XmlPullParserException, IOException {
Philip P. Moltmanna4844d12019-03-02 10:17:23 -08003291 Permission perm = new Permission(owner, (String) null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003292
Svet Ganov354cd3c2015-12-17 11:35:04 -08003293 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 com.android.internal.R.styleable.AndroidManifestPermissionTree);
3295
3296 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003297 "<permission-tree>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003298 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
3299 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003300 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003301 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003302 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
3303 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003304 sa.recycle();
3305 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003306 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003307 }
3308
3309 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003311 int index = perm.info.name.indexOf('.');
3312 if (index > 0) {
3313 index = perm.info.name.indexOf('.', index+1);
3314 }
3315 if (index < 0) {
3316 outError[0] = "<permission-tree> name has less than three segments: "
3317 + perm.info.name;
3318 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003319 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003320 }
3321
3322 perm.info.descriptionRes = 0;
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003323 perm.info.requestRes = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
3325 perm.tree = true;
3326
Svet Ganov354cd3c2015-12-17 11:35:04 -08003327 if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003328 outError)) {
3329 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003330 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003331 }
3332
3333 owner.permissions.add(perm);
3334
Dianne Hackborncd154e92017-02-28 17:37:35 -08003335 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003336 }
3337
3338 private Instrumentation parseInstrumentation(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003339 XmlResourceParser parser, String[] outError)
3340 throws XmlPullParserException, IOException {
3341 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 com.android.internal.R.styleable.AndroidManifestInstrumentation);
3343
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003344 if (mParseInstrumentationArgs == null) {
3345 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
3346 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
3347 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003348 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003349 com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003350 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
3351 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003352 mParseInstrumentationArgs.tag = "<instrumentation>";
3353 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003354
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003355 mParseInstrumentationArgs.sa = sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003356
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003357 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
3358 new InstrumentationInfo());
3359 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003360 sa.recycle();
3361 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3362 return null;
3363 }
3364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003366 // Note: don't allow this value to be a reference to a resource
3367 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 str = sa.getNonResourceString(
3369 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
3370 a.info.targetPackage = str != null ? str.intern() : null;
3371
Dianne Hackborn34041732017-01-31 15:27:13 -08003372 str = sa.getNonResourceString(
Dianne Hackborn1be53542017-04-28 13:36:00 -07003373 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcesses);
3374 a.info.targetProcesses = str != null ? str.intern() : null;
Dianne Hackborn34041732017-01-31 15:27:13 -08003375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003376 a.info.handleProfiling = sa.getBoolean(
3377 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
3378 false);
3379
3380 a.info.functionalTest = sa.getBoolean(
3381 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
3382 false);
3383
3384 sa.recycle();
3385
3386 if (a.info.targetPackage == null) {
3387 outError[0] = "<instrumentation> does not specify targetPackage";
3388 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3389 return null;
3390 }
3391
Svet Ganov354cd3c2015-12-17 11:35:04 -08003392 if (!parseAllMetaData(res, parser, "<instrumentation>", a,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003393 outError)) {
3394 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3395 return null;
3396 }
3397
3398 owner.instrumentation.add(a);
3399
3400 return a;
3401 }
3402
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003403 /**
3404 * Parse the {@code application} XML tree at the current parse location in a
3405 * <em>base APK</em> manifest.
3406 * <p>
3407 * When adding new features, carefully consider if they should also be
3408 * supported by split APKs.
3409 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01003410 @UnsupportedAppUsage
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003411 private boolean parseBaseApplication(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003412 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003413 throws XmlPullParserException, IOException {
3414 final ApplicationInfo ai = owner.applicationInfo;
3415 final String pkgName = owner.applicationInfo.packageName;
3416
Svet Ganov354cd3c2015-12-17 11:35:04 -08003417 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003418 com.android.internal.R.styleable.AndroidManifestApplication);
3419
Hyunyoung Song929de7a2019-03-21 23:51:27 -07003420 ai.iconRes = sa.getResourceId(
3421 com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
3422 ai.roundIconRes = sa.getResourceId(
3423 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon, 0);
3424
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003425 if (!parsePackageItemInfo(owner, ai, outError,
3426 "<application>", sa, false /*nameRequired*/,
3427 com.android.internal.R.styleable.AndroidManifestApplication_name,
3428 com.android.internal.R.styleable.AndroidManifestApplication_label,
3429 com.android.internal.R.styleable.AndroidManifestApplication_icon,
3430 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
3431 com.android.internal.R.styleable.AndroidManifestApplication_logo,
3432 com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
3433 sa.recycle();
3434 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3435 return false;
3436 }
3437
3438 if (ai.name != null) {
Todd Kennedyafb52692016-08-22 15:44:00 -07003439 ai.className = ai.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 }
3441
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003442 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003443 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
3444 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003445 if (manageSpaceActivity != null) {
3446 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
3447 outError);
3448 }
3449
Christopher Tate181fafa2009-05-14 11:12:14 -07003450 boolean allowBackup = sa.getBoolean(
3451 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
3452 if (allowBackup) {
3453 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07003454
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003455 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
3456 // and restoreAnyVersion are only relevant if backup is possible for the
3457 // given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003458 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003459 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
3460 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07003461 if (backupAgent != null) {
3462 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07003463 if (DEBUG_BACKUP) {
3464 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003465 + " from " + pkgName + "+" + backupAgent);
3466 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003467
3468 if (sa.getBoolean(
3469 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
3470 true)) {
3471 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
3472 }
3473 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08003474 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
3475 false)) {
3476 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
3477 }
Christopher Tated1de2562014-06-17 17:12:35 -07003478 if (sa.getBoolean(
3479 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
3480 false)) {
3481 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
3482 }
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003483 if (sa.getBoolean(
3484 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
3485 false)) {
3486 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
3487 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003488 }
Matthew Williams303650c2015-04-17 18:22:51 -07003489
3490 TypedValue v = sa.peekValue(
3491 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
3492 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
3493 if (DEBUG_BACKUP) {
3494 Slog.v(TAG, "fullBackupContent specified as boolean=" +
3495 (v.data == 0 ? "false" : "true"));
3496 }
3497 // "false" => -1, "true" => 0
3498 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
3499 }
3500 if (DEBUG_BACKUP) {
3501 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
3502 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003503 }
Christopher Tate4a627c72011-04-01 14:43:32 -07003504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003505 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08003506 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 ai.descriptionRes = sa.getResourceId(
3508 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
3509
Todd Kennedy232d29e2017-11-06 14:45:53 -08003510 if (sa.getBoolean(
3511 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
3512 false)) {
3513 // Check if persistence is based on a feature being present
3514 final String requiredFeature = sa.getNonResourceString(com.android.internal.R.styleable
3515 .AndroidManifestApplication_persistentWhenFeatureAvailable);
3516 if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
3517 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003518 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07003519 }
3520
3521 if (sa.getBoolean(
3522 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
3523 false)) {
3524 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07003525 }
3526
3527 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
3528 .AndroidManifestApplication_restrictedAccountType);
3529 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
3530 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003531 }
3532
Amith Yamasaniccbe3892013-04-12 17:52:42 -07003533 String requiredAccountType = sa.getString(com.android.internal.R.styleable
3534 .AndroidManifestApplication_requiredAccountType);
3535 if (requiredAccountType != null && requiredAccountType.length() > 0) {
3536 owner.mRequiredAccountType = requiredAccountType;
3537 }
3538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003539 if (sa.getBoolean(
3540 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
3541 false)) {
3542 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
Chris Craikce030282018-10-16 14:33:11 -07003543 // Debuggable implies profileable
3544 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003545 }
3546
3547 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07003548 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08003549 false)) {
3550 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
3551 }
3552
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003553 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07003554 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07003555 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07003556 if (owner.baseHardwareAccelerated) {
3557 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
3558 }
Romain Guy812ccbe2010-06-01 14:07:24 -07003559
3560 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003561 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
3562 true)) {
3563 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
3564 }
3565
3566 if (sa.getBoolean(
3567 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
3568 false)) {
3569 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
3570 }
3571
3572 if (sa.getBoolean(
3573 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
3574 true)) {
3575 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
3576 }
3577
Svet Ganov354cd3c2015-12-17 11:35:04 -08003578 // The parent package controls installation, hence specify test only installs.
3579 if (owner.parentPackage == null) {
3580 if (sa.getBoolean(
3581 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
3582 false)) {
3583 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
3584 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003585 }
3586
Jason parksa3cdaa52011-01-13 14:15:43 -06003587 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003588 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06003589 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003590 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06003591 }
3592
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003593 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07003594 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
Chad Brubaker0d285d52018-03-14 09:00:04 -07003595 owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.P)) {
Alex Klyubin01a959d2015-03-18 10:05:45 -07003596 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
3597 }
3598
3599 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003600 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
3601 false /* default is no RTL support*/)) {
3602 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
3603 }
3604
Narayan Kamath589a1bc2014-07-03 14:43:26 +01003605 if (sa.getBoolean(
3606 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
3607 false)) {
3608 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
3609 }
3610
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07003611 if (sa.getBoolean(
3612 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
Victor Hsieh0faa8012019-03-11 10:00:54 -07003613 true)) {
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07003614 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
3615 }
3616
Todd Kennedyd022ac22016-04-13 10:49:29 -07003617 if (sa.getBoolean(
Victor Hsiehfa9df0b2019-01-29 12:48:36 -08003618 R.styleable.AndroidManifestApplication_useEmbeddedDex,
Victor Hsiehe7b5a8d2018-11-16 10:27:06 -08003619 false)) {
Victor Hsiehfa9df0b2019-01-29 12:48:36 -08003620 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX;
Victor Hsiehe7b5a8d2018-11-16 10:27:06 -08003621 }
3622
3623 if (sa.getBoolean(
Todd Kennedyd022ac22016-04-13 10:49:29 -07003624 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
3625 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003626 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003627 }
Todd Kennedyd022ac22016-04-13 10:49:29 -07003628 if (sa.getBoolean(
3629 R.styleable.AndroidManifestApplication_directBootAware,
3630 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003631 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003632 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003633
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003634 if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
3635 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003636 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
3637 } else {
3638 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003639 }
3640 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003641 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwale6afdf912016-01-30 13:01:33 -08003642 }
3643
Ruslan Tkhakokhov75674852019-01-22 13:35:00 +00003644 if (sa.getBoolean(
3645 com.android.internal.R.styleable
3646 .AndroidManifestApplication_allowClearUserDataOnFailedRestore,
3647 true)) {
3648 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE;
3649 }
3650
Kevin Rocardf91d50b2019-02-21 14:32:46 -08003651 if (sa.getBoolean(
3652 R.styleable.AndroidManifestApplication_allowAudioPlaybackCapture,
3653 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q)) {
3654 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE;
3655 }
3656
Jeff Sharkeybcff13c2019-03-28 14:29:35 -06003657 if (sa.getBoolean(
Svet Ganovd563e932019-04-14 13:07:41 -07003658 R.styleable.AndroidManifestApplication_requestLegacyExternalStorage,
3659 owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.Q)) {
3660 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE;
Jeff Sharkeybcff13c2019-03-28 14:29:35 -06003661 }
3662
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07003663 ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
Adrian Roos917791e2018-11-28 16:30:44 +01003664 ai.minAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_minAspectRatio, 0);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07003665
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003666 ai.networkSecurityConfigRes = sa.getResourceId(
3667 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
3668 0);
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07003669 ai.category = sa.getInt(
3670 com.android.internal.R.styleable.AndroidManifestApplication_appCategory,
3671 ApplicationInfo.CATEGORY_UNDEFINED);
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003673 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003674 str = sa.getNonConfigurationString(
3675 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003676 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
3677
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003678 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3679 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003680 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
3681 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003682 } else {
3683 // Some older apps have been seen to use a resource reference
3684 // here that on older builds was ignored (with a warning). We
3685 // need to continue to do this for them so they don't break.
3686 str = sa.getNonResourceString(
3687 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
3688 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003689 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
3690 str, outError);
Jason Monka80bfb52017-11-16 17:15:37 -05003691 String factory = sa.getNonResourceString(
3692 com.android.internal.R.styleable.AndroidManifestApplication_appComponentFactory);
3693 if (factory != null) {
3694 ai.appComponentFactory = buildClassName(ai.packageName, factory, outError);
3695 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003696
David Brazdila5b4df22018-09-06 09:49:14 +01003697 if (sa.getBoolean(
3698 com.android.internal.R.styleable.AndroidManifestApplication_usesNonSdkApi, false)) {
3699 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API;
3700 }
David Brazdil787b6f22a2018-08-28 12:55:56 +01003701
Philip P. Moltmannae4a4b92018-12-12 11:28:57 -08003702 if (sa.getBoolean(
3703 com.android.internal.R.styleable.AndroidManifestApplication_hasFragileUserData,
3704 false)) {
3705 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA;
3706 }
3707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003708 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003709 CharSequence pname;
3710 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3711 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003712 com.android.internal.R.styleable.AndroidManifestApplication_process,
3713 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003714 } else {
3715 // Some older apps have been seen to use a resource reference
3716 // here that on older builds was ignored (with a warning). We
3717 // need to continue to do this for them so they don't break.
3718 pname = sa.getNonResourceString(
3719 com.android.internal.R.styleable.AndroidManifestApplication_process);
3720 }
3721 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003722 flags, mSeparateProcesses, outError);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003723
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003724 ai.enabled = sa.getBoolean(
3725 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003726
Jose Lima12d0b4c2014-03-14 16:55:12 -07003727 if (sa.getBoolean(
3728 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
3729 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
3730 }
3731
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003732 if (sa.getBoolean(
3733 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
3734 false)) {
3735 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07003736
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003737 // A heavy-weight application can not be in a custom process.
3738 // We can do direct compare because we intern all strings.
3739 if (ai.processName != null && !ai.processName.equals(ai.packageName)) {
3740 outError[0] = "cantSaveState applications can not use custom processes";
Dianne Hackborn860755f2010-06-03 18:47:52 -07003741 }
3742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003743 }
3744
Adam Powell269248d2011-08-02 10:26:54 -07003745 ai.uiOptions = sa.getInt(
3746 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
3747
Narayan Kamath96c11c52017-08-09 13:07:21 +01003748 ai.classLoaderName = sa.getString(
3749 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3750 if (ai.classLoaderName != null
3751 && !ClassLoaderFactory.isValidClassLoaderName(ai.classLoaderName)) {
3752 outError[0] = "Invalid class loader name: " + ai.classLoaderName;
3753 }
3754
Martijn Coenenfb7caa92019-01-29 11:45:56 +01003755 ai.zygotePreloadName = sa.getString(
3756 com.android.internal.R.styleable.AndroidManifestApplication_zygotePreloadName);
3757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003758 sa.recycle();
3759
3760 if (outError[0] != null) {
3761 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3762 return false;
3763 }
3764
3765 final int innerDepth = parser.getDepth();
Garrett Boyer52136662017-05-23 13:47:58 -07003766 // IMPORTANT: These must only be cached for a single <application> to avoid components
3767 // getting added to the wrong package.
3768 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003769 int type;
Todd Kennedy6d418b62018-02-22 14:15:18 -08003770 boolean hasActivityOrder = false;
3771 boolean hasReceiverOrder = false;
3772 boolean hasServiceOrder = false;
Kenny Rootd2d29252011-08-08 11:27:57 -07003773 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3774 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3775 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003776 continue;
3777 }
3778
3779 String tagName = parser.getName();
3780 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003781 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003782 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 if (a == null) {
3784 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3785 return false;
3786 }
3787
Todd Kennedy6d418b62018-02-22 14:15:18 -08003788 hasActivityOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003789 owner.activities.add(a);
3790
3791 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003792 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3793 true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 if (a == null) {
3795 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3796 return false;
3797 }
3798
Todd Kennedy6d418b62018-02-22 14:15:18 -08003799 hasReceiverOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800 owner.receivers.add(a);
3801
3802 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003803 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 if (s == null) {
3805 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3806 return false;
3807 }
3808
Todd Kennedy6d418b62018-02-22 14:15:18 -08003809 hasServiceOrder |= (s.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 owner.services.add(s);
3811
3812 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003813 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 if (p == null) {
3815 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3816 return false;
3817 }
3818
3819 owner.providers.add(p);
3820
3821 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003822 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003823 if (a == null) {
3824 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3825 return false;
3826 }
3827
Todd Kennedy6d418b62018-02-22 14:15:18 -08003828 hasActivityOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003829 owner.activities.add(a);
3830
3831 } else if (parser.getName().equals("meta-data")) {
3832 // note: application meta-data is stored off to the side, so it can
3833 // remain null in the primary copy (we like to avoid extra copies because
3834 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003835 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003836 outError)) == null) {
3837 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3838 return false;
3839 }
Svet Ganov67882122016-12-11 16:36:34 -08003840 } else if (tagName.equals("static-library")) {
3841 sa = res.obtainAttributes(parser,
3842 com.android.internal.R.styleable.AndroidManifestStaticLibrary);
3843
3844 // Note: don't allow this value to be a reference to a resource
3845 // that may change.
3846 final String lname = sa.getNonResourceString(
3847 com.android.internal.R.styleable.AndroidManifestStaticLibrary_name);
3848 final int version = sa.getInt(
3849 com.android.internal.R.styleable.AndroidManifestStaticLibrary_version, -1);
Dianne Hackborn3accca02013-09-20 09:32:11 -07003850 final int versionMajor = sa.getInt(
3851 com.android.internal.R.styleable.AndroidManifestStaticLibrary_versionMajor,
3852 0);
Svet Ganov67882122016-12-11 16:36:34 -08003853
3854 sa.recycle();
3855
3856 // Since the app canot run without a static lib - fail if malformed
3857 if (lname == null || version < 0) {
3858 outError[0] = "Bad static-library declaration name: " + lname
3859 + " version: " + version;
3860 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3861 XmlUtils.skipCurrentTag(parser);
3862 return false;
3863 }
3864
3865 if (owner.mSharedUserId != null) {
3866 outError[0] = "sharedUserId not allowed in static shared library";
3867 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
3868 XmlUtils.skipCurrentTag(parser);
3869 return false;
3870 }
3871
3872 if (owner.staticSharedLibName != null) {
3873 outError[0] = "Multiple static-shared libs for package " + pkgName;
3874 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3875 XmlUtils.skipCurrentTag(parser);
3876 return false;
3877 }
3878
3879 owner.staticSharedLibName = lname.intern();
Dianne Hackborn3accca02013-09-20 09:32:11 -07003880 if (version >= 0) {
3881 owner.staticSharedLibVersion =
3882 PackageInfo.composeLongVersionCode(versionMajor, version);
3883 } else {
3884 owner.staticSharedLibVersion = version;
3885 }
Svet Ganov67882122016-12-11 16:36:34 -08003886 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
3887
3888 XmlUtils.skipCurrentTag(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003889
Dianne Hackbornc895be72013-03-11 17:48:43 -07003890 } else if (tagName.equals("library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003891 sa = res.obtainAttributes(parser,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003892 com.android.internal.R.styleable.AndroidManifestLibrary);
3893
3894 // Note: don't allow this value to be a reference to a resource
3895 // that may change.
3896 String lname = sa.getNonResourceString(
3897 com.android.internal.R.styleable.AndroidManifestLibrary_name);
3898
3899 sa.recycle();
3900
3901 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003902 lname = lname.intern();
3903 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
Svet Ganov67882122016-12-11 16:36:34 -08003904 owner.libraryNames = ArrayUtils.add(
3905 owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07003906 }
3907 }
3908
3909 XmlUtils.skipCurrentTag(parser);
3910
Svet Ganov67882122016-12-11 16:36:34 -08003911 } else if (tagName.equals("uses-static-library")) {
3912 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3913 return false;
3914 }
3915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003917 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003918 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3919
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003920 // Note: don't allow this value to be a reference to a resource
3921 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003922 String lname = sa.getNonResourceString(
3923 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07003924 boolean req = sa.getBoolean(
3925 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3926 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003927
3928 sa.recycle();
3929
Dianne Hackborn49237342009-08-27 20:08:01 -07003930 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003931 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07003932 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003933 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003934 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003935 owner.usesOptionalLibraries = ArrayUtils.add(
3936 owner.usesOptionalLibraries, lname);
3937 }
3938 }
3939
3940 XmlUtils.skipCurrentTag(parser);
3941
3942 } else if (tagName.equals("uses-package")) {
3943 // Dependencies for app installers; we don't currently try to
3944 // enforce this.
3945 XmlUtils.skipCurrentTag(parser);
Chris Craikce030282018-10-16 14:33:11 -07003946 } else if (tagName.equals("profileable")) {
3947 sa = res.obtainAttributes(parser,
3948 com.android.internal.R.styleable.AndroidManifestProfileable);
3949 if (sa.getBoolean(
3950 com.android.internal.R.styleable.AndroidManifestProfileable_shell, false)) {
3951 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL;
3952 }
3953 XmlUtils.skipCurrentTag(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003954
3955 } else {
3956 if (!RIGID_PARSER) {
3957 Slog.w(TAG, "Unknown element under <application>: " + tagName
3958 + " at " + mArchiveSourcePath + " "
3959 + parser.getPositionDescription());
3960 XmlUtils.skipCurrentTag(parser);
3961 continue;
3962 } else {
3963 outError[0] = "Bad element under <application>: " + tagName;
3964 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3965 return false;
3966 }
3967 }
3968 }
3969
Patrick Baumann1f9b8852018-10-30 12:34:46 -07003970 if (TextUtils.isEmpty(owner.staticSharedLibName)) {
3971 // Add a hidden app detail activity to normal apps which forwards user to App Details
3972 // page.
3973 Activity a = generateAppDetailsHiddenActivity(owner, flags, outError,
3974 owner.baseHardwareAccelerated);
3975 owner.activities.add(a);
3976 }
Ricky Waicf134eb2018-10-10 09:26:32 +01003977
Todd Kennedy6d418b62018-02-22 14:15:18 -08003978 if (hasActivityOrder) {
3979 Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order));
3980 }
3981 if (hasReceiverOrder) {
3982 Collections.sort(owner.receivers, (r1, r2) -> Integer.compare(r2.order, r1.order));
3983 }
3984 if (hasServiceOrder) {
3985 Collections.sort(owner.services, (s1, s2) -> Integer.compare(s2.order, s1.order));
3986 }
Bryce Lee22571db2017-07-07 15:54:18 -07003987 // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
3988 // every activity info has had a chance to set it from its attributes.
3989 setMaxAspectRatio(owner);
Adrian Roos917791e2018-11-28 16:30:44 +01003990 setMinAspectRatio(owner);
Bryce Lee22571db2017-07-07 15:54:18 -07003991
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003992 if (hasDomainURLs(owner)) {
3993 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3994 } else {
3995 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3996 }
3997
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003998 return true;
3999 }
4000
4001 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07004002 * 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 -07004003 */
4004 private static boolean hasDomainURLs(Package pkg) {
4005 if (pkg == null || pkg.activities == null) return false;
4006 final ArrayList<Activity> activities = pkg.activities;
4007 final int countActivities = activities.size();
4008 for (int n=0; n<countActivities; n++) {
4009 Activity activity = activities.get(n);
4010 ArrayList<ActivityIntentInfo> filters = activity.intents;
4011 if (filters == null) continue;
4012 final int countFilters = filters.size();
4013 for (int m=0; m<countFilters; m++) {
4014 ActivityIntentInfo aii = filters.get(m);
4015 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07004016 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07004017 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
4018 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
4019 return true;
4020 }
4021 }
4022 }
4023 return false;
4024 }
4025
4026 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004027 * Parse the {@code application} XML tree at the current parse location in a
4028 * <em>split APK</em> manifest.
4029 * <p>
4030 * Note that split APKs have many more restrictions on what they're capable
4031 * of doing, so many valid features of a base APK have been carefully
4032 * omitted here.
4033 */
Svet Ganov354cd3c2015-12-17 11:35:04 -08004034 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
4035 int flags, int splitIndex, String[] outError)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004036 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004037 TypedArray sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004038 com.android.internal.R.styleable.AndroidManifestApplication);
4039
4040 if (sa.getBoolean(
4041 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
4042 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
4043 }
4044
Narayan Kamath96c11c52017-08-09 13:07:21 +01004045 final String classLoaderName = sa.getString(
4046 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
4047 if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
4048 owner.applicationInfo.splitClassLoaderNames[splitIndex] = classLoaderName;
4049 } else {
4050 outError[0] = "Invalid class loader name: " + classLoaderName;
4051 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4052 return false;
4053 }
4054
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004055 final int innerDepth = parser.getDepth();
4056 int type;
4057 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
4058 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
4059 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4060 continue;
4061 }
4062
Adam Lesinski4e862812016-11-21 16:02:24 -08004063 ComponentInfo parsedComponent = null;
4064
Garrett Boyer52136662017-05-23 13:47:58 -07004065 // IMPORTANT: These must only be cached for a single <application> to avoid components
4066 // getting added to the wrong package.
4067 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004068 String tagName = parser.getName();
4069 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004070 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004071 owner.baseHardwareAccelerated);
4072 if (a == null) {
4073 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4074 return false;
4075 }
4076
4077 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08004078 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004079
4080 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004081 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
4082 true, false);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004083 if (a == null) {
4084 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4085 return false;
4086 }
4087
4088 owner.receivers.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08004089 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004090
4091 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004092 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004093 if (s == null) {
4094 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4095 return false;
4096 }
4097
4098 owner.services.add(s);
Adam Lesinski4e862812016-11-21 16:02:24 -08004099 parsedComponent = s.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004100
4101 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004102 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004103 if (p == null) {
4104 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4105 return false;
4106 }
4107
4108 owner.providers.add(p);
Adam Lesinski4e862812016-11-21 16:02:24 -08004109 parsedComponent = p.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004110
4111 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004112 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004113 if (a == null) {
4114 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4115 return false;
4116 }
4117
4118 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08004119 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004120
4121 } else if (parser.getName().equals("meta-data")) {
4122 // note: application meta-data is stored off to the side, so it can
4123 // remain null in the primary copy (we like to avoid extra copies because
4124 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08004125 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004126 outError)) == null) {
4127 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4128 return false;
4129 }
4130
Svet Ganov67882122016-12-11 16:36:34 -08004131 } else if (tagName.equals("uses-static-library")) {
4132 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
4133 return false;
4134 }
4135
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004136 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004137 sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004138 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
4139
4140 // Note: don't allow this value to be a reference to a resource
4141 // that may change.
4142 String lname = sa.getNonResourceString(
4143 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
4144 boolean req = sa.getBoolean(
4145 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
4146 true);
4147
4148 sa.recycle();
4149
4150 if (lname != null) {
4151 lname = lname.intern();
4152 if (req) {
4153 // Upgrade to treat as stronger constraint
4154 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
4155 owner.usesOptionalLibraries = ArrayUtils.remove(
4156 owner.usesOptionalLibraries, lname);
4157 } else {
4158 // Ignore if someone already defined as required
4159 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
4160 owner.usesOptionalLibraries = ArrayUtils.add(
4161 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07004162 }
4163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004164 }
4165
4166 XmlUtils.skipCurrentTag(parser);
4167
Dianne Hackborncef65ee2010-09-30 18:27:22 -07004168 } else if (tagName.equals("uses-package")) {
4169 // Dependencies for app installers; we don't currently try to
4170 // enforce this.
4171 XmlUtils.skipCurrentTag(parser);
4172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 } else {
4174 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004175 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004176 + " at " + mArchiveSourcePath + " "
4177 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004178 XmlUtils.skipCurrentTag(parser);
4179 continue;
4180 } else {
4181 outError[0] = "Bad element under <application>: " + tagName;
4182 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4183 return false;
4184 }
4185 }
Adam Lesinski4e862812016-11-21 16:02:24 -08004186
4187 if (parsedComponent != null && parsedComponent.splitName == null) {
4188 // If the loaded component did not specify a split, inherit the split name
4189 // based on the split it is defined in.
4190 // This is used to later load the correct split when starting this
4191 // component.
4192 parsedComponent.splitName = owner.splitNames[splitIndex];
4193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 }
4195
4196 return true;
4197 }
4198
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004199 private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
4200 String[] outError, String tag, TypedArray sa, boolean nameRequired,
4201 int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00004202 // This case can only happen in unit tests where we sometimes need to create fakes
4203 // of various package parser data structures.
4204 if (sa == null) {
4205 outError[0] = tag + " does not contain any attributes";
4206 return false;
4207 }
4208
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004209 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004210 if (name == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004211 if (nameRequired) {
4212 outError[0] = tag + " does not specify android:name";
4213 return false;
4214 }
4215 } else {
Ricky Waicf134eb2018-10-10 09:26:32 +01004216 String outInfoName
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004217 = buildClassName(owner.applicationInfo.packageName, name, outError);
Ricky Wai92cd0062019-02-14 20:23:22 +00004218 if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(outInfoName)) {
Ricky Waicf134eb2018-10-10 09:26:32 +01004219 outError[0] = tag + " invalid android:name";
4220 return false;
4221 }
4222 outInfo.name = outInfoName;
4223 if (outInfoName == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004224 return false;
4225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004226 }
4227
Hyunyoung Song929de7a2019-03-21 23:51:27 -07004228 int roundIconVal = sUseRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004229 if (roundIconVal != 0) {
4230 outInfo.icon = roundIconVal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004231 outInfo.nonLocalizedLabel = null;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004232 } else {
4233 int iconVal = sa.getResourceId(iconRes, 0);
4234 if (iconVal != 0) {
4235 outInfo.icon = iconVal;
4236 outInfo.nonLocalizedLabel = null;
4237 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004238 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004239
Adam Powell81cd2e92010-04-21 16:35:18 -07004240 int logoVal = sa.getResourceId(logoRes, 0);
4241 if (logoVal != 0) {
4242 outInfo.logo = logoVal;
4243 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004244
Jose Limaf78e3122014-03-06 12:13:15 -08004245 int bannerVal = sa.getResourceId(bannerRes, 0);
4246 if (bannerVal != 0) {
4247 outInfo.banner = bannerVal;
4248 }
4249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004250 TypedValue v = sa.peekValue(labelRes);
4251 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4252 outInfo.nonLocalizedLabel = v.coerceToString();
4253 }
4254
4255 outInfo.packageName = owner.packageName;
4256
4257 return true;
4258 }
4259
Ricky Waicf134eb2018-10-10 09:26:32 +01004260 /**
4261 * Generate activity object that forwards user to App Details page automatically.
4262 * This activity should be invisible to user and user should not know or see it.
4263 */
4264 private @NonNull PackageParser.Activity generateAppDetailsHiddenActivity(
4265 PackageParser.Package owner, int flags, String[] outError,
4266 boolean hardwareAccelerated) {
4267
4268 // Build custom App Details activity info instead of parsing it from xml
Ricky Wai92cd0062019-02-14 20:23:22 +00004269 Activity a = new Activity(owner, PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME,
4270 new ActivityInfo());
Ricky Waicf134eb2018-10-10 09:26:32 +01004271 a.owner = owner;
4272 a.setPackageName(owner.packageName);
4273
Ricky Wai622925072019-01-29 16:40:59 +00004274 a.info.theme = android.R.style.Theme_NoDisplay;
Ricky Waicf134eb2018-10-10 09:26:32 +01004275 a.info.exported = true;
Ricky Wai92cd0062019-02-14 20:23:22 +00004276 a.info.name = PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME;
Ricky Waicf134eb2018-10-10 09:26:32 +01004277 a.info.processName = owner.applicationInfo.processName;
4278 a.info.uiOptions = a.info.applicationInfo.uiOptions;
4279 a.info.taskAffinity = buildTaskAffinityName(owner.packageName, owner.packageName,
4280 ":app_details", outError);
4281 a.info.enabled = true;
4282 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4283 a.info.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NONE;
4284 a.info.maxRecents = ActivityTaskManager.getDefaultAppRecentsLimitStatic();
4285 a.info.configChanges = getActivityConfigChanges(0, 0);
4286 a.info.softInputMode = 0;
4287 a.info.persistableMode = ActivityInfo.PERSIST_NEVER;
4288 a.info.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
4289 a.info.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4290 a.info.lockTaskLaunchMode = 0;
4291 a.info.encryptionAware = a.info.directBootAware = false;
4292 a.info.rotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
4293 a.info.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
4294 if (hardwareAccelerated) {
4295 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
4296 }
4297 return a;
4298 }
4299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004300 private Activity parseActivity(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004301 XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
Romain Guy529b60a2010-08-03 18:05:47 -07004302 boolean receiver, boolean hardwareAccelerated)
4303 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004304 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004305
Garrett Boyer52136662017-05-23 13:47:58 -07004306 if (cachedArgs.mActivityArgs == null) {
4307 cachedArgs.mActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004308 R.styleable.AndroidManifestActivity_name,
4309 R.styleable.AndroidManifestActivity_label,
4310 R.styleable.AndroidManifestActivity_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004311 R.styleable.AndroidManifestActivity_roundIcon,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004312 R.styleable.AndroidManifestActivity_logo,
4313 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004314 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004315 R.styleable.AndroidManifestActivity_process,
4316 R.styleable.AndroidManifestActivity_description,
4317 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004318 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004319
Garrett Boyer52136662017-05-23 13:47:58 -07004320 cachedArgs.mActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
4321 cachedArgs.mActivityArgs.sa = sa;
4322 cachedArgs.mActivityArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004323
Garrett Boyer52136662017-05-23 13:47:58 -07004324 Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004325 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004326 sa.recycle();
4327 return null;
4328 }
4329
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004330 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004331 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004332 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004333 }
4334
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004335 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004336
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004337 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07004338 a.info.applicationInfo.uiOptions);
4339
Adam Powelldd8fab22012-03-22 17:47:27 -07004340 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004341 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004342 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004343 if (parentName != null) {
4344 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4345 if (outError[0] == null) {
4346 a.info.parentActivityName = parentClassName;
4347 } else {
4348 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
4349 parentName);
4350 outError[0] = null;
4351 }
4352 }
4353
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004354 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004355 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004356 if (str == null) {
4357 a.info.permission = owner.applicationInfo.permission;
4358 } else {
4359 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4360 }
4361
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004362 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004363 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004364 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004365 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
4366 owner.applicationInfo.taskAffinity, str, outError);
4367
Todd Kennedye9d0d272017-01-23 06:49:29 -08004368 a.info.splitName =
4369 sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0);
4370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004371 a.info.flags = 0;
4372 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004373 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
4375 }
4376
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004377 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004378 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
4379 }
4380
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004381 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004382 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
4383 }
4384
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004385 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004386 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
4387 }
4388
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004389 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004390 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
4391 }
4392
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004393 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004394 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
4395 }
4396
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004397 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004398 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
4399 }
4400
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004401 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004402 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
4403 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
4404 }
4405
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004406 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07004407 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
4408 }
4409
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07004410 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
4411 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
4412 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07004413 }
4414
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004415 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04004416 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
4417 }
Craig Mautner5962b122012-10-05 14:45:52 -07004418
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07004419 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
4420 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08004421 }
4422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004423 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004424 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07004425 hardwareAccelerated)) {
4426 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
4427 }
4428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004429 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004430 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07004431 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004432 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07004433 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07004434 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004435 R.styleable.AndroidManifestActivity_maxRecents,
Wale Ogunwale65ebd952018-04-25 15:41:44 -07004436 ActivityTaskManager.getDefaultAppRecentsLimitStatic());
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004437 a.info.configChanges = getActivityConfigChanges(
4438 sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004439 sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004440 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004441 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07004442
Craig Mautner43e52ed2014-06-16 17:18:52 -07004443 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004444 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07004445 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07004446
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004447 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004448 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
4449 }
4450
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004451 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004452 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
4453 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004454
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004455 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004456 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
4457 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004458
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004459 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004460 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
4461 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004462
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004463 a.info.screenOrientation = sa.getInt(
4464 R.styleable.AndroidManifestActivity_screenOrientation,
4465 SCREEN_ORIENTATION_UNSPECIFIED);
Wale Ogunwale6a591362015-10-05 20:18:27 -07004466
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004467 setActivityResizeMode(a.info, sa, owner);
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004468
Winson Chungd3395382016-12-13 11:49:09 -08004469 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
4470 false)) {
4471 a.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE;
4472 }
4473
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004474 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004475 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004476 }
Wale Ogunwaleb60692e2015-10-24 12:35:56 -07004477
Bryce Lee22571db2017-07-07 15:54:18 -07004478 if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio)
4479 && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio)
4480 == TypedValue.TYPE_FLOAT) {
4481 a.setMaxAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio,
4482 0 /*default*/));
4483 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004484
Adrian Roos917791e2018-11-28 16:30:44 +01004485 if (sa.hasValue(R.styleable.AndroidManifestActivity_minAspectRatio)
4486 && sa.getType(R.styleable.AndroidManifestActivity_minAspectRatio)
4487 == TypedValue.TYPE_FLOAT) {
4488 a.setMinAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_minAspectRatio,
4489 0 /*default*/));
4490 }
4491
Craig Mautner15df08a2015-04-01 12:17:18 -07004492 a.info.lockTaskLaunchMode =
4493 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004494
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004495 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4496 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004497 false);
Ruben Brunkf56c9f42016-04-22 18:20:55 -07004498
4499 a.info.requestedVrComponent =
4500 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
Robert Carr0f5d7532016-10-17 16:39:17 -07004501
4502 a.info.rotationAnimation =
Robert Carr427ba4f2017-07-17 18:37:06 -07004503 sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_UNSPECIFIED);
Romain Guy48327452017-01-23 17:03:35 -08004504
4505 a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
4506 ActivityInfo.COLOR_MODE_DEFAULT);
chaviw59b98852017-06-13 12:05:44 -07004507
4508 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) {
4509 a.info.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
4510 }
4511
4512 if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) {
4513 a.info.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON;
4514 }
4515
Issei Suzuki74e1eb22018-12-20 17:42:52 +01004516 if (sa.getBoolean(R.styleable.AndroidManifestActivity_inheritShowWhenLocked, false)) {
4517 a.info.privateFlags |= ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
4518 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004519 } else {
4520 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4521 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004522
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004523 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07004524 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004525 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004526
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004527 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4528 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004529 false);
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004530 }
4531
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004532 if (a.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004533 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004534 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004535 }
4536
Todd Kennedy752fb702017-03-21 16:28:10 -07004537 // can't make this final; we may set it later via meta-data
4538 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08004539 sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004540 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004541 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004542 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004543 }
4544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004545 sa.recycle();
4546
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004547 if (receiver && (owner.applicationInfo.privateFlags
4548 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004549 // A heavy-weight application can not have receives in its main process
4550 // We can do direct compare because we intern all strings.
4551 if (a.info.processName == owner.packageName) {
4552 outError[0] = "Heavy-weight applications can not have receivers in main process";
4553 }
4554 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 if (outError[0] != null) {
4557 return null;
4558 }
4559
4560 int outerDepth = parser.getDepth();
4561 int type;
4562 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4563 && (type != XmlPullParser.END_TAG
4564 || parser.getDepth() > outerDepth)) {
4565 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4566 continue;
4567 }
4568
4569 if (parser.getName().equals("intent-filter")) {
4570 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004571 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4572 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004573 return null;
4574 }
4575 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004576 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004577 + mArchiveSourcePath + " "
4578 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 } else {
Todd Kennedy6d418b62018-02-22 14:15:18 -08004580 a.order = Math.max(intent.getOrder(), a.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 a.intents.add(intent);
4582 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004583 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004584 final int visibility = visibleToEphemeral
4585 ? IntentFilter.VISIBILITY_EXPLICIT
4586 : !receiver && isImplicitlyExposedIntent(intent)
4587 ? IntentFilter.VISIBILITY_IMPLICIT
4588 : IntentFilter.VISIBILITY_NONE;
4589 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004590 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004591 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4592 }
4593 if (intent.isImplicitlyVisibleToInstantApp()) {
4594 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004595 }
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -07004596 if (LOG_UNSAFE_BROADCASTS && receiver
4597 && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
4598 for (int i = 0; i < intent.countActions(); i++) {
4599 final String action = intent.getAction(i);
4600 if (action == null || !action.startsWith("android.")) continue;
4601 if (!SAFE_BROADCASTS.contains(action)) {
4602 Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
4603 + owner.packageName + " as requested at: "
4604 + parser.getPositionDescription());
4605 }
4606 }
4607 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004608 } else if (!receiver && parser.getName().equals("preferred")) {
4609 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004610 if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
4611 intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004612 return null;
4613 }
4614 if (intent.countActions() == 0) {
4615 Slog.w(TAG, "No actions in preferred at "
4616 + mArchiveSourcePath + " "
4617 + parser.getPositionDescription());
4618 } else {
4619 if (owner.preferredActivityFilters == null) {
4620 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
4621 }
4622 owner.preferredActivityFilters.add(intent);
4623 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004624 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004625 final int visibility = visibleToEphemeral
4626 ? IntentFilter.VISIBILITY_EXPLICIT
4627 : !receiver && isImplicitlyExposedIntent(intent)
4628 ? IntentFilter.VISIBILITY_IMPLICIT
4629 : IntentFilter.VISIBILITY_NONE;
4630 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004631 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004632 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4633 }
4634 if (intent.isImplicitlyVisibleToInstantApp()) {
4635 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004636 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004637 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004638 if ((a.metaData = parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004639 outError)) == null) {
4640 return null;
4641 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004642 } else if (!receiver && parser.getName().equals("layout")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004643 parseLayout(res, parser, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004644 } else {
4645 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004646 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004647 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004648 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004649 + " at " + mArchiveSourcePath + " "
4650 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004651 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004652 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004653 + " at " + mArchiveSourcePath + " "
4654 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655 }
4656 XmlUtils.skipCurrentTag(parser);
4657 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004658 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004659 if (receiver) {
4660 outError[0] = "Bad element under <receiver>: " + parser.getName();
4661 } else {
4662 outError[0] = "Bad element under <activity>: " + parser.getName();
4663 }
4664 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004666 }
4667 }
4668
4669 if (!setExported) {
4670 a.info.exported = a.intents.size() > 0;
4671 }
4672
4673 return a;
4674 }
4675
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004676 private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004677 final boolean appExplicitDefault = (owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004678 & (PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
4679 | PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004680
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004681 if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
4682 || appExplicitDefault) {
4683 // Activity or app explicitly set if it is resizeable or not;
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004684 final boolean appResizeable = (owner.applicationInfo.privateFlags
4685 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004686 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004687 appResizeable)) {
Winson Chungd3395382016-12-13 11:49:09 -08004688 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004689 } else {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004690 aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004691 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004692 return;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004693 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004694
4695 if ((owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004696 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) != 0) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004697 // The activity or app didn't explicitly set the resizing option, however we want to
4698 // make it resize due to the sdk version it is targeting.
4699 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4700 return;
4701 }
4702
4703 // resize preference isn't set and target sdk version doesn't support resizing apps by
4704 // default. For the app to be resizeable if it isn't fixed orientation or immersive.
skuhne@google.com322347b2016-12-02 12:54:03 -08004705 if (aInfo.isFixedOrientationPortrait()) {
4706 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
4707 } else if (aInfo.isFixedOrientationLandscape()) {
4708 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
4709 } else if (aInfo.isFixedOrientation()) {
4710 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
4711 } else {
4712 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4713 }
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004714 }
4715
Bryce Lee22571db2017-07-07 15:54:18 -07004716 /**
4717 * Sets every the max aspect ratio of every child activity that doesn't already have an aspect
4718 * ratio set.
4719 */
4720 private void setMaxAspectRatio(Package owner) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004721 // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
4722 // 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 -07004723 float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004724 ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
Bryce Lee22571db2017-07-07 15:54:18 -07004725
4726 if (owner.applicationInfo.maxAspectRatio != 0) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004727 // Use the application max aspect ration as default if set.
Bryce Lee22571db2017-07-07 15:54:18 -07004728 maxAspectRatio = owner.applicationInfo.maxAspectRatio;
4729 } else if (owner.mAppMetaData != null
4730 && owner.mAppMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) {
4731 maxAspectRatio = owner.mAppMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004732 }
4733
Bryce Lee22571db2017-07-07 15:54:18 -07004734 for (Activity activity : owner.activities) {
4735 // If the max aspect ratio for the activity has already been set, skip.
4736 if (activity.hasMaxAspectRatio()) {
4737 continue;
4738 }
4739
4740 // By default we prefer to use a values defined on the activity directly than values
4741 // defined on the application. We do not check the styled attributes on the activity
4742 // as it would have already been set when we processed the activity. We wait to process
4743 // the meta data here since this method is called at the end of processing the
4744 // application and all meta data is guaranteed.
4745 final float activityAspectRatio = activity.metaData != null
4746 ? activity.metaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio)
4747 : maxAspectRatio;
4748
4749 activity.setMaxAspectRatio(activityAspectRatio);
Wale Ogunwale0cb70ac2017-03-27 09:16:38 -07004750 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004751 }
4752
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004753 /**
Tiger Huang3d2b8982019-01-29 22:56:48 +08004754 * Sets every the min aspect ratio of every child activity that doesn't already have an aspect
Adrian Roos917791e2018-11-28 16:30:44 +01004755 * ratio set.
4756 */
4757 private void setMinAspectRatio(Package owner) {
4758 final float minAspectRatio;
4759 if (owner.applicationInfo.minAspectRatio != 0) {
4760 // Use the application max aspect ration as default if set.
4761 minAspectRatio = owner.applicationInfo.minAspectRatio;
4762 } else {
4763 // Default to (1.33) 4:3 aspect ratio for pre-Q apps and unset for Q and greater.
4764 // NOTE: 4:3 was the min aspect ratio Android devices can support pre-Q per the CDD,
4765 // except for watches which always supported 1:1.
4766 minAspectRatio = owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q
4767 ? 0
Mohammad Samiul Islam7aa7d2e2019-03-27 12:23:47 +00004768 : (mCallback != null && mCallback.hasFeature(FEATURE_WATCH))
Adrian Roos917791e2018-11-28 16:30:44 +01004769 ? DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH
4770 : DEFAULT_PRE_Q_MIN_ASPECT_RATIO;
4771 }
4772
4773 for (Activity activity : owner.activities) {
4774 if (activity.hasMinAspectRatio()) {
4775 continue;
4776 }
4777 activity.setMinAspectRatio(minAspectRatio);
4778 }
4779 }
4780
4781 /**
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004782 * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004783 * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from
4784 * AndroidManifest.xml.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004785 * @hide Exposed for unit testing only.
4786 */
4787 @TestApi
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004788 public static int getActivityConfigChanges(int configChanges, int recreateOnConfigChanges) {
4789 return configChanges | ((~recreateOnConfigChanges) & RECREATE_ON_CONFIG_CHANGES_MASK);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004790 }
4791
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004792 private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004793 TypedArray sw = res.obtainAttributes(attrs,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004794 com.android.internal.R.styleable.AndroidManifestLayout);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004795 int width = -1;
4796 float widthFraction = -1f;
4797 int height = -1;
4798 float heightFraction = -1f;
4799 final int widthType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004800 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004801 if (widthType == TypedValue.TYPE_FRACTION) {
4802 widthFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004803 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004804 1, 1, -1);
4805 } else if (widthType == TypedValue.TYPE_DIMENSION) {
4806 width = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004807 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004808 -1);
4809 }
4810 final int heightType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004811 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004812 if (heightType == TypedValue.TYPE_FRACTION) {
4813 heightFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004814 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004815 1, 1, -1);
4816 } else if (heightType == TypedValue.TYPE_DIMENSION) {
4817 height = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004818 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004819 -1);
4820 }
4821 int gravity = sw.getInt(
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004822 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004823 Gravity.CENTER);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004824 int minWidth = sw.getDimensionPixelSize(
4825 com.android.internal.R.styleable.AndroidManifestLayout_minWidth,
Andrii Kulian2e751b82016-03-16 16:59:32 -07004826 -1);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004827 int minHeight = sw.getDimensionPixelSize(
4828 com.android.internal.R.styleable.AndroidManifestLayout_minHeight,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004829 -1);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004830 sw.recycle();
Andrii Kulian2e751b82016-03-16 16:59:32 -07004831 a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction,
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004832 height, heightFraction, gravity, minWidth, minHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004833 }
4834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 private Activity parseActivityAlias(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004836 XmlResourceParser parser, int flags, String[] outError,
4837 CachedComponentArgs cachedArgs)
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004838 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004839 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004840 com.android.internal.R.styleable.AndroidManifestActivityAlias);
4841
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004842 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004843 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
4844 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 if (targetActivity == null) {
4846 outError[0] = "<activity-alias> does not specify android:targetActivity";
4847 sa.recycle();
4848 return null;
4849 }
4850
4851 targetActivity = buildClassName(owner.applicationInfo.packageName,
4852 targetActivity, outError);
4853 if (targetActivity == null) {
4854 sa.recycle();
4855 return null;
4856 }
4857
Garrett Boyer52136662017-05-23 13:47:58 -07004858 if (cachedArgs.mActivityAliasArgs == null) {
4859 cachedArgs.mActivityAliasArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004860 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
4861 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
4862 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004863 com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004864 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004865 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004866 mSeparateProcesses,
4867 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004868 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004869 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004870 cachedArgs.mActivityAliasArgs.tag = "<activity-alias>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004871 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004872
Garrett Boyer52136662017-05-23 13:47:58 -07004873 cachedArgs.mActivityAliasArgs.sa = sa;
4874 cachedArgs.mActivityAliasArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004876 Activity target = null;
4877
4878 final int NA = owner.activities.size();
4879 for (int i=0; i<NA; i++) {
4880 Activity t = owner.activities.get(i);
4881 if (targetActivity.equals(t.info.name)) {
4882 target = t;
4883 break;
4884 }
4885 }
4886
4887 if (target == null) {
4888 outError[0] = "<activity-alias> target activity " + targetActivity
4889 + " not found in manifest";
4890 sa.recycle();
4891 return null;
4892 }
4893
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004894 ActivityInfo info = new ActivityInfo();
4895 info.targetActivity = targetActivity;
4896 info.configChanges = target.info.configChanges;
4897 info.flags = target.info.flags;
Issei Suzuki74e1eb22018-12-20 17:42:52 +01004898 info.privateFlags = target.info.privateFlags;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004899 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07004900 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08004901 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004902 info.labelRes = target.info.labelRes;
4903 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
4904 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07004905 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004906 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004907 if (info.descriptionRes == 0) {
4908 info.descriptionRes = target.info.descriptionRes;
4909 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004910 info.screenOrientation = target.info.screenOrientation;
4911 info.taskAffinity = target.info.taskAffinity;
4912 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07004913 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07004914 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07004915 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07004916 info.maxRecents = target.info.maxRecents;
Andrii Kulian2e751b82016-03-16 16:59:32 -07004917 info.windowLayout = target.info.windowLayout;
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004918 info.resizeMode = target.info.resizeMode;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004919 info.maxAspectRatio = target.info.maxAspectRatio;
Adrian Roos917791e2018-11-28 16:30:44 +01004920 info.minAspectRatio = target.info.minAspectRatio;
rongliuc12ede42018-02-23 17:58:38 -08004921 info.requestedVrComponent = target.info.requestedVrComponent;
Bryce Lee22571db2017-07-07 15:54:18 -07004922
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004923 info.encryptionAware = info.directBootAware = target.info.directBootAware;
Craig Mautner8307ea72014-09-11 15:03:53 -07004924
Garrett Boyer52136662017-05-23 13:47:58 -07004925 Activity a = new Activity(cachedArgs.mActivityAliasArgs, info);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004926 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004927 sa.recycle();
4928 return null;
4929 }
4930
4931 final boolean setExported = sa.hasValue(
4932 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
4933 if (setExported) {
4934 a.info.exported = sa.getBoolean(
4935 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
4936 }
4937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004938 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004939 str = sa.getNonConfigurationString(
4940 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004941 if (str != null) {
4942 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4943 }
4944
Adam Powelldd8fab22012-03-22 17:47:27 -07004945 String parentName = sa.getNonConfigurationString(
4946 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004947 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004948 if (parentName != null) {
4949 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4950 if (outError[0] == null) {
4951 a.info.parentActivityName = parentClassName;
4952 } else {
4953 Log.e(TAG, "Activity alias " + a.info.name +
4954 " specified invalid parentActivityName " + parentName);
4955 outError[0] = null;
4956 }
4957 }
4958
Chad Brubaker699c7712017-01-20 13:53:42 -08004959 // TODO add visibleToInstantApps attribute to activity alias
Todd Kennedybe0b8892017-02-15 14:13:52 -08004960 final boolean visibleToEphemeral =
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004961 ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963 sa.recycle();
4964
4965 if (outError[0] != null) {
4966 return null;
4967 }
4968
4969 int outerDepth = parser.getDepth();
4970 int type;
4971 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4972 && (type != XmlPullParser.END_TAG
4973 || parser.getDepth() > outerDepth)) {
4974 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4975 continue;
4976 }
4977
4978 if (parser.getName().equals("intent-filter")) {
4979 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004980 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4981 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004982 return null;
4983 }
4984 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004985 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004986 + mArchiveSourcePath + " "
4987 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988 } else {
Todd Kennedy6d418b62018-02-22 14:15:18 -08004989 a.order = Math.max(intent.getOrder(), a.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 a.intents.add(intent);
4991 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004992 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004993 final int visibility = visibleToEphemeral
4994 ? IntentFilter.VISIBILITY_EXPLICIT
4995 : isImplicitlyExposedIntent(intent)
4996 ? IntentFilter.VISIBILITY_IMPLICIT
4997 : IntentFilter.VISIBILITY_NONE;
4998 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004999 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005000 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
5001 }
5002 if (intent.isImplicitlyVisibleToInstantApp()) {
5003 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005005 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005006 if ((a.metaData=parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005007 outError)) == null) {
5008 return null;
5009 }
5010 } else {
5011 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005012 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005013 + " at " + mArchiveSourcePath + " "
5014 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005015 XmlUtils.skipCurrentTag(parser);
5016 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005017 } else {
5018 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
5019 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005021 }
5022 }
5023
5024 if (!setExported) {
5025 a.info.exported = a.intents.size() > 0;
5026 }
5027
5028 return a;
5029 }
5030
5031 private Provider parseProvider(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07005032 XmlResourceParser parser, int flags, String[] outError,
5033 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005034 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005035 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005036 com.android.internal.R.styleable.AndroidManifestProvider);
5037
Garrett Boyer52136662017-05-23 13:47:58 -07005038 if (cachedArgs.mProviderArgs == null) {
5039 cachedArgs.mProviderArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005040 com.android.internal.R.styleable.AndroidManifestProvider_name,
5041 com.android.internal.R.styleable.AndroidManifestProvider_label,
5042 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005043 com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07005044 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08005045 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005046 mSeparateProcesses,
5047 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005048 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005049 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07005050 cachedArgs.mProviderArgs.tag = "<provider>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005051 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005052
Garrett Boyer52136662017-05-23 13:47:58 -07005053 cachedArgs.mProviderArgs.sa = sa;
5054 cachedArgs.mProviderArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005055
Garrett Boyer52136662017-05-23 13:47:58 -07005056 Provider p = new Provider(cachedArgs.mProviderArgs, new ProviderInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005057 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005058 sa.recycle();
5059 return null;
5060 }
5061
Nick Kralevichf097b162012-07-28 12:43:48 -07005062 boolean providerExportedDefault = false;
5063
5064 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
5065 // For compatibility, applications targeting API level 16 or lower
5066 // should have their content providers exported by default, unless they
5067 // specify otherwise.
5068 providerExportedDefault = true;
5069 }
5070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07005072 com.android.internal.R.styleable.AndroidManifestProvider_exported,
5073 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005074
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005075 String cpname = sa.getNonConfigurationString(
5076 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005077
5078 p.info.isSyncable = sa.getBoolean(
5079 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
5080 false);
5081
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005082 String permission = sa.getNonConfigurationString(
5083 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
5084 String str = sa.getNonConfigurationString(
5085 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005086 if (str == null) {
5087 str = permission;
5088 }
5089 if (str == null) {
5090 p.info.readPermission = owner.applicationInfo.permission;
5091 } else {
5092 p.info.readPermission =
5093 str.length() > 0 ? str.toString().intern() : null;
5094 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005095 str = sa.getNonConfigurationString(
5096 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 if (str == null) {
5098 str = permission;
5099 }
5100 if (str == null) {
5101 p.info.writePermission = owner.applicationInfo.permission;
5102 } else {
5103 p.info.writePermission =
5104 str.length() > 0 ? str.toString().intern() : null;
5105 }
5106
5107 p.info.grantUriPermissions = sa.getBoolean(
5108 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
5109 false);
5110
Dianne Hackborn52e42a42019-02-05 16:10:50 -08005111 p.info.forceUriPermissions = sa.getBoolean(
5112 com.android.internal.R.styleable.AndroidManifestProvider_forceUriPermissions,
5113 false);
5114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005115 p.info.multiprocess = sa.getBoolean(
5116 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
5117 false);
5118
5119 p.info.initOrder = sa.getInt(
5120 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
5121 0);
5122
Todd Kennedye9d0d272017-01-23 06:49:29 -08005123 p.info.splitName =
5124 sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0);
5125
Dianne Hackborn7d19e022012-08-07 19:12:33 -07005126 p.info.flags = 0;
5127
5128 if (sa.getBoolean(
5129 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
5130 false)) {
5131 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07005132 }
5133
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005134 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
5135 R.styleable.AndroidManifestProvider_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005136 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005137 if (p.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005138 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005139 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005140 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005141
Todd Kennedybe0b8892017-02-15 14:13:52 -08005142 final boolean visibleToEphemeral =
5143 sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005144 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005145 p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005146 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005147 }
5148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 sa.recycle();
5150
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005151 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5152 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005153 // A heavy-weight application can not have providers in its main process
5154 // We can do direct compare because we intern all strings.
5155 if (p.info.processName == owner.packageName) {
5156 outError[0] = "Heavy-weight applications can not have providers in main process";
5157 return null;
5158 }
5159 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005161 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07005162 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005163 return null;
5164 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08005165 if (cpname.length() <= 0) {
5166 outError[0] = "<provider> has empty authorities attribute";
5167 return null;
5168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005169 p.info.authority = cpname.intern();
5170
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005171 if (!parseProviderTags(
Patrick Baumanna2900392018-02-05 15:30:43 -08005172 res, parser, visibleToEphemeral, p, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005173 return null;
5174 }
5175
5176 return p;
5177 }
5178
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005179 private boolean parseProviderTags(Resources res, XmlResourceParser parser,
Patrick Baumanna2900392018-02-05 15:30:43 -08005180 boolean visibleToEphemeral, Provider outInfo, String[] outError)
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005181 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005182 int outerDepth = parser.getDepth();
5183 int type;
5184 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5185 && (type != XmlPullParser.END_TAG
5186 || parser.getDepth() > outerDepth)) {
5187 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5188 continue;
5189 }
5190
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005191 if (parser.getName().equals("intent-filter")) {
5192 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005193 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5194 intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005195 return false;
5196 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005197 if (visibleToEphemeral) {
5198 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5199 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005200 }
Todd Kennedy6d418b62018-02-22 14:15:18 -08005201 outInfo.order = Math.max(intent.getOrder(), outInfo.order);
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005202 outInfo.intents.add(intent);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005203
5204 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005205 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005206 outInfo.metaData, outError)) == null) {
5207 return false;
5208 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005210 } else if (parser.getName().equals("grant-uri-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005211 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005212 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
5213
5214 PatternMatcher pa = null;
5215
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005216 String str = sa.getNonConfigurationString(
5217 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005218 if (str != null) {
5219 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
5220 }
5221
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005222 str = sa.getNonConfigurationString(
5223 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005224 if (str != null) {
5225 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
5226 }
5227
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005228 str = sa.getNonConfigurationString(
5229 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005230 if (str != null) {
5231 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5232 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005234 sa.recycle();
5235
5236 if (pa != null) {
5237 if (outInfo.info.uriPermissionPatterns == null) {
5238 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
5239 outInfo.info.uriPermissionPatterns[0] = pa;
5240 } else {
5241 final int N = outInfo.info.uriPermissionPatterns.length;
5242 PatternMatcher[] newp = new PatternMatcher[N+1];
5243 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
5244 newp[N] = pa;
5245 outInfo.info.uriPermissionPatterns = newp;
5246 }
5247 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005248 } else {
5249 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005250 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005251 + parser.getName() + " at " + mArchiveSourcePath + " "
5252 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005253 XmlUtils.skipCurrentTag(parser);
5254 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005255 } else {
5256 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5257 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005258 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005259 }
5260 XmlUtils.skipCurrentTag(parser);
5261
5262 } else if (parser.getName().equals("path-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005263 TypedArray sa = res.obtainAttributes(parser,
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005264 com.android.internal.R.styleable.AndroidManifestPathPermission);
5265
5266 PathPermission pa = null;
5267
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005268 String permission = sa.getNonConfigurationString(
5269 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
5270 String readPermission = sa.getNonConfigurationString(
5271 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005272 if (readPermission == null) {
5273 readPermission = permission;
5274 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005275 String writePermission = sa.getNonConfigurationString(
5276 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005277 if (writePermission == null) {
5278 writePermission = permission;
5279 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005280
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005281 boolean havePerm = false;
5282 if (readPermission != null) {
5283 readPermission = readPermission.intern();
5284 havePerm = true;
5285 }
5286 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00005287 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005288 havePerm = true;
5289 }
5290
5291 if (!havePerm) {
5292 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005293 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005294 + parser.getName() + " at " + mArchiveSourcePath + " "
5295 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005296 XmlUtils.skipCurrentTag(parser);
5297 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005298 } else {
5299 outError[0] = "No readPermission or writePermssion for <path-permission>";
5300 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005301 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005302 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005303
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005304 String path = sa.getNonConfigurationString(
5305 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005306 if (path != null) {
5307 pa = new PathPermission(path,
5308 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
5309 }
5310
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005311 path = sa.getNonConfigurationString(
5312 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005313 if (path != null) {
5314 pa = new PathPermission(path,
5315 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
5316 }
5317
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005318 path = sa.getNonConfigurationString(
5319 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005320 if (path != null) {
5321 pa = new PathPermission(path,
5322 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
5323 }
5324
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005325 path = sa.getNonConfigurationString(
5326 com.android.internal.R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
5327 if (path != null) {
5328 pa = new PathPermission(path,
5329 PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission);
5330 }
5331
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005332 sa.recycle();
5333
5334 if (pa != null) {
5335 if (outInfo.info.pathPermissions == null) {
5336 outInfo.info.pathPermissions = new PathPermission[1];
5337 outInfo.info.pathPermissions[0] = pa;
5338 } else {
5339 final int N = outInfo.info.pathPermissions.length;
5340 PathPermission[] newp = new PathPermission[N+1];
5341 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
5342 newp[N] = pa;
5343 outInfo.info.pathPermissions = newp;
5344 }
5345 } else {
5346 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005347 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005348 + parser.getName() + " at " + mArchiveSourcePath + " "
5349 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005350 XmlUtils.skipCurrentTag(parser);
5351 continue;
5352 }
5353 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5354 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005355 }
5356 XmlUtils.skipCurrentTag(parser);
5357
5358 } else {
5359 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005360 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005361 + parser.getName() + " at " + mArchiveSourcePath + " "
5362 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363 XmlUtils.skipCurrentTag(parser);
5364 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005365 } else {
5366 outError[0] = "Bad element under <provider>: " + parser.getName();
5367 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005369 }
5370 }
5371 return true;
5372 }
5373
5374 private Service parseService(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07005375 XmlResourceParser parser, int flags, String[] outError,
5376 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005377 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005378 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005379 com.android.internal.R.styleable.AndroidManifestService);
5380
Garrett Boyer52136662017-05-23 13:47:58 -07005381 if (cachedArgs.mServiceArgs == null) {
5382 cachedArgs.mServiceArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005383 com.android.internal.R.styleable.AndroidManifestService_name,
5384 com.android.internal.R.styleable.AndroidManifestService_label,
5385 com.android.internal.R.styleable.AndroidManifestService_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005386 com.android.internal.R.styleable.AndroidManifestService_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07005387 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08005388 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005389 mSeparateProcesses,
5390 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005391 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005392 com.android.internal.R.styleable.AndroidManifestService_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07005393 cachedArgs.mServiceArgs.tag = "<service>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005394 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005395
Garrett Boyer52136662017-05-23 13:47:58 -07005396 cachedArgs.mServiceArgs.sa = sa;
5397 cachedArgs.mServiceArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005398
Garrett Boyer52136662017-05-23 13:47:58 -07005399 Service s = new Service(cachedArgs.mServiceArgs, new ServiceInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005400 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005401 sa.recycle();
5402 return null;
5403 }
5404
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005405 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005406 com.android.internal.R.styleable.AndroidManifestService_exported);
5407 if (setExported) {
5408 s.info.exported = sa.getBoolean(
5409 com.android.internal.R.styleable.AndroidManifestService_exported, false);
5410 }
5411
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005412 String str = sa.getNonConfigurationString(
5413 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005414 if (str == null) {
5415 s.info.permission = owner.applicationInfo.permission;
5416 } else {
5417 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
5418 }
5419
Todd Kennedye9d0d272017-01-23 06:49:29 -08005420 s.info.splitName =
5421 sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0);
5422
Hui Yu1ea85522018-12-06 16:59:18 -08005423 s.info.mForegroundServiceType = sa.getInt(
5424 com.android.internal.R.styleable.AndroidManifestService_foregroundServiceType,
Hui Yu2d4207f2019-01-22 15:32:20 -08005425 ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
Hui Yu1ea85522018-12-06 16:59:18 -08005426
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005427 s.info.flags = 0;
5428 if (sa.getBoolean(
5429 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
5430 false)) {
5431 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
5432 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08005433 if (sa.getBoolean(
5434 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
5435 false)) {
5436 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
5437 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005438 if (sa.getBoolean(
Robert Sesekb9a86662015-12-09 16:22:45 -05005439 com.android.internal.R.styleable.AndroidManifestService_externalService,
5440 false)) {
5441 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
5442 }
5443 if (sa.getBoolean(
Martijn Coenene066c5c2018-10-31 16:50:30 +01005444 com.android.internal.R.styleable.AndroidManifestService_useAppZygote,
5445 false)) {
5446 s.info.flags |= ServiceInfo.FLAG_USE_APP_ZYGOTE;
5447 }
5448 if (sa.getBoolean(
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005449 com.android.internal.R.styleable.AndroidManifestService_singleUser,
5450 false)) {
5451 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005452 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005453
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005454 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
5455 R.styleable.AndroidManifestService_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005456 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005457 if (s.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005458 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005459 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005460 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005461
Todd Kennedy752fb702017-03-21 16:28:10 -07005462 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08005463 sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005464 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005465 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005466 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005467 }
5468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005469 sa.recycle();
5470
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005471 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5472 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005473 // A heavy-weight application can not have services in its main process
5474 // We can do direct compare because we intern all strings.
5475 if (s.info.processName == owner.packageName) {
5476 outError[0] = "Heavy-weight applications can not have services in main process";
5477 return null;
5478 }
5479 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005481 int outerDepth = parser.getDepth();
5482 int type;
5483 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5484 && (type != XmlPullParser.END_TAG
5485 || parser.getDepth() > outerDepth)) {
5486 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5487 continue;
5488 }
5489
5490 if (parser.getName().equals("intent-filter")) {
5491 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005492 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5493 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005494 return null;
5495 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005496 if (visibleToEphemeral) {
5497 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5498 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005499 }
Todd Kennedy6d418b62018-02-22 14:15:18 -08005500 s.order = Math.max(intent.getOrder(), s.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005501 s.intents.add(intent);
5502 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005503 if ((s.metaData=parseMetaData(res, parser, s.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005504 outError)) == null) {
5505 return null;
5506 }
5507 } else {
5508 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005509 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005510 + parser.getName() + " at " + mArchiveSourcePath + " "
5511 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005512 XmlUtils.skipCurrentTag(parser);
5513 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005514 } else {
5515 outError[0] = "Bad element under <service>: " + parser.getName();
5516 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005517 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005518 }
5519 }
5520
5521 if (!setExported) {
5522 s.info.exported = s.intents.size() > 0;
5523 }
5524
5525 return s;
5526 }
5527
Chad Brubaker49414832017-04-13 16:13:23 -07005528 private boolean isImplicitlyExposedIntent(IntentInfo intent) {
5529 return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
5530 || intent.hasAction(Intent.ACTION_SEND)
5531 || intent.hasAction(Intent.ACTION_SENDTO)
5532 || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005533 }
5534
Svet Ganov354cd3c2015-12-17 11:35:04 -08005535 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
5536 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005537 int outerDepth = parser.getDepth();
5538 int type;
5539 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5540 && (type != XmlPullParser.END_TAG
5541 || parser.getDepth() > outerDepth)) {
5542 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5543 continue;
5544 }
5545
5546 if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005547 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005548 outInfo.metaData, outError)) == null) {
5549 return false;
5550 }
5551 } else {
5552 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005553 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005554 + parser.getName() + " at " + mArchiveSourcePath + " "
5555 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005556 XmlUtils.skipCurrentTag(parser);
5557 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005558 } else {
5559 outError[0] = "Bad element under " + tag + ": " + parser.getName();
5560 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005562 }
5563 }
5564 return true;
5565 }
5566
5567 private Bundle parseMetaData(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08005568 XmlResourceParser parser, Bundle data, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005569 throws XmlPullParserException, IOException {
5570
Svet Ganov354cd3c2015-12-17 11:35:04 -08005571 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005572 com.android.internal.R.styleable.AndroidManifestMetaData);
5573
5574 if (data == null) {
5575 data = new Bundle();
5576 }
5577
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005578 String name = sa.getNonConfigurationString(
5579 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005580 if (name == null) {
5581 outError[0] = "<meta-data> requires an android:name attribute";
5582 sa.recycle();
5583 return null;
5584 }
5585
Dianne Hackborn854060af2009-07-09 18:14:31 -07005586 name = name.intern();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005588 TypedValue v = sa.peekValue(
5589 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
5590 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005591 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005592 data.putInt(name, v.resourceId);
5593 } else {
5594 v = sa.peekValue(
5595 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07005596 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 if (v != null) {
5598 if (v.type == TypedValue.TYPE_STRING) {
5599 CharSequence cs = v.coerceToString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00005600 data.putString(name, cs != null ? cs.toString() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005601 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
5602 data.putBoolean(name, v.data != 0);
5603 } else if (v.type >= TypedValue.TYPE_FIRST_INT
5604 && v.type <= TypedValue.TYPE_LAST_INT) {
5605 data.putInt(name, v.data);
5606 } else if (v.type == TypedValue.TYPE_FLOAT) {
5607 data.putFloat(name, v.getFloat());
5608 } else {
5609 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005610 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005611 + parser.getName() + " at " + mArchiveSourcePath + " "
5612 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005613 } else {
5614 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
5615 data = null;
5616 }
5617 }
5618 } else {
5619 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
5620 data = null;
5621 }
5622 }
5623
5624 sa.recycle();
5625
5626 XmlUtils.skipCurrentTag(parser);
5627
5628 return data;
5629 }
5630
Adam Lesinski4e862812016-11-21 16:02:24 -08005631 private static VerifierInfo parseVerifier(AttributeSet attrs) {
5632 String packageName = null;
5633 String encodedPublicKey = null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005634
Adam Lesinski4e862812016-11-21 16:02:24 -08005635 final int attrCount = attrs.getAttributeCount();
5636 for (int i = 0; i < attrCount; i++) {
5637 final int attrResId = attrs.getAttributeNameResource(i);
5638 switch (attrResId) {
5639 case com.android.internal.R.attr.name:
5640 packageName = attrs.getAttributeValue(i);
5641 break;
Kenny Root05ca4c92011-09-15 10:36:25 -07005642
Adam Lesinski4e862812016-11-21 16:02:24 -08005643 case com.android.internal.R.attr.publicKey:
5644 encodedPublicKey = attrs.getAttributeValue(i);
5645 break;
5646 }
5647 }
Kenny Root05ca4c92011-09-15 10:36:25 -07005648
5649 if (packageName == null || packageName.length() == 0) {
5650 Slog.i(TAG, "verifier package name was null; skipping");
5651 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005652 }
5653
Christopher Tate30147332014-04-15 12:57:47 -07005654 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
5655 if (publicKey == null) {
5656 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
5657 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08005658 }
5659
Christopher Tate30147332014-04-15 12:57:47 -07005660 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08005661 }
5662
Christopher Tate30147332014-04-15 12:57:47 -07005663 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
5664 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07005665 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07005666 return null;
5667 }
5668
Kenny Root05ca4c92011-09-15 10:36:25 -07005669 EncodedKeySpec keySpec;
5670 try {
5671 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
5672 keySpec = new X509EncodedKeySpec(encoded);
5673 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07005674 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07005675 return null;
5676 }
5677
5678 /* First try the key as an RSA key. */
5679 try {
5680 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005681 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005682 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005683 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005684 } catch (InvalidKeySpecException e) {
5685 // Not a RSA public key.
5686 }
5687
dcashman1616f302015-05-29 14:47:23 -07005688 /* Now try it as a ECDSA key. */
5689 try {
5690 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
5691 return keyFactory.generatePublic(keySpec);
5692 } catch (NoSuchAlgorithmException e) {
5693 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
5694 } catch (InvalidKeySpecException e) {
5695 // Not a ECDSA public key.
5696 }
5697
Kenny Root05ca4c92011-09-15 10:36:25 -07005698 /* Now try it as a DSA key. */
5699 try {
5700 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005701 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005702 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005703 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005704 } catch (InvalidKeySpecException e) {
5705 // Not a DSA public key.
5706 }
5707
dcashman1616f302015-05-29 14:47:23 -07005708 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07005709 return null;
5710 }
5711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005712 private static final String ANDROID_RESOURCES
5713 = "http://schemas.android.com/apk/res/android";
5714
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005715 private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs,
5716 boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
5717 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005718
Svet Ganov354cd3c2015-12-17 11:35:04 -08005719 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005720 com.android.internal.R.styleable.AndroidManifestIntentFilter);
5721
5722 int priority = sa.getInt(
5723 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005724 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08005725
Todd Kennedy6d418b62018-02-22 14:15:18 -08005726 int order = sa.getInt(
5727 com.android.internal.R.styleable.AndroidManifestIntentFilter_order, 0);
5728 outInfo.setOrder(order);
5729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005730 TypedValue v = sa.peekValue(
5731 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
5732 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
5733 outInfo.nonLocalizedLabel = v.coerceToString();
5734 }
5735
Hyunyoung Song929de7a2019-03-21 23:51:27 -07005736 int roundIconVal = sUseRoundIcon ? sa.getResourceId(
Todd Kennedya83bfca2016-06-03 07:52:17 -07005737 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
5738 if (roundIconVal != 0) {
5739 outInfo.icon = roundIconVal;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005740 } else {
5741 outInfo.icon = sa.getResourceId(
5742 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
5743 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005744
Adam Powell81cd2e92010-04-21 16:35:18 -07005745 outInfo.logo = sa.getResourceId(
5746 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005747
Jose Limaf78e3122014-03-06 12:13:15 -08005748 outInfo.banner = sa.getResourceId(
5749 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
5750
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08005751 if (allowAutoVerify) {
5752 outInfo.setAutoVerify(sa.getBoolean(
5753 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
5754 false));
5755 }
5756
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005757 sa.recycle();
5758
5759 int outerDepth = parser.getDepth();
5760 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07005761 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
5762 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
5763 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005764 continue;
5765 }
5766
5767 String nodeName = parser.getName();
5768 if (nodeName.equals("action")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005769 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005770 ANDROID_RESOURCES, "name");
5771 if (value == null || value == "") {
5772 outError[0] = "No value supplied for <android:name>";
5773 return false;
5774 }
5775 XmlUtils.skipCurrentTag(parser);
5776
5777 outInfo.addAction(value);
5778 } else if (nodeName.equals("category")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005779 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005780 ANDROID_RESOURCES, "name");
5781 if (value == null || value == "") {
5782 outError[0] = "No value supplied for <android:name>";
5783 return false;
5784 }
5785 XmlUtils.skipCurrentTag(parser);
5786
5787 outInfo.addCategory(value);
5788
5789 } else if (nodeName.equals("data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005790 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 com.android.internal.R.styleable.AndroidManifestData);
5792
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005793 String str = sa.getNonConfigurationString(
5794 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005795 if (str != null) {
5796 try {
5797 outInfo.addDataType(str);
5798 } catch (IntentFilter.MalformedMimeTypeException e) {
5799 outError[0] = e.toString();
5800 sa.recycle();
5801 return false;
5802 }
5803 }
5804
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005805 str = sa.getNonConfigurationString(
5806 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005807 if (str != null) {
5808 outInfo.addDataScheme(str);
5809 }
5810
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005811 str = sa.getNonConfigurationString(
5812 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
5813 if (str != null) {
5814 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
5815 }
5816
5817 str = sa.getNonConfigurationString(
5818 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
5819 if (str != null) {
5820 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
5821 }
5822
5823 str = sa.getNonConfigurationString(
5824 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
5825 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005826 if (!allowGlobs) {
5827 outError[0] = "sspPattern not allowed here; ssp must be literal";
5828 return false;
5829 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005830 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5831 }
5832
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005833 String host = sa.getNonConfigurationString(
5834 com.android.internal.R.styleable.AndroidManifestData_host, 0);
5835 String port = sa.getNonConfigurationString(
5836 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005837 if (host != null) {
5838 outInfo.addDataAuthority(host, port);
5839 }
5840
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005841 str = sa.getNonConfigurationString(
5842 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005843 if (str != null) {
5844 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
5845 }
5846
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005847 str = sa.getNonConfigurationString(
5848 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005849 if (str != null) {
5850 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
5851 }
5852
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005853 str = sa.getNonConfigurationString(
5854 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005855 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005856 if (!allowGlobs) {
5857 outError[0] = "pathPattern not allowed here; path must be literal";
5858 return false;
5859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5861 }
5862
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005863 str = sa.getNonConfigurationString(
5864 com.android.internal.R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
5865 if (str != null) {
5866 if (!allowGlobs) {
5867 outError[0] = "pathAdvancedPattern not allowed here; path must be literal";
5868 return false;
5869 }
5870 outInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
5871 }
5872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005873 sa.recycle();
5874 XmlUtils.skipCurrentTag(parser);
5875 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005876 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005877 + parser.getName() + " at " + mArchiveSourcePath + " "
5878 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005879 XmlUtils.skipCurrentTag(parser);
5880 } else {
5881 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
5882 return false;
5883 }
5884 }
5885
5886 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07005887
5888 if (DEBUG_PARSER) {
5889 final StringBuilder cats = new StringBuilder("Intent d=");
5890 cats.append(outInfo.hasDefault);
5891 cats.append(", cat=");
5892
5893 final Iterator<String> it = outInfo.categoriesIterator();
5894 if (it != null) {
5895 while (it.hasNext()) {
5896 cats.append(' ');
5897 cats.append(it.next());
5898 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005899 }
Kenny Rootd2d29252011-08-08 11:27:57 -07005900 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005901 }
5902
5903 return true;
5904 }
5905
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005906 /**
5907 * A container for signing-related data of an application package.
5908 * @hide
5909 */
Patrick Baumann47117fc2017-12-19 10:17:21 -08005910 public static final class SigningDetails implements Parcelable {
5911
5912 @IntDef({SigningDetails.SignatureSchemeVersion.UNKNOWN,
5913 SigningDetails.SignatureSchemeVersion.JAR,
5914 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2,
5915 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3})
5916 public @interface SignatureSchemeVersion {
5917 int UNKNOWN = 0;
5918 int JAR = 1;
5919 int SIGNING_BLOCK_V2 = 2;
5920 int SIGNING_BLOCK_V3 = 3;
5921 }
5922
5923 @Nullable
Mathew Inwood5c0d3542018-08-14 13:54:31 +01005924 @UnsupportedAppUsage
Patrick Baumann47117fc2017-12-19 10:17:21 -08005925 public final Signature[] signatures;
5926 @SignatureSchemeVersion
5927 public final int signatureSchemeVersion;
5928 @Nullable
5929 public final ArraySet<PublicKey> publicKeys;
5930
Daniel Cashman77029c52018-01-18 16:19:29 -08005931 /**
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005932 * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
5933 * contains two pieces of information:
5934 * 1) the past signing certificates
5935 * 2) the flags that APK wants to assign to each of the past signing certificates.
5936 *
5937 * This collection of {@code Signature} objects, each of which is formed from a former
5938 * signing certificate of this APK before it was changed by signing certificate rotation,
5939 * represents the first piece of information. It is the APK saying to the rest of the
5940 * world: "hey if you trust the old cert, you can trust me!" This is useful, if for
5941 * instance, the platform would like to determine whether or not to allow this APK to do
5942 * something it would've allowed it to do under the old cert (like upgrade).
Daniel Cashman77029c52018-01-18 16:19:29 -08005943 */
5944 @Nullable
5945 public final Signature[] pastSigningCertificates;
5946
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005947 /** special value used to see if cert is in package - not exposed to callers */
5948 private static final int PAST_CERT_EXISTS = 0;
5949
5950 @IntDef(
5951 flag = true,
5952 value = {CertCapabilities.INSTALLED_DATA,
5953 CertCapabilities.SHARED_USER_ID,
Daniel Cashman629a5f92018-03-30 18:54:14 -07005954 CertCapabilities.PERMISSION,
5955 CertCapabilities.ROLLBACK})
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005956 public @interface CertCapabilities {
5957
5958 /** accept data from already installed pkg with this cert */
5959 int INSTALLED_DATA = 1;
5960
5961 /** accept sharedUserId with pkg with this cert */
5962 int SHARED_USER_ID = 2;
5963
5964 /** grant SIGNATURE permissions to pkgs with this cert */
5965 int PERMISSION = 4;
Daniel Cashman629a5f92018-03-30 18:54:14 -07005966
5967 /** allow pkg to update to one signed by this certificate */
5968 int ROLLBACK = 8;
Dan Cashman303c4bb2018-04-10 07:41:16 -07005969
5970 /** allow pkg to continue to have auth access gated by this cert */
5971 int AUTH = 16;
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005972 }
5973
Patrick Baumann47117fc2017-12-19 10:17:21 -08005974 /** A representation of unknown signing details. Use instead of null. */
5975 public static final SigningDetails UNKNOWN =
Michael Groovera117b0d2018-07-23 12:55:54 -07005976 new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005977
5978 @VisibleForTesting
5979 public SigningDetails(Signature[] signatures,
5980 @SignatureSchemeVersion int signatureSchemeVersion,
Michael Groovera117b0d2018-07-23 12:55:54 -07005981 ArraySet<PublicKey> keys, Signature[] pastSigningCertificates) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08005982 this.signatures = signatures;
5983 this.signatureSchemeVersion = signatureSchemeVersion;
5984 this.publicKeys = keys;
Daniel Cashman77029c52018-01-18 16:19:29 -08005985 this.pastSigningCertificates = pastSigningCertificates;
Daniel Cashman77029c52018-01-18 16:19:29 -08005986 }
5987
5988 public SigningDetails(Signature[] signatures,
5989 @SignatureSchemeVersion int signatureSchemeVersion,
Michael Groovera117b0d2018-07-23 12:55:54 -07005990 Signature[] pastSigningCertificates)
Daniel Cashman77029c52018-01-18 16:19:29 -08005991 throws CertificateException {
5992 this(signatures, signatureSchemeVersion, toSigningKeys(signatures),
Michael Groovera117b0d2018-07-23 12:55:54 -07005993 pastSigningCertificates);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005994 }
5995
5996 public SigningDetails(Signature[] signatures,
5997 @SignatureSchemeVersion int signatureSchemeVersion)
5998 throws CertificateException {
Michael Groovera117b0d2018-07-23 12:55:54 -07005999 this(signatures, signatureSchemeVersion, null);
Daniel Cashman77029c52018-01-18 16:19:29 -08006000 }
6001
6002 public SigningDetails(SigningDetails orig) {
6003 if (orig != null) {
6004 if (orig.signatures != null) {
6005 this.signatures = orig.signatures.clone();
6006 } else {
6007 this.signatures = null;
6008 }
6009 this.signatureSchemeVersion = orig.signatureSchemeVersion;
6010 this.publicKeys = new ArraySet<>(orig.publicKeys);
6011 if (orig.pastSigningCertificates != null) {
6012 this.pastSigningCertificates = orig.pastSigningCertificates.clone();
Daniel Cashman77029c52018-01-18 16:19:29 -08006013 } else {
6014 this.pastSigningCertificates = null;
Daniel Cashman77029c52018-01-18 16:19:29 -08006015 }
6016 } else {
6017 this.signatures = null;
6018 this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
6019 this.publicKeys = null;
6020 this.pastSigningCertificates = null;
Daniel Cashman77029c52018-01-18 16:19:29 -08006021 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08006022 }
6023
6024 /** Returns true if the signing details have one or more signatures. */
6025 public boolean hasSignatures() {
6026 return signatures != null && signatures.length > 0;
6027 }
6028
Daniel Cashman5cdda342018-01-19 07:22:52 -08006029 /** Returns true if the signing details have past signing certificates. */
6030 public boolean hasPastSigningCertificates() {
6031 return pastSigningCertificates != null && pastSigningCertificates.length > 0;
6032 }
6033
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006034 /**
6035 * Determines if the provided {@code oldDetails} is an ancestor of or the same as this one.
6036 * If the {@code oldDetails} signing certificate appears in our pastSigningCertificates,
6037 * then that means it has authorized a signing certificate rotation, which eventually leads
6038 * to our certificate, and thus can be trusted. If this method evaluates to true, this
6039 * SigningDetails object should be trusted if the previous one is.
6040 */
6041 public boolean hasAncestorOrSelf(SigningDetails oldDetails) {
6042 if (this == UNKNOWN || oldDetails == UNKNOWN) {
6043 return false;
6044 }
6045 if (oldDetails.signatures.length > 1) {
6046
6047 // multiple-signer packages cannot rotate signing certs, so we just compare current
6048 // signers for an exact match
6049 return signaturesMatchExactly(oldDetails);
6050 } else {
6051
6052 // we may have signing certificate rotation history, check to see if the oldDetails
6053 // was one of our old signing certificates
6054 return hasCertificate(oldDetails.signatures[0]);
6055 }
6056 }
6057
6058 /**
6059 * Similar to {@code hasAncestorOrSelf}. Returns true only if this {@code SigningDetails}
6060 * is a descendant of {@code oldDetails}, not if they're the same. This is used to
6061 * determine if this object is newer than the provided one.
6062 */
6063 public boolean hasAncestor(SigningDetails oldDetails) {
6064 if (this == UNKNOWN || oldDetails == UNKNOWN) {
6065 return false;
6066 }
6067 if (this.hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
6068
6069 // the last entry in pastSigningCertificates is the current signer, ignore it
6070 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
6071 if (pastSigningCertificates[i].equals(oldDetails.signatures[i])) {
6072 return true;
6073 }
6074 }
6075 }
6076 return false;
6077 }
6078
6079 /**
6080 * Determines if the provided {@code oldDetails} is an ancestor of this one, and whether or
6081 * not this one grants it the provided capability, represented by the {@code flags}
6082 * parameter. In the event of signing certificate rotation, a package may still interact
6083 * with entities signed by its old signing certificate and not want to break previously
6084 * functioning behavior. The {@code flags} value determines which capabilities the app
6085 * signed by the newer signing certificate would like to continue to give to its previous
6086 * signing certificate(s).
6087 */
6088 public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) {
6089 if (this == UNKNOWN || oldDetails == UNKNOWN) {
6090 return false;
6091 }
6092 if (oldDetails.signatures.length > 1) {
6093
6094 // multiple-signer packages cannot rotate signing certs, so we must have an exact
6095 // match, which also means all capabilities are granted
6096 return signaturesMatchExactly(oldDetails);
6097 } else {
6098
6099 // we may have signing certificate rotation history, check to see if the oldDetails
6100 // was one of our old signing certificates, and if we grant it the capability it's
6101 // requesting
6102 return hasCertificate(oldDetails.signatures[0], flags);
6103 }
6104 }
6105
6106 /**
6107 * A special case of {@code checkCapability} which re-encodes both sets of signing
6108 * certificates to counteract a previous re-encoding.
6109 */
6110 public boolean checkCapabilityRecover(SigningDetails oldDetails,
6111 @CertCapabilities int flags) throws CertificateException {
6112 if (oldDetails == UNKNOWN || this == UNKNOWN) {
6113 return false;
6114 }
6115 if (hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
6116
6117 // signing certificates may have rotated, check entire history for effective match
6118 for (int i = 0; i < pastSigningCertificates.length; i++) {
6119 if (Signature.areEffectiveMatch(
6120 oldDetails.signatures[0],
6121 pastSigningCertificates[i])
Michael Groovera117b0d2018-07-23 12:55:54 -07006122 && pastSigningCertificates[i].getFlags() == flags) {
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006123 return true;
6124 }
6125 }
6126 } else {
6127 return Signature.areEffectiveMatch(oldDetails.signatures, signatures);
6128 }
6129 return false;
6130 }
6131
6132 /**
6133 * Determine if {@code signature} is in this SigningDetails' signing certificate history,
6134 * including the current signer. Automatically returns false if this object has multiple
6135 * signing certificates, since rotation is only supported for single-signers; this is
6136 * enforced by {@code hasCertificateInternal}.
6137 */
6138 public boolean hasCertificate(Signature signature) {
6139 return hasCertificateInternal(signature, PAST_CERT_EXISTS);
6140 }
6141
6142 /**
6143 * Determine if {@code signature} is in this SigningDetails' signing certificate history,
6144 * including the current signer, and whether or not it has the given permission.
6145 * Certificates which match our current signer automatically get all capabilities.
6146 * Automatically returns false if this object has multiple signing certificates, since
6147 * rotation is only supported for single-signers.
6148 */
6149 public boolean hasCertificate(Signature signature, @CertCapabilities int flags) {
6150 return hasCertificateInternal(signature, flags);
6151 }
6152
6153 /** Convenient wrapper for calling {@code hasCertificate} with certificate's raw bytes. */
6154 public boolean hasCertificate(byte[] certificate) {
6155 Signature signature = new Signature(certificate);
6156 return hasCertificate(signature);
6157 }
6158
6159 private boolean hasCertificateInternal(Signature signature, int flags) {
6160 if (this == UNKNOWN) {
6161 return false;
6162 }
6163
6164 // only single-signed apps can have pastSigningCertificates
6165 if (hasPastSigningCertificates()) {
6166
6167 // check all past certs, except for the current one, which automatically gets all
6168 // capabilities, since it is the same as the current signature
6169 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
6170 if (pastSigningCertificates[i].equals(signature)) {
6171 if (flags == PAST_CERT_EXISTS
Michael Groovera117b0d2018-07-23 12:55:54 -07006172 || (flags & pastSigningCertificates[i].getFlags()) == flags) {
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006173 return true;
6174 }
6175 }
6176 }
6177 }
6178
6179 // not in previous certs signing history, just check the current signer and make sure
6180 // we are singly-signed
6181 return signatures.length == 1 && signatures[0].equals(signature);
6182 }
6183
6184 /**
6185 * Determines if the provided {@code sha256String} is an ancestor of this one, and whether
6186 * or not this one grants it the provided capability, represented by the {@code flags}
6187 * parameter. In the event of signing certificate rotation, a package may still interact
6188 * with entities signed by its old signing certificate and not want to break previously
6189 * functioning behavior. The {@code flags} value determines which capabilities the app
6190 * signed by the newer signing certificate would like to continue to give to its previous
6191 * signing certificate(s).
6192 *
6193 * @param sha256String A hex-encoded representation of a sha256 digest. In the case of an
6194 * app with multiple signers, this represents the hex-encoded sha256
6195 * digest of the combined hex-encoded sha256 digests of each individual
6196 * signing certificate according to {@link
6197 * PackageUtils#computeSignaturesSha256Digest(Signature[])}
6198 */
6199 public boolean checkCapability(String sha256String, @CertCapabilities int flags) {
6200 if (this == UNKNOWN) {
6201 return false;
6202 }
6203
6204 // first see if the hash represents a single-signer in our signing history
Neil Fuller2c7cc6e2019-04-11 11:04:06 +01006205 byte[] sha256Bytes = sha256String == null
6206 ? null : HexEncoding.decode(sha256String, false /* allowSingleChar */);
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006207 if (hasSha256Certificate(sha256Bytes, flags)) {
6208 return true;
6209 }
6210
6211 // Not in signing history, either represents multiple signatures or not a match.
6212 // Multiple signers can't rotate, so no need to check flags, just see if the SHAs match.
6213 // We already check the single-signer case above as part of hasSha256Certificate, so no
6214 // need to verify we have multiple signers, just run the old check
6215 // just consider current signing certs
6216 final String[] mSignaturesSha256Digests =
6217 PackageUtils.computeSignaturesSha256Digests(signatures);
6218 final String mSignaturesSha256Digest =
6219 PackageUtils.computeSignaturesSha256Digest(mSignaturesSha256Digests);
6220 return mSignaturesSha256Digest.equals(sha256String);
6221 }
6222
6223 /**
6224 * Determine if the {@code sha256Certificate} is in this SigningDetails' signing certificate
6225 * history, including the current signer. Automatically returns false if this object has
6226 * multiple signing certificates, since rotation is only supported for single-signers.
6227 */
6228 public boolean hasSha256Certificate(byte[] sha256Certificate) {
6229 return hasSha256CertificateInternal(sha256Certificate, PAST_CERT_EXISTS);
6230 }
6231
6232 /**
6233 * Determine if the {@code sha256Certificate} certificate hash corresponds to a signing
6234 * certificate in this SigningDetails' signing certificate history, including the current
6235 * signer, and whether or not it has the given permission. Certificates which match our
6236 * current signer automatically get all capabilities. Automatically returns false if this
6237 * object has multiple signing certificates, since rotation is only supported for
6238 * single-signers.
6239 */
6240 public boolean hasSha256Certificate(byte[] sha256Certificate, @CertCapabilities int flags) {
6241 return hasSha256CertificateInternal(sha256Certificate, flags);
6242 }
6243
6244 private boolean hasSha256CertificateInternal(byte[] sha256Certificate, int flags) {
6245 if (this == UNKNOWN) {
6246 return false;
6247 }
6248 if (hasPastSigningCertificates()) {
6249
6250 // check all past certs, except for the last one, which automatically gets all
6251 // capabilities, since it is the same as the current signature, and is checked below
6252 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
6253 byte[] digest = PackageUtils.computeSha256DigestBytes(
6254 pastSigningCertificates[i].toByteArray());
6255 if (Arrays.equals(sha256Certificate, digest)) {
6256 if (flags == PAST_CERT_EXISTS
Michael Groovera117b0d2018-07-23 12:55:54 -07006257 || (flags & pastSigningCertificates[i].getFlags()) == flags) {
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006258 return true;
6259 }
6260 }
6261 }
6262 }
6263
6264 // not in previous certs signing history, just check the current signer
6265 if (signatures.length == 1) {
6266 byte[] digest =
6267 PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray());
6268 return Arrays.equals(sha256Certificate, digest);
6269 }
6270 return false;
6271 }
6272
Patrick Baumann47117fc2017-12-19 10:17:21 -08006273 /** Returns true if the signatures in this and other match exactly. */
6274 public boolean signaturesMatchExactly(SigningDetails other) {
6275 return Signature.areExactMatch(this.signatures, other.signatures);
6276 }
6277
6278 @Override
6279 public int describeContents() {
6280 return 0;
6281 }
6282
6283 @Override
6284 public void writeToParcel(Parcel dest, int flags) {
6285 boolean isUnknown = UNKNOWN == this;
6286 dest.writeBoolean(isUnknown);
6287 if (isUnknown) {
6288 return;
6289 }
6290 dest.writeTypedArray(this.signatures, flags);
6291 dest.writeInt(this.signatureSchemeVersion);
6292 dest.writeArraySet(this.publicKeys);
Daniel Cashman77029c52018-01-18 16:19:29 -08006293 dest.writeTypedArray(this.pastSigningCertificates, flags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006294 }
6295
6296 protected SigningDetails(Parcel in) {
6297 final ClassLoader boot = Object.class.getClassLoader();
6298 this.signatures = in.createTypedArray(Signature.CREATOR);
6299 this.signatureSchemeVersion = in.readInt();
6300 this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot);
Daniel Cashman77029c52018-01-18 16:19:29 -08006301 this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006302 }
6303
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07006304 public static final @android.annotation.NonNull Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() {
Patrick Baumann47117fc2017-12-19 10:17:21 -08006305 @Override
6306 public SigningDetails createFromParcel(Parcel source) {
6307 if (source.readBoolean()) {
6308 return UNKNOWN;
6309 }
6310 return new SigningDetails(source);
6311 }
6312
6313 @Override
6314 public SigningDetails[] newArray(int size) {
6315 return new SigningDetails[size];
6316 }
6317 };
6318
6319 @Override
6320 public boolean equals(Object o) {
6321 if (this == o) return true;
6322 if (!(o instanceof SigningDetails)) return false;
6323
6324 SigningDetails that = (SigningDetails) o;
6325
6326 if (signatureSchemeVersion != that.signatureSchemeVersion) return false;
6327 if (!Signature.areExactMatch(signatures, that.signatures)) return false;
Daniel Cashman77029c52018-01-18 16:19:29 -08006328 if (publicKeys != null) {
6329 if (!publicKeys.equals((that.publicKeys))) {
6330 return false;
6331 }
6332 } else if (that.publicKeys != null) {
6333 return false;
6334 }
6335
6336 // can't use Signature.areExactMatch() because order matters with the past signing certs
6337 if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) {
6338 return false;
6339 }
Daniel Cashman77029c52018-01-18 16:19:29 -08006340
6341 return true;
Patrick Baumann47117fc2017-12-19 10:17:21 -08006342 }
6343
6344 @Override
6345 public int hashCode() {
6346 int result = +Arrays.hashCode(signatures);
6347 result = 31 * result + signatureSchemeVersion;
6348 result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0);
Daniel Cashman77029c52018-01-18 16:19:29 -08006349 result = 31 * result + Arrays.hashCode(pastSigningCertificates);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006350 return result;
6351 }
Daniel Cashman77029c52018-01-18 16:19:29 -08006352
6353 /**
6354 * Builder of {@code SigningDetails} instances.
6355 */
6356 public static class Builder {
6357 private Signature[] mSignatures;
6358 private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
6359 private Signature[] mPastSigningCertificates;
Daniel Cashman77029c52018-01-18 16:19:29 -08006360
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006361 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006362 public Builder() {
6363 }
6364
6365 /** get signing certificates used to sign the current APK */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006366 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006367 public Builder setSignatures(Signature[] signatures) {
6368 mSignatures = signatures;
6369 return this;
6370 }
6371
6372 /** set the signature scheme version used to sign the APK */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006373 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006374 public Builder setSignatureSchemeVersion(int signatureSchemeVersion) {
6375 mSignatureSchemeVersion = signatureSchemeVersion;
6376 return this;
6377 }
6378
6379 /** set the signing certificates by which the APK proved it can be authenticated */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006380 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006381 public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
6382 mPastSigningCertificates = pastSigningCertificates;
6383 return this;
6384 }
6385
Daniel Cashman77029c52018-01-18 16:19:29 -08006386 private void checkInvariants() {
6387 // must have signatures and scheme version set
6388 if (mSignatures == null) {
6389 throw new IllegalStateException("SigningDetails requires the current signing"
6390 + " certificates.");
6391 }
Daniel Cashman77029c52018-01-18 16:19:29 -08006392 }
6393 /** build a {@code SigningDetails} object */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006394 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006395 public SigningDetails build()
6396 throws CertificateException {
6397 checkInvariants();
6398 return new SigningDetails(mSignatures, mSignatureSchemeVersion,
Michael Groovera117b0d2018-07-23 12:55:54 -07006399 mPastSigningCertificates);
Daniel Cashman77029c52018-01-18 16:19:29 -08006400 }
6401 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08006402 }
6403
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006404 /**
6405 * Representation of a full package parsed from APK files on disk. A package
6406 * consists of a single base APK, and zero or more split APKs.
6407 */
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006408 public final static class Package implements Parcelable {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006409
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006410 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006411 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006412
Svet Ganov67882122016-12-11 16:36:34 -08006413 // The package name declared in the manifest as the package can be
6414 // renamed, for example static shared libs use synthetic package names.
6415 public String manifestPackageName;
6416
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006417 /** Names of any split APKs, ordered by parsed splitName */
6418 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006419
6420 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07006421
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07006422 public String volumeUuid;
6423
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006424 /**
6425 * Path where this package was found on disk. For monolithic packages
6426 * this is path to single base APK file; for cluster packages this is
6427 * path to the cluster directory.
6428 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006429 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006430
6431 /** Path of base APK */
6432 public String baseCodePath;
6433 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006434 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006435
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006436 /** Revision code of base APK */
6437 public int baseRevisionCode;
6438 /** Revision codes of any split APKs, ordered by parsed splitName */
6439 public int[] splitRevisionCodes;
6440
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006441 /** Flags of any split APKs; ordered by parsed splitName */
6442 public int[] splitFlags;
6443
Alex Klyubinb9f8a522015-02-03 11:12:59 -08006444 /**
6445 * Private flags of any split APKs; ordered by parsed splitName.
6446 *
6447 * {@hide}
6448 */
6449 public int[] splitPrivateFlags;
6450
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006451 public boolean baseHardwareAccelerated;
6452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006453 // For now we only support one application per package.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006454 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006455 public ApplicationInfo applicationInfo = new ApplicationInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006456
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006457 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006458 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006459 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006460 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006461 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006462 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006463 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006464 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006465 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006466 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006467 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006468 public final ArrayList<Service> services = new ArrayList<Service>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006469 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006470 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
6471
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006472 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006473 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
6474
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07006475 /** Permissions requested but not in the manifest. */
6476 public final ArrayList<String> implicitPermissions = new ArrayList<>();
6477
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006478 @UnsupportedAppUsage
Dianne Hackborn854060af2009-07-09 18:14:31 -07006479 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006480
Svet Ganov354cd3c2015-12-17 11:35:04 -08006481 public Package parentPackage;
6482 public ArrayList<Package> childPackages;
6483
Svet Ganov67882122016-12-11 16:36:34 -08006484 public String staticSharedLibName = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006485 public long staticSharedLibVersion = 0;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006486 public ArrayList<String> libraryNames = null;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006487 @UnsupportedAppUsage
Dianne Hackborn49237342009-08-27 20:08:01 -07006488 public ArrayList<String> usesLibraries = null;
Svet Ganov67882122016-12-11 16:36:34 -08006489 public ArrayList<String> usesStaticLibraries = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006490 public long[] usesStaticLibrariesVersions = null;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006491 public String[][] usesStaticLibrariesCertDigests = null;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006492 @UnsupportedAppUsage
Dianne Hackborn49237342009-08-27 20:08:01 -07006493 public ArrayList<String> usesOptionalLibraries = null;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006494 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006495 public String[] usesLibraryFiles = null;
Nicolas Geoffrayabcd58e2018-10-22 10:23:50 +01006496 public ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006497
Dianne Hackbornb09491f2013-07-22 15:30:11 -07006498 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
6499
Dianne Hackbornc1552392010-03-03 16:19:01 -08006500 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006501 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006502 public ArrayList<String> mAdoptPermissions = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006504 // We store the application meta-data independently to avoid multiple unwanted references
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006505 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006506 public Bundle mAppMetaData = null;
6507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006508 // The version code declared for this package.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006509 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006510 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006511
Dianne Hackborn3accca02013-09-20 09:32:11 -07006512 // The major version code declared for this package.
6513 public int mVersionCodeMajor;
6514
6515 // Return long containing mVersionCode and mVersionCodeMajor.
6516 public long getLongVersionCode() {
6517 return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
6518 }
6519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006520 // The version name declared for this package.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006521 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006522 public String mVersionName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006524 // The shared user id that this package wants to use.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006525 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006526 public String mSharedUserId;
6527
6528 // The shared user label that this package wants to use.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006529 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006530 public int mSharedUserLabel;
6531
6532 // Signatures that were read from the package.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006533 @UnsupportedAppUsage
Patrick Baumann47117fc2017-12-19 10:17:21 -08006534 @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006535
6536 // For use by package manager service for quick lookup of
6537 // preferred up order.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006538 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006539 public int mPreferredOrder = 0;
6540
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006541 // For use by package manager to keep track of when a package was last used.
Brian Carlstromca82e612016-04-19 23:16:08 -07006542 public long[] mLastPackageUsageTimeInMills =
6543 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006544
Amith Yamasani13593602012-03-22 16:16:17 -07006545 // // User set enabled state.
6546 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
6547 //
6548 // // Whether the package has been stopped.
6549 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08006550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006551 // Additional data supplied by callers.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006552 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006553 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07006554
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006555 // Applications hardware preferences
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006556 @UnsupportedAppUsage
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006557 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006558
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006559 // Applications requested features
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006560 @UnsupportedAppUsage
Dianne Hackborn49237342009-08-27 20:08:01 -07006561 public ArrayList<FeatureInfo> reqFeatures = null;
6562
Adam Lesinskid3edfde2014-08-08 17:32:44 -07006563 // Applications requested feature groups
6564 public ArrayList<FeatureGroupInfo> featureGroups = null;
6565
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006566 @UnsupportedAppUsage
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08006567 public int installLocation;
6568
Jeff Hao272bf3a2014-10-08 13:34:43 -07006569 public boolean coreApp;
6570
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08006571 /* An app that's required for all users and cannot be uninstalled for a user */
6572 public boolean mRequiredForAllUsers;
6573
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006574 /* The restricted account authenticator type that is used by this application */
6575 public String mRestrictedAccountType;
6576
Amith Yamasaniccbe3892013-04-12 17:52:42 -07006577 /* The required account type without which this application will not function */
6578 public String mRequiredAccountType;
6579
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006580 public String mOverlayTarget;
Ryan Mitchella3628462019-01-14 12:19:40 -08006581 public String mOverlayTargetName;
Adrian Roosc84df772018-01-19 21:20:22 +01006582 public String mOverlayCategory;
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006583 public int mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -08006584 public boolean mOverlayIsStatic;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006585
Alan Viveretteb6a25732017-11-21 14:49:24 -05006586 public int mCompileSdkVersion;
6587 public String mCompileSdkVersionCodename;
6588
Geremy Condraf1bcca82013-01-07 22:35:24 -08006589 /**
dcashman989eb3712014-06-17 12:56:12 -07006590 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08006591 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006592 @UnsupportedAppUsage
dcashman989eb3712014-06-17 12:56:12 -07006593 public ArraySet<String> mUpgradeKeySets;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006594 @UnsupportedAppUsage
dcashman989eb3712014-06-17 12:56:12 -07006595 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08006596
Narayan Kamath4903f642014-08-11 13:33:45 +01006597 /**
6598 * The install time abi override for this package, if any.
6599 *
6600 * TODO: This seems like a horrible place to put the abiOverride because
6601 * this isn't something the packageParser parsers. However, this fits in with
6602 * the rest of the PackageManager where package scanning randomly pushes
6603 * and prods fields out of {@code this.applicationInfo}.
6604 */
6605 public String cpuAbiOverride;
Selim Gurun2d291d82016-02-05 17:50:53 -08006606 /**
6607 * The install time abi override to choose 32bit abi's when multiple abi's
6608 * are present. This is only meaningfull for multiarch applications.
6609 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
6610 */
6611 public boolean use32bitAbi;
Narayan Kamath4903f642014-08-11 13:33:45 +01006612
Todd Kennedyfdd241a2016-04-28 12:26:53 -07006613 public byte[] restrictUpdateHash;
6614
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006615 /** Set if the app or any of its components are visible to instant applications. */
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006616 public boolean visibleToInstantApps;
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006617 /** Whether or not the package is a stub and must be replaced by the full version. */
6618 public boolean isStub;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006619
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006620 @UnsupportedAppUsage
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006621 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006622 this.packageName = packageName;
Svet Ganov67882122016-12-11 16:36:34 -08006623 this.manifestPackageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006624 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006625 applicationInfo.uid = -1;
6626 }
6627
Svet Ganov354cd3c2015-12-17 11:35:04 -08006628 public void setApplicationVolumeUuid(String volumeUuid) {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006629 final UUID storageUuid = StorageManager.convert(volumeUuid);
Svet Ganov354cd3c2015-12-17 11:35:04 -08006630 this.applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006631 this.applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006632 if (childPackages != null) {
6633 final int packageCount = childPackages.size();
6634 for (int i = 0; i < packageCount; i++) {
6635 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006636 childPackages.get(i).applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006637 }
6638 }
6639 }
6640
6641 public void setApplicationInfoCodePath(String codePath) {
6642 this.applicationInfo.setCodePath(codePath);
6643 if (childPackages != null) {
6644 final int packageCount = childPackages.size();
6645 for (int i = 0; i < packageCount; i++) {
6646 childPackages.get(i).applicationInfo.setCodePath(codePath);
6647 }
6648 }
6649 }
6650
Todd Kennedy30a23a52018-01-04 13:27:49 -08006651 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6652 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006653 public void setApplicationInfoResourcePath(String resourcePath) {
6654 this.applicationInfo.setResourcePath(resourcePath);
6655 if (childPackages != null) {
6656 final int packageCount = childPackages.size();
6657 for (int i = 0; i < packageCount; i++) {
6658 childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
6659 }
6660 }
6661 }
6662
Todd Kennedy30a23a52018-01-04 13:27:49 -08006663 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6664 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006665 public void setApplicationInfoBaseResourcePath(String resourcePath) {
6666 this.applicationInfo.setBaseResourcePath(resourcePath);
6667 if (childPackages != null) {
6668 final int packageCount = childPackages.size();
6669 for (int i = 0; i < packageCount; i++) {
6670 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
6671 }
6672 }
6673 }
6674
6675 public void setApplicationInfoBaseCodePath(String baseCodePath) {
6676 this.applicationInfo.setBaseCodePath(baseCodePath);
6677 if (childPackages != null) {
6678 final int packageCount = childPackages.size();
6679 for (int i = 0; i < packageCount; i++) {
6680 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
6681 }
6682 }
6683 }
6684
Todd Kennedy13715d52016-08-01 13:38:57 -07006685 public List<String> getChildPackageNames() {
6686 if (childPackages == null) {
6687 return null;
6688 }
6689 final int childCount = childPackages.size();
6690 final List<String> childPackageNames = new ArrayList<>(childCount);
6691 for (int i = 0; i < childCount; i++) {
6692 String childPackageName = childPackages.get(i).packageName;
6693 childPackageNames.add(childPackageName);
6694 }
6695 return childPackageNames;
6696 }
6697
Svet Ganov354cd3c2015-12-17 11:35:04 -08006698 public boolean hasChildPackage(String packageName) {
6699 final int childCount = (childPackages != null) ? childPackages.size() : 0;
6700 for (int i = 0; i < childCount; i++) {
6701 if (childPackages.get(i).packageName.equals(packageName)) {
6702 return true;
6703 }
6704 }
6705 return false;
6706 }
6707
6708 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
6709 this.applicationInfo.setSplitCodePaths(splitCodePaths);
6710 // Children have no splits
6711 }
6712
Todd Kennedy30a23a52018-01-04 13:27:49 -08006713 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6714 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006715 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
6716 this.applicationInfo.setSplitResourcePaths(resroucePaths);
6717 // Children have no splits
6718 }
6719
6720 public void setSplitCodePaths(String[] codePaths) {
6721 this.splitCodePaths = codePaths;
6722 }
6723
6724 public void setCodePath(String codePath) {
6725 this.codePath = codePath;
6726 if (childPackages != null) {
6727 final int packageCount = childPackages.size();
6728 for (int i = 0; i < packageCount; i++) {
6729 childPackages.get(i).codePath = codePath;
6730 }
6731 }
6732 }
6733
6734 public void setBaseCodePath(String baseCodePath) {
6735 this.baseCodePath = baseCodePath;
6736 if (childPackages != null) {
6737 final int packageCount = childPackages.size();
6738 for (int i = 0; i < packageCount; i++) {
6739 childPackages.get(i).baseCodePath = baseCodePath;
6740 }
6741 }
6742 }
6743
Patrick Baumann47117fc2017-12-19 10:17:21 -08006744 /** Sets signing details on the package and any of its children. */
6745 public void setSigningDetails(@NonNull SigningDetails signingDetails) {
6746 mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006747 if (childPackages != null) {
6748 final int packageCount = childPackages.size();
6749 for (int i = 0; i < packageCount; i++) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08006750 childPackages.get(i).mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006751 }
6752 }
6753 }
6754
6755 public void setVolumeUuid(String volumeUuid) {
6756 this.volumeUuid = volumeUuid;
6757 if (childPackages != null) {
6758 final int packageCount = childPackages.size();
6759 for (int i = 0; i < packageCount; i++) {
6760 childPackages.get(i).volumeUuid = volumeUuid;
6761 }
6762 }
6763 }
6764
6765 public void setApplicationInfoFlags(int mask, int flags) {
6766 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
6767 if (childPackages != null) {
6768 final int packageCount = childPackages.size();
6769 for (int i = 0; i < packageCount; i++) {
6770 childPackages.get(i).applicationInfo.flags =
6771 (applicationInfo.flags & ~mask) | (mask & flags);
6772 }
6773 }
6774 }
6775
Selim Gurun75827b22016-02-09 10:55:33 -08006776 public void setUse32bitAbi(boolean use32bitAbi) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006777 this.use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006778 if (childPackages != null) {
6779 final int packageCount = childPackages.size();
6780 for (int i = 0; i < packageCount; i++) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006781 childPackages.get(i).use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006782 }
6783 }
6784 }
6785
Svetoslav Ganov40610e32017-06-20 19:35:51 -07006786 public boolean isLibrary() {
6787 return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
6788 }
6789
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006790 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07006791 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006792 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07006793 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6794 Collections.addAll(paths, splitCodePaths);
6795 }
6796 return paths;
6797 }
6798
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006799 /**
6800 * Filtered set of {@link #getAllCodePaths()} that excludes
6801 * resource-only APKs.
6802 */
6803 public List<String> getAllCodePathsExcludingResourceOnly() {
6804 ArrayList<String> paths = new ArrayList<>();
6805 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6806 paths.add(baseCodePath);
6807 }
6808 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6809 for (int i = 0; i < splitCodePaths.length; i++) {
6810 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6811 paths.add(splitCodePaths[i]);
6812 }
6813 }
6814 }
6815 return paths;
6816 }
6817
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006818 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006819 public void setPackageName(String newName) {
6820 packageName = newName;
6821 applicationInfo.packageName = newName;
6822 for (int i=permissions.size()-1; i>=0; i--) {
6823 permissions.get(i).setPackageName(newName);
6824 }
6825 for (int i=permissionGroups.size()-1; i>=0; i--) {
6826 permissionGroups.get(i).setPackageName(newName);
6827 }
6828 for (int i=activities.size()-1; i>=0; i--) {
6829 activities.get(i).setPackageName(newName);
6830 }
6831 for (int i=receivers.size()-1; i>=0; i--) {
6832 receivers.get(i).setPackageName(newName);
6833 }
6834 for (int i=providers.size()-1; i>=0; i--) {
6835 providers.get(i).setPackageName(newName);
6836 }
6837 for (int i=services.size()-1; i>=0; i--) {
6838 services.get(i).setPackageName(newName);
6839 }
6840 for (int i=instrumentation.size()-1; i>=0; i--) {
6841 instrumentation.get(i).setPackageName(newName);
6842 }
6843 }
Dianne Hackborn65696252012-03-05 18:49:21 -08006844
6845 public boolean hasComponentClassName(String name) {
6846 for (int i=activities.size()-1; i>=0; i--) {
6847 if (name.equals(activities.get(i).className)) {
6848 return true;
6849 }
6850 }
6851 for (int i=receivers.size()-1; i>=0; i--) {
6852 if (name.equals(receivers.get(i).className)) {
6853 return true;
6854 }
6855 }
6856 for (int i=providers.size()-1; i>=0; i--) {
6857 if (name.equals(providers.get(i).className)) {
6858 return true;
6859 }
6860 }
6861 for (int i=services.size()-1; i>=0; i--) {
6862 if (name.equals(services.get(i).className)) {
6863 return true;
6864 }
6865 }
6866 for (int i=instrumentation.size()-1; i>=0; i--) {
6867 if (name.equals(instrumentation.get(i).className)) {
6868 return true;
6869 }
6870 }
6871 return false;
6872 }
6873
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006874 /** @hide */
6875 public boolean isExternal() {
6876 return applicationInfo.isExternal();
6877 }
6878
6879 /** @hide */
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08006880 public boolean isForwardLocked() {
Patrick Baumannfc2851e2018-11-13 15:23:22 -08006881 return false;
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08006882 }
6883
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006884 /** @hide */
6885 public boolean isOem() {
6886 return applicationInfo.isOem();
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006887 }
6888
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006889 /** @hide */
Jiyong Park002fdbd2017-02-13 20:50:31 +09006890 public boolean isVendor() {
6891 return applicationInfo.isVendor();
6892 }
6893
6894 /** @hide */
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09006895 public boolean isProduct() {
6896 return applicationInfo.isProduct();
6897 }
6898
6899 /** @hide */
Jeongik Chaf6629832019-07-04 21:12:06 +09006900 public boolean isSystemExt() {
6901 return applicationInfo.isSystemExt();
Dario Freni2bef1762018-06-01 14:02:08 +01006902 }
6903
6904 /** @hide */
MÃ¥rten Kongstad48c24cf2019-02-25 10:54:09 +01006905 public boolean isOdm() {
6906 return applicationInfo.isOdm();
6907 }
6908
6909 /** @hide */
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006910 public boolean isPrivileged() {
Svet Ganovadc1cf42015-06-15 16:36:24 -07006911 return applicationInfo.isPrivilegedApp();
6912 }
6913
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006914 /** @hide */
6915 public boolean isSystem() {
6916 return applicationInfo.isSystemApp();
6917 }
6918
6919 /** @hide */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006920 public boolean isUpdatedSystemApp() {
6921 return applicationInfo.isUpdatedSystemApp();
6922 }
6923
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006924 /** @hide */
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006925 public boolean canHaveOatDir() {
6926 // The following app types CANNOT have oat directory
6927 // - non-updated system apps
Patrick Baumannfc2851e2018-11-13 15:23:22 -08006928 return !isSystem() || isUpdatedSystemApp();
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006929 }
6930
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006931 public boolean isMatch(int flags) {
6932 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006933 return isSystem();
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006934 }
6935 return true;
6936 }
6937
Brian Carlstromca82e612016-04-19 23:16:08 -07006938 public long getLatestPackageUseTimeInMills() {
6939 long latestUse = 0L;
6940 for (long use : mLastPackageUsageTimeInMills) {
6941 latestUse = Math.max(latestUse, use);
6942 }
6943 return latestUse;
6944 }
6945
David Brazdil90e26992016-04-18 14:08:52 +01006946 public long getLatestForegroundPackageUseTimeInMills() {
6947 int[] foregroundReasons = {
6948 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
6949 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
6950 };
6951
6952 long latestUse = 0L;
6953 for (int reason : foregroundReasons) {
6954 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
6955 }
6956 return latestUse;
6957 }
6958
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006959 public String toString() {
6960 return "Package{"
6961 + Integer.toHexString(System.identityHashCode(this))
6962 + " " + packageName + "}";
6963 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006964
6965 @Override
6966 public int describeContents() {
6967 return 0;
6968 }
6969
6970 public Package(Parcel dest) {
6971 // We use the boot classloader for all classes that we load.
6972 final ClassLoader boot = Object.class.getClassLoader();
6973
Narayan Kamath07ac1442017-02-10 15:08:07 +00006974 packageName = dest.readString().intern();
Svet Ganov67882122016-12-11 16:36:34 -08006975 manifestPackageName = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006976 splitNames = dest.readStringArray();
6977 volumeUuid = dest.readString();
6978 codePath = dest.readString();
6979 baseCodePath = dest.readString();
6980 splitCodePaths = dest.readStringArray();
6981 baseRevisionCode = dest.readInt();
6982 splitRevisionCodes = dest.createIntArray();
6983 splitFlags = dest.createIntArray();
6984 splitPrivateFlags = dest.createIntArray();
6985 baseHardwareAccelerated = (dest.readInt() == 1);
6986 applicationInfo = dest.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006987 if (applicationInfo.permission != null) {
6988 applicationInfo.permission = applicationInfo.permission.intern();
6989 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006990
6991 // We don't serialize the "owner" package and the application info object for each of
6992 // these components, in order to save space and to avoid circular dependencies while
6993 // serialization. We need to fix them all up here.
6994 dest.readParcelableList(permissions, boot);
6995 fixupOwner(permissions);
6996 dest.readParcelableList(permissionGroups, boot);
6997 fixupOwner(permissionGroups);
6998 dest.readParcelableList(activities, boot);
6999 fixupOwner(activities);
7000 dest.readParcelableList(receivers, boot);
7001 fixupOwner(receivers);
7002 dest.readParcelableList(providers, boot);
7003 fixupOwner(providers);
7004 dest.readParcelableList(services, boot);
7005 fixupOwner(services);
7006 dest.readParcelableList(instrumentation, boot);
7007 fixupOwner(instrumentation);
7008
7009 dest.readStringList(requestedPermissions);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007010 internStringArrayList(requestedPermissions);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07007011 dest.readStringList(implicitPermissions);
7012 internStringArrayList(implicitPermissions);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007013 protectedBroadcasts = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007014 internStringArrayList(protectedBroadcasts);
7015
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007016 parentPackage = dest.readParcelable(boot);
7017
7018 childPackages = new ArrayList<>();
7019 dest.readParcelableList(childPackages, boot);
7020 if (childPackages.size() == 0) {
7021 childPackages = null;
7022 }
7023
Svet Ganov67882122016-12-11 16:36:34 -08007024 staticSharedLibName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007025 if (staticSharedLibName != null) {
7026 staticSharedLibName = staticSharedLibName.intern();
7027 }
Dianne Hackborn3accca02013-09-20 09:32:11 -07007028 staticSharedLibVersion = dest.readLong();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007029 libraryNames = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007030 internStringArrayList(libraryNames);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007031 usesLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007032 internStringArrayList(usesLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007033 usesOptionalLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007034 internStringArrayList(usesOptionalLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007035 usesLibraryFiles = dest.readStringArray();
7036
Nicolas Geoffrayabcd58e2018-10-22 10:23:50 +01007037 usesLibraryInfos = dest.createTypedArrayList(SharedLibraryInfo.CREATOR);
7038
Svet Ganov67882122016-12-11 16:36:34 -08007039 final int libCount = dest.readInt();
7040 if (libCount > 0) {
7041 usesStaticLibraries = new ArrayList<>(libCount);
7042 dest.readStringList(usesStaticLibraries);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007043 internStringArrayList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07007044 usesStaticLibrariesVersions = new long[libCount];
7045 dest.readLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07007046 usesStaticLibrariesCertDigests = new String[libCount][];
7047 for (int i = 0; i < libCount; i++) {
7048 usesStaticLibrariesCertDigests[i] = dest.createStringArray();
7049 }
Svet Ganov67882122016-12-11 16:36:34 -08007050 }
7051
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007052 preferredActivityFilters = new ArrayList<>();
7053 dest.readParcelableList(preferredActivityFilters, boot);
7054 if (preferredActivityFilters.size() == 0) {
7055 preferredActivityFilters = null;
7056 }
7057
7058 mOriginalPackages = dest.createStringArrayList();
7059 mRealPackage = dest.readString();
7060 mAdoptPermissions = dest.createStringArrayList();
7061 mAppMetaData = dest.readBundle();
7062 mVersionCode = dest.readInt();
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08007063 mVersionCodeMajor = dest.readInt();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007064 mVersionName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007065 if (mVersionName != null) {
7066 mVersionName = mVersionName.intern();
7067 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007068 mSharedUserId = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007069 if (mSharedUserId != null) {
7070 mSharedUserId = mSharedUserId.intern();
7071 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007072 mSharedUserLabel = dest.readInt();
7073
Patrick Baumann47117fc2017-12-19 10:17:21 -08007074 mSigningDetails = dest.readParcelable(boot);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007075
7076 mPreferredOrder = dest.readInt();
7077
7078 // long[] packageUsageTimeMillis is not persisted because it isn't information that
7079 // is parsed from the APK.
7080
7081 // Object mExtras is not persisted because it is not information that is read from
7082 // the APK, rather, it is supplied by callers.
7083
7084
7085 configPreferences = new ArrayList<>();
7086 dest.readParcelableList(configPreferences, boot);
7087 if (configPreferences.size() == 0) {
7088 configPreferences = null;
7089 }
7090
7091 reqFeatures = new ArrayList<>();
7092 dest.readParcelableList(reqFeatures, boot);
7093 if (reqFeatures.size() == 0) {
7094 reqFeatures = null;
7095 }
7096
7097 featureGroups = new ArrayList<>();
7098 dest.readParcelableList(featureGroups, boot);
7099 if (featureGroups.size() == 0) {
7100 featureGroups = null;
7101 }
7102
7103 installLocation = dest.readInt();
7104 coreApp = (dest.readInt() == 1);
7105 mRequiredForAllUsers = (dest.readInt() == 1);
7106 mRestrictedAccountType = dest.readString();
7107 mRequiredAccountType = dest.readString();
7108 mOverlayTarget = dest.readString();
Ryan Mitchella3628462019-01-14 12:19:40 -08007109 mOverlayTargetName = dest.readString();
Adrian Roosc84df772018-01-19 21:20:22 +01007110 mOverlayCategory = dest.readString();
Jaekyun Seok42d53f62017-04-10 13:48:58 +09007111 mOverlayPriority = dest.readInt();
Adam Lesinskie7334972018-01-17 16:13:52 -08007112 mOverlayIsStatic = (dest.readInt() == 1);
Alan Viveretteb6a25732017-11-21 14:49:24 -05007113 mCompileSdkVersion = dest.readInt();
7114 mCompileSdkVersionCodename = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007115 mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
7116
7117 mKeySetMapping = readKeySetMapping(dest);
7118
7119 cpuAbiOverride = dest.readString();
7120 use32bitAbi = (dest.readInt() == 1);
7121 restrictUpdateHash = dest.createByteArray();
Chad Brubaker49f24c62017-04-05 13:08:21 -07007122 visibleToInstantApps = dest.readInt() == 1;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007123 }
7124
Narayan Kamath07ac1442017-02-10 15:08:07 +00007125 private static void internStringArrayList(List<String> list) {
7126 if (list != null) {
7127 final int N = list.size();
7128 for (int i = 0; i < N; ++i) {
7129 list.set(i, list.get(i).intern());
7130 }
7131 }
7132 }
7133
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007134 /**
7135 * Sets the package owner and the the {@code applicationInfo} for every component
7136 * owner by this package.
7137 */
7138 private void fixupOwner(List<? extends Component<?>> list) {
7139 if (list != null) {
7140 for (Component<?> c : list) {
7141 c.owner = this;
7142 if (c instanceof Activity) {
7143 ((Activity) c).info.applicationInfo = this.applicationInfo;
7144 } else if (c instanceof Service) {
7145 ((Service) c).info.applicationInfo = this.applicationInfo;
7146 } else if (c instanceof Provider) {
7147 ((Provider) c).info.applicationInfo = this.applicationInfo;
7148 }
7149 }
7150 }
7151 }
7152
7153 @Override
7154 public void writeToParcel(Parcel dest, int flags) {
7155 dest.writeString(packageName);
Svet Ganov67882122016-12-11 16:36:34 -08007156 dest.writeString(manifestPackageName);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007157 dest.writeStringArray(splitNames);
7158 dest.writeString(volumeUuid);
7159 dest.writeString(codePath);
7160 dest.writeString(baseCodePath);
7161 dest.writeStringArray(splitCodePaths);
7162 dest.writeInt(baseRevisionCode);
7163 dest.writeIntArray(splitRevisionCodes);
7164 dest.writeIntArray(splitFlags);
7165 dest.writeIntArray(splitPrivateFlags);
7166 dest.writeInt(baseHardwareAccelerated ? 1 : 0);
7167 dest.writeParcelable(applicationInfo, flags);
7168
7169 dest.writeParcelableList(permissions, flags);
7170 dest.writeParcelableList(permissionGroups, flags);
7171 dest.writeParcelableList(activities, flags);
7172 dest.writeParcelableList(receivers, flags);
7173 dest.writeParcelableList(providers, flags);
7174 dest.writeParcelableList(services, flags);
7175 dest.writeParcelableList(instrumentation, flags);
7176
7177 dest.writeStringList(requestedPermissions);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07007178 dest.writeStringList(implicitPermissions);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007179 dest.writeStringList(protectedBroadcasts);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07007180
7181 // TODO: This doesn't work: b/64295061
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007182 dest.writeParcelable(parentPackage, flags);
7183 dest.writeParcelableList(childPackages, flags);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07007184
Svet Ganov67882122016-12-11 16:36:34 -08007185 dest.writeString(staticSharedLibName);
Dianne Hackborn3accca02013-09-20 09:32:11 -07007186 dest.writeLong(staticSharedLibVersion);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007187 dest.writeStringList(libraryNames);
7188 dest.writeStringList(usesLibraries);
7189 dest.writeStringList(usesOptionalLibraries);
7190 dest.writeStringArray(usesLibraryFiles);
Nicolas Geoffrayabcd58e2018-10-22 10:23:50 +01007191 dest.writeTypedList(usesLibraryInfos);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007192
Svet Ganov67882122016-12-11 16:36:34 -08007193 if (ArrayUtils.isEmpty(usesStaticLibraries)) {
7194 dest.writeInt(-1);
7195 } else {
7196 dest.writeInt(usesStaticLibraries.size());
7197 dest.writeStringList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07007198 dest.writeLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07007199 for (String[] usesStaticLibrariesCertDigest : usesStaticLibrariesCertDigests) {
7200 dest.writeStringArray(usesStaticLibrariesCertDigest);
7201 }
Svet Ganov67882122016-12-11 16:36:34 -08007202 }
7203
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007204 dest.writeParcelableList(preferredActivityFilters, flags);
7205
7206 dest.writeStringList(mOriginalPackages);
7207 dest.writeString(mRealPackage);
7208 dest.writeStringList(mAdoptPermissions);
7209 dest.writeBundle(mAppMetaData);
7210 dest.writeInt(mVersionCode);
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08007211 dest.writeInt(mVersionCodeMajor);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007212 dest.writeString(mVersionName);
7213 dest.writeString(mSharedUserId);
7214 dest.writeInt(mSharedUserLabel);
7215
Patrick Baumann47117fc2017-12-19 10:17:21 -08007216 dest.writeParcelable(mSigningDetails, flags);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007217
7218 dest.writeInt(mPreferredOrder);
7219
7220 // long[] packageUsageTimeMillis is not persisted because it isn't information that
7221 // is parsed from the APK.
7222
7223 // Object mExtras is not persisted because it is not information that is read from
7224 // the APK, rather, it is supplied by callers.
7225
7226 dest.writeParcelableList(configPreferences, flags);
7227 dest.writeParcelableList(reqFeatures, flags);
7228 dest.writeParcelableList(featureGroups, flags);
7229
7230 dest.writeInt(installLocation);
7231 dest.writeInt(coreApp ? 1 : 0);
7232 dest.writeInt(mRequiredForAllUsers ? 1 : 0);
7233 dest.writeString(mRestrictedAccountType);
7234 dest.writeString(mRequiredAccountType);
7235 dest.writeString(mOverlayTarget);
Ryan Mitchella3628462019-01-14 12:19:40 -08007236 dest.writeString(mOverlayTargetName);
Adrian Roosc84df772018-01-19 21:20:22 +01007237 dest.writeString(mOverlayCategory);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09007238 dest.writeInt(mOverlayPriority);
Adam Lesinskie7334972018-01-17 16:13:52 -08007239 dest.writeInt(mOverlayIsStatic ? 1 : 0);
Alan Viveretteb6a25732017-11-21 14:49:24 -05007240 dest.writeInt(mCompileSdkVersion);
7241 dest.writeString(mCompileSdkVersionCodename);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007242 dest.writeArraySet(mUpgradeKeySets);
7243 writeKeySetMapping(dest, mKeySetMapping);
7244 dest.writeString(cpuAbiOverride);
7245 dest.writeInt(use32bitAbi ? 1 : 0);
7246 dest.writeByteArray(restrictUpdateHash);
Chad Brubaker49f24c62017-04-05 13:08:21 -07007247 dest.writeInt(visibleToInstantApps ? 1 : 0);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007248 }
7249
7250
7251 /**
7252 * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
7253 */
7254 private static void writeKeySetMapping(
7255 Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
7256 if (keySetMapping == null) {
7257 dest.writeInt(-1);
7258 return;
7259 }
7260
7261 final int N = keySetMapping.size();
7262 dest.writeInt(N);
7263
7264 for (int i = 0; i < N; i++) {
7265 dest.writeString(keySetMapping.keyAt(i));
7266 ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
7267 if (keys == null) {
7268 dest.writeInt(-1);
7269 continue;
7270 }
7271
7272 final int M = keys.size();
7273 dest.writeInt(M);
7274 for (int j = 0; j < M; j++) {
7275 dest.writeSerializable(keys.valueAt(j));
7276 }
7277 }
7278 }
7279
7280 /**
7281 * Reads a keyset mapping from the given parcel at the given data position. May return
7282 * {@code null} if the serialized mapping was {@code null}.
7283 */
7284 private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
7285 final int N = in.readInt();
7286 if (N == -1) {
7287 return null;
7288 }
7289
7290 ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
7291 for (int i = 0; i < N; ++i) {
7292 String key = in.readString();
7293 final int M = in.readInt();
7294 if (M == -1) {
7295 keySetMapping.put(key, null);
7296 continue;
7297 }
7298
7299 ArraySet<PublicKey> keys = new ArraySet<>(M);
7300 for (int j = 0; j < M; ++j) {
7301 PublicKey pk = (PublicKey) in.readSerializable();
7302 keys.add(pk);
7303 }
7304
7305 keySetMapping.put(key, keys);
7306 }
7307
7308 return keySetMapping;
7309 }
7310
7311 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
7312 public Package createFromParcel(Parcel in) {
7313 return new Package(in);
7314 }
7315
7316 public Package[] newArray(int size) {
7317 return new Package[size];
7318 }
7319 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007320 }
7321
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007322 public static abstract class Component<II extends IntentInfo> {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007323 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007324 public final ArrayList<II> intents;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007325 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007326 public final String className;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007327
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007328 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 public Bundle metaData;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007330 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007331 public Package owner;
Todd Kennedy6d418b62018-02-22 14:15:18 -08007332 /** The order of this component in relation to its peers */
7333 public int order;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007334
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007335 ComponentName componentName;
7336 String componentShortName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007337
Ricky Waicf134eb2018-10-10 09:26:32 +01007338 public Component(Package owner, ArrayList<II> intents, String className) {
7339 this.owner = owner;
7340 this.intents = intents;
7341 this.className = className;
7342 }
7343
7344 public Component(Package owner) {
7345 this.owner = owner;
7346 this.intents = null;
7347 this.className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007348 }
7349
7350 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
7351 owner = args.owner;
7352 intents = new ArrayList<II>(0);
Todd Kennedybb8a42d2016-06-02 14:13:56 -07007353 if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
7354 true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
7355 args.roundIconRes, args.logoRes, args.bannerRes)) {
7356 className = outInfo.name;
7357 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007358 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007359 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007360 }
7361
7362 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
7363 this(args, (PackageItemInfo)outInfo);
7364 if (args.outError[0] != null) {
7365 return;
7366 }
7367
7368 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007369 CharSequence pname;
7370 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07007371 pname = args.sa.getNonConfigurationString(args.processRes,
7372 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007373 } else {
7374 // Some older apps have been seen to use a resource reference
7375 // here that on older builds was ignored (with a warning). We
7376 // need to continue to do this for them so they don't break.
7377 pname = args.sa.getNonResourceString(args.processRes);
7378 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007379 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007380 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007381 args.flags, args.sepProcesses, args.outError);
7382 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007383
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08007384 if (args.descriptionRes != 0) {
7385 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
7386 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007387
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007388 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007389 }
7390
7391 public Component(Component<II> clone) {
7392 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007393 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007394 className = clone.className;
7395 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007396 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007397 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007398
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007399 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007400 public ComponentName getComponentName() {
7401 if (componentName != null) {
7402 return componentName;
7403 }
7404 if (className != null) {
7405 componentName = new ComponentName(owner.applicationInfo.packageName,
7406 className);
7407 }
7408 return componentName;
7409 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007410
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007411 protected Component(Parcel in) {
7412 className = in.readString();
7413 metaData = in.readBundle();
7414 intents = createIntentsList(in);
7415
7416 owner = null;
7417 }
7418
7419 protected void writeToParcel(Parcel dest, int flags) {
7420 dest.writeString(className);
7421 dest.writeBundle(metaData);
7422
7423 writeIntentsList(intents, dest, flags);
7424 }
7425
7426 /**
7427 * <p>
7428 * Implementation note: The serialized form for the intent list also contains the name
7429 * of the concrete class that's stored in the list, and assumes that every element of the
7430 * list is of the same type. This is very similar to the original parcelable mechanism.
7431 * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
7432 * and is public API. It also declares Parcelable related methods as final which means
7433 * we can't extend them. The approach of using composition instead of inheritance leads to
7434 * a large set of cascading changes in the PackageManagerService, which seem undesirable.
7435 *
7436 * <p>
7437 * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
7438 * to make sure their owner fields are consistent. See {@code fixupOwner}.
7439 */
7440 private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out,
7441 int flags) {
7442 if (list == null) {
7443 out.writeInt(-1);
7444 return;
7445 }
7446
7447 final int N = list.size();
7448 out.writeInt(N);
7449
7450 // Don't bother writing the component name if the list is empty.
7451 if (N > 0) {
7452 IntentInfo info = list.get(0);
7453 out.writeString(info.getClass().getName());
7454
7455 for (int i = 0; i < N;i++) {
7456 list.get(i).writeIntentInfoToParcel(out, flags);
7457 }
7458 }
7459 }
7460
7461 private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) {
7462 int N = in.readInt();
7463 if (N == -1) {
7464 return null;
7465 }
7466
7467 if (N == 0) {
7468 return new ArrayList<>(0);
7469 }
7470
7471 String componentName = in.readString();
7472 final ArrayList<T> intentsList;
7473 try {
7474 final Class<T> cls = (Class<T>) Class.forName(componentName);
7475 final Constructor<T> cons = cls.getConstructor(Parcel.class);
7476
7477 intentsList = new ArrayList<>(N);
7478 for (int i = 0; i < N; ++i) {
7479 intentsList.add(cons.newInstance(in));
7480 }
7481 } catch (ReflectiveOperationException ree) {
7482 throw new AssertionError("Unable to construct intent list for: " + componentName);
7483 }
7484
7485 return intentsList;
7486 }
7487
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007488 public void appendComponentShortName(StringBuilder sb) {
7489 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007490 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007491
7492 public void printComponentShortName(PrintWriter pw) {
7493 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
7494 }
7495
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007496 public void setPackageName(String packageName) {
7497 componentName = null;
7498 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007499 }
7500 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007501
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007502 public final static class Permission extends Component<IntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007503 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007504 public final PermissionInfo info;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007505 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007506 public boolean tree;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007507 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007508 public PermissionGroup group;
7509
Philip P. Moltmanna4844d12019-03-02 10:17:23 -08007510 /**
7511 * @hide
7512 */
7513 public Permission(Package owner, @Nullable String backgroundPermission) {
7514 super(owner);
7515 info = new PermissionInfo(backgroundPermission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007516 }
7517
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007518 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007519 public Permission(Package _owner, PermissionInfo _info) {
7520 super(_owner);
7521 info = _info;
7522 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007523
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007524 public void setPackageName(String packageName) {
7525 super.setPackageName(packageName);
7526 info.packageName = packageName;
7527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007528
7529 public String toString() {
7530 return "Permission{"
7531 + Integer.toHexString(System.identityHashCode(this))
7532 + " " + info.name + "}";
7533 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007534
7535 @Override
7536 public int describeContents() {
7537 return 0;
7538 }
7539
7540 @Override
7541 public void writeToParcel(Parcel dest, int flags) {
7542 super.writeToParcel(dest, flags);
7543 dest.writeParcelable(info, flags);
7544 dest.writeInt(tree ? 1 : 0);
7545 dest.writeParcelable(group, flags);
7546 }
7547
Todd Kennedyc8423932017-10-05 08:58:36 -07007548 /** @hide */
7549 public boolean isAppOp() {
7550 return info.isAppOp();
7551 }
7552
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007553 private Permission(Parcel in) {
7554 super(in);
7555 final ClassLoader boot = Object.class.getClassLoader();
7556 info = in.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007557 if (info.group != null) {
7558 info.group = info.group.intern();
7559 }
7560
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007561 tree = (in.readInt() == 1);
7562 group = in.readParcelable(boot);
7563 }
7564
7565 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
7566 public Permission createFromParcel(Parcel in) {
7567 return new Permission(in);
7568 }
7569
7570 public Permission[] newArray(int size) {
7571 return new Permission[size];
7572 }
7573 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007574 }
7575
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007576 public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007577 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007578 public final PermissionGroupInfo info;
7579
Philip P. Moltmann0635dab2019-03-02 11:19:03 -08007580 public PermissionGroup(Package owner, @StringRes int requestDetailResourceId,
7581 @StringRes int backgroundRequestResourceId,
7582 @StringRes int backgroundRequestDetailResourceId) {
7583 super(owner);
7584 info = new PermissionGroupInfo(requestDetailResourceId, backgroundRequestResourceId,
7585 backgroundRequestDetailResourceId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007586 }
7587
7588 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
7589 super(_owner);
7590 info = _info;
7591 }
7592
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007593 public void setPackageName(String packageName) {
7594 super.setPackageName(packageName);
7595 info.packageName = packageName;
7596 }
7597
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007598 public String toString() {
7599 return "PermissionGroup{"
7600 + Integer.toHexString(System.identityHashCode(this))
7601 + " " + info.name + "}";
7602 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007603
7604 @Override
7605 public int describeContents() {
7606 return 0;
7607 }
7608
7609 @Override
7610 public void writeToParcel(Parcel dest, int flags) {
7611 super.writeToParcel(dest, flags);
7612 dest.writeParcelable(info, flags);
7613 }
7614
7615 private PermissionGroup(Parcel in) {
7616 super(in);
7617 info = in.readParcelable(Object.class.getClassLoader());
7618 }
7619
7620 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
7621 public PermissionGroup createFromParcel(Parcel in) {
7622 return new PermissionGroup(in);
7623 }
7624
7625 public PermissionGroup[] newArray(int size) {
7626 return new PermissionGroup[size];
7627 }
7628 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007629 }
7630
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007631 private static boolean copyNeeded(int flags, Package p,
7632 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07007633 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007634 // We always need to copy for other users, since we need
7635 // to fix up the uid.
7636 return true;
7637 }
7638 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
7639 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07007640 if (p.applicationInfo.enabled != enabled) {
7641 return true;
7642 }
7643 }
Rubin Xubf67c9c2016-04-20 17:09:38 +01007644 boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
7645 if (state.suspended != suspended) {
7646 return true;
7647 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007648 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007649 return true;
7650 }
7651 if (state.stopped) {
7652 return true;
7653 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007654 if (state.instantApp != p.applicationInfo.isInstantApp()) {
7655 return true;
7656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007657 if ((flags & PackageManager.GET_META_DATA) != 0
7658 && (metaData != null || p.mAppMetaData != null)) {
7659 return true;
7660 }
7661 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7662 && p.usesLibraryFiles != null) {
7663 return true;
7664 }
Nicolas Geoffrayabcd58e2018-10-22 10:23:50 +01007665 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7666 && p.usesLibraryInfos != null) {
7667 return true;
7668 }
Svet Ganov67882122016-12-11 16:36:34 -08007669 if (p.staticSharedLibName != null) {
7670 return true;
7671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007672 return false;
7673 }
7674
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007675 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007676 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
7677 PackageUserState state) {
7678 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07007679 }
7680
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007681 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
7682 PackageUserState state) {
7683 // CompatibilityMode is global state.
7684 if (!sCompatibilityModeEnabled) {
7685 ai.disableCompatibilityMode();
7686 }
7687 if (state.installed) {
7688 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
7689 } else {
7690 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
7691 }
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00007692 if (state.suspended) {
7693 ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
7694 } else {
7695 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
7696 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007697 if (state.instantApp) {
7698 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
7699 } else {
7700 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
7701 }
Todd Kennedy5eb5a7d2017-08-01 07:42:47 -07007702 if (state.virtualPreload) {
7703 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7704 } else {
7705 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7706 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007707 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007708 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007709 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007710 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007711 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007712 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
7713 ai.enabled = true;
7714 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
7715 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
7716 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
7717 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
7718 ai.enabled = false;
7719 }
7720 ai.enabledSetting = state.enabled;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07007721 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7722 ai.category = state.categoryHint;
7723 }
Jeff Sharkey0078e1b2017-01-11 16:05:27 -07007724 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7725 ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
7726 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007727 ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
Todd Kennedyb2749472017-06-13 08:24:32 -07007728 ai.resourceDirs = state.overlayPaths;
Hyunyoung Song929de7a2019-03-21 23:51:27 -07007729 ai.icon = (sUseRoundIcon && ai.roundIconRes != 0) ? ai.roundIconRes : ai.iconRes;
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007730 }
7731
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007732 @UnsupportedAppUsage
Amith Yamasani13593602012-03-22 16:16:17 -07007733 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007734 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007735 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007736 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007737 return null;
7738 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007739 if (!copyNeeded(flags, p, state, null, userId)
7740 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
7741 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
7742 // In this case it is safe to directly modify the internal ApplicationInfo state:
7743 // - CompatibilityMode is global state, so will be the same for every call.
7744 // - We only come in to here if the app should reported as installed; this is the
7745 // default state, and we will do a copy otherwise.
7746 // - The enable state will always be reported the same for the application across
7747 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
7748 // be doing a copy.
7749 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007750 return p.applicationInfo;
7751 }
7752
7753 // Make shallow copy so we can store the metadata/libraries safely
7754 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Jeff Sharkey15447792015-11-05 16:18:51 -08007755 ai.initForUser(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007756 if ((flags & PackageManager.GET_META_DATA) != 0) {
7757 ai.metaData = p.mAppMetaData;
7758 }
7759 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
7760 ai.sharedLibraryFiles = p.usesLibraryFiles;
Nicolas Geoffray8d144eb2018-11-15 12:59:52 +00007761 ai.sharedLibraryInfos = p.usesLibraryInfos;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007762 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007763 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007764 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007765 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007766 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007767 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007768 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007769 return ai;
7770 }
7771
Dianne Hackbornace27912014-09-18 18:38:30 -07007772 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
7773 PackageUserState state, int userId) {
7774 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007775 if (!checkUseInstalledOrHidden(flags, state, ai)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007776 return null;
7777 }
7778 // This is only used to return the ResolverActivity; we will just always
7779 // make a copy.
7780 ai = new ApplicationInfo(ai);
Jeff Sharkey15447792015-11-05 16:18:51 -08007781 ai.initForUser(userId);
Dianne Hackbornace27912014-09-18 18:38:30 -07007782 if (state.stopped) {
7783 ai.flags |= ApplicationInfo.FLAG_STOPPED;
7784 } else {
7785 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
7786 }
7787 updateApplicationInfo(ai, flags, state);
7788 return ai;
7789 }
7790
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007791 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792 public static final PermissionInfo generatePermissionInfo(
7793 Permission p, int flags) {
7794 if (p == null) return null;
7795 if ((flags&PackageManager.GET_META_DATA) == 0) {
7796 return p.info;
7797 }
7798 PermissionInfo pi = new PermissionInfo(p.info);
7799 pi.metaData = p.metaData;
7800 return pi;
7801 }
7802
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007803 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007804 public static final PermissionGroupInfo generatePermissionGroupInfo(
7805 PermissionGroup pg, int flags) {
7806 if (pg == null) return null;
7807 if ((flags&PackageManager.GET_META_DATA) == 0) {
7808 return pg.info;
7809 }
7810 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
7811 pgi.metaData = pg.metaData;
7812 return pgi;
7813 }
7814
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007815 public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007816 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007817 public final ActivityInfo info;
Bryce Lee22571db2017-07-07 15:54:18 -07007818 private boolean mHasMaxAspectRatio;
Adrian Roos917791e2018-11-28 16:30:44 +01007819 private boolean mHasMinAspectRatio;
Bryce Lee22571db2017-07-07 15:54:18 -07007820
7821 private boolean hasMaxAspectRatio() {
7822 return mHasMaxAspectRatio;
7823 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007824
Adrian Roos917791e2018-11-28 16:30:44 +01007825 private boolean hasMinAspectRatio() {
7826 return mHasMinAspectRatio;
7827 }
7828
Ricky Waicf134eb2018-10-10 09:26:32 +01007829 // To construct custom activity which does not exist in manifest
7830 Activity(final Package owner, final String className, final ActivityInfo info) {
7831 super(owner, new ArrayList<>(0), className);
7832 this.info = info;
7833 this.info.applicationInfo = owner.applicationInfo;
7834 }
7835
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007836 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
7837 super(args, _info);
7838 info = _info;
7839 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007840 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007841
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007842 public void setPackageName(String packageName) {
7843 super.setPackageName(packageName);
7844 info.packageName = packageName;
7845 }
7846
Bryce Lee22571db2017-07-07 15:54:18 -07007847
7848 private void setMaxAspectRatio(float maxAspectRatio) {
7849 if (info.resizeMode == RESIZE_MODE_RESIZEABLE
7850 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
7851 // Resizeable activities can be put in any aspect ratio.
7852 return;
7853 }
7854
7855 if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
7856 // Ignore any value lesser than 1.0.
7857 return;
7858 }
7859
7860 info.maxAspectRatio = maxAspectRatio;
7861 mHasMaxAspectRatio = true;
7862 }
7863
Adrian Roos917791e2018-11-28 16:30:44 +01007864 private void setMinAspectRatio(float minAspectRatio) {
7865 if (info.resizeMode == RESIZE_MODE_RESIZEABLE
7866 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
7867 // Resizeable activities can be put in any aspect ratio.
7868 return;
7869 }
7870
7871 if (minAspectRatio < 1.0f && minAspectRatio != 0) {
7872 // Ignore any value lesser than 1.0.
7873 return;
7874 }
7875
7876 info.minAspectRatio = minAspectRatio;
7877 mHasMinAspectRatio = true;
7878 }
7879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007880 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007881 StringBuilder sb = new StringBuilder(128);
7882 sb.append("Activity{");
7883 sb.append(Integer.toHexString(System.identityHashCode(this)));
7884 sb.append(' ');
7885 appendComponentShortName(sb);
7886 sb.append('}');
7887 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007888 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007889
7890 @Override
7891 public int describeContents() {
7892 return 0;
7893 }
7894
7895 @Override
7896 public void writeToParcel(Parcel dest, int flags) {
7897 super.writeToParcel(dest, flags);
7898 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
Bryce Lee22571db2017-07-07 15:54:18 -07007899 dest.writeBoolean(mHasMaxAspectRatio);
Adrian Roos917791e2018-11-28 16:30:44 +01007900 dest.writeBoolean(mHasMinAspectRatio);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007901 }
7902
7903 private Activity(Parcel in) {
7904 super(in);
7905 info = in.readParcelable(Object.class.getClassLoader());
Bryce Lee22571db2017-07-07 15:54:18 -07007906 mHasMaxAspectRatio = in.readBoolean();
Adrian Roos917791e2018-11-28 16:30:44 +01007907 mHasMinAspectRatio = in.readBoolean();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007908
7909 for (ActivityIntentInfo aii : intents) {
7910 aii.activity = this;
Todd Kennedy6d418b62018-02-22 14:15:18 -08007911 order = Math.max(aii.getOrder(), order);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007912 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007913
7914 if (info.permission != null) {
7915 info.permission = info.permission.intern();
7916 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007917 }
7918
7919 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
7920 public Activity createFromParcel(Parcel in) {
7921 return new Activity(in);
7922 }
7923
7924 public Activity[] newArray(int size) {
7925 return new Activity[size];
7926 }
7927 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007928 }
7929
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007930 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007931 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
7932 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007933 if (a == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007934 if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007935 return null;
7936 }
7937 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007938 updateApplicationInfo(a.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007939 return a.info;
7940 }
7941 // Make shallow copies so we can store the metadata safely
7942 ActivityInfo ai = new ActivityInfo(a.info);
7943 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007944 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007945 return ai;
7946 }
7947
Dianne Hackbornace27912014-09-18 18:38:30 -07007948 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
7949 PackageUserState state, int userId) {
7950 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007951 if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007952 return null;
7953 }
7954 // This is only used to return the ResolverActivity; we will just always
7955 // make a copy.
7956 ai = new ActivityInfo(ai);
7957 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
7958 return ai;
7959 }
7960
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007961 public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007962 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007963 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007964
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007965 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
7966 super(args, _info);
7967 info = _info;
7968 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007969 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007970
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007971 public void setPackageName(String packageName) {
7972 super.setPackageName(packageName);
7973 info.packageName = packageName;
7974 }
7975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007976 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007977 StringBuilder sb = new StringBuilder(128);
7978 sb.append("Service{");
7979 sb.append(Integer.toHexString(System.identityHashCode(this)));
7980 sb.append(' ');
7981 appendComponentShortName(sb);
7982 sb.append('}');
7983 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007984 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007985
7986 @Override
7987 public int describeContents() {
7988 return 0;
7989 }
7990
7991 @Override
7992 public void writeToParcel(Parcel dest, int flags) {
7993 super.writeToParcel(dest, flags);
7994 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7995 }
7996
7997 private Service(Parcel in) {
7998 super(in);
7999 info = in.readParcelable(Object.class.getClassLoader());
8000
8001 for (ServiceIntentInfo aii : intents) {
8002 aii.service = this;
Todd Kennedy6d418b62018-02-22 14:15:18 -08008003 order = Math.max(aii.getOrder(), order);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008004 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00008005
8006 if (info.permission != null) {
8007 info.permission = info.permission.intern();
8008 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008009 }
8010
8011 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
8012 public Service createFromParcel(Parcel in) {
8013 return new Service(in);
8014 }
8015
8016 public Service[] newArray(int size) {
8017 return new Service[size];
8018 }
8019 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008020 }
8021
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008022 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008023 public static final ServiceInfo generateServiceInfo(Service s, int flags,
8024 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008025 if (s == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07008026 if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008027 return null;
8028 }
8029 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07008030 updateApplicationInfo(s.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008031 return s.info;
8032 }
8033 // Make shallow copies so we can store the metadata safely
8034 ServiceInfo si = new ServiceInfo(s.info);
8035 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008036 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008037 return si;
8038 }
8039
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008040 public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008041 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008042 public final ProviderInfo info;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008043 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008044 public boolean syncable;
8045
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008046 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
8047 super(args, _info);
8048 info = _info;
8049 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008050 syncable = false;
8051 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07008052
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008053 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008054 public Provider(Provider existingProvider) {
8055 super(existingProvider);
8056 this.info = existingProvider.info;
8057 this.syncable = existingProvider.syncable;
8058 }
8059
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008060 public void setPackageName(String packageName) {
8061 super.setPackageName(packageName);
8062 info.packageName = packageName;
8063 }
8064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008065 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008066 StringBuilder sb = new StringBuilder(128);
8067 sb.append("Provider{");
8068 sb.append(Integer.toHexString(System.identityHashCode(this)));
8069 sb.append(' ');
8070 appendComponentShortName(sb);
8071 sb.append('}');
8072 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008073 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008074
8075 @Override
8076 public int describeContents() {
8077 return 0;
8078 }
8079
8080 @Override
8081 public void writeToParcel(Parcel dest, int flags) {
8082 super.writeToParcel(dest, flags);
8083 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
8084 dest.writeInt((syncable) ? 1 : 0);
8085 }
8086
8087 private Provider(Parcel in) {
8088 super(in);
8089 info = in.readParcelable(Object.class.getClassLoader());
8090 syncable = (in.readInt() == 1);
8091
8092 for (ProviderIntentInfo aii : intents) {
8093 aii.provider = this;
8094 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00008095
8096 if (info.readPermission != null) {
8097 info.readPermission = info.readPermission.intern();
8098 }
8099
8100 if (info.writePermission != null) {
8101 info.writePermission = info.writePermission.intern();
8102 }
8103
8104 if (info.authority != null) {
8105 info.authority = info.authority.intern();
8106 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008107 }
8108
8109 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
8110 public Provider createFromParcel(Parcel in) {
8111 return new Provider(in);
8112 }
8113
8114 public Provider[] newArray(int size) {
8115 return new Provider[size];
8116 }
8117 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008118 }
8119
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008120 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008121 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
8122 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008123 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07008124 if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008125 return null;
8126 }
8127 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008128 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008129 || p.info.uriPermissionPatterns == null)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07008130 updateApplicationInfo(p.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008131 return p.info;
8132 }
8133 // Make shallow copies so we can store the metadata safely
8134 ProviderInfo pi = new ProviderInfo(p.info);
8135 pi.metaData = p.metaData;
8136 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
8137 pi.uriPermissionPatterns = null;
8138 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008139 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008140 return pi;
8141 }
8142
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008143 public final static class Instrumentation extends Component<IntentInfo> implements
8144 Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008145 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008146 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008147
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008148 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
8149 super(args, _info);
8150 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008151 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07008152
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008153 public void setPackageName(String packageName) {
8154 super.setPackageName(packageName);
8155 info.packageName = packageName;
8156 }
8157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008158 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008159 StringBuilder sb = new StringBuilder(128);
8160 sb.append("Instrumentation{");
8161 sb.append(Integer.toHexString(System.identityHashCode(this)));
8162 sb.append(' ');
8163 appendComponentShortName(sb);
8164 sb.append('}');
8165 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008166 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008167
8168 @Override
8169 public int describeContents() {
8170 return 0;
8171 }
8172
8173 @Override
8174 public void writeToParcel(Parcel dest, int flags) {
8175 super.writeToParcel(dest, flags);
8176 dest.writeParcelable(info, flags);
8177 }
8178
8179 private Instrumentation(Parcel in) {
8180 super(in);
8181 info = in.readParcelable(Object.class.getClassLoader());
Narayan Kamath07ac1442017-02-10 15:08:07 +00008182
8183 if (info.targetPackage != null) {
8184 info.targetPackage = info.targetPackage.intern();
8185 }
8186
Dianne Hackborn1be53542017-04-28 13:36:00 -07008187 if (info.targetProcesses != null) {
8188 info.targetProcesses = info.targetProcesses.intern();
Narayan Kamath07ac1442017-02-10 15:08:07 +00008189 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008190 }
8191
8192 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
8193 public Instrumentation createFromParcel(Parcel in) {
8194 return new Instrumentation(in);
8195 }
8196
8197 public Instrumentation[] newArray(int size) {
8198 return new Instrumentation[size];
8199 }
8200 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008201 }
8202
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008203 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008204 public static final InstrumentationInfo generateInstrumentationInfo(
8205 Instrumentation i, int flags) {
8206 if (i == null) return null;
8207 if ((flags&PackageManager.GET_META_DATA) == 0) {
8208 return i.info;
8209 }
8210 InstrumentationInfo ii = new InstrumentationInfo(i.info);
8211 ii.metaData = i.metaData;
8212 return ii;
8213 }
8214
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008215 public static abstract class IntentInfo extends IntentFilter {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008216 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008217 public boolean hasDefault;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008218 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008219 public int labelRes;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008220 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008221 public CharSequence nonLocalizedLabel;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008222 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 public int icon;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008224 @UnsupportedAppUsage
Adam Powell81cd2e92010-04-21 16:35:18 -07008225 public int logo;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008226 @UnsupportedAppUsage
Jose Limaf78e3122014-03-06 12:13:15 -08008227 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07008228 public int preferred;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008229
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008230 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008231 protected IntentInfo() {
8232 }
8233
8234 protected IntentInfo(Parcel dest) {
8235 super(dest);
8236 hasDefault = (dest.readInt() == 1);
8237 labelRes = dest.readInt();
8238 nonLocalizedLabel = dest.readCharSequence();
8239 icon = dest.readInt();
8240 logo = dest.readInt();
8241 banner = dest.readInt();
8242 preferred = dest.readInt();
8243 }
8244
8245
8246 public void writeIntentInfoToParcel(Parcel dest, int flags) {
8247 super.writeToParcel(dest, flags);
8248 dest.writeInt(hasDefault ? 1 : 0);
8249 dest.writeInt(labelRes);
8250 dest.writeCharSequence(nonLocalizedLabel);
8251 dest.writeInt(icon);
8252 dest.writeInt(logo);
8253 dest.writeInt(banner);
8254 dest.writeInt(preferred);
8255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008256 }
8257
8258 public final static class ActivityIntentInfo extends IntentInfo {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008259 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008260 public Activity activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008261
8262 public ActivityIntentInfo(Activity _activity) {
8263 activity = _activity;
8264 }
8265
8266 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008267 StringBuilder sb = new StringBuilder(128);
8268 sb.append("ActivityIntentInfo{");
8269 sb.append(Integer.toHexString(System.identityHashCode(this)));
8270 sb.append(' ');
8271 activity.appendComponentShortName(sb);
8272 sb.append('}');
8273 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008274 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008275
8276 public ActivityIntentInfo(Parcel in) {
8277 super(in);
8278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008279 }
8280
8281 public final static class ServiceIntentInfo extends IntentInfo {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008282 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008283 public Service service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008284
8285 public ServiceIntentInfo(Service _service) {
8286 service = _service;
8287 }
8288
8289 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008290 StringBuilder sb = new StringBuilder(128);
8291 sb.append("ServiceIntentInfo{");
8292 sb.append(Integer.toHexString(System.identityHashCode(this)));
8293 sb.append(' ');
8294 service.appendComponentShortName(sb);
8295 sb.append('}');
8296 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008297 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008298
8299 public ServiceIntentInfo(Parcel in) {
8300 super(in);
8301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008302 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008303
Jeff Sharkey85f5f812013-10-07 10:16:12 -07008304 public static final class ProviderIntentInfo extends IntentInfo {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008305 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008306 public Provider provider;
Jeff Sharkey85f5f812013-10-07 10:16:12 -07008307
8308 public ProviderIntentInfo(Provider provider) {
8309 this.provider = provider;
8310 }
8311
8312 public String toString() {
8313 StringBuilder sb = new StringBuilder(128);
8314 sb.append("ProviderIntentInfo{");
8315 sb.append(Integer.toHexString(System.identityHashCode(this)));
8316 sb.append(' ');
8317 provider.appendComponentShortName(sb);
8318 sb.append('}');
8319 return sb.toString();
8320 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008321
8322 public ProviderIntentInfo(Parcel in) {
8323 super(in);
8324 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -07008325 }
8326
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008327 /**
8328 * @hide
8329 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008330 @UnsupportedAppUsage
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008331 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
8332 sCompatibilityModeEnabled = compatibilityModeEnabled;
8333 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07008334
Hyunyoung Song929de7a2019-03-21 23:51:27 -07008335 /**
8336 * @hide
8337 */
8338 public static void readConfigUseRoundIcon(Resources r) {
8339 if (r != null) {
8340 sUseRoundIcon = r.getBoolean(com.android.internal.R.bool.config_useRoundIcon);
8341 return;
8342 }
8343
8344 ApplicationInfo androidAppInfo;
8345 try {
8346 androidAppInfo = ActivityThread.getPackageManager().getApplicationInfo(
8347 "android", 0 /* flags */,
8348 UserHandle.myUserId());
8349 } catch (RemoteException e) {
8350 throw e.rethrowFromSystemServer();
8351 }
8352 Resources systemResources = Resources.getSystem();
8353
8354 // Create in-flight as this overlayable resource is only used when config changes
8355 Resources overlayableRes = ResourcesManager.getInstance().getResources(null,
8356 null,
8357 null,
8358 androidAppInfo.resourceDirs,
8359 androidAppInfo.sharedLibraryFiles,
8360 Display.DEFAULT_DISPLAY,
8361 null,
8362 systemResources.getCompatibilityInfo(),
8363 systemResources.getClassLoader());
8364
8365 sUseRoundIcon = overlayableRes.getBoolean(com.android.internal.R.bool.config_useRoundIcon);
8366 }
8367
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07008368 public static class PackageParserException extends Exception {
8369 public final int error;
8370
8371 public PackageParserException(int error, String detailMessage) {
8372 super(detailMessage);
8373 this.error = error;
8374 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07008375
8376 public PackageParserException(int error, String detailMessage, Throwable throwable) {
8377 super(detailMessage, throwable);
8378 this.error = error;
8379 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07008380 }
Jiyong Park5b1b7342019-01-18 09:45:17 +09008381
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +00008382 // TODO(b/129261524): Clean up API
Mohammad Samiul Islam7aa7d2e2019-03-27 12:23:47 +00008383 /**
8384 * PackageInfo parser specifically for apex files.
8385 * NOTE: It will collect certificates
8386 *
Gavin Corkeryef441722019-05-09 17:02:10 +01008387 * @param apexInfo
Mohammad Samiul Islam7aa7d2e2019-03-27 12:23:47 +00008388 * @return PackageInfo
8389 * @throws PackageParserException
8390 */
Gavin Corkeryef441722019-05-09 17:02:10 +01008391 public static PackageInfo generatePackageInfoFromApex(ApexInfo apexInfo, int flags)
Jiyong Park5b1b7342019-01-18 09:45:17 +09008392 throws PackageParserException {
Mohammad Samiul Islam7aa7d2e2019-03-27 12:23:47 +00008393 PackageParser pp = new PackageParser();
Nikita Ioffeb4eee2a2019-06-28 15:46:04 +01008394 File apexFile = new File(apexInfo.modulePath);
Mohammad Samiul Islam7aa7d2e2019-03-27 12:23:47 +00008395 final Package p = pp.parsePackage(apexFile, flags, false);
8396 PackageUserState state = new PackageUserState();
8397 PackageInfo pi = generatePackageInfo(p, EmptyArray.INT, flags, 0, 0,
8398 Collections.emptySet(), state);
Mohammad Samiul Islam7aa7d2e2019-03-27 12:23:47 +00008399 pi.applicationInfo.sourceDir = apexFile.getPath();
Andrew Sapperstein93f5ed62019-06-20 15:25:19 -07008400 pi.applicationInfo.publicSourceDir = apexFile.getPath();
Gavin Corkeryef441722019-05-09 17:02:10 +01008401 if (apexInfo.isFactory) {
8402 pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
8403 } else {
8404 pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
8405 }
8406 if (apexInfo.isActive) {
8407 pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
8408 } else {
8409 pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
8410 }
Mohammad Samiul Islam7aa7d2e2019-03-27 12:23:47 +00008411 pi.isApex = true;
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +00008412
Mohammad Samiul Islam7aa7d2e2019-03-27 12:23:47 +00008413 // Collect certificates
8414 if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
8415 collectCertificates(p, apexFile, false);
Todd Kennedy9c37cd22019-04-19 13:05:40 -07008416 // Keep legacy mechanism for handling signatures. While this is deprecated, it's
8417 // still part of the public API and needs to be maintained
8418 if (p.mSigningDetails.hasPastSigningCertificates()) {
8419 // Package has included signing certificate rotation information. Return
8420 // the oldest cert so that programmatic checks keep working even if unaware
8421 // of key rotation.
8422 pi.signatures = new Signature[1];
8423 pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0];
8424 } else if (p.mSigningDetails.hasSignatures()) {
8425 // otherwise keep old behavior
8426 int numberOfSigs = p.mSigningDetails.signatures.length;
8427 pi.signatures = new Signature[numberOfSigs];
8428 System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs);
8429 }
Mohammad Samiul Islam7aa7d2e2019-03-27 12:23:47 +00008430 if (p.mSigningDetails != SigningDetails.UNKNOWN) {
Jiyong Park5b1b7342019-01-18 09:45:17 +09008431 // only return a valid SigningInfo if there is signing information to report
Mohammad Samiul Islam7aa7d2e2019-03-27 12:23:47 +00008432 pi.signingInfo = new SigningInfo(p.mSigningDetails);
Jiyong Park5b1b7342019-01-18 09:45:17 +09008433 } else {
8434 pi.signingInfo = null;
8435 }
8436 }
Jiyong Park5b1b7342019-01-18 09:45:17 +09008437 return pi;
8438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008439}