blob: 812ae93f06415f8a6556854265203388e44186cc [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;
Anthony Hugh6f5eadc2019-08-22 15:35:48 -070060import android.content.pm.permission.SplitPermissionInfoParcelable;
Garrett Boyer52136662017-05-23 13:47:58 -070061import android.content.pm.split.DefaultSplitAssetLoader;
Adam Lesinski4e862812016-11-21 16:02:24 -080062import android.content.pm.split.SplitAssetDependencyLoader;
63import android.content.pm.split.SplitAssetLoader;
Adam Lesinskibebfcc42018-02-12 14:27:46 -080064import android.content.res.ApkAssets;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.content.res.AssetManager;
66import android.content.res.Configuration;
67import android.content.res.Resources;
68import android.content.res.TypedArray;
69import android.content.res.XmlResourceParser;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070070import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.os.Bundle;
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -070072import android.os.FileUtils;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070073import android.os.Parcel;
74import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.os.PatternMatcher;
Hyunyoung Song929de7a2019-03-21 23:51:27 -070076import android.os.RemoteException;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -070077import android.os.SystemClock;
Todd Leeea2f3be2017-03-16 14:00:52 -070078import android.os.SystemProperties;
Todd Kennedy27c24fb2015-09-17 16:49:25 -070079import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070080import android.os.UserHandle;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -060081import android.os.storage.StorageManager;
Philip P. Moltmann039678e2018-09-18 13:04:38 -070082import android.permission.PermissionManager;
Narayan Kamath988149c2016-12-01 13:32:59 +000083import android.system.ErrnoException;
84import android.system.OsConstants;
85import android.system.StructStat;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -070086import android.text.TextUtils;
Jeff Sharkey275e0852014-06-17 18:18:49 -070087import android.util.ArrayMap;
88import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import android.util.AttributeSet;
Kenny Root05ca4c92011-09-15 10:36:25 -070090import android.util.Base64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070092import android.util.Log;
Dan Cashman1dbe6d02018-01-23 11:18:28 -080093import android.util.PackageUtils;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070094import android.util.Pair;
Kenny Rootd2d29252011-08-08 11:27:57 -070095import android.util.Slog;
Adam Lesinski1665d0f2017-03-10 14:46:57 -080096import android.util.SparseArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.util.TypedValue;
Dan Cashmane92f8422017-12-08 14:02:51 -080098import android.util.apk.ApkSignatureVerifier;
Hyunyoung Song929de7a2019-03-21 23:51:27 -070099import android.view.Display;
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -0700100import android.view.Gravity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101
Jeff Sharkey9bc89af2017-01-11 11:25:50 -0700102import com.android.internal.R;
103import com.android.internal.annotations.VisibleForTesting;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100104import com.android.internal.os.ClassLoaderFactory;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -0700105import com.android.internal.util.ArrayUtils;
106import com.android.internal.util.XmlUtils;
Anthony Hugh6f5eadc2019-08-22 15:35:48 -0700107import com.android.server.SystemConfig;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -0700108
109import libcore.io.IoUtils;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -0700110import libcore.util.EmptyArray;
Neil Fuller2c7cc6e2019-04-11 11:04:06 +0100111import libcore.util.HexEncoding;
Svet Ganov087dce22017-09-07 15:42:16 -0700112
Jeff Sharkey9bc89af2017-01-11 11:25:50 -0700113import org.xmlpull.v1.XmlPullParser;
114import org.xmlpull.v1.XmlPullParserException;
115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116import java.io.File;
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700117import java.io.FileDescriptor;
Narayan Kamath988149c2016-12-01 13:32:59 +0000118import java.io.FileOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119import java.io.IOException;
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -0700120import java.io.PrintWriter;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800121import java.lang.annotation.Retention;
122import java.lang.annotation.RetentionPolicy;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000123import java.lang.reflect.Constructor;
Kenny Root05ca4c92011-09-15 10:36:25 -0700124import java.security.KeyFactory;
125import java.security.NoSuchAlgorithmException;
126import java.security.PublicKey;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800127import java.security.cert.CertificateException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700128import java.security.spec.EncodedKeySpec;
129import java.security.spec.InvalidKeySpecException;
130import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131import java.util.ArrayList;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700132import java.util.Arrays;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700133import java.util.Collections;
134import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -0700136import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800137import java.util.Set;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -0600138import java.util.UUID;
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700139import java.util.concurrent.atomic.AtomicInteger;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140
141/**
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700142 * Parser for package files (APKs) on disk. This supports apps packaged either
143 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
144 * APKs in a single directory.
145 * <p>
146 * Apps packaged as multiple APKs always consist of a single "base" APK (with a
147 * {@code null} split name) and zero or more "split" APKs (with unique split
148 * names). Any subset of those split APKs are a valid install, as long as the
149 * following constraints are met:
150 * <ul>
151 * <li>All APKs must have the exact same package name, version code, and signing
152 * certificates.
153 * <li>All APKs must have unique split names.
154 * <li>All installations must contain a single base APK.
155 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700157 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 */
159public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -0700160 private static final boolean DEBUG_JAR = false;
161 private static final boolean DEBUG_PARSER = false;
162 private static final boolean DEBUG_BACKUP = false;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -0700163 private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE;
164 private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100;
Kenny Rootd2d29252011-08-08 11:27:57 -0700165
Svet Ganova3c4eb32017-04-19 23:51:33 -0700166 private static final String PROPERTY_CHILD_PACKAGES_ENABLED =
167 "persist.sys.child_packages_enabled";
168
Jeff Sharkey3f1790d2017-04-25 18:56:17 -0600169 private static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE &&
Garrett Boyer17041532017-08-01 14:11:02 -0700170 SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false);
Svet Ganova3c4eb32017-04-19 23:51:33 -0700171
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700172 private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
Adrian Roos917791e2018-11-28 16:30:44 +0100173 private static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO = 1.333f;
174 private static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH = 1f;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700175
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +0000176 private static final int DEFAULT_MIN_SDK_VERSION = 1;
177 private static final int DEFAULT_TARGET_SDK_VERSION = 0;
178
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700179 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700180 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700181
Kenny Rootbcc954d2011-08-08 16:19:08 -0700182 /** File name in an APK for the Android manifest. */
Dan Cashmane92f8422017-12-08 14:02:51 -0800183 public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
Kenny Rootbcc954d2011-08-08 16:19:08 -0700184
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700185 /** Path prefix for apps on expanded storage */
186 private static final String MNT_EXPAND = "/mnt/expand/";
187
Svet Ganov354cd3c2015-12-17 11:35:04 -0800188 private static final String TAG_MANIFEST = "manifest";
189 private static final String TAG_APPLICATION = "application";
Adam Lesinski4e862812016-11-21 16:02:24 -0800190 private static final String TAG_PACKAGE_VERIFIER = "package-verifier";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800191 private static final String TAG_OVERLAY = "overlay";
192 private static final String TAG_KEY_SETS = "key-sets";
193 private static final String TAG_PERMISSION_GROUP = "permission-group";
194 private static final String TAG_PERMISSION = "permission";
195 private static final String TAG_PERMISSION_TREE = "permission-tree";
196 private static final String TAG_USES_PERMISSION = "uses-permission";
197 private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
198 private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
199 private static final String TAG_USES_CONFIGURATION = "uses-configuration";
200 private static final String TAG_USES_FEATURE = "uses-feature";
201 private static final String TAG_FEATURE_GROUP = "feature-group";
202 private static final String TAG_USES_SDK = "uses-sdk";
203 private static final String TAG_SUPPORT_SCREENS = "supports-screens";
204 private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
205 private static final String TAG_INSTRUMENTATION = "instrumentation";
206 private static final String TAG_ORIGINAL_PACKAGE = "original-package";
207 private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
208 private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
209 private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
210 private static final String TAG_SUPPORTS_INPUT = "supports-input";
211 private static final String TAG_EAT_COMMENT = "eat-comment";
212 private static final String TAG_PACKAGE = "package";
Todd Kennedyfdd241a2016-04-28 12:26:53 -0700213 private static final String TAG_RESTRICT_UPDATE = "restrict-update";
Adam Lesinski4e862812016-11-21 16:02:24 -0800214 private static final String TAG_USES_SPLIT = "uses-split";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800215
Bryce Lee22571db2017-07-07 15:54:18 -0700216 private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
217
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800218 /**
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700219 * Bit mask of all the valid bits that can be set in recreateOnConfigChanges.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800220 * @hide
221 */
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700222 private static final int RECREATE_ON_CONFIG_CHANGES_MASK =
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800223 ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
224
Svet Ganov354cd3c2015-12-17 11:35:04 -0800225 // These are the tags supported by child packages
226 private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
227 static {
228 CHILD_PACKAGE_TAGS.add(TAG_APPLICATION);
229 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION);
230 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M);
231 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23);
232 CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
233 CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
234 CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
235 CHILD_PACKAGE_TAGS.add(TAG_USES_SDK);
236 CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
237 CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
238 CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE);
239 CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS);
240 CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
241 CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
242 }
243
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700244 private static final boolean LOG_UNSAFE_BROADCASTS = false;
245
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700246 /**
247 * Total number of packages that were read from the cache. We use it only for logging.
248 */
249 public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger();
250
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700251 // Set of broadcast actions that are safe for manifest receivers
252 private static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
253 static {
254 SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
255 }
256
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700257 /** @hide */
Calin Juravle3fc56c32017-12-11 18:26:13 -0800258 public static final String APK_FILE_EXTENSION = ".apk";
Mohammad Samiul Islam73f17712019-07-05 14:47:17 +0100259 /** @hide */
260 public static final String APEX_FILE_EXTENSION = ".apex";
Calin Juravle3fc56c32017-12-11 18:26:13 -0800261
262 /** @hide */
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700263 public static class NewPermissionInfo {
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100264 @UnsupportedAppUsage
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700265 public final String name;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100266 @UnsupportedAppUsage
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700267 public final int sdkVersion;
268 public final int fileVersion;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700269
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700270 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
271 this.name = name;
272 this.sdkVersion = sdkVersion;
273 this.fileVersion = fileVersion;
274 }
275 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700276
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700277 /**
278 * List of new permissions that have been added since 1.0.
279 * NOTE: These must be declared in SDK version order, with permissions
280 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700281 * If sdkVersion is 0, then this is not a permission that we want to
282 * automatically add to older apps, but we do want to allow it to be
283 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700284 * @hide
285 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100286 @UnsupportedAppUsage
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700287 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
288 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700289 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700290 android.os.Build.VERSION_CODES.DONUT, 0),
291 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
292 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700293 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294
Dianne Hackborn79245122012-03-12 10:51:26 -0700295 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700296 * @deprecated callers should move to explicitly passing around source path.
297 */
298 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700302 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700303 private DisplayMetrics mMetrics;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100304 @UnsupportedAppUsage
Dianne Hackborncd154e92017-02-28 17:37:35 -0800305 private Callback mCallback;
Narayan Kamath988149c2016-12-01 13:32:59 +0000306 private File mCacheDir;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700307
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700308 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700309 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310
311 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
312
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700313 private static boolean sCompatibilityModeEnabled = true;
Hyunyoung Song929de7a2019-03-21 23:51:27 -0700314 private static boolean sUseRoundIcon = false;
315
Amith Yamasani655d0e22013-06-12 14:19:10 -0700316 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
317 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Todd Kennedy11e45072017-01-25 13:24:21 -0800318 private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700319
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700320 static class ParsePackageItemArgs {
321 final Package owner;
322 final String[] outError;
323 final int nameRes;
324 final int labelRes;
325 final int iconRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700326 final int roundIconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700327 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800328 final int bannerRes;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700329
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700330 String tag;
331 TypedArray sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700332
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700333 ParsePackageItemArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700334 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
335 int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700336 owner = _owner;
337 outError = _outError;
338 nameRes = _nameRes;
339 labelRes = _labelRes;
340 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700341 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800342 bannerRes = _bannerRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700343 roundIconRes = _roundIconRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700344 }
345 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700346
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000347 /** @hide */
348 @VisibleForTesting
349 public static class ParseComponentArgs extends ParsePackageItemArgs {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700350 final String[] sepProcesses;
351 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800352 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700353 final int enabledRes;
354 int flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700355
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000356 public ParseComponentArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700357 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
358 int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800359 String[] _sepProcesses, int _processRes,
360 int _descriptionRes, int _enabledRes) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700361 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes,
362 _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700363 sepProcesses = _sepProcesses;
364 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800365 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700366 enabledRes = _enabledRes;
367 }
368 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800369
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700370 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700371 * Lightweight parsed details about a single package.
372 */
373 public static class PackageLite {
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100374 @UnsupportedAppUsage
Jeff Sharkey73767b92014-07-04 20:18:13 -0700375 public final String packageName;
376 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700377 public final int versionCodeMajor;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100378 @UnsupportedAppUsage
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700379 public final int installLocation;
380 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700381
382 /** Names of any split APKs, ordered by parsed splitName */
383 public final String[] splitNames;
384
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800385 /** Names of any split APKs that are features. Ordered by splitName */
386 public final boolean[] isFeatureSplits;
387
Adam Lesinski4e862812016-11-21 16:02:24 -0800388 /** Dependencies of any split APKs, ordered by parsed splitName */
389 public final String[] usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800390 public final String[] configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800391
Jeff Sharkey73767b92014-07-04 20:18:13 -0700392 /**
393 * Path where this package was found on disk. For monolithic packages
394 * this is path to single base APK file; for cluster packages this is
395 * path to the cluster directory.
396 */
397 public final String codePath;
398
399 /** Path of base APK */
400 public final String baseCodePath;
401 /** Paths of any split APKs, ordered by parsed splitName */
402 public final String[] splitCodePaths;
403
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800404 /** Revision code of base APK */
405 public final int baseRevisionCode;
406 /** Revision codes of any split APKs, ordered by parsed splitName */
407 public final int[] splitRevisionCodes;
408
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700409 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100410 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100411 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800412 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700413 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800414 public final boolean isolatedSplits;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100415
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700416 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800417 boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100418 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700419 this.packageName = baseApk.packageName;
420 this.versionCode = baseApk.versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700421 this.versionCodeMajor = baseApk.versionCodeMajor;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700422 this.installLocation = baseApk.installLocation;
423 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700424 this.splitNames = splitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800425 this.isFeatureSplits = isFeatureSplits;
Adam Lesinski4e862812016-11-21 16:02:24 -0800426 this.usesSplitNames = usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800427 this.configForSplit = configForSplit;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700428 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700429 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700430 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800431 this.baseRevisionCode = baseApk.revisionCode;
432 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700433 this.coreApp = baseApk.coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100434 this.debuggable = baseApk.debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100435 this.multiArch = baseApk.multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800436 this.use32bitAbi = baseApk.use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700437 this.extractNativeLibs = baseApk.extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800438 this.isolatedSplits = baseApk.isolatedSplits;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700439 }
440
441 public List<String> getAllCodePaths() {
442 ArrayList<String> paths = new ArrayList<>();
443 paths.add(baseCodePath);
444 if (!ArrayUtils.isEmpty(splitCodePaths)) {
445 Collections.addAll(paths, splitCodePaths);
446 }
447 return paths;
448 }
449 }
450
451 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700452 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800453 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700454 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700455 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700456 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700457 public final String splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800458 public boolean isFeatureSplit;
459 public final String configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800460 public final String usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700461 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700462 public final int versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800463 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700464 public final int installLocation;
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +0000465 public final int minSdkVersion;
466 public final int targetSdkVersion;
Kenny Root05ca4c92011-09-15 10:36:25 -0700467 public final VerifierInfo[] verifiers;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800468 public final SigningDetails signingDetails;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700469 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100470 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100471 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800472 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700473 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800474 public final boolean isolatedSplits;
Todd Kennedy29cfa272018-09-26 10:25:24 -0700475 public final boolean isSplitRequired;
Victor Hsiehfa9df0b2019-01-29 12:48:36 -0800476 public final boolean useEmbeddedDex;
Kenny Root05ca4c92011-09-15 10:36:25 -0700477
Patrick Baumann47117fc2017-12-19 10:17:21 -0800478 public ApkLite(String codePath, String packageName, String splitName,
479 boolean isFeatureSplit,
Todd Kennedy29cfa272018-09-26 10:25:24 -0700480 String configForSplit, String usesSplitName, boolean isSplitRequired,
481 int versionCode, int versionCodeMajor,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700482 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Patrick Baumann47117fc2017-12-19 10:17:21 -0800483 SigningDetails signingDetails, boolean coreApp,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700484 boolean debuggable, boolean multiArch, boolean use32bitAbi,
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +0000485 boolean useEmbeddedDex, boolean extractNativeLibs, boolean isolatedSplits,
486 int minSdkVersion, int targetSdkVersion) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700487 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800488 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700489 this.splitName = splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800490 this.isFeatureSplit = isFeatureSplit;
491 this.configForSplit = configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800492 this.usesSplitName = usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700493 this.versionCode = versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700494 this.versionCodeMajor = versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800495 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800496 this.installLocation = installLocation;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800497 this.signingDetails = signingDetails;
Kenny Root05ca4c92011-09-15 10:36:25 -0700498 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700499 this.coreApp = coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100500 this.debuggable = debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100501 this.multiArch = multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800502 this.use32bitAbi = use32bitAbi;
Victor Hsiehfa9df0b2019-01-29 12:48:36 -0800503 this.useEmbeddedDex = useEmbeddedDex;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700504 this.extractNativeLibs = extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800505 this.isolatedSplits = isolatedSplits;
Todd Kennedy29cfa272018-09-26 10:25:24 -0700506 this.isSplitRequired = isSplitRequired;
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +0000507 this.minSdkVersion = minSdkVersion;
508 this.targetSdkVersion = targetSdkVersion;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800509 }
Dianne Hackborn3accca02013-09-20 09:32:11 -0700510
511 public long getLongVersionCode() {
512 return PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode);
513 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800514 }
515
Garrett Boyer52136662017-05-23 13:47:58 -0700516 /**
517 * Cached parse state for new components.
518 *
519 * Allows reuse of the same parse argument records to avoid GC pressure. Lifetime is carefully
520 * scoped to the parsing of a single application element.
521 */
522 private static class CachedComponentArgs {
523 ParseComponentArgs mActivityArgs;
524 ParseComponentArgs mActivityAliasArgs;
525 ParseComponentArgs mServiceArgs;
526 ParseComponentArgs mProviderArgs;
527 }
528
529 /**
530 * Cached state for parsing instrumentation to avoid GC pressure.
531 *
532 * Must be manually reset to null for each new manifest.
533 */
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700534 private ParsePackageItemArgs mParseInstrumentationArgs;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 /** If set to true, we will only allow package files that exactly match
537 * the DTD. Otherwise, we try to get as much from the package as we
538 * can without failing. This should normally be set to false, to
539 * support extensions to the DTD in future versions. */
540 private static final boolean RIGID_PARSER = false;
541
542 private static final String TAG = "PackageParser";
543
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100544 @UnsupportedAppUsage
Jeff Sharkey275e0852014-06-17 18:18:49 -0700545 public PackageParser() {
546 mMetrics = new DisplayMetrics();
547 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700548 }
549
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100550 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 public void setSeparateProcesses(String[] procs) {
552 mSeparateProcesses = procs;
553 }
554
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700555 /**
556 * Flag indicating this parser should only consider apps with
557 * {@code coreApp} manifest attribute to be valid apps. This is useful when
558 * creating a minimalist boot environment.
559 */
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700560 public void setOnlyCoreApps(boolean onlyCoreApps) {
561 mOnlyCoreApps = onlyCoreApps;
562 }
563
Jeff Sharkey275e0852014-06-17 18:18:49 -0700564 public void setDisplayMetrics(DisplayMetrics metrics) {
565 mMetrics = metrics;
566 }
567
Narayan Kamath988149c2016-12-01 13:32:59 +0000568 /**
569 * Sets the cache directory for this package parser.
570 */
571 public void setCacheDir(File cacheDir) {
572 mCacheDir = cacheDir;
573 }
574
Dianne Hackborncd154e92017-02-28 17:37:35 -0800575 /**
576 * Callback interface for retrieving information that may be needed while parsing
577 * a package.
578 */
579 public interface Callback {
580 boolean hasFeature(String feature);
Jack He61034792019-04-10 23:01:45 +0000581 String[] getOverlayPaths(String targetPackageName, String targetPath);
582 String[] getOverlayApks(String targetPackageName);
Dianne Hackborncd154e92017-02-28 17:37:35 -0800583 }
584
585 /**
586 * Standard implementation of {@link Callback} on top of the public {@link PackageManager}
587 * class.
588 */
589 public static final class CallbackImpl implements Callback {
590 private final PackageManager mPm;
591
592 public CallbackImpl(PackageManager pm) {
593 mPm = pm;
594 }
595
596 @Override public boolean hasFeature(String feature) {
597 return mPm.hasSystemFeature(feature);
598 }
Jack He61034792019-04-10 23:01:45 +0000599
600 @Override public String[] getOverlayPaths(String targetPackageName, String targetPath) {
601 return null;
602 }
603
604 @Override public String[] getOverlayApks(String targetPackageName) {
605 return null;
606 }
Dianne Hackborncd154e92017-02-28 17:37:35 -0800607 }
608
609 /**
610 * Set the {@link Callback} that can be used while parsing.
611 */
612 public void setCallback(Callback cb) {
613 mCallback = cb;
614 }
615
Jeff Sharkey73767b92014-07-04 20:18:13 -0700616 public static final boolean isApkFile(File file) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700617 return isApkPath(file.getName());
618 }
619
Adam Lesinski4e862812016-11-21 16:02:24 -0800620 public static boolean isApkPath(String path) {
Calin Juravle3fc56c32017-12-11 18:26:13 -0800621 return path.endsWith(APK_FILE_EXTENSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800622 }
623
624 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700625 * Returns true if the package is installed and not hidden, or if the caller
626 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700627 * @param appInfo The applicationInfo of the app being checked.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700628 */
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700629 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
630 ApplicationInfo appInfo) {
Rhed Jaocd47c262018-06-13 11:16:16 +0800631 // Returns false if the package is hidden system app until installed.
632 if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
633 && !state.installed
634 && appInfo != null && appInfo.hiddenUntilInstalled) {
635 return false;
636 }
637
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700638 // If available for the target user, or trying to match uninstalled packages and it's
639 // a system app.
640 return state.isAvailable(flags)
641 || (appInfo != null && appInfo.isSystemApp()
Rhed Jaocd47c262018-06-13 11:16:16 +0800642 && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
643 || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
Amith Yamasani483f3b02012-03-13 16:08:00 -0700644 }
645
Christopher Tateba629da2013-11-13 17:42:28 -0800646 public static boolean isAvailable(PackageUserState state) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700647 return checkUseInstalledOrHidden(0, state, null);
Christopher Tateba629da2013-11-13 17:42:28 -0800648 }
649
Oli Lan11380122019-07-31 15:27:22 +0100650 /**
651 * Generate and return the {@link PackageInfo} for a parsed package.
652 *
653 * @param p the parsed package.
654 * @param flags indicating which optional information is included.
655 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100656 @UnsupportedAppUsage
Amith Yamasani13593602012-03-22 16:16:17 -0700657 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Oli Lan11380122019-07-31 15:27:22 +0100658 int[] gids, int flags, long firstInstallTime, long lastUpdateTime,
659 Set<String> grantedPermissions, PackageUserState state) {
660
661 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
662 grantedPermissions, state, UserHandle.getCallingUserId());
663 }
664
665 @UnsupportedAppUsage
666 public static PackageInfo generatePackageInfo(PackageParser.Package p,
667 int[] gids, int flags, long firstInstallTime, long lastUpdateTime,
668 Set<String> grantedPermissions, PackageUserState state, int userId) {
669
670 return generatePackageInfo(p, null, gids, flags, firstInstallTime, lastUpdateTime,
671 grantedPermissions, state, userId);
672 }
673
674 /**
675 * PackageInfo generator specifically for apex files.
676 *
677 * @param pkg Package to generate info from. Should be derived from an apex.
678 * @param apexInfo Apex info relating to the package.
679 * @return PackageInfo
680 * @throws PackageParserException
681 */
682 public static PackageInfo generatePackageInfo(
683 PackageParser.Package pkg, ApexInfo apexInfo, int flags) {
684 return generatePackageInfo(pkg, apexInfo, EmptyArray.INT, flags, 0, 0,
685 Collections.emptySet(), new PackageUserState(), UserHandle.getCallingUserId());
686 }
687
688 private static PackageInfo generatePackageInfo(PackageParser.Package p, ApexInfo apexInfo,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700689 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800690 Set<String> grantedPermissions, PackageUserState state, int userId) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700691 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700692 return null;
693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 PackageInfo pi = new PackageInfo();
695 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700696 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 pi.versionCode = p.mVersionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700698 pi.versionCodeMajor = p.mVersionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800699 pi.baseRevisionCode = p.baseRevisionCode;
700 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800701 pi.versionName = p.mVersionName;
702 pi.sharedUserId = p.mSharedUserId;
703 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700704 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800705 pi.installLocation = p.installLocation;
Todd Kennedy7c8addf2017-06-27 14:13:55 -0700706 pi.isStub = p.isStub;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700707 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700708 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
709 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
710 pi.requiredForAllUsers = p.mRequiredForAllUsers;
711 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700712 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700713 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100714 pi.overlayTarget = p.mOverlayTarget;
Ryan Mitchelld57fb1f2019-03-20 17:18:58 -0700715 pi.targetOverlayableName = p.mOverlayTargetName;
Adrian Roosc84df772018-01-19 21:20:22 +0100716 pi.overlayCategory = p.mOverlayCategory;
Jaekyun Seok42d53f62017-04-10 13:48:58 +0900717 pi.overlayPriority = p.mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -0800718 pi.mOverlayIsStatic = p.mOverlayIsStatic;
Alan Viveretteb6a25732017-11-21 14:49:24 -0500719 pi.compileSdkVersion = p.mCompileSdkVersion;
720 pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700721 pi.firstInstallTime = firstInstallTime;
722 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 if ((flags&PackageManager.GET_GIDS) != 0) {
724 pi.gids = gids;
725 }
726 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700727 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 if (N > 0) {
729 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700730 p.configPreferences.toArray(pi.configPreferences);
731 }
732 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
733 if (N > 0) {
734 pi.reqFeatures = new FeatureInfo[N];
735 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700737 N = p.featureGroups != null ? p.featureGroups.size() : 0;
738 if (N > 0) {
739 pi.featureGroups = new FeatureGroupInfo[N];
740 p.featureGroups.toArray(pi.featureGroups);
741 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800742 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700743 if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
744 final int N = p.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800745 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700746 int num = 0;
747 final ActivityInfo[] res = new ActivityInfo[N];
748 for (int i = 0; i < N; i++) {
749 final Activity a = p.activities.get(i);
750 if (state.isMatch(a.info, flags)) {
Ricky Wai905908f2019-01-29 15:19:52 +0000751 if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(a.className)) {
752 continue;
753 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700754 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 }
756 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700757 pi.activities = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800758 }
759 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700760 if ((flags & PackageManager.GET_RECEIVERS) != 0) {
761 final int N = p.receivers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700763 int num = 0;
764 final ActivityInfo[] res = new ActivityInfo[N];
765 for (int i = 0; i < N; i++) {
766 final Activity a = p.receivers.get(i);
767 if (state.isMatch(a.info, flags)) {
768 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 }
770 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700771 pi.receivers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 }
773 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700774 if ((flags & PackageManager.GET_SERVICES) != 0) {
775 final int N = p.services.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700777 int num = 0;
778 final ServiceInfo[] res = new ServiceInfo[N];
779 for (int i = 0; i < N; i++) {
780 final Service s = p.services.get(i);
781 if (state.isMatch(s.info, flags)) {
782 res[num++] = generateServiceInfo(s, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783 }
784 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700785 pi.services = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 }
787 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700788 if ((flags & PackageManager.GET_PROVIDERS) != 0) {
789 final int N = p.providers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700791 int num = 0;
792 final ProviderInfo[] res = new ProviderInfo[N];
793 for (int i = 0; i < N; i++) {
794 final Provider pr = p.providers.get(i);
795 if (state.isMatch(pr.info, flags)) {
796 res[num++] = generateProviderInfo(pr, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 }
798 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700799 pi.providers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800800 }
801 }
802 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
803 int N = p.instrumentation.size();
804 if (N > 0) {
805 pi.instrumentation = new InstrumentationInfo[N];
806 for (int i=0; i<N; i++) {
807 pi.instrumentation[i] = generateInstrumentationInfo(
808 p.instrumentation.get(i), flags);
809 }
810 }
811 }
812 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
813 int N = p.permissions.size();
814 if (N > 0) {
815 pi.permissions = new PermissionInfo[N];
816 for (int i=0; i<N; i++) {
817 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
818 }
819 }
Chad Brubakere2107312019-02-04 12:30:01 -0800820 N = p.requestedPermissions.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800821 if (N > 0) {
822 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800823 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824 for (int i=0; i<N; i++) {
Chad Brubakere2107312019-02-04 12:30:01 -0800825 final String perm = p.requestedPermissions.get(i);
Dianne Hackborne639da72012-02-21 15:11:13 -0800826 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700827 // The notion of required permissions is deprecated but for compatibility.
Chad Brubakere2107312019-02-04 12:30:01 -0800828 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800829 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
Chad Brubakere2107312019-02-04 12:30:01 -0800830 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800831 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 }
833 }
834 }
Oli Lan11380122019-07-31 15:27:22 +0100835
836 if (apexInfo != null) {
837 File apexFile = new File(apexInfo.modulePath);
838
839 pi.applicationInfo.sourceDir = apexFile.getPath();
840 pi.applicationInfo.publicSourceDir = apexFile.getPath();
841 if (apexInfo.isFactory) {
842 pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
843 } else {
844 pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
845 }
846 if (apexInfo.isActive) {
847 pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
848 } else {
849 pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
850 }
851 pi.isApex = true;
852 }
853
Daniel Cashman5cdda342018-01-19 07:22:52 -0800854 // deprecated method of getting signing certificates
Oli Lan11380122019-07-31 15:27:22 +0100855 if ((flags & PackageManager.GET_SIGNATURES) != 0) {
Daniel Cashman5cdda342018-01-19 07:22:52 -0800856 if (p.mSigningDetails.hasPastSigningCertificates()) {
857 // Package has included signing certificate rotation information. Return the oldest
858 // cert so that programmatic checks keep working even if unaware of key rotation.
859 pi.signatures = new Signature[1];
860 pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0];
861 } else if (p.mSigningDetails.hasSignatures()) {
862 // otherwise keep old behavior
Patrick Baumann47117fc2017-12-19 10:17:21 -0800863 int numberOfSigs = p.mSigningDetails.signatures.length;
864 pi.signatures = new Signature[numberOfSigs];
865 System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 }
867 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800868
869 // replacement for GET_SIGNATURES
870 if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
Dan Cashman5c9f527e2018-04-03 16:42:23 -0700871 if (p.mSigningDetails != SigningDetails.UNKNOWN) {
872 // only return a valid SigningInfo if there is signing information to report
873 pi.signingInfo = new SigningInfo(p.mSigningDetails);
874 } else {
875 pi.signingInfo = null;
Daniel Cashman5cdda342018-01-19 07:22:52 -0800876 }
877 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 return pi;
879 }
880
Todd Kennedy232d29e2017-11-06 14:45:53 -0800881 public static final int PARSE_MUST_BE_APK = 1 << 0;
882 public static final int PARSE_IGNORE_PROCESSES = 1 << 1;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800883 public static final int PARSE_EXTERNAL_STORAGE = 1 << 3;
884 public static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
885 public static final int PARSE_COLLECT_CERTIFICATES = 1 << 5;
886 public static final int PARSE_ENFORCE_CODE = 1 << 6;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800887 public static final int PARSE_CHATTY = 1 << 31;
888
889 @IntDef(flag = true, prefix = { "PARSE_" }, value = {
890 PARSE_CHATTY,
891 PARSE_COLLECT_CERTIFICATES,
892 PARSE_ENFORCE_CODE,
893 PARSE_EXTERNAL_STORAGE,
Todd Kennedy232d29e2017-11-06 14:45:53 -0800894 PARSE_IGNORE_PROCESSES,
Todd Kennedy232d29e2017-11-06 14:45:53 -0800895 PARSE_IS_SYSTEM_DIR,
896 PARSE_MUST_BE_APK,
897 })
898 @Retention(RetentionPolicy.SOURCE)
899 public @interface ParseFlags {}
Jeff Sharkey275e0852014-06-17 18:18:49 -0700900
901 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700903 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700904 * Used to sort a set of APKs based on their split names, always placing the
905 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700906 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700907 private static class SplitNameComparator implements Comparator<String> {
908 @Override
909 public int compare(String lhs, String rhs) {
910 if (lhs == null) {
911 return -1;
912 } else if (rhs == null) {
913 return 1;
914 } else {
915 return lhs.compareTo(rhs);
916 }
917 }
918 }
919
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700920 /**
921 * Parse only lightweight details about the package at the given location.
922 * Automatically detects if the package is a monolithic style (single APK
923 * file) or cluster style (directory of APKs).
924 * <p>
925 * This performs sanity checking on cluster style packages, such as
926 * requiring identical package name and version codes, a single base APK,
927 * and unique split names.
928 *
929 * @see PackageParser#parsePackage(File, int)
930 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100931 @UnsupportedAppUsage
Jeff Sharkey73767b92014-07-04 20:18:13 -0700932 public static PackageLite parsePackageLite(File packageFile, int flags)
933 throws PackageParserException {
934 if (packageFile.isDirectory()) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800935 return parseClusterPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700936 } else {
Adam Lesinski4e862812016-11-21 16:02:24 -0800937 return parseMonolithicPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700938 }
939 }
940
Adam Lesinski4e862812016-11-21 16:02:24 -0800941 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
942 throws PackageParserException {
Todd Kennedycd029da2016-07-21 07:41:09 -0700943 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Adam Lesinski4e862812016-11-21 16:02:24 -0800944 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700945 final String packagePath = packageFile.getAbsolutePath();
Todd Kennedycd029da2016-07-21 07:41:09 -0700946 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Narayan Kamath96c11c52017-08-09 13:07:21 +0100947 return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700948 }
949
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800950 static PackageLite parseClusterPackageLite(File packageDir, int flags)
Adam Lesinski4e862812016-11-21 16:02:24 -0800951 throws PackageParserException {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700952 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700953 if (ArrayUtils.isEmpty(files)) {
954 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
955 "No packages found in split");
956 }
957
Jeff Sharkey275e0852014-06-17 18:18:49 -0700958 String packageName = null;
959 int versionCode = 0;
960
Todd Kennedycd029da2016-07-21 07:41:09 -0700961 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700962 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700963 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700964 if (isApkFile(file)) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800965 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700966
967 // Assert that all package names and version codes are
968 // consistent with the first one we encounter.
969 if (packageName == null) {
970 packageName = lite.packageName;
971 versionCode = lite.versionCode;
972 } else {
973 if (!packageName.equals(lite.packageName)) {
974 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
975 "Inconsistent package " + lite.packageName + " in " + file
976 + "; expected " + packageName);
977 }
978 if (versionCode != lite.versionCode) {
979 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
980 "Inconsistent version " + lite.versionCode + " in " + file
981 + "; expected " + versionCode);
982 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700983 }
984
Jeff Sharkey275e0852014-06-17 18:18:49 -0700985 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700986 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700987 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
988 "Split name " + lite.splitName
989 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700990 }
991 }
992 }
Todd Kennedycd029da2016-07-21 07:41:09 -0700993 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700994
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700995 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700996 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700997 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700998 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700999 }
1000
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001001 // Always apply deterministic ordering based on splitName
1002 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001003
Jeff Sharkey73767b92014-07-04 20:18:13 -07001004 String[] splitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001005 boolean[] isFeatureSplits = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001006 String[] usesSplitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001007 String[] configForSplits = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -07001008 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001009 int[] splitRevisionCodes = null;
Narayan Kamathf9419f02017-06-15 11:35:38 +01001010 String[] splitClassLoaderNames = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -07001011 if (size > 0) {
1012 splitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001013 isFeatureSplits = new boolean[size];
Adam Lesinski4e862812016-11-21 16:02:24 -08001014 usesSplitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001015 configForSplits = new String[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -07001016 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001017 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -07001018
1019 splitNames = apks.keySet().toArray(splitNames);
1020 Arrays.sort(splitNames, sSplitNameComparator);
1021
1022 for (int i = 0; i < size; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -08001023 final ApkLite apk = apks.get(splitNames[i]);
1024 usesSplitNames[i] = apk.usesSplitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001025 isFeatureSplits[i] = apk.isFeatureSplit;
1026 configForSplits[i] = apk.configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -08001027 splitCodePaths[i] = apk.codePath;
1028 splitRevisionCodes[i] = apk.revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -07001029 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001030 }
1031
Jeff Sharkey73767b92014-07-04 20:18:13 -07001032 final String codePath = packageDir.getAbsolutePath();
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001033 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames,
Narayan Kamath96c11c52017-08-09 13:07:21 +01001034 configForSplits, splitCodePaths, splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001035 }
1036
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001037 /**
1038 * Parse the package at the given location. Automatically detects if the
1039 * package is a monolithic style (single APK file) or cluster style
1040 * (directory of APKs).
1041 * <p>
1042 * This performs sanity checking on cluster style packages, such as
1043 * requiring identical package name and version codes, a single base APK,
1044 * and unique split names.
1045 * <p>
1046 * Note that this <em>does not</em> perform signature verification; that
1047 * must be done separately in {@link #collectCertificates(Package, int)}.
1048 *
Narayan Kamath988149c2016-12-01 13:32:59 +00001049 * If {@code useCaches} is true, the package parser might return a cached
1050 * result from a previous parse of the same {@code packageFile} with the same
1051 * {@code flags}. Note that this method does not check whether {@code packageFile}
1052 * has changed since the last parse, it's up to callers to do so.
1053 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001054 * @see #parsePackageLite(File, int)
1055 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001056 @UnsupportedAppUsage
Narayan Kamath988149c2016-12-01 13:32:59 +00001057 public Package parsePackage(File packageFile, int flags, boolean useCaches)
1058 throws PackageParserException {
1059 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
1060 if (parsed != null) {
1061 return parsed;
1062 }
1063
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001064 long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Jeff Sharkey73767b92014-07-04 20:18:13 -07001065 if (packageFile.isDirectory()) {
Narayan Kamath988149c2016-12-01 13:32:59 +00001066 parsed = parseClusterPackage(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001067 } else {
Narayan Kamath988149c2016-12-01 13:32:59 +00001068 parsed = parseMonolithicPackage(packageFile, flags);
1069 }
1070
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001071 long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Narayan Kamath988149c2016-12-01 13:32:59 +00001072 cacheResult(packageFile, flags, parsed);
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001073 if (LOG_PARSE_TIMINGS) {
1074 parseTime = cacheTime - parseTime;
1075 cacheTime = SystemClock.uptimeMillis() - cacheTime;
1076 if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
1077 Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
1078 + "ms, update_cache=" + cacheTime + " ms");
1079 }
1080 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001081 return parsed;
1082 }
1083
1084 /**
1085 * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}.
1086 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001087 @UnsupportedAppUsage
Narayan Kamath988149c2016-12-01 13:32:59 +00001088 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
1089 return parsePackage(packageFile, flags, false /* useCaches */);
1090 }
1091
1092 /**
1093 * Returns the cache key for a specificied {@code packageFile} and {@code flags}.
1094 */
1095 private String getCacheKey(File packageFile, int flags) {
1096 StringBuilder sb = new StringBuilder(packageFile.getName());
1097 sb.append('-');
1098 sb.append(flags);
1099
1100 return sb.toString();
1101 }
1102
1103 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001104 protected Package fromCacheEntry(byte[] bytes) {
1105 return fromCacheEntryStatic(bytes);
1106 }
1107
1108 /** static version of {@link #fromCacheEntry} for unit tests. */
1109 @VisibleForTesting
1110 public static Package fromCacheEntryStatic(byte[] bytes) {
1111 final Parcel p = Parcel.obtain();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001112 p.unmarshall(bytes, 0, bytes.length);
1113 p.setDataPosition(0);
1114
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001115 final ReadHelper helper = new ReadHelper(p);
1116 helper.startAndInstall();
1117
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001118 PackageParser.Package pkg = new PackageParser.Package(p);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001119
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001120 p.recycle();
1121
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001122 sCachedPackageReadCount.incrementAndGet();
1123
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001124 return pkg;
Narayan Kamath988149c2016-12-01 13:32:59 +00001125 }
1126
1127 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001128 protected byte[] toCacheEntry(Package pkg) {
1129 return toCacheEntryStatic(pkg);
1130
1131 }
1132
1133 /** static version of {@link #toCacheEntry} for unit tests. */
1134 @VisibleForTesting
1135 public static byte[] toCacheEntryStatic(Package pkg) {
1136 final Parcel p = Parcel.obtain();
1137 final WriteHelper helper = new WriteHelper(p);
1138
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001139 pkg.writeToParcel(p, 0 /* flags */);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001140
1141 helper.finishAndUninstall();
1142
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001143 byte[] serialized = p.marshall();
1144 p.recycle();
1145
1146 return serialized;
Narayan Kamath988149c2016-12-01 13:32:59 +00001147 }
1148
1149 /**
1150 * Given a {@code packageFile} and a {@code cacheFile} returns whether the
1151 * cache file is up to date based on the mod-time of both files.
1152 */
1153 private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
1154 try {
1155 // NOTE: We don't use the File.lastModified API because it has the very
1156 // non-ideal failure mode of returning 0 with no excepions thrown.
1157 // The nio2 Files API is a little better but is considerably more expensive.
1158 final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
1159 final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
1160 return pkg.st_mtime < cache.st_mtime;
1161 } catch (ErrnoException ee) {
1162 // The most common reason why stat fails is that a given cache file doesn't
1163 // exist. We ignore that here. It's easy to reason that it's safe to say the
1164 // cache isn't up to date if we see any sort of exception here.
1165 //
1166 // (1) Exception while stating the package file : This should never happen,
1167 // and if it does, we do a full package parse (which is likely to throw the
1168 // same exception).
1169 // (2) Exception while stating the cache file : If the file doesn't exist, the
1170 // cache is obviously out of date. If the file *does* exist, we can't read it.
1171 // We will attempt to delete and recreate it after parsing the package.
1172 if (ee.errno != OsConstants.ENOENT) {
1173 Slog.w("Error while stating package cache : ", ee);
1174 }
1175
1176 return false;
1177 }
1178 }
1179
1180 /**
1181 * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
1182 * or {@code null} if no cached result exists.
1183 */
1184 private Package getCachedResult(File packageFile, int flags) {
1185 if (mCacheDir == null) {
1186 return null;
1187 }
1188
1189 final String cacheKey = getCacheKey(packageFile, flags);
1190 final File cacheFile = new File(mCacheDir, cacheKey);
1191
Narayan Kamath988149c2016-12-01 13:32:59 +00001192 try {
Makoto Onuki48e93162017-08-18 11:00:19 -07001193 // If the cache is not up to date, return null.
1194 if (!isCacheUpToDate(packageFile, cacheFile)) {
1195 return null;
1196 }
1197
Narayan Kamath988149c2016-12-01 13:32:59 +00001198 final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
Jack He61034792019-04-10 23:01:45 +00001199 Package p = fromCacheEntry(bytes);
1200 if (mCallback != null) {
1201 String[] overlayApks = mCallback.getOverlayApks(p.packageName);
1202 if (overlayApks != null && overlayApks.length > 0) {
1203 for (String overlayApk : overlayApks) {
1204 // If a static RRO is updated, return null.
1205 if (!isCacheUpToDate(new File(overlayApk), cacheFile)) {
1206 return null;
1207 }
1208 }
1209 }
1210 }
1211 return p;
Makoto Onuki48e93162017-08-18 11:00:19 -07001212 } catch (Throwable e) {
Narayan Kamath21a28382017-01-13 10:34:29 +00001213 Slog.w(TAG, "Error reading package cache: ", e);
Narayan Kamath988149c2016-12-01 13:32:59 +00001214
1215 // If something went wrong while reading the cache entry, delete the cache file
1216 // so that we regenerate it the next time.
1217 cacheFile.delete();
1218 return null;
1219 }
1220 }
1221
1222 /**
1223 * Caches the parse result for {@code packageFile} with flags {@code flags}.
1224 */
1225 private void cacheResult(File packageFile, int flags, Package parsed) {
1226 if (mCacheDir == null) {
1227 return;
1228 }
1229
Makoto Onuki48e93162017-08-18 11:00:19 -07001230 try {
1231 final String cacheKey = getCacheKey(packageFile, flags);
1232 final File cacheFile = new File(mCacheDir, cacheKey);
Narayan Kamath988149c2016-12-01 13:32:59 +00001233
Makoto Onuki48e93162017-08-18 11:00:19 -07001234 if (cacheFile.exists()) {
1235 if (!cacheFile.delete()) {
1236 Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
1237 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001238 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001239
Makoto Onuki48e93162017-08-18 11:00:19 -07001240 final byte[] cacheEntry = toCacheEntry(parsed);
Narayan Kamath988149c2016-12-01 13:32:59 +00001241
Makoto Onuki48e93162017-08-18 11:00:19 -07001242 if (cacheEntry == null) {
1243 return;
1244 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001245
Makoto Onuki48e93162017-08-18 11:00:19 -07001246 try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
1247 fos.write(cacheEntry);
1248 } catch (IOException ioe) {
1249 Slog.w(TAG, "Error writing cache entry.", ioe);
1250 cacheFile.delete();
1251 }
1252 } catch (Throwable e) {
1253 Slog.w(TAG, "Error saving package cache.", e);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001254 }
1255 }
1256
1257 /**
1258 * Parse all APKs contained in the given directory, treating them as a
1259 * single package. This also performs sanity checking, such as requiring
1260 * identical package name and version codes, a single base APK, and unique
1261 * split names.
1262 * <p>
1263 * Note that this <em>does not</em> perform signature verification; that
1264 * must be done separately in {@link #collectCertificates(Package, int)}.
1265 */
1266 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001267 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001268 if (mOnlyCoreApps && !lite.coreApp) {
1269 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1270 "Not a coreApp: " + packageDir);
1271 }
1272
Adam Lesinski4e862812016-11-21 16:02:24 -08001273 // Build the split dependency tree.
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001274 SparseArray<int[]> splitDependencies = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001275 final SplitAssetLoader assetLoader;
1276 if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001277 try {
1278 splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
1279 assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
1280 } catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
1281 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
1282 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001283 } else {
1284 assetLoader = new DefaultSplitAssetLoader(lite, flags);
1285 }
1286
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001287 try {
Adam Lesinski4e862812016-11-21 16:02:24 -08001288 final AssetManager assets = assetLoader.getBaseAssetManager();
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001289 final File baseApk = new File(lite.baseCodePath);
1290 final Package pkg = parseBaseApk(baseApk, assets, flags);
1291 if (pkg == null) {
1292 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1293 "Failed to parse base APK: " + baseApk);
1294 }
1295
1296 if (!ArrayUtils.isEmpty(lite.splitNames)) {
1297 final int num = lite.splitNames.length;
1298 pkg.splitNames = lite.splitNames;
1299 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001300 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001301 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001302 pkg.splitPrivateFlags = new int[num];
Adam Lesinski4e862812016-11-21 16:02:24 -08001303 pkg.applicationInfo.splitNames = pkg.splitNames;
1304 pkg.applicationInfo.splitDependencies = splitDependencies;
Narayan Kamath96c11c52017-08-09 13:07:21 +01001305 pkg.applicationInfo.splitClassLoaderNames = new String[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001306
1307 for (int i = 0; i < num; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -08001308 final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
1309 parseSplitApk(pkg, i, splitAssets, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001310 }
1311 }
1312
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001313 pkg.setCodePath(packageDir.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001314 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001315 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001316 } catch (IOException e) {
1317 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1318 "Failed to get path: " + lite.baseCodePath, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001319 } finally {
Adam Lesinski4e862812016-11-21 16:02:24 -08001320 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001322 }
1323
Jeff Sharkey275e0852014-06-17 18:18:49 -07001324 /**
1325 * Parse the given APK file, treating it as as a single monolithic package.
1326 * <p>
1327 * Note that this <em>does not</em> perform signature verification; that
1328 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001329 *
1330 * @deprecated external callers should move to
1331 * {@link #parsePackage(File, int)}. Eventually this method will
1332 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -07001333 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001334 @Deprecated
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001335 @UnsupportedAppUsage
Jeff Sharkey275e0852014-06-17 18:18:49 -07001336 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001337 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001338 if (mOnlyCoreApps) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001339 if (!lite.coreApp) {
1340 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1341 "Not a coreApp: " + apkFile);
1342 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001343 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001344
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001345 final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001346 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001347 final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001348 pkg.setCodePath(apkFile.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001349 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001350 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001351 } catch (IOException e) {
1352 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1353 "Failed to get path: " + apkFile, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001354 } finally {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001355 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001356 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001357 }
1358
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001359 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
1360 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001361 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001362
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07001363 String volumeUuid = null;
1364 if (apkPath.startsWith(MNT_EXPAND)) {
1365 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
1366 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
1367 }
1368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001370 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001371
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001372 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001374 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001376 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 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001381 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001382 final Resources res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001383
1384 final String[] outError = new String[1];
Jack He61034792019-04-10 23:01:45 +00001385 final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001386 if (pkg == null) {
1387 throw new PackageParserException(mParseError,
1388 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001390
Svet Ganov354cd3c2015-12-17 11:35:04 -08001391 pkg.setVolumeUuid(volumeUuid);
1392 pkg.setApplicationVolumeUuid(volumeUuid);
1393 pkg.setBaseCodePath(apkPath);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001394 pkg.setSigningDetails(SigningDetails.UNKNOWN);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001395
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001396 return pkg;
1397
1398 } catch (PackageParserException e) {
1399 throw e;
1400 } catch (Exception e) {
1401 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001402 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001403 } finally {
1404 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 }
1407
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001408 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001409 throws PackageParserException {
1410 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -07001411
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001412 mParseError = PackageManager.INSTALL_SUCCEEDED;
1413 mArchiveSourcePath = apkPath;
1414
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001415 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
1416
Adam Lesinski4e862812016-11-21 16:02:24 -08001417 final Resources res;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001418 XmlResourceParser parser = null;
1419 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001420 // This must always succeed, as the path has been added to the AssetManager before.
1421 final int cookie = assets.findCookieForPath(apkPath);
1422 if (cookie == 0) {
1423 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1424 "Failed adding asset path: " + apkPath);
1425 }
1426
Adam Lesinski56c82be2018-02-09 11:02:04 -08001427 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001428 res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001429
1430 final String[] outError = new String[1];
1431 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
1432 if (pkg == null) {
1433 throw new PackageParserException(mParseError,
1434 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
1435 }
1436
1437 } catch (PackageParserException e) {
1438 throw e;
1439 } catch (Exception e) {
1440 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001441 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001442 } finally {
1443 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001444 }
1445 }
1446
1447 /**
1448 * Parse the manifest of a <em>split APK</em>.
1449 * <p>
1450 * Note that split APKs have many more restrictions on what they're capable
1451 * of doing, so many valid features of a base APK have been carefully
1452 * omitted here.
1453 */
1454 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001455 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
1456 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001457 AttributeSet attrs = parser;
1458
Jeff Sharkey78a13012014-07-15 20:18:34 -07001459 // We parsed manifest tag earlier; just skip past it
Svet Ganov354cd3c2015-12-17 11:35:04 -08001460 parsePackageSplitNames(parser, attrs);
Jeff Sharkey78a13012014-07-15 20:18:34 -07001461
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001462 mParseInstrumentationArgs = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001463
1464 int type;
1465
1466 boolean foundApp = false;
1467
1468 int outerDepth = parser.getDepth();
1469 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1470 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1471 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1472 continue;
1473 }
1474
1475 String tagName = parser.getName();
Adam Lesinski4e862812016-11-21 16:02:24 -08001476 if (tagName.equals(TAG_APPLICATION)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001477 if (foundApp) {
1478 if (RIGID_PARSER) {
1479 outError[0] = "<manifest> has more than one <application>";
1480 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1481 return null;
1482 } else {
1483 Slog.w(TAG, "<manifest> has more than one <application>");
1484 XmlUtils.skipCurrentTag(parser);
1485 continue;
1486 }
1487 }
1488
1489 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001490 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001491 return null;
1492 }
1493
1494 } else if (RIGID_PARSER) {
1495 outError[0] = "Bad element under <manifest>: "
1496 + parser.getName();
1497 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1498 return null;
1499
1500 } else {
1501 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1502 + " at " + mArchiveSourcePath + " "
1503 + parser.getPositionDescription());
1504 XmlUtils.skipCurrentTag(parser);
1505 continue;
1506 }
1507 }
1508
1509 if (!foundApp) {
1510 outError[0] = "<manifest> does not contain an <application>";
1511 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1512 }
1513
1514 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001515 }
1516
Patrick Baumann47117fc2017-12-19 10:17:21 -08001517 /** Parses the public keys from the set of signatures. */
1518 public static ArraySet<PublicKey> toSigningKeys(Signature[] signatures)
1519 throws CertificateException {
1520 ArraySet<PublicKey> keys = new ArraySet<>(signatures.length);
1521 for (int i = 0; i < signatures.length; i++) {
1522 keys.add(signatures[i].getPublicKey());
Todd Kennedy66c55532016-02-26 16:22:11 -08001523 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001524 return keys;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001525 }
1526
1527 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -07001528 * Collect certificates from all the APKs described in the given package,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001529 * populating {@link Package#mSigningDetails}. Also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001530 * contents are signed correctly and consistently.
1531 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001532 @UnsupportedAppUsage
Victor Hsieh5f761242018-01-20 10:30:12 -08001533 public static void collectCertificates(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001534 throws PackageParserException {
Victor Hsieh5f761242018-01-20 10:30:12 -08001535 collectCertificatesInternal(pkg, skipVerify);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001536 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1537 for (int i = 0; i < childCount; i++) {
1538 Package childPkg = pkg.childPackages.get(i);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001539 childPkg.mSigningDetails = pkg.mSigningDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001540 }
1541 }
1542
Victor Hsieh5f761242018-01-20 10:30:12 -08001543 private static void collectCertificatesInternal(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001544 throws PackageParserException {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001545 pkg.mSigningDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001546
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001547 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1548 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001549 collectCertificates(pkg, new File(pkg.baseCodePath), skipVerify);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001550
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001551 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1552 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
Victor Hsieh5f761242018-01-20 10:30:12 -08001553 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001554 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001555 }
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001556 } finally {
1557 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001558 }
1559 }
1560
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001561 @UnsupportedAppUsage
Victor Hsieh5f761242018-01-20 10:30:12 -08001562 private static void collectCertificates(Package pkg, File apkFile, boolean skipVerify)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001563 throws PackageParserException {
1564 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565
Patrick Baumann47117fc2017-12-19 10:17:21 -08001566 int minSignatureScheme = SigningDetails.SignatureSchemeVersion.JAR;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001567 if (pkg.applicationInfo.isStaticSharedLibrary()) {
Dan Cashmane92f8422017-12-08 14:02:51 -08001568 // must use v2 signing scheme
Patrick Baumann47117fc2017-12-19 10:17:21 -08001569 minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;
Dan Cashmane92f8422017-12-08 14:02:51 -08001570 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001571 SigningDetails verified;
Victor Hsieh5f761242018-01-20 10:30:12 -08001572 if (skipVerify) {
Dan Cashman636ea5e2017-12-18 10:38:20 -08001573 // systemDir APKs are already trusted, save time by not verifying
Gavin Corkeryed521ab2019-01-31 16:59:41 +00001574 verified = ApkSignatureVerifier.unsafeGetCertsWithoutVerification(
Dan Cashman636ea5e2017-12-18 10:38:20 -08001575 apkPath, minSignatureScheme);
1576 } else {
1577 verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme);
1578 }
Dan Cashman636ea5e2017-12-18 10:38:20 -08001579
1580 // Verify that entries are signed consistently with the first pkg
1581 // we encountered. Note that for splits, certificates may have
1582 // already been populated during an earlier parse of a base APK.
Patrick Baumann47117fc2017-12-19 10:17:21 -08001583 if (pkg.mSigningDetails == SigningDetails.UNKNOWN) {
1584 pkg.mSigningDetails = verified;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001585 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001586 if (!Signature.areExactMatch(pkg.mSigningDetails.signatures, verified.signatures)) {
Patrick Baumann9ff55742017-12-14 10:50:18 -08001587 throw new PackageParserException(
1588 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
1589 apkPath + " has mismatched certificates");
1590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 }
1593
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001594 private static AssetManager newConfiguredAssetManager() {
1595 AssetManager assetManager = new AssetManager();
Romain Guy408afbf2017-01-25 10:23:03 -08001596 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 -07001597 Build.VERSION.RESOURCES_SDK_INT);
1598 return assetManager;
1599 }
1600
Jeff Sharkey275e0852014-06-17 18:18:49 -07001601 /**
1602 * Utility method that retrieves lightweight details about a single APK
1603 * file, including package name, split name, and install location.
1604 *
1605 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001606 * @param flags optional parse flags, such as
1607 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001608 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001609 public static ApkLite parseApkLite(File apkFile, int flags)
1610 throws PackageParserException {
Dianne Hackbornca3872c2017-10-30 14:19:32 -07001611 return parseApkLiteInner(apkFile, null, null, flags);
1612 }
1613
1614 /**
1615 * Utility method that retrieves lightweight details about a single APK
1616 * file, including package name, split name, and install location.
1617 *
1618 * @param fd already open file descriptor of an apk file
1619 * @param debugPathName arbitrary text name for this file, for debug output
1620 * @param flags optional parse flags, such as
1621 * {@link #PARSE_COLLECT_CERTIFICATES}
1622 */
1623 public static ApkLite parseApkLite(FileDescriptor fd, String debugPathName, int flags)
1624 throws PackageParserException {
1625 return parseApkLiteInner(null, fd, debugPathName, flags);
1626 }
1627
1628 private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName,
1629 int flags) throws PackageParserException {
1630 final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001631
Jeff Sharkey275e0852014-06-17 18:18:49 -07001632 XmlResourceParser parser = null;
Winson7a3d82a2019-03-07 12:54:24 -08001633 ApkAssets apkAssets = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001635 try {
1636 apkAssets = fd != null
1637 ? ApkAssets.loadFromFd(fd, debugPathName, false, false)
1638 : ApkAssets.loadFromPath(apkPath);
1639 } catch (IOException e) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001640 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1641 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001642 }
1643
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001644 parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001645
Patrick Baumann47117fc2017-12-19 10:17:21 -08001646 final SigningDetails signingDetails;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001647 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1648 // TODO: factor signature related items out of Package object
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001649 final Package tempPkg = new Package((String) null);
Victor Hsieh5f761242018-01-20 10:30:12 -08001650 final boolean skipVerify = (flags & PARSE_IS_SYSTEM_DIR) != 0;
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001651 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1652 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001653 collectCertificates(tempPkg, apkFile, skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001654 } finally {
1655 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1656 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001657 signingDetails = tempPkg.mSigningDetails;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001658 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001659 signingDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001660 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001661
Jeff Sharkey275e0852014-06-17 18:18:49 -07001662 final AttributeSet attrs = parser;
Victor Hsieh54305982019-03-12 10:09:39 -07001663 return parseApkLite(apkPath, parser, attrs, signingDetails);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001664
1665 } catch (XmlPullParserException | IOException | RuntimeException e) {
Dianne Hackborn34041732017-01-31 15:27:13 -08001666 Slog.w(TAG, "Failed to parse " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001667 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1668 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001669 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001670 IoUtils.closeQuietly(parser);
Winson7a3d82a2019-03-07 12:54:24 -08001671 if (apkAssets != null) {
1672 try {
1673 apkAssets.close();
1674 } catch (Throwable ignored) {
1675 }
1676 }
1677 // TODO(b/72056911): Implement AutoCloseable on ApkAssets.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 }
1680
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001681 private static String validateName(String name, boolean requireSeparator,
1682 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 final int N = name.length();
1684 boolean hasSep = false;
1685 boolean front = true;
1686 for (int i=0; i<N; i++) {
1687 final char c = name.charAt(i);
1688 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1689 front = false;
1690 continue;
1691 }
1692 if (!front) {
1693 if ((c >= '0' && c <= '9') || c == '_') {
1694 continue;
1695 }
1696 }
1697 if (c == '.') {
1698 hasSep = true;
1699 front = true;
1700 continue;
1701 }
1702 return "bad character '" + c + "'";
1703 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001704 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1705 return "Invalid filename";
1706 }
1707 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 ? null : "must have at least one '.' separator";
1709 }
1710
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001711 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
Svet Ganov354cd3c2015-12-17 11:35:04 -08001712 AttributeSet attrs) throws IOException, XmlPullParserException,
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001713 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714
1715 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001716 while ((type = parser.next()) != XmlPullParser.START_TAG
1717 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 }
1719
Kenny Rootd2d29252011-08-08 11:27:57 -07001720 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001721 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1722 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001724 if (!parser.getName().equals(TAG_MANIFEST)) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001725 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1726 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 }
1728
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001729 final String packageName = attrs.getAttributeValue(null, "package");
1730 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001731 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001732 if (error != null) {
1733 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1734 "Invalid manifest package: " + error);
1735 }
1736 }
1737
Jeff Sharkey275e0852014-06-17 18:18:49 -07001738 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001739 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001740 if (splitName.length() == 0) {
1741 splitName = null;
1742 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001743 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001744 if (error != null) {
1745 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1746 "Invalid manifest split: " + error);
1747 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001748 }
1749 }
1750
1751 return Pair.create(packageName.intern(),
1752 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 }
1754
Adam Lesinski4e862812016-11-21 16:02:24 -08001755 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
Victor Hsieh54305982019-03-12 10:09:39 -07001756 SigningDetails signingDetails)
Adam Lesinski4e862812016-11-21 16:02:24 -08001757 throws IOException, XmlPullParserException, PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001758 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001759
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001760 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001761 int versionCode = 0;
Dianne Hackborn3accca02013-09-20 09:32:11 -07001762 int versionCodeMajor = 0;
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +00001763 int targetSdkVersion = DEFAULT_TARGET_SDK_VERSION;
1764 int minSdkVersion = DEFAULT_MIN_SDK_VERSION;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001765 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001766 boolean coreApp = false;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001767 boolean debuggable = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001768 boolean multiArch = false;
Selim Gurun2d291d82016-02-05 17:50:53 -08001769 boolean use32bitAbi = false;
Victor Hsieh54305982019-03-12 10:09:39 -07001770 boolean extractNativeLibs = true;
Adam Lesinski4e862812016-11-21 16:02:24 -08001771 boolean isolatedSplits = false;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001772 boolean isFeatureSplit = false;
Todd Kennedy29cfa272018-09-26 10:25:24 -07001773 boolean isSplitRequired = false;
Victor Hsiehfa9df0b2019-01-29 12:48:36 -08001774 boolean useEmbeddedDex = false;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001775 String configForSplit = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001776 String usesSplitName = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001777
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001778 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001779 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001780 if (attr.equals("installLocation")) {
1781 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001782 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001783 } else if (attr.equals("versionCode")) {
1784 versionCode = attrs.getAttributeIntValue(i, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001785 } else if (attr.equals("versionCodeMajor")) {
1786 versionCodeMajor = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001787 } else if (attr.equals("revisionCode")) {
1788 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001789 } else if (attr.equals("coreApp")) {
1790 coreApp = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski4e862812016-11-21 16:02:24 -08001791 } else if (attr.equals("isolatedSplits")) {
1792 isolatedSplits = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001793 } else if (attr.equals("configForSplit")) {
1794 configForSplit = attrs.getAttributeValue(i);
1795 } else if (attr.equals("isFeatureSplit")) {
1796 isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
Todd Kennedy29cfa272018-09-26 10:25:24 -07001797 } else if (attr.equals("isSplitRequired")) {
1798 isSplitRequired = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001799 }
1800 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001801
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +00001802 // Only search the tree when the tag is the direct child of <manifest> tag
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001803 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001804 final int searchDepth = parser.getDepth() + 1;
1805
1806 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1807 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1808 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1809 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1810 continue;
1811 }
1812
Adam Lesinski4e862812016-11-21 16:02:24 -08001813 if (parser.getDepth() != searchDepth) {
1814 continue;
1815 }
1816
1817 if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
1818 final VerifierInfo verifier = parseVerifier(attrs);
Kenny Root05ca4c92011-09-15 10:36:25 -07001819 if (verifier != null) {
1820 verifiers.add(verifier);
1821 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001822 } else if (TAG_APPLICATION.equals(parser.getName())) {
Narayan Kamatha8755a82014-07-15 12:26:35 +01001823 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1824 final String attr = attrs.getAttributeName(i);
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001825 if ("debuggable".equals(attr)) {
1826 debuggable = attrs.getAttributeBooleanValue(i, false);
1827 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001828 if ("multiArch".equals(attr)) {
1829 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001830 }
Selim Gurun2d291d82016-02-05 17:50:53 -08001831 if ("use32bitAbi".equals(attr)) {
1832 use32bitAbi = attrs.getAttributeBooleanValue(i, false);
Tao Baic9a02372016-01-12 15:02:24 -08001833 }
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001834 if ("extractNativeLibs".equals(attr)) {
Victor Hsieh54305982019-03-12 10:09:39 -07001835 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001836 }
Victor Hsiehfa9df0b2019-01-29 12:48:36 -08001837 if ("useEmbeddedDex".equals(attr)) {
1838 useEmbeddedDex = attrs.getAttributeBooleanValue(i, false);
Victor Hsiehe7b5a8d2018-11-16 10:27:06 -08001839 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001840 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001841 } else if (TAG_USES_SPLIT.equals(parser.getName())) {
1842 if (usesSplitName != null) {
1843 Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
1844 continue;
1845 }
1846
1847 usesSplitName = attrs.getAttributeValue(ANDROID_RESOURCES, "name");
1848 if (usesSplitName == null) {
1849 throw new PackageParserException(
1850 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1851 "<uses-split> tag requires 'android:name' attribute");
1852 }
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +00001853 } else if (TAG_USES_SDK.equals(parser.getName())) {
1854 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1855 final String attr = attrs.getAttributeName(i);
1856 if ("targetSdkVersion".equals(attr)) {
1857 targetSdkVersion = attrs.getAttributeIntValue(i,
1858 DEFAULT_TARGET_SDK_VERSION);
1859 }
1860 if ("minSdkVersion".equals(attr)) {
1861 minSdkVersion = attrs.getAttributeIntValue(i, DEFAULT_MIN_SDK_VERSION);
1862 }
1863 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001864 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001865 }
1866
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001867 return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
Todd Kennedy29cfa272018-09-26 10:25:24 -07001868 configForSplit, usesSplitName, isSplitRequired, versionCode, versionCodeMajor,
1869 revisionCode, installLocation, verifiers, signingDetails, coreApp, debuggable,
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +00001870 multiArch, use32bitAbi, useEmbeddedDex, extractNativeLibs, isolatedSplits,
1871 minSdkVersion, targetSdkVersion);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001872 }
1873
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001874 /**
Svet Ganov354cd3c2015-12-17 11:35:04 -08001875 * Parses a child package and adds it to the parent if successful. If you add
1876 * new tags that need to be supported by child packages make sure to add them
1877 * to {@link #CHILD_PACKAGE_TAGS}.
1878 *
1879 * @param parentPkg The parent that contains the child
1880 * @param res Resources against which to resolve values
1881 * @param parser Parser of the manifest
1882 * @param flags Flags about how to parse
1883 * @param outError Human readable error if parsing fails
1884 * @return True of parsing succeeded.
1885 *
1886 * @throws XmlPullParserException
1887 * @throws IOException
1888 */
1889 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
1890 int flags, String[] outError) throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001891 // Make sure we have a valid child package name
1892 String childPackageName = parser.getAttributeValue(null, "package");
1893 if (validateName(childPackageName, true, false) != null) {
1894 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1895 return false;
1896 }
1897
1898 // Child packages must be unique
1899 if (childPackageName.equals(parentPkg.packageName)) {
1900 String message = "Child package name cannot be equal to parent package name: "
1901 + parentPkg.packageName;
1902 Slog.w(TAG, message);
1903 outError[0] = message;
1904 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1905 return false;
1906 }
1907
1908 // Child packages must be unique
1909 if (parentPkg.hasChildPackage(childPackageName)) {
1910 String message = "Duplicate child package:" + childPackageName;
1911 Slog.w(TAG, message);
1912 outError[0] = message;
1913 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1914 return false;
1915 }
1916
1917 // Go ahead and parse the child
1918 Package childPkg = new Package(childPackageName);
1919
1920 // Child package inherits parent version code/name/target SDK
1921 childPkg.mVersionCode = parentPkg.mVersionCode;
1922 childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
1923 childPkg.mVersionName = parentPkg.mVersionName;
1924 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
Todd Kennedy89d60182016-03-11 11:18:32 -08001925 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001926
1927 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
1928 if (childPkg == null) {
1929 // If we got null then error was set during child parsing
1930 return false;
1931 }
1932
1933 // Set the parent-child relation
1934 if (parentPkg.childPackages == null) {
1935 parentPkg.childPackages = new ArrayList<>();
1936 }
1937 parentPkg.childPackages.add(childPkg);
1938 childPkg.parentPackage = parentPkg;
1939
1940 return true;
1941 }
1942
1943 /**
1944 * Parse the manifest of a <em>base APK</em>. When adding new features you
1945 * need to consider whether they should be supported by split APKs and child
1946 * packages.
1947 *
Jack He61034792019-04-10 23:01:45 +00001948 * @param apkPath The package apk file path
Svet Ganov354cd3c2015-12-17 11:35:04 -08001949 * @param res The resources from which to resolve values
1950 * @param parser The manifest parser
1951 * @param flags Flags how to parse
1952 * @param outError Human readable error message
1953 * @return Parsed package or null on error.
1954 *
1955 * @throws XmlPullParserException
1956 * @throws IOException
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001957 */
Jack He61034792019-04-10 23:01:45 +00001958 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1959 private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001960 String[] outError) throws XmlPullParserException, IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001961 final String splitName;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001962 final String pkgName;
1963
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001964 try {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001965 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001966 pkgName = packageSplit.first;
1967 splitName = packageSplit.second;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001968
1969 if (!TextUtils.isEmpty(splitName)) {
1970 outError[0] = "Expected base APK, but found split " + splitName;
1971 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1972 return null;
1973 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001974 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1976 return null;
1977 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001978
Jack He61034792019-04-10 23:01:45 +00001979 if (mCallback != null) {
1980 String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
1981 if (overlayPaths != null && overlayPaths.length > 0) {
1982 for (String overlayPath : overlayPaths) {
1983 res.getAssets().addOverlayPath(overlayPath);
1984 }
1985 }
1986 }
1987
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001988 final Package pkg = new Package(pkgName);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001989
Svet Ganov354cd3c2015-12-17 11:35:04 -08001990 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001991 com.android.internal.R.styleable.AndroidManifest);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001992
Dianne Hackborn3accca02013-09-20 09:32:11 -07001993 pkg.mVersionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001994 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001995 pkg.mVersionCodeMajor = sa.getInteger(
1996 com.android.internal.R.styleable.AndroidManifest_versionCodeMajor, 0);
Patrick Baumannc2def582018-04-04 12:14:15 -07001997 pkg.applicationInfo.setVersionCode(pkg.getLongVersionCode());
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001998 pkg.baseRevisionCode = sa.getInteger(
1999 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002000 pkg.mVersionName = sa.getNonConfigurationString(
2001 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002002 if (pkg.mVersionName != null) {
2003 pkg.mVersionName = pkg.mVersionName.intern();
2004 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002005
2006 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
2007
Alan Viveretteb6a25732017-11-21 14:49:24 -05002008 pkg.mCompileSdkVersion = sa.getInteger(
2009 com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0);
2010 pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion;
2011 pkg.mCompileSdkVersionCodename = sa.getNonConfigurationString(
2012 com.android.internal.R.styleable.AndroidManifest_compileSdkVersionCodename, 0);
2013 if (pkg.mCompileSdkVersionCodename != null) {
2014 pkg.mCompileSdkVersionCodename = pkg.mCompileSdkVersionCodename.intern();
2015 }
2016 pkg.applicationInfo.compileSdkVersionCodename = pkg.mCompileSdkVersionCodename;
2017
Svet Ganov354cd3c2015-12-17 11:35:04 -08002018 sa.recycle();
2019
2020 return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
2021 }
2022
2023 /**
2024 * This is the common parsing routing for handling parent and child
2025 * packages in a base APK. The difference between parent and child
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002026 * parsing is that some tags are not supported by child packages as
Svet Ganov354cd3c2015-12-17 11:35:04 -08002027 * well as some manifest attributes are ignored. The implementation
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002028 * assumes the calling code has already handled the manifest tag if needed
Svet Ganov354cd3c2015-12-17 11:35:04 -08002029 * (this applies to the parent only).
2030 *
2031 * @param pkg The package which to populate
2032 * @param acceptedTags Which tags to handle, null to handle all
2033 * @param res Resources against which to resolve values
2034 * @param parser Parser of the manifest
2035 * @param flags Flags about how to parse
2036 * @param outError Human readable error if parsing fails
2037 * @return The package if parsing succeeded or null.
2038 *
2039 * @throws XmlPullParserException
2040 * @throws IOException
2041 */
2042 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
2043 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
2044 IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002045 mParseInstrumentationArgs = null;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002046
2047 int type;
2048 boolean foundApp = false;
2049
2050 TypedArray sa = res.obtainAttributes(parser,
2051 com.android.internal.R.styleable.AndroidManifest);
2052
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002053 String str = sa.getNonConfigurationString(
2054 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
2055 if (str != null && str.length() > 0) {
Sudheer Shanka9c5079a2018-08-03 12:41:10 -07002056 String nameError = validateName(str, true, true);
Svet Ganov354cd3c2015-12-17 11:35:04 -08002057 if (nameError != null && !"android".equals(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002058 outError[0] = "<manifest> specifies bad sharedUserId name \""
2059 + str + "\": " + nameError;
2060 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
2061 return null;
2062 }
2063 pkg.mSharedUserId = str.intern();
2064 pkg.mSharedUserLabel = sa.getResourceId(
2065 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
2066 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08002067
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08002068 pkg.installLocation = sa.getInteger(
2069 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07002070 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002071 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07002072
Todd Kennedy11e45072017-01-25 13:24:21 -08002073 final int targetSandboxVersion = sa.getInteger(
2074 com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion,
2075 PARSE_DEFAULT_TARGET_SANDBOX);
2076 pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion;
Alan Viverettefd274a02014-03-27 15:39:15 -07002077
Kenny Root7cb9be22012-05-30 15:30:37 -07002078 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07002079 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07002080 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
2081 }
2082
Adam Lesinski4e862812016-11-21 16:02:24 -08002083 if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
2084 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
2085 }
2086
Dianne Hackborn723738c2009-06-25 19:48:04 -07002087 // Resource boolean are -1, so 1 means we don't know the value.
2088 int supportsSmallScreens = 1;
2089 int supportsNormalScreens = 1;
2090 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002091 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002092 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002093 int anyDensity = 1;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002095 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07002096 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2097 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2098 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002099 continue;
2100 }
2101
2102 String tagName = parser.getName();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002103
2104 if (acceptedTags != null && !acceptedTags.contains(tagName)) {
2105 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
2106 + tagName + " at " + mArchiveSourcePath + " "
2107 + parser.getPositionDescription());
2108 XmlUtils.skipCurrentTag(parser);
2109 continue;
2110 }
2111
2112 if (tagName.equals(TAG_APPLICATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002113 if (foundApp) {
2114 if (RIGID_PARSER) {
2115 outError[0] = "<manifest> has more than one <application>";
2116 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2117 return null;
2118 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002119 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002120 XmlUtils.skipCurrentTag(parser);
2121 continue;
2122 }
2123 }
2124
2125 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002126 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002127 return null;
2128 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002129 } else if (tagName.equals(TAG_OVERLAY)) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002130 sa = res.obtainAttributes(parser,
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002131 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
2132 pkg.mOverlayTarget = sa.getString(
2133 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
Ryan Mitchella3628462019-01-14 12:19:40 -08002134 pkg.mOverlayTargetName = sa.getString(
2135 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetName);
Adrian Roosc84df772018-01-19 21:20:22 +01002136 pkg.mOverlayCategory = sa.getString(
2137 com.android.internal.R.styleable.AndroidManifestResourceOverlay_category);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002138 pkg.mOverlayPriority = sa.getInt(
2139 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
2140 0);
Adam Lesinskie7334972018-01-17 16:13:52 -08002141 pkg.mOverlayIsStatic = sa.getBoolean(
Jaekyun Seok04342892017-03-02 15:24:19 +09002142 com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
2143 false);
Todd Leeea2f3be2017-03-16 14:00:52 -07002144 final String propName = sa.getString(
2145 com.android.internal.R.styleable
2146 .AndroidManifestResourceOverlay_requiredSystemPropertyName);
2147 final String propValue = sa.getString(
2148 com.android.internal.R.styleable
2149 .AndroidManifestResourceOverlay_requiredSystemPropertyValue);
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002150 sa.recycle();
2151
2152 if (pkg.mOverlayTarget == null) {
2153 outError[0] = "<overlay> does not specify a target package";
2154 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2155 return null;
2156 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002157
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002158 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
2159 outError[0] = "<overlay> priority must be between 0 and 9999";
2160 mParseError =
2161 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2162 return null;
2163 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002164
2165 // check to see if overlay should be excluded based on system property condition
2166 if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
2167 Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
2168 + pkg.baseCodePath+ ": overlay ignored due to required system property: "
2169 + propName + " with value: " + propValue);
2170 return null;
Jaekyun Seok04342892017-03-02 15:24:19 +09002171 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002172
Zoran Jovanovic946e32f2019-02-17 22:02:40 +01002173 pkg.applicationInfo.privateFlags |=
2174 ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY;
2175
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002176 XmlUtils.skipCurrentTag(parser);
2177
Svet Ganov354cd3c2015-12-17 11:35:04 -08002178 } else if (tagName.equals(TAG_KEY_SETS)) {
2179 if (!parseKeySets(pkg, res, parser, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08002180 return null;
2181 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002182 } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002183 if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002184 return null;
2185 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002186 } else if (tagName.equals(TAG_PERMISSION)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002187 if (!parsePermission(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 return null;
2189 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002190 } else if (tagName.equals(TAG_PERMISSION_TREE)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002191 if (!parsePermissionTree(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 return null;
2193 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002194 } else if (tagName.equals(TAG_USES_PERMISSION)) {
Chad Brubakere2107312019-02-04 12:30:01 -08002195 if (!parseUsesPermission(pkg, res, parser)) {
Svetoslav96a77162015-04-03 13:58:33 -07002196 return null;
2197 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002198 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
2199 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
Chad Brubakere2107312019-02-04 12:30:01 -08002200 if (!parseUsesPermission(pkg, res, parser)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002201 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002202 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002203 } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002204 ConfigurationInfo cPref = new ConfigurationInfo();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002205 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
2207 cPref.reqTouchScreen = sa.getInt(
2208 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
2209 Configuration.TOUCHSCREEN_UNDEFINED);
2210 cPref.reqKeyboardType = sa.getInt(
2211 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
2212 Configuration.KEYBOARD_UNDEFINED);
2213 if (sa.getBoolean(
2214 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
2215 false)) {
2216 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
2217 }
2218 cPref.reqNavigation = sa.getInt(
2219 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
2220 Configuration.NAVIGATION_UNDEFINED);
2221 if (sa.getBoolean(
2222 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
2223 false)) {
2224 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
2225 }
2226 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002227 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002228
2229 XmlUtils.skipCurrentTag(parser);
2230
Svet Ganov354cd3c2015-12-17 11:35:04 -08002231 } else if (tagName.equals(TAG_USES_FEATURE)) {
2232 FeatureInfo fi = parseUsesFeature(res, parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002233 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
2234
Dianne Hackborn49237342009-08-27 20:08:01 -07002235 if (fi.name == null) {
2236 ConfigurationInfo cPref = new ConfigurationInfo();
2237 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002238 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07002239 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07002240
2241 XmlUtils.skipCurrentTag(parser);
2242
Svet Ganov354cd3c2015-12-17 11:35:04 -08002243 } else if (tagName.equals(TAG_FEATURE_GROUP)) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002244 FeatureGroupInfo group = new FeatureGroupInfo();
2245 ArrayList<FeatureInfo> features = null;
2246 final int innerDepth = parser.getDepth();
2247 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2248 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2249 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2250 continue;
2251 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07002252
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002253 final String innerTagName = parser.getName();
2254 if (innerTagName.equals("uses-feature")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002255 FeatureInfo featureInfo = parseUsesFeature(res, parser);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002256 // FeatureGroups are stricter and mandate that
2257 // any <uses-feature> declared are mandatory.
2258 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
2259 features = ArrayUtils.add(features, featureInfo);
2260 } else {
2261 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
2262 " at " + mArchiveSourcePath + " " +
2263 parser.getPositionDescription());
2264 }
2265 XmlUtils.skipCurrentTag(parser);
2266 }
2267
2268 if (features != null) {
2269 group.features = new FeatureInfo[features.size()];
2270 group.features = features.toArray(group.features);
2271 }
2272 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07002273
Svet Ganov354cd3c2015-12-17 11:35:04 -08002274 } else if (tagName.equals(TAG_USES_SDK)) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07002275 if (SDK_VERSION > 0) {
Victor Hsieh54305982019-03-12 10:09:39 -07002276 sa = res.obtainAttributes(parser,
2277 com.android.internal.R.styleable.AndroidManifestUsesSdk);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002278
Victor Hsieh54305982019-03-12 10:09:39 -07002279 int minVers = 1;
2280 String minCode = null;
2281 int targetVers = 0;
2282 String targetCode = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002283
Victor Hsieh54305982019-03-12 10:09:39 -07002284 TypedValue val = sa.peekValue(
2285 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
2286 if (val != null) {
2287 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
2288 minCode = val.string.toString();
2289 } else {
2290 // If it's not a string, it's an integer.
2291 minVers = val.data;
2292 }
2293 }
Victor Hsieh4e54b522018-10-12 15:38:18 -07002294
Victor Hsieh54305982019-03-12 10:09:39 -07002295 val = sa.peekValue(
2296 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
2297 if (val != null) {
2298 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
2299 targetCode = val.string.toString();
2300 if (minCode == null) {
2301 minCode = targetCode;
2302 }
2303 } else {
2304 // If it's not a string, it's an integer.
2305 targetVers = val.data;
2306 }
2307 } else {
2308 targetVers = minVers;
2309 targetCode = minCode;
2310 }
Victor Hsieh4e54b522018-10-12 15:38:18 -07002311
Victor Hsieh54305982019-03-12 10:09:39 -07002312 sa.recycle();
Victor Hsieh4e54b522018-10-12 15:38:18 -07002313
Victor Hsieh54305982019-03-12 10:09:39 -07002314 final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode,
2315 SDK_VERSION, SDK_CODENAMES, outError);
2316 if (minSdkVersion < 0) {
Victor Hsieh4e54b522018-10-12 15:38:18 -07002317 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2318 return null;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002319 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002320
Victor Hsieh54305982019-03-12 10:09:39 -07002321 final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers,
2322 targetCode, SDK_CODENAMES, outError);
2323 if (targetSdkVersion < 0) {
2324 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2325 return null;
2326 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002327
Victor Hsieh54305982019-03-12 10:09:39 -07002328 pkg.applicationInfo.minSdkVersion = minSdkVersion;
2329 pkg.applicationInfo.targetSdkVersion = targetSdkVersion;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002330 }
Victor Hsieh54305982019-03-12 10:09:39 -07002331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332 XmlUtils.skipCurrentTag(parser);
Victor Hsieh54305982019-03-12 10:09:39 -07002333
Svet Ganov354cd3c2015-12-17 11:35:04 -08002334 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
2335 sa = res.obtainAttributes(parser,
Dianne Hackborn723738c2009-06-25 19:48:04 -07002336 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
2337
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002338 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
2339 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
2340 0);
2341 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
2342 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
2343 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07002344 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
2345 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
2346 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002347
Dianne Hackborn723738c2009-06-25 19:48:04 -07002348 // This is a trick to get a boolean and still able to detect
2349 // if a value was actually set.
2350 supportsSmallScreens = sa.getInteger(
2351 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
2352 supportsSmallScreens);
2353 supportsNormalScreens = sa.getInteger(
2354 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
2355 supportsNormalScreens);
2356 supportsLargeScreens = sa.getInteger(
2357 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
2358 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002359 supportsXLargeScreens = sa.getInteger(
2360 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
2361 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002362 resizeable = sa.getInteger(
2363 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002364 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002365 anyDensity = sa.getInteger(
2366 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
2367 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07002368
2369 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002370
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002371 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002372
Svet Ganov354cd3c2015-12-17 11:35:04 -08002373 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
2374 sa = res.obtainAttributes(parser,
Dianne Hackborn854060af2009-07-09 18:14:31 -07002375 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
2376
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002377 // Note: don't allow this value to be a reference to a resource
2378 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07002379 String name = sa.getNonResourceString(
2380 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
2381
2382 sa.recycle();
2383
Todd Kennedy232d29e2017-11-06 14:45:53 -08002384 if (name != null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002385 if (pkg.protectedBroadcasts == null) {
2386 pkg.protectedBroadcasts = new ArrayList<String>();
2387 }
2388 if (!pkg.protectedBroadcasts.contains(name)) {
2389 pkg.protectedBroadcasts.add(name.intern());
2390 }
2391 }
2392
2393 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002394
Svet Ganov354cd3c2015-12-17 11:35:04 -08002395 } else if (tagName.equals(TAG_INSTRUMENTATION)) {
2396 if (parseInstrumentation(pkg, res, parser, outError) == null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002397 return null;
2398 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002399 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
2400 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002401 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2402
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002403 String orig =sa.getNonConfigurationString(
2404 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002405 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002406 if (pkg.mOriginalPackages == null) {
2407 pkg.mOriginalPackages = new ArrayList<String>();
2408 pkg.mRealPackage = pkg.packageName;
2409 }
2410 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002411 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002412
2413 sa.recycle();
2414
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002415 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002416
Svet Ganov354cd3c2015-12-17 11:35:04 -08002417 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
2418 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002419 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2420
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002421 String name = sa.getNonConfigurationString(
2422 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002423
2424 sa.recycle();
2425
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002426 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002427 if (pkg.mAdoptPermissions == null) {
2428 pkg.mAdoptPermissions = new ArrayList<String>();
2429 }
2430 pkg.mAdoptPermissions.add(name);
2431 }
2432
2433 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002434
Svet Ganov354cd3c2015-12-17 11:35:04 -08002435 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002436 // Just skip this tag
2437 XmlUtils.skipCurrentTag(parser);
2438 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002439
Svet Ganov354cd3c2015-12-17 11:35:04 -08002440 } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002441 // Just skip this tag
2442 XmlUtils.skipCurrentTag(parser);
2443 continue;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002444 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
Michael Wrighteaeb1902013-09-05 18:15:57 -07002445 XmlUtils.skipCurrentTag(parser);
2446 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002447
Svet Ganov354cd3c2015-12-17 11:35:04 -08002448 } else if (tagName.equals(TAG_EAT_COMMENT)) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002449 // Just skip this tag
2450 XmlUtils.skipCurrentTag(parser);
2451 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002452
Svet Ganov354cd3c2015-12-17 11:35:04 -08002453 } else if (tagName.equals(TAG_PACKAGE)) {
Svet Ganova7532cf2016-05-02 08:13:17 -07002454 if (!MULTI_PACKAGE_APK_ENABLED) {
2455 XmlUtils.skipCurrentTag(parser);
2456 continue;
2457 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002458 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
2459 // If parsing a child failed the error is already set
2460 return null;
2461 }
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002462
2463 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
2464 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
2465 sa = res.obtainAttributes(parser,
2466 com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
2467 final String hash = sa.getNonConfigurationString(
2468 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
2469 sa.recycle();
2470
2471 pkg.restrictUpdateHash = null;
2472 if (hash != null) {
2473 final int hashLength = hash.length();
2474 final byte[] hashBytes = new byte[hashLength / 2];
2475 for (int i = 0; i < hashLength; i += 2){
2476 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
2477 + Character.digit(hash.charAt(i + 1), 16));
2478 }
2479 pkg.restrictUpdateHash = hashBytes;
2480 }
2481 }
2482
2483 XmlUtils.skipCurrentTag(parser);
2484
Dianne Hackborn854060af2009-07-09 18:14:31 -07002485 } else if (RIGID_PARSER) {
2486 outError[0] = "Bad element under <manifest>: "
2487 + parser.getName();
2488 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2489 return null;
2490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002491 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002492 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002493 + " at " + mArchiveSourcePath + " "
2494 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002495 XmlUtils.skipCurrentTag(parser);
2496 continue;
2497 }
2498 }
2499
2500 if (!foundApp && pkg.instrumentation.size() == 0) {
2501 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
2502 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
2503 }
2504
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002505 final int NP = PackageParser.NEW_PERMISSIONS.length;
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002506 StringBuilder newPermsMsg = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002507 for (int ip=0; ip<NP; ip++) {
2508 final PackageParser.NewPermissionInfo npi
2509 = PackageParser.NEW_PERMISSIONS[ip];
2510 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
2511 break;
2512 }
2513 if (!pkg.requestedPermissions.contains(npi.name)) {
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002514 if (newPermsMsg == null) {
2515 newPermsMsg = new StringBuilder(128);
2516 newPermsMsg.append(pkg.packageName);
2517 newPermsMsg.append(": compat added ");
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002518 } else {
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002519 newPermsMsg.append(' ');
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002520 }
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002521 newPermsMsg.append(npi.name);
Chad Brubakere2107312019-02-04 12:30:01 -08002522 pkg.requestedPermissions.add(npi.name);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002523 pkg.implicitPermissions.add(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002524 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002525 }
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002526 if (newPermsMsg != null) {
2527 Slog.i(TAG, newPermsMsg.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002528 }
Dianne Hackborn79245122012-03-12 10:51:26 -07002529
Anthony Hugh6f5eadc2019-08-22 15:35:48 -07002530 List<SplitPermissionInfoParcelable> splitPermissions = getSplitPermissions();
2531 final int listSize = splitPermissions.size();
2532 for (int is = 0; is < listSize; is++) {
2533 final SplitPermissionInfoParcelable spi = splitPermissions.get(is);
Philip P. Moltmann039678e2018-09-18 13:04:38 -07002534 if (pkg.applicationInfo.targetSdkVersion >= spi.getTargetSdk()
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -07002535 || !pkg.requestedPermissions.contains(spi.getSplitPermission())) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07002536 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07002537 }
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -07002538 final List<String> newPerms = spi.getNewPermissions();
2539 for (int in = 0; in < newPerms.size(); in++) {
2540 final String perm = newPerms.get(in);
Dianne Hackborn79245122012-03-12 10:51:26 -07002541 if (!pkg.requestedPermissions.contains(perm)) {
Chad Brubakere2107312019-02-04 12:30:01 -08002542 pkg.requestedPermissions.add(perm);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002543 pkg.implicitPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07002544 }
2545 }
2546 }
2547
Dianne Hackborn723738c2009-06-25 19:48:04 -07002548 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
2549 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002550 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002551 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
2552 }
2553 if (supportsNormalScreens != 0) {
2554 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
2555 }
2556 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
2557 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002558 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002559 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
2560 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002561 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
2562 && pkg.applicationInfo.targetSdkVersion
2563 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
2564 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
2565 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002566 if (resizeable < 0 || (resizeable > 0
2567 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002568 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002569 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
2570 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002571 if (anyDensity < 0 || (anyDensity > 0
2572 && pkg.applicationInfo.targetSdkVersion
2573 >= android.os.Build.VERSION_CODES.DONUT)) {
2574 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07002575 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07002576
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002577 // At this point we can check if an application is not supporting densities and hence
2578 // cannot be windowed / resized. Note that an SDK version of 0 is common for
2579 // pre-Doughnut applications.
2580 if (pkg.applicationInfo.usesCompatibilityMode()) {
Winson Chungd3395382016-12-13 11:49:09 -08002581 adjustPackageToBeUnresizeableAndUnpipable(pkg);
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002582 }
Jeff Sharkey4aacd8b2018-07-24 15:24:21 -06002583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002584 return pkg;
2585 }
2586
Anthony Hugh6f5eadc2019-08-22 15:35:48 -07002587 private List<SplitPermissionInfoParcelable> getSplitPermissions() {
2588 // PackageManager runs this code during initialization prior to registering with
2589 // ServiceManager, so we can't use the PackageManager API. Instead, just read from
2590 // SystemConfig directly when in any SystemProcess and only use PackageManager when not in
2591 // one.
2592 if (ActivityThread.isSystem()) {
2593 return PermissionManager.splitPermissionInfoListToParcelableList(
2594 SystemConfig.getInstance().getSplitPermissions());
2595 } else {
2596 try {
2597 return ActivityThread.getPackageManager().getSplitPermissions();
2598 } catch (RemoteException e) {
2599 throw e.rethrowFromSystemServer();
2600 }
2601 }
2602 }
2603
Todd Leeea2f3be2017-03-16 14:00:52 -07002604 private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
2605
2606 if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
2607 if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
2608 // malformed condition - incomplete
2609 Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
2610 + "=" + propValue + "' - require both requiredSystemPropertyName"
2611 + " AND requiredSystemPropertyValue to be specified.");
2612 return false;
2613 }
2614 // no valid condition set - so no exclusion criteria, overlay will be included.
2615 return true;
2616 }
2617
2618 // check property value - make sure it is both set and equal to expected value
2619 final String currValue = SystemProperties.get(propName);
2620 return (currValue != null && currValue.equals(propValue));
2621 }
2622
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002623 /**
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002624 * This is a pre-density application which will get scaled - instead of being pixel perfect.
2625 * This type of application is not resizable.
2626 *
2627 * @param pkg The package which needs to be marked as unresizable.
2628 */
Winson Chungd3395382016-12-13 11:49:09 -08002629 private void adjustPackageToBeUnresizeableAndUnpipable(Package pkg) {
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002630 for (Activity a : pkg.activities) {
2631 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -08002632 a.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE;
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002633 }
2634 }
2635
2636 /**
Chad Brubakera58ce392018-10-29 14:14:22 -07002637
2638 /**
Narayan Kamath71fcc142019-01-15 18:20:39 +00002639 * Matches a given {@code targetCode} against a set of release codeNames. Target codes can
2640 * either be of the form {@code [codename]}" (e.g {@code "Q"}) or of the form
2641 * {@code [codename].[fingerprint]} (e.g {@code "Q.cafebc561"}).
2642 */
2643 private static boolean matchTargetCode(@NonNull String[] codeNames,
2644 @NonNull String targetCode) {
2645 final String targetCodeName;
2646 final int targetCodeIdx = targetCode.indexOf('.');
2647 if (targetCodeIdx == -1) {
2648 targetCodeName = targetCode;
2649 } else {
2650 targetCodeName = targetCode.substring(0, targetCodeIdx);
2651 }
2652 return ArrayUtils.contains(codeNames, targetCodeName);
2653 }
2654
2655 /**
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002656 * Computes the targetSdkVersion to use at runtime. If the package is not
2657 * compatible with this platform, populates {@code outError[0]} with an
2658 * error message.
2659 * <p>
2660 * If {@code targetCode} is not specified, e.g. the value is {@code null},
2661 * then the {@code targetVers} will be returned unmodified.
2662 * <p>
2663 * Otherwise, the behavior varies based on whether the current platform
2664 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2665 * has length > 0:
2666 * <ul>
2667 * <li>If this is a pre-release platform and the value specified by
2668 * {@code targetCode} is contained within the array of allowed pre-release
2669 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2670 * <li>If this is a released platform, this method will return -1 to
2671 * indicate that the package is not compatible with this platform.
2672 * </ul>
2673 *
2674 * @param targetVers targetSdkVersion number, if specified in the
2675 * application manifest, or 0 otherwise
2676 * @param targetCode targetSdkVersion code, if specified in the application
2677 * manifest, or {@code null} otherwise
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002678 * @param platformSdkCodenames array of allowed pre-release SDK codenames
2679 * for this platform
2680 * @param outError output array to populate with error, if applicable
2681 * @return the targetSdkVersion to use at runtime, or -1 if the package is
2682 * not compatible with this platform
2683 * @hide Exposed for unit testing only.
2684 */
2685 @TestApi
2686 public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002687 @Nullable String targetCode, @NonNull String[] platformSdkCodenames,
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +00002688 @NonNull String[] outError) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002689 // If it's a release SDK, return the version number unmodified.
2690 if (targetCode == null) {
2691 return targetVers;
2692 }
2693
2694 // If it's a pre-release SDK and the codename matches this platform, it
2695 // definitely targets this SDK.
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +00002696 if (matchTargetCode(platformSdkCodenames, targetCode)) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002697 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2698 }
2699
2700 // Otherwise, we're looking at an incompatible pre-release SDK.
2701 if (platformSdkCodenames.length > 0) {
2702 outError[0] = "Requires development platform " + targetCode
2703 + " (current platform is any of "
2704 + Arrays.toString(platformSdkCodenames) + ")";
2705 } else {
2706 outError[0] = "Requires development platform " + targetCode
2707 + " but this is a release platform.";
2708 }
2709 return -1;
2710 }
2711
2712 /**
2713 * Computes the minSdkVersion to use at runtime. If the package is not
2714 * compatible with this platform, populates {@code outError[0]} with an
2715 * error message.
2716 * <p>
2717 * If {@code minCode} is not specified, e.g. the value is {@code null},
2718 * then behavior varies based on the {@code platformSdkVersion}:
2719 * <ul>
2720 * <li>If the platform SDK version is greater than or equal to the
2721 * {@code minVers}, returns the {@code mniVers} unmodified.
2722 * <li>Otherwise, returns -1 to indicate that the package is not
2723 * compatible with this platform.
2724 * </ul>
2725 * <p>
2726 * Otherwise, the behavior varies based on whether the current platform
2727 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2728 * has length > 0:
2729 * <ul>
2730 * <li>If this is a pre-release platform and the value specified by
2731 * {@code targetCode} is contained within the array of allowed pre-release
2732 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2733 * <li>If this is a released platform, this method will return -1 to
2734 * indicate that the package is not compatible with this platform.
2735 * </ul>
2736 *
2737 * @param minVers minSdkVersion number, if specified in the application
2738 * manifest, or 1 otherwise
2739 * @param minCode minSdkVersion code, if specified in the application
2740 * manifest, or {@code null} otherwise
2741 * @param platformSdkVersion platform SDK version number, typically
2742 * Build.VERSION.SDK_INT
2743 * @param platformSdkCodenames array of allowed prerelease SDK codenames
2744 * for this platform
2745 * @param outError output array to populate with error, if applicable
2746 * @return the minSdkVersion to use at runtime, or -1 if the package is not
2747 * compatible with this platform
2748 * @hide Exposed for unit testing only.
2749 */
2750 @TestApi
2751 public static int computeMinSdkVersion(@IntRange(from = 1) int minVers,
2752 @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion,
2753 @NonNull String[] platformSdkCodenames, @NonNull String[] outError) {
2754 // If it's a release SDK, make sure we meet the minimum SDK requirement.
2755 if (minCode == null) {
2756 if (minVers <= platformSdkVersion) {
2757 return minVers;
2758 }
2759
2760 // We don't meet the minimum SDK requirement.
2761 outError[0] = "Requires newer sdk version #" + minVers
2762 + " (current version is #" + platformSdkVersion + ")";
2763 return -1;
2764 }
2765
2766 // If it's a pre-release SDK and the codename matches this platform, we
2767 // definitely meet the minimum SDK requirement.
Narayan Kamath71fcc142019-01-15 18:20:39 +00002768 if (matchTargetCode(platformSdkCodenames, minCode)) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002769 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2770 }
2771
2772 // Otherwise, we're looking at an incompatible pre-release SDK.
2773 if (platformSdkCodenames.length > 0) {
2774 outError[0] = "Requires development platform " + minCode
2775 + " (current platform is any of "
2776 + Arrays.toString(platformSdkCodenames) + ")";
2777 } else {
2778 outError[0] = "Requires development platform " + minCode
2779 + " but this is a release platform.";
2780 }
2781 return -1;
2782 }
2783
Todd Kennedy27c24fb2015-09-17 16:49:25 -07002784 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002785 FeatureInfo fi = new FeatureInfo();
2786 TypedArray sa = res.obtainAttributes(attrs,
2787 com.android.internal.R.styleable.AndroidManifestUsesFeature);
2788 // Note: don't allow this value to be a reference to a resource
2789 // that may change.
2790 fi.name = sa.getNonResourceString(
2791 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
Jeff Sharkey115d2c12016-02-15 17:25:57 -07002792 fi.version = sa.getInt(
2793 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002794 if (fi.name == null) {
2795 fi.reqGlEsVersion = sa.getInt(
2796 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
2797 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2798 }
2799 if (sa.getBoolean(
2800 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
2801 fi.flags |= FeatureInfo.FLAG_REQUIRED;
2802 }
2803 sa.recycle();
2804 return fi;
2805 }
2806
Svet Ganov67882122016-12-11 16:36:34 -08002807 private boolean parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser,
2808 String[] outError) throws XmlPullParserException, IOException {
2809 TypedArray sa = res.obtainAttributes(parser,
2810 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary);
2811
2812 // Note: don't allow this value to be a reference to a resource that may change.
2813 String lname = sa.getNonResourceString(
2814 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
2815 final int version = sa.getInt(
2816 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002817 String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable
Svet Ganov67882122016-12-11 16:36:34 -08002818 .AndroidManifestUsesStaticLibrary_certDigest);
2819 sa.recycle();
2820
2821 // Since an APK providing a static shared lib can only provide the lib - fail if malformed
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002822 if (lname == null || version < 0 || certSha256Digest == null) {
Svet Ganov67882122016-12-11 16:36:34 -08002823 outError[0] = "Bad uses-static-library declaration name: " + lname + " version: "
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002824 + version + " certDigest" + certSha256Digest;
Svet Ganov67882122016-12-11 16:36:34 -08002825 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2826 XmlUtils.skipCurrentTag(parser);
2827 return false;
2828 }
2829
2830 // Can depend only on one version of the same library
2831 if (pkg.usesStaticLibraries != null && pkg.usesStaticLibraries.contains(lname)) {
2832 outError[0] = "Depending on multiple versions of static library " + lname;
2833 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2834 XmlUtils.skipCurrentTag(parser);
2835 return false;
2836 }
2837
2838 lname = lname.intern();
2839 // We allow ":" delimiters in the SHA declaration as this is the format
2840 // emitted by the certtool making it easy for developers to copy/paste.
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002841 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2842
2843 // Fot apps targeting O-MR1 we require explicit enumeration of all certs.
2844 String[] additionalCertSha256Digests = EmptyArray.STRING;
Jeff Sharkeyaa1a9112018-04-10 15:18:12 -06002845 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O_MR1) {
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002846 additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError);
2847 if (additionalCertSha256Digests == null) {
2848 return false;
2849 }
2850 } else {
2851 XmlUtils.skipCurrentTag(parser);
2852 }
2853
2854 final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1];
2855 certSha256Digests[0] = certSha256Digest;
2856 System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
2857 1, additionalCertSha256Digests.length);
2858
Svet Ganov67882122016-12-11 16:36:34 -08002859 pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname);
Dianne Hackborn3accca02013-09-20 09:32:11 -07002860 pkg.usesStaticLibrariesVersions = ArrayUtils.appendLong(
Svet Ganov8a10ef52017-02-16 20:58:09 -08002861 pkg.usesStaticLibrariesVersions, version, true);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002862 pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
2863 pkg.usesStaticLibrariesCertDigests, certSha256Digests, true);
Svet Ganov67882122016-12-11 16:36:34 -08002864
2865 return true;
2866 }
2867
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002868 private String[] parseAdditionalCertificates(Resources resources, XmlResourceParser parser,
2869 String[] outError) throws XmlPullParserException, IOException {
2870 String[] certSha256Digests = EmptyArray.STRING;
2871
2872 int outerDepth = parser.getDepth();
2873 int type;
2874 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2875 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2876 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2877 continue;
2878 }
2879
2880 final String nodeName = parser.getName();
2881 if (nodeName.equals("additional-certificate")) {
2882 final TypedArray sa = resources.obtainAttributes(parser, com.android.internal.
2883 R.styleable.AndroidManifestAdditionalCertificate);
2884 String certSha256Digest = sa.getNonResourceString(com.android.internal.
2885 R.styleable.AndroidManifestAdditionalCertificate_certDigest);
2886 sa.recycle();
2887
2888 if (TextUtils.isEmpty(certSha256Digest)) {
2889 outError[0] = "Bad additional-certificate declaration with empty"
2890 + " certDigest:" + certSha256Digest;
2891 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2892 XmlUtils.skipCurrentTag(parser);
2893 sa.recycle();
2894 return null;
2895 }
2896
2897 // We allow ":" delimiters in the SHA declaration as this is the format
2898 // emitted by the certtool making it easy for developers to copy/paste.
2899 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2900 certSha256Digests = ArrayUtils.appendElement(String.class,
2901 certSha256Digests, certSha256Digest);
2902 } else {
2903 XmlUtils.skipCurrentTag(parser);
2904 }
2905 }
2906
2907 return certSha256Digests;
2908 }
2909
Chad Brubakere2107312019-02-04 12:30:01 -08002910 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
2911 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002912 TypedArray sa = res.obtainAttributes(parser,
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002913 com.android.internal.R.styleable.AndroidManifestUsesPermission);
2914
2915 // Note: don't allow this value to be a reference to a resource
2916 // that may change.
2917 String name = sa.getNonResourceString(
2918 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002919
Christopher Tatefb0676a2013-09-16 16:34:52 -07002920 int maxSdkVersion = 0;
2921 TypedValue val = sa.peekValue(
2922 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
2923 if (val != null) {
2924 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
2925 maxSdkVersion = val.data;
2926 }
2927 }
2928
Dianne Hackborncd154e92017-02-28 17:37:35 -08002929 final String requiredFeature = sa.getNonConfigurationString(
2930 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
2931
2932 final String requiredNotfeature = sa.getNonConfigurationString(
2933 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
2934
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002935 sa.recycle();
2936
Dianne Hackborncd154e92017-02-28 17:37:35 -08002937 XmlUtils.skipCurrentTag(parser);
2938
2939 if (name == null) {
2940 return true;
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002941 }
2942
Dianne Hackborncd154e92017-02-28 17:37:35 -08002943 if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
2944 return true;
2945 }
2946
2947 // Only allow requesting this permission if the platform supports the given feature.
2948 if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
2949 return true;
2950 }
2951
2952 // Only allow requesting this permission if the platform doesn't support the given feature.
2953 if (requiredNotfeature != null && mCallback != null
2954 && mCallback.hasFeature(requiredNotfeature)) {
2955 return true;
2956 }
2957
2958 int index = pkg.requestedPermissions.indexOf(name);
2959 if (index == -1) {
2960 pkg.requestedPermissions.add(name.intern());
2961 } else {
2962 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
2963 + name + " in package: " + pkg.packageName + " at: "
2964 + parser.getPositionDescription());
2965 }
2966
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002967 return true;
2968 }
2969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002970 private static String buildClassName(String pkg, CharSequence clsSeq,
2971 String[] outError) {
2972 if (clsSeq == null || clsSeq.length() <= 0) {
2973 outError[0] = "Empty class name in package " + pkg;
2974 return null;
2975 }
2976 String cls = clsSeq.toString();
2977 char c = cls.charAt(0);
2978 if (c == '.') {
Narayan Kamath07ac1442017-02-10 15:08:07 +00002979 return pkg + cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980 }
2981 if (cls.indexOf('.') < 0) {
2982 StringBuilder b = new StringBuilder(pkg);
2983 b.append('.');
2984 b.append(cls);
Narayan Kamath07ac1442017-02-10 15:08:07 +00002985 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002986 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002987 return cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002988 }
2989
2990 private static String buildCompoundName(String pkg,
2991 CharSequence procSeq, String type, String[] outError) {
2992 String proc = procSeq.toString();
2993 char c = proc.charAt(0);
2994 if (pkg != null && c == ':') {
2995 if (proc.length() < 2) {
2996 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
2997 + ": must be at least two characters";
2998 return null;
2999 }
3000 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07003001 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003002 if (nameError != null) {
3003 outError[0] = "Invalid " + type + " name " + proc + " in package "
3004 + pkg + ": " + nameError;
3005 return null;
3006 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00003007 return pkg + proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003008 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07003009 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003010 if (nameError != null && !"system".equals(proc)) {
3011 outError[0] = "Invalid " + type + " name " + proc + " in package "
3012 + pkg + ": " + nameError;
3013 return null;
3014 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00003015 return proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003016 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003018 private static String buildProcessName(String pkg, String defProc,
3019 CharSequence procSeq, int flags, String[] separateProcesses,
3020 String[] outError) {
3021 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
3022 return defProc != null ? defProc : pkg;
3023 }
3024 if (separateProcesses != null) {
3025 for (int i=separateProcesses.length-1; i>=0; i--) {
3026 String sp = separateProcesses[i];
3027 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
3028 return pkg;
3029 }
3030 }
3031 }
3032 if (procSeq == null || procSeq.length() <= 0) {
3033 return defProc;
3034 }
Makoto Onuki812d188a2017-08-07 09:58:23 -07003035 return TextUtils.safeIntern(buildCompoundName(pkg, procSeq, "process", outError));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003036 }
3037
3038 private static String buildTaskAffinityName(String pkg, String defProc,
3039 CharSequence procSeq, String[] outError) {
3040 if (procSeq == null) {
3041 return defProc;
3042 }
3043 if (procSeq.length() <= 0) {
3044 return null;
3045 }
3046 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
3047 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003048
dcashman989eb3712014-06-17 12:56:12 -07003049 private boolean parseKeySets(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003050 XmlResourceParser parser, String[] outError)
Geremy Condraf1bcca82013-01-07 22:35:24 -08003051 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07003052 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08003053 // all the keys and keysets that we want must be defined here
3054 // so we're going to iterate over the parser and pull out the things we want
3055 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07003056 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003057 int type;
dcashman989eb3712014-06-17 12:56:12 -07003058 String currentKeySet = null;
3059 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
3060 ArraySet<String> upgradeKeySets = new ArraySet<String>();
3061 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
3062 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08003063 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3064 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
3065 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07003066 if (parser.getDepth() == currentKeySetDepth) {
3067 currentKeySet = null;
3068 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07003069 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003070 continue;
3071 }
dcashman989eb3712014-06-17 12:56:12 -07003072 String tagName = parser.getName();
3073 if (tagName.equals("key-set")) {
3074 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07003075 outError[0] = "Improperly nested 'key-set' tag at "
3076 + parser.getPositionDescription();
3077 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003078 return false;
3079 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08003080 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003081 com.android.internal.R.styleable.AndroidManifestKeySet);
3082 final String keysetName = sa.getNonResourceString(
3083 com.android.internal.R.styleable.AndroidManifestKeySet_name);
3084 definedKeySets.put(keysetName, new ArraySet<String>());
3085 currentKeySet = keysetName;
3086 currentKeySetDepth = parser.getDepth();
3087 sa.recycle();
3088 } else if (tagName.equals("public-key")) {
3089 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07003090 outError[0] = "Improperly nested 'key-set' tag at "
3091 + parser.getPositionDescription();
3092 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003093 return false;
3094 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08003095 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003096 com.android.internal.R.styleable.AndroidManifestPublicKey);
3097 final String publicKeyName = sa.getNonResourceString(
3098 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003099 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07003100 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
3101 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07003102 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
3103 + " on first use at " + parser.getPositionDescription();
3104 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07003105 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003106 return false;
3107 } else if (encodedKey != null) {
3108 PublicKey currentKey = parsePublicKey(encodedKey);
3109 if (currentKey == null) {
3110 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
3111 + parser.getPositionDescription() + " key-set " + currentKeySet
3112 + " will not be added to the package's defined key-sets.");
3113 sa.recycle();
3114 improperKeySets.add(currentKeySet);
3115 XmlUtils.skipCurrentTag(parser);
3116 continue;
3117 }
3118 if (publicKeys.get(publicKeyName) == null
3119 || publicKeys.get(publicKeyName).equals(currentKey)) {
3120
3121 /* public-key first definition, or matches old definition */
3122 publicKeys.put(publicKeyName, currentKey);
3123 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003124 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07003125 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07003126 + parser.getPositionDescription();
3127 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003128 sa.recycle();
3129 return false;
3130 }
Kenny Root37dca152013-07-10 14:01:49 -07003131 }
dcashman989eb3712014-06-17 12:56:12 -07003132 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003133 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003134 XmlUtils.skipCurrentTag(parser);
3135 } else if (tagName.equals("upgrade-key-set")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003136 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003137 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
3138 String name = sa.getNonResourceString(
3139 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
3140 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003141 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003142 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003143 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07003144 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003145 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07003146 + parser.getPositionDescription();
3147 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003148 return false;
3149 } else {
dcashman989eb3712014-06-17 12:56:12 -07003150 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003151 + " at " + mArchiveSourcePath + " "
3152 + parser.getPositionDescription());
3153 XmlUtils.skipCurrentTag(parser);
3154 continue;
3155 }
3156 }
dcashman989eb3712014-06-17 12:56:12 -07003157 Set<String> publicKeyNames = publicKeys.keySet();
3158 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07003159 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
3160 + "'key-set' and 'public-key' names must be distinct.";
3161 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003162 return false;
3163 }
3164 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
3165 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
3166 final String keySetName = e.getKey();
3167 if (e.getValue().size() == 0) {
3168 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3169 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
3170 + " Not including in package's defined key-sets.");
3171 continue;
3172 } else if (improperKeySets.contains(keySetName)) {
3173 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3174 + "'key-set' " + keySetName + " contained improper 'public-key'"
3175 + " tags. Not including in package's defined key-sets.");
3176 continue;
3177 }
3178 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
3179 for (String s : e.getValue()) {
3180 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08003181 }
3182 }
dcashman989eb3712014-06-17 12:56:12 -07003183 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
3184 owner.mUpgradeKeySets = upgradeKeySets;
3185 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003186 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
3187 + "does not define all 'upgrade-key-set's .";
3188 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003189 return false;
3190 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003191 return true;
3192 }
3193
Dianne Hackborncd154e92017-02-28 17:37:35 -08003194 private boolean parsePermissionGroup(Package owner, int flags, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003195 XmlResourceParser parser, String[] outError)
3196 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003197 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003198 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
Philip P. Moltmann0635dab2019-03-02 11:19:03 -08003199
3200 int requestDetailResourceId = sa.getResourceId(
3201 com.android.internal.R.styleable.AndroidManifestPermissionGroup_requestDetail, 0);
3202 int backgroundRequestResourceId = sa.getResourceId(
3203 com.android.internal.R.styleable.AndroidManifestPermissionGroup_backgroundRequest,
3204 0);
3205 int backgroundRequestDetailResourceId = sa.getResourceId(
3206 com.android.internal.R.styleable
3207 .AndroidManifestPermissionGroup_backgroundRequestDetail, 0);
3208
3209 PermissionGroup perm = new PermissionGroup(owner, requestDetailResourceId,
3210 backgroundRequestResourceId, backgroundRequestDetailResourceId);
3211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003212 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003213 "<permission-group>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003214 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
3215 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003216 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003217 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003218 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
3219 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003220 sa.recycle();
3221 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003222 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003223 }
3224
3225 perm.info.descriptionRes = sa.getResourceId(
3226 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
3227 0);
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003228 perm.info.requestRes = sa.getResourceId(
3229 com.android.internal.R.styleable.AndroidManifestPermissionGroup_request, 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07003230 perm.info.flags = sa.getInt(
3231 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07003232 perm.info.priority = sa.getInt(
3233 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003234
3235 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003236
Svet Ganov354cd3c2015-12-17 11:35:04 -08003237 if (!parseAllMetaData(res, parser, "<permission-group>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003238 outError)) {
3239 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003240 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003241 }
3242
3243 owner.permissionGroups.add(perm);
3244
Dianne Hackborncd154e92017-02-28 17:37:35 -08003245 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003246 }
3247
Dianne Hackborncd154e92017-02-28 17:37:35 -08003248 private boolean parsePermission(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003249 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003250 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251
Svet Ganov354cd3c2015-12-17 11:35:04 -08003252 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253 com.android.internal.R.styleable.AndroidManifestPermission);
3254
Philip P. Moltmanna4844d12019-03-02 10:17:23 -08003255 String backgroundPermission = null;
3256 if (sa.hasValue(
3257 com.android.internal.R.styleable.AndroidManifestPermission_backgroundPermission)) {
3258 if ("android".equals(owner.packageName)) {
3259 backgroundPermission = sa.getNonResourceString(
3260 com.android.internal.R.styleable
3261 .AndroidManifestPermission_backgroundPermission);
3262 } else {
3263 Slog.w(TAG, owner.packageName + " defines a background permission. Only the "
3264 + "'android' package can do that.");
3265 }
3266 }
3267
3268 Permission perm = new Permission(owner, backgroundPermission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003269 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003270 "<permission>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003271 com.android.internal.R.styleable.AndroidManifestPermission_name,
3272 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003273 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003274 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003275 com.android.internal.R.styleable.AndroidManifestPermission_logo,
3276 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003277 sa.recycle();
3278 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003279 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003280 }
3281
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003282 // Note: don't allow this value to be a reference to a resource
3283 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003284 perm.info.group = sa.getNonResourceString(
3285 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
3286 if (perm.info.group != null) {
3287 perm.info.group = perm.info.group.intern();
3288 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003290 perm.info.descriptionRes = sa.getResourceId(
3291 com.android.internal.R.styleable.AndroidManifestPermission_description,
3292 0);
3293
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003294 perm.info.requestRes = sa.getResourceId(
3295 com.android.internal.R.styleable.AndroidManifestPermission_request, 0);
3296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003297 perm.info.protectionLevel = sa.getInt(
3298 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
3299 PermissionInfo.PROTECTION_NORMAL);
3300
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07003301 perm.info.flags = sa.getInt(
3302 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
3303
Svet Ganovd8eb8b22019-04-05 18:52:08 -07003304 // For now only platform runtime permissions can be restricted
3305 if (!perm.info.isRuntime() || !"android".equals(perm.info.packageName)) {
3306 perm.info.flags &= ~PermissionInfo.FLAG_HARD_RESTRICTED;
3307 perm.info.flags &= ~PermissionInfo.FLAG_SOFT_RESTRICTED;
3308 } else {
3309 // The platform does not get to specify conflicting permissions
3310 if ((perm.info.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0
3311 && (perm.info.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0) {
3312 throw new IllegalStateException("Permission cannot be both soft and hard"
3313 + " restricted: " + perm.info.name);
3314 }
3315 }
3316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08003318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 if (perm.info.protectionLevel == -1) {
3320 outError[0] = "<permission> does not specify protectionLevel";
3321 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003322 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003323 }
Dianne Hackborne639da72012-02-21 15:11:13 -08003324
3325 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
3326
Makoto Onuki700feef2018-02-15 10:59:41 -08003327 if (perm.info.getProtectionFlags() != 0) {
Todd Kennedyc247fa12017-06-02 10:29:22 -07003328 if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_INSTANT) == 0
Chad Brubakera5d70a12017-03-23 11:04:50 -07003329 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0
Chad Brubakerc19706a2016-10-13 15:44:59 -07003330 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
Dianne Hackborne639da72012-02-21 15:11:13 -08003331 PermissionInfo.PROTECTION_SIGNATURE) {
Joe Maples39bb9e82018-01-11 11:09:46 -05003332 outError[0] = "<permission> protectionLevel specifies a non-instant flag but is "
Dianne Hackborne639da72012-02-21 15:11:13 -08003333 + "not based on signature type";
3334 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003335 return false;
Dianne Hackborne639da72012-02-21 15:11:13 -08003336 }
3337 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003338
Svet Ganov354cd3c2015-12-17 11:35:04 -08003339 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003341 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 }
3343
3344 owner.permissions.add(perm);
3345
Dianne Hackborncd154e92017-02-28 17:37:35 -08003346 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 }
3348
Dianne Hackborncd154e92017-02-28 17:37:35 -08003349 private boolean parsePermissionTree(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003350 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003351 throws XmlPullParserException, IOException {
Philip P. Moltmanna4844d12019-03-02 10:17:23 -08003352 Permission perm = new Permission(owner, (String) null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353
Svet Ganov354cd3c2015-12-17 11:35:04 -08003354 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003355 com.android.internal.R.styleable.AndroidManifestPermissionTree);
3356
3357 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003358 "<permission-tree>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
3360 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003361 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003362 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003363 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
3364 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 sa.recycle();
3366 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003367 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 }
3369
3370 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003372 int index = perm.info.name.indexOf('.');
3373 if (index > 0) {
3374 index = perm.info.name.indexOf('.', index+1);
3375 }
3376 if (index < 0) {
3377 outError[0] = "<permission-tree> name has less than three segments: "
3378 + perm.info.name;
3379 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003380 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003381 }
3382
3383 perm.info.descriptionRes = 0;
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003384 perm.info.requestRes = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003385 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
3386 perm.tree = true;
3387
Svet Ganov354cd3c2015-12-17 11:35:04 -08003388 if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389 outError)) {
3390 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003391 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003392 }
3393
3394 owner.permissions.add(perm);
3395
Dianne Hackborncd154e92017-02-28 17:37:35 -08003396 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003397 }
3398
3399 private Instrumentation parseInstrumentation(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003400 XmlResourceParser parser, String[] outError)
3401 throws XmlPullParserException, IOException {
3402 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003403 com.android.internal.R.styleable.AndroidManifestInstrumentation);
3404
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003405 if (mParseInstrumentationArgs == null) {
3406 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
3407 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
3408 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003409 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003410 com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003411 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
3412 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003413 mParseInstrumentationArgs.tag = "<instrumentation>";
3414 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003415
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003416 mParseInstrumentationArgs.sa = sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003417
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003418 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
3419 new InstrumentationInfo());
3420 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003421 sa.recycle();
3422 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3423 return null;
3424 }
3425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003427 // Note: don't allow this value to be a reference to a resource
3428 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003429 str = sa.getNonResourceString(
3430 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
3431 a.info.targetPackage = str != null ? str.intern() : null;
3432
Dianne Hackborn34041732017-01-31 15:27:13 -08003433 str = sa.getNonResourceString(
Dianne Hackborn1be53542017-04-28 13:36:00 -07003434 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcesses);
3435 a.info.targetProcesses = str != null ? str.intern() : null;
Dianne Hackborn34041732017-01-31 15:27:13 -08003436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437 a.info.handleProfiling = sa.getBoolean(
3438 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
3439 false);
3440
3441 a.info.functionalTest = sa.getBoolean(
3442 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
3443 false);
3444
3445 sa.recycle();
3446
3447 if (a.info.targetPackage == null) {
3448 outError[0] = "<instrumentation> does not specify targetPackage";
3449 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3450 return null;
3451 }
3452
Svet Ganov354cd3c2015-12-17 11:35:04 -08003453 if (!parseAllMetaData(res, parser, "<instrumentation>", a,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003454 outError)) {
3455 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3456 return null;
3457 }
3458
3459 owner.instrumentation.add(a);
3460
3461 return a;
3462 }
3463
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003464 /**
3465 * Parse the {@code application} XML tree at the current parse location in a
3466 * <em>base APK</em> manifest.
3467 * <p>
3468 * When adding new features, carefully consider if they should also be
3469 * supported by split APKs.
3470 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01003471 @UnsupportedAppUsage
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003472 private boolean parseBaseApplication(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003473 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003474 throws XmlPullParserException, IOException {
3475 final ApplicationInfo ai = owner.applicationInfo;
3476 final String pkgName = owner.applicationInfo.packageName;
3477
Svet Ganov354cd3c2015-12-17 11:35:04 -08003478 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 com.android.internal.R.styleable.AndroidManifestApplication);
3480
Hyunyoung Song929de7a2019-03-21 23:51:27 -07003481 ai.iconRes = sa.getResourceId(
3482 com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
3483 ai.roundIconRes = sa.getResourceId(
3484 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon, 0);
3485
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003486 if (!parsePackageItemInfo(owner, ai, outError,
3487 "<application>", sa, false /*nameRequired*/,
3488 com.android.internal.R.styleable.AndroidManifestApplication_name,
3489 com.android.internal.R.styleable.AndroidManifestApplication_label,
3490 com.android.internal.R.styleable.AndroidManifestApplication_icon,
3491 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
3492 com.android.internal.R.styleable.AndroidManifestApplication_logo,
3493 com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
3494 sa.recycle();
3495 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3496 return false;
3497 }
3498
3499 if (ai.name != null) {
Todd Kennedyafb52692016-08-22 15:44:00 -07003500 ai.className = ai.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003501 }
3502
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003503 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003504 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
3505 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003506 if (manageSpaceActivity != null) {
3507 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
3508 outError);
3509 }
3510
Christopher Tate181fafa2009-05-14 11:12:14 -07003511 boolean allowBackup = sa.getBoolean(
3512 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
3513 if (allowBackup) {
3514 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07003515
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003516 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
3517 // and restoreAnyVersion are only relevant if backup is possible for the
3518 // given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003519 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003520 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
3521 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07003522 if (backupAgent != null) {
3523 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07003524 if (DEBUG_BACKUP) {
3525 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003526 + " from " + pkgName + "+" + backupAgent);
3527 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003528
3529 if (sa.getBoolean(
3530 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
3531 true)) {
3532 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
3533 }
3534 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08003535 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
3536 false)) {
3537 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
3538 }
Christopher Tated1de2562014-06-17 17:12:35 -07003539 if (sa.getBoolean(
3540 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
3541 false)) {
3542 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
3543 }
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003544 if (sa.getBoolean(
3545 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
3546 false)) {
3547 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
3548 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003549 }
Matthew Williams303650c2015-04-17 18:22:51 -07003550
3551 TypedValue v = sa.peekValue(
3552 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
3553 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
3554 if (DEBUG_BACKUP) {
3555 Slog.v(TAG, "fullBackupContent specified as boolean=" +
3556 (v.data == 0 ? "false" : "true"));
3557 }
3558 // "false" => -1, "true" => 0
3559 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
3560 }
3561 if (DEBUG_BACKUP) {
3562 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
3563 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003564 }
Christopher Tate4a627c72011-04-01 14:43:32 -07003565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003566 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08003567 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003568 ai.descriptionRes = sa.getResourceId(
3569 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
3570
Todd Kennedy232d29e2017-11-06 14:45:53 -08003571 if (sa.getBoolean(
3572 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
3573 false)) {
3574 // Check if persistence is based on a feature being present
3575 final String requiredFeature = sa.getNonResourceString(com.android.internal.R.styleable
3576 .AndroidManifestApplication_persistentWhenFeatureAvailable);
3577 if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
3578 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003579 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07003580 }
3581
3582 if (sa.getBoolean(
3583 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
3584 false)) {
3585 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07003586 }
3587
3588 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
3589 .AndroidManifestApplication_restrictedAccountType);
3590 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
3591 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003592 }
3593
Amith Yamasaniccbe3892013-04-12 17:52:42 -07003594 String requiredAccountType = sa.getString(com.android.internal.R.styleable
3595 .AndroidManifestApplication_requiredAccountType);
3596 if (requiredAccountType != null && requiredAccountType.length() > 0) {
3597 owner.mRequiredAccountType = requiredAccountType;
3598 }
3599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003600 if (sa.getBoolean(
3601 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
3602 false)) {
3603 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
Chris Craikce030282018-10-16 14:33:11 -07003604 // Debuggable implies profileable
3605 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003606 }
3607
3608 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07003609 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08003610 false)) {
3611 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
3612 }
3613
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003614 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07003615 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07003616 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07003617 if (owner.baseHardwareAccelerated) {
3618 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
3619 }
Romain Guy812ccbe2010-06-01 14:07:24 -07003620
3621 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003622 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
3623 true)) {
3624 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
3625 }
3626
3627 if (sa.getBoolean(
3628 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
3629 false)) {
3630 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
3631 }
3632
3633 if (sa.getBoolean(
3634 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
3635 true)) {
3636 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
3637 }
3638
Svet Ganov354cd3c2015-12-17 11:35:04 -08003639 // The parent package controls installation, hence specify test only installs.
3640 if (owner.parentPackage == null) {
3641 if (sa.getBoolean(
3642 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
3643 false)) {
3644 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
3645 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003646 }
3647
Jason parksa3cdaa52011-01-13 14:15:43 -06003648 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003649 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06003650 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003651 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06003652 }
3653
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003654 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07003655 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
Chad Brubaker0d285d52018-03-14 09:00:04 -07003656 owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.P)) {
Alex Klyubin01a959d2015-03-18 10:05:45 -07003657 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
3658 }
3659
3660 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003661 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
3662 false /* default is no RTL support*/)) {
3663 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
3664 }
3665
Narayan Kamath589a1bc2014-07-03 14:43:26 +01003666 if (sa.getBoolean(
3667 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
3668 false)) {
3669 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
3670 }
3671
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07003672 if (sa.getBoolean(
3673 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
Victor Hsieh0faa8012019-03-11 10:00:54 -07003674 true)) {
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07003675 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
3676 }
3677
Todd Kennedyd022ac22016-04-13 10:49:29 -07003678 if (sa.getBoolean(
Victor Hsiehfa9df0b2019-01-29 12:48:36 -08003679 R.styleable.AndroidManifestApplication_useEmbeddedDex,
Victor Hsiehe7b5a8d2018-11-16 10:27:06 -08003680 false)) {
Victor Hsiehfa9df0b2019-01-29 12:48:36 -08003681 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX;
Victor Hsiehe7b5a8d2018-11-16 10:27:06 -08003682 }
3683
3684 if (sa.getBoolean(
Todd Kennedyd022ac22016-04-13 10:49:29 -07003685 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
3686 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003687 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003688 }
Todd Kennedyd022ac22016-04-13 10:49:29 -07003689 if (sa.getBoolean(
3690 R.styleable.AndroidManifestApplication_directBootAware,
3691 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003692 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003693 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003694
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003695 if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
3696 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003697 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
3698 } else {
3699 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003700 }
3701 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003702 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwale6afdf912016-01-30 13:01:33 -08003703 }
3704
Ruslan Tkhakokhov75674852019-01-22 13:35:00 +00003705 if (sa.getBoolean(
3706 com.android.internal.R.styleable
3707 .AndroidManifestApplication_allowClearUserDataOnFailedRestore,
3708 true)) {
3709 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE;
3710 }
3711
Kevin Rocardf91d50b2019-02-21 14:32:46 -08003712 if (sa.getBoolean(
3713 R.styleable.AndroidManifestApplication_allowAudioPlaybackCapture,
3714 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q)) {
3715 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE;
3716 }
3717
Jeff Sharkeybcff13c2019-03-28 14:29:35 -06003718 if (sa.getBoolean(
Svet Ganovd563e932019-04-14 13:07:41 -07003719 R.styleable.AndroidManifestApplication_requestLegacyExternalStorage,
3720 owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.Q)) {
3721 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE;
Jeff Sharkeybcff13c2019-03-28 14:29:35 -06003722 }
3723
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07003724 ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
Adrian Roos917791e2018-11-28 16:30:44 +01003725 ai.minAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_minAspectRatio, 0);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07003726
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003727 ai.networkSecurityConfigRes = sa.getResourceId(
3728 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
3729 0);
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07003730 ai.category = sa.getInt(
3731 com.android.internal.R.styleable.AndroidManifestApplication_appCategory,
3732 ApplicationInfo.CATEGORY_UNDEFINED);
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003734 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003735 str = sa.getNonConfigurationString(
3736 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003737 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
3738
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003739 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3740 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003741 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
3742 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003743 } else {
3744 // Some older apps have been seen to use a resource reference
3745 // here that on older builds was ignored (with a warning). We
3746 // need to continue to do this for them so they don't break.
3747 str = sa.getNonResourceString(
3748 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
3749 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003750 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
3751 str, outError);
Jason Monka80bfb52017-11-16 17:15:37 -05003752 String factory = sa.getNonResourceString(
3753 com.android.internal.R.styleable.AndroidManifestApplication_appComponentFactory);
3754 if (factory != null) {
3755 ai.appComponentFactory = buildClassName(ai.packageName, factory, outError);
3756 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003757
David Brazdila5b4df22018-09-06 09:49:14 +01003758 if (sa.getBoolean(
3759 com.android.internal.R.styleable.AndroidManifestApplication_usesNonSdkApi, false)) {
3760 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API;
3761 }
David Brazdil787b6f22a2018-08-28 12:55:56 +01003762
Philip P. Moltmannae4a4b92018-12-12 11:28:57 -08003763 if (sa.getBoolean(
3764 com.android.internal.R.styleable.AndroidManifestApplication_hasFragileUserData,
3765 false)) {
3766 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA;
3767 }
3768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003769 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003770 CharSequence pname;
3771 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3772 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003773 com.android.internal.R.styleable.AndroidManifestApplication_process,
3774 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003775 } else {
3776 // Some older apps have been seen to use a resource reference
3777 // here that on older builds was ignored (with a warning). We
3778 // need to continue to do this for them so they don't break.
3779 pname = sa.getNonResourceString(
3780 com.android.internal.R.styleable.AndroidManifestApplication_process);
3781 }
3782 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 flags, mSeparateProcesses, outError);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003784
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003785 ai.enabled = sa.getBoolean(
3786 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003787
Jose Lima12d0b4c2014-03-14 16:55:12 -07003788 if (sa.getBoolean(
3789 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
3790 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
3791 }
3792
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003793 if (sa.getBoolean(
3794 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
3795 false)) {
3796 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07003797
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003798 // A heavy-weight application can not be in a custom process.
3799 // We can do direct compare because we intern all strings.
3800 if (ai.processName != null && !ai.processName.equals(ai.packageName)) {
3801 outError[0] = "cantSaveState applications can not use custom processes";
Dianne Hackborn860755f2010-06-03 18:47:52 -07003802 }
3803 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 }
3805
Adam Powell269248d2011-08-02 10:26:54 -07003806 ai.uiOptions = sa.getInt(
3807 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
3808
Narayan Kamath96c11c52017-08-09 13:07:21 +01003809 ai.classLoaderName = sa.getString(
3810 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3811 if (ai.classLoaderName != null
3812 && !ClassLoaderFactory.isValidClassLoaderName(ai.classLoaderName)) {
3813 outError[0] = "Invalid class loader name: " + ai.classLoaderName;
3814 }
3815
Martijn Coenenfb7caa92019-01-29 11:45:56 +01003816 ai.zygotePreloadName = sa.getString(
3817 com.android.internal.R.styleable.AndroidManifestApplication_zygotePreloadName);
3818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 sa.recycle();
3820
3821 if (outError[0] != null) {
3822 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3823 return false;
3824 }
3825
3826 final int innerDepth = parser.getDepth();
Garrett Boyer52136662017-05-23 13:47:58 -07003827 // IMPORTANT: These must only be cached for a single <application> to avoid components
3828 // getting added to the wrong package.
3829 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 int type;
Todd Kennedy6d418b62018-02-22 14:15:18 -08003831 boolean hasActivityOrder = false;
3832 boolean hasReceiverOrder = false;
3833 boolean hasServiceOrder = false;
Kenny Rootd2d29252011-08-08 11:27:57 -07003834 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3835 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3836 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003837 continue;
3838 }
3839
3840 String tagName = parser.getName();
3841 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003842 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003843 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003844 if (a == null) {
3845 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3846 return false;
3847 }
3848
Todd Kennedy6d418b62018-02-22 14:15:18 -08003849 hasActivityOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003850 owner.activities.add(a);
3851
3852 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003853 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3854 true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003855 if (a == null) {
3856 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3857 return false;
3858 }
3859
Todd Kennedy6d418b62018-02-22 14:15:18 -08003860 hasReceiverOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003861 owner.receivers.add(a);
3862
3863 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003864 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003865 if (s == null) {
3866 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3867 return false;
3868 }
3869
Todd Kennedy6d418b62018-02-22 14:15:18 -08003870 hasServiceOrder |= (s.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003871 owner.services.add(s);
3872
3873 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003874 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003875 if (p == null) {
3876 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3877 return false;
3878 }
3879
3880 owner.providers.add(p);
3881
3882 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003883 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003884 if (a == null) {
3885 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3886 return false;
3887 }
3888
Todd Kennedy6d418b62018-02-22 14:15:18 -08003889 hasActivityOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 owner.activities.add(a);
3891
3892 } else if (parser.getName().equals("meta-data")) {
3893 // note: application meta-data is stored off to the side, so it can
3894 // remain null in the primary copy (we like to avoid extra copies because
3895 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003896 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003897 outError)) == null) {
3898 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3899 return false;
3900 }
Svet Ganov67882122016-12-11 16:36:34 -08003901 } else if (tagName.equals("static-library")) {
3902 sa = res.obtainAttributes(parser,
3903 com.android.internal.R.styleable.AndroidManifestStaticLibrary);
3904
3905 // Note: don't allow this value to be a reference to a resource
3906 // that may change.
3907 final String lname = sa.getNonResourceString(
3908 com.android.internal.R.styleable.AndroidManifestStaticLibrary_name);
3909 final int version = sa.getInt(
3910 com.android.internal.R.styleable.AndroidManifestStaticLibrary_version, -1);
Dianne Hackborn3accca02013-09-20 09:32:11 -07003911 final int versionMajor = sa.getInt(
3912 com.android.internal.R.styleable.AndroidManifestStaticLibrary_versionMajor,
3913 0);
Svet Ganov67882122016-12-11 16:36:34 -08003914
3915 sa.recycle();
3916
3917 // Since the app canot run without a static lib - fail if malformed
3918 if (lname == null || version < 0) {
3919 outError[0] = "Bad static-library declaration name: " + lname
3920 + " version: " + version;
3921 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3922 XmlUtils.skipCurrentTag(parser);
3923 return false;
3924 }
3925
3926 if (owner.mSharedUserId != null) {
3927 outError[0] = "sharedUserId not allowed in static shared library";
3928 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
3929 XmlUtils.skipCurrentTag(parser);
3930 return false;
3931 }
3932
3933 if (owner.staticSharedLibName != null) {
3934 outError[0] = "Multiple static-shared libs for package " + pkgName;
3935 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3936 XmlUtils.skipCurrentTag(parser);
3937 return false;
3938 }
3939
3940 owner.staticSharedLibName = lname.intern();
Dianne Hackborn3accca02013-09-20 09:32:11 -07003941 if (version >= 0) {
3942 owner.staticSharedLibVersion =
3943 PackageInfo.composeLongVersionCode(versionMajor, version);
3944 } else {
3945 owner.staticSharedLibVersion = version;
3946 }
Svet Ganov67882122016-12-11 16:36:34 -08003947 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
3948
3949 XmlUtils.skipCurrentTag(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003950
Dianne Hackbornc895be72013-03-11 17:48:43 -07003951 } else if (tagName.equals("library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003952 sa = res.obtainAttributes(parser,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003953 com.android.internal.R.styleable.AndroidManifestLibrary);
3954
3955 // Note: don't allow this value to be a reference to a resource
3956 // that may change.
3957 String lname = sa.getNonResourceString(
3958 com.android.internal.R.styleable.AndroidManifestLibrary_name);
3959
3960 sa.recycle();
3961
3962 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003963 lname = lname.intern();
3964 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
Svet Ganov67882122016-12-11 16:36:34 -08003965 owner.libraryNames = ArrayUtils.add(
3966 owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07003967 }
3968 }
3969
3970 XmlUtils.skipCurrentTag(parser);
3971
Svet Ganov67882122016-12-11 16:36:34 -08003972 } else if (tagName.equals("uses-static-library")) {
3973 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3974 return false;
3975 }
3976
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003977 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003978 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003979 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3980
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003981 // Note: don't allow this value to be a reference to a resource
3982 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 String lname = sa.getNonResourceString(
3984 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07003985 boolean req = sa.getBoolean(
3986 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3987 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988
3989 sa.recycle();
3990
Dianne Hackborn49237342009-08-27 20:08:01 -07003991 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003992 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07003993 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003994 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003995 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003996 owner.usesOptionalLibraries = ArrayUtils.add(
3997 owner.usesOptionalLibraries, lname);
3998 }
3999 }
4000
4001 XmlUtils.skipCurrentTag(parser);
4002
4003 } else if (tagName.equals("uses-package")) {
4004 // Dependencies for app installers; we don't currently try to
4005 // enforce this.
4006 XmlUtils.skipCurrentTag(parser);
Chris Craikce030282018-10-16 14:33:11 -07004007 } else if (tagName.equals("profileable")) {
4008 sa = res.obtainAttributes(parser,
4009 com.android.internal.R.styleable.AndroidManifestProfileable);
4010 if (sa.getBoolean(
4011 com.android.internal.R.styleable.AndroidManifestProfileable_shell, false)) {
4012 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL;
4013 }
4014 XmlUtils.skipCurrentTag(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004015
4016 } else {
4017 if (!RIGID_PARSER) {
4018 Slog.w(TAG, "Unknown element under <application>: " + tagName
4019 + " at " + mArchiveSourcePath + " "
4020 + parser.getPositionDescription());
4021 XmlUtils.skipCurrentTag(parser);
4022 continue;
4023 } else {
4024 outError[0] = "Bad element under <application>: " + tagName;
4025 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4026 return false;
4027 }
4028 }
4029 }
4030
Patrick Baumann1f9b8852018-10-30 12:34:46 -07004031 if (TextUtils.isEmpty(owner.staticSharedLibName)) {
4032 // Add a hidden app detail activity to normal apps which forwards user to App Details
4033 // page.
4034 Activity a = generateAppDetailsHiddenActivity(owner, flags, outError,
4035 owner.baseHardwareAccelerated);
4036 owner.activities.add(a);
4037 }
Ricky Waicf134eb2018-10-10 09:26:32 +01004038
Todd Kennedy6d418b62018-02-22 14:15:18 -08004039 if (hasActivityOrder) {
4040 Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order));
4041 }
4042 if (hasReceiverOrder) {
4043 Collections.sort(owner.receivers, (r1, r2) -> Integer.compare(r2.order, r1.order));
4044 }
4045 if (hasServiceOrder) {
4046 Collections.sort(owner.services, (s1, s2) -> Integer.compare(s2.order, s1.order));
4047 }
Bryce Lee22571db2017-07-07 15:54:18 -07004048 // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
4049 // every activity info has had a chance to set it from its attributes.
4050 setMaxAspectRatio(owner);
Adrian Roos917791e2018-11-28 16:30:44 +01004051 setMinAspectRatio(owner);
Bryce Lee22571db2017-07-07 15:54:18 -07004052
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07004053 if (hasDomainURLs(owner)) {
4054 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
4055 } else {
4056 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
4057 }
4058
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004059 return true;
4060 }
4061
4062 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07004063 * 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 -07004064 */
4065 private static boolean hasDomainURLs(Package pkg) {
4066 if (pkg == null || pkg.activities == null) return false;
4067 final ArrayList<Activity> activities = pkg.activities;
4068 final int countActivities = activities.size();
4069 for (int n=0; n<countActivities; n++) {
4070 Activity activity = activities.get(n);
4071 ArrayList<ActivityIntentInfo> filters = activity.intents;
4072 if (filters == null) continue;
4073 final int countFilters = filters.size();
4074 for (int m=0; m<countFilters; m++) {
4075 ActivityIntentInfo aii = filters.get(m);
4076 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07004077 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07004078 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
4079 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
4080 return true;
4081 }
4082 }
4083 }
4084 return false;
4085 }
4086
4087 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004088 * Parse the {@code application} XML tree at the current parse location in a
4089 * <em>split APK</em> manifest.
4090 * <p>
4091 * Note that split APKs have many more restrictions on what they're capable
4092 * of doing, so many valid features of a base APK have been carefully
4093 * omitted here.
4094 */
Svet Ganov354cd3c2015-12-17 11:35:04 -08004095 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
4096 int flags, int splitIndex, String[] outError)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004097 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004098 TypedArray sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004099 com.android.internal.R.styleable.AndroidManifestApplication);
4100
4101 if (sa.getBoolean(
4102 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
4103 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
4104 }
4105
Narayan Kamath96c11c52017-08-09 13:07:21 +01004106 final String classLoaderName = sa.getString(
4107 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
4108 if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
4109 owner.applicationInfo.splitClassLoaderNames[splitIndex] = classLoaderName;
4110 } else {
4111 outError[0] = "Invalid class loader name: " + classLoaderName;
4112 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4113 return false;
4114 }
4115
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004116 final int innerDepth = parser.getDepth();
4117 int type;
4118 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
4119 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
4120 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4121 continue;
4122 }
4123
Adam Lesinski4e862812016-11-21 16:02:24 -08004124 ComponentInfo parsedComponent = null;
4125
Garrett Boyer52136662017-05-23 13:47:58 -07004126 // IMPORTANT: These must only be cached for a single <application> to avoid components
4127 // getting added to the wrong package.
4128 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004129 String tagName = parser.getName();
4130 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004131 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004132 owner.baseHardwareAccelerated);
4133 if (a == null) {
4134 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4135 return false;
4136 }
4137
4138 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08004139 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004140
4141 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004142 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
4143 true, false);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004144 if (a == null) {
4145 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4146 return false;
4147 }
4148
4149 owner.receivers.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08004150 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004151
4152 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004153 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004154 if (s == null) {
4155 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4156 return false;
4157 }
4158
4159 owner.services.add(s);
Adam Lesinski4e862812016-11-21 16:02:24 -08004160 parsedComponent = s.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004161
4162 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004163 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004164 if (p == null) {
4165 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4166 return false;
4167 }
4168
4169 owner.providers.add(p);
Adam Lesinski4e862812016-11-21 16:02:24 -08004170 parsedComponent = p.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004171
4172 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004173 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004174 if (a == null) {
4175 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4176 return false;
4177 }
4178
4179 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08004180 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004181
4182 } else if (parser.getName().equals("meta-data")) {
4183 // note: application meta-data is stored off to the side, so it can
4184 // remain null in the primary copy (we like to avoid extra copies because
4185 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08004186 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004187 outError)) == null) {
4188 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4189 return false;
4190 }
4191
Svet Ganov67882122016-12-11 16:36:34 -08004192 } else if (tagName.equals("uses-static-library")) {
4193 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
4194 return false;
4195 }
4196
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004197 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004198 sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004199 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
4200
4201 // Note: don't allow this value to be a reference to a resource
4202 // that may change.
4203 String lname = sa.getNonResourceString(
4204 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
4205 boolean req = sa.getBoolean(
4206 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
4207 true);
4208
4209 sa.recycle();
4210
4211 if (lname != null) {
4212 lname = lname.intern();
4213 if (req) {
4214 // Upgrade to treat as stronger constraint
4215 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
4216 owner.usesOptionalLibraries = ArrayUtils.remove(
4217 owner.usesOptionalLibraries, lname);
4218 } else {
4219 // Ignore if someone already defined as required
4220 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
4221 owner.usesOptionalLibraries = ArrayUtils.add(
4222 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07004223 }
4224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 }
4226
4227 XmlUtils.skipCurrentTag(parser);
4228
Dianne Hackborncef65ee2010-09-30 18:27:22 -07004229 } else if (tagName.equals("uses-package")) {
4230 // Dependencies for app installers; we don't currently try to
4231 // enforce this.
4232 XmlUtils.skipCurrentTag(parser);
4233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004234 } else {
4235 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004236 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004237 + " at " + mArchiveSourcePath + " "
4238 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004239 XmlUtils.skipCurrentTag(parser);
4240 continue;
4241 } else {
4242 outError[0] = "Bad element under <application>: " + tagName;
4243 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4244 return false;
4245 }
4246 }
Adam Lesinski4e862812016-11-21 16:02:24 -08004247
4248 if (parsedComponent != null && parsedComponent.splitName == null) {
4249 // If the loaded component did not specify a split, inherit the split name
4250 // based on the split it is defined in.
4251 // This is used to later load the correct split when starting this
4252 // component.
4253 parsedComponent.splitName = owner.splitNames[splitIndex];
4254 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004255 }
4256
4257 return true;
4258 }
4259
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004260 private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
4261 String[] outError, String tag, TypedArray sa, boolean nameRequired,
4262 int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00004263 // This case can only happen in unit tests where we sometimes need to create fakes
4264 // of various package parser data structures.
4265 if (sa == null) {
4266 outError[0] = tag + " does not contain any attributes";
4267 return false;
4268 }
4269
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004270 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004271 if (name == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004272 if (nameRequired) {
4273 outError[0] = tag + " does not specify android:name";
4274 return false;
4275 }
4276 } else {
Ricky Waicf134eb2018-10-10 09:26:32 +01004277 String outInfoName
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004278 = buildClassName(owner.applicationInfo.packageName, name, outError);
Ricky Wai92cd0062019-02-14 20:23:22 +00004279 if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(outInfoName)) {
Ricky Waicf134eb2018-10-10 09:26:32 +01004280 outError[0] = tag + " invalid android:name";
4281 return false;
4282 }
4283 outInfo.name = outInfoName;
4284 if (outInfoName == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004285 return false;
4286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004287 }
4288
Hyunyoung Song929de7a2019-03-21 23:51:27 -07004289 int roundIconVal = sUseRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004290 if (roundIconVal != 0) {
4291 outInfo.icon = roundIconVal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004292 outInfo.nonLocalizedLabel = null;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004293 } else {
4294 int iconVal = sa.getResourceId(iconRes, 0);
4295 if (iconVal != 0) {
4296 outInfo.icon = iconVal;
4297 outInfo.nonLocalizedLabel = null;
4298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004299 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004300
Adam Powell81cd2e92010-04-21 16:35:18 -07004301 int logoVal = sa.getResourceId(logoRes, 0);
4302 if (logoVal != 0) {
4303 outInfo.logo = logoVal;
4304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004305
Jose Limaf78e3122014-03-06 12:13:15 -08004306 int bannerVal = sa.getResourceId(bannerRes, 0);
4307 if (bannerVal != 0) {
4308 outInfo.banner = bannerVal;
4309 }
4310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311 TypedValue v = sa.peekValue(labelRes);
4312 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4313 outInfo.nonLocalizedLabel = v.coerceToString();
4314 }
4315
4316 outInfo.packageName = owner.packageName;
4317
4318 return true;
4319 }
4320
Ricky Waicf134eb2018-10-10 09:26:32 +01004321 /**
4322 * Generate activity object that forwards user to App Details page automatically.
4323 * This activity should be invisible to user and user should not know or see it.
4324 */
4325 private @NonNull PackageParser.Activity generateAppDetailsHiddenActivity(
4326 PackageParser.Package owner, int flags, String[] outError,
4327 boolean hardwareAccelerated) {
4328
4329 // Build custom App Details activity info instead of parsing it from xml
Ricky Wai92cd0062019-02-14 20:23:22 +00004330 Activity a = new Activity(owner, PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME,
4331 new ActivityInfo());
Ricky Waicf134eb2018-10-10 09:26:32 +01004332 a.owner = owner;
4333 a.setPackageName(owner.packageName);
4334
Ricky Wai622925072019-01-29 16:40:59 +00004335 a.info.theme = android.R.style.Theme_NoDisplay;
Ricky Waicf134eb2018-10-10 09:26:32 +01004336 a.info.exported = true;
Ricky Wai92cd0062019-02-14 20:23:22 +00004337 a.info.name = PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME;
Ricky Waicf134eb2018-10-10 09:26:32 +01004338 a.info.processName = owner.applicationInfo.processName;
4339 a.info.uiOptions = a.info.applicationInfo.uiOptions;
4340 a.info.taskAffinity = buildTaskAffinityName(owner.packageName, owner.packageName,
4341 ":app_details", outError);
4342 a.info.enabled = true;
4343 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4344 a.info.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NONE;
4345 a.info.maxRecents = ActivityTaskManager.getDefaultAppRecentsLimitStatic();
4346 a.info.configChanges = getActivityConfigChanges(0, 0);
4347 a.info.softInputMode = 0;
4348 a.info.persistableMode = ActivityInfo.PERSIST_NEVER;
4349 a.info.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
4350 a.info.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4351 a.info.lockTaskLaunchMode = 0;
4352 a.info.encryptionAware = a.info.directBootAware = false;
4353 a.info.rotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
4354 a.info.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
4355 if (hardwareAccelerated) {
4356 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
4357 }
4358 return a;
4359 }
4360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004361 private Activity parseActivity(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004362 XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
Romain Guy529b60a2010-08-03 18:05:47 -07004363 boolean receiver, boolean hardwareAccelerated)
4364 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004365 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004366
Garrett Boyer52136662017-05-23 13:47:58 -07004367 if (cachedArgs.mActivityArgs == null) {
4368 cachedArgs.mActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004369 R.styleable.AndroidManifestActivity_name,
4370 R.styleable.AndroidManifestActivity_label,
4371 R.styleable.AndroidManifestActivity_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004372 R.styleable.AndroidManifestActivity_roundIcon,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004373 R.styleable.AndroidManifestActivity_logo,
4374 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004375 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004376 R.styleable.AndroidManifestActivity_process,
4377 R.styleable.AndroidManifestActivity_description,
4378 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004379 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004380
Garrett Boyer52136662017-05-23 13:47:58 -07004381 cachedArgs.mActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
4382 cachedArgs.mActivityArgs.sa = sa;
4383 cachedArgs.mActivityArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004384
Garrett Boyer52136662017-05-23 13:47:58 -07004385 Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004386 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004387 sa.recycle();
4388 return null;
4389 }
4390
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004391 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004392 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004393 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004394 }
4395
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004396 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004398 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07004399 a.info.applicationInfo.uiOptions);
4400
Adam Powelldd8fab22012-03-22 17:47:27 -07004401 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004402 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004403 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004404 if (parentName != null) {
4405 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4406 if (outError[0] == null) {
4407 a.info.parentActivityName = parentClassName;
4408 } else {
4409 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
4410 parentName);
4411 outError[0] = null;
4412 }
4413 }
4414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004415 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004416 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004417 if (str == null) {
4418 a.info.permission = owner.applicationInfo.permission;
4419 } else {
4420 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4421 }
4422
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004423 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004424 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004425 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004426 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
4427 owner.applicationInfo.taskAffinity, str, outError);
4428
Todd Kennedye9d0d272017-01-23 06:49:29 -08004429 a.info.splitName =
4430 sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0);
4431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004432 a.info.flags = 0;
4433 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004434 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004435 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
4436 }
4437
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004438 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004439 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
4440 }
4441
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004442 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004443 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
4444 }
4445
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004446 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004447 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
4448 }
4449
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004450 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
4452 }
4453
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004454 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004455 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
4456 }
4457
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004458 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004459 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
4460 }
4461
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004462 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004463 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
4464 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
4465 }
4466
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004467 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07004468 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
4469 }
4470
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07004471 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
4472 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
4473 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07004474 }
4475
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004476 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04004477 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
4478 }
Craig Mautner5962b122012-10-05 14:45:52 -07004479
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07004480 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
4481 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08004482 }
4483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004484 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004485 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07004486 hardwareAccelerated)) {
4487 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
4488 }
4489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004490 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004491 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07004492 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004493 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07004494 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07004495 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004496 R.styleable.AndroidManifestActivity_maxRecents,
Wale Ogunwale65ebd952018-04-25 15:41:44 -07004497 ActivityTaskManager.getDefaultAppRecentsLimitStatic());
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004498 a.info.configChanges = getActivityConfigChanges(
4499 sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004500 sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004501 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004502 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07004503
Craig Mautner43e52ed2014-06-16 17:18:52 -07004504 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004505 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07004506 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07004507
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004508 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004509 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
4510 }
4511
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004512 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004513 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
4514 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004515
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004516 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004517 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
4518 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004519
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004520 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004521 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
4522 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004523
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004524 a.info.screenOrientation = sa.getInt(
4525 R.styleable.AndroidManifestActivity_screenOrientation,
4526 SCREEN_ORIENTATION_UNSPECIFIED);
Wale Ogunwale6a591362015-10-05 20:18:27 -07004527
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004528 setActivityResizeMode(a.info, sa, owner);
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004529
Winson Chungd3395382016-12-13 11:49:09 -08004530 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
4531 false)) {
4532 a.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE;
4533 }
4534
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004535 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004536 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004537 }
Wale Ogunwaleb60692e2015-10-24 12:35:56 -07004538
Bryce Lee22571db2017-07-07 15:54:18 -07004539 if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio)
4540 && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio)
4541 == TypedValue.TYPE_FLOAT) {
4542 a.setMaxAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio,
4543 0 /*default*/));
4544 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004545
Adrian Roos917791e2018-11-28 16:30:44 +01004546 if (sa.hasValue(R.styleable.AndroidManifestActivity_minAspectRatio)
4547 && sa.getType(R.styleable.AndroidManifestActivity_minAspectRatio)
4548 == TypedValue.TYPE_FLOAT) {
4549 a.setMinAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_minAspectRatio,
4550 0 /*default*/));
4551 }
4552
Craig Mautner15df08a2015-04-01 12:17:18 -07004553 a.info.lockTaskLaunchMode =
4554 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004555
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004556 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4557 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004558 false);
Ruben Brunkf56c9f42016-04-22 18:20:55 -07004559
4560 a.info.requestedVrComponent =
4561 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
Robert Carr0f5d7532016-10-17 16:39:17 -07004562
4563 a.info.rotationAnimation =
Robert Carr427ba4f2017-07-17 18:37:06 -07004564 sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_UNSPECIFIED);
Romain Guy48327452017-01-23 17:03:35 -08004565
4566 a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
4567 ActivityInfo.COLOR_MODE_DEFAULT);
chaviw59b98852017-06-13 12:05:44 -07004568
4569 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) {
4570 a.info.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
4571 }
4572
4573 if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) {
4574 a.info.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON;
4575 }
4576
Issei Suzuki74e1eb22018-12-20 17:42:52 +01004577 if (sa.getBoolean(R.styleable.AndroidManifestActivity_inheritShowWhenLocked, false)) {
4578 a.info.privateFlags |= ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
4579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004580 } else {
4581 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4582 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004583
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004584 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07004585 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004586 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004587
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004588 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4589 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004590 false);
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004591 }
4592
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004593 if (a.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004594 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004595 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004596 }
4597
Todd Kennedy752fb702017-03-21 16:28:10 -07004598 // can't make this final; we may set it later via meta-data
4599 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08004600 sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004601 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004602 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004603 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004604 }
4605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004606 sa.recycle();
4607
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004608 if (receiver && (owner.applicationInfo.privateFlags
4609 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004610 // A heavy-weight application can not have receives in its main process
4611 // We can do direct compare because we intern all strings.
4612 if (a.info.processName == owner.packageName) {
4613 outError[0] = "Heavy-weight applications can not have receivers in main process";
4614 }
4615 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004617 if (outError[0] != null) {
4618 return null;
4619 }
4620
4621 int outerDepth = parser.getDepth();
4622 int type;
4623 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4624 && (type != XmlPullParser.END_TAG
4625 || parser.getDepth() > outerDepth)) {
4626 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4627 continue;
4628 }
4629
4630 if (parser.getName().equals("intent-filter")) {
4631 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004632 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4633 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004634 return null;
4635 }
4636 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004637 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004638 + mArchiveSourcePath + " "
4639 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640 } else {
Todd Kennedy6d418b62018-02-22 14:15:18 -08004641 a.order = Math.max(intent.getOrder(), a.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004642 a.intents.add(intent);
4643 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004644 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004645 final int visibility = visibleToEphemeral
4646 ? IntentFilter.VISIBILITY_EXPLICIT
4647 : !receiver && isImplicitlyExposedIntent(intent)
4648 ? IntentFilter.VISIBILITY_IMPLICIT
4649 : IntentFilter.VISIBILITY_NONE;
4650 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004651 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004652 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4653 }
4654 if (intent.isImplicitlyVisibleToInstantApp()) {
4655 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004656 }
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -07004657 if (LOG_UNSAFE_BROADCASTS && receiver
4658 && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
4659 for (int i = 0; i < intent.countActions(); i++) {
4660 final String action = intent.getAction(i);
4661 if (action == null || !action.startsWith("android.")) continue;
4662 if (!SAFE_BROADCASTS.contains(action)) {
4663 Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
4664 + owner.packageName + " as requested at: "
4665 + parser.getPositionDescription());
4666 }
4667 }
4668 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004669 } else if (!receiver && parser.getName().equals("preferred")) {
4670 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004671 if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
4672 intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004673 return null;
4674 }
4675 if (intent.countActions() == 0) {
4676 Slog.w(TAG, "No actions in preferred at "
4677 + mArchiveSourcePath + " "
4678 + parser.getPositionDescription());
4679 } else {
4680 if (owner.preferredActivityFilters == null) {
4681 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
4682 }
4683 owner.preferredActivityFilters.add(intent);
4684 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004685 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004686 final int visibility = visibleToEphemeral
4687 ? IntentFilter.VISIBILITY_EXPLICIT
4688 : !receiver && isImplicitlyExposedIntent(intent)
4689 ? IntentFilter.VISIBILITY_IMPLICIT
4690 : IntentFilter.VISIBILITY_NONE;
4691 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004692 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004693 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4694 }
4695 if (intent.isImplicitlyVisibleToInstantApp()) {
4696 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004697 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004698 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004699 if ((a.metaData = parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004700 outError)) == null) {
4701 return null;
4702 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004703 } else if (!receiver && parser.getName().equals("layout")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004704 parseLayout(res, parser, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004705 } else {
4706 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004707 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004708 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004709 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004710 + " at " + mArchiveSourcePath + " "
4711 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004713 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004714 + " at " + mArchiveSourcePath + " "
4715 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004716 }
4717 XmlUtils.skipCurrentTag(parser);
4718 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004719 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004720 if (receiver) {
4721 outError[0] = "Bad element under <receiver>: " + parser.getName();
4722 } else {
4723 outError[0] = "Bad element under <activity>: " + parser.getName();
4724 }
4725 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004726 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 }
4728 }
4729
4730 if (!setExported) {
4731 a.info.exported = a.intents.size() > 0;
4732 }
4733
4734 return a;
4735 }
4736
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004737 private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004738 final boolean appExplicitDefault = (owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004739 & (PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
4740 | PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004741
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004742 if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
4743 || appExplicitDefault) {
4744 // Activity or app explicitly set if it is resizeable or not;
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004745 final boolean appResizeable = (owner.applicationInfo.privateFlags
4746 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004747 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004748 appResizeable)) {
Winson Chungd3395382016-12-13 11:49:09 -08004749 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004750 } else {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004751 aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004752 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004753 return;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004754 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004755
4756 if ((owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004757 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) != 0) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004758 // The activity or app didn't explicitly set the resizing option, however we want to
4759 // make it resize due to the sdk version it is targeting.
4760 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4761 return;
4762 }
4763
4764 // resize preference isn't set and target sdk version doesn't support resizing apps by
4765 // default. For the app to be resizeable if it isn't fixed orientation or immersive.
skuhne@google.com322347b2016-12-02 12:54:03 -08004766 if (aInfo.isFixedOrientationPortrait()) {
4767 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
4768 } else if (aInfo.isFixedOrientationLandscape()) {
4769 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
4770 } else if (aInfo.isFixedOrientation()) {
4771 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
4772 } else {
4773 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4774 }
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004775 }
4776
Bryce Lee22571db2017-07-07 15:54:18 -07004777 /**
4778 * Sets every the max aspect ratio of every child activity that doesn't already have an aspect
4779 * ratio set.
4780 */
4781 private void setMaxAspectRatio(Package owner) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004782 // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
4783 // 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 -07004784 float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004785 ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
Bryce Lee22571db2017-07-07 15:54:18 -07004786
4787 if (owner.applicationInfo.maxAspectRatio != 0) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004788 // Use the application max aspect ration as default if set.
Bryce Lee22571db2017-07-07 15:54:18 -07004789 maxAspectRatio = owner.applicationInfo.maxAspectRatio;
4790 } else if (owner.mAppMetaData != null
4791 && owner.mAppMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) {
4792 maxAspectRatio = owner.mAppMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004793 }
4794
Bryce Lee22571db2017-07-07 15:54:18 -07004795 for (Activity activity : owner.activities) {
4796 // If the max aspect ratio for the activity has already been set, skip.
4797 if (activity.hasMaxAspectRatio()) {
4798 continue;
4799 }
4800
4801 // By default we prefer to use a values defined on the activity directly than values
4802 // defined on the application. We do not check the styled attributes on the activity
4803 // as it would have already been set when we processed the activity. We wait to process
4804 // the meta data here since this method is called at the end of processing the
4805 // application and all meta data is guaranteed.
4806 final float activityAspectRatio = activity.metaData != null
4807 ? activity.metaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio)
4808 : maxAspectRatio;
4809
4810 activity.setMaxAspectRatio(activityAspectRatio);
Wale Ogunwale0cb70ac2017-03-27 09:16:38 -07004811 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004812 }
4813
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004814 /**
Tiger Huang3d2b8982019-01-29 22:56:48 +08004815 * Sets every the min aspect ratio of every child activity that doesn't already have an aspect
Adrian Roos917791e2018-11-28 16:30:44 +01004816 * ratio set.
4817 */
4818 private void setMinAspectRatio(Package owner) {
4819 final float minAspectRatio;
4820 if (owner.applicationInfo.minAspectRatio != 0) {
4821 // Use the application max aspect ration as default if set.
4822 minAspectRatio = owner.applicationInfo.minAspectRatio;
4823 } else {
4824 // Default to (1.33) 4:3 aspect ratio for pre-Q apps and unset for Q and greater.
4825 // NOTE: 4:3 was the min aspect ratio Android devices can support pre-Q per the CDD,
4826 // except for watches which always supported 1:1.
4827 minAspectRatio = owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q
4828 ? 0
Mohammad Samiul Islam7aa7d2e2019-03-27 12:23:47 +00004829 : (mCallback != null && mCallback.hasFeature(FEATURE_WATCH))
Adrian Roos917791e2018-11-28 16:30:44 +01004830 ? DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH
4831 : DEFAULT_PRE_Q_MIN_ASPECT_RATIO;
4832 }
4833
4834 for (Activity activity : owner.activities) {
4835 if (activity.hasMinAspectRatio()) {
4836 continue;
4837 }
4838 activity.setMinAspectRatio(minAspectRatio);
4839 }
4840 }
4841
4842 /**
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004843 * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004844 * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from
4845 * AndroidManifest.xml.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004846 * @hide Exposed for unit testing only.
4847 */
4848 @TestApi
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004849 public static int getActivityConfigChanges(int configChanges, int recreateOnConfigChanges) {
4850 return configChanges | ((~recreateOnConfigChanges) & RECREATE_ON_CONFIG_CHANGES_MASK);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004851 }
4852
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004853 private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004854 TypedArray sw = res.obtainAttributes(attrs,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004855 com.android.internal.R.styleable.AndroidManifestLayout);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004856 int width = -1;
4857 float widthFraction = -1f;
4858 int height = -1;
4859 float heightFraction = -1f;
4860 final int widthType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004861 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004862 if (widthType == TypedValue.TYPE_FRACTION) {
4863 widthFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004864 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004865 1, 1, -1);
4866 } else if (widthType == TypedValue.TYPE_DIMENSION) {
4867 width = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004868 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004869 -1);
4870 }
4871 final int heightType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004872 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004873 if (heightType == TypedValue.TYPE_FRACTION) {
4874 heightFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004875 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004876 1, 1, -1);
4877 } else if (heightType == TypedValue.TYPE_DIMENSION) {
4878 height = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004879 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004880 -1);
4881 }
4882 int gravity = sw.getInt(
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004883 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004884 Gravity.CENTER);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004885 int minWidth = sw.getDimensionPixelSize(
4886 com.android.internal.R.styleable.AndroidManifestLayout_minWidth,
Andrii Kulian2e751b82016-03-16 16:59:32 -07004887 -1);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004888 int minHeight = sw.getDimensionPixelSize(
4889 com.android.internal.R.styleable.AndroidManifestLayout_minHeight,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004890 -1);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004891 sw.recycle();
Andrii Kulian2e751b82016-03-16 16:59:32 -07004892 a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction,
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004893 height, heightFraction, gravity, minWidth, minHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004894 }
4895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004896 private Activity parseActivityAlias(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004897 XmlResourceParser parser, int flags, String[] outError,
4898 CachedComponentArgs cachedArgs)
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004899 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004900 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004901 com.android.internal.R.styleable.AndroidManifestActivityAlias);
4902
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004903 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004904 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
4905 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004906 if (targetActivity == null) {
4907 outError[0] = "<activity-alias> does not specify android:targetActivity";
4908 sa.recycle();
4909 return null;
4910 }
4911
4912 targetActivity = buildClassName(owner.applicationInfo.packageName,
4913 targetActivity, outError);
4914 if (targetActivity == null) {
4915 sa.recycle();
4916 return null;
4917 }
4918
Garrett Boyer52136662017-05-23 13:47:58 -07004919 if (cachedArgs.mActivityAliasArgs == null) {
4920 cachedArgs.mActivityAliasArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004921 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
4922 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
4923 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004924 com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004925 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004926 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004927 mSeparateProcesses,
4928 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004929 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004930 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004931 cachedArgs.mActivityAliasArgs.tag = "<activity-alias>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004932 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004933
Garrett Boyer52136662017-05-23 13:47:58 -07004934 cachedArgs.mActivityAliasArgs.sa = sa;
4935 cachedArgs.mActivityAliasArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004937 Activity target = null;
4938
4939 final int NA = owner.activities.size();
4940 for (int i=0; i<NA; i++) {
4941 Activity t = owner.activities.get(i);
4942 if (targetActivity.equals(t.info.name)) {
4943 target = t;
4944 break;
4945 }
4946 }
4947
4948 if (target == null) {
4949 outError[0] = "<activity-alias> target activity " + targetActivity
4950 + " not found in manifest";
4951 sa.recycle();
4952 return null;
4953 }
4954
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004955 ActivityInfo info = new ActivityInfo();
4956 info.targetActivity = targetActivity;
4957 info.configChanges = target.info.configChanges;
4958 info.flags = target.info.flags;
Issei Suzuki74e1eb22018-12-20 17:42:52 +01004959 info.privateFlags = target.info.privateFlags;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004960 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07004961 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08004962 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004963 info.labelRes = target.info.labelRes;
4964 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
4965 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07004966 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004967 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004968 if (info.descriptionRes == 0) {
4969 info.descriptionRes = target.info.descriptionRes;
4970 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004971 info.screenOrientation = target.info.screenOrientation;
4972 info.taskAffinity = target.info.taskAffinity;
4973 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07004974 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07004975 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07004976 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07004977 info.maxRecents = target.info.maxRecents;
Andrii Kulian2e751b82016-03-16 16:59:32 -07004978 info.windowLayout = target.info.windowLayout;
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004979 info.resizeMode = target.info.resizeMode;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004980 info.maxAspectRatio = target.info.maxAspectRatio;
Adrian Roos917791e2018-11-28 16:30:44 +01004981 info.minAspectRatio = target.info.minAspectRatio;
rongliuc12ede42018-02-23 17:58:38 -08004982 info.requestedVrComponent = target.info.requestedVrComponent;
Bryce Lee22571db2017-07-07 15:54:18 -07004983
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004984 info.encryptionAware = info.directBootAware = target.info.directBootAware;
Craig Mautner8307ea72014-09-11 15:03:53 -07004985
Garrett Boyer52136662017-05-23 13:47:58 -07004986 Activity a = new Activity(cachedArgs.mActivityAliasArgs, info);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004987 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988 sa.recycle();
4989 return null;
4990 }
4991
4992 final boolean setExported = sa.hasValue(
4993 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
4994 if (setExported) {
4995 a.info.exported = sa.getBoolean(
4996 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
4997 }
4998
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005000 str = sa.getNonConfigurationString(
5001 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005002 if (str != null) {
5003 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
5004 }
5005
Adam Powelldd8fab22012-03-22 17:47:27 -07005006 String parentName = sa.getNonConfigurationString(
5007 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07005008 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07005009 if (parentName != null) {
5010 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
5011 if (outError[0] == null) {
5012 a.info.parentActivityName = parentClassName;
5013 } else {
5014 Log.e(TAG, "Activity alias " + a.info.name +
5015 " specified invalid parentActivityName " + parentName);
5016 outError[0] = null;
5017 }
5018 }
5019
Chad Brubaker699c7712017-01-20 13:53:42 -08005020 // TODO add visibleToInstantApps attribute to activity alias
Todd Kennedybe0b8892017-02-15 14:13:52 -08005021 final boolean visibleToEphemeral =
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005022 ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005024 sa.recycle();
5025
5026 if (outError[0] != null) {
5027 return null;
5028 }
5029
5030 int outerDepth = parser.getDepth();
5031 int type;
5032 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5033 && (type != XmlPullParser.END_TAG
5034 || parser.getDepth() > outerDepth)) {
5035 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5036 continue;
5037 }
5038
5039 if (parser.getName().equals("intent-filter")) {
5040 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005041 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
5042 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005043 return null;
5044 }
5045 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005046 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07005047 + mArchiveSourcePath + " "
5048 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005049 } else {
Todd Kennedy6d418b62018-02-22 14:15:18 -08005050 a.order = Math.max(intent.getOrder(), a.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005051 a.intents.add(intent);
5052 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005053 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005054 final int visibility = visibleToEphemeral
5055 ? IntentFilter.VISIBILITY_EXPLICIT
5056 : isImplicitlyExposedIntent(intent)
5057 ? IntentFilter.VISIBILITY_IMPLICIT
5058 : IntentFilter.VISIBILITY_NONE;
5059 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08005060 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005061 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
5062 }
5063 if (intent.isImplicitlyVisibleToInstantApp()) {
5064 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005066 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005067 if ((a.metaData=parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005068 outError)) == null) {
5069 return null;
5070 }
5071 } else {
5072 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005073 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005074 + " at " + mArchiveSourcePath + " "
5075 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005076 XmlUtils.skipCurrentTag(parser);
5077 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005078 } else {
5079 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
5080 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005081 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005082 }
5083 }
5084
5085 if (!setExported) {
5086 a.info.exported = a.intents.size() > 0;
5087 }
5088
5089 return a;
5090 }
5091
5092 private Provider parseProvider(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07005093 XmlResourceParser parser, int flags, String[] outError,
5094 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005095 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005096 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 com.android.internal.R.styleable.AndroidManifestProvider);
5098
Garrett Boyer52136662017-05-23 13:47:58 -07005099 if (cachedArgs.mProviderArgs == null) {
5100 cachedArgs.mProviderArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005101 com.android.internal.R.styleable.AndroidManifestProvider_name,
5102 com.android.internal.R.styleable.AndroidManifestProvider_label,
5103 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005104 com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07005105 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08005106 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005107 mSeparateProcesses,
5108 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005109 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005110 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07005111 cachedArgs.mProviderArgs.tag = "<provider>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005112 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005113
Garrett Boyer52136662017-05-23 13:47:58 -07005114 cachedArgs.mProviderArgs.sa = sa;
5115 cachedArgs.mProviderArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005116
Garrett Boyer52136662017-05-23 13:47:58 -07005117 Provider p = new Provider(cachedArgs.mProviderArgs, new ProviderInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005118 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005119 sa.recycle();
5120 return null;
5121 }
5122
Nick Kralevichf097b162012-07-28 12:43:48 -07005123 boolean providerExportedDefault = false;
5124
5125 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
5126 // For compatibility, applications targeting API level 16 or lower
5127 // should have their content providers exported by default, unless they
5128 // specify otherwise.
5129 providerExportedDefault = true;
5130 }
5131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005132 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07005133 com.android.internal.R.styleable.AndroidManifestProvider_exported,
5134 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005135
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005136 String cpname = sa.getNonConfigurationString(
5137 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138
5139 p.info.isSyncable = sa.getBoolean(
5140 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
5141 false);
5142
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005143 String permission = sa.getNonConfigurationString(
5144 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
5145 String str = sa.getNonConfigurationString(
5146 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005147 if (str == null) {
5148 str = permission;
5149 }
5150 if (str == null) {
5151 p.info.readPermission = owner.applicationInfo.permission;
5152 } else {
5153 p.info.readPermission =
5154 str.length() > 0 ? str.toString().intern() : null;
5155 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005156 str = sa.getNonConfigurationString(
5157 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005158 if (str == null) {
5159 str = permission;
5160 }
5161 if (str == null) {
5162 p.info.writePermission = owner.applicationInfo.permission;
5163 } else {
5164 p.info.writePermission =
5165 str.length() > 0 ? str.toString().intern() : null;
5166 }
5167
5168 p.info.grantUriPermissions = sa.getBoolean(
5169 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
5170 false);
5171
Dianne Hackborn52e42a42019-02-05 16:10:50 -08005172 p.info.forceUriPermissions = sa.getBoolean(
5173 com.android.internal.R.styleable.AndroidManifestProvider_forceUriPermissions,
5174 false);
5175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005176 p.info.multiprocess = sa.getBoolean(
5177 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
5178 false);
5179
5180 p.info.initOrder = sa.getInt(
5181 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
5182 0);
5183
Todd Kennedye9d0d272017-01-23 06:49:29 -08005184 p.info.splitName =
5185 sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0);
5186
Dianne Hackborn7d19e022012-08-07 19:12:33 -07005187 p.info.flags = 0;
5188
5189 if (sa.getBoolean(
5190 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
5191 false)) {
5192 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07005193 }
5194
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005195 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
5196 R.styleable.AndroidManifestProvider_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005197 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005198 if (p.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005199 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005200 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005201 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005202
Todd Kennedybe0b8892017-02-15 14:13:52 -08005203 final boolean visibleToEphemeral =
5204 sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005205 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005206 p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005207 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005208 }
5209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005210 sa.recycle();
5211
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005212 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5213 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005214 // A heavy-weight application can not have providers in its main process
5215 // We can do direct compare because we intern all strings.
5216 if (p.info.processName == owner.packageName) {
5217 outError[0] = "Heavy-weight applications can not have providers in main process";
5218 return null;
5219 }
5220 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005222 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07005223 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005224 return null;
5225 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08005226 if (cpname.length() <= 0) {
5227 outError[0] = "<provider> has empty authorities attribute";
5228 return null;
5229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005230 p.info.authority = cpname.intern();
5231
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005232 if (!parseProviderTags(
Patrick Baumanna2900392018-02-05 15:30:43 -08005233 res, parser, visibleToEphemeral, p, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005234 return null;
5235 }
5236
5237 return p;
5238 }
5239
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005240 private boolean parseProviderTags(Resources res, XmlResourceParser parser,
Patrick Baumanna2900392018-02-05 15:30:43 -08005241 boolean visibleToEphemeral, Provider outInfo, String[] outError)
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005242 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 int outerDepth = parser.getDepth();
5244 int type;
5245 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5246 && (type != XmlPullParser.END_TAG
5247 || parser.getDepth() > outerDepth)) {
5248 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5249 continue;
5250 }
5251
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005252 if (parser.getName().equals("intent-filter")) {
5253 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005254 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5255 intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005256 return false;
5257 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005258 if (visibleToEphemeral) {
5259 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5260 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005261 }
Todd Kennedy6d418b62018-02-22 14:15:18 -08005262 outInfo.order = Math.max(intent.getOrder(), outInfo.order);
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005263 outInfo.intents.add(intent);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005264
5265 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005266 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005267 outInfo.metaData, outError)) == null) {
5268 return false;
5269 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 } else if (parser.getName().equals("grant-uri-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005272 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005273 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
5274
5275 PatternMatcher pa = null;
5276
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005277 String str = sa.getNonConfigurationString(
5278 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005279 if (str != null) {
5280 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
5281 }
5282
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005283 str = sa.getNonConfigurationString(
5284 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005285 if (str != null) {
5286 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
5287 }
5288
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005289 str = sa.getNonConfigurationString(
5290 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005291 if (str != null) {
5292 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5293 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 sa.recycle();
5296
5297 if (pa != null) {
5298 if (outInfo.info.uriPermissionPatterns == null) {
5299 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
5300 outInfo.info.uriPermissionPatterns[0] = pa;
5301 } else {
5302 final int N = outInfo.info.uriPermissionPatterns.length;
5303 PatternMatcher[] newp = new PatternMatcher[N+1];
5304 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
5305 newp[N] = pa;
5306 outInfo.info.uriPermissionPatterns = newp;
5307 }
5308 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005309 } else {
5310 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005311 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005312 + parser.getName() + " at " + mArchiveSourcePath + " "
5313 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005314 XmlUtils.skipCurrentTag(parser);
5315 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005316 } else {
5317 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5318 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005319 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005320 }
5321 XmlUtils.skipCurrentTag(parser);
5322
5323 } else if (parser.getName().equals("path-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005324 TypedArray sa = res.obtainAttributes(parser,
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005325 com.android.internal.R.styleable.AndroidManifestPathPermission);
5326
5327 PathPermission pa = null;
5328
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005329 String permission = sa.getNonConfigurationString(
5330 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
5331 String readPermission = sa.getNonConfigurationString(
5332 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005333 if (readPermission == null) {
5334 readPermission = permission;
5335 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005336 String writePermission = sa.getNonConfigurationString(
5337 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005338 if (writePermission == null) {
5339 writePermission = permission;
5340 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005341
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005342 boolean havePerm = false;
5343 if (readPermission != null) {
5344 readPermission = readPermission.intern();
5345 havePerm = true;
5346 }
5347 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00005348 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005349 havePerm = true;
5350 }
5351
5352 if (!havePerm) {
5353 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005354 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005355 + parser.getName() + " at " + mArchiveSourcePath + " "
5356 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005357 XmlUtils.skipCurrentTag(parser);
5358 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005359 } else {
5360 outError[0] = "No readPermission or writePermssion for <path-permission>";
5361 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005362 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005363 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005364
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005365 String path = sa.getNonConfigurationString(
5366 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005367 if (path != null) {
5368 pa = new PathPermission(path,
5369 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
5370 }
5371
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005372 path = sa.getNonConfigurationString(
5373 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005374 if (path != null) {
5375 pa = new PathPermission(path,
5376 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
5377 }
5378
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005379 path = sa.getNonConfigurationString(
5380 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005381 if (path != null) {
5382 pa = new PathPermission(path,
5383 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
5384 }
5385
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005386 path = sa.getNonConfigurationString(
5387 com.android.internal.R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
5388 if (path != null) {
5389 pa = new PathPermission(path,
5390 PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission);
5391 }
5392
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005393 sa.recycle();
5394
5395 if (pa != null) {
5396 if (outInfo.info.pathPermissions == null) {
5397 outInfo.info.pathPermissions = new PathPermission[1];
5398 outInfo.info.pathPermissions[0] = pa;
5399 } else {
5400 final int N = outInfo.info.pathPermissions.length;
5401 PathPermission[] newp = new PathPermission[N+1];
5402 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
5403 newp[N] = pa;
5404 outInfo.info.pathPermissions = newp;
5405 }
5406 } else {
5407 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005408 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005409 + parser.getName() + " at " + mArchiveSourcePath + " "
5410 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005411 XmlUtils.skipCurrentTag(parser);
5412 continue;
5413 }
5414 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5415 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005416 }
5417 XmlUtils.skipCurrentTag(parser);
5418
5419 } else {
5420 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005421 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005422 + parser.getName() + " at " + mArchiveSourcePath + " "
5423 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424 XmlUtils.skipCurrentTag(parser);
5425 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005426 } else {
5427 outError[0] = "Bad element under <provider>: " + parser.getName();
5428 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005430 }
5431 }
5432 return true;
5433 }
5434
5435 private Service parseService(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07005436 XmlResourceParser parser, int flags, String[] outError,
5437 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005438 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005439 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005440 com.android.internal.R.styleable.AndroidManifestService);
5441
Garrett Boyer52136662017-05-23 13:47:58 -07005442 if (cachedArgs.mServiceArgs == null) {
5443 cachedArgs.mServiceArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005444 com.android.internal.R.styleable.AndroidManifestService_name,
5445 com.android.internal.R.styleable.AndroidManifestService_label,
5446 com.android.internal.R.styleable.AndroidManifestService_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005447 com.android.internal.R.styleable.AndroidManifestService_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07005448 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08005449 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005450 mSeparateProcesses,
5451 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005452 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005453 com.android.internal.R.styleable.AndroidManifestService_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07005454 cachedArgs.mServiceArgs.tag = "<service>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005455 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005456
Garrett Boyer52136662017-05-23 13:47:58 -07005457 cachedArgs.mServiceArgs.sa = sa;
5458 cachedArgs.mServiceArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005459
Garrett Boyer52136662017-05-23 13:47:58 -07005460 Service s = new Service(cachedArgs.mServiceArgs, new ServiceInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005461 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005462 sa.recycle();
5463 return null;
5464 }
5465
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005466 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005467 com.android.internal.R.styleable.AndroidManifestService_exported);
5468 if (setExported) {
5469 s.info.exported = sa.getBoolean(
5470 com.android.internal.R.styleable.AndroidManifestService_exported, false);
5471 }
5472
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005473 String str = sa.getNonConfigurationString(
5474 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005475 if (str == null) {
5476 s.info.permission = owner.applicationInfo.permission;
5477 } else {
5478 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
5479 }
5480
Todd Kennedye9d0d272017-01-23 06:49:29 -08005481 s.info.splitName =
5482 sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0);
5483
Hui Yu1ea85522018-12-06 16:59:18 -08005484 s.info.mForegroundServiceType = sa.getInt(
5485 com.android.internal.R.styleable.AndroidManifestService_foregroundServiceType,
Hui Yu2d4207f2019-01-22 15:32:20 -08005486 ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
Hui Yu1ea85522018-12-06 16:59:18 -08005487
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005488 s.info.flags = 0;
5489 if (sa.getBoolean(
5490 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
5491 false)) {
5492 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
5493 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08005494 if (sa.getBoolean(
5495 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
5496 false)) {
5497 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
5498 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005499 if (sa.getBoolean(
Robert Sesekb9a86662015-12-09 16:22:45 -05005500 com.android.internal.R.styleable.AndroidManifestService_externalService,
5501 false)) {
5502 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
5503 }
5504 if (sa.getBoolean(
Martijn Coenene066c5c2018-10-31 16:50:30 +01005505 com.android.internal.R.styleable.AndroidManifestService_useAppZygote,
5506 false)) {
5507 s.info.flags |= ServiceInfo.FLAG_USE_APP_ZYGOTE;
5508 }
5509 if (sa.getBoolean(
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005510 com.android.internal.R.styleable.AndroidManifestService_singleUser,
5511 false)) {
5512 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005513 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005514
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005515 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
5516 R.styleable.AndroidManifestService_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005517 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005518 if (s.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005519 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005520 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005521 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005522
Todd Kennedy752fb702017-03-21 16:28:10 -07005523 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08005524 sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005525 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005526 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005527 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005528 }
5529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005530 sa.recycle();
5531
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005532 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5533 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005534 // A heavy-weight application can not have services in its main process
5535 // We can do direct compare because we intern all strings.
5536 if (s.info.processName == owner.packageName) {
5537 outError[0] = "Heavy-weight applications can not have services in main process";
5538 return null;
5539 }
5540 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005542 int outerDepth = parser.getDepth();
5543 int type;
5544 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5545 && (type != XmlPullParser.END_TAG
5546 || parser.getDepth() > outerDepth)) {
5547 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5548 continue;
5549 }
5550
5551 if (parser.getName().equals("intent-filter")) {
5552 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005553 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5554 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005555 return null;
5556 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005557 if (visibleToEphemeral) {
5558 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5559 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005560 }
Todd Kennedy6d418b62018-02-22 14:15:18 -08005561 s.order = Math.max(intent.getOrder(), s.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005562 s.intents.add(intent);
5563 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005564 if ((s.metaData=parseMetaData(res, parser, s.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005565 outError)) == null) {
5566 return null;
5567 }
5568 } else {
5569 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005570 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005571 + parser.getName() + " at " + mArchiveSourcePath + " "
5572 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005573 XmlUtils.skipCurrentTag(parser);
5574 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005575 } else {
5576 outError[0] = "Bad element under <service>: " + parser.getName();
5577 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005578 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005579 }
5580 }
5581
5582 if (!setExported) {
5583 s.info.exported = s.intents.size() > 0;
5584 }
5585
5586 return s;
5587 }
5588
Chad Brubaker49414832017-04-13 16:13:23 -07005589 private boolean isImplicitlyExposedIntent(IntentInfo intent) {
5590 return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
5591 || intent.hasAction(Intent.ACTION_SEND)
5592 || intent.hasAction(Intent.ACTION_SENDTO)
5593 || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005594 }
5595
Svet Ganov354cd3c2015-12-17 11:35:04 -08005596 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
5597 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005598 int outerDepth = parser.getDepth();
5599 int type;
5600 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5601 && (type != XmlPullParser.END_TAG
5602 || parser.getDepth() > outerDepth)) {
5603 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5604 continue;
5605 }
5606
5607 if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005608 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005609 outInfo.metaData, outError)) == null) {
5610 return false;
5611 }
5612 } else {
5613 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005614 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005615 + parser.getName() + " at " + mArchiveSourcePath + " "
5616 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005617 XmlUtils.skipCurrentTag(parser);
5618 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005619 } else {
5620 outError[0] = "Bad element under " + tag + ": " + parser.getName();
5621 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005623 }
5624 }
5625 return true;
5626 }
5627
5628 private Bundle parseMetaData(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08005629 XmlResourceParser parser, Bundle data, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005630 throws XmlPullParserException, IOException {
5631
Svet Ganov354cd3c2015-12-17 11:35:04 -08005632 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005633 com.android.internal.R.styleable.AndroidManifestMetaData);
5634
5635 if (data == null) {
5636 data = new Bundle();
5637 }
5638
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005639 String name = sa.getNonConfigurationString(
5640 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005641 if (name == null) {
5642 outError[0] = "<meta-data> requires an android:name attribute";
5643 sa.recycle();
5644 return null;
5645 }
5646
Dianne Hackborn854060af2009-07-09 18:14:31 -07005647 name = name.intern();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005649 TypedValue v = sa.peekValue(
5650 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
5651 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005652 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005653 data.putInt(name, v.resourceId);
5654 } else {
5655 v = sa.peekValue(
5656 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07005657 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005658 if (v != null) {
5659 if (v.type == TypedValue.TYPE_STRING) {
5660 CharSequence cs = v.coerceToString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00005661 data.putString(name, cs != null ? cs.toString() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005662 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
5663 data.putBoolean(name, v.data != 0);
5664 } else if (v.type >= TypedValue.TYPE_FIRST_INT
5665 && v.type <= TypedValue.TYPE_LAST_INT) {
5666 data.putInt(name, v.data);
5667 } else if (v.type == TypedValue.TYPE_FLOAT) {
5668 data.putFloat(name, v.getFloat());
5669 } else {
5670 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005671 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005672 + parser.getName() + " at " + mArchiveSourcePath + " "
5673 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 } else {
5675 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
5676 data = null;
5677 }
5678 }
5679 } else {
5680 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
5681 data = null;
5682 }
5683 }
5684
5685 sa.recycle();
5686
5687 XmlUtils.skipCurrentTag(parser);
5688
5689 return data;
5690 }
5691
Adam Lesinski4e862812016-11-21 16:02:24 -08005692 private static VerifierInfo parseVerifier(AttributeSet attrs) {
5693 String packageName = null;
5694 String encodedPublicKey = null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005695
Adam Lesinski4e862812016-11-21 16:02:24 -08005696 final int attrCount = attrs.getAttributeCount();
5697 for (int i = 0; i < attrCount; i++) {
5698 final int attrResId = attrs.getAttributeNameResource(i);
5699 switch (attrResId) {
5700 case com.android.internal.R.attr.name:
5701 packageName = attrs.getAttributeValue(i);
5702 break;
Kenny Root05ca4c92011-09-15 10:36:25 -07005703
Adam Lesinski4e862812016-11-21 16:02:24 -08005704 case com.android.internal.R.attr.publicKey:
5705 encodedPublicKey = attrs.getAttributeValue(i);
5706 break;
5707 }
5708 }
Kenny Root05ca4c92011-09-15 10:36:25 -07005709
5710 if (packageName == null || packageName.length() == 0) {
5711 Slog.i(TAG, "verifier package name was null; skipping");
5712 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005713 }
5714
Christopher Tate30147332014-04-15 12:57:47 -07005715 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
5716 if (publicKey == null) {
5717 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
5718 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08005719 }
5720
Christopher Tate30147332014-04-15 12:57:47 -07005721 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08005722 }
5723
Christopher Tate30147332014-04-15 12:57:47 -07005724 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
5725 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07005726 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07005727 return null;
5728 }
5729
Kenny Root05ca4c92011-09-15 10:36:25 -07005730 EncodedKeySpec keySpec;
5731 try {
5732 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
5733 keySpec = new X509EncodedKeySpec(encoded);
5734 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07005735 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07005736 return null;
5737 }
5738
5739 /* First try the key as an RSA key. */
5740 try {
5741 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005742 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005743 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005744 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005745 } catch (InvalidKeySpecException e) {
5746 // Not a RSA public key.
5747 }
5748
dcashman1616f302015-05-29 14:47:23 -07005749 /* Now try it as a ECDSA key. */
5750 try {
5751 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
5752 return keyFactory.generatePublic(keySpec);
5753 } catch (NoSuchAlgorithmException e) {
5754 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
5755 } catch (InvalidKeySpecException e) {
5756 // Not a ECDSA public key.
5757 }
5758
Kenny Root05ca4c92011-09-15 10:36:25 -07005759 /* Now try it as a DSA key. */
5760 try {
5761 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005762 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005763 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005764 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005765 } catch (InvalidKeySpecException e) {
5766 // Not a DSA public key.
5767 }
5768
dcashman1616f302015-05-29 14:47:23 -07005769 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07005770 return null;
5771 }
5772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005773 private static final String ANDROID_RESOURCES
5774 = "http://schemas.android.com/apk/res/android";
5775
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005776 private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs,
5777 boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
5778 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005779
Svet Ganov354cd3c2015-12-17 11:35:04 -08005780 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005781 com.android.internal.R.styleable.AndroidManifestIntentFilter);
5782
5783 int priority = sa.getInt(
5784 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005785 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08005786
Todd Kennedy6d418b62018-02-22 14:15:18 -08005787 int order = sa.getInt(
5788 com.android.internal.R.styleable.AndroidManifestIntentFilter_order, 0);
5789 outInfo.setOrder(order);
5790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 TypedValue v = sa.peekValue(
5792 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
5793 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
5794 outInfo.nonLocalizedLabel = v.coerceToString();
5795 }
5796
Hyunyoung Song929de7a2019-03-21 23:51:27 -07005797 int roundIconVal = sUseRoundIcon ? sa.getResourceId(
Todd Kennedya83bfca2016-06-03 07:52:17 -07005798 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
5799 if (roundIconVal != 0) {
5800 outInfo.icon = roundIconVal;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005801 } else {
5802 outInfo.icon = sa.getResourceId(
5803 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
5804 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005805
Adam Powell81cd2e92010-04-21 16:35:18 -07005806 outInfo.logo = sa.getResourceId(
5807 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005808
Jose Limaf78e3122014-03-06 12:13:15 -08005809 outInfo.banner = sa.getResourceId(
5810 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
5811
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08005812 if (allowAutoVerify) {
5813 outInfo.setAutoVerify(sa.getBoolean(
5814 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
5815 false));
5816 }
5817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005818 sa.recycle();
5819
5820 int outerDepth = parser.getDepth();
5821 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07005822 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
5823 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
5824 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005825 continue;
5826 }
5827
5828 String nodeName = parser.getName();
5829 if (nodeName.equals("action")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005830 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005831 ANDROID_RESOURCES, "name");
5832 if (value == null || value == "") {
5833 outError[0] = "No value supplied for <android:name>";
5834 return false;
5835 }
5836 XmlUtils.skipCurrentTag(parser);
5837
5838 outInfo.addAction(value);
5839 } else if (nodeName.equals("category")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005840 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005841 ANDROID_RESOURCES, "name");
5842 if (value == null || value == "") {
5843 outError[0] = "No value supplied for <android:name>";
5844 return false;
5845 }
5846 XmlUtils.skipCurrentTag(parser);
5847
5848 outInfo.addCategory(value);
5849
5850 } else if (nodeName.equals("data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005851 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005852 com.android.internal.R.styleable.AndroidManifestData);
5853
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005854 String str = sa.getNonConfigurationString(
5855 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005856 if (str != null) {
5857 try {
5858 outInfo.addDataType(str);
5859 } catch (IntentFilter.MalformedMimeTypeException e) {
5860 outError[0] = e.toString();
5861 sa.recycle();
5862 return false;
5863 }
5864 }
5865
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005866 str = sa.getNonConfigurationString(
5867 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 if (str != null) {
5869 outInfo.addDataScheme(str);
5870 }
5871
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005872 str = sa.getNonConfigurationString(
5873 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
5874 if (str != null) {
5875 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
5876 }
5877
5878 str = sa.getNonConfigurationString(
5879 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
5880 if (str != null) {
5881 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
5882 }
5883
5884 str = sa.getNonConfigurationString(
5885 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
5886 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005887 if (!allowGlobs) {
5888 outError[0] = "sspPattern not allowed here; ssp must be literal";
5889 return false;
5890 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005891 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5892 }
5893
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005894 String host = sa.getNonConfigurationString(
5895 com.android.internal.R.styleable.AndroidManifestData_host, 0);
5896 String port = sa.getNonConfigurationString(
5897 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005898 if (host != null) {
5899 outInfo.addDataAuthority(host, port);
5900 }
5901
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005902 str = sa.getNonConfigurationString(
5903 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005904 if (str != null) {
5905 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
5906 }
5907
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005908 str = sa.getNonConfigurationString(
5909 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005910 if (str != null) {
5911 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
5912 }
5913
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005914 str = sa.getNonConfigurationString(
5915 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005916 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005917 if (!allowGlobs) {
5918 outError[0] = "pathPattern not allowed here; path must be literal";
5919 return false;
5920 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005921 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5922 }
5923
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005924 str = sa.getNonConfigurationString(
5925 com.android.internal.R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
5926 if (str != null) {
5927 if (!allowGlobs) {
5928 outError[0] = "pathAdvancedPattern not allowed here; path must be literal";
5929 return false;
5930 }
5931 outInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
5932 }
5933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005934 sa.recycle();
5935 XmlUtils.skipCurrentTag(parser);
5936 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005937 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005938 + parser.getName() + " at " + mArchiveSourcePath + " "
5939 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005940 XmlUtils.skipCurrentTag(parser);
5941 } else {
5942 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
5943 return false;
5944 }
5945 }
5946
5947 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07005948
5949 if (DEBUG_PARSER) {
5950 final StringBuilder cats = new StringBuilder("Intent d=");
5951 cats.append(outInfo.hasDefault);
5952 cats.append(", cat=");
5953
5954 final Iterator<String> it = outInfo.categoriesIterator();
5955 if (it != null) {
5956 while (it.hasNext()) {
5957 cats.append(' ');
5958 cats.append(it.next());
5959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005960 }
Kenny Rootd2d29252011-08-08 11:27:57 -07005961 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005962 }
5963
5964 return true;
5965 }
5966
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005967 /**
5968 * A container for signing-related data of an application package.
5969 * @hide
5970 */
Patrick Baumann47117fc2017-12-19 10:17:21 -08005971 public static final class SigningDetails implements Parcelable {
5972
5973 @IntDef({SigningDetails.SignatureSchemeVersion.UNKNOWN,
5974 SigningDetails.SignatureSchemeVersion.JAR,
5975 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2,
5976 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3})
5977 public @interface SignatureSchemeVersion {
5978 int UNKNOWN = 0;
5979 int JAR = 1;
5980 int SIGNING_BLOCK_V2 = 2;
5981 int SIGNING_BLOCK_V3 = 3;
5982 }
5983
5984 @Nullable
Mathew Inwood5c0d3542018-08-14 13:54:31 +01005985 @UnsupportedAppUsage
Patrick Baumann47117fc2017-12-19 10:17:21 -08005986 public final Signature[] signatures;
5987 @SignatureSchemeVersion
5988 public final int signatureSchemeVersion;
5989 @Nullable
5990 public final ArraySet<PublicKey> publicKeys;
5991
Daniel Cashman77029c52018-01-18 16:19:29 -08005992 /**
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005993 * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
5994 * contains two pieces of information:
5995 * 1) the past signing certificates
5996 * 2) the flags that APK wants to assign to each of the past signing certificates.
5997 *
5998 * This collection of {@code Signature} objects, each of which is formed from a former
5999 * signing certificate of this APK before it was changed by signing certificate rotation,
6000 * represents the first piece of information. It is the APK saying to the rest of the
6001 * world: "hey if you trust the old cert, you can trust me!" This is useful, if for
6002 * instance, the platform would like to determine whether or not to allow this APK to do
6003 * something it would've allowed it to do under the old cert (like upgrade).
Daniel Cashman77029c52018-01-18 16:19:29 -08006004 */
6005 @Nullable
6006 public final Signature[] pastSigningCertificates;
6007
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006008 /** special value used to see if cert is in package - not exposed to callers */
6009 private static final int PAST_CERT_EXISTS = 0;
6010
6011 @IntDef(
6012 flag = true,
6013 value = {CertCapabilities.INSTALLED_DATA,
6014 CertCapabilities.SHARED_USER_ID,
Daniel Cashman629a5f92018-03-30 18:54:14 -07006015 CertCapabilities.PERMISSION,
6016 CertCapabilities.ROLLBACK})
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006017 public @interface CertCapabilities {
6018
6019 /** accept data from already installed pkg with this cert */
6020 int INSTALLED_DATA = 1;
6021
6022 /** accept sharedUserId with pkg with this cert */
6023 int SHARED_USER_ID = 2;
6024
6025 /** grant SIGNATURE permissions to pkgs with this cert */
6026 int PERMISSION = 4;
Daniel Cashman629a5f92018-03-30 18:54:14 -07006027
6028 /** allow pkg to update to one signed by this certificate */
6029 int ROLLBACK = 8;
Dan Cashman303c4bb2018-04-10 07:41:16 -07006030
6031 /** allow pkg to continue to have auth access gated by this cert */
6032 int AUTH = 16;
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006033 }
6034
Patrick Baumann47117fc2017-12-19 10:17:21 -08006035 /** A representation of unknown signing details. Use instead of null. */
6036 public static final SigningDetails UNKNOWN =
Michael Groovera117b0d2018-07-23 12:55:54 -07006037 new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006038
6039 @VisibleForTesting
6040 public SigningDetails(Signature[] signatures,
6041 @SignatureSchemeVersion int signatureSchemeVersion,
Michael Groovera117b0d2018-07-23 12:55:54 -07006042 ArraySet<PublicKey> keys, Signature[] pastSigningCertificates) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08006043 this.signatures = signatures;
6044 this.signatureSchemeVersion = signatureSchemeVersion;
6045 this.publicKeys = keys;
Daniel Cashman77029c52018-01-18 16:19:29 -08006046 this.pastSigningCertificates = pastSigningCertificates;
Daniel Cashman77029c52018-01-18 16:19:29 -08006047 }
6048
6049 public SigningDetails(Signature[] signatures,
6050 @SignatureSchemeVersion int signatureSchemeVersion,
Michael Groovera117b0d2018-07-23 12:55:54 -07006051 Signature[] pastSigningCertificates)
Daniel Cashman77029c52018-01-18 16:19:29 -08006052 throws CertificateException {
6053 this(signatures, signatureSchemeVersion, toSigningKeys(signatures),
Michael Groovera117b0d2018-07-23 12:55:54 -07006054 pastSigningCertificates);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006055 }
6056
6057 public SigningDetails(Signature[] signatures,
6058 @SignatureSchemeVersion int signatureSchemeVersion)
6059 throws CertificateException {
Michael Groovera117b0d2018-07-23 12:55:54 -07006060 this(signatures, signatureSchemeVersion, null);
Daniel Cashman77029c52018-01-18 16:19:29 -08006061 }
6062
6063 public SigningDetails(SigningDetails orig) {
6064 if (orig != null) {
6065 if (orig.signatures != null) {
6066 this.signatures = orig.signatures.clone();
6067 } else {
6068 this.signatures = null;
6069 }
6070 this.signatureSchemeVersion = orig.signatureSchemeVersion;
6071 this.publicKeys = new ArraySet<>(orig.publicKeys);
6072 if (orig.pastSigningCertificates != null) {
6073 this.pastSigningCertificates = orig.pastSigningCertificates.clone();
Daniel Cashman77029c52018-01-18 16:19:29 -08006074 } else {
6075 this.pastSigningCertificates = null;
Daniel Cashman77029c52018-01-18 16:19:29 -08006076 }
6077 } else {
6078 this.signatures = null;
6079 this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
6080 this.publicKeys = null;
6081 this.pastSigningCertificates = null;
Daniel Cashman77029c52018-01-18 16:19:29 -08006082 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08006083 }
6084
6085 /** Returns true if the signing details have one or more signatures. */
6086 public boolean hasSignatures() {
6087 return signatures != null && signatures.length > 0;
6088 }
6089
Daniel Cashman5cdda342018-01-19 07:22:52 -08006090 /** Returns true if the signing details have past signing certificates. */
6091 public boolean hasPastSigningCertificates() {
6092 return pastSigningCertificates != null && pastSigningCertificates.length > 0;
6093 }
6094
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006095 /**
6096 * Determines if the provided {@code oldDetails} is an ancestor of or the same as this one.
6097 * If the {@code oldDetails} signing certificate appears in our pastSigningCertificates,
6098 * then that means it has authorized a signing certificate rotation, which eventually leads
6099 * to our certificate, and thus can be trusted. If this method evaluates to true, this
6100 * SigningDetails object should be trusted if the previous one is.
6101 */
6102 public boolean hasAncestorOrSelf(SigningDetails oldDetails) {
6103 if (this == UNKNOWN || oldDetails == UNKNOWN) {
6104 return false;
6105 }
6106 if (oldDetails.signatures.length > 1) {
6107
6108 // multiple-signer packages cannot rotate signing certs, so we just compare current
6109 // signers for an exact match
6110 return signaturesMatchExactly(oldDetails);
6111 } else {
6112
6113 // we may have signing certificate rotation history, check to see if the oldDetails
6114 // was one of our old signing certificates
6115 return hasCertificate(oldDetails.signatures[0]);
6116 }
6117 }
6118
6119 /**
6120 * Similar to {@code hasAncestorOrSelf}. Returns true only if this {@code SigningDetails}
6121 * is a descendant of {@code oldDetails}, not if they're the same. This is used to
6122 * determine if this object is newer than the provided one.
6123 */
6124 public boolean hasAncestor(SigningDetails oldDetails) {
6125 if (this == UNKNOWN || oldDetails == UNKNOWN) {
6126 return false;
6127 }
6128 if (this.hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
6129
6130 // the last entry in pastSigningCertificates is the current signer, ignore it
6131 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
6132 if (pastSigningCertificates[i].equals(oldDetails.signatures[i])) {
6133 return true;
6134 }
6135 }
6136 }
6137 return false;
6138 }
6139
6140 /**
6141 * Determines if the provided {@code oldDetails} is an ancestor of this one, and whether or
6142 * not this one grants it the provided capability, represented by the {@code flags}
6143 * parameter. In the event of signing certificate rotation, a package may still interact
6144 * with entities signed by its old signing certificate and not want to break previously
6145 * functioning behavior. The {@code flags} value determines which capabilities the app
6146 * signed by the newer signing certificate would like to continue to give to its previous
6147 * signing certificate(s).
6148 */
6149 public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) {
6150 if (this == UNKNOWN || oldDetails == UNKNOWN) {
6151 return false;
6152 }
6153 if (oldDetails.signatures.length > 1) {
6154
6155 // multiple-signer packages cannot rotate signing certs, so we must have an exact
6156 // match, which also means all capabilities are granted
6157 return signaturesMatchExactly(oldDetails);
6158 } else {
6159
6160 // we may have signing certificate rotation history, check to see if the oldDetails
6161 // was one of our old signing certificates, and if we grant it the capability it's
6162 // requesting
6163 return hasCertificate(oldDetails.signatures[0], flags);
6164 }
6165 }
6166
6167 /**
6168 * A special case of {@code checkCapability} which re-encodes both sets of signing
6169 * certificates to counteract a previous re-encoding.
6170 */
6171 public boolean checkCapabilityRecover(SigningDetails oldDetails,
6172 @CertCapabilities int flags) throws CertificateException {
6173 if (oldDetails == UNKNOWN || this == UNKNOWN) {
6174 return false;
6175 }
6176 if (hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
6177
6178 // signing certificates may have rotated, check entire history for effective match
6179 for (int i = 0; i < pastSigningCertificates.length; i++) {
6180 if (Signature.areEffectiveMatch(
6181 oldDetails.signatures[0],
6182 pastSigningCertificates[i])
Michael Groovera117b0d2018-07-23 12:55:54 -07006183 && pastSigningCertificates[i].getFlags() == flags) {
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006184 return true;
6185 }
6186 }
6187 } else {
6188 return Signature.areEffectiveMatch(oldDetails.signatures, signatures);
6189 }
6190 return false;
6191 }
6192
6193 /**
6194 * Determine if {@code signature} is in this SigningDetails' signing certificate history,
6195 * including the current signer. Automatically returns false if this object has multiple
6196 * signing certificates, since rotation is only supported for single-signers; this is
6197 * enforced by {@code hasCertificateInternal}.
6198 */
6199 public boolean hasCertificate(Signature signature) {
6200 return hasCertificateInternal(signature, PAST_CERT_EXISTS);
6201 }
6202
6203 /**
6204 * Determine if {@code signature} is in this SigningDetails' signing certificate history,
6205 * including the current signer, and whether or not it has the given permission.
6206 * Certificates which match our current signer automatically get all capabilities.
6207 * Automatically returns false if this object has multiple signing certificates, since
6208 * rotation is only supported for single-signers.
6209 */
6210 public boolean hasCertificate(Signature signature, @CertCapabilities int flags) {
6211 return hasCertificateInternal(signature, flags);
6212 }
6213
6214 /** Convenient wrapper for calling {@code hasCertificate} with certificate's raw bytes. */
6215 public boolean hasCertificate(byte[] certificate) {
6216 Signature signature = new Signature(certificate);
6217 return hasCertificate(signature);
6218 }
6219
6220 private boolean hasCertificateInternal(Signature signature, int flags) {
6221 if (this == UNKNOWN) {
6222 return false;
6223 }
6224
6225 // only single-signed apps can have pastSigningCertificates
6226 if (hasPastSigningCertificates()) {
6227
6228 // check all past certs, except for the current one, which automatically gets all
6229 // capabilities, since it is the same as the current signature
6230 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
6231 if (pastSigningCertificates[i].equals(signature)) {
6232 if (flags == PAST_CERT_EXISTS
Michael Groovera117b0d2018-07-23 12:55:54 -07006233 || (flags & pastSigningCertificates[i].getFlags()) == flags) {
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006234 return true;
6235 }
6236 }
6237 }
6238 }
6239
6240 // not in previous certs signing history, just check the current signer and make sure
6241 // we are singly-signed
6242 return signatures.length == 1 && signatures[0].equals(signature);
6243 }
6244
6245 /**
6246 * Determines if the provided {@code sha256String} is an ancestor of this one, and whether
6247 * or not this one grants it the provided capability, represented by the {@code flags}
6248 * parameter. In the event of signing certificate rotation, a package may still interact
6249 * with entities signed by its old signing certificate and not want to break previously
6250 * functioning behavior. The {@code flags} value determines which capabilities the app
6251 * signed by the newer signing certificate would like to continue to give to its previous
6252 * signing certificate(s).
6253 *
6254 * @param sha256String A hex-encoded representation of a sha256 digest. In the case of an
6255 * app with multiple signers, this represents the hex-encoded sha256
6256 * digest of the combined hex-encoded sha256 digests of each individual
6257 * signing certificate according to {@link
6258 * PackageUtils#computeSignaturesSha256Digest(Signature[])}
6259 */
6260 public boolean checkCapability(String sha256String, @CertCapabilities int flags) {
6261 if (this == UNKNOWN) {
6262 return false;
6263 }
6264
6265 // first see if the hash represents a single-signer in our signing history
Neil Fuller2c7cc6e2019-04-11 11:04:06 +01006266 byte[] sha256Bytes = sha256String == null
6267 ? null : HexEncoding.decode(sha256String, false /* allowSingleChar */);
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006268 if (hasSha256Certificate(sha256Bytes, flags)) {
6269 return true;
6270 }
6271
6272 // Not in signing history, either represents multiple signatures or not a match.
6273 // Multiple signers can't rotate, so no need to check flags, just see if the SHAs match.
6274 // We already check the single-signer case above as part of hasSha256Certificate, so no
6275 // need to verify we have multiple signers, just run the old check
6276 // just consider current signing certs
6277 final String[] mSignaturesSha256Digests =
6278 PackageUtils.computeSignaturesSha256Digests(signatures);
6279 final String mSignaturesSha256Digest =
6280 PackageUtils.computeSignaturesSha256Digest(mSignaturesSha256Digests);
6281 return mSignaturesSha256Digest.equals(sha256String);
6282 }
6283
6284 /**
6285 * Determine if the {@code sha256Certificate} is in this SigningDetails' signing certificate
6286 * history, including the current signer. Automatically returns false if this object has
6287 * multiple signing certificates, since rotation is only supported for single-signers.
6288 */
6289 public boolean hasSha256Certificate(byte[] sha256Certificate) {
6290 return hasSha256CertificateInternal(sha256Certificate, PAST_CERT_EXISTS);
6291 }
6292
6293 /**
6294 * Determine if the {@code sha256Certificate} certificate hash corresponds to a signing
6295 * certificate in this SigningDetails' signing certificate history, including the current
6296 * signer, and whether or not it has the given permission. Certificates which match our
6297 * current signer automatically get all capabilities. Automatically returns false if this
6298 * object has multiple signing certificates, since rotation is only supported for
6299 * single-signers.
6300 */
6301 public boolean hasSha256Certificate(byte[] sha256Certificate, @CertCapabilities int flags) {
6302 return hasSha256CertificateInternal(sha256Certificate, flags);
6303 }
6304
6305 private boolean hasSha256CertificateInternal(byte[] sha256Certificate, int flags) {
6306 if (this == UNKNOWN) {
6307 return false;
6308 }
6309 if (hasPastSigningCertificates()) {
6310
6311 // check all past certs, except for the last one, which automatically gets all
6312 // capabilities, since it is the same as the current signature, and is checked below
6313 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
6314 byte[] digest = PackageUtils.computeSha256DigestBytes(
6315 pastSigningCertificates[i].toByteArray());
6316 if (Arrays.equals(sha256Certificate, digest)) {
6317 if (flags == PAST_CERT_EXISTS
Michael Groovera117b0d2018-07-23 12:55:54 -07006318 || (flags & pastSigningCertificates[i].getFlags()) == flags) {
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006319 return true;
6320 }
6321 }
6322 }
6323 }
6324
6325 // not in previous certs signing history, just check the current signer
6326 if (signatures.length == 1) {
6327 byte[] digest =
6328 PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray());
6329 return Arrays.equals(sha256Certificate, digest);
6330 }
6331 return false;
6332 }
6333
Patrick Baumann47117fc2017-12-19 10:17:21 -08006334 /** Returns true if the signatures in this and other match exactly. */
6335 public boolean signaturesMatchExactly(SigningDetails other) {
6336 return Signature.areExactMatch(this.signatures, other.signatures);
6337 }
6338
6339 @Override
6340 public int describeContents() {
6341 return 0;
6342 }
6343
6344 @Override
6345 public void writeToParcel(Parcel dest, int flags) {
6346 boolean isUnknown = UNKNOWN == this;
6347 dest.writeBoolean(isUnknown);
6348 if (isUnknown) {
6349 return;
6350 }
6351 dest.writeTypedArray(this.signatures, flags);
6352 dest.writeInt(this.signatureSchemeVersion);
6353 dest.writeArraySet(this.publicKeys);
Daniel Cashman77029c52018-01-18 16:19:29 -08006354 dest.writeTypedArray(this.pastSigningCertificates, flags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006355 }
6356
6357 protected SigningDetails(Parcel in) {
6358 final ClassLoader boot = Object.class.getClassLoader();
6359 this.signatures = in.createTypedArray(Signature.CREATOR);
6360 this.signatureSchemeVersion = in.readInt();
6361 this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot);
Daniel Cashman77029c52018-01-18 16:19:29 -08006362 this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006363 }
6364
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07006365 public static final @android.annotation.NonNull Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() {
Patrick Baumann47117fc2017-12-19 10:17:21 -08006366 @Override
6367 public SigningDetails createFromParcel(Parcel source) {
6368 if (source.readBoolean()) {
6369 return UNKNOWN;
6370 }
6371 return new SigningDetails(source);
6372 }
6373
6374 @Override
6375 public SigningDetails[] newArray(int size) {
6376 return new SigningDetails[size];
6377 }
6378 };
6379
6380 @Override
6381 public boolean equals(Object o) {
6382 if (this == o) return true;
6383 if (!(o instanceof SigningDetails)) return false;
6384
6385 SigningDetails that = (SigningDetails) o;
6386
6387 if (signatureSchemeVersion != that.signatureSchemeVersion) return false;
6388 if (!Signature.areExactMatch(signatures, that.signatures)) return false;
Daniel Cashman77029c52018-01-18 16:19:29 -08006389 if (publicKeys != null) {
6390 if (!publicKeys.equals((that.publicKeys))) {
6391 return false;
6392 }
6393 } else if (that.publicKeys != null) {
6394 return false;
6395 }
6396
6397 // can't use Signature.areExactMatch() because order matters with the past signing certs
6398 if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) {
6399 return false;
6400 }
Daniel Cashman77029c52018-01-18 16:19:29 -08006401
6402 return true;
Patrick Baumann47117fc2017-12-19 10:17:21 -08006403 }
6404
6405 @Override
6406 public int hashCode() {
6407 int result = +Arrays.hashCode(signatures);
6408 result = 31 * result + signatureSchemeVersion;
6409 result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0);
Daniel Cashman77029c52018-01-18 16:19:29 -08006410 result = 31 * result + Arrays.hashCode(pastSigningCertificates);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006411 return result;
6412 }
Daniel Cashman77029c52018-01-18 16:19:29 -08006413
6414 /**
6415 * Builder of {@code SigningDetails} instances.
6416 */
6417 public static class Builder {
6418 private Signature[] mSignatures;
6419 private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
6420 private Signature[] mPastSigningCertificates;
Daniel Cashman77029c52018-01-18 16:19:29 -08006421
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006422 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006423 public Builder() {
6424 }
6425
6426 /** get signing certificates used to sign the current APK */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006427 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006428 public Builder setSignatures(Signature[] signatures) {
6429 mSignatures = signatures;
6430 return this;
6431 }
6432
6433 /** set the signature scheme version used to sign the APK */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006434 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006435 public Builder setSignatureSchemeVersion(int signatureSchemeVersion) {
6436 mSignatureSchemeVersion = signatureSchemeVersion;
6437 return this;
6438 }
6439
6440 /** set the signing certificates by which the APK proved it can be authenticated */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006441 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006442 public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
6443 mPastSigningCertificates = pastSigningCertificates;
6444 return this;
6445 }
6446
Daniel Cashman77029c52018-01-18 16:19:29 -08006447 private void checkInvariants() {
6448 // must have signatures and scheme version set
6449 if (mSignatures == null) {
6450 throw new IllegalStateException("SigningDetails requires the current signing"
6451 + " certificates.");
6452 }
Daniel Cashman77029c52018-01-18 16:19:29 -08006453 }
6454 /** build a {@code SigningDetails} object */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006455 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006456 public SigningDetails build()
6457 throws CertificateException {
6458 checkInvariants();
6459 return new SigningDetails(mSignatures, mSignatureSchemeVersion,
Michael Groovera117b0d2018-07-23 12:55:54 -07006460 mPastSigningCertificates);
Daniel Cashman77029c52018-01-18 16:19:29 -08006461 }
6462 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08006463 }
6464
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006465 /**
6466 * Representation of a full package parsed from APK files on disk. A package
6467 * consists of a single base APK, and zero or more split APKs.
6468 */
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006469 public final static class Package implements Parcelable {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006470
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006471 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006472 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006473
Svet Ganov67882122016-12-11 16:36:34 -08006474 // The package name declared in the manifest as the package can be
6475 // renamed, for example static shared libs use synthetic package names.
6476 public String manifestPackageName;
6477
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006478 /** Names of any split APKs, ordered by parsed splitName */
6479 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006480
6481 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07006482
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07006483 public String volumeUuid;
6484
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006485 /**
6486 * Path where this package was found on disk. For monolithic packages
6487 * this is path to single base APK file; for cluster packages this is
6488 * path to the cluster directory.
6489 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006490 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006491
6492 /** Path of base APK */
6493 public String baseCodePath;
6494 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006495 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006496
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006497 /** Revision code of base APK */
6498 public int baseRevisionCode;
6499 /** Revision codes of any split APKs, ordered by parsed splitName */
6500 public int[] splitRevisionCodes;
6501
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006502 /** Flags of any split APKs; ordered by parsed splitName */
6503 public int[] splitFlags;
6504
Alex Klyubinb9f8a522015-02-03 11:12:59 -08006505 /**
6506 * Private flags of any split APKs; ordered by parsed splitName.
6507 *
6508 * {@hide}
6509 */
6510 public int[] splitPrivateFlags;
6511
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006512 public boolean baseHardwareAccelerated;
6513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006514 // For now we only support one application per package.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006515 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006516 public ApplicationInfo applicationInfo = new ApplicationInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006517
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006518 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006519 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006520 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006521 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006522 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006524 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006525 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006526 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006527 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006528 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006529 public final ArrayList<Service> services = new ArrayList<Service>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006530 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006531 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
6532
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006533 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006534 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
6535
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07006536 /** Permissions requested but not in the manifest. */
6537 public final ArrayList<String> implicitPermissions = new ArrayList<>();
6538
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006539 @UnsupportedAppUsage
Dianne Hackborn854060af2009-07-09 18:14:31 -07006540 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006541
Svet Ganov354cd3c2015-12-17 11:35:04 -08006542 public Package parentPackage;
6543 public ArrayList<Package> childPackages;
6544
Svet Ganov67882122016-12-11 16:36:34 -08006545 public String staticSharedLibName = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006546 public long staticSharedLibVersion = 0;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006547 public ArrayList<String> libraryNames = null;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006548 @UnsupportedAppUsage
Dianne Hackborn49237342009-08-27 20:08:01 -07006549 public ArrayList<String> usesLibraries = null;
Svet Ganov67882122016-12-11 16:36:34 -08006550 public ArrayList<String> usesStaticLibraries = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006551 public long[] usesStaticLibrariesVersions = null;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006552 public String[][] usesStaticLibrariesCertDigests = null;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006553 @UnsupportedAppUsage
Dianne Hackborn49237342009-08-27 20:08:01 -07006554 public ArrayList<String> usesOptionalLibraries = null;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006555 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006556 public String[] usesLibraryFiles = null;
Nicolas Geoffrayabcd58e2018-10-22 10:23:50 +01006557 public ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006558
Dianne Hackbornb09491f2013-07-22 15:30:11 -07006559 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
6560
Dianne Hackbornc1552392010-03-03 16:19:01 -08006561 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006562 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006563 public ArrayList<String> mAdoptPermissions = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006565 // We store the application meta-data independently to avoid multiple unwanted references
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006566 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006567 public Bundle mAppMetaData = null;
6568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006569 // The version code declared for this package.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006570 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006571 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006572
Dianne Hackborn3accca02013-09-20 09:32:11 -07006573 // The major version code declared for this package.
6574 public int mVersionCodeMajor;
6575
6576 // Return long containing mVersionCode and mVersionCodeMajor.
6577 public long getLongVersionCode() {
6578 return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
6579 }
6580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006581 // The version name declared for this package.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006582 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006583 public String mVersionName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006585 // The shared user id that this package wants to use.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006586 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006587 public String mSharedUserId;
6588
6589 // The shared user label that this package wants to use.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006590 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006591 public int mSharedUserLabel;
6592
6593 // Signatures that were read from the package.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006594 @UnsupportedAppUsage
Patrick Baumann47117fc2017-12-19 10:17:21 -08006595 @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006596
6597 // For use by package manager service for quick lookup of
6598 // preferred up order.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006599 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006600 public int mPreferredOrder = 0;
6601
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006602 // For use by package manager to keep track of when a package was last used.
Brian Carlstromca82e612016-04-19 23:16:08 -07006603 public long[] mLastPackageUsageTimeInMills =
6604 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006605
Amith Yamasani13593602012-03-22 16:16:17 -07006606 // // User set enabled state.
6607 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
6608 //
6609 // // Whether the package has been stopped.
6610 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08006611
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006612 // Additional data supplied by callers.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006613 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006614 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07006615
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006616 // Applications hardware preferences
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006617 @UnsupportedAppUsage
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006618 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006619
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006620 // Applications requested features
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006621 @UnsupportedAppUsage
Dianne Hackborn49237342009-08-27 20:08:01 -07006622 public ArrayList<FeatureInfo> reqFeatures = null;
6623
Adam Lesinskid3edfde2014-08-08 17:32:44 -07006624 // Applications requested feature groups
6625 public ArrayList<FeatureGroupInfo> featureGroups = null;
6626
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006627 @UnsupportedAppUsage
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08006628 public int installLocation;
6629
Jeff Hao272bf3a2014-10-08 13:34:43 -07006630 public boolean coreApp;
6631
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08006632 /* An app that's required for all users and cannot be uninstalled for a user */
6633 public boolean mRequiredForAllUsers;
6634
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006635 /* The restricted account authenticator type that is used by this application */
6636 public String mRestrictedAccountType;
6637
Amith Yamasaniccbe3892013-04-12 17:52:42 -07006638 /* The required account type without which this application will not function */
6639 public String mRequiredAccountType;
6640
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006641 public String mOverlayTarget;
Ryan Mitchella3628462019-01-14 12:19:40 -08006642 public String mOverlayTargetName;
Adrian Roosc84df772018-01-19 21:20:22 +01006643 public String mOverlayCategory;
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006644 public int mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -08006645 public boolean mOverlayIsStatic;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006646
Alan Viveretteb6a25732017-11-21 14:49:24 -05006647 public int mCompileSdkVersion;
6648 public String mCompileSdkVersionCodename;
6649
Geremy Condraf1bcca82013-01-07 22:35:24 -08006650 /**
dcashman989eb3712014-06-17 12:56:12 -07006651 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08006652 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006653 @UnsupportedAppUsage
dcashman989eb3712014-06-17 12:56:12 -07006654 public ArraySet<String> mUpgradeKeySets;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006655 @UnsupportedAppUsage
dcashman989eb3712014-06-17 12:56:12 -07006656 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08006657
Narayan Kamath4903f642014-08-11 13:33:45 +01006658 /**
6659 * The install time abi override for this package, if any.
6660 *
6661 * TODO: This seems like a horrible place to put the abiOverride because
6662 * this isn't something the packageParser parsers. However, this fits in with
6663 * the rest of the PackageManager where package scanning randomly pushes
6664 * and prods fields out of {@code this.applicationInfo}.
6665 */
6666 public String cpuAbiOverride;
Selim Gurun2d291d82016-02-05 17:50:53 -08006667 /**
6668 * The install time abi override to choose 32bit abi's when multiple abi's
6669 * are present. This is only meaningfull for multiarch applications.
6670 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
6671 */
6672 public boolean use32bitAbi;
Narayan Kamath4903f642014-08-11 13:33:45 +01006673
Todd Kennedyfdd241a2016-04-28 12:26:53 -07006674 public byte[] restrictUpdateHash;
6675
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006676 /** Set if the app or any of its components are visible to instant applications. */
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006677 public boolean visibleToInstantApps;
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006678 /** Whether or not the package is a stub and must be replaced by the full version. */
6679 public boolean isStub;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006680
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006681 @UnsupportedAppUsage
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006682 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006683 this.packageName = packageName;
Svet Ganov67882122016-12-11 16:36:34 -08006684 this.manifestPackageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006685 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006686 applicationInfo.uid = -1;
6687 }
6688
Svet Ganov354cd3c2015-12-17 11:35:04 -08006689 public void setApplicationVolumeUuid(String volumeUuid) {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006690 final UUID storageUuid = StorageManager.convert(volumeUuid);
Svet Ganov354cd3c2015-12-17 11:35:04 -08006691 this.applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006692 this.applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006693 if (childPackages != null) {
6694 final int packageCount = childPackages.size();
6695 for (int i = 0; i < packageCount; i++) {
6696 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006697 childPackages.get(i).applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006698 }
6699 }
6700 }
6701
6702 public void setApplicationInfoCodePath(String codePath) {
6703 this.applicationInfo.setCodePath(codePath);
6704 if (childPackages != null) {
6705 final int packageCount = childPackages.size();
6706 for (int i = 0; i < packageCount; i++) {
6707 childPackages.get(i).applicationInfo.setCodePath(codePath);
6708 }
6709 }
6710 }
6711
Todd Kennedy30a23a52018-01-04 13:27:49 -08006712 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6713 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006714 public void setApplicationInfoResourcePath(String resourcePath) {
6715 this.applicationInfo.setResourcePath(resourcePath);
6716 if (childPackages != null) {
6717 final int packageCount = childPackages.size();
6718 for (int i = 0; i < packageCount; i++) {
6719 childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
6720 }
6721 }
6722 }
6723
Todd Kennedy30a23a52018-01-04 13:27:49 -08006724 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6725 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006726 public void setApplicationInfoBaseResourcePath(String resourcePath) {
6727 this.applicationInfo.setBaseResourcePath(resourcePath);
6728 if (childPackages != null) {
6729 final int packageCount = childPackages.size();
6730 for (int i = 0; i < packageCount; i++) {
6731 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
6732 }
6733 }
6734 }
6735
6736 public void setApplicationInfoBaseCodePath(String baseCodePath) {
6737 this.applicationInfo.setBaseCodePath(baseCodePath);
6738 if (childPackages != null) {
6739 final int packageCount = childPackages.size();
6740 for (int i = 0; i < packageCount; i++) {
6741 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
6742 }
6743 }
6744 }
6745
Todd Kennedy13715d52016-08-01 13:38:57 -07006746 public List<String> getChildPackageNames() {
6747 if (childPackages == null) {
6748 return null;
6749 }
6750 final int childCount = childPackages.size();
6751 final List<String> childPackageNames = new ArrayList<>(childCount);
6752 for (int i = 0; i < childCount; i++) {
6753 String childPackageName = childPackages.get(i).packageName;
6754 childPackageNames.add(childPackageName);
6755 }
6756 return childPackageNames;
6757 }
6758
Svet Ganov354cd3c2015-12-17 11:35:04 -08006759 public boolean hasChildPackage(String packageName) {
6760 final int childCount = (childPackages != null) ? childPackages.size() : 0;
6761 for (int i = 0; i < childCount; i++) {
6762 if (childPackages.get(i).packageName.equals(packageName)) {
6763 return true;
6764 }
6765 }
6766 return false;
6767 }
6768
6769 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
6770 this.applicationInfo.setSplitCodePaths(splitCodePaths);
6771 // Children have no splits
6772 }
6773
Todd Kennedy30a23a52018-01-04 13:27:49 -08006774 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6775 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006776 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
6777 this.applicationInfo.setSplitResourcePaths(resroucePaths);
6778 // Children have no splits
6779 }
6780
6781 public void setSplitCodePaths(String[] codePaths) {
6782 this.splitCodePaths = codePaths;
6783 }
6784
6785 public void setCodePath(String codePath) {
6786 this.codePath = codePath;
6787 if (childPackages != null) {
6788 final int packageCount = childPackages.size();
6789 for (int i = 0; i < packageCount; i++) {
6790 childPackages.get(i).codePath = codePath;
6791 }
6792 }
6793 }
6794
6795 public void setBaseCodePath(String baseCodePath) {
6796 this.baseCodePath = baseCodePath;
6797 if (childPackages != null) {
6798 final int packageCount = childPackages.size();
6799 for (int i = 0; i < packageCount; i++) {
6800 childPackages.get(i).baseCodePath = baseCodePath;
6801 }
6802 }
6803 }
6804
Patrick Baumann47117fc2017-12-19 10:17:21 -08006805 /** Sets signing details on the package and any of its children. */
6806 public void setSigningDetails(@NonNull SigningDetails signingDetails) {
6807 mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006808 if (childPackages != null) {
6809 final int packageCount = childPackages.size();
6810 for (int i = 0; i < packageCount; i++) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08006811 childPackages.get(i).mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006812 }
6813 }
6814 }
6815
6816 public void setVolumeUuid(String volumeUuid) {
6817 this.volumeUuid = volumeUuid;
6818 if (childPackages != null) {
6819 final int packageCount = childPackages.size();
6820 for (int i = 0; i < packageCount; i++) {
6821 childPackages.get(i).volumeUuid = volumeUuid;
6822 }
6823 }
6824 }
6825
6826 public void setApplicationInfoFlags(int mask, int flags) {
6827 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
6828 if (childPackages != null) {
6829 final int packageCount = childPackages.size();
6830 for (int i = 0; i < packageCount; i++) {
6831 childPackages.get(i).applicationInfo.flags =
6832 (applicationInfo.flags & ~mask) | (mask & flags);
6833 }
6834 }
6835 }
6836
Selim Gurun75827b22016-02-09 10:55:33 -08006837 public void setUse32bitAbi(boolean use32bitAbi) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006838 this.use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006839 if (childPackages != null) {
6840 final int packageCount = childPackages.size();
6841 for (int i = 0; i < packageCount; i++) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006842 childPackages.get(i).use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006843 }
6844 }
6845 }
6846
Svetoslav Ganov40610e32017-06-20 19:35:51 -07006847 public boolean isLibrary() {
6848 return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
6849 }
6850
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006851 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07006852 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006853 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07006854 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6855 Collections.addAll(paths, splitCodePaths);
6856 }
6857 return paths;
6858 }
6859
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006860 /**
6861 * Filtered set of {@link #getAllCodePaths()} that excludes
6862 * resource-only APKs.
6863 */
6864 public List<String> getAllCodePathsExcludingResourceOnly() {
6865 ArrayList<String> paths = new ArrayList<>();
6866 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6867 paths.add(baseCodePath);
6868 }
6869 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6870 for (int i = 0; i < splitCodePaths.length; i++) {
6871 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6872 paths.add(splitCodePaths[i]);
6873 }
6874 }
6875 }
6876 return paths;
6877 }
6878
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006879 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006880 public void setPackageName(String newName) {
6881 packageName = newName;
6882 applicationInfo.packageName = newName;
6883 for (int i=permissions.size()-1; i>=0; i--) {
6884 permissions.get(i).setPackageName(newName);
6885 }
6886 for (int i=permissionGroups.size()-1; i>=0; i--) {
6887 permissionGroups.get(i).setPackageName(newName);
6888 }
6889 for (int i=activities.size()-1; i>=0; i--) {
6890 activities.get(i).setPackageName(newName);
6891 }
6892 for (int i=receivers.size()-1; i>=0; i--) {
6893 receivers.get(i).setPackageName(newName);
6894 }
6895 for (int i=providers.size()-1; i>=0; i--) {
6896 providers.get(i).setPackageName(newName);
6897 }
6898 for (int i=services.size()-1; i>=0; i--) {
6899 services.get(i).setPackageName(newName);
6900 }
6901 for (int i=instrumentation.size()-1; i>=0; i--) {
6902 instrumentation.get(i).setPackageName(newName);
6903 }
6904 }
Dianne Hackborn65696252012-03-05 18:49:21 -08006905
6906 public boolean hasComponentClassName(String name) {
6907 for (int i=activities.size()-1; i>=0; i--) {
6908 if (name.equals(activities.get(i).className)) {
6909 return true;
6910 }
6911 }
6912 for (int i=receivers.size()-1; i>=0; i--) {
6913 if (name.equals(receivers.get(i).className)) {
6914 return true;
6915 }
6916 }
6917 for (int i=providers.size()-1; i>=0; i--) {
6918 if (name.equals(providers.get(i).className)) {
6919 return true;
6920 }
6921 }
6922 for (int i=services.size()-1; i>=0; i--) {
6923 if (name.equals(services.get(i).className)) {
6924 return true;
6925 }
6926 }
6927 for (int i=instrumentation.size()-1; i>=0; i--) {
6928 if (name.equals(instrumentation.get(i).className)) {
6929 return true;
6930 }
6931 }
6932 return false;
6933 }
6934
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006935 /** @hide */
6936 public boolean isExternal() {
6937 return applicationInfo.isExternal();
6938 }
6939
6940 /** @hide */
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08006941 public boolean isForwardLocked() {
Patrick Baumannfc2851e2018-11-13 15:23:22 -08006942 return false;
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08006943 }
6944
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006945 /** @hide */
6946 public boolean isOem() {
6947 return applicationInfo.isOem();
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006948 }
6949
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006950 /** @hide */
Jiyong Park002fdbd2017-02-13 20:50:31 +09006951 public boolean isVendor() {
6952 return applicationInfo.isVendor();
6953 }
6954
6955 /** @hide */
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09006956 public boolean isProduct() {
6957 return applicationInfo.isProduct();
6958 }
6959
6960 /** @hide */
Jeongik Chaf6629832019-07-04 21:12:06 +09006961 public boolean isSystemExt() {
6962 return applicationInfo.isSystemExt();
Dario Freni2bef1762018-06-01 14:02:08 +01006963 }
6964
6965 /** @hide */
MÃ¥rten Kongstad48c24cf2019-02-25 10:54:09 +01006966 public boolean isOdm() {
6967 return applicationInfo.isOdm();
6968 }
6969
6970 /** @hide */
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006971 public boolean isPrivileged() {
Svet Ganovadc1cf42015-06-15 16:36:24 -07006972 return applicationInfo.isPrivilegedApp();
6973 }
6974
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006975 /** @hide */
6976 public boolean isSystem() {
6977 return applicationInfo.isSystemApp();
6978 }
6979
6980 /** @hide */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006981 public boolean isUpdatedSystemApp() {
6982 return applicationInfo.isUpdatedSystemApp();
6983 }
6984
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006985 /** @hide */
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006986 public boolean canHaveOatDir() {
6987 // The following app types CANNOT have oat directory
6988 // - non-updated system apps
Patrick Baumannfc2851e2018-11-13 15:23:22 -08006989 return !isSystem() || isUpdatedSystemApp();
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006990 }
6991
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006992 public boolean isMatch(int flags) {
6993 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006994 return isSystem();
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006995 }
6996 return true;
6997 }
6998
Brian Carlstromca82e612016-04-19 23:16:08 -07006999 public long getLatestPackageUseTimeInMills() {
7000 long latestUse = 0L;
7001 for (long use : mLastPackageUsageTimeInMills) {
7002 latestUse = Math.max(latestUse, use);
7003 }
7004 return latestUse;
7005 }
7006
David Brazdil90e26992016-04-18 14:08:52 +01007007 public long getLatestForegroundPackageUseTimeInMills() {
7008 int[] foregroundReasons = {
7009 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
7010 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
7011 };
7012
7013 long latestUse = 0L;
7014 for (int reason : foregroundReasons) {
7015 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
7016 }
7017 return latestUse;
7018 }
7019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007020 public String toString() {
7021 return "Package{"
7022 + Integer.toHexString(System.identityHashCode(this))
7023 + " " + packageName + "}";
7024 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007025
7026 @Override
7027 public int describeContents() {
7028 return 0;
7029 }
7030
7031 public Package(Parcel dest) {
7032 // We use the boot classloader for all classes that we load.
7033 final ClassLoader boot = Object.class.getClassLoader();
7034
Narayan Kamath07ac1442017-02-10 15:08:07 +00007035 packageName = dest.readString().intern();
Svet Ganov67882122016-12-11 16:36:34 -08007036 manifestPackageName = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007037 splitNames = dest.readStringArray();
7038 volumeUuid = dest.readString();
7039 codePath = dest.readString();
7040 baseCodePath = dest.readString();
7041 splitCodePaths = dest.readStringArray();
7042 baseRevisionCode = dest.readInt();
7043 splitRevisionCodes = dest.createIntArray();
7044 splitFlags = dest.createIntArray();
7045 splitPrivateFlags = dest.createIntArray();
7046 baseHardwareAccelerated = (dest.readInt() == 1);
7047 applicationInfo = dest.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007048 if (applicationInfo.permission != null) {
7049 applicationInfo.permission = applicationInfo.permission.intern();
7050 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007051
7052 // We don't serialize the "owner" package and the application info object for each of
7053 // these components, in order to save space and to avoid circular dependencies while
7054 // serialization. We need to fix them all up here.
7055 dest.readParcelableList(permissions, boot);
7056 fixupOwner(permissions);
7057 dest.readParcelableList(permissionGroups, boot);
7058 fixupOwner(permissionGroups);
7059 dest.readParcelableList(activities, boot);
7060 fixupOwner(activities);
7061 dest.readParcelableList(receivers, boot);
7062 fixupOwner(receivers);
7063 dest.readParcelableList(providers, boot);
7064 fixupOwner(providers);
7065 dest.readParcelableList(services, boot);
7066 fixupOwner(services);
7067 dest.readParcelableList(instrumentation, boot);
7068 fixupOwner(instrumentation);
7069
7070 dest.readStringList(requestedPermissions);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007071 internStringArrayList(requestedPermissions);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07007072 dest.readStringList(implicitPermissions);
7073 internStringArrayList(implicitPermissions);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007074 protectedBroadcasts = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007075 internStringArrayList(protectedBroadcasts);
7076
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007077 parentPackage = dest.readParcelable(boot);
7078
7079 childPackages = new ArrayList<>();
7080 dest.readParcelableList(childPackages, boot);
7081 if (childPackages.size() == 0) {
7082 childPackages = null;
7083 }
7084
Svet Ganov67882122016-12-11 16:36:34 -08007085 staticSharedLibName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007086 if (staticSharedLibName != null) {
7087 staticSharedLibName = staticSharedLibName.intern();
7088 }
Dianne Hackborn3accca02013-09-20 09:32:11 -07007089 staticSharedLibVersion = dest.readLong();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007090 libraryNames = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007091 internStringArrayList(libraryNames);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007092 usesLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007093 internStringArrayList(usesLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007094 usesOptionalLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007095 internStringArrayList(usesOptionalLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007096 usesLibraryFiles = dest.readStringArray();
7097
Nicolas Geoffrayabcd58e2018-10-22 10:23:50 +01007098 usesLibraryInfos = dest.createTypedArrayList(SharedLibraryInfo.CREATOR);
7099
Svet Ganov67882122016-12-11 16:36:34 -08007100 final int libCount = dest.readInt();
7101 if (libCount > 0) {
7102 usesStaticLibraries = new ArrayList<>(libCount);
7103 dest.readStringList(usesStaticLibraries);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007104 internStringArrayList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07007105 usesStaticLibrariesVersions = new long[libCount];
7106 dest.readLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07007107 usesStaticLibrariesCertDigests = new String[libCount][];
7108 for (int i = 0; i < libCount; i++) {
7109 usesStaticLibrariesCertDigests[i] = dest.createStringArray();
7110 }
Svet Ganov67882122016-12-11 16:36:34 -08007111 }
7112
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007113 preferredActivityFilters = new ArrayList<>();
7114 dest.readParcelableList(preferredActivityFilters, boot);
7115 if (preferredActivityFilters.size() == 0) {
7116 preferredActivityFilters = null;
7117 }
7118
7119 mOriginalPackages = dest.createStringArrayList();
7120 mRealPackage = dest.readString();
7121 mAdoptPermissions = dest.createStringArrayList();
7122 mAppMetaData = dest.readBundle();
7123 mVersionCode = dest.readInt();
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08007124 mVersionCodeMajor = dest.readInt();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007125 mVersionName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007126 if (mVersionName != null) {
7127 mVersionName = mVersionName.intern();
7128 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007129 mSharedUserId = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007130 if (mSharedUserId != null) {
7131 mSharedUserId = mSharedUserId.intern();
7132 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007133 mSharedUserLabel = dest.readInt();
7134
Patrick Baumann47117fc2017-12-19 10:17:21 -08007135 mSigningDetails = dest.readParcelable(boot);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007136
7137 mPreferredOrder = dest.readInt();
7138
7139 // long[] packageUsageTimeMillis is not persisted because it isn't information that
7140 // is parsed from the APK.
7141
7142 // Object mExtras is not persisted because it is not information that is read from
7143 // the APK, rather, it is supplied by callers.
7144
7145
7146 configPreferences = new ArrayList<>();
7147 dest.readParcelableList(configPreferences, boot);
7148 if (configPreferences.size() == 0) {
7149 configPreferences = null;
7150 }
7151
7152 reqFeatures = new ArrayList<>();
7153 dest.readParcelableList(reqFeatures, boot);
7154 if (reqFeatures.size() == 0) {
7155 reqFeatures = null;
7156 }
7157
7158 featureGroups = new ArrayList<>();
7159 dest.readParcelableList(featureGroups, boot);
7160 if (featureGroups.size() == 0) {
7161 featureGroups = null;
7162 }
7163
7164 installLocation = dest.readInt();
7165 coreApp = (dest.readInt() == 1);
7166 mRequiredForAllUsers = (dest.readInt() == 1);
7167 mRestrictedAccountType = dest.readString();
7168 mRequiredAccountType = dest.readString();
7169 mOverlayTarget = dest.readString();
Ryan Mitchella3628462019-01-14 12:19:40 -08007170 mOverlayTargetName = dest.readString();
Adrian Roosc84df772018-01-19 21:20:22 +01007171 mOverlayCategory = dest.readString();
Jaekyun Seok42d53f62017-04-10 13:48:58 +09007172 mOverlayPriority = dest.readInt();
Adam Lesinskie7334972018-01-17 16:13:52 -08007173 mOverlayIsStatic = (dest.readInt() == 1);
Alan Viveretteb6a25732017-11-21 14:49:24 -05007174 mCompileSdkVersion = dest.readInt();
7175 mCompileSdkVersionCodename = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007176 mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
7177
7178 mKeySetMapping = readKeySetMapping(dest);
7179
7180 cpuAbiOverride = dest.readString();
7181 use32bitAbi = (dest.readInt() == 1);
7182 restrictUpdateHash = dest.createByteArray();
Chad Brubaker49f24c62017-04-05 13:08:21 -07007183 visibleToInstantApps = dest.readInt() == 1;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007184 }
7185
Narayan Kamath07ac1442017-02-10 15:08:07 +00007186 private static void internStringArrayList(List<String> list) {
7187 if (list != null) {
7188 final int N = list.size();
7189 for (int i = 0; i < N; ++i) {
7190 list.set(i, list.get(i).intern());
7191 }
7192 }
7193 }
7194
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007195 /**
7196 * Sets the package owner and the the {@code applicationInfo} for every component
7197 * owner by this package.
7198 */
7199 private void fixupOwner(List<? extends Component<?>> list) {
7200 if (list != null) {
7201 for (Component<?> c : list) {
7202 c.owner = this;
7203 if (c instanceof Activity) {
7204 ((Activity) c).info.applicationInfo = this.applicationInfo;
7205 } else if (c instanceof Service) {
7206 ((Service) c).info.applicationInfo = this.applicationInfo;
7207 } else if (c instanceof Provider) {
7208 ((Provider) c).info.applicationInfo = this.applicationInfo;
7209 }
7210 }
7211 }
7212 }
7213
7214 @Override
7215 public void writeToParcel(Parcel dest, int flags) {
7216 dest.writeString(packageName);
Svet Ganov67882122016-12-11 16:36:34 -08007217 dest.writeString(manifestPackageName);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007218 dest.writeStringArray(splitNames);
7219 dest.writeString(volumeUuid);
7220 dest.writeString(codePath);
7221 dest.writeString(baseCodePath);
7222 dest.writeStringArray(splitCodePaths);
7223 dest.writeInt(baseRevisionCode);
7224 dest.writeIntArray(splitRevisionCodes);
7225 dest.writeIntArray(splitFlags);
7226 dest.writeIntArray(splitPrivateFlags);
7227 dest.writeInt(baseHardwareAccelerated ? 1 : 0);
7228 dest.writeParcelable(applicationInfo, flags);
7229
7230 dest.writeParcelableList(permissions, flags);
7231 dest.writeParcelableList(permissionGroups, flags);
7232 dest.writeParcelableList(activities, flags);
7233 dest.writeParcelableList(receivers, flags);
7234 dest.writeParcelableList(providers, flags);
7235 dest.writeParcelableList(services, flags);
7236 dest.writeParcelableList(instrumentation, flags);
7237
7238 dest.writeStringList(requestedPermissions);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07007239 dest.writeStringList(implicitPermissions);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007240 dest.writeStringList(protectedBroadcasts);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07007241
7242 // TODO: This doesn't work: b/64295061
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007243 dest.writeParcelable(parentPackage, flags);
7244 dest.writeParcelableList(childPackages, flags);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07007245
Svet Ganov67882122016-12-11 16:36:34 -08007246 dest.writeString(staticSharedLibName);
Dianne Hackborn3accca02013-09-20 09:32:11 -07007247 dest.writeLong(staticSharedLibVersion);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007248 dest.writeStringList(libraryNames);
7249 dest.writeStringList(usesLibraries);
7250 dest.writeStringList(usesOptionalLibraries);
7251 dest.writeStringArray(usesLibraryFiles);
Nicolas Geoffrayabcd58e2018-10-22 10:23:50 +01007252 dest.writeTypedList(usesLibraryInfos);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007253
Svet Ganov67882122016-12-11 16:36:34 -08007254 if (ArrayUtils.isEmpty(usesStaticLibraries)) {
7255 dest.writeInt(-1);
7256 } else {
7257 dest.writeInt(usesStaticLibraries.size());
7258 dest.writeStringList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07007259 dest.writeLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07007260 for (String[] usesStaticLibrariesCertDigest : usesStaticLibrariesCertDigests) {
7261 dest.writeStringArray(usesStaticLibrariesCertDigest);
7262 }
Svet Ganov67882122016-12-11 16:36:34 -08007263 }
7264
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007265 dest.writeParcelableList(preferredActivityFilters, flags);
7266
7267 dest.writeStringList(mOriginalPackages);
7268 dest.writeString(mRealPackage);
7269 dest.writeStringList(mAdoptPermissions);
7270 dest.writeBundle(mAppMetaData);
7271 dest.writeInt(mVersionCode);
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08007272 dest.writeInt(mVersionCodeMajor);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007273 dest.writeString(mVersionName);
7274 dest.writeString(mSharedUserId);
7275 dest.writeInt(mSharedUserLabel);
7276
Patrick Baumann47117fc2017-12-19 10:17:21 -08007277 dest.writeParcelable(mSigningDetails, flags);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007278
7279 dest.writeInt(mPreferredOrder);
7280
7281 // long[] packageUsageTimeMillis is not persisted because it isn't information that
7282 // is parsed from the APK.
7283
7284 // Object mExtras is not persisted because it is not information that is read from
7285 // the APK, rather, it is supplied by callers.
7286
7287 dest.writeParcelableList(configPreferences, flags);
7288 dest.writeParcelableList(reqFeatures, flags);
7289 dest.writeParcelableList(featureGroups, flags);
7290
7291 dest.writeInt(installLocation);
7292 dest.writeInt(coreApp ? 1 : 0);
7293 dest.writeInt(mRequiredForAllUsers ? 1 : 0);
7294 dest.writeString(mRestrictedAccountType);
7295 dest.writeString(mRequiredAccountType);
7296 dest.writeString(mOverlayTarget);
Ryan Mitchella3628462019-01-14 12:19:40 -08007297 dest.writeString(mOverlayTargetName);
Adrian Roosc84df772018-01-19 21:20:22 +01007298 dest.writeString(mOverlayCategory);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09007299 dest.writeInt(mOverlayPriority);
Adam Lesinskie7334972018-01-17 16:13:52 -08007300 dest.writeInt(mOverlayIsStatic ? 1 : 0);
Alan Viveretteb6a25732017-11-21 14:49:24 -05007301 dest.writeInt(mCompileSdkVersion);
7302 dest.writeString(mCompileSdkVersionCodename);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007303 dest.writeArraySet(mUpgradeKeySets);
7304 writeKeySetMapping(dest, mKeySetMapping);
7305 dest.writeString(cpuAbiOverride);
7306 dest.writeInt(use32bitAbi ? 1 : 0);
7307 dest.writeByteArray(restrictUpdateHash);
Chad Brubaker49f24c62017-04-05 13:08:21 -07007308 dest.writeInt(visibleToInstantApps ? 1 : 0);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007309 }
7310
7311
7312 /**
7313 * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
7314 */
7315 private static void writeKeySetMapping(
7316 Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
7317 if (keySetMapping == null) {
7318 dest.writeInt(-1);
7319 return;
7320 }
7321
7322 final int N = keySetMapping.size();
7323 dest.writeInt(N);
7324
7325 for (int i = 0; i < N; i++) {
7326 dest.writeString(keySetMapping.keyAt(i));
7327 ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
7328 if (keys == null) {
7329 dest.writeInt(-1);
7330 continue;
7331 }
7332
7333 final int M = keys.size();
7334 dest.writeInt(M);
7335 for (int j = 0; j < M; j++) {
7336 dest.writeSerializable(keys.valueAt(j));
7337 }
7338 }
7339 }
7340
7341 /**
7342 * Reads a keyset mapping from the given parcel at the given data position. May return
7343 * {@code null} if the serialized mapping was {@code null}.
7344 */
7345 private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
7346 final int N = in.readInt();
7347 if (N == -1) {
7348 return null;
7349 }
7350
7351 ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
7352 for (int i = 0; i < N; ++i) {
7353 String key = in.readString();
7354 final int M = in.readInt();
7355 if (M == -1) {
7356 keySetMapping.put(key, null);
7357 continue;
7358 }
7359
7360 ArraySet<PublicKey> keys = new ArraySet<>(M);
7361 for (int j = 0; j < M; ++j) {
7362 PublicKey pk = (PublicKey) in.readSerializable();
7363 keys.add(pk);
7364 }
7365
7366 keySetMapping.put(key, keys);
7367 }
7368
7369 return keySetMapping;
7370 }
7371
7372 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
7373 public Package createFromParcel(Parcel in) {
7374 return new Package(in);
7375 }
7376
7377 public Package[] newArray(int size) {
7378 return new Package[size];
7379 }
7380 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007381 }
7382
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007383 public static abstract class Component<II extends IntentInfo> {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007384 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007385 public final ArrayList<II> intents;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007386 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007387 public final String className;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007388
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007389 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390 public Bundle metaData;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007391 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007392 public Package owner;
Todd Kennedy6d418b62018-02-22 14:15:18 -08007393 /** The order of this component in relation to its peers */
7394 public int order;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007395
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007396 ComponentName componentName;
7397 String componentShortName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007398
Ricky Waicf134eb2018-10-10 09:26:32 +01007399 public Component(Package owner, ArrayList<II> intents, String className) {
7400 this.owner = owner;
7401 this.intents = intents;
7402 this.className = className;
7403 }
7404
7405 public Component(Package owner) {
7406 this.owner = owner;
7407 this.intents = null;
7408 this.className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007409 }
7410
7411 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
7412 owner = args.owner;
7413 intents = new ArrayList<II>(0);
Todd Kennedybb8a42d2016-06-02 14:13:56 -07007414 if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
7415 true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
7416 args.roundIconRes, args.logoRes, args.bannerRes)) {
7417 className = outInfo.name;
7418 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007419 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007420 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007421 }
7422
7423 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
7424 this(args, (PackageItemInfo)outInfo);
7425 if (args.outError[0] != null) {
7426 return;
7427 }
7428
7429 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007430 CharSequence pname;
7431 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07007432 pname = args.sa.getNonConfigurationString(args.processRes,
7433 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007434 } else {
7435 // Some older apps have been seen to use a resource reference
7436 // here that on older builds was ignored (with a warning). We
7437 // need to continue to do this for them so they don't break.
7438 pname = args.sa.getNonResourceString(args.processRes);
7439 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007440 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007441 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007442 args.flags, args.sepProcesses, args.outError);
7443 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007444
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08007445 if (args.descriptionRes != 0) {
7446 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
7447 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007448
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007449 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007450 }
7451
7452 public Component(Component<II> clone) {
7453 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007454 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007455 className = clone.className;
7456 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007457 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007458 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007459
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007460 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007461 public ComponentName getComponentName() {
7462 if (componentName != null) {
7463 return componentName;
7464 }
7465 if (className != null) {
7466 componentName = new ComponentName(owner.applicationInfo.packageName,
7467 className);
7468 }
7469 return componentName;
7470 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007471
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007472 protected Component(Parcel in) {
7473 className = in.readString();
7474 metaData = in.readBundle();
7475 intents = createIntentsList(in);
7476
7477 owner = null;
7478 }
7479
7480 protected void writeToParcel(Parcel dest, int flags) {
7481 dest.writeString(className);
7482 dest.writeBundle(metaData);
7483
7484 writeIntentsList(intents, dest, flags);
7485 }
7486
7487 /**
7488 * <p>
7489 * Implementation note: The serialized form for the intent list also contains the name
7490 * of the concrete class that's stored in the list, and assumes that every element of the
7491 * list is of the same type. This is very similar to the original parcelable mechanism.
7492 * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
7493 * and is public API. It also declares Parcelable related methods as final which means
7494 * we can't extend them. The approach of using composition instead of inheritance leads to
7495 * a large set of cascading changes in the PackageManagerService, which seem undesirable.
7496 *
7497 * <p>
7498 * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
7499 * to make sure their owner fields are consistent. See {@code fixupOwner}.
7500 */
7501 private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out,
7502 int flags) {
7503 if (list == null) {
7504 out.writeInt(-1);
7505 return;
7506 }
7507
7508 final int N = list.size();
7509 out.writeInt(N);
7510
7511 // Don't bother writing the component name if the list is empty.
7512 if (N > 0) {
7513 IntentInfo info = list.get(0);
7514 out.writeString(info.getClass().getName());
7515
7516 for (int i = 0; i < N;i++) {
7517 list.get(i).writeIntentInfoToParcel(out, flags);
7518 }
7519 }
7520 }
7521
7522 private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) {
7523 int N = in.readInt();
7524 if (N == -1) {
7525 return null;
7526 }
7527
7528 if (N == 0) {
7529 return new ArrayList<>(0);
7530 }
7531
7532 String componentName = in.readString();
7533 final ArrayList<T> intentsList;
7534 try {
7535 final Class<T> cls = (Class<T>) Class.forName(componentName);
7536 final Constructor<T> cons = cls.getConstructor(Parcel.class);
7537
7538 intentsList = new ArrayList<>(N);
7539 for (int i = 0; i < N; ++i) {
7540 intentsList.add(cons.newInstance(in));
7541 }
7542 } catch (ReflectiveOperationException ree) {
7543 throw new AssertionError("Unable to construct intent list for: " + componentName);
7544 }
7545
7546 return intentsList;
7547 }
7548
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007549 public void appendComponentShortName(StringBuilder sb) {
7550 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007551 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007552
7553 public void printComponentShortName(PrintWriter pw) {
7554 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
7555 }
7556
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007557 public void setPackageName(String packageName) {
7558 componentName = null;
7559 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007560 }
7561 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007562
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007563 public final static class Permission extends Component<IntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007564 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007565 public final PermissionInfo info;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007566 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007567 public boolean tree;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007568 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007569 public PermissionGroup group;
7570
Philip P. Moltmanna4844d12019-03-02 10:17:23 -08007571 /**
7572 * @hide
7573 */
7574 public Permission(Package owner, @Nullable String backgroundPermission) {
7575 super(owner);
7576 info = new PermissionInfo(backgroundPermission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007577 }
7578
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007579 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007580 public Permission(Package _owner, PermissionInfo _info) {
7581 super(_owner);
7582 info = _info;
7583 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007584
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007585 public void setPackageName(String packageName) {
7586 super.setPackageName(packageName);
7587 info.packageName = packageName;
7588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007589
7590 public String toString() {
7591 return "Permission{"
7592 + Integer.toHexString(System.identityHashCode(this))
7593 + " " + info.name + "}";
7594 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007595
7596 @Override
7597 public int describeContents() {
7598 return 0;
7599 }
7600
7601 @Override
7602 public void writeToParcel(Parcel dest, int flags) {
7603 super.writeToParcel(dest, flags);
7604 dest.writeParcelable(info, flags);
7605 dest.writeInt(tree ? 1 : 0);
7606 dest.writeParcelable(group, flags);
7607 }
7608
Todd Kennedyc8423932017-10-05 08:58:36 -07007609 /** @hide */
7610 public boolean isAppOp() {
7611 return info.isAppOp();
7612 }
7613
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007614 private Permission(Parcel in) {
7615 super(in);
7616 final ClassLoader boot = Object.class.getClassLoader();
7617 info = in.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007618 if (info.group != null) {
7619 info.group = info.group.intern();
7620 }
7621
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007622 tree = (in.readInt() == 1);
7623 group = in.readParcelable(boot);
7624 }
7625
7626 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
7627 public Permission createFromParcel(Parcel in) {
7628 return new Permission(in);
7629 }
7630
7631 public Permission[] newArray(int size) {
7632 return new Permission[size];
7633 }
7634 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007635 }
7636
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007637 public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007638 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007639 public final PermissionGroupInfo info;
7640
Philip P. Moltmann0635dab2019-03-02 11:19:03 -08007641 public PermissionGroup(Package owner, @StringRes int requestDetailResourceId,
7642 @StringRes int backgroundRequestResourceId,
7643 @StringRes int backgroundRequestDetailResourceId) {
7644 super(owner);
7645 info = new PermissionGroupInfo(requestDetailResourceId, backgroundRequestResourceId,
7646 backgroundRequestDetailResourceId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007647 }
7648
7649 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
7650 super(_owner);
7651 info = _info;
7652 }
7653
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007654 public void setPackageName(String packageName) {
7655 super.setPackageName(packageName);
7656 info.packageName = packageName;
7657 }
7658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007659 public String toString() {
7660 return "PermissionGroup{"
7661 + Integer.toHexString(System.identityHashCode(this))
7662 + " " + info.name + "}";
7663 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007664
7665 @Override
7666 public int describeContents() {
7667 return 0;
7668 }
7669
7670 @Override
7671 public void writeToParcel(Parcel dest, int flags) {
7672 super.writeToParcel(dest, flags);
7673 dest.writeParcelable(info, flags);
7674 }
7675
7676 private PermissionGroup(Parcel in) {
7677 super(in);
7678 info = in.readParcelable(Object.class.getClassLoader());
7679 }
7680
7681 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
7682 public PermissionGroup createFromParcel(Parcel in) {
7683 return new PermissionGroup(in);
7684 }
7685
7686 public PermissionGroup[] newArray(int size) {
7687 return new PermissionGroup[size];
7688 }
7689 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007690 }
7691
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007692 private static boolean copyNeeded(int flags, Package p,
7693 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07007694 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007695 // We always need to copy for other users, since we need
7696 // to fix up the uid.
7697 return true;
7698 }
7699 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
7700 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07007701 if (p.applicationInfo.enabled != enabled) {
7702 return true;
7703 }
7704 }
Rubin Xubf67c9c2016-04-20 17:09:38 +01007705 boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
7706 if (state.suspended != suspended) {
7707 return true;
7708 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007709 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007710 return true;
7711 }
7712 if (state.stopped) {
7713 return true;
7714 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007715 if (state.instantApp != p.applicationInfo.isInstantApp()) {
7716 return true;
7717 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007718 if ((flags & PackageManager.GET_META_DATA) != 0
7719 && (metaData != null || p.mAppMetaData != null)) {
7720 return true;
7721 }
7722 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7723 && p.usesLibraryFiles != null) {
7724 return true;
7725 }
Nicolas Geoffrayabcd58e2018-10-22 10:23:50 +01007726 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7727 && p.usesLibraryInfos != null) {
7728 return true;
7729 }
Svet Ganov67882122016-12-11 16:36:34 -08007730 if (p.staticSharedLibName != null) {
7731 return true;
7732 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007733 return false;
7734 }
7735
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007736 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007737 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
7738 PackageUserState state) {
7739 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07007740 }
7741
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007742 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
7743 PackageUserState state) {
7744 // CompatibilityMode is global state.
7745 if (!sCompatibilityModeEnabled) {
7746 ai.disableCompatibilityMode();
7747 }
7748 if (state.installed) {
7749 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
7750 } else {
7751 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
7752 }
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00007753 if (state.suspended) {
7754 ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
7755 } else {
7756 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
7757 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007758 if (state.instantApp) {
7759 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
7760 } else {
7761 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
7762 }
Todd Kennedy5eb5a7d2017-08-01 07:42:47 -07007763 if (state.virtualPreload) {
7764 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7765 } else {
7766 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7767 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007768 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007769 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007770 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007771 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007772 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007773 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
7774 ai.enabled = true;
7775 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
7776 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
7777 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
7778 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
7779 ai.enabled = false;
7780 }
7781 ai.enabledSetting = state.enabled;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07007782 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7783 ai.category = state.categoryHint;
7784 }
Jeff Sharkey0078e1b2017-01-11 16:05:27 -07007785 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7786 ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
7787 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007788 ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
Todd Kennedyb2749472017-06-13 08:24:32 -07007789 ai.resourceDirs = state.overlayPaths;
Hyunyoung Song929de7a2019-03-21 23:51:27 -07007790 ai.icon = (sUseRoundIcon && ai.roundIconRes != 0) ? ai.roundIconRes : ai.iconRes;
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007791 }
7792
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007793 @UnsupportedAppUsage
Amith Yamasani13593602012-03-22 16:16:17 -07007794 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007795 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007796 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007797 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007798 return null;
7799 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007800 if (!copyNeeded(flags, p, state, null, userId)
7801 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
7802 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
7803 // In this case it is safe to directly modify the internal ApplicationInfo state:
7804 // - CompatibilityMode is global state, so will be the same for every call.
7805 // - We only come in to here if the app should reported as installed; this is the
7806 // default state, and we will do a copy otherwise.
7807 // - The enable state will always be reported the same for the application across
7808 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
7809 // be doing a copy.
7810 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007811 return p.applicationInfo;
7812 }
7813
7814 // Make shallow copy so we can store the metadata/libraries safely
7815 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Jeff Sharkey15447792015-11-05 16:18:51 -08007816 ai.initForUser(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007817 if ((flags & PackageManager.GET_META_DATA) != 0) {
7818 ai.metaData = p.mAppMetaData;
7819 }
7820 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
7821 ai.sharedLibraryFiles = p.usesLibraryFiles;
Nicolas Geoffray8d144eb2018-11-15 12:59:52 +00007822 ai.sharedLibraryInfos = p.usesLibraryInfos;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007823 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007824 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007825 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007826 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007827 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007828 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007829 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007830 return ai;
7831 }
7832
Dianne Hackbornace27912014-09-18 18:38:30 -07007833 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
7834 PackageUserState state, int userId) {
7835 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007836 if (!checkUseInstalledOrHidden(flags, state, ai)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007837 return null;
7838 }
7839 // This is only used to return the ResolverActivity; we will just always
7840 // make a copy.
7841 ai = new ApplicationInfo(ai);
Jeff Sharkey15447792015-11-05 16:18:51 -08007842 ai.initForUser(userId);
Dianne Hackbornace27912014-09-18 18:38:30 -07007843 if (state.stopped) {
7844 ai.flags |= ApplicationInfo.FLAG_STOPPED;
7845 } else {
7846 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
7847 }
7848 updateApplicationInfo(ai, flags, state);
7849 return ai;
7850 }
7851
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007852 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007853 public static final PermissionInfo generatePermissionInfo(
7854 Permission p, int flags) {
7855 if (p == null) return null;
7856 if ((flags&PackageManager.GET_META_DATA) == 0) {
7857 return p.info;
7858 }
7859 PermissionInfo pi = new PermissionInfo(p.info);
7860 pi.metaData = p.metaData;
7861 return pi;
7862 }
7863
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007864 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007865 public static final PermissionGroupInfo generatePermissionGroupInfo(
7866 PermissionGroup pg, int flags) {
7867 if (pg == null) return null;
7868 if ((flags&PackageManager.GET_META_DATA) == 0) {
7869 return pg.info;
7870 }
7871 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
7872 pgi.metaData = pg.metaData;
7873 return pgi;
7874 }
7875
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007876 public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007877 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007878 public final ActivityInfo info;
Bryce Lee22571db2017-07-07 15:54:18 -07007879 private boolean mHasMaxAspectRatio;
Adrian Roos917791e2018-11-28 16:30:44 +01007880 private boolean mHasMinAspectRatio;
Bryce Lee22571db2017-07-07 15:54:18 -07007881
7882 private boolean hasMaxAspectRatio() {
7883 return mHasMaxAspectRatio;
7884 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007885
Adrian Roos917791e2018-11-28 16:30:44 +01007886 private boolean hasMinAspectRatio() {
7887 return mHasMinAspectRatio;
7888 }
7889
Ricky Waicf134eb2018-10-10 09:26:32 +01007890 // To construct custom activity which does not exist in manifest
7891 Activity(final Package owner, final String className, final ActivityInfo info) {
7892 super(owner, new ArrayList<>(0), className);
7893 this.info = info;
7894 this.info.applicationInfo = owner.applicationInfo;
7895 }
7896
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007897 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
7898 super(args, _info);
7899 info = _info;
7900 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007901 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007902
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007903 public void setPackageName(String packageName) {
7904 super.setPackageName(packageName);
7905 info.packageName = packageName;
7906 }
7907
Bryce Lee22571db2017-07-07 15:54:18 -07007908
7909 private void setMaxAspectRatio(float maxAspectRatio) {
7910 if (info.resizeMode == RESIZE_MODE_RESIZEABLE
7911 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
7912 // Resizeable activities can be put in any aspect ratio.
7913 return;
7914 }
7915
7916 if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
7917 // Ignore any value lesser than 1.0.
7918 return;
7919 }
7920
7921 info.maxAspectRatio = maxAspectRatio;
7922 mHasMaxAspectRatio = true;
7923 }
7924
Adrian Roos917791e2018-11-28 16:30:44 +01007925 private void setMinAspectRatio(float minAspectRatio) {
7926 if (info.resizeMode == RESIZE_MODE_RESIZEABLE
7927 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
7928 // Resizeable activities can be put in any aspect ratio.
7929 return;
7930 }
7931
7932 if (minAspectRatio < 1.0f && minAspectRatio != 0) {
7933 // Ignore any value lesser than 1.0.
7934 return;
7935 }
7936
7937 info.minAspectRatio = minAspectRatio;
7938 mHasMinAspectRatio = true;
7939 }
7940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007941 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007942 StringBuilder sb = new StringBuilder(128);
7943 sb.append("Activity{");
7944 sb.append(Integer.toHexString(System.identityHashCode(this)));
7945 sb.append(' ');
7946 appendComponentShortName(sb);
7947 sb.append('}');
7948 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007949 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007950
7951 @Override
7952 public int describeContents() {
7953 return 0;
7954 }
7955
7956 @Override
7957 public void writeToParcel(Parcel dest, int flags) {
7958 super.writeToParcel(dest, flags);
7959 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
Bryce Lee22571db2017-07-07 15:54:18 -07007960 dest.writeBoolean(mHasMaxAspectRatio);
Adrian Roos917791e2018-11-28 16:30:44 +01007961 dest.writeBoolean(mHasMinAspectRatio);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007962 }
7963
7964 private Activity(Parcel in) {
7965 super(in);
7966 info = in.readParcelable(Object.class.getClassLoader());
Bryce Lee22571db2017-07-07 15:54:18 -07007967 mHasMaxAspectRatio = in.readBoolean();
Adrian Roos917791e2018-11-28 16:30:44 +01007968 mHasMinAspectRatio = in.readBoolean();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007969
7970 for (ActivityIntentInfo aii : intents) {
7971 aii.activity = this;
Todd Kennedy6d418b62018-02-22 14:15:18 -08007972 order = Math.max(aii.getOrder(), order);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007973 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007974
7975 if (info.permission != null) {
7976 info.permission = info.permission.intern();
7977 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007978 }
7979
7980 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
7981 public Activity createFromParcel(Parcel in) {
7982 return new Activity(in);
7983 }
7984
7985 public Activity[] newArray(int size) {
7986 return new Activity[size];
7987 }
7988 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007989 }
7990
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007991 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007992 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
7993 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007994 if (a == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007995 if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007996 return null;
7997 }
7998 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007999 updateApplicationInfo(a.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008000 return a.info;
8001 }
8002 // Make shallow copies so we can store the metadata safely
8003 ActivityInfo ai = new ActivityInfo(a.info);
8004 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008005 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008006 return ai;
8007 }
8008
Dianne Hackbornace27912014-09-18 18:38:30 -07008009 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
8010 PackageUserState state, int userId) {
8011 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07008012 if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07008013 return null;
8014 }
8015 // This is only used to return the ResolverActivity; we will just always
8016 // make a copy.
8017 ai = new ActivityInfo(ai);
8018 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
8019 return ai;
8020 }
8021
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008022 public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008023 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008024 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008025
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008026 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
8027 super(args, _info);
8028 info = _info;
8029 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008030 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07008031
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008032 public void setPackageName(String packageName) {
8033 super.setPackageName(packageName);
8034 info.packageName = packageName;
8035 }
8036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008037 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008038 StringBuilder sb = new StringBuilder(128);
8039 sb.append("Service{");
8040 sb.append(Integer.toHexString(System.identityHashCode(this)));
8041 sb.append(' ');
8042 appendComponentShortName(sb);
8043 sb.append('}');
8044 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008045 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008046
8047 @Override
8048 public int describeContents() {
8049 return 0;
8050 }
8051
8052 @Override
8053 public void writeToParcel(Parcel dest, int flags) {
8054 super.writeToParcel(dest, flags);
8055 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
8056 }
8057
8058 private Service(Parcel in) {
8059 super(in);
8060 info = in.readParcelable(Object.class.getClassLoader());
8061
8062 for (ServiceIntentInfo aii : intents) {
8063 aii.service = this;
Todd Kennedy6d418b62018-02-22 14:15:18 -08008064 order = Math.max(aii.getOrder(), order);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008065 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00008066
8067 if (info.permission != null) {
8068 info.permission = info.permission.intern();
8069 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008070 }
8071
8072 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
8073 public Service createFromParcel(Parcel in) {
8074 return new Service(in);
8075 }
8076
8077 public Service[] newArray(int size) {
8078 return new Service[size];
8079 }
8080 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008081 }
8082
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008083 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008084 public static final ServiceInfo generateServiceInfo(Service s, int flags,
8085 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008086 if (s == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07008087 if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008088 return null;
8089 }
8090 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07008091 updateApplicationInfo(s.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008092 return s.info;
8093 }
8094 // Make shallow copies so we can store the metadata safely
8095 ServiceInfo si = new ServiceInfo(s.info);
8096 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008097 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008098 return si;
8099 }
8100
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008101 public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008102 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008103 public final ProviderInfo info;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008104 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008105 public boolean syncable;
8106
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008107 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
8108 super(args, _info);
8109 info = _info;
8110 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008111 syncable = false;
8112 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07008113
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008114 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008115 public Provider(Provider existingProvider) {
8116 super(existingProvider);
8117 this.info = existingProvider.info;
8118 this.syncable = existingProvider.syncable;
8119 }
8120
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008121 public void setPackageName(String packageName) {
8122 super.setPackageName(packageName);
8123 info.packageName = packageName;
8124 }
8125
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008126 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008127 StringBuilder sb = new StringBuilder(128);
8128 sb.append("Provider{");
8129 sb.append(Integer.toHexString(System.identityHashCode(this)));
8130 sb.append(' ');
8131 appendComponentShortName(sb);
8132 sb.append('}');
8133 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008134 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008135
8136 @Override
8137 public int describeContents() {
8138 return 0;
8139 }
8140
8141 @Override
8142 public void writeToParcel(Parcel dest, int flags) {
8143 super.writeToParcel(dest, flags);
8144 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
8145 dest.writeInt((syncable) ? 1 : 0);
8146 }
8147
8148 private Provider(Parcel in) {
8149 super(in);
8150 info = in.readParcelable(Object.class.getClassLoader());
8151 syncable = (in.readInt() == 1);
8152
8153 for (ProviderIntentInfo aii : intents) {
8154 aii.provider = this;
8155 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00008156
8157 if (info.readPermission != null) {
8158 info.readPermission = info.readPermission.intern();
8159 }
8160
8161 if (info.writePermission != null) {
8162 info.writePermission = info.writePermission.intern();
8163 }
8164
8165 if (info.authority != null) {
8166 info.authority = info.authority.intern();
8167 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008168 }
8169
8170 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
8171 public Provider createFromParcel(Parcel in) {
8172 return new Provider(in);
8173 }
8174
8175 public Provider[] newArray(int size) {
8176 return new Provider[size];
8177 }
8178 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008179 }
8180
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008181 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008182 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
8183 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008184 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07008185 if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008186 return null;
8187 }
8188 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008189 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008190 || p.info.uriPermissionPatterns == null)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07008191 updateApplicationInfo(p.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008192 return p.info;
8193 }
8194 // Make shallow copies so we can store the metadata safely
8195 ProviderInfo pi = new ProviderInfo(p.info);
8196 pi.metaData = p.metaData;
8197 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
8198 pi.uriPermissionPatterns = null;
8199 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008200 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008201 return pi;
8202 }
8203
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008204 public final static class Instrumentation extends Component<IntentInfo> implements
8205 Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008206 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008207 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008208
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008209 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
8210 super(args, _info);
8211 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008212 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07008213
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008214 public void setPackageName(String packageName) {
8215 super.setPackageName(packageName);
8216 info.packageName = packageName;
8217 }
8218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008219 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008220 StringBuilder sb = new StringBuilder(128);
8221 sb.append("Instrumentation{");
8222 sb.append(Integer.toHexString(System.identityHashCode(this)));
8223 sb.append(' ');
8224 appendComponentShortName(sb);
8225 sb.append('}');
8226 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008227 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008228
8229 @Override
8230 public int describeContents() {
8231 return 0;
8232 }
8233
8234 @Override
8235 public void writeToParcel(Parcel dest, int flags) {
8236 super.writeToParcel(dest, flags);
8237 dest.writeParcelable(info, flags);
8238 }
8239
8240 private Instrumentation(Parcel in) {
8241 super(in);
8242 info = in.readParcelable(Object.class.getClassLoader());
Narayan Kamath07ac1442017-02-10 15:08:07 +00008243
8244 if (info.targetPackage != null) {
8245 info.targetPackage = info.targetPackage.intern();
8246 }
8247
Dianne Hackborn1be53542017-04-28 13:36:00 -07008248 if (info.targetProcesses != null) {
8249 info.targetProcesses = info.targetProcesses.intern();
Narayan Kamath07ac1442017-02-10 15:08:07 +00008250 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008251 }
8252
8253 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
8254 public Instrumentation createFromParcel(Parcel in) {
8255 return new Instrumentation(in);
8256 }
8257
8258 public Instrumentation[] newArray(int size) {
8259 return new Instrumentation[size];
8260 }
8261 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008262 }
8263
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008264 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008265 public static final InstrumentationInfo generateInstrumentationInfo(
8266 Instrumentation i, int flags) {
8267 if (i == null) return null;
8268 if ((flags&PackageManager.GET_META_DATA) == 0) {
8269 return i.info;
8270 }
8271 InstrumentationInfo ii = new InstrumentationInfo(i.info);
8272 ii.metaData = i.metaData;
8273 return ii;
8274 }
8275
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008276 public static abstract class IntentInfo extends IntentFilter {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008277 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008278 public boolean hasDefault;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008279 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008280 public int labelRes;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008281 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008282 public CharSequence nonLocalizedLabel;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008283 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008284 public int icon;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008285 @UnsupportedAppUsage
Adam Powell81cd2e92010-04-21 16:35:18 -07008286 public int logo;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008287 @UnsupportedAppUsage
Jose Limaf78e3122014-03-06 12:13:15 -08008288 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07008289 public int preferred;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008290
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008291 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008292 protected IntentInfo() {
8293 }
8294
8295 protected IntentInfo(Parcel dest) {
8296 super(dest);
8297 hasDefault = (dest.readInt() == 1);
8298 labelRes = dest.readInt();
8299 nonLocalizedLabel = dest.readCharSequence();
8300 icon = dest.readInt();
8301 logo = dest.readInt();
8302 banner = dest.readInt();
8303 preferred = dest.readInt();
8304 }
8305
8306
8307 public void writeIntentInfoToParcel(Parcel dest, int flags) {
8308 super.writeToParcel(dest, flags);
8309 dest.writeInt(hasDefault ? 1 : 0);
8310 dest.writeInt(labelRes);
8311 dest.writeCharSequence(nonLocalizedLabel);
8312 dest.writeInt(icon);
8313 dest.writeInt(logo);
8314 dest.writeInt(banner);
8315 dest.writeInt(preferred);
8316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008317 }
8318
8319 public final static class ActivityIntentInfo extends IntentInfo {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008320 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008321 public Activity activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008322
8323 public ActivityIntentInfo(Activity _activity) {
8324 activity = _activity;
8325 }
8326
8327 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008328 StringBuilder sb = new StringBuilder(128);
8329 sb.append("ActivityIntentInfo{");
8330 sb.append(Integer.toHexString(System.identityHashCode(this)));
8331 sb.append(' ');
8332 activity.appendComponentShortName(sb);
8333 sb.append('}');
8334 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008335 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008336
8337 public ActivityIntentInfo(Parcel in) {
8338 super(in);
8339 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008340 }
8341
8342 public final static class ServiceIntentInfo extends IntentInfo {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008343 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008344 public Service service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008345
8346 public ServiceIntentInfo(Service _service) {
8347 service = _service;
8348 }
8349
8350 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008351 StringBuilder sb = new StringBuilder(128);
8352 sb.append("ServiceIntentInfo{");
8353 sb.append(Integer.toHexString(System.identityHashCode(this)));
8354 sb.append(' ');
8355 service.appendComponentShortName(sb);
8356 sb.append('}');
8357 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008358 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008359
8360 public ServiceIntentInfo(Parcel in) {
8361 super(in);
8362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008363 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008364
Jeff Sharkey85f5f812013-10-07 10:16:12 -07008365 public static final class ProviderIntentInfo extends IntentInfo {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008366 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008367 public Provider provider;
Jeff Sharkey85f5f812013-10-07 10:16:12 -07008368
8369 public ProviderIntentInfo(Provider provider) {
8370 this.provider = provider;
8371 }
8372
8373 public String toString() {
8374 StringBuilder sb = new StringBuilder(128);
8375 sb.append("ProviderIntentInfo{");
8376 sb.append(Integer.toHexString(System.identityHashCode(this)));
8377 sb.append(' ');
8378 provider.appendComponentShortName(sb);
8379 sb.append('}');
8380 return sb.toString();
8381 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008382
8383 public ProviderIntentInfo(Parcel in) {
8384 super(in);
8385 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -07008386 }
8387
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008388 /**
8389 * @hide
8390 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008391 @UnsupportedAppUsage
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008392 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
8393 sCompatibilityModeEnabled = compatibilityModeEnabled;
8394 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07008395
Hyunyoung Song929de7a2019-03-21 23:51:27 -07008396 /**
8397 * @hide
8398 */
8399 public static void readConfigUseRoundIcon(Resources r) {
8400 if (r != null) {
8401 sUseRoundIcon = r.getBoolean(com.android.internal.R.bool.config_useRoundIcon);
8402 return;
8403 }
8404
8405 ApplicationInfo androidAppInfo;
8406 try {
8407 androidAppInfo = ActivityThread.getPackageManager().getApplicationInfo(
8408 "android", 0 /* flags */,
8409 UserHandle.myUserId());
8410 } catch (RemoteException e) {
8411 throw e.rethrowFromSystemServer();
8412 }
8413 Resources systemResources = Resources.getSystem();
8414
8415 // Create in-flight as this overlayable resource is only used when config changes
8416 Resources overlayableRes = ResourcesManager.getInstance().getResources(null,
8417 null,
8418 null,
8419 androidAppInfo.resourceDirs,
8420 androidAppInfo.sharedLibraryFiles,
8421 Display.DEFAULT_DISPLAY,
8422 null,
8423 systemResources.getCompatibilityInfo(),
8424 systemResources.getClassLoader());
8425
8426 sUseRoundIcon = overlayableRes.getBoolean(com.android.internal.R.bool.config_useRoundIcon);
8427 }
8428
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07008429 public static class PackageParserException extends Exception {
8430 public final int error;
8431
8432 public PackageParserException(int error, String detailMessage) {
8433 super(detailMessage);
8434 this.error = error;
8435 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07008436
8437 public PackageParserException(int error, String detailMessage, Throwable throwable) {
8438 super(detailMessage, throwable);
8439 this.error = error;
8440 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07008441 }
Jiyong Park5b1b7342019-01-18 09:45:17 +09008442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008443}