blob: c4a574a7d95c5e4fbb1f8b8bcf5f8e06cd4ca3d4 [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;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070051import android.app.ActivityTaskManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.content.ComponentName;
53import android.content.Intent;
54import android.content.IntentFilter;
Makoto Onuki4501c61d2017-07-27 15:56:40 -070055import android.content.pm.PackageParserCacheHelper.ReadHelper;
56import android.content.pm.PackageParserCacheHelper.WriteHelper;
Garrett Boyer52136662017-05-23 13:47:58 -070057import android.content.pm.split.DefaultSplitAssetLoader;
Adam Lesinski4e862812016-11-21 16:02:24 -080058import android.content.pm.split.SplitAssetDependencyLoader;
59import android.content.pm.split.SplitAssetLoader;
Adam Lesinskibebfcc42018-02-12 14:27:46 -080060import android.content.res.ApkAssets;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.content.res.AssetManager;
62import android.content.res.Configuration;
63import android.content.res.Resources;
64import android.content.res.TypedArray;
65import android.content.res.XmlResourceParser;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070066import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.os.Bundle;
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -070068import android.os.FileUtils;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070069import android.os.Parcel;
70import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.os.PatternMatcher;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -070072import android.os.SystemClock;
Todd Leeea2f3be2017-03-16 14:00:52 -070073import android.os.SystemProperties;
Todd Kennedy27c24fb2015-09-17 16:49:25 -070074import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070075import android.os.UserHandle;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -060076import android.os.storage.StorageManager;
Philip P. Moltmann039678e2018-09-18 13:04:38 -070077import android.permission.PermissionManager;
Narayan Kamath988149c2016-12-01 13:32:59 +000078import android.system.ErrnoException;
79import android.system.OsConstants;
80import android.system.StructStat;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -070081import android.text.TextUtils;
Jeff Sharkey275e0852014-06-17 18:18:49 -070082import android.util.ArrayMap;
83import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.util.AttributeSet;
Kenny Root05ca4c92011-09-15 10:36:25 -070085import android.util.Base64;
Dan Cashman1dbe6d02018-01-23 11:18:28 -080086import android.util.ByteStringUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070088import android.util.Log;
Dan Cashman1dbe6d02018-01-23 11:18:28 -080089import android.util.PackageUtils;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070090import android.util.Pair;
Kenny Rootd2d29252011-08-08 11:27:57 -070091import android.util.Slog;
Adam Lesinski1665d0f2017-03-10 14:46:57 -080092import android.util.SparseArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093import android.util.TypedValue;
Dan Cashmane92f8422017-12-08 14:02:51 -080094import android.util.apk.ApkSignatureVerifier;
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -070095import android.view.Gravity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070097import com.android.internal.R;
98import com.android.internal.annotations.VisibleForTesting;
Narayan Kamathf9419f02017-06-15 11:35:38 +010099import com.android.internal.os.ClassLoaderFactory;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -0700100import com.android.internal.util.ArrayUtils;
101import com.android.internal.util.XmlUtils;
102
103import libcore.io.IoUtils;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -0700104import libcore.util.EmptyArray;
Svet Ganov087dce22017-09-07 15:42:16 -0700105
Jeff Sharkey9bc89af2017-01-11 11:25:50 -0700106import org.xmlpull.v1.XmlPullParser;
107import org.xmlpull.v1.XmlPullParserException;
108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import java.io.File;
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700110import java.io.FileDescriptor;
Narayan Kamath988149c2016-12-01 13:32:59 +0000111import java.io.FileOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import java.io.IOException;
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -0700113import java.io.PrintWriter;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800114import java.lang.annotation.Retention;
115import java.lang.annotation.RetentionPolicy;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000116import java.lang.reflect.Constructor;
Kenny Root05ca4c92011-09-15 10:36:25 -0700117import java.security.KeyFactory;
118import java.security.NoSuchAlgorithmException;
119import java.security.PublicKey;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800120import java.security.cert.CertificateException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700121import java.security.spec.EncodedKeySpec;
122import java.security.spec.InvalidKeySpecException;
123import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124import java.util.ArrayList;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700125import java.util.Arrays;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700126import java.util.Collections;
127import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -0700129import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800130import java.util.Set;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -0600131import java.util.UUID;
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700132import java.util.concurrent.atomic.AtomicInteger;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133
134/**
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700135 * Parser for package files (APKs) on disk. This supports apps packaged either
136 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
137 * APKs in a single directory.
138 * <p>
139 * Apps packaged as multiple APKs always consist of a single "base" APK (with a
140 * {@code null} split name) and zero or more "split" APKs (with unique split
141 * names). Any subset of those split APKs are a valid install, as long as the
142 * following constraints are met:
143 * <ul>
144 * <li>All APKs must have the exact same package name, version code, and signing
145 * certificates.
146 * <li>All APKs must have unique split names.
147 * <li>All installations must contain a single base APK.
148 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700150 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 */
152public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -0700153 private static final boolean DEBUG_JAR = false;
154 private static final boolean DEBUG_PARSER = false;
155 private static final boolean DEBUG_BACKUP = false;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -0700156 private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE;
157 private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100;
Kenny Rootd2d29252011-08-08 11:27:57 -0700158
Svet Ganova3c4eb32017-04-19 23:51:33 -0700159 private static final String PROPERTY_CHILD_PACKAGES_ENABLED =
160 "persist.sys.child_packages_enabled";
161
Jeff Sharkey3f1790d2017-04-25 18:56:17 -0600162 private static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE &&
Garrett Boyer17041532017-08-01 14:11:02 -0700163 SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false);
Svet Ganova3c4eb32017-04-19 23:51:33 -0700164
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700165 private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
Adrian Roos917791e2018-11-28 16:30:44 +0100166 private static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO = 1.333f;
167 private static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH = 1f;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700168
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700169 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700170 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700171
Kenny Rootbcc954d2011-08-08 16:19:08 -0700172 /** File name in an APK for the Android manifest. */
Dan Cashmane92f8422017-12-08 14:02:51 -0800173 public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
Kenny Rootbcc954d2011-08-08 16:19:08 -0700174
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700175 /** Path prefix for apps on expanded storage */
176 private static final String MNT_EXPAND = "/mnt/expand/";
177
Svet Ganov354cd3c2015-12-17 11:35:04 -0800178 private static final String TAG_MANIFEST = "manifest";
179 private static final String TAG_APPLICATION = "application";
Adam Lesinski4e862812016-11-21 16:02:24 -0800180 private static final String TAG_PACKAGE_VERIFIER = "package-verifier";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800181 private static final String TAG_OVERLAY = "overlay";
182 private static final String TAG_KEY_SETS = "key-sets";
183 private static final String TAG_PERMISSION_GROUP = "permission-group";
184 private static final String TAG_PERMISSION = "permission";
185 private static final String TAG_PERMISSION_TREE = "permission-tree";
186 private static final String TAG_USES_PERMISSION = "uses-permission";
187 private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
188 private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
189 private static final String TAG_USES_CONFIGURATION = "uses-configuration";
190 private static final String TAG_USES_FEATURE = "uses-feature";
191 private static final String TAG_FEATURE_GROUP = "feature-group";
192 private static final String TAG_USES_SDK = "uses-sdk";
193 private static final String TAG_SUPPORT_SCREENS = "supports-screens";
194 private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
195 private static final String TAG_INSTRUMENTATION = "instrumentation";
196 private static final String TAG_ORIGINAL_PACKAGE = "original-package";
197 private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
198 private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
199 private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
200 private static final String TAG_SUPPORTS_INPUT = "supports-input";
201 private static final String TAG_EAT_COMMENT = "eat-comment";
202 private static final String TAG_PACKAGE = "package";
Todd Kennedyfdd241a2016-04-28 12:26:53 -0700203 private static final String TAG_RESTRICT_UPDATE = "restrict-update";
Adam Lesinski4e862812016-11-21 16:02:24 -0800204 private static final String TAG_USES_SPLIT = "uses-split";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800205
Bryce Lee22571db2017-07-07 15:54:18 -0700206 private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
207
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800208 /**
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700209 * Bit mask of all the valid bits that can be set in recreateOnConfigChanges.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800210 * @hide
211 */
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700212 private static final int RECREATE_ON_CONFIG_CHANGES_MASK =
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800213 ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
214
Svet Ganov354cd3c2015-12-17 11:35:04 -0800215 // These are the tags supported by child packages
216 private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
217 static {
218 CHILD_PACKAGE_TAGS.add(TAG_APPLICATION);
219 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION);
220 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M);
221 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23);
222 CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
223 CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
224 CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
225 CHILD_PACKAGE_TAGS.add(TAG_USES_SDK);
226 CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
227 CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
228 CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE);
229 CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS);
230 CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
231 CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
232 }
233
Jeff Sharkey669e6b12018-10-27 17:58:44 -0600234 // STOPSHIP(b/112545973): remove once feature enabled by default
235 private static final Set<String> FORCE_AUDIO_PACKAGES;
236 private static final Set<String> FORCE_VIDEO_PACKAGES;
237 private static final Set<String> FORCE_IMAGES_PACKAGES;
238 static {
239 FORCE_AUDIO_PACKAGES = parsePackageList(
240 SystemProperties.get(StorageManager.PROP_FORCE_AUDIO));
241 FORCE_VIDEO_PACKAGES = parsePackageList(
242 SystemProperties.get(StorageManager.PROP_FORCE_VIDEO));
243 FORCE_IMAGES_PACKAGES = parsePackageList(
244 SystemProperties.get(StorageManager.PROP_FORCE_IMAGES));
245 }
246
247 private static Set<String> parsePackageList(String pkgs) {
248 if (TextUtils.isEmpty(pkgs)) return Collections.emptySet();
249 return new ArraySet<String>(Arrays.asList(pkgs.split(",")));
250 }
251
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700252 private static final boolean LOG_UNSAFE_BROADCASTS = false;
253
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700254 /**
255 * Total number of packages that were read from the cache. We use it only for logging.
256 */
257 public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger();
258
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700259 // Set of broadcast actions that are safe for manifest receivers
260 private static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
261 static {
262 SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
263 }
264
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700265 /** @hide */
Calin Juravle3fc56c32017-12-11 18:26:13 -0800266 public static final String APK_FILE_EXTENSION = ".apk";
267
268 /** @hide */
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700269 public static class NewPermissionInfo {
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100270 @UnsupportedAppUsage
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700271 public final String name;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100272 @UnsupportedAppUsage
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700273 public final int sdkVersion;
274 public final int fileVersion;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700275
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700276 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
277 this.name = name;
278 this.sdkVersion = sdkVersion;
279 this.fileVersion = fileVersion;
280 }
281 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700282
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700283 /**
284 * List of new permissions that have been added since 1.0.
285 * NOTE: These must be declared in SDK version order, with permissions
286 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700287 * If sdkVersion is 0, then this is not a permission that we want to
288 * automatically add to older apps, but we do want to allow it to be
289 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700290 * @hide
291 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100292 @UnsupportedAppUsage
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700293 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
294 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700295 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700296 android.os.Build.VERSION_CODES.DONUT, 0),
297 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
298 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700299 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300
Dianne Hackborn79245122012-03-12 10:51:26 -0700301 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700302 * @deprecated callers should move to explicitly passing around source path.
303 */
304 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700308 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700309 private DisplayMetrics mMetrics;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100310 @UnsupportedAppUsage
Dianne Hackborncd154e92017-02-28 17:37:35 -0800311 private Callback mCallback;
Narayan Kamath988149c2016-12-01 13:32:59 +0000312 private File mCacheDir;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700313
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700314 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700315 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316
317 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
318
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700319 private static boolean sCompatibilityModeEnabled = true;
Amith Yamasani655d0e22013-06-12 14:19:10 -0700320 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
321 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Todd Kennedy11e45072017-01-25 13:24:21 -0800322 private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700323
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700324 static class ParsePackageItemArgs {
325 final Package owner;
326 final String[] outError;
327 final int nameRes;
328 final int labelRes;
329 final int iconRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700330 final int roundIconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700331 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800332 final int bannerRes;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700333
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700334 String tag;
335 TypedArray sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700336
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700337 ParsePackageItemArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700338 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
339 int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700340 owner = _owner;
341 outError = _outError;
342 nameRes = _nameRes;
343 labelRes = _labelRes;
344 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700345 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800346 bannerRes = _bannerRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700347 roundIconRes = _roundIconRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700348 }
349 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700350
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000351 /** @hide */
352 @VisibleForTesting
353 public static class ParseComponentArgs extends ParsePackageItemArgs {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700354 final String[] sepProcesses;
355 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800356 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700357 final int enabledRes;
358 int flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700359
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000360 public ParseComponentArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700361 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
362 int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800363 String[] _sepProcesses, int _processRes,
364 int _descriptionRes, int _enabledRes) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700365 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes,
366 _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700367 sepProcesses = _sepProcesses;
368 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800369 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700370 enabledRes = _enabledRes;
371 }
372 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800373
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700374 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700375 * Lightweight parsed details about a single package.
376 */
377 public static class PackageLite {
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100378 @UnsupportedAppUsage
Jeff Sharkey73767b92014-07-04 20:18:13 -0700379 public final String packageName;
380 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700381 public final int versionCodeMajor;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100382 @UnsupportedAppUsage
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700383 public final int installLocation;
384 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700385
386 /** Names of any split APKs, ordered by parsed splitName */
387 public final String[] splitNames;
388
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800389 /** Names of any split APKs that are features. Ordered by splitName */
390 public final boolean[] isFeatureSplits;
391
Adam Lesinski4e862812016-11-21 16:02:24 -0800392 /** Dependencies of any split APKs, ordered by parsed splitName */
393 public final String[] usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800394 public final String[] configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800395
Jeff Sharkey73767b92014-07-04 20:18:13 -0700396 /**
397 * Path where this package was found on disk. For monolithic packages
398 * this is path to single base APK file; for cluster packages this is
399 * path to the cluster directory.
400 */
401 public final String codePath;
402
403 /** Path of base APK */
404 public final String baseCodePath;
405 /** Paths of any split APKs, ordered by parsed splitName */
406 public final String[] splitCodePaths;
407
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800408 /** Revision code of base APK */
409 public final int baseRevisionCode;
410 /** Revision codes of any split APKs, ordered by parsed splitName */
411 public final int[] splitRevisionCodes;
412
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700413 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100414 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100415 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800416 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700417 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800418 public final boolean isolatedSplits;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100419
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700420 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800421 boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100422 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700423 this.packageName = baseApk.packageName;
424 this.versionCode = baseApk.versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700425 this.versionCodeMajor = baseApk.versionCodeMajor;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700426 this.installLocation = baseApk.installLocation;
427 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700428 this.splitNames = splitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800429 this.isFeatureSplits = isFeatureSplits;
Adam Lesinski4e862812016-11-21 16:02:24 -0800430 this.usesSplitNames = usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800431 this.configForSplit = configForSplit;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700432 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700433 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700434 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800435 this.baseRevisionCode = baseApk.revisionCode;
436 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700437 this.coreApp = baseApk.coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100438 this.debuggable = baseApk.debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100439 this.multiArch = baseApk.multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800440 this.use32bitAbi = baseApk.use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700441 this.extractNativeLibs = baseApk.extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800442 this.isolatedSplits = baseApk.isolatedSplits;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700443 }
444
445 public List<String> getAllCodePaths() {
446 ArrayList<String> paths = new ArrayList<>();
447 paths.add(baseCodePath);
448 if (!ArrayUtils.isEmpty(splitCodePaths)) {
449 Collections.addAll(paths, splitCodePaths);
450 }
451 return paths;
452 }
453 }
454
455 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700456 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800457 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700458 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700459 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700460 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700461 public final String splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800462 public boolean isFeatureSplit;
463 public final String configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800464 public final String usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700465 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700466 public final int versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800467 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700468 public final int installLocation;
469 public final VerifierInfo[] verifiers;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800470 public final SigningDetails signingDetails;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700471 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100472 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100473 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800474 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700475 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800476 public final boolean isolatedSplits;
Todd Kennedy29cfa272018-09-26 10:25:24 -0700477 public final boolean isSplitRequired;
Victor Hsiehfa9df0b2019-01-29 12:48:36 -0800478 public final boolean useEmbeddedDex;
Kenny Root05ca4c92011-09-15 10:36:25 -0700479
Patrick Baumann47117fc2017-12-19 10:17:21 -0800480 public ApkLite(String codePath, String packageName, String splitName,
481 boolean isFeatureSplit,
Todd Kennedy29cfa272018-09-26 10:25:24 -0700482 String configForSplit, String usesSplitName, boolean isSplitRequired,
483 int versionCode, int versionCodeMajor,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700484 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Patrick Baumann47117fc2017-12-19 10:17:21 -0800485 SigningDetails signingDetails, boolean coreApp,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700486 boolean debuggable, boolean multiArch, boolean use32bitAbi,
Victor Hsiehfa9df0b2019-01-29 12:48:36 -0800487 boolean useEmbeddedDex, boolean extractNativeLibs, boolean isolatedSplits) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700488 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800489 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700490 this.splitName = splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800491 this.isFeatureSplit = isFeatureSplit;
492 this.configForSplit = configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800493 this.usesSplitName = usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700494 this.versionCode = versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700495 this.versionCodeMajor = versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800496 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800497 this.installLocation = installLocation;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800498 this.signingDetails = signingDetails;
Kenny Root05ca4c92011-09-15 10:36:25 -0700499 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700500 this.coreApp = coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100501 this.debuggable = debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100502 this.multiArch = multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800503 this.use32bitAbi = use32bitAbi;
Victor Hsiehfa9df0b2019-01-29 12:48:36 -0800504 this.useEmbeddedDex = useEmbeddedDex;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700505 this.extractNativeLibs = extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800506 this.isolatedSplits = isolatedSplits;
Todd Kennedy29cfa272018-09-26 10:25:24 -0700507 this.isSplitRequired = isSplitRequired;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800508 }
Dianne Hackborn3accca02013-09-20 09:32:11 -0700509
510 public long getLongVersionCode() {
511 return PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode);
512 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800513 }
514
Garrett Boyer52136662017-05-23 13:47:58 -0700515 /**
516 * Cached parse state for new components.
517 *
518 * Allows reuse of the same parse argument records to avoid GC pressure. Lifetime is carefully
519 * scoped to the parsing of a single application element.
520 */
521 private static class CachedComponentArgs {
522 ParseComponentArgs mActivityArgs;
523 ParseComponentArgs mActivityAliasArgs;
524 ParseComponentArgs mServiceArgs;
525 ParseComponentArgs mProviderArgs;
526 }
527
528 /**
529 * Cached state for parsing instrumentation to avoid GC pressure.
530 *
531 * Must be manually reset to null for each new manifest.
532 */
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700533 private ParsePackageItemArgs mParseInstrumentationArgs;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 /** If set to true, we will only allow package files that exactly match
536 * the DTD. Otherwise, we try to get as much from the package as we
537 * can without failing. This should normally be set to false, to
538 * support extensions to the DTD in future versions. */
539 private static final boolean RIGID_PARSER = false;
540
541 private static final String TAG = "PackageParser";
542
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100543 @UnsupportedAppUsage
Jeff Sharkey275e0852014-06-17 18:18:49 -0700544 public PackageParser() {
545 mMetrics = new DisplayMetrics();
546 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700547 }
548
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100549 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 public void setSeparateProcesses(String[] procs) {
551 mSeparateProcesses = procs;
552 }
553
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700554 /**
555 * Flag indicating this parser should only consider apps with
556 * {@code coreApp} manifest attribute to be valid apps. This is useful when
557 * creating a minimalist boot environment.
558 */
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700559 public void setOnlyCoreApps(boolean onlyCoreApps) {
560 mOnlyCoreApps = onlyCoreApps;
561 }
562
Jeff Sharkey275e0852014-06-17 18:18:49 -0700563 public void setDisplayMetrics(DisplayMetrics metrics) {
564 mMetrics = metrics;
565 }
566
Narayan Kamath988149c2016-12-01 13:32:59 +0000567 /**
568 * Sets the cache directory for this package parser.
569 */
570 public void setCacheDir(File cacheDir) {
571 mCacheDir = cacheDir;
572 }
573
Dianne Hackborncd154e92017-02-28 17:37:35 -0800574 /**
575 * Callback interface for retrieving information that may be needed while parsing
576 * a package.
577 */
578 public interface Callback {
579 boolean hasFeature(String feature);
Jaekyun Seok30dc2a02017-04-11 09:41:11 +0900580 String[] getOverlayPaths(String targetPackageName, String targetPath);
581 String[] getOverlayApks(String targetPackageName);
Dianne Hackborncd154e92017-02-28 17:37:35 -0800582 }
583
584 /**
585 * Standard implementation of {@link Callback} on top of the public {@link PackageManager}
586 * class.
587 */
588 public static final class CallbackImpl implements Callback {
589 private final PackageManager mPm;
590
591 public CallbackImpl(PackageManager pm) {
592 mPm = pm;
593 }
594
595 @Override public boolean hasFeature(String feature) {
596 return mPm.hasSystemFeature(feature);
597 }
Jaekyun Seok30dc2a02017-04-11 09:41:11 +0900598
599 @Override public String[] getOverlayPaths(String targetPackageName, String targetPath) {
600 return null;
601 }
602
603 @Override public String[] getOverlayApks(String targetPackageName) {
604 return null;
605 }
Dianne Hackborncd154e92017-02-28 17:37:35 -0800606 }
607
608 /**
609 * Set the {@link Callback} that can be used while parsing.
610 */
611 public void setCallback(Callback cb) {
612 mCallback = cb;
613 }
614
Jeff Sharkey73767b92014-07-04 20:18:13 -0700615 public static final boolean isApkFile(File file) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700616 return isApkPath(file.getName());
617 }
618
Adam Lesinski4e862812016-11-21 16:02:24 -0800619 public static boolean isApkPath(String path) {
Calin Juravle3fc56c32017-12-11 18:26:13 -0800620 return path.endsWith(APK_FILE_EXTENSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 }
622
623 /**
624 * Generate and return the {@link PackageInfo} for a parsed package.
625 *
626 * @param p the parsed package.
627 * @param flags indicating which optional information is included.
628 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100629 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800631 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svet Ganov3695b8a2015-03-24 16:30:25 -0700632 Set<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633
Amith Yamasani483f3b02012-03-13 16:08:00 -0700634 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700635 grantedPermissions, state, UserHandle.getCallingUserId());
636 }
637
Amith Yamasani655d0e22013-06-12 14:19:10 -0700638 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700639 * Returns true if the package is installed and not hidden, or if the caller
640 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700641 * @param appInfo The applicationInfo of the app being checked.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700642 */
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700643 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
644 ApplicationInfo appInfo) {
Rhed Jaocd47c262018-06-13 11:16:16 +0800645 // Returns false if the package is hidden system app until installed.
646 if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
647 && !state.installed
648 && appInfo != null && appInfo.hiddenUntilInstalled) {
649 return false;
650 }
651
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700652 // If available for the target user, or trying to match uninstalled packages and it's
653 // a system app.
654 return state.isAvailable(flags)
655 || (appInfo != null && appInfo.isSystemApp()
Rhed Jaocd47c262018-06-13 11:16:16 +0800656 && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
657 || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
Amith Yamasani483f3b02012-03-13 16:08:00 -0700658 }
659
Christopher Tateba629da2013-11-13 17:42:28 -0800660 public static boolean isAvailable(PackageUserState state) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700661 return checkUseInstalledOrHidden(0, state, null);
Christopher Tateba629da2013-11-13 17:42:28 -0800662 }
663
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100664 @UnsupportedAppUsage
Amith Yamasani13593602012-03-22 16:16:17 -0700665 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700666 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800667 Set<String> grantedPermissions, PackageUserState state, int userId) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700668 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700669 return null;
670 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671 PackageInfo pi = new PackageInfo();
672 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700673 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 pi.versionCode = p.mVersionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700675 pi.versionCodeMajor = p.mVersionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800676 pi.baseRevisionCode = p.baseRevisionCode;
677 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 pi.versionName = p.mVersionName;
679 pi.sharedUserId = p.mSharedUserId;
680 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700681 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800682 pi.installLocation = p.installLocation;
Todd Kennedy7c8addf2017-06-27 14:13:55 -0700683 pi.isStub = p.isStub;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700684 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700685 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
686 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
687 pi.requiredForAllUsers = p.mRequiredForAllUsers;
688 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700689 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700690 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100691 pi.overlayTarget = p.mOverlayTarget;
Ryan Mitchella3628462019-01-14 12:19:40 -0800692 pi.overlayTargetName = p.mOverlayTargetName;
Adrian Roosc84df772018-01-19 21:20:22 +0100693 pi.overlayCategory = p.mOverlayCategory;
Jaekyun Seok42d53f62017-04-10 13:48:58 +0900694 pi.overlayPriority = p.mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -0800695 pi.mOverlayIsStatic = p.mOverlayIsStatic;
Alan Viveretteb6a25732017-11-21 14:49:24 -0500696 pi.compileSdkVersion = p.mCompileSdkVersion;
697 pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700698 pi.firstInstallTime = firstInstallTime;
699 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 if ((flags&PackageManager.GET_GIDS) != 0) {
701 pi.gids = gids;
702 }
703 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700704 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 if (N > 0) {
706 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700707 p.configPreferences.toArray(pi.configPreferences);
708 }
709 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
710 if (N > 0) {
711 pi.reqFeatures = new FeatureInfo[N];
712 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700714 N = p.featureGroups != null ? p.featureGroups.size() : 0;
715 if (N > 0) {
716 pi.featureGroups = new FeatureGroupInfo[N];
717 p.featureGroups.toArray(pi.featureGroups);
718 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700720 if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
721 final int N = p.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800722 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700723 int num = 0;
724 final ActivityInfo[] res = new ActivityInfo[N];
725 for (int i = 0; i < N; i++) {
726 final Activity a = p.activities.get(i);
727 if (state.isMatch(a.info, flags)) {
Ricky Wai905908f2019-01-29 15:19:52 +0000728 if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(a.className)) {
729 continue;
730 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700731 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 }
733 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700734 pi.activities = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 }
736 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700737 if ((flags & PackageManager.GET_RECEIVERS) != 0) {
738 final int N = p.receivers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800739 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700740 int num = 0;
741 final ActivityInfo[] res = new ActivityInfo[N];
742 for (int i = 0; i < N; i++) {
743 final Activity a = p.receivers.get(i);
744 if (state.isMatch(a.info, flags)) {
745 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 }
747 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700748 pi.receivers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 }
750 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700751 if ((flags & PackageManager.GET_SERVICES) != 0) {
752 final int N = p.services.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800753 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700754 int num = 0;
755 final ServiceInfo[] res = new ServiceInfo[N];
756 for (int i = 0; i < N; i++) {
757 final Service s = p.services.get(i);
758 if (state.isMatch(s.info, flags)) {
759 res[num++] = generateServiceInfo(s, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 }
761 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700762 pi.services = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 }
764 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700765 if ((flags & PackageManager.GET_PROVIDERS) != 0) {
766 final int N = p.providers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700768 int num = 0;
769 final ProviderInfo[] res = new ProviderInfo[N];
770 for (int i = 0; i < N; i++) {
771 final Provider pr = p.providers.get(i);
772 if (state.isMatch(pr.info, flags)) {
773 res[num++] = generateProviderInfo(pr, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 }
775 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700776 pi.providers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 }
778 }
779 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
780 int N = p.instrumentation.size();
781 if (N > 0) {
782 pi.instrumentation = new InstrumentationInfo[N];
783 for (int i=0; i<N; i++) {
784 pi.instrumentation[i] = generateInstrumentationInfo(
785 p.instrumentation.get(i), flags);
786 }
787 }
788 }
789 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
790 int N = p.permissions.size();
791 if (N > 0) {
792 pi.permissions = new PermissionInfo[N];
793 for (int i=0; i<N; i++) {
794 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
795 }
796 }
Chad Brubakere2107312019-02-04 12:30:01 -0800797 N = p.requestedPermissions.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 if (N > 0) {
799 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800800 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 for (int i=0; i<N; i++) {
Chad Brubakere2107312019-02-04 12:30:01 -0800802 final String perm = p.requestedPermissions.get(i);
Dianne Hackborne639da72012-02-21 15:11:13 -0800803 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700804 // The notion of required permissions is deprecated but for compatibility.
Chad Brubakere2107312019-02-04 12:30:01 -0800805 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800806 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
Chad Brubakere2107312019-02-04 12:30:01 -0800807 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809 }
810 }
811 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800812 // deprecated method of getting signing certificates
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800813 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Daniel Cashman5cdda342018-01-19 07:22:52 -0800814 if (p.mSigningDetails.hasPastSigningCertificates()) {
815 // Package has included signing certificate rotation information. Return the oldest
816 // cert so that programmatic checks keep working even if unaware of key rotation.
817 pi.signatures = new Signature[1];
818 pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0];
819 } else if (p.mSigningDetails.hasSignatures()) {
820 // otherwise keep old behavior
Patrick Baumann47117fc2017-12-19 10:17:21 -0800821 int numberOfSigs = p.mSigningDetails.signatures.length;
822 pi.signatures = new Signature[numberOfSigs];
823 System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824 }
825 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800826
827 // replacement for GET_SIGNATURES
828 if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
Dan Cashman5c9f527e2018-04-03 16:42:23 -0700829 if (p.mSigningDetails != SigningDetails.UNKNOWN) {
830 // only return a valid SigningInfo if there is signing information to report
831 pi.signingInfo = new SigningInfo(p.mSigningDetails);
832 } else {
833 pi.signingInfo = null;
Daniel Cashman5cdda342018-01-19 07:22:52 -0800834 }
835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 return pi;
837 }
838
Todd Kennedy232d29e2017-11-06 14:45:53 -0800839 public static final int PARSE_MUST_BE_APK = 1 << 0;
840 public static final int PARSE_IGNORE_PROCESSES = 1 << 1;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800841 public static final int PARSE_EXTERNAL_STORAGE = 1 << 3;
842 public static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
843 public static final int PARSE_COLLECT_CERTIFICATES = 1 << 5;
844 public static final int PARSE_ENFORCE_CODE = 1 << 6;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800845 public static final int PARSE_CHATTY = 1 << 31;
846
847 @IntDef(flag = true, prefix = { "PARSE_" }, value = {
848 PARSE_CHATTY,
849 PARSE_COLLECT_CERTIFICATES,
850 PARSE_ENFORCE_CODE,
851 PARSE_EXTERNAL_STORAGE,
Todd Kennedy232d29e2017-11-06 14:45:53 -0800852 PARSE_IGNORE_PROCESSES,
Todd Kennedy232d29e2017-11-06 14:45:53 -0800853 PARSE_IS_SYSTEM_DIR,
854 PARSE_MUST_BE_APK,
855 })
856 @Retention(RetentionPolicy.SOURCE)
857 public @interface ParseFlags {}
Jeff Sharkey275e0852014-06-17 18:18:49 -0700858
859 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700861 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700862 * Used to sort a set of APKs based on their split names, always placing the
863 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700864 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700865 private static class SplitNameComparator implements Comparator<String> {
866 @Override
867 public int compare(String lhs, String rhs) {
868 if (lhs == null) {
869 return -1;
870 } else if (rhs == null) {
871 return 1;
872 } else {
873 return lhs.compareTo(rhs);
874 }
875 }
876 }
877
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700878 /**
879 * Parse only lightweight details about the package at the given location.
880 * Automatically detects if the package is a monolithic style (single APK
881 * file) or cluster style (directory of APKs).
882 * <p>
883 * This performs sanity checking on cluster style packages, such as
884 * requiring identical package name and version codes, a single base APK,
885 * and unique split names.
886 *
887 * @see PackageParser#parsePackage(File, int)
888 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100889 @UnsupportedAppUsage
Jeff Sharkey73767b92014-07-04 20:18:13 -0700890 public static PackageLite parsePackageLite(File packageFile, int flags)
891 throws PackageParserException {
892 if (packageFile.isDirectory()) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800893 return parseClusterPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700894 } else {
Adam Lesinski4e862812016-11-21 16:02:24 -0800895 return parseMonolithicPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700896 }
897 }
898
Adam Lesinski4e862812016-11-21 16:02:24 -0800899 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
900 throws PackageParserException {
Todd Kennedycd029da2016-07-21 07:41:09 -0700901 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Adam Lesinski4e862812016-11-21 16:02:24 -0800902 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700903 final String packagePath = packageFile.getAbsolutePath();
Todd Kennedycd029da2016-07-21 07:41:09 -0700904 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Narayan Kamath96c11c52017-08-09 13:07:21 +0100905 return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700906 }
907
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800908 static PackageLite parseClusterPackageLite(File packageDir, int flags)
Adam Lesinski4e862812016-11-21 16:02:24 -0800909 throws PackageParserException {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700910 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700911 if (ArrayUtils.isEmpty(files)) {
912 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
913 "No packages found in split");
914 }
915
Jeff Sharkey275e0852014-06-17 18:18:49 -0700916 String packageName = null;
917 int versionCode = 0;
918
Todd Kennedycd029da2016-07-21 07:41:09 -0700919 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700920 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700921 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700922 if (isApkFile(file)) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800923 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700924
925 // Assert that all package names and version codes are
926 // consistent with the first one we encounter.
927 if (packageName == null) {
928 packageName = lite.packageName;
929 versionCode = lite.versionCode;
930 } else {
931 if (!packageName.equals(lite.packageName)) {
932 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
933 "Inconsistent package " + lite.packageName + " in " + file
934 + "; expected " + packageName);
935 }
936 if (versionCode != lite.versionCode) {
937 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
938 "Inconsistent version " + lite.versionCode + " in " + file
939 + "; expected " + versionCode);
940 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700941 }
942
Jeff Sharkey275e0852014-06-17 18:18:49 -0700943 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700944 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700945 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
946 "Split name " + lite.splitName
947 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700948 }
949 }
950 }
Todd Kennedycd029da2016-07-21 07:41:09 -0700951 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700952
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700953 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700954 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700955 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700956 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700957 }
958
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700959 // Always apply deterministic ordering based on splitName
960 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700961
Jeff Sharkey73767b92014-07-04 20:18:13 -0700962 String[] splitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800963 boolean[] isFeatureSplits = null;
Adam Lesinski4e862812016-11-21 16:02:24 -0800964 String[] usesSplitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800965 String[] configForSplits = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700966 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800967 int[] splitRevisionCodes = null;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100968 String[] splitClassLoaderNames = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700969 if (size > 0) {
970 splitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800971 isFeatureSplits = new boolean[size];
Adam Lesinski4e862812016-11-21 16:02:24 -0800972 usesSplitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800973 configForSplits = new String[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700974 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800975 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700976
977 splitNames = apks.keySet().toArray(splitNames);
978 Arrays.sort(splitNames, sSplitNameComparator);
979
980 for (int i = 0; i < size; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800981 final ApkLite apk = apks.get(splitNames[i]);
982 usesSplitNames[i] = apk.usesSplitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800983 isFeatureSplits[i] = apk.isFeatureSplit;
984 configForSplits[i] = apk.configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800985 splitCodePaths[i] = apk.codePath;
986 splitRevisionCodes[i] = apk.revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700987 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700988 }
989
Jeff Sharkey73767b92014-07-04 20:18:13 -0700990 final String codePath = packageDir.getAbsolutePath();
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800991 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100992 configForSplits, splitCodePaths, splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700993 }
994
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700995 /**
996 * Parse the package at the given location. Automatically detects if the
997 * package is a monolithic style (single APK file) or cluster style
998 * (directory of APKs).
999 * <p>
1000 * This performs sanity checking on cluster style packages, such as
1001 * requiring identical package name and version codes, a single base APK,
1002 * and unique split names.
1003 * <p>
1004 * Note that this <em>does not</em> perform signature verification; that
1005 * must be done separately in {@link #collectCertificates(Package, int)}.
1006 *
Narayan Kamath988149c2016-12-01 13:32:59 +00001007 * If {@code useCaches} is true, the package parser might return a cached
1008 * result from a previous parse of the same {@code packageFile} with the same
1009 * {@code flags}. Note that this method does not check whether {@code packageFile}
1010 * has changed since the last parse, it's up to callers to do so.
1011 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001012 * @see #parsePackageLite(File, int)
1013 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001014 @UnsupportedAppUsage
Narayan Kamath988149c2016-12-01 13:32:59 +00001015 public Package parsePackage(File packageFile, int flags, boolean useCaches)
1016 throws PackageParserException {
1017 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
1018 if (parsed != null) {
1019 return parsed;
1020 }
1021
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001022 long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Jeff Sharkey73767b92014-07-04 20:18:13 -07001023 if (packageFile.isDirectory()) {
Narayan Kamath988149c2016-12-01 13:32:59 +00001024 parsed = parseClusterPackage(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001025 } else {
Narayan Kamath988149c2016-12-01 13:32:59 +00001026 parsed = parseMonolithicPackage(packageFile, flags);
1027 }
1028
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001029 long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Narayan Kamath988149c2016-12-01 13:32:59 +00001030 cacheResult(packageFile, flags, parsed);
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001031 if (LOG_PARSE_TIMINGS) {
1032 parseTime = cacheTime - parseTime;
1033 cacheTime = SystemClock.uptimeMillis() - cacheTime;
1034 if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
1035 Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
1036 + "ms, update_cache=" + cacheTime + " ms");
1037 }
1038 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001039 return parsed;
1040 }
1041
1042 /**
1043 * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}.
1044 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001045 @UnsupportedAppUsage
Narayan Kamath988149c2016-12-01 13:32:59 +00001046 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
1047 return parsePackage(packageFile, flags, false /* useCaches */);
1048 }
1049
1050 /**
1051 * Returns the cache key for a specificied {@code packageFile} and {@code flags}.
1052 */
1053 private String getCacheKey(File packageFile, int flags) {
1054 StringBuilder sb = new StringBuilder(packageFile.getName());
1055 sb.append('-');
1056 sb.append(flags);
1057
1058 return sb.toString();
1059 }
1060
1061 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001062 protected Package fromCacheEntry(byte[] bytes) {
1063 return fromCacheEntryStatic(bytes);
1064 }
1065
1066 /** static version of {@link #fromCacheEntry} for unit tests. */
1067 @VisibleForTesting
1068 public static Package fromCacheEntryStatic(byte[] bytes) {
1069 final Parcel p = Parcel.obtain();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001070 p.unmarshall(bytes, 0, bytes.length);
1071 p.setDataPosition(0);
1072
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001073 final ReadHelper helper = new ReadHelper(p);
1074 helper.startAndInstall();
1075
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001076 PackageParser.Package pkg = new PackageParser.Package(p);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001077
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001078 p.recycle();
1079
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001080 sCachedPackageReadCount.incrementAndGet();
1081
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001082 return pkg;
Narayan Kamath988149c2016-12-01 13:32:59 +00001083 }
1084
1085 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001086 protected byte[] toCacheEntry(Package pkg) {
1087 return toCacheEntryStatic(pkg);
1088
1089 }
1090
1091 /** static version of {@link #toCacheEntry} for unit tests. */
1092 @VisibleForTesting
1093 public static byte[] toCacheEntryStatic(Package pkg) {
1094 final Parcel p = Parcel.obtain();
1095 final WriteHelper helper = new WriteHelper(p);
1096
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001097 pkg.writeToParcel(p, 0 /* flags */);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001098
1099 helper.finishAndUninstall();
1100
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001101 byte[] serialized = p.marshall();
1102 p.recycle();
1103
1104 return serialized;
Narayan Kamath988149c2016-12-01 13:32:59 +00001105 }
1106
1107 /**
1108 * Given a {@code packageFile} and a {@code cacheFile} returns whether the
1109 * cache file is up to date based on the mod-time of both files.
1110 */
1111 private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
1112 try {
1113 // NOTE: We don't use the File.lastModified API because it has the very
1114 // non-ideal failure mode of returning 0 with no excepions thrown.
1115 // The nio2 Files API is a little better but is considerably more expensive.
1116 final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
1117 final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
1118 return pkg.st_mtime < cache.st_mtime;
1119 } catch (ErrnoException ee) {
1120 // The most common reason why stat fails is that a given cache file doesn't
1121 // exist. We ignore that here. It's easy to reason that it's safe to say the
1122 // cache isn't up to date if we see any sort of exception here.
1123 //
1124 // (1) Exception while stating the package file : This should never happen,
1125 // and if it does, we do a full package parse (which is likely to throw the
1126 // same exception).
1127 // (2) Exception while stating the cache file : If the file doesn't exist, the
1128 // cache is obviously out of date. If the file *does* exist, we can't read it.
1129 // We will attempt to delete and recreate it after parsing the package.
1130 if (ee.errno != OsConstants.ENOENT) {
1131 Slog.w("Error while stating package cache : ", ee);
1132 }
1133
1134 return false;
1135 }
1136 }
1137
1138 /**
1139 * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
1140 * or {@code null} if no cached result exists.
1141 */
1142 private Package getCachedResult(File packageFile, int flags) {
1143 if (mCacheDir == null) {
1144 return null;
1145 }
1146
1147 final String cacheKey = getCacheKey(packageFile, flags);
1148 final File cacheFile = new File(mCacheDir, cacheKey);
1149
Narayan Kamath988149c2016-12-01 13:32:59 +00001150 try {
Makoto Onuki48e93162017-08-18 11:00:19 -07001151 // If the cache is not up to date, return null.
1152 if (!isCacheUpToDate(packageFile, cacheFile)) {
1153 return null;
1154 }
1155
Narayan Kamath988149c2016-12-01 13:32:59 +00001156 final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001157 Package p = fromCacheEntry(bytes);
1158 if (mCallback != null) {
1159 String[] overlayApks = mCallback.getOverlayApks(p.packageName);
1160 if (overlayApks != null && overlayApks.length > 0) {
1161 for (String overlayApk : overlayApks) {
1162 // If a static RRO is updated, return null.
1163 if (!isCacheUpToDate(new File(overlayApk), cacheFile)) {
1164 return null;
1165 }
1166 }
1167 }
1168 }
1169 return p;
Makoto Onuki48e93162017-08-18 11:00:19 -07001170 } catch (Throwable e) {
Narayan Kamath21a28382017-01-13 10:34:29 +00001171 Slog.w(TAG, "Error reading package cache: ", e);
Narayan Kamath988149c2016-12-01 13:32:59 +00001172
1173 // If something went wrong while reading the cache entry, delete the cache file
1174 // so that we regenerate it the next time.
1175 cacheFile.delete();
1176 return null;
1177 }
1178 }
1179
1180 /**
1181 * Caches the parse result for {@code packageFile} with flags {@code flags}.
1182 */
1183 private void cacheResult(File packageFile, int flags, Package parsed) {
1184 if (mCacheDir == null) {
1185 return;
1186 }
1187
Makoto Onuki48e93162017-08-18 11:00:19 -07001188 try {
1189 final String cacheKey = getCacheKey(packageFile, flags);
1190 final File cacheFile = new File(mCacheDir, cacheKey);
Narayan Kamath988149c2016-12-01 13:32:59 +00001191
Makoto Onuki48e93162017-08-18 11:00:19 -07001192 if (cacheFile.exists()) {
1193 if (!cacheFile.delete()) {
1194 Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
1195 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001196 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001197
Makoto Onuki48e93162017-08-18 11:00:19 -07001198 final byte[] cacheEntry = toCacheEntry(parsed);
Narayan Kamath988149c2016-12-01 13:32:59 +00001199
Makoto Onuki48e93162017-08-18 11:00:19 -07001200 if (cacheEntry == null) {
1201 return;
1202 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001203
Makoto Onuki48e93162017-08-18 11:00:19 -07001204 try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
1205 fos.write(cacheEntry);
1206 } catch (IOException ioe) {
1207 Slog.w(TAG, "Error writing cache entry.", ioe);
1208 cacheFile.delete();
1209 }
1210 } catch (Throwable e) {
1211 Slog.w(TAG, "Error saving package cache.", e);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001212 }
1213 }
1214
1215 /**
1216 * Parse all APKs contained in the given directory, treating them as a
1217 * single package. This also performs sanity checking, such as requiring
1218 * identical package name and version codes, a single base APK, and unique
1219 * split names.
1220 * <p>
1221 * Note that this <em>does not</em> perform signature verification; that
1222 * must be done separately in {@link #collectCertificates(Package, int)}.
1223 */
1224 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001225 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001226 if (mOnlyCoreApps && !lite.coreApp) {
1227 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1228 "Not a coreApp: " + packageDir);
1229 }
1230
Adam Lesinski4e862812016-11-21 16:02:24 -08001231 // Build the split dependency tree.
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001232 SparseArray<int[]> splitDependencies = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001233 final SplitAssetLoader assetLoader;
1234 if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001235 try {
1236 splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
1237 assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
1238 } catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
1239 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
1240 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001241 } else {
1242 assetLoader = new DefaultSplitAssetLoader(lite, flags);
1243 }
1244
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001245 try {
Adam Lesinski4e862812016-11-21 16:02:24 -08001246 final AssetManager assets = assetLoader.getBaseAssetManager();
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001247 final File baseApk = new File(lite.baseCodePath);
1248 final Package pkg = parseBaseApk(baseApk, assets, flags);
1249 if (pkg == null) {
1250 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1251 "Failed to parse base APK: " + baseApk);
1252 }
1253
1254 if (!ArrayUtils.isEmpty(lite.splitNames)) {
1255 final int num = lite.splitNames.length;
1256 pkg.splitNames = lite.splitNames;
1257 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001258 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001259 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001260 pkg.splitPrivateFlags = new int[num];
Adam Lesinski4e862812016-11-21 16:02:24 -08001261 pkg.applicationInfo.splitNames = pkg.splitNames;
1262 pkg.applicationInfo.splitDependencies = splitDependencies;
Narayan Kamath96c11c52017-08-09 13:07:21 +01001263 pkg.applicationInfo.splitClassLoaderNames = new String[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001264
1265 for (int i = 0; i < num; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -08001266 final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
1267 parseSplitApk(pkg, i, splitAssets, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001268 }
1269 }
1270
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001271 pkg.setCodePath(packageDir.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001272 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001273 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001274 } catch (IOException e) {
1275 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1276 "Failed to get path: " + lite.baseCodePath, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001277 } finally {
Adam Lesinski4e862812016-11-21 16:02:24 -08001278 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001280 }
1281
Jeff Sharkey275e0852014-06-17 18:18:49 -07001282 /**
1283 * Parse the given APK file, treating it as as a single monolithic package.
1284 * <p>
1285 * Note that this <em>does not</em> perform signature verification; that
1286 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001287 *
1288 * @deprecated external callers should move to
1289 * {@link #parsePackage(File, int)}. Eventually this method will
1290 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -07001291 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001292 @Deprecated
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001293 @UnsupportedAppUsage
Jeff Sharkey275e0852014-06-17 18:18:49 -07001294 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001295 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001296 if (mOnlyCoreApps) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001297 if (!lite.coreApp) {
1298 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1299 "Not a coreApp: " + apkFile);
1300 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001301 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001302
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001303 final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001304 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001305 final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001306 pkg.setCodePath(apkFile.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001307 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001308 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001309 } catch (IOException e) {
1310 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1311 "Failed to get path: " + apkFile, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001312 } finally {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001313 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001314 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001315 }
1316
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001317 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
1318 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001319 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001320
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07001321 String volumeUuid = null;
1322 if (apkPath.startsWith(MNT_EXPAND)) {
1323 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
1324 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
1325 }
1326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001328 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001329
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001330 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001332 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001333 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001334 final int cookie = assets.findCookieForPath(apkPath);
1335 if (cookie == 0) {
1336 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1337 "Failed adding asset path: " + apkPath);
1338 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001339 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001340 final Resources res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001341
1342 final String[] outError = new String[1];
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001343 final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001344 if (pkg == null) {
1345 throw new PackageParserException(mParseError,
1346 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001347 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001348
Svet Ganov354cd3c2015-12-17 11:35:04 -08001349 pkg.setVolumeUuid(volumeUuid);
1350 pkg.setApplicationVolumeUuid(volumeUuid);
1351 pkg.setBaseCodePath(apkPath);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001352 pkg.setSigningDetails(SigningDetails.UNKNOWN);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001353
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001354 return pkg;
1355
1356 } catch (PackageParserException e) {
1357 throw e;
1358 } catch (Exception e) {
1359 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001360 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001361 } finally {
1362 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 }
1365
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001366 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001367 throws PackageParserException {
1368 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -07001369
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001370 mParseError = PackageManager.INSTALL_SUCCEEDED;
1371 mArchiveSourcePath = apkPath;
1372
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001373 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
1374
Adam Lesinski4e862812016-11-21 16:02:24 -08001375 final Resources res;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001376 XmlResourceParser parser = null;
1377 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001378 // This must always succeed, as the path has been added to the AssetManager before.
1379 final int cookie = assets.findCookieForPath(apkPath);
1380 if (cookie == 0) {
1381 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1382 "Failed adding asset path: " + apkPath);
1383 }
1384
Adam Lesinski56c82be2018-02-09 11:02:04 -08001385 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001386 res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001387
1388 final String[] outError = new String[1];
1389 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
1390 if (pkg == null) {
1391 throw new PackageParserException(mParseError,
1392 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
1393 }
1394
1395 } catch (PackageParserException e) {
1396 throw e;
1397 } catch (Exception e) {
1398 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001399 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001400 } finally {
1401 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001402 }
1403 }
1404
1405 /**
1406 * Parse the manifest of a <em>split APK</em>.
1407 * <p>
1408 * Note that split APKs have many more restrictions on what they're capable
1409 * of doing, so many valid features of a base APK have been carefully
1410 * omitted here.
1411 */
1412 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001413 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
1414 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001415 AttributeSet attrs = parser;
1416
Jeff Sharkey78a13012014-07-15 20:18:34 -07001417 // We parsed manifest tag earlier; just skip past it
Svet Ganov354cd3c2015-12-17 11:35:04 -08001418 parsePackageSplitNames(parser, attrs);
Jeff Sharkey78a13012014-07-15 20:18:34 -07001419
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001420 mParseInstrumentationArgs = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001421
1422 int type;
1423
1424 boolean foundApp = false;
1425
1426 int outerDepth = parser.getDepth();
1427 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1428 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1429 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1430 continue;
1431 }
1432
1433 String tagName = parser.getName();
Adam Lesinski4e862812016-11-21 16:02:24 -08001434 if (tagName.equals(TAG_APPLICATION)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001435 if (foundApp) {
1436 if (RIGID_PARSER) {
1437 outError[0] = "<manifest> has more than one <application>";
1438 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1439 return null;
1440 } else {
1441 Slog.w(TAG, "<manifest> has more than one <application>");
1442 XmlUtils.skipCurrentTag(parser);
1443 continue;
1444 }
1445 }
1446
1447 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001448 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001449 return null;
1450 }
1451
1452 } else if (RIGID_PARSER) {
1453 outError[0] = "Bad element under <manifest>: "
1454 + parser.getName();
1455 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1456 return null;
1457
1458 } else {
1459 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1460 + " at " + mArchiveSourcePath + " "
1461 + parser.getPositionDescription());
1462 XmlUtils.skipCurrentTag(parser);
1463 continue;
1464 }
1465 }
1466
1467 if (!foundApp) {
1468 outError[0] = "<manifest> does not contain an <application>";
1469 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1470 }
1471
1472 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001473 }
1474
Patrick Baumann47117fc2017-12-19 10:17:21 -08001475 /** Parses the public keys from the set of signatures. */
1476 public static ArraySet<PublicKey> toSigningKeys(Signature[] signatures)
1477 throws CertificateException {
1478 ArraySet<PublicKey> keys = new ArraySet<>(signatures.length);
1479 for (int i = 0; i < signatures.length; i++) {
1480 keys.add(signatures[i].getPublicKey());
Todd Kennedy66c55532016-02-26 16:22:11 -08001481 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001482 return keys;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001483 }
1484
1485 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -07001486 * Collect certificates from all the APKs described in the given package,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001487 * populating {@link Package#mSigningDetails}. Also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001488 * contents are signed correctly and consistently.
1489 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001490 @UnsupportedAppUsage
Victor Hsieh5f761242018-01-20 10:30:12 -08001491 public static void collectCertificates(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001492 throws PackageParserException {
Victor Hsieh5f761242018-01-20 10:30:12 -08001493 collectCertificatesInternal(pkg, skipVerify);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001494 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1495 for (int i = 0; i < childCount; i++) {
1496 Package childPkg = pkg.childPackages.get(i);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001497 childPkg.mSigningDetails = pkg.mSigningDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001498 }
1499 }
1500
Victor Hsieh5f761242018-01-20 10:30:12 -08001501 private static void collectCertificatesInternal(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001502 throws PackageParserException {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001503 pkg.mSigningDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001504
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001505 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1506 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001507 collectCertificates(pkg, new File(pkg.baseCodePath), skipVerify);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001508
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001509 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1510 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
Victor Hsieh5f761242018-01-20 10:30:12 -08001511 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001512 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001513 }
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001514 } finally {
1515 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001516 }
1517 }
1518
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001519 @UnsupportedAppUsage
Victor Hsieh5f761242018-01-20 10:30:12 -08001520 private static void collectCertificates(Package pkg, File apkFile, boolean skipVerify)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001521 throws PackageParserException {
1522 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523
Patrick Baumann47117fc2017-12-19 10:17:21 -08001524 int minSignatureScheme = SigningDetails.SignatureSchemeVersion.JAR;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001525 if (pkg.applicationInfo.isStaticSharedLibrary()) {
Dan Cashmane92f8422017-12-08 14:02:51 -08001526 // must use v2 signing scheme
Patrick Baumann47117fc2017-12-19 10:17:21 -08001527 minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;
Dan Cashmane92f8422017-12-08 14:02:51 -08001528 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001529 SigningDetails verified;
Victor Hsieh5f761242018-01-20 10:30:12 -08001530 if (skipVerify) {
Dan Cashman636ea5e2017-12-18 10:38:20 -08001531 // systemDir APKs are already trusted, save time by not verifying
Gavin Corkeryed521ab2019-01-31 16:59:41 +00001532 verified = ApkSignatureVerifier.unsafeGetCertsWithoutVerification(
Dan Cashman636ea5e2017-12-18 10:38:20 -08001533 apkPath, minSignatureScheme);
1534 } else {
1535 verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme);
1536 }
Dan Cashman636ea5e2017-12-18 10:38:20 -08001537
1538 // Verify that entries are signed consistently with the first pkg
1539 // we encountered. Note that for splits, certificates may have
1540 // already been populated during an earlier parse of a base APK.
Patrick Baumann47117fc2017-12-19 10:17:21 -08001541 if (pkg.mSigningDetails == SigningDetails.UNKNOWN) {
1542 pkg.mSigningDetails = verified;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001543 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001544 if (!Signature.areExactMatch(pkg.mSigningDetails.signatures, verified.signatures)) {
Patrick Baumann9ff55742017-12-14 10:50:18 -08001545 throw new PackageParserException(
1546 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
1547 apkPath + " has mismatched certificates");
1548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 }
1551
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001552 private static AssetManager newConfiguredAssetManager() {
1553 AssetManager assetManager = new AssetManager();
Romain Guy408afbf2017-01-25 10:23:03 -08001554 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 -07001555 Build.VERSION.RESOURCES_SDK_INT);
1556 return assetManager;
1557 }
1558
Jeff Sharkey275e0852014-06-17 18:18:49 -07001559 /**
1560 * Utility method that retrieves lightweight details about a single APK
1561 * file, including package name, split name, and install location.
1562 *
1563 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001564 * @param flags optional parse flags, such as
1565 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001566 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001567 public static ApkLite parseApkLite(File apkFile, int flags)
1568 throws PackageParserException {
Dianne Hackbornca3872c2017-10-30 14:19:32 -07001569 return parseApkLiteInner(apkFile, null, null, flags);
1570 }
1571
1572 /**
1573 * Utility method that retrieves lightweight details about a single APK
1574 * file, including package name, split name, and install location.
1575 *
1576 * @param fd already open file descriptor of an apk file
1577 * @param debugPathName arbitrary text name for this file, for debug output
1578 * @param flags optional parse flags, such as
1579 * {@link #PARSE_COLLECT_CERTIFICATES}
1580 */
1581 public static ApkLite parseApkLite(FileDescriptor fd, String debugPathName, int flags)
1582 throws PackageParserException {
1583 return parseApkLiteInner(null, fd, debugPathName, flags);
1584 }
1585
1586 private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName,
1587 int flags) throws PackageParserException {
1588 final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001589
Jeff Sharkey275e0852014-06-17 18:18:49 -07001590 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001592 final ApkAssets apkAssets;
1593 try {
1594 apkAssets = fd != null
1595 ? ApkAssets.loadFromFd(fd, debugPathName, false, false)
1596 : ApkAssets.loadFromPath(apkPath);
1597 } catch (IOException e) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001598 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1599 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001600 }
1601
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001602 parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001603
Patrick Baumann47117fc2017-12-19 10:17:21 -08001604 final SigningDetails signingDetails;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001605 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1606 // TODO: factor signature related items out of Package object
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001607 final Package tempPkg = new Package((String) null);
Victor Hsieh5f761242018-01-20 10:30:12 -08001608 final boolean skipVerify = (flags & PARSE_IS_SYSTEM_DIR) != 0;
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001609 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1610 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001611 collectCertificates(tempPkg, apkFile, skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001612 } finally {
1613 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1614 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001615 signingDetails = tempPkg.mSigningDetails;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001616 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001617 signingDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001618 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001619
Jeff Sharkey275e0852014-06-17 18:18:49 -07001620 final AttributeSet attrs = parser;
Victor Hsieh4e54b522018-10-12 15:38:18 -07001621 return parseApkLite(apkPath, parser, attrs, signingDetails, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001622
1623 } catch (XmlPullParserException | IOException | RuntimeException e) {
Dianne Hackborn34041732017-01-31 15:27:13 -08001624 Slog.w(TAG, "Failed to parse " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001625 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1626 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001627 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001628 IoUtils.closeQuietly(parser);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001629 // TODO(b/72056911): Implement and call close() on ApkAssets.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 }
1632
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001633 private static String validateName(String name, boolean requireSeparator,
1634 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 final int N = name.length();
1636 boolean hasSep = false;
1637 boolean front = true;
1638 for (int i=0; i<N; i++) {
1639 final char c = name.charAt(i);
1640 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1641 front = false;
1642 continue;
1643 }
1644 if (!front) {
1645 if ((c >= '0' && c <= '9') || c == '_') {
1646 continue;
1647 }
1648 }
1649 if (c == '.') {
1650 hasSep = true;
1651 front = true;
1652 continue;
1653 }
1654 return "bad character '" + c + "'";
1655 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001656 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1657 return "Invalid filename";
1658 }
1659 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 ? null : "must have at least one '.' separator";
1661 }
1662
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001663 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
Svet Ganov354cd3c2015-12-17 11:35:04 -08001664 AttributeSet attrs) throws IOException, XmlPullParserException,
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001665 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666
1667 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001668 while ((type = parser.next()) != XmlPullParser.START_TAG
1669 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 }
1671
Kenny Rootd2d29252011-08-08 11:27:57 -07001672 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001673 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1674 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001676 if (!parser.getName().equals(TAG_MANIFEST)) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001677 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1678 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 }
1680
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001681 final String packageName = attrs.getAttributeValue(null, "package");
1682 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001683 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001684 if (error != null) {
1685 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1686 "Invalid manifest package: " + error);
1687 }
1688 }
1689
Jeff Sharkey275e0852014-06-17 18:18:49 -07001690 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001691 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001692 if (splitName.length() == 0) {
1693 splitName = null;
1694 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001695 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001696 if (error != null) {
1697 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1698 "Invalid manifest split: " + error);
1699 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001700 }
1701 }
1702
1703 return Pair.create(packageName.intern(),
1704 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 }
1706
Adam Lesinski4e862812016-11-21 16:02:24 -08001707 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
Victor Hsieh4e54b522018-10-12 15:38:18 -07001708 SigningDetails signingDetails, int flags)
Adam Lesinski4e862812016-11-21 16:02:24 -08001709 throws IOException, XmlPullParserException, PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001710 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001711
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001712 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001713 int versionCode = 0;
Dianne Hackborn3accca02013-09-20 09:32:11 -07001714 int versionCodeMajor = 0;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001715 int revisionCode = 0;
Victor Hsieh4e54b522018-10-12 15:38:18 -07001716 int targetSdkVersion = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001717 boolean coreApp = false;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001718 boolean debuggable = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001719 boolean multiArch = false;
Selim Gurun2d291d82016-02-05 17:50:53 -08001720 boolean use32bitAbi = false;
Victor Hsieh4e54b522018-10-12 15:38:18 -07001721 Boolean extractNativeLibsProvided = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001722 boolean isolatedSplits = false;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001723 boolean isFeatureSplit = false;
Todd Kennedy29cfa272018-09-26 10:25:24 -07001724 boolean isSplitRequired = false;
Victor Hsiehfa9df0b2019-01-29 12:48:36 -08001725 boolean useEmbeddedDex = false;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001726 String configForSplit = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001727 String usesSplitName = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001728
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001729 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001730 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001731 if (attr.equals("installLocation")) {
1732 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001733 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001734 } else if (attr.equals("versionCode")) {
1735 versionCode = attrs.getAttributeIntValue(i, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001736 } else if (attr.equals("versionCodeMajor")) {
1737 versionCodeMajor = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001738 } else if (attr.equals("revisionCode")) {
1739 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001740 } else if (attr.equals("coreApp")) {
1741 coreApp = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski4e862812016-11-21 16:02:24 -08001742 } else if (attr.equals("isolatedSplits")) {
1743 isolatedSplits = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001744 } else if (attr.equals("configForSplit")) {
1745 configForSplit = attrs.getAttributeValue(i);
1746 } else if (attr.equals("isFeatureSplit")) {
1747 isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
Todd Kennedy29cfa272018-09-26 10:25:24 -07001748 } else if (attr.equals("isSplitRequired")) {
1749 isSplitRequired = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001750 }
1751 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001752
1753 // Only search the tree when the tag is directly below <manifest>
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001754 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001755 final int searchDepth = parser.getDepth() + 1;
1756
1757 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1758 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1759 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1760 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1761 continue;
1762 }
1763
Adam Lesinski4e862812016-11-21 16:02:24 -08001764 if (parser.getDepth() != searchDepth) {
1765 continue;
1766 }
1767
1768 if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
1769 final VerifierInfo verifier = parseVerifier(attrs);
Kenny Root05ca4c92011-09-15 10:36:25 -07001770 if (verifier != null) {
1771 verifiers.add(verifier);
1772 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001773 } else if (TAG_APPLICATION.equals(parser.getName())) {
Narayan Kamatha8755a82014-07-15 12:26:35 +01001774 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1775 final String attr = attrs.getAttributeName(i);
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001776 if ("debuggable".equals(attr)) {
1777 debuggable = attrs.getAttributeBooleanValue(i, false);
1778 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001779 if ("multiArch".equals(attr)) {
1780 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001781 }
Selim Gurun2d291d82016-02-05 17:50:53 -08001782 if ("use32bitAbi".equals(attr)) {
1783 use32bitAbi = attrs.getAttributeBooleanValue(i, false);
Tao Baic9a02372016-01-12 15:02:24 -08001784 }
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001785 if ("extractNativeLibs".equals(attr)) {
Victor Hsieh4e54b522018-10-12 15:38:18 -07001786 extractNativeLibsProvided = Boolean.valueOf(
1787 attrs.getAttributeBooleanValue(i, true));
Narayan Kamatha8755a82014-07-15 12:26:35 +01001788 }
Victor Hsiehfa9df0b2019-01-29 12:48:36 -08001789 if ("useEmbeddedDex".equals(attr)) {
1790 useEmbeddedDex = attrs.getAttributeBooleanValue(i, false);
Victor Hsiehe7b5a8d2018-11-16 10:27:06 -08001791 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001792 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001793 } else if (TAG_USES_SPLIT.equals(parser.getName())) {
1794 if (usesSplitName != null) {
1795 Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
1796 continue;
1797 }
1798
1799 usesSplitName = attrs.getAttributeValue(ANDROID_RESOURCES, "name");
1800 if (usesSplitName == null) {
1801 throw new PackageParserException(
1802 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1803 "<uses-split> tag requires 'android:name' attribute");
1804 }
Victor Hsieh4e54b522018-10-12 15:38:18 -07001805 } else if (TAG_USES_SDK.equals(parser.getName())) {
1806 final String[] errorMsg = new String[1];
1807 Pair<Integer, Integer> versions = deriveSdkVersions(new AbstractVersionsAccessor() {
1808 @Override public String getMinSdkVersionCode() {
1809 return getAttributeAsString("minSdkVersion");
1810 }
1811
1812 @Override public int getMinSdkVersion() {
1813 return getAttributeAsInt("minSdkVersion");
1814 }
1815
1816 @Override public String getTargetSdkVersionCode() {
1817 return getAttributeAsString("targetSdkVersion");
1818 }
1819
1820 @Override public int getTargetSdkVersion() {
1821 return getAttributeAsInt("targetSdkVersion");
1822 }
1823
1824 private String getAttributeAsString(String name) {
1825 return attrs.getAttributeValue(ANDROID_RESOURCES, name);
1826 }
1827
1828 private int getAttributeAsInt(String name) {
1829 try {
1830 return attrs.getAttributeIntValue(ANDROID_RESOURCES, name, -1);
1831 } catch (NumberFormatException e) {
1832 return -1;
1833 }
1834 }
1835 }, flags, errorMsg);
1836
1837 if (versions == null) {
1838 throw new PackageParserException(
1839 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, errorMsg[0]);
1840 }
1841
1842 targetSdkVersion = versions.second;
Narayan Kamatha8755a82014-07-15 12:26:35 +01001843 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001844 }
1845
Victor Hsieh4e54b522018-10-12 15:38:18 -07001846 final boolean extractNativeLibsDefault = targetSdkVersion < Build.VERSION_CODES.Q;
1847 final boolean extractNativeLibs = (extractNativeLibsProvided != null)
1848 ? extractNativeLibsProvided : extractNativeLibsDefault;
1849
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001850 return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
Todd Kennedy29cfa272018-09-26 10:25:24 -07001851 configForSplit, usesSplitName, isSplitRequired, versionCode, versionCodeMajor,
1852 revisionCode, installLocation, verifiers, signingDetails, coreApp, debuggable,
Victor Hsiehfa9df0b2019-01-29 12:48:36 -08001853 multiArch, use32bitAbi, useEmbeddedDex, extractNativeLibs, isolatedSplits);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854 }
1855
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001856 /**
Svet Ganov354cd3c2015-12-17 11:35:04 -08001857 * Parses a child package and adds it to the parent if successful. If you add
1858 * new tags that need to be supported by child packages make sure to add them
1859 * to {@link #CHILD_PACKAGE_TAGS}.
1860 *
1861 * @param parentPkg The parent that contains the child
1862 * @param res Resources against which to resolve values
1863 * @param parser Parser of the manifest
1864 * @param flags Flags about how to parse
1865 * @param outError Human readable error if parsing fails
1866 * @return True of parsing succeeded.
1867 *
1868 * @throws XmlPullParserException
1869 * @throws IOException
1870 */
1871 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
1872 int flags, String[] outError) throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001873 // Make sure we have a valid child package name
1874 String childPackageName = parser.getAttributeValue(null, "package");
1875 if (validateName(childPackageName, true, false) != null) {
1876 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1877 return false;
1878 }
1879
1880 // Child packages must be unique
1881 if (childPackageName.equals(parentPkg.packageName)) {
1882 String message = "Child package name cannot be equal to parent package name: "
1883 + parentPkg.packageName;
1884 Slog.w(TAG, message);
1885 outError[0] = message;
1886 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1887 return false;
1888 }
1889
1890 // Child packages must be unique
1891 if (parentPkg.hasChildPackage(childPackageName)) {
1892 String message = "Duplicate child package:" + childPackageName;
1893 Slog.w(TAG, message);
1894 outError[0] = message;
1895 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1896 return false;
1897 }
1898
1899 // Go ahead and parse the child
1900 Package childPkg = new Package(childPackageName);
1901
1902 // Child package inherits parent version code/name/target SDK
1903 childPkg.mVersionCode = parentPkg.mVersionCode;
1904 childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
1905 childPkg.mVersionName = parentPkg.mVersionName;
1906 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
Todd Kennedy89d60182016-03-11 11:18:32 -08001907 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001908
1909 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
1910 if (childPkg == null) {
1911 // If we got null then error was set during child parsing
1912 return false;
1913 }
1914
1915 // Set the parent-child relation
1916 if (parentPkg.childPackages == null) {
1917 parentPkg.childPackages = new ArrayList<>();
1918 }
1919 parentPkg.childPackages.add(childPkg);
1920 childPkg.parentPackage = parentPkg;
1921
1922 return true;
1923 }
1924
1925 /**
1926 * Parse the manifest of a <em>base APK</em>. When adding new features you
1927 * need to consider whether they should be supported by split APKs and child
1928 * packages.
1929 *
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001930 * @param apkPath The package apk file path
Svet Ganov354cd3c2015-12-17 11:35:04 -08001931 * @param res The resources from which to resolve values
1932 * @param parser The manifest parser
1933 * @param flags Flags how to parse
1934 * @param outError Human readable error message
1935 * @return Parsed package or null on error.
1936 *
1937 * @throws XmlPullParserException
1938 * @throws IOException
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001939 */
Mathew Inwood8c854f82018-09-14 12:35:36 +01001940 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001941 private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001942 String[] outError) throws XmlPullParserException, IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001943 final String splitName;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001944 final String pkgName;
1945
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001946 try {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001947 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001948 pkgName = packageSplit.first;
1949 splitName = packageSplit.second;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001950
1951 if (!TextUtils.isEmpty(splitName)) {
1952 outError[0] = "Expected base APK, but found split " + splitName;
1953 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1954 return null;
1955 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001956 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001957 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1958 return null;
1959 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001960
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001961 if (mCallback != null) {
1962 String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
1963 if (overlayPaths != null && overlayPaths.length > 0) {
1964 for (String overlayPath : overlayPaths) {
1965 res.getAssets().addOverlayPath(overlayPath);
1966 }
1967 }
1968 }
1969
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001970 final Package pkg = new Package(pkgName);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001971
Svet Ganov354cd3c2015-12-17 11:35:04 -08001972 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001973 com.android.internal.R.styleable.AndroidManifest);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001974
Dianne Hackborn3accca02013-09-20 09:32:11 -07001975 pkg.mVersionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001976 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001977 pkg.mVersionCodeMajor = sa.getInteger(
1978 com.android.internal.R.styleable.AndroidManifest_versionCodeMajor, 0);
Patrick Baumannc2def582018-04-04 12:14:15 -07001979 pkg.applicationInfo.setVersionCode(pkg.getLongVersionCode());
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001980 pkg.baseRevisionCode = sa.getInteger(
1981 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001982 pkg.mVersionName = sa.getNonConfigurationString(
1983 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001984 if (pkg.mVersionName != null) {
1985 pkg.mVersionName = pkg.mVersionName.intern();
1986 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001987
1988 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
1989
Alan Viveretteb6a25732017-11-21 14:49:24 -05001990 pkg.mCompileSdkVersion = sa.getInteger(
1991 com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0);
1992 pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion;
1993 pkg.mCompileSdkVersionCodename = sa.getNonConfigurationString(
1994 com.android.internal.R.styleable.AndroidManifest_compileSdkVersionCodename, 0);
1995 if (pkg.mCompileSdkVersionCodename != null) {
1996 pkg.mCompileSdkVersionCodename = pkg.mCompileSdkVersionCodename.intern();
1997 }
1998 pkg.applicationInfo.compileSdkVersionCodename = pkg.mCompileSdkVersionCodename;
1999
Svet Ganov354cd3c2015-12-17 11:35:04 -08002000 sa.recycle();
2001
2002 return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
2003 }
2004
2005 /**
2006 * This is the common parsing routing for handling parent and child
2007 * packages in a base APK. The difference between parent and child
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002008 * parsing is that some tags are not supported by child packages as
Svet Ganov354cd3c2015-12-17 11:35:04 -08002009 * well as some manifest attributes are ignored. The implementation
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002010 * assumes the calling code has already handled the manifest tag if needed
Svet Ganov354cd3c2015-12-17 11:35:04 -08002011 * (this applies to the parent only).
2012 *
2013 * @param pkg The package which to populate
2014 * @param acceptedTags Which tags to handle, null to handle all
2015 * @param res Resources against which to resolve values
2016 * @param parser Parser of the manifest
2017 * @param flags Flags about how to parse
2018 * @param outError Human readable error if parsing fails
2019 * @return The package if parsing succeeded or null.
2020 *
2021 * @throws XmlPullParserException
2022 * @throws IOException
2023 */
2024 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
2025 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
2026 IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002027 mParseInstrumentationArgs = null;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002028
2029 int type;
2030 boolean foundApp = false;
2031
2032 TypedArray sa = res.obtainAttributes(parser,
2033 com.android.internal.R.styleable.AndroidManifest);
2034
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002035 String str = sa.getNonConfigurationString(
2036 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
2037 if (str != null && str.length() > 0) {
Sudheer Shanka9c5079a2018-08-03 12:41:10 -07002038 String nameError = validateName(str, true, true);
Svet Ganov354cd3c2015-12-17 11:35:04 -08002039 if (nameError != null && !"android".equals(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002040 outError[0] = "<manifest> specifies bad sharedUserId name \""
2041 + str + "\": " + nameError;
2042 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
2043 return null;
2044 }
2045 pkg.mSharedUserId = str.intern();
2046 pkg.mSharedUserLabel = sa.getResourceId(
2047 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
2048 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08002049
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08002050 pkg.installLocation = sa.getInteger(
2051 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07002052 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002053 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07002054
Todd Kennedy11e45072017-01-25 13:24:21 -08002055 final int targetSandboxVersion = sa.getInteger(
2056 com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion,
2057 PARSE_DEFAULT_TARGET_SANDBOX);
2058 pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion;
Alan Viverettefd274a02014-03-27 15:39:15 -07002059
Kenny Root7cb9be22012-05-30 15:30:37 -07002060 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07002061 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07002062 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
2063 }
2064
Adam Lesinski4e862812016-11-21 16:02:24 -08002065 if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
2066 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
2067 }
2068
Dianne Hackborn723738c2009-06-25 19:48:04 -07002069 // Resource boolean are -1, so 1 means we don't know the value.
2070 int supportsSmallScreens = 1;
2071 int supportsNormalScreens = 1;
2072 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002073 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002074 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002075 int anyDensity = 1;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07002078 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2079 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2080 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002081 continue;
2082 }
2083
2084 String tagName = parser.getName();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002085
2086 if (acceptedTags != null && !acceptedTags.contains(tagName)) {
2087 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
2088 + tagName + " at " + mArchiveSourcePath + " "
2089 + parser.getPositionDescription());
2090 XmlUtils.skipCurrentTag(parser);
2091 continue;
2092 }
2093
2094 if (tagName.equals(TAG_APPLICATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002095 if (foundApp) {
2096 if (RIGID_PARSER) {
2097 outError[0] = "<manifest> has more than one <application>";
2098 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2099 return null;
2100 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002101 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002102 XmlUtils.skipCurrentTag(parser);
2103 continue;
2104 }
2105 }
2106
2107 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002108 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 return null;
2110 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002111 } else if (tagName.equals(TAG_OVERLAY)) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002112 sa = res.obtainAttributes(parser,
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002113 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
2114 pkg.mOverlayTarget = sa.getString(
2115 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
Ryan Mitchella3628462019-01-14 12:19:40 -08002116 pkg.mOverlayTargetName = sa.getString(
2117 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetName);
Adrian Roosc84df772018-01-19 21:20:22 +01002118 pkg.mOverlayCategory = sa.getString(
2119 com.android.internal.R.styleable.AndroidManifestResourceOverlay_category);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002120 pkg.mOverlayPriority = sa.getInt(
2121 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
2122 0);
Adam Lesinskie7334972018-01-17 16:13:52 -08002123 pkg.mOverlayIsStatic = sa.getBoolean(
Jaekyun Seok04342892017-03-02 15:24:19 +09002124 com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
2125 false);
Todd Leeea2f3be2017-03-16 14:00:52 -07002126 final String propName = sa.getString(
2127 com.android.internal.R.styleable
2128 .AndroidManifestResourceOverlay_requiredSystemPropertyName);
2129 final String propValue = sa.getString(
2130 com.android.internal.R.styleable
2131 .AndroidManifestResourceOverlay_requiredSystemPropertyValue);
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002132 sa.recycle();
2133
2134 if (pkg.mOverlayTarget == null) {
2135 outError[0] = "<overlay> does not specify a target package";
2136 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2137 return null;
2138 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002139
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002140 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
2141 outError[0] = "<overlay> priority must be between 0 and 9999";
2142 mParseError =
2143 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2144 return null;
2145 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002146
2147 // check to see if overlay should be excluded based on system property condition
2148 if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
2149 Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
2150 + pkg.baseCodePath+ ": overlay ignored due to required system property: "
2151 + propName + " with value: " + propValue);
2152 return null;
Jaekyun Seok04342892017-03-02 15:24:19 +09002153 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002154
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002155 XmlUtils.skipCurrentTag(parser);
2156
Svet Ganov354cd3c2015-12-17 11:35:04 -08002157 } else if (tagName.equals(TAG_KEY_SETS)) {
2158 if (!parseKeySets(pkg, res, parser, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08002159 return null;
2160 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002161 } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002162 if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 return null;
2164 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002165 } else if (tagName.equals(TAG_PERMISSION)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002166 if (!parsePermission(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002167 return null;
2168 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002169 } else if (tagName.equals(TAG_PERMISSION_TREE)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002170 if (!parsePermissionTree(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002171 return null;
2172 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002173 } else if (tagName.equals(TAG_USES_PERMISSION)) {
Chad Brubakere2107312019-02-04 12:30:01 -08002174 if (!parseUsesPermission(pkg, res, parser)) {
Svetoslav96a77162015-04-03 13:58:33 -07002175 return null;
2176 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002177 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
2178 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
Chad Brubakere2107312019-02-04 12:30:01 -08002179 if (!parseUsesPermission(pkg, res, parser)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002180 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002182 } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183 ConfigurationInfo cPref = new ConfigurationInfo();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002184 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002185 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
2186 cPref.reqTouchScreen = sa.getInt(
2187 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
2188 Configuration.TOUCHSCREEN_UNDEFINED);
2189 cPref.reqKeyboardType = sa.getInt(
2190 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
2191 Configuration.KEYBOARD_UNDEFINED);
2192 if (sa.getBoolean(
2193 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
2194 false)) {
2195 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
2196 }
2197 cPref.reqNavigation = sa.getInt(
2198 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
2199 Configuration.NAVIGATION_UNDEFINED);
2200 if (sa.getBoolean(
2201 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
2202 false)) {
2203 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
2204 }
2205 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002206 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002207
2208 XmlUtils.skipCurrentTag(parser);
2209
Svet Ganov354cd3c2015-12-17 11:35:04 -08002210 } else if (tagName.equals(TAG_USES_FEATURE)) {
2211 FeatureInfo fi = parseUsesFeature(res, parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002212 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
2213
Dianne Hackborn49237342009-08-27 20:08:01 -07002214 if (fi.name == null) {
2215 ConfigurationInfo cPref = new ConfigurationInfo();
2216 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002217 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07002218 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07002219
2220 XmlUtils.skipCurrentTag(parser);
2221
Svet Ganov354cd3c2015-12-17 11:35:04 -08002222 } else if (tagName.equals(TAG_FEATURE_GROUP)) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002223 FeatureGroupInfo group = new FeatureGroupInfo();
2224 ArrayList<FeatureInfo> features = null;
2225 final int innerDepth = parser.getDepth();
2226 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2227 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2228 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2229 continue;
2230 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07002231
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002232 final String innerTagName = parser.getName();
2233 if (innerTagName.equals("uses-feature")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002234 FeatureInfo featureInfo = parseUsesFeature(res, parser);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002235 // FeatureGroups are stricter and mandate that
2236 // any <uses-feature> declared are mandatory.
2237 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
2238 features = ArrayUtils.add(features, featureInfo);
2239 } else {
2240 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
2241 " at " + mArchiveSourcePath + " " +
2242 parser.getPositionDescription());
2243 }
2244 XmlUtils.skipCurrentTag(parser);
2245 }
2246
2247 if (features != null) {
2248 group.features = new FeatureInfo[features.size()];
2249 group.features = features.toArray(group.features);
2250 }
2251 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07002252
Svet Ganov354cd3c2015-12-17 11:35:04 -08002253 } else if (tagName.equals(TAG_USES_SDK)) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07002254 if (SDK_VERSION > 0) {
Victor Hsieh4e54b522018-10-12 15:38:18 -07002255 sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesSdk);
2256 final TypedArray saFinal = sa;
2257 Pair<Integer, Integer> versions = deriveSdkVersions(
2258 new AbstractVersionsAccessor() {
2259 @Override public String getMinSdkVersionCode() {
2260 return getAttributeAsString(
2261 R.styleable.AndroidManifestUsesSdk_minSdkVersion);
2262 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002263
Victor Hsieh4e54b522018-10-12 15:38:18 -07002264 @Override public int getMinSdkVersion() {
2265 return getAttributeAsInt(
2266 R.styleable.AndroidManifestUsesSdk_minSdkVersion);
2267 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002268
Victor Hsieh4e54b522018-10-12 15:38:18 -07002269 @Override public String getTargetSdkVersionCode() {
2270 return getAttributeAsString(
2271 R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
2272 }
2273
2274 @Override public int getTargetSdkVersion() {
2275 return getAttributeAsInt(
2276 R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
2277 }
2278
2279 private String getAttributeAsString(int index) {
2280 TypedValue val = saFinal.peekValue(index);
2281 if (val != null && val.type == TypedValue.TYPE_STRING
2282 && val.string != null) {
2283 return val.string.toString();
2284 }
2285 return null;
2286 }
2287
2288 private int getAttributeAsInt(int index) {
2289 TypedValue val = saFinal.peekValue(index);
2290 if (val != null && val.type != TypedValue.TYPE_STRING) {
2291 // If it's not a string, it's an integer.
2292 return val.data;
2293 }
2294 return -1;
2295 }
2296 }, flags, outError);
2297
2298 if (versions == null) {
2299 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2300 return null;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002301 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002302
Victor Hsieh4e54b522018-10-12 15:38:18 -07002303 pkg.applicationInfo.minSdkVersion = versions.first;
2304 pkg.applicationInfo.targetSdkVersion = versions.second;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002306 sa.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002308 XmlUtils.skipCurrentTag(parser);
Svet Ganov354cd3c2015-12-17 11:35:04 -08002309 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
2310 sa = res.obtainAttributes(parser,
Dianne Hackborn723738c2009-06-25 19:48:04 -07002311 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
2312
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002313 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
2314 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
2315 0);
2316 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
2317 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
2318 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07002319 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
2320 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
2321 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002322
Dianne Hackborn723738c2009-06-25 19:48:04 -07002323 // This is a trick to get a boolean and still able to detect
2324 // if a value was actually set.
2325 supportsSmallScreens = sa.getInteger(
2326 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
2327 supportsSmallScreens);
2328 supportsNormalScreens = sa.getInteger(
2329 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
2330 supportsNormalScreens);
2331 supportsLargeScreens = sa.getInteger(
2332 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
2333 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002334 supportsXLargeScreens = sa.getInteger(
2335 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
2336 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002337 resizeable = sa.getInteger(
2338 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002339 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002340 anyDensity = sa.getInteger(
2341 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
2342 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07002343
2344 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002345
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002346 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002347
Svet Ganov354cd3c2015-12-17 11:35:04 -08002348 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
2349 sa = res.obtainAttributes(parser,
Dianne Hackborn854060af2009-07-09 18:14:31 -07002350 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
2351
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002352 // Note: don't allow this value to be a reference to a resource
2353 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07002354 String name = sa.getNonResourceString(
2355 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
2356
2357 sa.recycle();
2358
Todd Kennedy232d29e2017-11-06 14:45:53 -08002359 if (name != null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002360 if (pkg.protectedBroadcasts == null) {
2361 pkg.protectedBroadcasts = new ArrayList<String>();
2362 }
2363 if (!pkg.protectedBroadcasts.contains(name)) {
2364 pkg.protectedBroadcasts.add(name.intern());
2365 }
2366 }
2367
2368 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002369
Svet Ganov354cd3c2015-12-17 11:35:04 -08002370 } else if (tagName.equals(TAG_INSTRUMENTATION)) {
2371 if (parseInstrumentation(pkg, res, parser, outError) == null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002372 return null;
2373 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002374 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
2375 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002376 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2377
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002378 String orig =sa.getNonConfigurationString(
2379 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002380 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002381 if (pkg.mOriginalPackages == null) {
2382 pkg.mOriginalPackages = new ArrayList<String>();
2383 pkg.mRealPackage = pkg.packageName;
2384 }
2385 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002386 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002387
2388 sa.recycle();
2389
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002390 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002391
Svet Ganov354cd3c2015-12-17 11:35:04 -08002392 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
2393 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002394 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2395
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002396 String name = sa.getNonConfigurationString(
2397 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002398
2399 sa.recycle();
2400
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002401 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002402 if (pkg.mAdoptPermissions == null) {
2403 pkg.mAdoptPermissions = new ArrayList<String>();
2404 }
2405 pkg.mAdoptPermissions.add(name);
2406 }
2407
2408 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002409
Svet Ganov354cd3c2015-12-17 11:35:04 -08002410 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002411 // Just skip this tag
2412 XmlUtils.skipCurrentTag(parser);
2413 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002414
Svet Ganov354cd3c2015-12-17 11:35:04 -08002415 } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002416 // Just skip this tag
2417 XmlUtils.skipCurrentTag(parser);
2418 continue;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002419 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
Michael Wrighteaeb1902013-09-05 18:15:57 -07002420 XmlUtils.skipCurrentTag(parser);
2421 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002422
Svet Ganov354cd3c2015-12-17 11:35:04 -08002423 } else if (tagName.equals(TAG_EAT_COMMENT)) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002424 // Just skip this tag
2425 XmlUtils.skipCurrentTag(parser);
2426 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002427
Svet Ganov354cd3c2015-12-17 11:35:04 -08002428 } else if (tagName.equals(TAG_PACKAGE)) {
Svet Ganova7532cf2016-05-02 08:13:17 -07002429 if (!MULTI_PACKAGE_APK_ENABLED) {
2430 XmlUtils.skipCurrentTag(parser);
2431 continue;
2432 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002433 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
2434 // If parsing a child failed the error is already set
2435 return null;
2436 }
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002437
2438 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
2439 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
2440 sa = res.obtainAttributes(parser,
2441 com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
2442 final String hash = sa.getNonConfigurationString(
2443 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
2444 sa.recycle();
2445
2446 pkg.restrictUpdateHash = null;
2447 if (hash != null) {
2448 final int hashLength = hash.length();
2449 final byte[] hashBytes = new byte[hashLength / 2];
2450 for (int i = 0; i < hashLength; i += 2){
2451 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
2452 + Character.digit(hash.charAt(i + 1), 16));
2453 }
2454 pkg.restrictUpdateHash = hashBytes;
2455 }
2456 }
2457
2458 XmlUtils.skipCurrentTag(parser);
2459
Dianne Hackborn854060af2009-07-09 18:14:31 -07002460 } else if (RIGID_PARSER) {
2461 outError[0] = "Bad element under <manifest>: "
2462 + parser.getName();
2463 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2464 return null;
2465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002466 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002467 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002468 + " at " + mArchiveSourcePath + " "
2469 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002470 XmlUtils.skipCurrentTag(parser);
2471 continue;
2472 }
2473 }
2474
2475 if (!foundApp && pkg.instrumentation.size() == 0) {
2476 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
2477 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
2478 }
2479
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002480 final int NP = PackageParser.NEW_PERMISSIONS.length;
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002481 StringBuilder newPermsMsg = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002482 for (int ip=0; ip<NP; ip++) {
2483 final PackageParser.NewPermissionInfo npi
2484 = PackageParser.NEW_PERMISSIONS[ip];
2485 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
2486 break;
2487 }
2488 if (!pkg.requestedPermissions.contains(npi.name)) {
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002489 if (newPermsMsg == null) {
2490 newPermsMsg = new StringBuilder(128);
2491 newPermsMsg.append(pkg.packageName);
2492 newPermsMsg.append(": compat added ");
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002493 } else {
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002494 newPermsMsg.append(' ');
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002495 }
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002496 newPermsMsg.append(npi.name);
Chad Brubakere2107312019-02-04 12:30:01 -08002497 pkg.requestedPermissions.add(npi.name);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002498 pkg.implicitPermissions.add(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002499 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002500 }
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002501 if (newPermsMsg != null) {
2502 Slog.i(TAG, newPermsMsg.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002503 }
Dianne Hackborn79245122012-03-12 10:51:26 -07002504
Philip P. Moltmann039678e2018-09-18 13:04:38 -07002505
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -07002506 final int NS = PermissionManager.SPLIT_PERMISSIONS.size();
Dianne Hackborn79245122012-03-12 10:51:26 -07002507 for (int is=0; is<NS; is++) {
Philip P. Moltmann039678e2018-09-18 13:04:38 -07002508 final PermissionManager.SplitPermissionInfo spi =
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -07002509 PermissionManager.SPLIT_PERMISSIONS.get(is);
Philip P. Moltmann039678e2018-09-18 13:04:38 -07002510 if (pkg.applicationInfo.targetSdkVersion >= spi.getTargetSdk()
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -07002511 || !pkg.requestedPermissions.contains(spi.getSplitPermission())) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07002512 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07002513 }
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -07002514 final List<String> newPerms = spi.getNewPermissions();
2515 for (int in = 0; in < newPerms.size(); in++) {
2516 final String perm = newPerms.get(in);
Dianne Hackborn79245122012-03-12 10:51:26 -07002517 if (!pkg.requestedPermissions.contains(perm)) {
Chad Brubakere2107312019-02-04 12:30:01 -08002518 pkg.requestedPermissions.add(perm);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07002519 pkg.implicitPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07002520 }
2521 }
2522 }
2523
Dianne Hackborn723738c2009-06-25 19:48:04 -07002524 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
2525 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002526 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002527 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
2528 }
2529 if (supportsNormalScreens != 0) {
2530 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
2531 }
2532 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
2533 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002534 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002535 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
2536 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002537 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
2538 && pkg.applicationInfo.targetSdkVersion
2539 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
2540 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
2541 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002542 if (resizeable < 0 || (resizeable > 0
2543 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002544 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002545 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
2546 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002547 if (anyDensity < 0 || (anyDensity > 0
2548 && pkg.applicationInfo.targetSdkVersion
2549 >= android.os.Build.VERSION_CODES.DONUT)) {
2550 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07002551 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07002552
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002553 // At this point we can check if an application is not supporting densities and hence
2554 // cannot be windowed / resized. Note that an SDK version of 0 is common for
2555 // pre-Doughnut applications.
2556 if (pkg.applicationInfo.usesCompatibilityMode()) {
Winson Chungd3395382016-12-13 11:49:09 -08002557 adjustPackageToBeUnresizeableAndUnpipable(pkg);
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002558 }
Jeff Sharkey4aacd8b2018-07-24 15:24:21 -06002559
2560 // If the storage model feature flag is disabled, we need to fiddle
2561 // around with permission definitions to return us to pre-Q behavior.
2562 // STOPSHIP(b/112545973): remove once feature enabled by default
Jeff Sharkey10ec9d82018-11-28 14:52:45 -07002563 if (!StorageManager.hasIsolatedStorage()) {
Jeff Sharkey4aacd8b2018-07-24 15:24:21 -06002564 if ("android".equals(pkg.packageName)) {
2565 final ArraySet<String> newGroups = new ArraySet<>();
2566 newGroups.add(android.Manifest.permission_group.MEDIA_AURAL);
2567 newGroups.add(android.Manifest.permission_group.MEDIA_VISUAL);
2568
2569 for (int i = pkg.permissionGroups.size() - 1; i >= 0; i--) {
2570 final PermissionGroup pg = pkg.permissionGroups.get(i);
2571 if (newGroups.contains(pg.info.name)) {
2572 pkg.permissionGroups.remove(i);
2573 }
2574 }
2575
2576 final ArraySet<String> newPermissions = new ArraySet<>();
2577 newPermissions.add(android.Manifest.permission.READ_MEDIA_AUDIO);
Jeff Sharkey4aacd8b2018-07-24 15:24:21 -06002578 newPermissions.add(android.Manifest.permission.READ_MEDIA_VIDEO);
Jeff Sharkey4aacd8b2018-07-24 15:24:21 -06002579 newPermissions.add(android.Manifest.permission.READ_MEDIA_IMAGES);
Jeff Sharkey4aacd8b2018-07-24 15:24:21 -06002580 newPermissions.add(android.Manifest.permission.ACCESS_MEDIA_LOCATION);
2581 newPermissions.add(android.Manifest.permission.WRITE_OBB);
2582
Jeff Sharkey9787a9452018-11-18 17:53:02 -07002583 final ArraySet<String> removedPermissions = new ArraySet<>();
2584 removedPermissions.add(android.Manifest.permission.READ_EXTERNAL_STORAGE);
2585 removedPermissions.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
Jeff Sharkey4aacd8b2018-07-24 15:24:21 -06002586
2587 for (int i = pkg.permissions.size() - 1; i >= 0; i--) {
2588 final Permission p = pkg.permissions.get(i);
2589 if (newPermissions.contains(p.info.name)) {
2590 pkg.permissions.remove(i);
Jeff Sharkey9787a9452018-11-18 17:53:02 -07002591 } else if (removedPermissions.contains(p.info.name)) {
2592 p.info.flags &= ~PermissionInfo.FLAG_REMOVED;
Jeff Sharkey4aacd8b2018-07-24 15:24:21 -06002593 }
2594 }
2595 }
Jeff Sharkey669e6b12018-10-27 17:58:44 -06002596 } else {
2597 if (FORCE_AUDIO_PACKAGES.contains(pkg.packageName)) {
Chad Brubakere2107312019-02-04 12:30:01 -08002598 pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_AUDIO);
Jeff Sharkey669e6b12018-10-27 17:58:44 -06002599 }
2600 if (FORCE_VIDEO_PACKAGES.contains(pkg.packageName)) {
Chad Brubakere2107312019-02-04 12:30:01 -08002601 pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_VIDEO);
Jeff Sharkey669e6b12018-10-27 17:58:44 -06002602 }
2603 if (FORCE_IMAGES_PACKAGES.contains(pkg.packageName)) {
Chad Brubakere2107312019-02-04 12:30:01 -08002604 pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_IMAGES);
Jeff Sharkey669e6b12018-10-27 17:58:44 -06002605 }
Jeff Sharkey4aacd8b2018-07-24 15:24:21 -06002606 }
2607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002608 return pkg;
2609 }
2610
Todd Leeea2f3be2017-03-16 14:00:52 -07002611 private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
2612
2613 if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
2614 if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
2615 // malformed condition - incomplete
2616 Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
2617 + "=" + propValue + "' - require both requiredSystemPropertyName"
2618 + " AND requiredSystemPropertyValue to be specified.");
2619 return false;
2620 }
2621 // no valid condition set - so no exclusion criteria, overlay will be included.
2622 return true;
2623 }
2624
2625 // check property value - make sure it is both set and equal to expected value
2626 final String currValue = SystemProperties.get(propName);
2627 return (currValue != null && currValue.equals(propValue));
2628 }
2629
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002630 /**
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002631 * This is a pre-density application which will get scaled - instead of being pixel perfect.
2632 * This type of application is not resizable.
2633 *
2634 * @param pkg The package which needs to be marked as unresizable.
2635 */
Winson Chungd3395382016-12-13 11:49:09 -08002636 private void adjustPackageToBeUnresizeableAndUnpipable(Package pkg) {
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002637 for (Activity a : pkg.activities) {
2638 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -08002639 a.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE;
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002640 }
2641 }
2642
2643 /**
Chad Brubakera58ce392018-10-29 14:14:22 -07002644
2645 /**
Narayan Kamath71fcc142019-01-15 18:20:39 +00002646 * Matches a given {@code targetCode} against a set of release codeNames. Target codes can
2647 * either be of the form {@code [codename]}" (e.g {@code "Q"}) or of the form
2648 * {@code [codename].[fingerprint]} (e.g {@code "Q.cafebc561"}).
2649 */
2650 private static boolean matchTargetCode(@NonNull String[] codeNames,
2651 @NonNull String targetCode) {
2652 final String targetCodeName;
2653 final int targetCodeIdx = targetCode.indexOf('.');
2654 if (targetCodeIdx == -1) {
2655 targetCodeName = targetCode;
2656 } else {
2657 targetCodeName = targetCode.substring(0, targetCodeIdx);
2658 }
2659 return ArrayUtils.contains(codeNames, targetCodeName);
2660 }
2661
2662 /**
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002663 * Computes the targetSdkVersion to use at runtime. If the package is not
2664 * compatible with this platform, populates {@code outError[0]} with an
2665 * error message.
2666 * <p>
2667 * If {@code targetCode} is not specified, e.g. the value is {@code null},
2668 * then the {@code targetVers} will be returned unmodified.
2669 * <p>
2670 * Otherwise, the behavior varies based on whether the current platform
2671 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2672 * has length > 0:
2673 * <ul>
2674 * <li>If this is a pre-release platform and the value specified by
2675 * {@code targetCode} is contained within the array of allowed pre-release
2676 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2677 * <li>If this is a released platform, this method will return -1 to
2678 * indicate that the package is not compatible with this platform.
2679 * </ul>
2680 *
2681 * @param targetVers targetSdkVersion number, if specified in the
2682 * application manifest, or 0 otherwise
2683 * @param targetCode targetSdkVersion code, if specified in the application
2684 * manifest, or {@code null} otherwise
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002685 * @param platformSdkCodenames array of allowed pre-release SDK codenames
2686 * for this platform
2687 * @param outError output array to populate with error, if applicable
2688 * @return the targetSdkVersion to use at runtime, or -1 if the package is
2689 * not compatible with this platform
2690 * @hide Exposed for unit testing only.
2691 */
2692 @TestApi
2693 public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002694 @Nullable String targetCode, @NonNull String[] platformSdkCodenames,
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +00002695 @NonNull String[] outError) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002696 // If it's a release SDK, return the version number unmodified.
2697 if (targetCode == null) {
2698 return targetVers;
2699 }
2700
2701 // If it's a pre-release SDK and the codename matches this platform, it
2702 // definitely targets this SDK.
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +00002703 if (matchTargetCode(platformSdkCodenames, targetCode)) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002704 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2705 }
2706
2707 // Otherwise, we're looking at an incompatible pre-release SDK.
2708 if (platformSdkCodenames.length > 0) {
2709 outError[0] = "Requires development platform " + targetCode
2710 + " (current platform is any of "
2711 + Arrays.toString(platformSdkCodenames) + ")";
2712 } else {
2713 outError[0] = "Requires development platform " + targetCode
2714 + " but this is a release platform.";
2715 }
2716 return -1;
2717 }
2718
Victor Hsieh4e54b522018-10-12 15:38:18 -07002719 private interface AbstractVersionsAccessor {
2720 /** Returns minimum SDK version code string, or null if absent. */
2721 String getMinSdkVersionCode();
2722
2723 /** Returns minimum SDK version code, or -1 if absent. */
2724 int getMinSdkVersion();
2725
2726 /** Returns target SDK version code string, or null if absent. */
2727 String getTargetSdkVersionCode();
2728
2729 /** Returns target SDK version code, or -1 if absent. */
2730 int getTargetSdkVersion();
2731 }
2732
2733 private static @Nullable Pair<Integer, Integer> deriveSdkVersions(
2734 @NonNull AbstractVersionsAccessor accessor, int flags, String[] outError) {
2735 int minVers = 1;
2736 String minCode = null;
2737 int targetVers = 0;
2738 String targetCode = null;
2739
2740 String code = accessor.getMinSdkVersionCode();
2741 int version = accessor.getMinSdkVersion();
2742 // Check integer first since code is almost never a null string (e.g. "28").
2743 if (version >= 0) {
2744 minVers = version;
2745 } else if (code != null) {
2746 minCode = code;
2747 }
2748
2749 code = accessor.getTargetSdkVersionCode();
2750 version = accessor.getTargetSdkVersion();
2751 // Check integer first since code is almost never a null string (e.g. "28").
2752 if (version >= 0) {
2753 targetVers = version;
2754 } else if (code != null) {
2755 targetCode = code;
2756 if (minCode == null) {
2757 minCode = targetCode;
2758 }
2759 } else {
2760 targetVers = minVers;
2761 targetCode = minCode;
2762 }
2763
2764 final int minSdkVersion = computeMinSdkVersion(minVers, minCode,
2765 SDK_VERSION, SDK_CODENAMES, outError);
2766 if (minSdkVersion < 0) {
2767 return null;
2768 }
2769
Victor Hsieh4e54b522018-10-12 15:38:18 -07002770 final int targetSdkVersion = computeTargetSdkVersion(targetVers,
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +00002771 targetCode, SDK_CODENAMES, outError);
Victor Hsieh4e54b522018-10-12 15:38:18 -07002772 if (targetSdkVersion < 0) {
2773 return null;
2774 }
2775
2776 return Pair.create(minSdkVersion, targetSdkVersion);
2777 }
2778
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002779 /**
2780 * Computes the minSdkVersion to use at runtime. If the package is not
2781 * compatible with this platform, populates {@code outError[0]} with an
2782 * error message.
2783 * <p>
2784 * If {@code minCode} is not specified, e.g. the value is {@code null},
2785 * then behavior varies based on the {@code platformSdkVersion}:
2786 * <ul>
2787 * <li>If the platform SDK version is greater than or equal to the
2788 * {@code minVers}, returns the {@code mniVers} unmodified.
2789 * <li>Otherwise, returns -1 to indicate that the package is not
2790 * compatible with this platform.
2791 * </ul>
2792 * <p>
2793 * Otherwise, the behavior varies based on whether the current platform
2794 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2795 * has length > 0:
2796 * <ul>
2797 * <li>If this is a pre-release platform and the value specified by
2798 * {@code targetCode} is contained within the array of allowed pre-release
2799 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2800 * <li>If this is a released platform, this method will return -1 to
2801 * indicate that the package is not compatible with this platform.
2802 * </ul>
2803 *
2804 * @param minVers minSdkVersion number, if specified in the application
2805 * manifest, or 1 otherwise
2806 * @param minCode minSdkVersion code, if specified in the application
2807 * manifest, or {@code null} otherwise
2808 * @param platformSdkVersion platform SDK version number, typically
2809 * Build.VERSION.SDK_INT
2810 * @param platformSdkCodenames array of allowed prerelease SDK codenames
2811 * for this platform
2812 * @param outError output array to populate with error, if applicable
2813 * @return the minSdkVersion to use at runtime, or -1 if the package is not
2814 * compatible with this platform
2815 * @hide Exposed for unit testing only.
2816 */
2817 @TestApi
2818 public static int computeMinSdkVersion(@IntRange(from = 1) int minVers,
2819 @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion,
2820 @NonNull String[] platformSdkCodenames, @NonNull String[] outError) {
2821 // If it's a release SDK, make sure we meet the minimum SDK requirement.
2822 if (minCode == null) {
2823 if (minVers <= platformSdkVersion) {
2824 return minVers;
2825 }
2826
2827 // We don't meet the minimum SDK requirement.
2828 outError[0] = "Requires newer sdk version #" + minVers
2829 + " (current version is #" + platformSdkVersion + ")";
2830 return -1;
2831 }
2832
2833 // If it's a pre-release SDK and the codename matches this platform, we
2834 // definitely meet the minimum SDK requirement.
Narayan Kamath71fcc142019-01-15 18:20:39 +00002835 if (matchTargetCode(platformSdkCodenames, minCode)) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002836 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2837 }
2838
2839 // Otherwise, we're looking at an incompatible pre-release SDK.
2840 if (platformSdkCodenames.length > 0) {
2841 outError[0] = "Requires development platform " + minCode
2842 + " (current platform is any of "
2843 + Arrays.toString(platformSdkCodenames) + ")";
2844 } else {
2845 outError[0] = "Requires development platform " + minCode
2846 + " but this is a release platform.";
2847 }
2848 return -1;
2849 }
2850
Todd Kennedy27c24fb2015-09-17 16:49:25 -07002851 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002852 FeatureInfo fi = new FeatureInfo();
2853 TypedArray sa = res.obtainAttributes(attrs,
2854 com.android.internal.R.styleable.AndroidManifestUsesFeature);
2855 // Note: don't allow this value to be a reference to a resource
2856 // that may change.
2857 fi.name = sa.getNonResourceString(
2858 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
Jeff Sharkey115d2c12016-02-15 17:25:57 -07002859 fi.version = sa.getInt(
2860 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002861 if (fi.name == null) {
2862 fi.reqGlEsVersion = sa.getInt(
2863 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
2864 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2865 }
2866 if (sa.getBoolean(
2867 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
2868 fi.flags |= FeatureInfo.FLAG_REQUIRED;
2869 }
2870 sa.recycle();
2871 return fi;
2872 }
2873
Svet Ganov67882122016-12-11 16:36:34 -08002874 private boolean parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser,
2875 String[] outError) throws XmlPullParserException, IOException {
2876 TypedArray sa = res.obtainAttributes(parser,
2877 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary);
2878
2879 // Note: don't allow this value to be a reference to a resource that may change.
2880 String lname = sa.getNonResourceString(
2881 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
2882 final int version = sa.getInt(
2883 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002884 String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable
Svet Ganov67882122016-12-11 16:36:34 -08002885 .AndroidManifestUsesStaticLibrary_certDigest);
2886 sa.recycle();
2887
2888 // Since an APK providing a static shared lib can only provide the lib - fail if malformed
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002889 if (lname == null || version < 0 || certSha256Digest == null) {
Svet Ganov67882122016-12-11 16:36:34 -08002890 outError[0] = "Bad uses-static-library declaration name: " + lname + " version: "
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002891 + version + " certDigest" + certSha256Digest;
Svet Ganov67882122016-12-11 16:36:34 -08002892 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2893 XmlUtils.skipCurrentTag(parser);
2894 return false;
2895 }
2896
2897 // Can depend only on one version of the same library
2898 if (pkg.usesStaticLibraries != null && pkg.usesStaticLibraries.contains(lname)) {
2899 outError[0] = "Depending on multiple versions of static library " + lname;
2900 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2901 XmlUtils.skipCurrentTag(parser);
2902 return false;
2903 }
2904
2905 lname = lname.intern();
2906 // We allow ":" delimiters in the SHA declaration as this is the format
2907 // emitted by the certtool making it easy for developers to copy/paste.
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002908 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2909
2910 // Fot apps targeting O-MR1 we require explicit enumeration of all certs.
2911 String[] additionalCertSha256Digests = EmptyArray.STRING;
Jeff Sharkeyaa1a9112018-04-10 15:18:12 -06002912 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O_MR1) {
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002913 additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError);
2914 if (additionalCertSha256Digests == null) {
2915 return false;
2916 }
2917 } else {
2918 XmlUtils.skipCurrentTag(parser);
2919 }
2920
2921 final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1];
2922 certSha256Digests[0] = certSha256Digest;
2923 System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
2924 1, additionalCertSha256Digests.length);
2925
Svet Ganov67882122016-12-11 16:36:34 -08002926 pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname);
Dianne Hackborn3accca02013-09-20 09:32:11 -07002927 pkg.usesStaticLibrariesVersions = ArrayUtils.appendLong(
Svet Ganov8a10ef52017-02-16 20:58:09 -08002928 pkg.usesStaticLibrariesVersions, version, true);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002929 pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
2930 pkg.usesStaticLibrariesCertDigests, certSha256Digests, true);
Svet Ganov67882122016-12-11 16:36:34 -08002931
2932 return true;
2933 }
2934
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002935 private String[] parseAdditionalCertificates(Resources resources, XmlResourceParser parser,
2936 String[] outError) throws XmlPullParserException, IOException {
2937 String[] certSha256Digests = EmptyArray.STRING;
2938
2939 int outerDepth = parser.getDepth();
2940 int type;
2941 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2942 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2943 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2944 continue;
2945 }
2946
2947 final String nodeName = parser.getName();
2948 if (nodeName.equals("additional-certificate")) {
2949 final TypedArray sa = resources.obtainAttributes(parser, com.android.internal.
2950 R.styleable.AndroidManifestAdditionalCertificate);
2951 String certSha256Digest = sa.getNonResourceString(com.android.internal.
2952 R.styleable.AndroidManifestAdditionalCertificate_certDigest);
2953 sa.recycle();
2954
2955 if (TextUtils.isEmpty(certSha256Digest)) {
2956 outError[0] = "Bad additional-certificate declaration with empty"
2957 + " certDigest:" + certSha256Digest;
2958 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2959 XmlUtils.skipCurrentTag(parser);
2960 sa.recycle();
2961 return null;
2962 }
2963
2964 // We allow ":" delimiters in the SHA declaration as this is the format
2965 // emitted by the certtool making it easy for developers to copy/paste.
2966 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2967 certSha256Digests = ArrayUtils.appendElement(String.class,
2968 certSha256Digests, certSha256Digest);
2969 } else {
2970 XmlUtils.skipCurrentTag(parser);
2971 }
2972 }
2973
2974 return certSha256Digests;
2975 }
2976
Chad Brubakere2107312019-02-04 12:30:01 -08002977 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
2978 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002979 TypedArray sa = res.obtainAttributes(parser,
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002980 com.android.internal.R.styleable.AndroidManifestUsesPermission);
2981
2982 // Note: don't allow this value to be a reference to a resource
2983 // that may change.
2984 String name = sa.getNonResourceString(
2985 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002986
Christopher Tatefb0676a2013-09-16 16:34:52 -07002987 int maxSdkVersion = 0;
2988 TypedValue val = sa.peekValue(
2989 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
2990 if (val != null) {
2991 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
2992 maxSdkVersion = val.data;
2993 }
2994 }
2995
Dianne Hackborncd154e92017-02-28 17:37:35 -08002996 final String requiredFeature = sa.getNonConfigurationString(
2997 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
2998
2999 final String requiredNotfeature = sa.getNonConfigurationString(
3000 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
3001
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07003002 sa.recycle();
3003
Dianne Hackborncd154e92017-02-28 17:37:35 -08003004 XmlUtils.skipCurrentTag(parser);
3005
3006 if (name == null) {
3007 return true;
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07003008 }
3009
Dianne Hackborncd154e92017-02-28 17:37:35 -08003010 if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
3011 return true;
3012 }
3013
3014 // Only allow requesting this permission if the platform supports the given feature.
3015 if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
3016 return true;
3017 }
3018
3019 // Only allow requesting this permission if the platform doesn't support the given feature.
3020 if (requiredNotfeature != null && mCallback != null
3021 && mCallback.hasFeature(requiredNotfeature)) {
3022 return true;
3023 }
3024
3025 int index = pkg.requestedPermissions.indexOf(name);
3026 if (index == -1) {
3027 pkg.requestedPermissions.add(name.intern());
3028 } else {
3029 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
3030 + name + " in package: " + pkg.packageName + " at: "
3031 + parser.getPositionDescription());
3032 }
3033
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07003034 return true;
3035 }
3036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003037 private static String buildClassName(String pkg, CharSequence clsSeq,
3038 String[] outError) {
3039 if (clsSeq == null || clsSeq.length() <= 0) {
3040 outError[0] = "Empty class name in package " + pkg;
3041 return null;
3042 }
3043 String cls = clsSeq.toString();
3044 char c = cls.charAt(0);
3045 if (c == '.') {
Narayan Kamath07ac1442017-02-10 15:08:07 +00003046 return pkg + cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003047 }
3048 if (cls.indexOf('.') < 0) {
3049 StringBuilder b = new StringBuilder(pkg);
3050 b.append('.');
3051 b.append(cls);
Narayan Kamath07ac1442017-02-10 15:08:07 +00003052 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003053 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00003054 return cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055 }
3056
3057 private static String buildCompoundName(String pkg,
3058 CharSequence procSeq, String type, String[] outError) {
3059 String proc = procSeq.toString();
3060 char c = proc.charAt(0);
3061 if (pkg != null && c == ':') {
3062 if (proc.length() < 2) {
3063 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
3064 + ": must be at least two characters";
3065 return null;
3066 }
3067 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07003068 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 if (nameError != null) {
3070 outError[0] = "Invalid " + type + " name " + proc + " in package "
3071 + pkg + ": " + nameError;
3072 return null;
3073 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00003074 return pkg + proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003075 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07003076 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003077 if (nameError != null && !"system".equals(proc)) {
3078 outError[0] = "Invalid " + type + " name " + proc + " in package "
3079 + pkg + ": " + nameError;
3080 return null;
3081 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00003082 return proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003083 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003085 private static String buildProcessName(String pkg, String defProc,
3086 CharSequence procSeq, int flags, String[] separateProcesses,
3087 String[] outError) {
3088 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
3089 return defProc != null ? defProc : pkg;
3090 }
3091 if (separateProcesses != null) {
3092 for (int i=separateProcesses.length-1; i>=0; i--) {
3093 String sp = separateProcesses[i];
3094 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
3095 return pkg;
3096 }
3097 }
3098 }
3099 if (procSeq == null || procSeq.length() <= 0) {
3100 return defProc;
3101 }
Makoto Onuki812d188a2017-08-07 09:58:23 -07003102 return TextUtils.safeIntern(buildCompoundName(pkg, procSeq, "process", outError));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003103 }
3104
3105 private static String buildTaskAffinityName(String pkg, String defProc,
3106 CharSequence procSeq, String[] outError) {
3107 if (procSeq == null) {
3108 return defProc;
3109 }
3110 if (procSeq.length() <= 0) {
3111 return null;
3112 }
3113 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
3114 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003115
dcashman989eb3712014-06-17 12:56:12 -07003116 private boolean parseKeySets(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003117 XmlResourceParser parser, String[] outError)
Geremy Condraf1bcca82013-01-07 22:35:24 -08003118 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07003119 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08003120 // all the keys and keysets that we want must be defined here
3121 // so we're going to iterate over the parser and pull out the things we want
3122 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07003123 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003124 int type;
dcashman989eb3712014-06-17 12:56:12 -07003125 String currentKeySet = null;
3126 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
3127 ArraySet<String> upgradeKeySets = new ArraySet<String>();
3128 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
3129 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08003130 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3131 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
3132 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07003133 if (parser.getDepth() == currentKeySetDepth) {
3134 currentKeySet = null;
3135 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07003136 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003137 continue;
3138 }
dcashman989eb3712014-06-17 12:56:12 -07003139 String tagName = parser.getName();
3140 if (tagName.equals("key-set")) {
3141 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07003142 outError[0] = "Improperly nested 'key-set' tag at "
3143 + parser.getPositionDescription();
3144 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003145 return false;
3146 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08003147 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003148 com.android.internal.R.styleable.AndroidManifestKeySet);
3149 final String keysetName = sa.getNonResourceString(
3150 com.android.internal.R.styleable.AndroidManifestKeySet_name);
3151 definedKeySets.put(keysetName, new ArraySet<String>());
3152 currentKeySet = keysetName;
3153 currentKeySetDepth = parser.getDepth();
3154 sa.recycle();
3155 } else if (tagName.equals("public-key")) {
3156 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07003157 outError[0] = "Improperly nested 'key-set' tag at "
3158 + parser.getPositionDescription();
3159 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003160 return false;
3161 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08003162 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003163 com.android.internal.R.styleable.AndroidManifestPublicKey);
3164 final String publicKeyName = sa.getNonResourceString(
3165 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003166 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07003167 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
3168 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07003169 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
3170 + " on first use at " + parser.getPositionDescription();
3171 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07003172 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003173 return false;
3174 } else if (encodedKey != null) {
3175 PublicKey currentKey = parsePublicKey(encodedKey);
3176 if (currentKey == null) {
3177 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
3178 + parser.getPositionDescription() + " key-set " + currentKeySet
3179 + " will not be added to the package's defined key-sets.");
3180 sa.recycle();
3181 improperKeySets.add(currentKeySet);
3182 XmlUtils.skipCurrentTag(parser);
3183 continue;
3184 }
3185 if (publicKeys.get(publicKeyName) == null
3186 || publicKeys.get(publicKeyName).equals(currentKey)) {
3187
3188 /* public-key first definition, or matches old definition */
3189 publicKeys.put(publicKeyName, currentKey);
3190 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003191 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07003192 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07003193 + parser.getPositionDescription();
3194 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003195 sa.recycle();
3196 return false;
3197 }
Kenny Root37dca152013-07-10 14:01:49 -07003198 }
dcashman989eb3712014-06-17 12:56:12 -07003199 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003200 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003201 XmlUtils.skipCurrentTag(parser);
3202 } else if (tagName.equals("upgrade-key-set")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003203 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003204 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
3205 String name = sa.getNonResourceString(
3206 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
3207 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003208 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003209 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003210 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07003211 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003212 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07003213 + parser.getPositionDescription();
3214 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003215 return false;
3216 } else {
dcashman989eb3712014-06-17 12:56:12 -07003217 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003218 + " at " + mArchiveSourcePath + " "
3219 + parser.getPositionDescription());
3220 XmlUtils.skipCurrentTag(parser);
3221 continue;
3222 }
3223 }
dcashman989eb3712014-06-17 12:56:12 -07003224 Set<String> publicKeyNames = publicKeys.keySet();
3225 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07003226 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
3227 + "'key-set' and 'public-key' names must be distinct.";
3228 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003229 return false;
3230 }
3231 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
3232 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
3233 final String keySetName = e.getKey();
3234 if (e.getValue().size() == 0) {
3235 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3236 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
3237 + " Not including in package's defined key-sets.");
3238 continue;
3239 } else if (improperKeySets.contains(keySetName)) {
3240 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3241 + "'key-set' " + keySetName + " contained improper 'public-key'"
3242 + " tags. Not including in package's defined key-sets.");
3243 continue;
3244 }
3245 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
3246 for (String s : e.getValue()) {
3247 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08003248 }
3249 }
dcashman989eb3712014-06-17 12:56:12 -07003250 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
3251 owner.mUpgradeKeySets = upgradeKeySets;
3252 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003253 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
3254 + "does not define all 'upgrade-key-set's .";
3255 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003256 return false;
3257 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003258 return true;
3259 }
3260
Dianne Hackborncd154e92017-02-28 17:37:35 -08003261 private boolean parsePermissionGroup(Package owner, int flags, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003262 XmlResourceParser parser, String[] outError)
3263 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003264 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003265 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
Philip P. Moltmann0635dab2019-03-02 11:19:03 -08003266
3267 int requestDetailResourceId = sa.getResourceId(
3268 com.android.internal.R.styleable.AndroidManifestPermissionGroup_requestDetail, 0);
3269 int backgroundRequestResourceId = sa.getResourceId(
3270 com.android.internal.R.styleable.AndroidManifestPermissionGroup_backgroundRequest,
3271 0);
3272 int backgroundRequestDetailResourceId = sa.getResourceId(
3273 com.android.internal.R.styleable
3274 .AndroidManifestPermissionGroup_backgroundRequestDetail, 0);
3275
3276 PermissionGroup perm = new PermissionGroup(owner, requestDetailResourceId,
3277 backgroundRequestResourceId, backgroundRequestDetailResourceId);
3278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003279 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003280 "<permission-group>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003281 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
3282 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003283 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003284 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003285 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
3286 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003287 sa.recycle();
3288 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003289 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003290 }
3291
3292 perm.info.descriptionRes = sa.getResourceId(
3293 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
3294 0);
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003295 perm.info.requestRes = sa.getResourceId(
3296 com.android.internal.R.styleable.AndroidManifestPermissionGroup_request, 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07003297 perm.info.flags = sa.getInt(
3298 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07003299 perm.info.priority = sa.getInt(
3300 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003301
3302 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003303
Svet Ganov354cd3c2015-12-17 11:35:04 -08003304 if (!parseAllMetaData(res, parser, "<permission-group>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 outError)) {
3306 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003307 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003308 }
3309
3310 owner.permissionGroups.add(perm);
3311
Dianne Hackborncd154e92017-02-28 17:37:35 -08003312 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003313 }
3314
Dianne Hackborncd154e92017-02-28 17:37:35 -08003315 private boolean parsePermission(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003316 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003318
Svet Ganov354cd3c2015-12-17 11:35:04 -08003319 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003320 com.android.internal.R.styleable.AndroidManifestPermission);
3321
Philip P. Moltmanna4844d12019-03-02 10:17:23 -08003322 String backgroundPermission = null;
3323 if (sa.hasValue(
3324 com.android.internal.R.styleable.AndroidManifestPermission_backgroundPermission)) {
3325 if ("android".equals(owner.packageName)) {
3326 backgroundPermission = sa.getNonResourceString(
3327 com.android.internal.R.styleable
3328 .AndroidManifestPermission_backgroundPermission);
3329 } else {
3330 Slog.w(TAG, owner.packageName + " defines a background permission. Only the "
3331 + "'android' package can do that.");
3332 }
3333 }
3334
3335 Permission perm = new Permission(owner, backgroundPermission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003336 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003337 "<permission>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003338 com.android.internal.R.styleable.AndroidManifestPermission_name,
3339 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003340 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003341 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003342 com.android.internal.R.styleable.AndroidManifestPermission_logo,
3343 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 sa.recycle();
3345 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003346 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 }
3348
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003349 // Note: don't allow this value to be a reference to a resource
3350 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003351 perm.info.group = sa.getNonResourceString(
3352 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
3353 if (perm.info.group != null) {
3354 perm.info.group = perm.info.group.intern();
3355 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003357 perm.info.descriptionRes = sa.getResourceId(
3358 com.android.internal.R.styleable.AndroidManifestPermission_description,
3359 0);
3360
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003361 perm.info.requestRes = sa.getResourceId(
3362 com.android.internal.R.styleable.AndroidManifestPermission_request, 0);
3363
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003364 perm.info.protectionLevel = sa.getInt(
3365 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
3366 PermissionInfo.PROTECTION_NORMAL);
3367
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07003368 perm.info.flags = sa.getInt(
3369 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
3370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003371 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08003372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003373 if (perm.info.protectionLevel == -1) {
3374 outError[0] = "<permission> does not specify protectionLevel";
3375 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003376 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377 }
Dianne Hackborne639da72012-02-21 15:11:13 -08003378
3379 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
3380
Makoto Onuki700feef2018-02-15 10:59:41 -08003381 if (perm.info.getProtectionFlags() != 0) {
Todd Kennedyc247fa12017-06-02 10:29:22 -07003382 if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_INSTANT) == 0
Chad Brubakera5d70a12017-03-23 11:04:50 -07003383 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0
Chad Brubakerc19706a2016-10-13 15:44:59 -07003384 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
Dianne Hackborne639da72012-02-21 15:11:13 -08003385 PermissionInfo.PROTECTION_SIGNATURE) {
Joe Maples39bb9e82018-01-11 11:09:46 -05003386 outError[0] = "<permission> protectionLevel specifies a non-instant flag but is "
Dianne Hackborne639da72012-02-21 15:11:13 -08003387 + "not based on signature type";
3388 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003389 return false;
Dianne Hackborne639da72012-02-21 15:11:13 -08003390 }
3391 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003392
Svet Ganov354cd3c2015-12-17 11:35:04 -08003393 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003394 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003395 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003396 }
3397
3398 owner.permissions.add(perm);
3399
Dianne Hackborncd154e92017-02-28 17:37:35 -08003400 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401 }
3402
Dianne Hackborncd154e92017-02-28 17:37:35 -08003403 private boolean parsePermissionTree(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003404 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003405 throws XmlPullParserException, IOException {
Philip P. Moltmanna4844d12019-03-02 10:17:23 -08003406 Permission perm = new Permission(owner, (String) null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003407
Svet Ganov354cd3c2015-12-17 11:35:04 -08003408 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003409 com.android.internal.R.styleable.AndroidManifestPermissionTree);
3410
3411 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003412 "<permission-tree>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003413 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
3414 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003415 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003416 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003417 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
3418 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003419 sa.recycle();
3420 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003421 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003422 }
3423
3424 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 int index = perm.info.name.indexOf('.');
3427 if (index > 0) {
3428 index = perm.info.name.indexOf('.', index+1);
3429 }
3430 if (index < 0) {
3431 outError[0] = "<permission-tree> name has less than three segments: "
3432 + perm.info.name;
3433 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003434 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003435 }
3436
3437 perm.info.descriptionRes = 0;
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003438 perm.info.requestRes = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003439 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
3440 perm.tree = true;
3441
Svet Ganov354cd3c2015-12-17 11:35:04 -08003442 if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003443 outError)) {
3444 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003445 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003446 }
3447
3448 owner.permissions.add(perm);
3449
Dianne Hackborncd154e92017-02-28 17:37:35 -08003450 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003451 }
3452
3453 private Instrumentation parseInstrumentation(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003454 XmlResourceParser parser, String[] outError)
3455 throws XmlPullParserException, IOException {
3456 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003457 com.android.internal.R.styleable.AndroidManifestInstrumentation);
3458
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003459 if (mParseInstrumentationArgs == null) {
3460 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
3461 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
3462 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003463 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003464 com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003465 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
3466 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003467 mParseInstrumentationArgs.tag = "<instrumentation>";
3468 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003469
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003470 mParseInstrumentationArgs.sa = sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003471
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003472 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
3473 new InstrumentationInfo());
3474 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003475 sa.recycle();
3476 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3477 return null;
3478 }
3479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003480 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003481 // Note: don't allow this value to be a reference to a resource
3482 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003483 str = sa.getNonResourceString(
3484 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
3485 a.info.targetPackage = str != null ? str.intern() : null;
3486
Dianne Hackborn34041732017-01-31 15:27:13 -08003487 str = sa.getNonResourceString(
Dianne Hackborn1be53542017-04-28 13:36:00 -07003488 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcesses);
3489 a.info.targetProcesses = str != null ? str.intern() : null;
Dianne Hackborn34041732017-01-31 15:27:13 -08003490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003491 a.info.handleProfiling = sa.getBoolean(
3492 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
3493 false);
3494
3495 a.info.functionalTest = sa.getBoolean(
3496 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
3497 false);
3498
3499 sa.recycle();
3500
3501 if (a.info.targetPackage == null) {
3502 outError[0] = "<instrumentation> does not specify targetPackage";
3503 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3504 return null;
3505 }
3506
Svet Ganov354cd3c2015-12-17 11:35:04 -08003507 if (!parseAllMetaData(res, parser, "<instrumentation>", a,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003508 outError)) {
3509 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3510 return null;
3511 }
3512
3513 owner.instrumentation.add(a);
3514
3515 return a;
3516 }
3517
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003518 /**
3519 * Parse the {@code application} XML tree at the current parse location in a
3520 * <em>base APK</em> manifest.
3521 * <p>
3522 * When adding new features, carefully consider if they should also be
3523 * supported by split APKs.
3524 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01003525 @UnsupportedAppUsage
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003526 private boolean parseBaseApplication(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003527 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003528 throws XmlPullParserException, IOException {
3529 final ApplicationInfo ai = owner.applicationInfo;
3530 final String pkgName = owner.applicationInfo.packageName;
3531
Svet Ganov354cd3c2015-12-17 11:35:04 -08003532 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533 com.android.internal.R.styleable.AndroidManifestApplication);
3534
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003535 if (!parsePackageItemInfo(owner, ai, outError,
3536 "<application>", sa, false /*nameRequired*/,
3537 com.android.internal.R.styleable.AndroidManifestApplication_name,
3538 com.android.internal.R.styleable.AndroidManifestApplication_label,
3539 com.android.internal.R.styleable.AndroidManifestApplication_icon,
3540 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
3541 com.android.internal.R.styleable.AndroidManifestApplication_logo,
3542 com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
3543 sa.recycle();
3544 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3545 return false;
3546 }
3547
3548 if (ai.name != null) {
Todd Kennedyafb52692016-08-22 15:44:00 -07003549 ai.className = ai.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003550 }
3551
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003552 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003553 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
3554 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003555 if (manageSpaceActivity != null) {
3556 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
3557 outError);
3558 }
3559
Christopher Tate181fafa2009-05-14 11:12:14 -07003560 boolean allowBackup = sa.getBoolean(
3561 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
3562 if (allowBackup) {
3563 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07003564
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003565 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
3566 // and restoreAnyVersion are only relevant if backup is possible for the
3567 // given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003568 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003569 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
3570 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07003571 if (backupAgent != null) {
3572 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07003573 if (DEBUG_BACKUP) {
3574 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003575 + " from " + pkgName + "+" + backupAgent);
3576 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003577
3578 if (sa.getBoolean(
3579 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
3580 true)) {
3581 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
3582 }
3583 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08003584 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
3585 false)) {
3586 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
3587 }
Christopher Tated1de2562014-06-17 17:12:35 -07003588 if (sa.getBoolean(
3589 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
3590 false)) {
3591 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
3592 }
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003593 if (sa.getBoolean(
3594 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
3595 false)) {
3596 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
3597 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003598 }
Matthew Williams303650c2015-04-17 18:22:51 -07003599
3600 TypedValue v = sa.peekValue(
3601 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
3602 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
3603 if (DEBUG_BACKUP) {
3604 Slog.v(TAG, "fullBackupContent specified as boolean=" +
3605 (v.data == 0 ? "false" : "true"));
3606 }
3607 // "false" => -1, "true" => 0
3608 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
3609 }
3610 if (DEBUG_BACKUP) {
3611 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
3612 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003613 }
Christopher Tate4a627c72011-04-01 14:43:32 -07003614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08003616 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003617 ai.descriptionRes = sa.getResourceId(
3618 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
3619
Todd Kennedy232d29e2017-11-06 14:45:53 -08003620 if (sa.getBoolean(
3621 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
3622 false)) {
3623 // Check if persistence is based on a feature being present
3624 final String requiredFeature = sa.getNonResourceString(com.android.internal.R.styleable
3625 .AndroidManifestApplication_persistentWhenFeatureAvailable);
3626 if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
3627 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003628 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07003629 }
3630
3631 if (sa.getBoolean(
3632 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
3633 false)) {
3634 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07003635 }
3636
3637 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
3638 .AndroidManifestApplication_restrictedAccountType);
3639 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
3640 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 }
3642
Amith Yamasaniccbe3892013-04-12 17:52:42 -07003643 String requiredAccountType = sa.getString(com.android.internal.R.styleable
3644 .AndroidManifestApplication_requiredAccountType);
3645 if (requiredAccountType != null && requiredAccountType.length() > 0) {
3646 owner.mRequiredAccountType = requiredAccountType;
3647 }
3648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003649 if (sa.getBoolean(
3650 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
3651 false)) {
3652 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
Chris Craikce030282018-10-16 14:33:11 -07003653 // Debuggable implies profileable
3654 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003655 }
3656
3657 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07003658 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08003659 false)) {
3660 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
3661 }
3662
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003663 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07003664 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07003665 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07003666 if (owner.baseHardwareAccelerated) {
3667 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
3668 }
Romain Guy812ccbe2010-06-01 14:07:24 -07003669
3670 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003671 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
3672 true)) {
3673 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
3674 }
3675
3676 if (sa.getBoolean(
3677 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
3678 false)) {
3679 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
3680 }
3681
3682 if (sa.getBoolean(
3683 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
3684 true)) {
3685 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
3686 }
3687
Svet Ganov354cd3c2015-12-17 11:35:04 -08003688 // The parent package controls installation, hence specify test only installs.
3689 if (owner.parentPackage == null) {
3690 if (sa.getBoolean(
3691 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
3692 false)) {
3693 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
3694 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003695 }
3696
Jason parksa3cdaa52011-01-13 14:15:43 -06003697 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003698 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06003699 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003700 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06003701 }
3702
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003703 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07003704 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
Chad Brubaker0d285d52018-03-14 09:00:04 -07003705 owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.P)) {
Alex Klyubin01a959d2015-03-18 10:05:45 -07003706 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
3707 }
3708
3709 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003710 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
3711 false /* default is no RTL support*/)) {
3712 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
3713 }
3714
Narayan Kamath589a1bc2014-07-03 14:43:26 +01003715 if (sa.getBoolean(
3716 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
3717 false)) {
3718 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
3719 }
3720
Victor Hsieh12dd9cd2019-01-14 20:56:40 -08003721 final boolean extractNativeLibsDefault =
3722 owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.Q;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07003723 if (sa.getBoolean(
3724 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
Victor Hsieh12dd9cd2019-01-14 20:56:40 -08003725 extractNativeLibsDefault)) {
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07003726 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
3727 }
3728
Todd Kennedyd022ac22016-04-13 10:49:29 -07003729 if (sa.getBoolean(
Victor Hsiehfa9df0b2019-01-29 12:48:36 -08003730 R.styleable.AndroidManifestApplication_useEmbeddedDex,
Victor Hsiehe7b5a8d2018-11-16 10:27:06 -08003731 false)) {
Victor Hsiehfa9df0b2019-01-29 12:48:36 -08003732 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX;
Victor Hsiehe7b5a8d2018-11-16 10:27:06 -08003733 }
3734
3735 if (sa.getBoolean(
Todd Kennedyd022ac22016-04-13 10:49:29 -07003736 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
3737 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003738 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003739 }
Todd Kennedyd022ac22016-04-13 10:49:29 -07003740 if (sa.getBoolean(
3741 R.styleable.AndroidManifestApplication_directBootAware,
3742 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003743 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003744 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003745
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003746 if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
3747 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003748 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
3749 } else {
3750 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003751 }
3752 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003753 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwale6afdf912016-01-30 13:01:33 -08003754 }
3755
Ruslan Tkhakokhov75674852019-01-22 13:35:00 +00003756 if (sa.getBoolean(
3757 com.android.internal.R.styleable
3758 .AndroidManifestApplication_allowClearUserDataOnFailedRestore,
3759 true)) {
3760 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE;
3761 }
3762
Kevin Rocardf91d50b2019-02-21 14:32:46 -08003763 if (sa.getBoolean(
3764 R.styleable.AndroidManifestApplication_allowAudioPlaybackCapture,
3765 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q)) {
3766 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE;
3767 }
3768
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07003769 ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
Adrian Roos917791e2018-11-28 16:30:44 +01003770 ai.minAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_minAspectRatio, 0);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07003771
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003772 ai.networkSecurityConfigRes = sa.getResourceId(
3773 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
3774 0);
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07003775 ai.category = sa.getInt(
3776 com.android.internal.R.styleable.AndroidManifestApplication_appCategory,
3777 ApplicationInfo.CATEGORY_UNDEFINED);
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003779 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003780 str = sa.getNonConfigurationString(
3781 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003782 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
3783
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003784 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3785 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003786 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
3787 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003788 } else {
3789 // Some older apps have been seen to use a resource reference
3790 // here that on older builds was ignored (with a warning). We
3791 // need to continue to do this for them so they don't break.
3792 str = sa.getNonResourceString(
3793 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
3794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003795 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
3796 str, outError);
Jason Monka80bfb52017-11-16 17:15:37 -05003797 String factory = sa.getNonResourceString(
3798 com.android.internal.R.styleable.AndroidManifestApplication_appComponentFactory);
3799 if (factory != null) {
3800 ai.appComponentFactory = buildClassName(ai.packageName, factory, outError);
3801 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003802
David Brazdila5b4df22018-09-06 09:49:14 +01003803 if (sa.getBoolean(
3804 com.android.internal.R.styleable.AndroidManifestApplication_usesNonSdkApi, false)) {
3805 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API;
3806 }
David Brazdil787b6f22a2018-08-28 12:55:56 +01003807
Philip P. Moltmannae4a4b92018-12-12 11:28:57 -08003808 if (sa.getBoolean(
3809 com.android.internal.R.styleable.AndroidManifestApplication_hasFragileUserData,
3810 false)) {
3811 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA;
3812 }
3813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003815 CharSequence pname;
3816 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3817 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003818 com.android.internal.R.styleable.AndroidManifestApplication_process,
3819 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003820 } else {
3821 // Some older apps have been seen to use a resource reference
3822 // here that on older builds was ignored (with a warning). We
3823 // need to continue to do this for them so they don't break.
3824 pname = sa.getNonResourceString(
3825 com.android.internal.R.styleable.AndroidManifestApplication_process);
3826 }
3827 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003828 flags, mSeparateProcesses, outError);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003829
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003830 ai.enabled = sa.getBoolean(
3831 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003832
Jose Lima12d0b4c2014-03-14 16:55:12 -07003833 if (sa.getBoolean(
3834 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
3835 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
3836 }
3837
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003838 if (sa.getBoolean(
3839 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
3840 false)) {
3841 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07003842
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003843 // A heavy-weight application can not be in a custom process.
3844 // We can do direct compare because we intern all strings.
3845 if (ai.processName != null && !ai.processName.equals(ai.packageName)) {
3846 outError[0] = "cantSaveState applications can not use custom processes";
Dianne Hackborn860755f2010-06-03 18:47:52 -07003847 }
3848 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003849 }
3850
Adam Powell269248d2011-08-02 10:26:54 -07003851 ai.uiOptions = sa.getInt(
3852 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
3853
Narayan Kamath96c11c52017-08-09 13:07:21 +01003854 ai.classLoaderName = sa.getString(
3855 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3856 if (ai.classLoaderName != null
3857 && !ClassLoaderFactory.isValidClassLoaderName(ai.classLoaderName)) {
3858 outError[0] = "Invalid class loader name: " + ai.classLoaderName;
3859 }
3860
Martijn Coenenfb7caa92019-01-29 11:45:56 +01003861 ai.zygotePreloadName = sa.getString(
3862 com.android.internal.R.styleable.AndroidManifestApplication_zygotePreloadName);
3863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003864 sa.recycle();
3865
3866 if (outError[0] != null) {
3867 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3868 return false;
3869 }
3870
3871 final int innerDepth = parser.getDepth();
Garrett Boyer52136662017-05-23 13:47:58 -07003872 // IMPORTANT: These must only be cached for a single <application> to avoid components
3873 // getting added to the wrong package.
3874 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003875 int type;
Todd Kennedy6d418b62018-02-22 14:15:18 -08003876 boolean hasActivityOrder = false;
3877 boolean hasReceiverOrder = false;
3878 boolean hasServiceOrder = false;
Kenny Rootd2d29252011-08-08 11:27:57 -07003879 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3880 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3881 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003882 continue;
3883 }
3884
3885 String tagName = parser.getName();
3886 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003887 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003888 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003889 if (a == null) {
3890 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3891 return false;
3892 }
3893
Todd Kennedy6d418b62018-02-22 14:15:18 -08003894 hasActivityOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003895 owner.activities.add(a);
3896
3897 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003898 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3899 true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003900 if (a == null) {
3901 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3902 return false;
3903 }
3904
Todd Kennedy6d418b62018-02-22 14:15:18 -08003905 hasReceiverOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003906 owner.receivers.add(a);
3907
3908 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003909 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 if (s == null) {
3911 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3912 return false;
3913 }
3914
Todd Kennedy6d418b62018-02-22 14:15:18 -08003915 hasServiceOrder |= (s.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916 owner.services.add(s);
3917
3918 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003919 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003920 if (p == null) {
3921 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3922 return false;
3923 }
3924
3925 owner.providers.add(p);
3926
3927 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003928 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003929 if (a == null) {
3930 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3931 return false;
3932 }
3933
Todd Kennedy6d418b62018-02-22 14:15:18 -08003934 hasActivityOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003935 owner.activities.add(a);
3936
3937 } else if (parser.getName().equals("meta-data")) {
3938 // note: application meta-data is stored off to the side, so it can
3939 // remain null in the primary copy (we like to avoid extra copies because
3940 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003941 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 outError)) == null) {
3943 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3944 return false;
3945 }
Svet Ganov67882122016-12-11 16:36:34 -08003946 } else if (tagName.equals("static-library")) {
3947 sa = res.obtainAttributes(parser,
3948 com.android.internal.R.styleable.AndroidManifestStaticLibrary);
3949
3950 // Note: don't allow this value to be a reference to a resource
3951 // that may change.
3952 final String lname = sa.getNonResourceString(
3953 com.android.internal.R.styleable.AndroidManifestStaticLibrary_name);
3954 final int version = sa.getInt(
3955 com.android.internal.R.styleable.AndroidManifestStaticLibrary_version, -1);
Dianne Hackborn3accca02013-09-20 09:32:11 -07003956 final int versionMajor = sa.getInt(
3957 com.android.internal.R.styleable.AndroidManifestStaticLibrary_versionMajor,
3958 0);
Svet Ganov67882122016-12-11 16:36:34 -08003959
3960 sa.recycle();
3961
3962 // Since the app canot run without a static lib - fail if malformed
3963 if (lname == null || version < 0) {
3964 outError[0] = "Bad static-library declaration name: " + lname
3965 + " version: " + version;
3966 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3967 XmlUtils.skipCurrentTag(parser);
3968 return false;
3969 }
3970
3971 if (owner.mSharedUserId != null) {
3972 outError[0] = "sharedUserId not allowed in static shared library";
3973 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
3974 XmlUtils.skipCurrentTag(parser);
3975 return false;
3976 }
3977
3978 if (owner.staticSharedLibName != null) {
3979 outError[0] = "Multiple static-shared libs for package " + pkgName;
3980 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3981 XmlUtils.skipCurrentTag(parser);
3982 return false;
3983 }
3984
3985 owner.staticSharedLibName = lname.intern();
Dianne Hackborn3accca02013-09-20 09:32:11 -07003986 if (version >= 0) {
3987 owner.staticSharedLibVersion =
3988 PackageInfo.composeLongVersionCode(versionMajor, version);
3989 } else {
3990 owner.staticSharedLibVersion = version;
3991 }
Svet Ganov67882122016-12-11 16:36:34 -08003992 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
3993
3994 XmlUtils.skipCurrentTag(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995
Dianne Hackbornc895be72013-03-11 17:48:43 -07003996 } else if (tagName.equals("library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003997 sa = res.obtainAttributes(parser,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003998 com.android.internal.R.styleable.AndroidManifestLibrary);
3999
4000 // Note: don't allow this value to be a reference to a resource
4001 // that may change.
4002 String lname = sa.getNonResourceString(
4003 com.android.internal.R.styleable.AndroidManifestLibrary_name);
4004
4005 sa.recycle();
4006
4007 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004008 lname = lname.intern();
4009 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
Svet Ganov67882122016-12-11 16:36:34 -08004010 owner.libraryNames = ArrayUtils.add(
4011 owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07004012 }
4013 }
4014
4015 XmlUtils.skipCurrentTag(parser);
4016
Svet Ganov67882122016-12-11 16:36:34 -08004017 } else if (tagName.equals("uses-static-library")) {
4018 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
4019 return false;
4020 }
4021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004022 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004023 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004024 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
4025
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004026 // Note: don't allow this value to be a reference to a resource
4027 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004028 String lname = sa.getNonResourceString(
4029 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07004030 boolean req = sa.getBoolean(
4031 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
4032 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004033
4034 sa.recycle();
4035
Dianne Hackborn49237342009-08-27 20:08:01 -07004036 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004037 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07004038 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004039 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07004040 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004041 owner.usesOptionalLibraries = ArrayUtils.add(
4042 owner.usesOptionalLibraries, lname);
4043 }
4044 }
4045
4046 XmlUtils.skipCurrentTag(parser);
4047
4048 } else if (tagName.equals("uses-package")) {
4049 // Dependencies for app installers; we don't currently try to
4050 // enforce this.
4051 XmlUtils.skipCurrentTag(parser);
Chris Craikce030282018-10-16 14:33:11 -07004052 } else if (tagName.equals("profileable")) {
4053 sa = res.obtainAttributes(parser,
4054 com.android.internal.R.styleable.AndroidManifestProfileable);
4055 if (sa.getBoolean(
4056 com.android.internal.R.styleable.AndroidManifestProfileable_shell, false)) {
4057 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL;
4058 }
4059 XmlUtils.skipCurrentTag(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004060
4061 } else {
4062 if (!RIGID_PARSER) {
4063 Slog.w(TAG, "Unknown element under <application>: " + tagName
4064 + " at " + mArchiveSourcePath + " "
4065 + parser.getPositionDescription());
4066 XmlUtils.skipCurrentTag(parser);
4067 continue;
4068 } else {
4069 outError[0] = "Bad element under <application>: " + tagName;
4070 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4071 return false;
4072 }
4073 }
4074 }
4075
Patrick Baumann1f9b8852018-10-30 12:34:46 -07004076 if (TextUtils.isEmpty(owner.staticSharedLibName)) {
4077 // Add a hidden app detail activity to normal apps which forwards user to App Details
4078 // page.
4079 Activity a = generateAppDetailsHiddenActivity(owner, flags, outError,
4080 owner.baseHardwareAccelerated);
4081 owner.activities.add(a);
4082 }
Ricky Waicf134eb2018-10-10 09:26:32 +01004083
Todd Kennedy6d418b62018-02-22 14:15:18 -08004084 if (hasActivityOrder) {
4085 Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order));
4086 }
4087 if (hasReceiverOrder) {
4088 Collections.sort(owner.receivers, (r1, r2) -> Integer.compare(r2.order, r1.order));
4089 }
4090 if (hasServiceOrder) {
4091 Collections.sort(owner.services, (s1, s2) -> Integer.compare(s2.order, s1.order));
4092 }
Bryce Lee22571db2017-07-07 15:54:18 -07004093 // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
4094 // every activity info has had a chance to set it from its attributes.
4095 setMaxAspectRatio(owner);
Adrian Roos917791e2018-11-28 16:30:44 +01004096 setMinAspectRatio(owner);
Bryce Lee22571db2017-07-07 15:54:18 -07004097
Paul Duffin855d7022017-07-10 15:16:07 +01004098 PackageBackwardCompatibility.modifySharedLibraries(owner);
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00004099
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07004100 if (hasDomainURLs(owner)) {
4101 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
4102 } else {
4103 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
4104 }
4105
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004106 return true;
4107 }
4108
4109 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07004110 * 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 -07004111 */
4112 private static boolean hasDomainURLs(Package pkg) {
4113 if (pkg == null || pkg.activities == null) return false;
4114 final ArrayList<Activity> activities = pkg.activities;
4115 final int countActivities = activities.size();
4116 for (int n=0; n<countActivities; n++) {
4117 Activity activity = activities.get(n);
4118 ArrayList<ActivityIntentInfo> filters = activity.intents;
4119 if (filters == null) continue;
4120 final int countFilters = filters.size();
4121 for (int m=0; m<countFilters; m++) {
4122 ActivityIntentInfo aii = filters.get(m);
4123 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07004124 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07004125 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
4126 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
4127 return true;
4128 }
4129 }
4130 }
4131 return false;
4132 }
4133
4134 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004135 * Parse the {@code application} XML tree at the current parse location in a
4136 * <em>split APK</em> manifest.
4137 * <p>
4138 * Note that split APKs have many more restrictions on what they're capable
4139 * of doing, so many valid features of a base APK have been carefully
4140 * omitted here.
4141 */
Svet Ganov354cd3c2015-12-17 11:35:04 -08004142 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
4143 int flags, int splitIndex, String[] outError)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004144 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004145 TypedArray sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004146 com.android.internal.R.styleable.AndroidManifestApplication);
4147
4148 if (sa.getBoolean(
4149 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
4150 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
4151 }
4152
Narayan Kamath96c11c52017-08-09 13:07:21 +01004153 final String classLoaderName = sa.getString(
4154 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
4155 if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
4156 owner.applicationInfo.splitClassLoaderNames[splitIndex] = classLoaderName;
4157 } else {
4158 outError[0] = "Invalid class loader name: " + classLoaderName;
4159 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4160 return false;
4161 }
4162
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004163 final int innerDepth = parser.getDepth();
4164 int type;
4165 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
4166 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
4167 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4168 continue;
4169 }
4170
Adam Lesinski4e862812016-11-21 16:02:24 -08004171 ComponentInfo parsedComponent = null;
4172
Garrett Boyer52136662017-05-23 13:47:58 -07004173 // IMPORTANT: These must only be cached for a single <application> to avoid components
4174 // getting added to the wrong package.
4175 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004176 String tagName = parser.getName();
4177 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004178 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004179 owner.baseHardwareAccelerated);
4180 if (a == null) {
4181 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4182 return false;
4183 }
4184
4185 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08004186 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004187
4188 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004189 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
4190 true, false);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004191 if (a == null) {
4192 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4193 return false;
4194 }
4195
4196 owner.receivers.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08004197 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004198
4199 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004200 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004201 if (s == null) {
4202 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4203 return false;
4204 }
4205
4206 owner.services.add(s);
Adam Lesinski4e862812016-11-21 16:02:24 -08004207 parsedComponent = s.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004208
4209 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004210 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004211 if (p == null) {
4212 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4213 return false;
4214 }
4215
4216 owner.providers.add(p);
Adam Lesinski4e862812016-11-21 16:02:24 -08004217 parsedComponent = p.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004218
4219 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004220 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004221 if (a == null) {
4222 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4223 return false;
4224 }
4225
4226 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08004227 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004228
4229 } else if (parser.getName().equals("meta-data")) {
4230 // note: application meta-data is stored off to the side, so it can
4231 // remain null in the primary copy (we like to avoid extra copies because
4232 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08004233 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004234 outError)) == null) {
4235 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4236 return false;
4237 }
4238
Svet Ganov67882122016-12-11 16:36:34 -08004239 } else if (tagName.equals("uses-static-library")) {
4240 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
4241 return false;
4242 }
4243
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004244 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004245 sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004246 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
4247
4248 // Note: don't allow this value to be a reference to a resource
4249 // that may change.
4250 String lname = sa.getNonResourceString(
4251 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
4252 boolean req = sa.getBoolean(
4253 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
4254 true);
4255
4256 sa.recycle();
4257
4258 if (lname != null) {
4259 lname = lname.intern();
4260 if (req) {
4261 // Upgrade to treat as stronger constraint
4262 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
4263 owner.usesOptionalLibraries = ArrayUtils.remove(
4264 owner.usesOptionalLibraries, lname);
4265 } else {
4266 // Ignore if someone already defined as required
4267 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
4268 owner.usesOptionalLibraries = ArrayUtils.add(
4269 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07004270 }
4271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 }
4273
4274 XmlUtils.skipCurrentTag(parser);
4275
Dianne Hackborncef65ee2010-09-30 18:27:22 -07004276 } else if (tagName.equals("uses-package")) {
4277 // Dependencies for app installers; we don't currently try to
4278 // enforce this.
4279 XmlUtils.skipCurrentTag(parser);
4280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004281 } else {
4282 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004283 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004284 + " at " + mArchiveSourcePath + " "
4285 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004286 XmlUtils.skipCurrentTag(parser);
4287 continue;
4288 } else {
4289 outError[0] = "Bad element under <application>: " + tagName;
4290 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4291 return false;
4292 }
4293 }
Adam Lesinski4e862812016-11-21 16:02:24 -08004294
4295 if (parsedComponent != null && parsedComponent.splitName == null) {
4296 // If the loaded component did not specify a split, inherit the split name
4297 // based on the split it is defined in.
4298 // This is used to later load the correct split when starting this
4299 // component.
4300 parsedComponent.splitName = owner.splitNames[splitIndex];
4301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004302 }
4303
4304 return true;
4305 }
4306
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004307 private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
4308 String[] outError, String tag, TypedArray sa, boolean nameRequired,
4309 int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00004310 // This case can only happen in unit tests where we sometimes need to create fakes
4311 // of various package parser data structures.
4312 if (sa == null) {
4313 outError[0] = tag + " does not contain any attributes";
4314 return false;
4315 }
4316
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004317 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004318 if (name == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004319 if (nameRequired) {
4320 outError[0] = tag + " does not specify android:name";
4321 return false;
4322 }
4323 } else {
Ricky Waicf134eb2018-10-10 09:26:32 +01004324 String outInfoName
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004325 = buildClassName(owner.applicationInfo.packageName, name, outError);
Ricky Wai92cd0062019-02-14 20:23:22 +00004326 if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(outInfoName)) {
Ricky Waicf134eb2018-10-10 09:26:32 +01004327 outError[0] = tag + " invalid android:name";
4328 return false;
4329 }
4330 outInfo.name = outInfoName;
4331 if (outInfoName == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004332 return false;
4333 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004334 }
4335
Todd Kennedya83bfca2016-06-03 07:52:17 -07004336 final boolean useRoundIcon =
4337 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
4338 int roundIconVal = useRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004339 if (roundIconVal != 0) {
4340 outInfo.icon = roundIconVal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004341 outInfo.nonLocalizedLabel = null;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004342 } else {
4343 int iconVal = sa.getResourceId(iconRes, 0);
4344 if (iconVal != 0) {
4345 outInfo.icon = iconVal;
4346 outInfo.nonLocalizedLabel = null;
4347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004349
Adam Powell81cd2e92010-04-21 16:35:18 -07004350 int logoVal = sa.getResourceId(logoRes, 0);
4351 if (logoVal != 0) {
4352 outInfo.logo = logoVal;
4353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004354
Jose Limaf78e3122014-03-06 12:13:15 -08004355 int bannerVal = sa.getResourceId(bannerRes, 0);
4356 if (bannerVal != 0) {
4357 outInfo.banner = bannerVal;
4358 }
4359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004360 TypedValue v = sa.peekValue(labelRes);
4361 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4362 outInfo.nonLocalizedLabel = v.coerceToString();
4363 }
4364
4365 outInfo.packageName = owner.packageName;
4366
4367 return true;
4368 }
4369
Ricky Waicf134eb2018-10-10 09:26:32 +01004370 /**
4371 * Generate activity object that forwards user to App Details page automatically.
4372 * This activity should be invisible to user and user should not know or see it.
4373 */
4374 private @NonNull PackageParser.Activity generateAppDetailsHiddenActivity(
4375 PackageParser.Package owner, int flags, String[] outError,
4376 boolean hardwareAccelerated) {
4377
4378 // Build custom App Details activity info instead of parsing it from xml
Ricky Wai92cd0062019-02-14 20:23:22 +00004379 Activity a = new Activity(owner, PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME,
4380 new ActivityInfo());
Ricky Waicf134eb2018-10-10 09:26:32 +01004381 a.owner = owner;
4382 a.setPackageName(owner.packageName);
4383
Ricky Wai622925072019-01-29 16:40:59 +00004384 a.info.theme = android.R.style.Theme_NoDisplay;
Ricky Waicf134eb2018-10-10 09:26:32 +01004385 a.info.exported = true;
Ricky Wai92cd0062019-02-14 20:23:22 +00004386 a.info.name = PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME;
Ricky Waicf134eb2018-10-10 09:26:32 +01004387 a.info.processName = owner.applicationInfo.processName;
4388 a.info.uiOptions = a.info.applicationInfo.uiOptions;
4389 a.info.taskAffinity = buildTaskAffinityName(owner.packageName, owner.packageName,
4390 ":app_details", outError);
4391 a.info.enabled = true;
4392 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4393 a.info.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NONE;
4394 a.info.maxRecents = ActivityTaskManager.getDefaultAppRecentsLimitStatic();
4395 a.info.configChanges = getActivityConfigChanges(0, 0);
4396 a.info.softInputMode = 0;
4397 a.info.persistableMode = ActivityInfo.PERSIST_NEVER;
4398 a.info.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
4399 a.info.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4400 a.info.lockTaskLaunchMode = 0;
4401 a.info.encryptionAware = a.info.directBootAware = false;
4402 a.info.rotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
4403 a.info.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
4404 if (hardwareAccelerated) {
4405 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
4406 }
4407 return a;
4408 }
4409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410 private Activity parseActivity(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004411 XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
Romain Guy529b60a2010-08-03 18:05:47 -07004412 boolean receiver, boolean hardwareAccelerated)
4413 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004414 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004415
Garrett Boyer52136662017-05-23 13:47:58 -07004416 if (cachedArgs.mActivityArgs == null) {
4417 cachedArgs.mActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004418 R.styleable.AndroidManifestActivity_name,
4419 R.styleable.AndroidManifestActivity_label,
4420 R.styleable.AndroidManifestActivity_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004421 R.styleable.AndroidManifestActivity_roundIcon,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004422 R.styleable.AndroidManifestActivity_logo,
4423 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004424 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004425 R.styleable.AndroidManifestActivity_process,
4426 R.styleable.AndroidManifestActivity_description,
4427 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004428 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004429
Garrett Boyer52136662017-05-23 13:47:58 -07004430 cachedArgs.mActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
4431 cachedArgs.mActivityArgs.sa = sa;
4432 cachedArgs.mActivityArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004433
Garrett Boyer52136662017-05-23 13:47:58 -07004434 Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004435 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 sa.recycle();
4437 return null;
4438 }
4439
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004440 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004441 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004442 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004443 }
4444
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004445 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004446
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004447 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07004448 a.info.applicationInfo.uiOptions);
4449
Adam Powelldd8fab22012-03-22 17:47:27 -07004450 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004451 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004452 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004453 if (parentName != null) {
4454 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4455 if (outError[0] == null) {
4456 a.info.parentActivityName = parentClassName;
4457 } else {
4458 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
4459 parentName);
4460 outError[0] = null;
4461 }
4462 }
4463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004464 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004465 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004466 if (str == null) {
4467 a.info.permission = owner.applicationInfo.permission;
4468 } else {
4469 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4470 }
4471
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004472 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004473 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004474 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004475 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
4476 owner.applicationInfo.taskAffinity, str, outError);
4477
Todd Kennedye9d0d272017-01-23 06:49:29 -08004478 a.info.splitName =
4479 sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0);
4480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004481 a.info.flags = 0;
4482 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004483 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004484 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
4485 }
4486
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004487 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004488 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
4489 }
4490
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004491 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004492 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
4493 }
4494
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004495 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004496 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
4497 }
4498
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004499 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004500 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
4501 }
4502
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004503 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004504 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
4505 }
4506
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004507 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
4509 }
4510
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004511 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004512 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
4513 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
4514 }
4515
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004516 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07004517 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
4518 }
4519
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07004520 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
4521 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
4522 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07004523 }
4524
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004525 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04004526 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
4527 }
Craig Mautner5962b122012-10-05 14:45:52 -07004528
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07004529 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
4530 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08004531 }
4532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004533 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004534 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07004535 hardwareAccelerated)) {
4536 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
4537 }
4538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004539 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004540 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07004541 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004542 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07004543 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07004544 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004545 R.styleable.AndroidManifestActivity_maxRecents,
Wale Ogunwale65ebd952018-04-25 15:41:44 -07004546 ActivityTaskManager.getDefaultAppRecentsLimitStatic());
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004547 a.info.configChanges = getActivityConfigChanges(
4548 sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004549 sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004550 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004551 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07004552
Craig Mautner43e52ed2014-06-16 17:18:52 -07004553 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004554 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07004555 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07004556
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004557 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004558 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
4559 }
4560
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004561 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004562 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
4563 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004564
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004565 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004566 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
4567 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004568
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004569 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004570 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
4571 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004572
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004573 a.info.screenOrientation = sa.getInt(
4574 R.styleable.AndroidManifestActivity_screenOrientation,
4575 SCREEN_ORIENTATION_UNSPECIFIED);
Wale Ogunwale6a591362015-10-05 20:18:27 -07004576
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004577 setActivityResizeMode(a.info, sa, owner);
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004578
Winson Chungd3395382016-12-13 11:49:09 -08004579 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
4580 false)) {
4581 a.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE;
4582 }
4583
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004584 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004585 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004586 }
Wale Ogunwaleb60692e2015-10-24 12:35:56 -07004587
Bryce Lee22571db2017-07-07 15:54:18 -07004588 if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio)
4589 && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio)
4590 == TypedValue.TYPE_FLOAT) {
4591 a.setMaxAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio,
4592 0 /*default*/));
4593 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004594
Adrian Roos917791e2018-11-28 16:30:44 +01004595 if (sa.hasValue(R.styleable.AndroidManifestActivity_minAspectRatio)
4596 && sa.getType(R.styleable.AndroidManifestActivity_minAspectRatio)
4597 == TypedValue.TYPE_FLOAT) {
4598 a.setMinAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_minAspectRatio,
4599 0 /*default*/));
4600 }
4601
Craig Mautner15df08a2015-04-01 12:17:18 -07004602 a.info.lockTaskLaunchMode =
4603 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004604
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004605 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4606 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004607 false);
Ruben Brunkf56c9f42016-04-22 18:20:55 -07004608
4609 a.info.requestedVrComponent =
4610 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
Robert Carr0f5d7532016-10-17 16:39:17 -07004611
4612 a.info.rotationAnimation =
Robert Carr427ba4f2017-07-17 18:37:06 -07004613 sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_UNSPECIFIED);
Romain Guy48327452017-01-23 17:03:35 -08004614
4615 a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
4616 ActivityInfo.COLOR_MODE_DEFAULT);
chaviw59b98852017-06-13 12:05:44 -07004617
4618 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) {
4619 a.info.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
4620 }
4621
4622 if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) {
4623 a.info.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON;
4624 }
4625
Issei Suzuki74e1eb22018-12-20 17:42:52 +01004626 if (sa.getBoolean(R.styleable.AndroidManifestActivity_inheritShowWhenLocked, false)) {
4627 a.info.privateFlags |= ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
4628 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004629 } else {
4630 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4631 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004632
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004633 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07004634 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004635 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004636
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004637 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4638 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004639 false);
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004640 }
4641
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004642 if (a.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004643 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004644 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004645 }
4646
Todd Kennedy752fb702017-03-21 16:28:10 -07004647 // can't make this final; we may set it later via meta-data
4648 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08004649 sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004650 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004651 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004652 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004653 }
4654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655 sa.recycle();
4656
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004657 if (receiver && (owner.applicationInfo.privateFlags
4658 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004659 // A heavy-weight application can not have receives in its main process
4660 // We can do direct compare because we intern all strings.
4661 if (a.info.processName == owner.packageName) {
4662 outError[0] = "Heavy-weight applications can not have receivers in main process";
4663 }
4664 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004666 if (outError[0] != null) {
4667 return null;
4668 }
4669
4670 int outerDepth = parser.getDepth();
4671 int type;
4672 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4673 && (type != XmlPullParser.END_TAG
4674 || parser.getDepth() > outerDepth)) {
4675 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4676 continue;
4677 }
4678
4679 if (parser.getName().equals("intent-filter")) {
4680 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004681 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4682 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004683 return null;
4684 }
4685 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004686 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004687 + mArchiveSourcePath + " "
4688 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004689 } else {
Todd Kennedy6d418b62018-02-22 14:15:18 -08004690 a.order = Math.max(intent.getOrder(), a.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 a.intents.add(intent);
4692 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004693 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004694 final int visibility = visibleToEphemeral
4695 ? IntentFilter.VISIBILITY_EXPLICIT
4696 : !receiver && isImplicitlyExposedIntent(intent)
4697 ? IntentFilter.VISIBILITY_IMPLICIT
4698 : IntentFilter.VISIBILITY_NONE;
4699 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004700 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004701 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4702 }
4703 if (intent.isImplicitlyVisibleToInstantApp()) {
4704 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004705 }
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -07004706 if (LOG_UNSAFE_BROADCASTS && receiver
4707 && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
4708 for (int i = 0; i < intent.countActions(); i++) {
4709 final String action = intent.getAction(i);
4710 if (action == null || !action.startsWith("android.")) continue;
4711 if (!SAFE_BROADCASTS.contains(action)) {
4712 Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
4713 + owner.packageName + " as requested at: "
4714 + parser.getPositionDescription());
4715 }
4716 }
4717 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004718 } else if (!receiver && parser.getName().equals("preferred")) {
4719 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004720 if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
4721 intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004722 return null;
4723 }
4724 if (intent.countActions() == 0) {
4725 Slog.w(TAG, "No actions in preferred at "
4726 + mArchiveSourcePath + " "
4727 + parser.getPositionDescription());
4728 } else {
4729 if (owner.preferredActivityFilters == null) {
4730 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
4731 }
4732 owner.preferredActivityFilters.add(intent);
4733 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004734 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004735 final int visibility = visibleToEphemeral
4736 ? IntentFilter.VISIBILITY_EXPLICIT
4737 : !receiver && isImplicitlyExposedIntent(intent)
4738 ? IntentFilter.VISIBILITY_IMPLICIT
4739 : IntentFilter.VISIBILITY_NONE;
4740 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004741 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004742 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4743 }
4744 if (intent.isImplicitlyVisibleToInstantApp()) {
4745 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004746 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004748 if ((a.metaData = parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004749 outError)) == null) {
4750 return null;
4751 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004752 } else if (!receiver && parser.getName().equals("layout")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004753 parseLayout(res, parser, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004754 } else {
4755 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004756 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004757 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004758 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004759 + " at " + mArchiveSourcePath + " "
4760 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004761 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004762 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004763 + " at " + mArchiveSourcePath + " "
4764 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004765 }
4766 XmlUtils.skipCurrentTag(parser);
4767 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004768 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004769 if (receiver) {
4770 outError[0] = "Bad element under <receiver>: " + parser.getName();
4771 } else {
4772 outError[0] = "Bad element under <activity>: " + parser.getName();
4773 }
4774 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004776 }
4777 }
4778
4779 if (!setExported) {
4780 a.info.exported = a.intents.size() > 0;
4781 }
4782
4783 return a;
4784 }
4785
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004786 private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004787 final boolean appExplicitDefault = (owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004788 & (PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
4789 | PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004790
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004791 if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
4792 || appExplicitDefault) {
4793 // Activity or app explicitly set if it is resizeable or not;
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004794 final boolean appResizeable = (owner.applicationInfo.privateFlags
4795 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004796 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004797 appResizeable)) {
Winson Chungd3395382016-12-13 11:49:09 -08004798 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004799 } else {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004800 aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004801 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004802 return;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004803 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004804
4805 if ((owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004806 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) != 0) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004807 // The activity or app didn't explicitly set the resizing option, however we want to
4808 // make it resize due to the sdk version it is targeting.
4809 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4810 return;
4811 }
4812
4813 // resize preference isn't set and target sdk version doesn't support resizing apps by
4814 // default. For the app to be resizeable if it isn't fixed orientation or immersive.
skuhne@google.com322347b2016-12-02 12:54:03 -08004815 if (aInfo.isFixedOrientationPortrait()) {
4816 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
4817 } else if (aInfo.isFixedOrientationLandscape()) {
4818 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
4819 } else if (aInfo.isFixedOrientation()) {
4820 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
4821 } else {
4822 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4823 }
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004824 }
4825
Bryce Lee22571db2017-07-07 15:54:18 -07004826 /**
4827 * Sets every the max aspect ratio of every child activity that doesn't already have an aspect
4828 * ratio set.
4829 */
4830 private void setMaxAspectRatio(Package owner) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004831 // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
4832 // 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 -07004833 float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004834 ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
Bryce Lee22571db2017-07-07 15:54:18 -07004835
4836 if (owner.applicationInfo.maxAspectRatio != 0) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004837 // Use the application max aspect ration as default if set.
Bryce Lee22571db2017-07-07 15:54:18 -07004838 maxAspectRatio = owner.applicationInfo.maxAspectRatio;
4839 } else if (owner.mAppMetaData != null
4840 && owner.mAppMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) {
4841 maxAspectRatio = owner.mAppMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004842 }
4843
Bryce Lee22571db2017-07-07 15:54:18 -07004844 for (Activity activity : owner.activities) {
4845 // If the max aspect ratio for the activity has already been set, skip.
4846 if (activity.hasMaxAspectRatio()) {
4847 continue;
4848 }
4849
4850 // By default we prefer to use a values defined on the activity directly than values
4851 // defined on the application. We do not check the styled attributes on the activity
4852 // as it would have already been set when we processed the activity. We wait to process
4853 // the meta data here since this method is called at the end of processing the
4854 // application and all meta data is guaranteed.
4855 final float activityAspectRatio = activity.metaData != null
4856 ? activity.metaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio)
4857 : maxAspectRatio;
4858
4859 activity.setMaxAspectRatio(activityAspectRatio);
Wale Ogunwale0cb70ac2017-03-27 09:16:38 -07004860 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004861 }
4862
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004863 /**
Tiger Huang3d2b8982019-01-29 22:56:48 +08004864 * Sets every the min aspect ratio of every child activity that doesn't already have an aspect
Adrian Roos917791e2018-11-28 16:30:44 +01004865 * ratio set.
4866 */
4867 private void setMinAspectRatio(Package owner) {
4868 final float minAspectRatio;
4869 if (owner.applicationInfo.minAspectRatio != 0) {
4870 // Use the application max aspect ration as default if set.
4871 minAspectRatio = owner.applicationInfo.minAspectRatio;
4872 } else {
4873 // Default to (1.33) 4:3 aspect ratio for pre-Q apps and unset for Q and greater.
4874 // NOTE: 4:3 was the min aspect ratio Android devices can support pre-Q per the CDD,
4875 // except for watches which always supported 1:1.
4876 minAspectRatio = owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q
4877 ? 0
4878 : mCallback.hasFeature(FEATURE_WATCH)
4879 ? DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH
4880 : DEFAULT_PRE_Q_MIN_ASPECT_RATIO;
4881 }
4882
4883 for (Activity activity : owner.activities) {
4884 if (activity.hasMinAspectRatio()) {
4885 continue;
4886 }
4887 activity.setMinAspectRatio(minAspectRatio);
4888 }
4889 }
4890
4891 /**
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004892 * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004893 * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from
4894 * AndroidManifest.xml.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004895 * @hide Exposed for unit testing only.
4896 */
4897 @TestApi
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004898 public static int getActivityConfigChanges(int configChanges, int recreateOnConfigChanges) {
4899 return configChanges | ((~recreateOnConfigChanges) & RECREATE_ON_CONFIG_CHANGES_MASK);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004900 }
4901
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004902 private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004903 TypedArray sw = res.obtainAttributes(attrs,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004904 com.android.internal.R.styleable.AndroidManifestLayout);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004905 int width = -1;
4906 float widthFraction = -1f;
4907 int height = -1;
4908 float heightFraction = -1f;
4909 final int widthType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004910 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004911 if (widthType == TypedValue.TYPE_FRACTION) {
4912 widthFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004913 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004914 1, 1, -1);
4915 } else if (widthType == TypedValue.TYPE_DIMENSION) {
4916 width = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004917 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004918 -1);
4919 }
4920 final int heightType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004921 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004922 if (heightType == TypedValue.TYPE_FRACTION) {
4923 heightFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004924 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004925 1, 1, -1);
4926 } else if (heightType == TypedValue.TYPE_DIMENSION) {
4927 height = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004928 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004929 -1);
4930 }
4931 int gravity = sw.getInt(
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004932 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004933 Gravity.CENTER);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004934 int minWidth = sw.getDimensionPixelSize(
4935 com.android.internal.R.styleable.AndroidManifestLayout_minWidth,
Andrii Kulian2e751b82016-03-16 16:59:32 -07004936 -1);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004937 int minHeight = sw.getDimensionPixelSize(
4938 com.android.internal.R.styleable.AndroidManifestLayout_minHeight,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004939 -1);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004940 sw.recycle();
Andrii Kulian2e751b82016-03-16 16:59:32 -07004941 a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction,
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004942 height, heightFraction, gravity, minWidth, minHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004943 }
4944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 private Activity parseActivityAlias(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004946 XmlResourceParser parser, int flags, String[] outError,
4947 CachedComponentArgs cachedArgs)
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004948 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004949 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004950 com.android.internal.R.styleable.AndroidManifestActivityAlias);
4951
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004952 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004953 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
4954 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004955 if (targetActivity == null) {
4956 outError[0] = "<activity-alias> does not specify android:targetActivity";
4957 sa.recycle();
4958 return null;
4959 }
4960
4961 targetActivity = buildClassName(owner.applicationInfo.packageName,
4962 targetActivity, outError);
4963 if (targetActivity == null) {
4964 sa.recycle();
4965 return null;
4966 }
4967
Garrett Boyer52136662017-05-23 13:47:58 -07004968 if (cachedArgs.mActivityAliasArgs == null) {
4969 cachedArgs.mActivityAliasArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004970 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
4971 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
4972 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004973 com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004974 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004975 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004976 mSeparateProcesses,
4977 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004978 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004979 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004980 cachedArgs.mActivityAliasArgs.tag = "<activity-alias>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004981 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004982
Garrett Boyer52136662017-05-23 13:47:58 -07004983 cachedArgs.mActivityAliasArgs.sa = sa;
4984 cachedArgs.mActivityAliasArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004985
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004986 Activity target = null;
4987
4988 final int NA = owner.activities.size();
4989 for (int i=0; i<NA; i++) {
4990 Activity t = owner.activities.get(i);
4991 if (targetActivity.equals(t.info.name)) {
4992 target = t;
4993 break;
4994 }
4995 }
4996
4997 if (target == null) {
4998 outError[0] = "<activity-alias> target activity " + targetActivity
4999 + " not found in manifest";
5000 sa.recycle();
5001 return null;
5002 }
5003
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005004 ActivityInfo info = new ActivityInfo();
5005 info.targetActivity = targetActivity;
5006 info.configChanges = target.info.configChanges;
5007 info.flags = target.info.flags;
Issei Suzuki74e1eb22018-12-20 17:42:52 +01005008 info.privateFlags = target.info.privateFlags;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005009 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07005010 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08005011 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005012 info.labelRes = target.info.labelRes;
5013 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
5014 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07005015 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005016 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005017 if (info.descriptionRes == 0) {
5018 info.descriptionRes = target.info.descriptionRes;
5019 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005020 info.screenOrientation = target.info.screenOrientation;
5021 info.taskAffinity = target.info.taskAffinity;
5022 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07005023 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07005024 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07005025 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07005026 info.maxRecents = target.info.maxRecents;
Andrii Kulian2e751b82016-03-16 16:59:32 -07005027 info.windowLayout = target.info.windowLayout;
Wale Ogunwaled26176f2016-01-25 20:04:04 -08005028 info.resizeMode = target.info.resizeMode;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07005029 info.maxAspectRatio = target.info.maxAspectRatio;
Adrian Roos917791e2018-11-28 16:30:44 +01005030 info.minAspectRatio = target.info.minAspectRatio;
rongliuc12ede42018-02-23 17:58:38 -08005031 info.requestedVrComponent = target.info.requestedVrComponent;
Bryce Lee22571db2017-07-07 15:54:18 -07005032
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005033 info.encryptionAware = info.directBootAware = target.info.directBootAware;
Craig Mautner8307ea72014-09-11 15:03:53 -07005034
Garrett Boyer52136662017-05-23 13:47:58 -07005035 Activity a = new Activity(cachedArgs.mActivityAliasArgs, info);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005036 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005037 sa.recycle();
5038 return null;
5039 }
5040
5041 final boolean setExported = sa.hasValue(
5042 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
5043 if (setExported) {
5044 a.info.exported = sa.getBoolean(
5045 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
5046 }
5047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005048 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005049 str = sa.getNonConfigurationString(
5050 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005051 if (str != null) {
5052 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
5053 }
5054
Adam Powelldd8fab22012-03-22 17:47:27 -07005055 String parentName = sa.getNonConfigurationString(
5056 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07005057 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07005058 if (parentName != null) {
5059 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
5060 if (outError[0] == null) {
5061 a.info.parentActivityName = parentClassName;
5062 } else {
5063 Log.e(TAG, "Activity alias " + a.info.name +
5064 " specified invalid parentActivityName " + parentName);
5065 outError[0] = null;
5066 }
5067 }
5068
Chad Brubaker699c7712017-01-20 13:53:42 -08005069 // TODO add visibleToInstantApps attribute to activity alias
Todd Kennedybe0b8892017-02-15 14:13:52 -08005070 final boolean visibleToEphemeral =
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005071 ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005073 sa.recycle();
5074
5075 if (outError[0] != null) {
5076 return null;
5077 }
5078
5079 int outerDepth = parser.getDepth();
5080 int type;
5081 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5082 && (type != XmlPullParser.END_TAG
5083 || parser.getDepth() > outerDepth)) {
5084 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5085 continue;
5086 }
5087
5088 if (parser.getName().equals("intent-filter")) {
5089 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005090 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
5091 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005092 return null;
5093 }
5094 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005095 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07005096 + mArchiveSourcePath + " "
5097 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005098 } else {
Todd Kennedy6d418b62018-02-22 14:15:18 -08005099 a.order = Math.max(intent.getOrder(), a.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100 a.intents.add(intent);
5101 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005102 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005103 final int visibility = visibleToEphemeral
5104 ? IntentFilter.VISIBILITY_EXPLICIT
5105 : isImplicitlyExposedIntent(intent)
5106 ? IntentFilter.VISIBILITY_IMPLICIT
5107 : IntentFilter.VISIBILITY_NONE;
5108 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08005109 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005110 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
5111 }
5112 if (intent.isImplicitlyVisibleToInstantApp()) {
5113 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005114 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005115 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005116 if ((a.metaData=parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005117 outError)) == null) {
5118 return null;
5119 }
5120 } else {
5121 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005122 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005123 + " at " + mArchiveSourcePath + " "
5124 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005125 XmlUtils.skipCurrentTag(parser);
5126 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005127 } else {
5128 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
5129 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005131 }
5132 }
5133
5134 if (!setExported) {
5135 a.info.exported = a.intents.size() > 0;
5136 }
5137
5138 return a;
5139 }
5140
5141 private Provider parseProvider(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07005142 XmlResourceParser parser, int flags, String[] outError,
5143 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005144 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005145 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005146 com.android.internal.R.styleable.AndroidManifestProvider);
5147
Garrett Boyer52136662017-05-23 13:47:58 -07005148 if (cachedArgs.mProviderArgs == null) {
5149 cachedArgs.mProviderArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005150 com.android.internal.R.styleable.AndroidManifestProvider_name,
5151 com.android.internal.R.styleable.AndroidManifestProvider_label,
5152 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005153 com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07005154 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08005155 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005156 mSeparateProcesses,
5157 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005158 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005159 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07005160 cachedArgs.mProviderArgs.tag = "<provider>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005161 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005162
Garrett Boyer52136662017-05-23 13:47:58 -07005163 cachedArgs.mProviderArgs.sa = sa;
5164 cachedArgs.mProviderArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005165
Garrett Boyer52136662017-05-23 13:47:58 -07005166 Provider p = new Provider(cachedArgs.mProviderArgs, new ProviderInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005167 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005168 sa.recycle();
5169 return null;
5170 }
5171
Nick Kralevichf097b162012-07-28 12:43:48 -07005172 boolean providerExportedDefault = false;
5173
5174 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
5175 // For compatibility, applications targeting API level 16 or lower
5176 // should have their content providers exported by default, unless they
5177 // specify otherwise.
5178 providerExportedDefault = true;
5179 }
5180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005181 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07005182 com.android.internal.R.styleable.AndroidManifestProvider_exported,
5183 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005184
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005185 String cpname = sa.getNonConfigurationString(
5186 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005187
5188 p.info.isSyncable = sa.getBoolean(
5189 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
5190 false);
5191
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005192 String permission = sa.getNonConfigurationString(
5193 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
5194 String str = sa.getNonConfigurationString(
5195 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005196 if (str == null) {
5197 str = permission;
5198 }
5199 if (str == null) {
5200 p.info.readPermission = owner.applicationInfo.permission;
5201 } else {
5202 p.info.readPermission =
5203 str.length() > 0 ? str.toString().intern() : null;
5204 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005205 str = sa.getNonConfigurationString(
5206 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005207 if (str == null) {
5208 str = permission;
5209 }
5210 if (str == null) {
5211 p.info.writePermission = owner.applicationInfo.permission;
5212 } else {
5213 p.info.writePermission =
5214 str.length() > 0 ? str.toString().intern() : null;
5215 }
5216
5217 p.info.grantUriPermissions = sa.getBoolean(
5218 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
5219 false);
5220
Dianne Hackborn52e42a42019-02-05 16:10:50 -08005221 p.info.forceUriPermissions = sa.getBoolean(
5222 com.android.internal.R.styleable.AndroidManifestProvider_forceUriPermissions,
5223 false);
5224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 p.info.multiprocess = sa.getBoolean(
5226 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
5227 false);
5228
5229 p.info.initOrder = sa.getInt(
5230 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
5231 0);
5232
Todd Kennedye9d0d272017-01-23 06:49:29 -08005233 p.info.splitName =
5234 sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0);
5235
Dianne Hackborn7d19e022012-08-07 19:12:33 -07005236 p.info.flags = 0;
5237
5238 if (sa.getBoolean(
5239 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
5240 false)) {
5241 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07005242 }
5243
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005244 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
5245 R.styleable.AndroidManifestProvider_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005246 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005247 if (p.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005248 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005249 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005250 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005251
Todd Kennedybe0b8892017-02-15 14:13:52 -08005252 final boolean visibleToEphemeral =
5253 sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005254 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005255 p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005256 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005257 }
5258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005259 sa.recycle();
5260
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005261 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5262 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005263 // A heavy-weight application can not have providers in its main process
5264 // We can do direct compare because we intern all strings.
5265 if (p.info.processName == owner.packageName) {
5266 outError[0] = "Heavy-weight applications can not have providers in main process";
5267 return null;
5268 }
5269 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07005272 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005273 return null;
5274 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08005275 if (cpname.length() <= 0) {
5276 outError[0] = "<provider> has empty authorities attribute";
5277 return null;
5278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005279 p.info.authority = cpname.intern();
5280
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005281 if (!parseProviderTags(
Patrick Baumanna2900392018-02-05 15:30:43 -08005282 res, parser, visibleToEphemeral, p, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005283 return null;
5284 }
5285
5286 return p;
5287 }
5288
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005289 private boolean parseProviderTags(Resources res, XmlResourceParser parser,
Patrick Baumanna2900392018-02-05 15:30:43 -08005290 boolean visibleToEphemeral, Provider outInfo, String[] outError)
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005291 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005292 int outerDepth = parser.getDepth();
5293 int type;
5294 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5295 && (type != XmlPullParser.END_TAG
5296 || parser.getDepth() > outerDepth)) {
5297 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5298 continue;
5299 }
5300
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005301 if (parser.getName().equals("intent-filter")) {
5302 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005303 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5304 intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005305 return false;
5306 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005307 if (visibleToEphemeral) {
5308 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5309 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005310 }
Todd Kennedy6d418b62018-02-22 14:15:18 -08005311 outInfo.order = Math.max(intent.getOrder(), outInfo.order);
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005312 outInfo.intents.add(intent);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005313
5314 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005315 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005316 outInfo.metaData, outError)) == null) {
5317 return false;
5318 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320 } else if (parser.getName().equals("grant-uri-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005321 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005322 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
5323
5324 PatternMatcher pa = null;
5325
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005326 String str = sa.getNonConfigurationString(
5327 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005328 if (str != null) {
5329 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
5330 }
5331
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005332 str = sa.getNonConfigurationString(
5333 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005334 if (str != null) {
5335 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
5336 }
5337
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005338 str = sa.getNonConfigurationString(
5339 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005340 if (str != null) {
5341 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5342 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005344 sa.recycle();
5345
5346 if (pa != null) {
5347 if (outInfo.info.uriPermissionPatterns == null) {
5348 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
5349 outInfo.info.uriPermissionPatterns[0] = pa;
5350 } else {
5351 final int N = outInfo.info.uriPermissionPatterns.length;
5352 PatternMatcher[] newp = new PatternMatcher[N+1];
5353 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
5354 newp[N] = pa;
5355 outInfo.info.uriPermissionPatterns = newp;
5356 }
5357 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005358 } else {
5359 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005360 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005361 + parser.getName() + " at " + mArchiveSourcePath + " "
5362 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005363 XmlUtils.skipCurrentTag(parser);
5364 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005365 } else {
5366 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5367 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005368 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005369 }
5370 XmlUtils.skipCurrentTag(parser);
5371
5372 } else if (parser.getName().equals("path-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005373 TypedArray sa = res.obtainAttributes(parser,
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005374 com.android.internal.R.styleable.AndroidManifestPathPermission);
5375
5376 PathPermission pa = null;
5377
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005378 String permission = sa.getNonConfigurationString(
5379 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
5380 String readPermission = sa.getNonConfigurationString(
5381 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005382 if (readPermission == null) {
5383 readPermission = permission;
5384 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005385 String writePermission = sa.getNonConfigurationString(
5386 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005387 if (writePermission == null) {
5388 writePermission = permission;
5389 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005390
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005391 boolean havePerm = false;
5392 if (readPermission != null) {
5393 readPermission = readPermission.intern();
5394 havePerm = true;
5395 }
5396 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00005397 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005398 havePerm = true;
5399 }
5400
5401 if (!havePerm) {
5402 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005403 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005404 + parser.getName() + " at " + mArchiveSourcePath + " "
5405 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005406 XmlUtils.skipCurrentTag(parser);
5407 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005408 } else {
5409 outError[0] = "No readPermission or writePermssion for <path-permission>";
5410 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005411 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005412 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005413
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005414 String path = sa.getNonConfigurationString(
5415 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005416 if (path != null) {
5417 pa = new PathPermission(path,
5418 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
5419 }
5420
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005421 path = sa.getNonConfigurationString(
5422 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005423 if (path != null) {
5424 pa = new PathPermission(path,
5425 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
5426 }
5427
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005428 path = sa.getNonConfigurationString(
5429 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005430 if (path != null) {
5431 pa = new PathPermission(path,
5432 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
5433 }
5434
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005435 path = sa.getNonConfigurationString(
5436 com.android.internal.R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
5437 if (path != null) {
5438 pa = new PathPermission(path,
5439 PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission);
5440 }
5441
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005442 sa.recycle();
5443
5444 if (pa != null) {
5445 if (outInfo.info.pathPermissions == null) {
5446 outInfo.info.pathPermissions = new PathPermission[1];
5447 outInfo.info.pathPermissions[0] = pa;
5448 } else {
5449 final int N = outInfo.info.pathPermissions.length;
5450 PathPermission[] newp = new PathPermission[N+1];
5451 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
5452 newp[N] = pa;
5453 outInfo.info.pathPermissions = newp;
5454 }
5455 } else {
5456 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005457 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005458 + parser.getName() + " at " + mArchiveSourcePath + " "
5459 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005460 XmlUtils.skipCurrentTag(parser);
5461 continue;
5462 }
5463 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5464 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005465 }
5466 XmlUtils.skipCurrentTag(parser);
5467
5468 } else {
5469 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005470 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005471 + parser.getName() + " at " + mArchiveSourcePath + " "
5472 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005473 XmlUtils.skipCurrentTag(parser);
5474 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005475 } else {
5476 outError[0] = "Bad element under <provider>: " + parser.getName();
5477 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005478 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005479 }
5480 }
5481 return true;
5482 }
5483
5484 private Service parseService(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07005485 XmlResourceParser parser, int flags, String[] outError,
5486 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005487 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005488 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005489 com.android.internal.R.styleable.AndroidManifestService);
5490
Garrett Boyer52136662017-05-23 13:47:58 -07005491 if (cachedArgs.mServiceArgs == null) {
5492 cachedArgs.mServiceArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005493 com.android.internal.R.styleable.AndroidManifestService_name,
5494 com.android.internal.R.styleable.AndroidManifestService_label,
5495 com.android.internal.R.styleable.AndroidManifestService_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005496 com.android.internal.R.styleable.AndroidManifestService_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07005497 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08005498 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005499 mSeparateProcesses,
5500 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005501 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005502 com.android.internal.R.styleable.AndroidManifestService_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07005503 cachedArgs.mServiceArgs.tag = "<service>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005504 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005505
Garrett Boyer52136662017-05-23 13:47:58 -07005506 cachedArgs.mServiceArgs.sa = sa;
5507 cachedArgs.mServiceArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005508
Garrett Boyer52136662017-05-23 13:47:58 -07005509 Service s = new Service(cachedArgs.mServiceArgs, new ServiceInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005510 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005511 sa.recycle();
5512 return null;
5513 }
5514
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005515 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005516 com.android.internal.R.styleable.AndroidManifestService_exported);
5517 if (setExported) {
5518 s.info.exported = sa.getBoolean(
5519 com.android.internal.R.styleable.AndroidManifestService_exported, false);
5520 }
5521
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005522 String str = sa.getNonConfigurationString(
5523 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005524 if (str == null) {
5525 s.info.permission = owner.applicationInfo.permission;
5526 } else {
5527 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
5528 }
5529
Todd Kennedye9d0d272017-01-23 06:49:29 -08005530 s.info.splitName =
5531 sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0);
5532
Hui Yu1ea85522018-12-06 16:59:18 -08005533 s.info.mForegroundServiceType = sa.getInt(
5534 com.android.internal.R.styleable.AndroidManifestService_foregroundServiceType,
Hui Yu2d4207f2019-01-22 15:32:20 -08005535 ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
Hui Yu1ea85522018-12-06 16:59:18 -08005536
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005537 s.info.flags = 0;
5538 if (sa.getBoolean(
5539 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
5540 false)) {
5541 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
5542 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08005543 if (sa.getBoolean(
5544 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
5545 false)) {
5546 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
5547 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005548 if (sa.getBoolean(
Robert Sesekb9a86662015-12-09 16:22:45 -05005549 com.android.internal.R.styleable.AndroidManifestService_externalService,
5550 false)) {
5551 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
5552 }
5553 if (sa.getBoolean(
Martijn Coenene066c5c2018-10-31 16:50:30 +01005554 com.android.internal.R.styleable.AndroidManifestService_useAppZygote,
5555 false)) {
5556 s.info.flags |= ServiceInfo.FLAG_USE_APP_ZYGOTE;
5557 }
5558 if (sa.getBoolean(
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005559 com.android.internal.R.styleable.AndroidManifestService_singleUser,
5560 false)) {
5561 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005562 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005563
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005564 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
5565 R.styleable.AndroidManifestService_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005566 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005567 if (s.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005568 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005569 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005570 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005571
Todd Kennedy752fb702017-03-21 16:28:10 -07005572 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08005573 sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005574 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005575 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005576 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005577 }
5578
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005579 sa.recycle();
5580
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005581 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5582 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005583 // A heavy-weight application can not have services in its main process
5584 // We can do direct compare because we intern all strings.
5585 if (s.info.processName == owner.packageName) {
5586 outError[0] = "Heavy-weight applications can not have services in main process";
5587 return null;
5588 }
5589 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005591 int outerDepth = parser.getDepth();
5592 int type;
5593 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5594 && (type != XmlPullParser.END_TAG
5595 || parser.getDepth() > outerDepth)) {
5596 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5597 continue;
5598 }
5599
5600 if (parser.getName().equals("intent-filter")) {
5601 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005602 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5603 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005604 return null;
5605 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005606 if (visibleToEphemeral) {
5607 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5608 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005609 }
Todd Kennedy6d418b62018-02-22 14:15:18 -08005610 s.order = Math.max(intent.getOrder(), s.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005611 s.intents.add(intent);
5612 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005613 if ((s.metaData=parseMetaData(res, parser, s.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005614 outError)) == null) {
5615 return null;
5616 }
5617 } else {
5618 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005619 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005620 + parser.getName() + " at " + mArchiveSourcePath + " "
5621 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 XmlUtils.skipCurrentTag(parser);
5623 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005624 } else {
5625 outError[0] = "Bad element under <service>: " + parser.getName();
5626 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005627 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005628 }
5629 }
5630
5631 if (!setExported) {
5632 s.info.exported = s.intents.size() > 0;
5633 }
5634
5635 return s;
5636 }
5637
Chad Brubaker49414832017-04-13 16:13:23 -07005638 private boolean isImplicitlyExposedIntent(IntentInfo intent) {
5639 return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
5640 || intent.hasAction(Intent.ACTION_SEND)
5641 || intent.hasAction(Intent.ACTION_SENDTO)
5642 || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005643 }
5644
Svet Ganov354cd3c2015-12-17 11:35:04 -08005645 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
5646 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005647 int outerDepth = parser.getDepth();
5648 int type;
5649 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5650 && (type != XmlPullParser.END_TAG
5651 || parser.getDepth() > outerDepth)) {
5652 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5653 continue;
5654 }
5655
5656 if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005657 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005658 outInfo.metaData, outError)) == null) {
5659 return false;
5660 }
5661 } else {
5662 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005663 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005664 + parser.getName() + " at " + mArchiveSourcePath + " "
5665 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 XmlUtils.skipCurrentTag(parser);
5667 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005668 } else {
5669 outError[0] = "Bad element under " + tag + ": " + parser.getName();
5670 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005672 }
5673 }
5674 return true;
5675 }
5676
5677 private Bundle parseMetaData(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08005678 XmlResourceParser parser, Bundle data, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 throws XmlPullParserException, IOException {
5680
Svet Ganov354cd3c2015-12-17 11:35:04 -08005681 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005682 com.android.internal.R.styleable.AndroidManifestMetaData);
5683
5684 if (data == null) {
5685 data = new Bundle();
5686 }
5687
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005688 String name = sa.getNonConfigurationString(
5689 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005690 if (name == null) {
5691 outError[0] = "<meta-data> requires an android:name attribute";
5692 sa.recycle();
5693 return null;
5694 }
5695
Dianne Hackborn854060af2009-07-09 18:14:31 -07005696 name = name.intern();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005698 TypedValue v = sa.peekValue(
5699 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
5700 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005701 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005702 data.putInt(name, v.resourceId);
5703 } else {
5704 v = sa.peekValue(
5705 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07005706 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005707 if (v != null) {
5708 if (v.type == TypedValue.TYPE_STRING) {
5709 CharSequence cs = v.coerceToString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00005710 data.putString(name, cs != null ? cs.toString() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005711 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
5712 data.putBoolean(name, v.data != 0);
5713 } else if (v.type >= TypedValue.TYPE_FIRST_INT
5714 && v.type <= TypedValue.TYPE_LAST_INT) {
5715 data.putInt(name, v.data);
5716 } else if (v.type == TypedValue.TYPE_FLOAT) {
5717 data.putFloat(name, v.getFloat());
5718 } else {
5719 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005720 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005721 + parser.getName() + " at " + mArchiveSourcePath + " "
5722 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005723 } else {
5724 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
5725 data = null;
5726 }
5727 }
5728 } else {
5729 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
5730 data = null;
5731 }
5732 }
5733
5734 sa.recycle();
5735
5736 XmlUtils.skipCurrentTag(parser);
5737
5738 return data;
5739 }
5740
Adam Lesinski4e862812016-11-21 16:02:24 -08005741 private static VerifierInfo parseVerifier(AttributeSet attrs) {
5742 String packageName = null;
5743 String encodedPublicKey = null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005744
Adam Lesinski4e862812016-11-21 16:02:24 -08005745 final int attrCount = attrs.getAttributeCount();
5746 for (int i = 0; i < attrCount; i++) {
5747 final int attrResId = attrs.getAttributeNameResource(i);
5748 switch (attrResId) {
5749 case com.android.internal.R.attr.name:
5750 packageName = attrs.getAttributeValue(i);
5751 break;
Kenny Root05ca4c92011-09-15 10:36:25 -07005752
Adam Lesinski4e862812016-11-21 16:02:24 -08005753 case com.android.internal.R.attr.publicKey:
5754 encodedPublicKey = attrs.getAttributeValue(i);
5755 break;
5756 }
5757 }
Kenny Root05ca4c92011-09-15 10:36:25 -07005758
5759 if (packageName == null || packageName.length() == 0) {
5760 Slog.i(TAG, "verifier package name was null; skipping");
5761 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005762 }
5763
Christopher Tate30147332014-04-15 12:57:47 -07005764 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
5765 if (publicKey == null) {
5766 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
5767 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08005768 }
5769
Christopher Tate30147332014-04-15 12:57:47 -07005770 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08005771 }
5772
Christopher Tate30147332014-04-15 12:57:47 -07005773 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
5774 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07005775 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07005776 return null;
5777 }
5778
Kenny Root05ca4c92011-09-15 10:36:25 -07005779 EncodedKeySpec keySpec;
5780 try {
5781 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
5782 keySpec = new X509EncodedKeySpec(encoded);
5783 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07005784 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07005785 return null;
5786 }
5787
5788 /* First try the key as an RSA key. */
5789 try {
5790 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005791 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005792 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005793 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005794 } catch (InvalidKeySpecException e) {
5795 // Not a RSA public key.
5796 }
5797
dcashman1616f302015-05-29 14:47:23 -07005798 /* Now try it as a ECDSA key. */
5799 try {
5800 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
5801 return keyFactory.generatePublic(keySpec);
5802 } catch (NoSuchAlgorithmException e) {
5803 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
5804 } catch (InvalidKeySpecException e) {
5805 // Not a ECDSA public key.
5806 }
5807
Kenny Root05ca4c92011-09-15 10:36:25 -07005808 /* Now try it as a DSA key. */
5809 try {
5810 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005811 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005812 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005813 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005814 } catch (InvalidKeySpecException e) {
5815 // Not a DSA public key.
5816 }
5817
dcashman1616f302015-05-29 14:47:23 -07005818 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07005819 return null;
5820 }
5821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005822 private static final String ANDROID_RESOURCES
5823 = "http://schemas.android.com/apk/res/android";
5824
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005825 private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs,
5826 boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
5827 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005828
Svet Ganov354cd3c2015-12-17 11:35:04 -08005829 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 com.android.internal.R.styleable.AndroidManifestIntentFilter);
5831
5832 int priority = sa.getInt(
5833 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005834 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08005835
Todd Kennedy6d418b62018-02-22 14:15:18 -08005836 int order = sa.getInt(
5837 com.android.internal.R.styleable.AndroidManifestIntentFilter_order, 0);
5838 outInfo.setOrder(order);
5839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005840 TypedValue v = sa.peekValue(
5841 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
5842 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
5843 outInfo.nonLocalizedLabel = v.coerceToString();
5844 }
5845
Todd Kennedya83bfca2016-06-03 07:52:17 -07005846 final boolean useRoundIcon =
5847 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
5848 int roundIconVal = useRoundIcon ? sa.getResourceId(
5849 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
5850 if (roundIconVal != 0) {
5851 outInfo.icon = roundIconVal;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005852 } else {
5853 outInfo.icon = sa.getResourceId(
5854 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
5855 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005856
Adam Powell81cd2e92010-04-21 16:35:18 -07005857 outInfo.logo = sa.getResourceId(
5858 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005859
Jose Limaf78e3122014-03-06 12:13:15 -08005860 outInfo.banner = sa.getResourceId(
5861 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
5862
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08005863 if (allowAutoVerify) {
5864 outInfo.setAutoVerify(sa.getBoolean(
5865 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
5866 false));
5867 }
5868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005869 sa.recycle();
5870
5871 int outerDepth = parser.getDepth();
5872 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07005873 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
5874 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
5875 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005876 continue;
5877 }
5878
5879 String nodeName = parser.getName();
5880 if (nodeName.equals("action")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005881 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005882 ANDROID_RESOURCES, "name");
5883 if (value == null || value == "") {
5884 outError[0] = "No value supplied for <android:name>";
5885 return false;
5886 }
5887 XmlUtils.skipCurrentTag(parser);
5888
5889 outInfo.addAction(value);
5890 } else if (nodeName.equals("category")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005891 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005892 ANDROID_RESOURCES, "name");
5893 if (value == null || value == "") {
5894 outError[0] = "No value supplied for <android:name>";
5895 return false;
5896 }
5897 XmlUtils.skipCurrentTag(parser);
5898
5899 outInfo.addCategory(value);
5900
5901 } else if (nodeName.equals("data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005902 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005903 com.android.internal.R.styleable.AndroidManifestData);
5904
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005905 String str = sa.getNonConfigurationString(
5906 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005907 if (str != null) {
5908 try {
5909 outInfo.addDataType(str);
5910 } catch (IntentFilter.MalformedMimeTypeException e) {
5911 outError[0] = e.toString();
5912 sa.recycle();
5913 return false;
5914 }
5915 }
5916
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005917 str = sa.getNonConfigurationString(
5918 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005919 if (str != null) {
5920 outInfo.addDataScheme(str);
5921 }
5922
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005923 str = sa.getNonConfigurationString(
5924 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
5925 if (str != null) {
5926 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
5927 }
5928
5929 str = sa.getNonConfigurationString(
5930 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
5931 if (str != null) {
5932 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
5933 }
5934
5935 str = sa.getNonConfigurationString(
5936 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
5937 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005938 if (!allowGlobs) {
5939 outError[0] = "sspPattern not allowed here; ssp must be literal";
5940 return false;
5941 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005942 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5943 }
5944
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005945 String host = sa.getNonConfigurationString(
5946 com.android.internal.R.styleable.AndroidManifestData_host, 0);
5947 String port = sa.getNonConfigurationString(
5948 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005949 if (host != null) {
5950 outInfo.addDataAuthority(host, port);
5951 }
5952
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005953 str = sa.getNonConfigurationString(
5954 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005955 if (str != null) {
5956 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
5957 }
5958
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005959 str = sa.getNonConfigurationString(
5960 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005961 if (str != null) {
5962 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
5963 }
5964
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005965 str = sa.getNonConfigurationString(
5966 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005967 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005968 if (!allowGlobs) {
5969 outError[0] = "pathPattern not allowed here; path must be literal";
5970 return false;
5971 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005972 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5973 }
5974
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005975 str = sa.getNonConfigurationString(
5976 com.android.internal.R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
5977 if (str != null) {
5978 if (!allowGlobs) {
5979 outError[0] = "pathAdvancedPattern not allowed here; path must be literal";
5980 return false;
5981 }
5982 outInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
5983 }
5984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005985 sa.recycle();
5986 XmlUtils.skipCurrentTag(parser);
5987 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005988 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005989 + parser.getName() + " at " + mArchiveSourcePath + " "
5990 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005991 XmlUtils.skipCurrentTag(parser);
5992 } else {
5993 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
5994 return false;
5995 }
5996 }
5997
5998 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07005999
6000 if (DEBUG_PARSER) {
6001 final StringBuilder cats = new StringBuilder("Intent d=");
6002 cats.append(outInfo.hasDefault);
6003 cats.append(", cat=");
6004
6005 final Iterator<String> it = outInfo.categoriesIterator();
6006 if (it != null) {
6007 while (it.hasNext()) {
6008 cats.append(' ');
6009 cats.append(it.next());
6010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006011 }
Kenny Rootd2d29252011-08-08 11:27:57 -07006012 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006013 }
6014
6015 return true;
6016 }
6017
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006018 /**
6019 * A container for signing-related data of an application package.
6020 * @hide
6021 */
Patrick Baumann47117fc2017-12-19 10:17:21 -08006022 public static final class SigningDetails implements Parcelable {
6023
6024 @IntDef({SigningDetails.SignatureSchemeVersion.UNKNOWN,
6025 SigningDetails.SignatureSchemeVersion.JAR,
6026 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2,
6027 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3})
6028 public @interface SignatureSchemeVersion {
6029 int UNKNOWN = 0;
6030 int JAR = 1;
6031 int SIGNING_BLOCK_V2 = 2;
6032 int SIGNING_BLOCK_V3 = 3;
6033 }
6034
6035 @Nullable
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006036 @UnsupportedAppUsage
Patrick Baumann47117fc2017-12-19 10:17:21 -08006037 public final Signature[] signatures;
6038 @SignatureSchemeVersion
6039 public final int signatureSchemeVersion;
6040 @Nullable
6041 public final ArraySet<PublicKey> publicKeys;
6042
Daniel Cashman77029c52018-01-18 16:19:29 -08006043 /**
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006044 * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
6045 * contains two pieces of information:
6046 * 1) the past signing certificates
6047 * 2) the flags that APK wants to assign to each of the past signing certificates.
6048 *
6049 * This collection of {@code Signature} objects, each of which is formed from a former
6050 * signing certificate of this APK before it was changed by signing certificate rotation,
6051 * represents the first piece of information. It is the APK saying to the rest of the
6052 * world: "hey if you trust the old cert, you can trust me!" This is useful, if for
6053 * instance, the platform would like to determine whether or not to allow this APK to do
6054 * something it would've allowed it to do under the old cert (like upgrade).
Daniel Cashman77029c52018-01-18 16:19:29 -08006055 */
6056 @Nullable
6057 public final Signature[] pastSigningCertificates;
6058
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006059 /** special value used to see if cert is in package - not exposed to callers */
6060 private static final int PAST_CERT_EXISTS = 0;
6061
6062 @IntDef(
6063 flag = true,
6064 value = {CertCapabilities.INSTALLED_DATA,
6065 CertCapabilities.SHARED_USER_ID,
Daniel Cashman629a5f92018-03-30 18:54:14 -07006066 CertCapabilities.PERMISSION,
6067 CertCapabilities.ROLLBACK})
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006068 public @interface CertCapabilities {
6069
6070 /** accept data from already installed pkg with this cert */
6071 int INSTALLED_DATA = 1;
6072
6073 /** accept sharedUserId with pkg with this cert */
6074 int SHARED_USER_ID = 2;
6075
6076 /** grant SIGNATURE permissions to pkgs with this cert */
6077 int PERMISSION = 4;
Daniel Cashman629a5f92018-03-30 18:54:14 -07006078
6079 /** allow pkg to update to one signed by this certificate */
6080 int ROLLBACK = 8;
Dan Cashman303c4bb2018-04-10 07:41:16 -07006081
6082 /** allow pkg to continue to have auth access gated by this cert */
6083 int AUTH = 16;
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006084 }
6085
Patrick Baumann47117fc2017-12-19 10:17:21 -08006086 /** A representation of unknown signing details. Use instead of null. */
6087 public static final SigningDetails UNKNOWN =
Michael Groovera117b0d2018-07-23 12:55:54 -07006088 new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006089
6090 @VisibleForTesting
6091 public SigningDetails(Signature[] signatures,
6092 @SignatureSchemeVersion int signatureSchemeVersion,
Michael Groovera117b0d2018-07-23 12:55:54 -07006093 ArraySet<PublicKey> keys, Signature[] pastSigningCertificates) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08006094 this.signatures = signatures;
6095 this.signatureSchemeVersion = signatureSchemeVersion;
6096 this.publicKeys = keys;
Daniel Cashman77029c52018-01-18 16:19:29 -08006097 this.pastSigningCertificates = pastSigningCertificates;
Daniel Cashman77029c52018-01-18 16:19:29 -08006098 }
6099
6100 public SigningDetails(Signature[] signatures,
6101 @SignatureSchemeVersion int signatureSchemeVersion,
Michael Groovera117b0d2018-07-23 12:55:54 -07006102 Signature[] pastSigningCertificates)
Daniel Cashman77029c52018-01-18 16:19:29 -08006103 throws CertificateException {
6104 this(signatures, signatureSchemeVersion, toSigningKeys(signatures),
Michael Groovera117b0d2018-07-23 12:55:54 -07006105 pastSigningCertificates);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006106 }
6107
6108 public SigningDetails(Signature[] signatures,
6109 @SignatureSchemeVersion int signatureSchemeVersion)
6110 throws CertificateException {
Michael Groovera117b0d2018-07-23 12:55:54 -07006111 this(signatures, signatureSchemeVersion, null);
Daniel Cashman77029c52018-01-18 16:19:29 -08006112 }
6113
6114 public SigningDetails(SigningDetails orig) {
6115 if (orig != null) {
6116 if (orig.signatures != null) {
6117 this.signatures = orig.signatures.clone();
6118 } else {
6119 this.signatures = null;
6120 }
6121 this.signatureSchemeVersion = orig.signatureSchemeVersion;
6122 this.publicKeys = new ArraySet<>(orig.publicKeys);
6123 if (orig.pastSigningCertificates != null) {
6124 this.pastSigningCertificates = orig.pastSigningCertificates.clone();
Daniel Cashman77029c52018-01-18 16:19:29 -08006125 } else {
6126 this.pastSigningCertificates = null;
Daniel Cashman77029c52018-01-18 16:19:29 -08006127 }
6128 } else {
6129 this.signatures = null;
6130 this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
6131 this.publicKeys = null;
6132 this.pastSigningCertificates = null;
Daniel Cashman77029c52018-01-18 16:19:29 -08006133 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08006134 }
6135
6136 /** Returns true if the signing details have one or more signatures. */
6137 public boolean hasSignatures() {
6138 return signatures != null && signatures.length > 0;
6139 }
6140
Daniel Cashman5cdda342018-01-19 07:22:52 -08006141 /** Returns true if the signing details have past signing certificates. */
6142 public boolean hasPastSigningCertificates() {
6143 return pastSigningCertificates != null && pastSigningCertificates.length > 0;
6144 }
6145
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006146 /**
6147 * Determines if the provided {@code oldDetails} is an ancestor of or the same as this one.
6148 * If the {@code oldDetails} signing certificate appears in our pastSigningCertificates,
6149 * then that means it has authorized a signing certificate rotation, which eventually leads
6150 * to our certificate, and thus can be trusted. If this method evaluates to true, this
6151 * SigningDetails object should be trusted if the previous one is.
6152 */
6153 public boolean hasAncestorOrSelf(SigningDetails oldDetails) {
6154 if (this == UNKNOWN || oldDetails == UNKNOWN) {
6155 return false;
6156 }
6157 if (oldDetails.signatures.length > 1) {
6158
6159 // multiple-signer packages cannot rotate signing certs, so we just compare current
6160 // signers for an exact match
6161 return signaturesMatchExactly(oldDetails);
6162 } else {
6163
6164 // we may have signing certificate rotation history, check to see if the oldDetails
6165 // was one of our old signing certificates
6166 return hasCertificate(oldDetails.signatures[0]);
6167 }
6168 }
6169
6170 /**
6171 * Similar to {@code hasAncestorOrSelf}. Returns true only if this {@code SigningDetails}
6172 * is a descendant of {@code oldDetails}, not if they're the same. This is used to
6173 * determine if this object is newer than the provided one.
6174 */
6175 public boolean hasAncestor(SigningDetails oldDetails) {
6176 if (this == UNKNOWN || oldDetails == UNKNOWN) {
6177 return false;
6178 }
6179 if (this.hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
6180
6181 // the last entry in pastSigningCertificates is the current signer, ignore it
6182 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
6183 if (pastSigningCertificates[i].equals(oldDetails.signatures[i])) {
6184 return true;
6185 }
6186 }
6187 }
6188 return false;
6189 }
6190
6191 /**
6192 * Determines if the provided {@code oldDetails} is an ancestor of this one, and whether or
6193 * not this one grants it the provided capability, represented by the {@code flags}
6194 * parameter. In the event of signing certificate rotation, a package may still interact
6195 * with entities signed by its old signing certificate and not want to break previously
6196 * functioning behavior. The {@code flags} value determines which capabilities the app
6197 * signed by the newer signing certificate would like to continue to give to its previous
6198 * signing certificate(s).
6199 */
6200 public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) {
6201 if (this == UNKNOWN || oldDetails == UNKNOWN) {
6202 return false;
6203 }
6204 if (oldDetails.signatures.length > 1) {
6205
6206 // multiple-signer packages cannot rotate signing certs, so we must have an exact
6207 // match, which also means all capabilities are granted
6208 return signaturesMatchExactly(oldDetails);
6209 } else {
6210
6211 // we may have signing certificate rotation history, check to see if the oldDetails
6212 // was one of our old signing certificates, and if we grant it the capability it's
6213 // requesting
6214 return hasCertificate(oldDetails.signatures[0], flags);
6215 }
6216 }
6217
6218 /**
6219 * A special case of {@code checkCapability} which re-encodes both sets of signing
6220 * certificates to counteract a previous re-encoding.
6221 */
6222 public boolean checkCapabilityRecover(SigningDetails oldDetails,
6223 @CertCapabilities int flags) throws CertificateException {
6224 if (oldDetails == UNKNOWN || this == UNKNOWN) {
6225 return false;
6226 }
6227 if (hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
6228
6229 // signing certificates may have rotated, check entire history for effective match
6230 for (int i = 0; i < pastSigningCertificates.length; i++) {
6231 if (Signature.areEffectiveMatch(
6232 oldDetails.signatures[0],
6233 pastSigningCertificates[i])
Michael Groovera117b0d2018-07-23 12:55:54 -07006234 && pastSigningCertificates[i].getFlags() == flags) {
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006235 return true;
6236 }
6237 }
6238 } else {
6239 return Signature.areEffectiveMatch(oldDetails.signatures, signatures);
6240 }
6241 return false;
6242 }
6243
6244 /**
6245 * Determine if {@code signature} is in this SigningDetails' signing certificate history,
6246 * including the current signer. Automatically returns false if this object has multiple
6247 * signing certificates, since rotation is only supported for single-signers; this is
6248 * enforced by {@code hasCertificateInternal}.
6249 */
6250 public boolean hasCertificate(Signature signature) {
6251 return hasCertificateInternal(signature, PAST_CERT_EXISTS);
6252 }
6253
6254 /**
6255 * Determine if {@code signature} is in this SigningDetails' signing certificate history,
6256 * including the current signer, and whether or not it has the given permission.
6257 * Certificates which match our current signer automatically get all capabilities.
6258 * Automatically returns false if this object has multiple signing certificates, since
6259 * rotation is only supported for single-signers.
6260 */
6261 public boolean hasCertificate(Signature signature, @CertCapabilities int flags) {
6262 return hasCertificateInternal(signature, flags);
6263 }
6264
6265 /** Convenient wrapper for calling {@code hasCertificate} with certificate's raw bytes. */
6266 public boolean hasCertificate(byte[] certificate) {
6267 Signature signature = new Signature(certificate);
6268 return hasCertificate(signature);
6269 }
6270
6271 private boolean hasCertificateInternal(Signature signature, int flags) {
6272 if (this == UNKNOWN) {
6273 return false;
6274 }
6275
6276 // only single-signed apps can have pastSigningCertificates
6277 if (hasPastSigningCertificates()) {
6278
6279 // check all past certs, except for the current one, which automatically gets all
6280 // capabilities, since it is the same as the current signature
6281 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
6282 if (pastSigningCertificates[i].equals(signature)) {
6283 if (flags == PAST_CERT_EXISTS
Michael Groovera117b0d2018-07-23 12:55:54 -07006284 || (flags & pastSigningCertificates[i].getFlags()) == flags) {
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006285 return true;
6286 }
6287 }
6288 }
6289 }
6290
6291 // not in previous certs signing history, just check the current signer and make sure
6292 // we are singly-signed
6293 return signatures.length == 1 && signatures[0].equals(signature);
6294 }
6295
6296 /**
6297 * Determines if the provided {@code sha256String} is an ancestor of this one, and whether
6298 * or not this one grants it the provided capability, represented by the {@code flags}
6299 * parameter. In the event of signing certificate rotation, a package may still interact
6300 * with entities signed by its old signing certificate and not want to break previously
6301 * functioning behavior. The {@code flags} value determines which capabilities the app
6302 * signed by the newer signing certificate would like to continue to give to its previous
6303 * signing certificate(s).
6304 *
6305 * @param sha256String A hex-encoded representation of a sha256 digest. In the case of an
6306 * app with multiple signers, this represents the hex-encoded sha256
6307 * digest of the combined hex-encoded sha256 digests of each individual
6308 * signing certificate according to {@link
6309 * PackageUtils#computeSignaturesSha256Digest(Signature[])}
6310 */
6311 public boolean checkCapability(String sha256String, @CertCapabilities int flags) {
6312 if (this == UNKNOWN) {
6313 return false;
6314 }
6315
6316 // first see if the hash represents a single-signer in our signing history
6317 byte[] sha256Bytes = ByteStringUtils.fromHexToByteArray(sha256String);
6318 if (hasSha256Certificate(sha256Bytes, flags)) {
6319 return true;
6320 }
6321
6322 // Not in signing history, either represents multiple signatures or not a match.
6323 // Multiple signers can't rotate, so no need to check flags, just see if the SHAs match.
6324 // We already check the single-signer case above as part of hasSha256Certificate, so no
6325 // need to verify we have multiple signers, just run the old check
6326 // just consider current signing certs
6327 final String[] mSignaturesSha256Digests =
6328 PackageUtils.computeSignaturesSha256Digests(signatures);
6329 final String mSignaturesSha256Digest =
6330 PackageUtils.computeSignaturesSha256Digest(mSignaturesSha256Digests);
6331 return mSignaturesSha256Digest.equals(sha256String);
6332 }
6333
6334 /**
6335 * Determine if the {@code sha256Certificate} is in this SigningDetails' signing certificate
6336 * history, including the current signer. Automatically returns false if this object has
6337 * multiple signing certificates, since rotation is only supported for single-signers.
6338 */
6339 public boolean hasSha256Certificate(byte[] sha256Certificate) {
6340 return hasSha256CertificateInternal(sha256Certificate, PAST_CERT_EXISTS);
6341 }
6342
6343 /**
6344 * Determine if the {@code sha256Certificate} certificate hash corresponds to a signing
6345 * certificate in this SigningDetails' signing certificate history, including the current
6346 * signer, and whether or not it has the given permission. Certificates which match our
6347 * current signer automatically get all capabilities. Automatically returns false if this
6348 * object has multiple signing certificates, since rotation is only supported for
6349 * single-signers.
6350 */
6351 public boolean hasSha256Certificate(byte[] sha256Certificate, @CertCapabilities int flags) {
6352 return hasSha256CertificateInternal(sha256Certificate, flags);
6353 }
6354
6355 private boolean hasSha256CertificateInternal(byte[] sha256Certificate, int flags) {
6356 if (this == UNKNOWN) {
6357 return false;
6358 }
6359 if (hasPastSigningCertificates()) {
6360
6361 // check all past certs, except for the last one, which automatically gets all
6362 // capabilities, since it is the same as the current signature, and is checked below
6363 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
6364 byte[] digest = PackageUtils.computeSha256DigestBytes(
6365 pastSigningCertificates[i].toByteArray());
6366 if (Arrays.equals(sha256Certificate, digest)) {
6367 if (flags == PAST_CERT_EXISTS
Michael Groovera117b0d2018-07-23 12:55:54 -07006368 || (flags & pastSigningCertificates[i].getFlags()) == flags) {
Dan Cashman1dbe6d02018-01-23 11:18:28 -08006369 return true;
6370 }
6371 }
6372 }
6373 }
6374
6375 // not in previous certs signing history, just check the current signer
6376 if (signatures.length == 1) {
6377 byte[] digest =
6378 PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray());
6379 return Arrays.equals(sha256Certificate, digest);
6380 }
6381 return false;
6382 }
6383
Patrick Baumann47117fc2017-12-19 10:17:21 -08006384 /** Returns true if the signatures in this and other match exactly. */
6385 public boolean signaturesMatchExactly(SigningDetails other) {
6386 return Signature.areExactMatch(this.signatures, other.signatures);
6387 }
6388
6389 @Override
6390 public int describeContents() {
6391 return 0;
6392 }
6393
6394 @Override
6395 public void writeToParcel(Parcel dest, int flags) {
6396 boolean isUnknown = UNKNOWN == this;
6397 dest.writeBoolean(isUnknown);
6398 if (isUnknown) {
6399 return;
6400 }
6401 dest.writeTypedArray(this.signatures, flags);
6402 dest.writeInt(this.signatureSchemeVersion);
6403 dest.writeArraySet(this.publicKeys);
Daniel Cashman77029c52018-01-18 16:19:29 -08006404 dest.writeTypedArray(this.pastSigningCertificates, flags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006405 }
6406
6407 protected SigningDetails(Parcel in) {
6408 final ClassLoader boot = Object.class.getClassLoader();
6409 this.signatures = in.createTypedArray(Signature.CREATOR);
6410 this.signatureSchemeVersion = in.readInt();
6411 this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot);
Daniel Cashman77029c52018-01-18 16:19:29 -08006412 this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006413 }
6414
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07006415 public static final @android.annotation.NonNull Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() {
Patrick Baumann47117fc2017-12-19 10:17:21 -08006416 @Override
6417 public SigningDetails createFromParcel(Parcel source) {
6418 if (source.readBoolean()) {
6419 return UNKNOWN;
6420 }
6421 return new SigningDetails(source);
6422 }
6423
6424 @Override
6425 public SigningDetails[] newArray(int size) {
6426 return new SigningDetails[size];
6427 }
6428 };
6429
6430 @Override
6431 public boolean equals(Object o) {
6432 if (this == o) return true;
6433 if (!(o instanceof SigningDetails)) return false;
6434
6435 SigningDetails that = (SigningDetails) o;
6436
6437 if (signatureSchemeVersion != that.signatureSchemeVersion) return false;
6438 if (!Signature.areExactMatch(signatures, that.signatures)) return false;
Daniel Cashman77029c52018-01-18 16:19:29 -08006439 if (publicKeys != null) {
6440 if (!publicKeys.equals((that.publicKeys))) {
6441 return false;
6442 }
6443 } else if (that.publicKeys != null) {
6444 return false;
6445 }
6446
6447 // can't use Signature.areExactMatch() because order matters with the past signing certs
6448 if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) {
6449 return false;
6450 }
Daniel Cashman77029c52018-01-18 16:19:29 -08006451
6452 return true;
Patrick Baumann47117fc2017-12-19 10:17:21 -08006453 }
6454
6455 @Override
6456 public int hashCode() {
6457 int result = +Arrays.hashCode(signatures);
6458 result = 31 * result + signatureSchemeVersion;
6459 result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0);
Daniel Cashman77029c52018-01-18 16:19:29 -08006460 result = 31 * result + Arrays.hashCode(pastSigningCertificates);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006461 return result;
6462 }
Daniel Cashman77029c52018-01-18 16:19:29 -08006463
6464 /**
6465 * Builder of {@code SigningDetails} instances.
6466 */
6467 public static class Builder {
6468 private Signature[] mSignatures;
6469 private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
6470 private Signature[] mPastSigningCertificates;
Daniel Cashman77029c52018-01-18 16:19:29 -08006471
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006472 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006473 public Builder() {
6474 }
6475
6476 /** get signing certificates used to sign the current APK */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006477 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006478 public Builder setSignatures(Signature[] signatures) {
6479 mSignatures = signatures;
6480 return this;
6481 }
6482
6483 /** set the signature scheme version used to sign the APK */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006484 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006485 public Builder setSignatureSchemeVersion(int signatureSchemeVersion) {
6486 mSignatureSchemeVersion = signatureSchemeVersion;
6487 return this;
6488 }
6489
6490 /** set the signing certificates by which the APK proved it can be authenticated */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006491 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006492 public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
6493 mPastSigningCertificates = pastSigningCertificates;
6494 return this;
6495 }
6496
Daniel Cashman77029c52018-01-18 16:19:29 -08006497 private void checkInvariants() {
6498 // must have signatures and scheme version set
6499 if (mSignatures == null) {
6500 throw new IllegalStateException("SigningDetails requires the current signing"
6501 + " certificates.");
6502 }
Daniel Cashman77029c52018-01-18 16:19:29 -08006503 }
6504 /** build a {@code SigningDetails} object */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006505 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006506 public SigningDetails build()
6507 throws CertificateException {
6508 checkInvariants();
6509 return new SigningDetails(mSignatures, mSignatureSchemeVersion,
Michael Groovera117b0d2018-07-23 12:55:54 -07006510 mPastSigningCertificates);
Daniel Cashman77029c52018-01-18 16:19:29 -08006511 }
6512 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08006513 }
6514
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006515 /**
6516 * Representation of a full package parsed from APK files on disk. A package
6517 * consists of a single base APK, and zero or more split APKs.
6518 */
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006519 public final static class Package implements Parcelable {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006520
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006521 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006522 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006523
Svet Ganov67882122016-12-11 16:36:34 -08006524 // The package name declared in the manifest as the package can be
6525 // renamed, for example static shared libs use synthetic package names.
6526 public String manifestPackageName;
6527
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006528 /** Names of any split APKs, ordered by parsed splitName */
6529 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006530
6531 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07006532
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07006533 public String volumeUuid;
6534
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006535 /**
6536 * Path where this package was found on disk. For monolithic packages
6537 * this is path to single base APK file; for cluster packages this is
6538 * path to the cluster directory.
6539 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006540 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006541
6542 /** Path of base APK */
6543 public String baseCodePath;
6544 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006545 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006546
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006547 /** Revision code of base APK */
6548 public int baseRevisionCode;
6549 /** Revision codes of any split APKs, ordered by parsed splitName */
6550 public int[] splitRevisionCodes;
6551
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006552 /** Flags of any split APKs; ordered by parsed splitName */
6553 public int[] splitFlags;
6554
Alex Klyubinb9f8a522015-02-03 11:12:59 -08006555 /**
6556 * Private flags of any split APKs; ordered by parsed splitName.
6557 *
6558 * {@hide}
6559 */
6560 public int[] splitPrivateFlags;
6561
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006562 public boolean baseHardwareAccelerated;
6563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006564 // For now we only support one application per package.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006565 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006566 public ApplicationInfo applicationInfo = new ApplicationInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006567
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006568 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006569 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006570 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006571 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006572 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006573 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006574 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006575 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006576 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006577 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006578 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006579 public final ArrayList<Service> services = new ArrayList<Service>(0);
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006580 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006581 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
6582
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006583 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006584 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
6585
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07006586 /** Permissions requested but not in the manifest. */
6587 public final ArrayList<String> implicitPermissions = new ArrayList<>();
6588
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006589 @UnsupportedAppUsage
Dianne Hackborn854060af2009-07-09 18:14:31 -07006590 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006591
Svet Ganov354cd3c2015-12-17 11:35:04 -08006592 public Package parentPackage;
6593 public ArrayList<Package> childPackages;
6594
Svet Ganov67882122016-12-11 16:36:34 -08006595 public String staticSharedLibName = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006596 public long staticSharedLibVersion = 0;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006597 public ArrayList<String> libraryNames = null;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006598 @UnsupportedAppUsage
Dianne Hackborn49237342009-08-27 20:08:01 -07006599 public ArrayList<String> usesLibraries = null;
Svet Ganov67882122016-12-11 16:36:34 -08006600 public ArrayList<String> usesStaticLibraries = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006601 public long[] usesStaticLibrariesVersions = null;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006602 public String[][] usesStaticLibrariesCertDigests = null;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006603 @UnsupportedAppUsage
Dianne Hackborn49237342009-08-27 20:08:01 -07006604 public ArrayList<String> usesOptionalLibraries = null;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006605 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006606 public String[] usesLibraryFiles = null;
Nicolas Geoffrayabcd58e2018-10-22 10:23:50 +01006607 public ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006608
Dianne Hackbornb09491f2013-07-22 15:30:11 -07006609 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
6610
Dianne Hackbornc1552392010-03-03 16:19:01 -08006611 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006612 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006613 public ArrayList<String> mAdoptPermissions = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006615 // We store the application meta-data independently to avoid multiple unwanted references
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006616 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006617 public Bundle mAppMetaData = null;
6618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006619 // The version code declared for this package.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006620 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006621 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006622
Dianne Hackborn3accca02013-09-20 09:32:11 -07006623 // The major version code declared for this package.
6624 public int mVersionCodeMajor;
6625
6626 // Return long containing mVersionCode and mVersionCodeMajor.
6627 public long getLongVersionCode() {
6628 return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
6629 }
6630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006631 // The version name declared for this package.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006632 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006633 public String mVersionName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006635 // The shared user id that this package wants to use.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006636 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006637 public String mSharedUserId;
6638
6639 // The shared user label that this package wants to use.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006640 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006641 public int mSharedUserLabel;
6642
6643 // Signatures that were read from the package.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006644 @UnsupportedAppUsage
Patrick Baumann47117fc2017-12-19 10:17:21 -08006645 @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006646
6647 // For use by package manager service for quick lookup of
6648 // preferred up order.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006649 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006650 public int mPreferredOrder = 0;
6651
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006652 // For use by package manager to keep track of when a package was last used.
Brian Carlstromca82e612016-04-19 23:16:08 -07006653 public long[] mLastPackageUsageTimeInMills =
6654 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006655
Amith Yamasani13593602012-03-22 16:16:17 -07006656 // // User set enabled state.
6657 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
6658 //
6659 // // Whether the package has been stopped.
6660 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08006661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006662 // Additional data supplied by callers.
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006663 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006664 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07006665
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006666 // Applications hardware preferences
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006667 @UnsupportedAppUsage
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006668 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006669
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006670 // Applications requested features
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006671 @UnsupportedAppUsage
Dianne Hackborn49237342009-08-27 20:08:01 -07006672 public ArrayList<FeatureInfo> reqFeatures = null;
6673
Adam Lesinskid3edfde2014-08-08 17:32:44 -07006674 // Applications requested feature groups
6675 public ArrayList<FeatureGroupInfo> featureGroups = null;
6676
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006677 @UnsupportedAppUsage
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08006678 public int installLocation;
6679
Jeff Hao272bf3a2014-10-08 13:34:43 -07006680 public boolean coreApp;
6681
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08006682 /* An app that's required for all users and cannot be uninstalled for a user */
6683 public boolean mRequiredForAllUsers;
6684
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006685 /* The restricted account authenticator type that is used by this application */
6686 public String mRestrictedAccountType;
6687
Amith Yamasaniccbe3892013-04-12 17:52:42 -07006688 /* The required account type without which this application will not function */
6689 public String mRequiredAccountType;
6690
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006691 public String mOverlayTarget;
Ryan Mitchella3628462019-01-14 12:19:40 -08006692 public String mOverlayTargetName;
Adrian Roosc84df772018-01-19 21:20:22 +01006693 public String mOverlayCategory;
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006694 public int mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -08006695 public boolean mOverlayIsStatic;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006696
Alan Viveretteb6a25732017-11-21 14:49:24 -05006697 public int mCompileSdkVersion;
6698 public String mCompileSdkVersionCodename;
6699
Geremy Condraf1bcca82013-01-07 22:35:24 -08006700 /**
dcashman989eb3712014-06-17 12:56:12 -07006701 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08006702 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006703 @UnsupportedAppUsage
dcashman989eb3712014-06-17 12:56:12 -07006704 public ArraySet<String> mUpgradeKeySets;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006705 @UnsupportedAppUsage
dcashman989eb3712014-06-17 12:56:12 -07006706 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08006707
Narayan Kamath4903f642014-08-11 13:33:45 +01006708 /**
6709 * The install time abi override for this package, if any.
6710 *
6711 * TODO: This seems like a horrible place to put the abiOverride because
6712 * this isn't something the packageParser parsers. However, this fits in with
6713 * the rest of the PackageManager where package scanning randomly pushes
6714 * and prods fields out of {@code this.applicationInfo}.
6715 */
6716 public String cpuAbiOverride;
Selim Gurun2d291d82016-02-05 17:50:53 -08006717 /**
6718 * The install time abi override to choose 32bit abi's when multiple abi's
6719 * are present. This is only meaningfull for multiarch applications.
6720 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
6721 */
6722 public boolean use32bitAbi;
Narayan Kamath4903f642014-08-11 13:33:45 +01006723
Todd Kennedyfdd241a2016-04-28 12:26:53 -07006724 public byte[] restrictUpdateHash;
6725
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006726 /** Set if the app or any of its components are visible to instant applications. */
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006727 public boolean visibleToInstantApps;
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006728 /** Whether or not the package is a stub and must be replaced by the full version. */
6729 public boolean isStub;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006730
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006731 @UnsupportedAppUsage
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006732 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006733 this.packageName = packageName;
Svet Ganov67882122016-12-11 16:36:34 -08006734 this.manifestPackageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006735 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006736 applicationInfo.uid = -1;
6737 }
6738
Svet Ganov354cd3c2015-12-17 11:35:04 -08006739 public void setApplicationVolumeUuid(String volumeUuid) {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006740 final UUID storageUuid = StorageManager.convert(volumeUuid);
Svet Ganov354cd3c2015-12-17 11:35:04 -08006741 this.applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006742 this.applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006743 if (childPackages != null) {
6744 final int packageCount = childPackages.size();
6745 for (int i = 0; i < packageCount; i++) {
6746 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006747 childPackages.get(i).applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006748 }
6749 }
6750 }
6751
6752 public void setApplicationInfoCodePath(String codePath) {
6753 this.applicationInfo.setCodePath(codePath);
6754 if (childPackages != null) {
6755 final int packageCount = childPackages.size();
6756 for (int i = 0; i < packageCount; i++) {
6757 childPackages.get(i).applicationInfo.setCodePath(codePath);
6758 }
6759 }
6760 }
6761
Todd Kennedy30a23a52018-01-04 13:27:49 -08006762 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6763 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006764 public void setApplicationInfoResourcePath(String resourcePath) {
6765 this.applicationInfo.setResourcePath(resourcePath);
6766 if (childPackages != null) {
6767 final int packageCount = childPackages.size();
6768 for (int i = 0; i < packageCount; i++) {
6769 childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
6770 }
6771 }
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 setApplicationInfoBaseResourcePath(String resourcePath) {
6777 this.applicationInfo.setBaseResourcePath(resourcePath);
6778 if (childPackages != null) {
6779 final int packageCount = childPackages.size();
6780 for (int i = 0; i < packageCount; i++) {
6781 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
6782 }
6783 }
6784 }
6785
6786 public void setApplicationInfoBaseCodePath(String baseCodePath) {
6787 this.applicationInfo.setBaseCodePath(baseCodePath);
6788 if (childPackages != null) {
6789 final int packageCount = childPackages.size();
6790 for (int i = 0; i < packageCount; i++) {
6791 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
6792 }
6793 }
6794 }
6795
Todd Kennedy13715d52016-08-01 13:38:57 -07006796 public List<String> getChildPackageNames() {
6797 if (childPackages == null) {
6798 return null;
6799 }
6800 final int childCount = childPackages.size();
6801 final List<String> childPackageNames = new ArrayList<>(childCount);
6802 for (int i = 0; i < childCount; i++) {
6803 String childPackageName = childPackages.get(i).packageName;
6804 childPackageNames.add(childPackageName);
6805 }
6806 return childPackageNames;
6807 }
6808
Svet Ganov354cd3c2015-12-17 11:35:04 -08006809 public boolean hasChildPackage(String packageName) {
6810 final int childCount = (childPackages != null) ? childPackages.size() : 0;
6811 for (int i = 0; i < childCount; i++) {
6812 if (childPackages.get(i).packageName.equals(packageName)) {
6813 return true;
6814 }
6815 }
6816 return false;
6817 }
6818
6819 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
6820 this.applicationInfo.setSplitCodePaths(splitCodePaths);
6821 // Children have no splits
6822 }
6823
Todd Kennedy30a23a52018-01-04 13:27:49 -08006824 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6825 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006826 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
6827 this.applicationInfo.setSplitResourcePaths(resroucePaths);
6828 // Children have no splits
6829 }
6830
6831 public void setSplitCodePaths(String[] codePaths) {
6832 this.splitCodePaths = codePaths;
6833 }
6834
6835 public void setCodePath(String codePath) {
6836 this.codePath = codePath;
6837 if (childPackages != null) {
6838 final int packageCount = childPackages.size();
6839 for (int i = 0; i < packageCount; i++) {
6840 childPackages.get(i).codePath = codePath;
6841 }
6842 }
6843 }
6844
6845 public void setBaseCodePath(String baseCodePath) {
6846 this.baseCodePath = baseCodePath;
6847 if (childPackages != null) {
6848 final int packageCount = childPackages.size();
6849 for (int i = 0; i < packageCount; i++) {
6850 childPackages.get(i).baseCodePath = baseCodePath;
6851 }
6852 }
6853 }
6854
Patrick Baumann47117fc2017-12-19 10:17:21 -08006855 /** Sets signing details on the package and any of its children. */
6856 public void setSigningDetails(@NonNull SigningDetails signingDetails) {
6857 mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006858 if (childPackages != null) {
6859 final int packageCount = childPackages.size();
6860 for (int i = 0; i < packageCount; i++) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08006861 childPackages.get(i).mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006862 }
6863 }
6864 }
6865
6866 public void setVolumeUuid(String volumeUuid) {
6867 this.volumeUuid = volumeUuid;
6868 if (childPackages != null) {
6869 final int packageCount = childPackages.size();
6870 for (int i = 0; i < packageCount; i++) {
6871 childPackages.get(i).volumeUuid = volumeUuid;
6872 }
6873 }
6874 }
6875
6876 public void setApplicationInfoFlags(int mask, int flags) {
6877 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
6878 if (childPackages != null) {
6879 final int packageCount = childPackages.size();
6880 for (int i = 0; i < packageCount; i++) {
6881 childPackages.get(i).applicationInfo.flags =
6882 (applicationInfo.flags & ~mask) | (mask & flags);
6883 }
6884 }
6885 }
6886
Selim Gurun75827b22016-02-09 10:55:33 -08006887 public void setUse32bitAbi(boolean use32bitAbi) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006888 this.use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006889 if (childPackages != null) {
6890 final int packageCount = childPackages.size();
6891 for (int i = 0; i < packageCount; i++) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006892 childPackages.get(i).use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006893 }
6894 }
6895 }
6896
Svetoslav Ganov40610e32017-06-20 19:35:51 -07006897 public boolean isLibrary() {
6898 return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
6899 }
6900
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006901 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07006902 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006903 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07006904 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6905 Collections.addAll(paths, splitCodePaths);
6906 }
6907 return paths;
6908 }
6909
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006910 /**
6911 * Filtered set of {@link #getAllCodePaths()} that excludes
6912 * resource-only APKs.
6913 */
6914 public List<String> getAllCodePathsExcludingResourceOnly() {
6915 ArrayList<String> paths = new ArrayList<>();
6916 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6917 paths.add(baseCodePath);
6918 }
6919 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6920 for (int i = 0; i < splitCodePaths.length; i++) {
6921 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6922 paths.add(splitCodePaths[i]);
6923 }
6924 }
6925 }
6926 return paths;
6927 }
6928
Mathew Inwood5c0d3542018-08-14 13:54:31 +01006929 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006930 public void setPackageName(String newName) {
6931 packageName = newName;
6932 applicationInfo.packageName = newName;
6933 for (int i=permissions.size()-1; i>=0; i--) {
6934 permissions.get(i).setPackageName(newName);
6935 }
6936 for (int i=permissionGroups.size()-1; i>=0; i--) {
6937 permissionGroups.get(i).setPackageName(newName);
6938 }
6939 for (int i=activities.size()-1; i>=0; i--) {
6940 activities.get(i).setPackageName(newName);
6941 }
6942 for (int i=receivers.size()-1; i>=0; i--) {
6943 receivers.get(i).setPackageName(newName);
6944 }
6945 for (int i=providers.size()-1; i>=0; i--) {
6946 providers.get(i).setPackageName(newName);
6947 }
6948 for (int i=services.size()-1; i>=0; i--) {
6949 services.get(i).setPackageName(newName);
6950 }
6951 for (int i=instrumentation.size()-1; i>=0; i--) {
6952 instrumentation.get(i).setPackageName(newName);
6953 }
6954 }
Dianne Hackborn65696252012-03-05 18:49:21 -08006955
6956 public boolean hasComponentClassName(String name) {
6957 for (int i=activities.size()-1; i>=0; i--) {
6958 if (name.equals(activities.get(i).className)) {
6959 return true;
6960 }
6961 }
6962 for (int i=receivers.size()-1; i>=0; i--) {
6963 if (name.equals(receivers.get(i).className)) {
6964 return true;
6965 }
6966 }
6967 for (int i=providers.size()-1; i>=0; i--) {
6968 if (name.equals(providers.get(i).className)) {
6969 return true;
6970 }
6971 }
6972 for (int i=services.size()-1; i>=0; i--) {
6973 if (name.equals(services.get(i).className)) {
6974 return true;
6975 }
6976 }
6977 for (int i=instrumentation.size()-1; i>=0; i--) {
6978 if (name.equals(instrumentation.get(i).className)) {
6979 return true;
6980 }
6981 }
6982 return false;
6983 }
6984
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006985 /** @hide */
6986 public boolean isExternal() {
6987 return applicationInfo.isExternal();
6988 }
6989
6990 /** @hide */
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08006991 public boolean isForwardLocked() {
Patrick Baumannfc2851e2018-11-13 15:23:22 -08006992 return false;
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08006993 }
6994
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006995 /** @hide */
6996 public boolean isOem() {
6997 return applicationInfo.isOem();
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006998 }
6999
Todd Kennedyc29b11a2017-10-23 15:55:59 -07007000 /** @hide */
Jiyong Park002fdbd2017-02-13 20:50:31 +09007001 public boolean isVendor() {
7002 return applicationInfo.isVendor();
7003 }
7004
7005 /** @hide */
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09007006 public boolean isProduct() {
7007 return applicationInfo.isProduct();
7008 }
7009
7010 /** @hide */
Dario Freni2bef1762018-06-01 14:02:08 +01007011 public boolean isProductServices() {
7012 return applicationInfo.isProductServices();
7013 }
7014
7015 /** @hide */
Todd Kennedyc29b11a2017-10-23 15:55:59 -07007016 public boolean isPrivileged() {
Svet Ganovadc1cf42015-06-15 16:36:24 -07007017 return applicationInfo.isPrivilegedApp();
7018 }
7019
Todd Kennedyc29b11a2017-10-23 15:55:59 -07007020 /** @hide */
7021 public boolean isSystem() {
7022 return applicationInfo.isSystemApp();
7023 }
7024
7025 /** @hide */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08007026 public boolean isUpdatedSystemApp() {
7027 return applicationInfo.isUpdatedSystemApp();
7028 }
7029
Todd Kennedyc29b11a2017-10-23 15:55:59 -07007030 /** @hide */
Fyodor Kupolovebcac162015-09-09 15:56:45 -07007031 public boolean canHaveOatDir() {
7032 // The following app types CANNOT have oat directory
7033 // - non-updated system apps
Patrick Baumannfc2851e2018-11-13 15:23:22 -08007034 return !isSystem() || isUpdatedSystemApp();
Fyodor Kupolovebcac162015-09-09 15:56:45 -07007035 }
7036
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07007037 public boolean isMatch(int flags) {
7038 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07007039 return isSystem();
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07007040 }
7041 return true;
7042 }
7043
Brian Carlstromca82e612016-04-19 23:16:08 -07007044 public long getLatestPackageUseTimeInMills() {
7045 long latestUse = 0L;
7046 for (long use : mLastPackageUsageTimeInMills) {
7047 latestUse = Math.max(latestUse, use);
7048 }
7049 return latestUse;
7050 }
7051
David Brazdil90e26992016-04-18 14:08:52 +01007052 public long getLatestForegroundPackageUseTimeInMills() {
7053 int[] foregroundReasons = {
7054 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
7055 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
7056 };
7057
7058 long latestUse = 0L;
7059 for (int reason : foregroundReasons) {
7060 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
7061 }
7062 return latestUse;
7063 }
7064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007065 public String toString() {
7066 return "Package{"
7067 + Integer.toHexString(System.identityHashCode(this))
7068 + " " + packageName + "}";
7069 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007070
7071 @Override
7072 public int describeContents() {
7073 return 0;
7074 }
7075
7076 public Package(Parcel dest) {
7077 // We use the boot classloader for all classes that we load.
7078 final ClassLoader boot = Object.class.getClassLoader();
7079
Narayan Kamath07ac1442017-02-10 15:08:07 +00007080 packageName = dest.readString().intern();
Svet Ganov67882122016-12-11 16:36:34 -08007081 manifestPackageName = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007082 splitNames = dest.readStringArray();
7083 volumeUuid = dest.readString();
7084 codePath = dest.readString();
7085 baseCodePath = dest.readString();
7086 splitCodePaths = dest.readStringArray();
7087 baseRevisionCode = dest.readInt();
7088 splitRevisionCodes = dest.createIntArray();
7089 splitFlags = dest.createIntArray();
7090 splitPrivateFlags = dest.createIntArray();
7091 baseHardwareAccelerated = (dest.readInt() == 1);
7092 applicationInfo = dest.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007093 if (applicationInfo.permission != null) {
7094 applicationInfo.permission = applicationInfo.permission.intern();
7095 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007096
7097 // We don't serialize the "owner" package and the application info object for each of
7098 // these components, in order to save space and to avoid circular dependencies while
7099 // serialization. We need to fix them all up here.
7100 dest.readParcelableList(permissions, boot);
7101 fixupOwner(permissions);
7102 dest.readParcelableList(permissionGroups, boot);
7103 fixupOwner(permissionGroups);
7104 dest.readParcelableList(activities, boot);
7105 fixupOwner(activities);
7106 dest.readParcelableList(receivers, boot);
7107 fixupOwner(receivers);
7108 dest.readParcelableList(providers, boot);
7109 fixupOwner(providers);
7110 dest.readParcelableList(services, boot);
7111 fixupOwner(services);
7112 dest.readParcelableList(instrumentation, boot);
7113 fixupOwner(instrumentation);
7114
7115 dest.readStringList(requestedPermissions);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007116 internStringArrayList(requestedPermissions);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07007117 dest.readStringList(implicitPermissions);
7118 internStringArrayList(implicitPermissions);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007119 protectedBroadcasts = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007120 internStringArrayList(protectedBroadcasts);
7121
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007122 parentPackage = dest.readParcelable(boot);
7123
7124 childPackages = new ArrayList<>();
7125 dest.readParcelableList(childPackages, boot);
7126 if (childPackages.size() == 0) {
7127 childPackages = null;
7128 }
7129
Svet Ganov67882122016-12-11 16:36:34 -08007130 staticSharedLibName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007131 if (staticSharedLibName != null) {
7132 staticSharedLibName = staticSharedLibName.intern();
7133 }
Dianne Hackborn3accca02013-09-20 09:32:11 -07007134 staticSharedLibVersion = dest.readLong();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007135 libraryNames = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007136 internStringArrayList(libraryNames);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007137 usesLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007138 internStringArrayList(usesLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007139 usesOptionalLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007140 internStringArrayList(usesOptionalLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007141 usesLibraryFiles = dest.readStringArray();
7142
Nicolas Geoffrayabcd58e2018-10-22 10:23:50 +01007143 usesLibraryInfos = dest.createTypedArrayList(SharedLibraryInfo.CREATOR);
7144
Svet Ganov67882122016-12-11 16:36:34 -08007145 final int libCount = dest.readInt();
7146 if (libCount > 0) {
7147 usesStaticLibraries = new ArrayList<>(libCount);
7148 dest.readStringList(usesStaticLibraries);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007149 internStringArrayList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07007150 usesStaticLibrariesVersions = new long[libCount];
7151 dest.readLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07007152 usesStaticLibrariesCertDigests = new String[libCount][];
7153 for (int i = 0; i < libCount; i++) {
7154 usesStaticLibrariesCertDigests[i] = dest.createStringArray();
7155 }
Svet Ganov67882122016-12-11 16:36:34 -08007156 }
7157
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007158 preferredActivityFilters = new ArrayList<>();
7159 dest.readParcelableList(preferredActivityFilters, boot);
7160 if (preferredActivityFilters.size() == 0) {
7161 preferredActivityFilters = null;
7162 }
7163
7164 mOriginalPackages = dest.createStringArrayList();
7165 mRealPackage = dest.readString();
7166 mAdoptPermissions = dest.createStringArrayList();
7167 mAppMetaData = dest.readBundle();
7168 mVersionCode = dest.readInt();
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08007169 mVersionCodeMajor = dest.readInt();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007170 mVersionName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007171 if (mVersionName != null) {
7172 mVersionName = mVersionName.intern();
7173 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007174 mSharedUserId = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007175 if (mSharedUserId != null) {
7176 mSharedUserId = mSharedUserId.intern();
7177 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007178 mSharedUserLabel = dest.readInt();
7179
Patrick Baumann47117fc2017-12-19 10:17:21 -08007180 mSigningDetails = dest.readParcelable(boot);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007181
7182 mPreferredOrder = dest.readInt();
7183
7184 // long[] packageUsageTimeMillis is not persisted because it isn't information that
7185 // is parsed from the APK.
7186
7187 // Object mExtras is not persisted because it is not information that is read from
7188 // the APK, rather, it is supplied by callers.
7189
7190
7191 configPreferences = new ArrayList<>();
7192 dest.readParcelableList(configPreferences, boot);
7193 if (configPreferences.size() == 0) {
7194 configPreferences = null;
7195 }
7196
7197 reqFeatures = new ArrayList<>();
7198 dest.readParcelableList(reqFeatures, boot);
7199 if (reqFeatures.size() == 0) {
7200 reqFeatures = null;
7201 }
7202
7203 featureGroups = new ArrayList<>();
7204 dest.readParcelableList(featureGroups, boot);
7205 if (featureGroups.size() == 0) {
7206 featureGroups = null;
7207 }
7208
7209 installLocation = dest.readInt();
7210 coreApp = (dest.readInt() == 1);
7211 mRequiredForAllUsers = (dest.readInt() == 1);
7212 mRestrictedAccountType = dest.readString();
7213 mRequiredAccountType = dest.readString();
7214 mOverlayTarget = dest.readString();
Ryan Mitchella3628462019-01-14 12:19:40 -08007215 mOverlayTargetName = dest.readString();
Adrian Roosc84df772018-01-19 21:20:22 +01007216 mOverlayCategory = dest.readString();
Jaekyun Seok42d53f62017-04-10 13:48:58 +09007217 mOverlayPriority = dest.readInt();
Adam Lesinskie7334972018-01-17 16:13:52 -08007218 mOverlayIsStatic = (dest.readInt() == 1);
Alan Viveretteb6a25732017-11-21 14:49:24 -05007219 mCompileSdkVersion = dest.readInt();
7220 mCompileSdkVersionCodename = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007221 mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
7222
7223 mKeySetMapping = readKeySetMapping(dest);
7224
7225 cpuAbiOverride = dest.readString();
7226 use32bitAbi = (dest.readInt() == 1);
7227 restrictUpdateHash = dest.createByteArray();
Chad Brubaker49f24c62017-04-05 13:08:21 -07007228 visibleToInstantApps = dest.readInt() == 1;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007229 }
7230
Narayan Kamath07ac1442017-02-10 15:08:07 +00007231 private static void internStringArrayList(List<String> list) {
7232 if (list != null) {
7233 final int N = list.size();
7234 for (int i = 0; i < N; ++i) {
7235 list.set(i, list.get(i).intern());
7236 }
7237 }
7238 }
7239
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007240 /**
7241 * Sets the package owner and the the {@code applicationInfo} for every component
7242 * owner by this package.
7243 */
7244 private void fixupOwner(List<? extends Component<?>> list) {
7245 if (list != null) {
7246 for (Component<?> c : list) {
7247 c.owner = this;
7248 if (c instanceof Activity) {
7249 ((Activity) c).info.applicationInfo = this.applicationInfo;
7250 } else if (c instanceof Service) {
7251 ((Service) c).info.applicationInfo = this.applicationInfo;
7252 } else if (c instanceof Provider) {
7253 ((Provider) c).info.applicationInfo = this.applicationInfo;
7254 }
7255 }
7256 }
7257 }
7258
7259 @Override
7260 public void writeToParcel(Parcel dest, int flags) {
7261 dest.writeString(packageName);
Svet Ganov67882122016-12-11 16:36:34 -08007262 dest.writeString(manifestPackageName);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007263 dest.writeStringArray(splitNames);
7264 dest.writeString(volumeUuid);
7265 dest.writeString(codePath);
7266 dest.writeString(baseCodePath);
7267 dest.writeStringArray(splitCodePaths);
7268 dest.writeInt(baseRevisionCode);
7269 dest.writeIntArray(splitRevisionCodes);
7270 dest.writeIntArray(splitFlags);
7271 dest.writeIntArray(splitPrivateFlags);
7272 dest.writeInt(baseHardwareAccelerated ? 1 : 0);
7273 dest.writeParcelable(applicationInfo, flags);
7274
7275 dest.writeParcelableList(permissions, flags);
7276 dest.writeParcelableList(permissionGroups, flags);
7277 dest.writeParcelableList(activities, flags);
7278 dest.writeParcelableList(receivers, flags);
7279 dest.writeParcelableList(providers, flags);
7280 dest.writeParcelableList(services, flags);
7281 dest.writeParcelableList(instrumentation, flags);
7282
7283 dest.writeStringList(requestedPermissions);
Philip P. Moltmann17f65af2018-10-18 15:32:29 -07007284 dest.writeStringList(implicitPermissions);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007285 dest.writeStringList(protectedBroadcasts);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07007286
7287 // TODO: This doesn't work: b/64295061
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007288 dest.writeParcelable(parentPackage, flags);
7289 dest.writeParcelableList(childPackages, flags);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07007290
Svet Ganov67882122016-12-11 16:36:34 -08007291 dest.writeString(staticSharedLibName);
Dianne Hackborn3accca02013-09-20 09:32:11 -07007292 dest.writeLong(staticSharedLibVersion);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007293 dest.writeStringList(libraryNames);
7294 dest.writeStringList(usesLibraries);
7295 dest.writeStringList(usesOptionalLibraries);
7296 dest.writeStringArray(usesLibraryFiles);
Nicolas Geoffrayabcd58e2018-10-22 10:23:50 +01007297 dest.writeTypedList(usesLibraryInfos);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007298
Svet Ganov67882122016-12-11 16:36:34 -08007299 if (ArrayUtils.isEmpty(usesStaticLibraries)) {
7300 dest.writeInt(-1);
7301 } else {
7302 dest.writeInt(usesStaticLibraries.size());
7303 dest.writeStringList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07007304 dest.writeLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07007305 for (String[] usesStaticLibrariesCertDigest : usesStaticLibrariesCertDigests) {
7306 dest.writeStringArray(usesStaticLibrariesCertDigest);
7307 }
Svet Ganov67882122016-12-11 16:36:34 -08007308 }
7309
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007310 dest.writeParcelableList(preferredActivityFilters, flags);
7311
7312 dest.writeStringList(mOriginalPackages);
7313 dest.writeString(mRealPackage);
7314 dest.writeStringList(mAdoptPermissions);
7315 dest.writeBundle(mAppMetaData);
7316 dest.writeInt(mVersionCode);
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08007317 dest.writeInt(mVersionCodeMajor);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007318 dest.writeString(mVersionName);
7319 dest.writeString(mSharedUserId);
7320 dest.writeInt(mSharedUserLabel);
7321
Patrick Baumann47117fc2017-12-19 10:17:21 -08007322 dest.writeParcelable(mSigningDetails, flags);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007323
7324 dest.writeInt(mPreferredOrder);
7325
7326 // long[] packageUsageTimeMillis is not persisted because it isn't information that
7327 // is parsed from the APK.
7328
7329 // Object mExtras is not persisted because it is not information that is read from
7330 // the APK, rather, it is supplied by callers.
7331
7332 dest.writeParcelableList(configPreferences, flags);
7333 dest.writeParcelableList(reqFeatures, flags);
7334 dest.writeParcelableList(featureGroups, flags);
7335
7336 dest.writeInt(installLocation);
7337 dest.writeInt(coreApp ? 1 : 0);
7338 dest.writeInt(mRequiredForAllUsers ? 1 : 0);
7339 dest.writeString(mRestrictedAccountType);
7340 dest.writeString(mRequiredAccountType);
7341 dest.writeString(mOverlayTarget);
Ryan Mitchella3628462019-01-14 12:19:40 -08007342 dest.writeString(mOverlayTargetName);
Adrian Roosc84df772018-01-19 21:20:22 +01007343 dest.writeString(mOverlayCategory);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09007344 dest.writeInt(mOverlayPriority);
Adam Lesinskie7334972018-01-17 16:13:52 -08007345 dest.writeInt(mOverlayIsStatic ? 1 : 0);
Alan Viveretteb6a25732017-11-21 14:49:24 -05007346 dest.writeInt(mCompileSdkVersion);
7347 dest.writeString(mCompileSdkVersionCodename);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007348 dest.writeArraySet(mUpgradeKeySets);
7349 writeKeySetMapping(dest, mKeySetMapping);
7350 dest.writeString(cpuAbiOverride);
7351 dest.writeInt(use32bitAbi ? 1 : 0);
7352 dest.writeByteArray(restrictUpdateHash);
Chad Brubaker49f24c62017-04-05 13:08:21 -07007353 dest.writeInt(visibleToInstantApps ? 1 : 0);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007354 }
7355
7356
7357 /**
7358 * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
7359 */
7360 private static void writeKeySetMapping(
7361 Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
7362 if (keySetMapping == null) {
7363 dest.writeInt(-1);
7364 return;
7365 }
7366
7367 final int N = keySetMapping.size();
7368 dest.writeInt(N);
7369
7370 for (int i = 0; i < N; i++) {
7371 dest.writeString(keySetMapping.keyAt(i));
7372 ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
7373 if (keys == null) {
7374 dest.writeInt(-1);
7375 continue;
7376 }
7377
7378 final int M = keys.size();
7379 dest.writeInt(M);
7380 for (int j = 0; j < M; j++) {
7381 dest.writeSerializable(keys.valueAt(j));
7382 }
7383 }
7384 }
7385
7386 /**
7387 * Reads a keyset mapping from the given parcel at the given data position. May return
7388 * {@code null} if the serialized mapping was {@code null}.
7389 */
7390 private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
7391 final int N = in.readInt();
7392 if (N == -1) {
7393 return null;
7394 }
7395
7396 ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
7397 for (int i = 0; i < N; ++i) {
7398 String key = in.readString();
7399 final int M = in.readInt();
7400 if (M == -1) {
7401 keySetMapping.put(key, null);
7402 continue;
7403 }
7404
7405 ArraySet<PublicKey> keys = new ArraySet<>(M);
7406 for (int j = 0; j < M; ++j) {
7407 PublicKey pk = (PublicKey) in.readSerializable();
7408 keys.add(pk);
7409 }
7410
7411 keySetMapping.put(key, keys);
7412 }
7413
7414 return keySetMapping;
7415 }
7416
7417 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
7418 public Package createFromParcel(Parcel in) {
7419 return new Package(in);
7420 }
7421
7422 public Package[] newArray(int size) {
7423 return new Package[size];
7424 }
7425 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007426 }
7427
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007428 public static abstract class Component<II extends IntentInfo> {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007429 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007430 public final ArrayList<II> intents;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007431 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007432 public final String className;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007433
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007434 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007435 public Bundle metaData;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007436 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007437 public Package owner;
Todd Kennedy6d418b62018-02-22 14:15:18 -08007438 /** The order of this component in relation to its peers */
7439 public int order;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007440
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007441 ComponentName componentName;
7442 String componentShortName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007443
Ricky Waicf134eb2018-10-10 09:26:32 +01007444 public Component(Package owner, ArrayList<II> intents, String className) {
7445 this.owner = owner;
7446 this.intents = intents;
7447 this.className = className;
7448 }
7449
7450 public Component(Package owner) {
7451 this.owner = owner;
7452 this.intents = null;
7453 this.className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007454 }
7455
7456 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
7457 owner = args.owner;
7458 intents = new ArrayList<II>(0);
Todd Kennedybb8a42d2016-06-02 14:13:56 -07007459 if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
7460 true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
7461 args.roundIconRes, args.logoRes, args.bannerRes)) {
7462 className = outInfo.name;
7463 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007464 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007465 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007466 }
7467
7468 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
7469 this(args, (PackageItemInfo)outInfo);
7470 if (args.outError[0] != null) {
7471 return;
7472 }
7473
7474 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007475 CharSequence pname;
7476 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07007477 pname = args.sa.getNonConfigurationString(args.processRes,
7478 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007479 } else {
7480 // Some older apps have been seen to use a resource reference
7481 // here that on older builds was ignored (with a warning). We
7482 // need to continue to do this for them so they don't break.
7483 pname = args.sa.getNonResourceString(args.processRes);
7484 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007485 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007486 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007487 args.flags, args.sepProcesses, args.outError);
7488 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007489
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08007490 if (args.descriptionRes != 0) {
7491 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
7492 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007493
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007494 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007495 }
7496
7497 public Component(Component<II> clone) {
7498 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007499 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007500 className = clone.className;
7501 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007502 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007503 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007504
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007505 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007506 public ComponentName getComponentName() {
7507 if (componentName != null) {
7508 return componentName;
7509 }
7510 if (className != null) {
7511 componentName = new ComponentName(owner.applicationInfo.packageName,
7512 className);
7513 }
7514 return componentName;
7515 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007516
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007517 protected Component(Parcel in) {
7518 className = in.readString();
7519 metaData = in.readBundle();
7520 intents = createIntentsList(in);
7521
7522 owner = null;
7523 }
7524
7525 protected void writeToParcel(Parcel dest, int flags) {
7526 dest.writeString(className);
7527 dest.writeBundle(metaData);
7528
7529 writeIntentsList(intents, dest, flags);
7530 }
7531
7532 /**
7533 * <p>
7534 * Implementation note: The serialized form for the intent list also contains the name
7535 * of the concrete class that's stored in the list, and assumes that every element of the
7536 * list is of the same type. This is very similar to the original parcelable mechanism.
7537 * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
7538 * and is public API. It also declares Parcelable related methods as final which means
7539 * we can't extend them. The approach of using composition instead of inheritance leads to
7540 * a large set of cascading changes in the PackageManagerService, which seem undesirable.
7541 *
7542 * <p>
7543 * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
7544 * to make sure their owner fields are consistent. See {@code fixupOwner}.
7545 */
7546 private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out,
7547 int flags) {
7548 if (list == null) {
7549 out.writeInt(-1);
7550 return;
7551 }
7552
7553 final int N = list.size();
7554 out.writeInt(N);
7555
7556 // Don't bother writing the component name if the list is empty.
7557 if (N > 0) {
7558 IntentInfo info = list.get(0);
7559 out.writeString(info.getClass().getName());
7560
7561 for (int i = 0; i < N;i++) {
7562 list.get(i).writeIntentInfoToParcel(out, flags);
7563 }
7564 }
7565 }
7566
7567 private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) {
7568 int N = in.readInt();
7569 if (N == -1) {
7570 return null;
7571 }
7572
7573 if (N == 0) {
7574 return new ArrayList<>(0);
7575 }
7576
7577 String componentName = in.readString();
7578 final ArrayList<T> intentsList;
7579 try {
7580 final Class<T> cls = (Class<T>) Class.forName(componentName);
7581 final Constructor<T> cons = cls.getConstructor(Parcel.class);
7582
7583 intentsList = new ArrayList<>(N);
7584 for (int i = 0; i < N; ++i) {
7585 intentsList.add(cons.newInstance(in));
7586 }
7587 } catch (ReflectiveOperationException ree) {
7588 throw new AssertionError("Unable to construct intent list for: " + componentName);
7589 }
7590
7591 return intentsList;
7592 }
7593
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007594 public void appendComponentShortName(StringBuilder sb) {
7595 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007596 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007597
7598 public void printComponentShortName(PrintWriter pw) {
7599 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
7600 }
7601
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007602 public void setPackageName(String packageName) {
7603 componentName = null;
7604 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007605 }
7606 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007607
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007608 public final static class Permission extends Component<IntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007609 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007610 public final PermissionInfo info;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007611 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007612 public boolean tree;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007613 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007614 public PermissionGroup group;
7615
Philip P. Moltmanna4844d12019-03-02 10:17:23 -08007616 /**
7617 * @hide
7618 */
7619 public Permission(Package owner, @Nullable String backgroundPermission) {
7620 super(owner);
7621 info = new PermissionInfo(backgroundPermission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007622 }
7623
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007624 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007625 public Permission(Package _owner, PermissionInfo _info) {
7626 super(_owner);
7627 info = _info;
7628 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007629
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007630 public void setPackageName(String packageName) {
7631 super.setPackageName(packageName);
7632 info.packageName = packageName;
7633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007634
7635 public String toString() {
7636 return "Permission{"
7637 + Integer.toHexString(System.identityHashCode(this))
7638 + " " + info.name + "}";
7639 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007640
7641 @Override
7642 public int describeContents() {
7643 return 0;
7644 }
7645
7646 @Override
7647 public void writeToParcel(Parcel dest, int flags) {
7648 super.writeToParcel(dest, flags);
7649 dest.writeParcelable(info, flags);
7650 dest.writeInt(tree ? 1 : 0);
7651 dest.writeParcelable(group, flags);
7652 }
7653
Todd Kennedyc8423932017-10-05 08:58:36 -07007654 /** @hide */
7655 public boolean isAppOp() {
7656 return info.isAppOp();
7657 }
7658
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007659 private Permission(Parcel in) {
7660 super(in);
7661 final ClassLoader boot = Object.class.getClassLoader();
7662 info = in.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007663 if (info.group != null) {
7664 info.group = info.group.intern();
7665 }
7666
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007667 tree = (in.readInt() == 1);
7668 group = in.readParcelable(boot);
7669 }
7670
7671 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
7672 public Permission createFromParcel(Parcel in) {
7673 return new Permission(in);
7674 }
7675
7676 public Permission[] newArray(int size) {
7677 return new Permission[size];
7678 }
7679 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007680 }
7681
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007682 public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007683 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007684 public final PermissionGroupInfo info;
7685
Philip P. Moltmann0635dab2019-03-02 11:19:03 -08007686 public PermissionGroup(Package owner, @StringRes int requestDetailResourceId,
7687 @StringRes int backgroundRequestResourceId,
7688 @StringRes int backgroundRequestDetailResourceId) {
7689 super(owner);
7690 info = new PermissionGroupInfo(requestDetailResourceId, backgroundRequestResourceId,
7691 backgroundRequestDetailResourceId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007692 }
7693
7694 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
7695 super(_owner);
7696 info = _info;
7697 }
7698
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007699 public void setPackageName(String packageName) {
7700 super.setPackageName(packageName);
7701 info.packageName = packageName;
7702 }
7703
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007704 public String toString() {
7705 return "PermissionGroup{"
7706 + Integer.toHexString(System.identityHashCode(this))
7707 + " " + info.name + "}";
7708 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007709
7710 @Override
7711 public int describeContents() {
7712 return 0;
7713 }
7714
7715 @Override
7716 public void writeToParcel(Parcel dest, int flags) {
7717 super.writeToParcel(dest, flags);
7718 dest.writeParcelable(info, flags);
7719 }
7720
7721 private PermissionGroup(Parcel in) {
7722 super(in);
7723 info = in.readParcelable(Object.class.getClassLoader());
7724 }
7725
7726 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
7727 public PermissionGroup createFromParcel(Parcel in) {
7728 return new PermissionGroup(in);
7729 }
7730
7731 public PermissionGroup[] newArray(int size) {
7732 return new PermissionGroup[size];
7733 }
7734 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007735 }
7736
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007737 private static boolean copyNeeded(int flags, Package p,
7738 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07007739 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007740 // We always need to copy for other users, since we need
7741 // to fix up the uid.
7742 return true;
7743 }
7744 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
7745 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07007746 if (p.applicationInfo.enabled != enabled) {
7747 return true;
7748 }
7749 }
Rubin Xubf67c9c2016-04-20 17:09:38 +01007750 boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
7751 if (state.suspended != suspended) {
7752 return true;
7753 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007754 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007755 return true;
7756 }
7757 if (state.stopped) {
7758 return true;
7759 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007760 if (state.instantApp != p.applicationInfo.isInstantApp()) {
7761 return true;
7762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007763 if ((flags & PackageManager.GET_META_DATA) != 0
7764 && (metaData != null || p.mAppMetaData != null)) {
7765 return true;
7766 }
7767 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7768 && p.usesLibraryFiles != null) {
7769 return true;
7770 }
Nicolas Geoffrayabcd58e2018-10-22 10:23:50 +01007771 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7772 && p.usesLibraryInfos != null) {
7773 return true;
7774 }
Svet Ganov67882122016-12-11 16:36:34 -08007775 if (p.staticSharedLibName != null) {
7776 return true;
7777 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007778 return false;
7779 }
7780
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007781 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007782 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
7783 PackageUserState state) {
7784 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07007785 }
7786
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007787 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
7788 PackageUserState state) {
7789 // CompatibilityMode is global state.
7790 if (!sCompatibilityModeEnabled) {
7791 ai.disableCompatibilityMode();
7792 }
7793 if (state.installed) {
7794 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
7795 } else {
7796 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
7797 }
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00007798 if (state.suspended) {
7799 ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
7800 } else {
7801 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
7802 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007803 if (state.instantApp) {
7804 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
7805 } else {
7806 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
7807 }
Todd Kennedy5eb5a7d2017-08-01 07:42:47 -07007808 if (state.virtualPreload) {
7809 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7810 } else {
7811 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7812 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007813 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007814 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007815 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007816 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007817 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007818 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
7819 ai.enabled = true;
7820 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
7821 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
7822 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
7823 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
7824 ai.enabled = false;
7825 }
7826 ai.enabledSetting = state.enabled;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07007827 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7828 ai.category = state.categoryHint;
7829 }
Jeff Sharkey0078e1b2017-01-11 16:05:27 -07007830 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7831 ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
7832 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007833 ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
Todd Kennedyb2749472017-06-13 08:24:32 -07007834 ai.resourceDirs = state.overlayPaths;
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007835 }
7836
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007837 @UnsupportedAppUsage
Amith Yamasani13593602012-03-22 16:16:17 -07007838 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007839 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007840 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007841 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007842 return null;
7843 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007844 if (!copyNeeded(flags, p, state, null, userId)
7845 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
7846 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
7847 // In this case it is safe to directly modify the internal ApplicationInfo state:
7848 // - CompatibilityMode is global state, so will be the same for every call.
7849 // - We only come in to here if the app should reported as installed; this is the
7850 // default state, and we will do a copy otherwise.
7851 // - The enable state will always be reported the same for the application across
7852 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
7853 // be doing a copy.
7854 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007855 return p.applicationInfo;
7856 }
7857
7858 // Make shallow copy so we can store the metadata/libraries safely
7859 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Jeff Sharkey15447792015-11-05 16:18:51 -08007860 ai.initForUser(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007861 if ((flags & PackageManager.GET_META_DATA) != 0) {
7862 ai.metaData = p.mAppMetaData;
7863 }
7864 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
7865 ai.sharedLibraryFiles = p.usesLibraryFiles;
Nicolas Geoffray8d144eb2018-11-15 12:59:52 +00007866 ai.sharedLibraryInfos = p.usesLibraryInfos;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007867 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007868 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007869 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007870 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007871 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007872 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007873 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007874 return ai;
7875 }
7876
Dianne Hackbornace27912014-09-18 18:38:30 -07007877 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
7878 PackageUserState state, int userId) {
7879 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007880 if (!checkUseInstalledOrHidden(flags, state, ai)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007881 return null;
7882 }
7883 // This is only used to return the ResolverActivity; we will just always
7884 // make a copy.
7885 ai = new ApplicationInfo(ai);
Jeff Sharkey15447792015-11-05 16:18:51 -08007886 ai.initForUser(userId);
Dianne Hackbornace27912014-09-18 18:38:30 -07007887 if (state.stopped) {
7888 ai.flags |= ApplicationInfo.FLAG_STOPPED;
7889 } else {
7890 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
7891 }
7892 updateApplicationInfo(ai, flags, state);
7893 return ai;
7894 }
7895
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007896 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007897 public static final PermissionInfo generatePermissionInfo(
7898 Permission p, int flags) {
7899 if (p == null) return null;
7900 if ((flags&PackageManager.GET_META_DATA) == 0) {
7901 return p.info;
7902 }
7903 PermissionInfo pi = new PermissionInfo(p.info);
7904 pi.metaData = p.metaData;
7905 return pi;
7906 }
7907
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007908 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007909 public static final PermissionGroupInfo generatePermissionGroupInfo(
7910 PermissionGroup pg, int flags) {
7911 if (pg == null) return null;
7912 if ((flags&PackageManager.GET_META_DATA) == 0) {
7913 return pg.info;
7914 }
7915 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
7916 pgi.metaData = pg.metaData;
7917 return pgi;
7918 }
7919
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007920 public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01007921 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007922 public final ActivityInfo info;
Bryce Lee22571db2017-07-07 15:54:18 -07007923 private boolean mHasMaxAspectRatio;
Adrian Roos917791e2018-11-28 16:30:44 +01007924 private boolean mHasMinAspectRatio;
Bryce Lee22571db2017-07-07 15:54:18 -07007925
7926 private boolean hasMaxAspectRatio() {
7927 return mHasMaxAspectRatio;
7928 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007929
Adrian Roos917791e2018-11-28 16:30:44 +01007930 private boolean hasMinAspectRatio() {
7931 return mHasMinAspectRatio;
7932 }
7933
Ricky Waicf134eb2018-10-10 09:26:32 +01007934 // To construct custom activity which does not exist in manifest
7935 Activity(final Package owner, final String className, final ActivityInfo info) {
7936 super(owner, new ArrayList<>(0), className);
7937 this.info = info;
7938 this.info.applicationInfo = owner.applicationInfo;
7939 }
7940
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007941 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
7942 super(args, _info);
7943 info = _info;
7944 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007945 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007946
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007947 public void setPackageName(String packageName) {
7948 super.setPackageName(packageName);
7949 info.packageName = packageName;
7950 }
7951
Bryce Lee22571db2017-07-07 15:54:18 -07007952
7953 private void setMaxAspectRatio(float maxAspectRatio) {
7954 if (info.resizeMode == RESIZE_MODE_RESIZEABLE
7955 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
7956 // Resizeable activities can be put in any aspect ratio.
7957 return;
7958 }
7959
7960 if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
7961 // Ignore any value lesser than 1.0.
7962 return;
7963 }
7964
7965 info.maxAspectRatio = maxAspectRatio;
7966 mHasMaxAspectRatio = true;
7967 }
7968
Adrian Roos917791e2018-11-28 16:30:44 +01007969 private void setMinAspectRatio(float minAspectRatio) {
7970 if (info.resizeMode == RESIZE_MODE_RESIZEABLE
7971 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
7972 // Resizeable activities can be put in any aspect ratio.
7973 return;
7974 }
7975
7976 if (minAspectRatio < 1.0f && minAspectRatio != 0) {
7977 // Ignore any value lesser than 1.0.
7978 return;
7979 }
7980
7981 info.minAspectRatio = minAspectRatio;
7982 mHasMinAspectRatio = true;
7983 }
7984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007985 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007986 StringBuilder sb = new StringBuilder(128);
7987 sb.append("Activity{");
7988 sb.append(Integer.toHexString(System.identityHashCode(this)));
7989 sb.append(' ');
7990 appendComponentShortName(sb);
7991 sb.append('}');
7992 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007993 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007994
7995 @Override
7996 public int describeContents() {
7997 return 0;
7998 }
7999
8000 @Override
8001 public void writeToParcel(Parcel dest, int flags) {
8002 super.writeToParcel(dest, flags);
8003 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
Bryce Lee22571db2017-07-07 15:54:18 -07008004 dest.writeBoolean(mHasMaxAspectRatio);
Adrian Roos917791e2018-11-28 16:30:44 +01008005 dest.writeBoolean(mHasMinAspectRatio);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008006 }
8007
8008 private Activity(Parcel in) {
8009 super(in);
8010 info = in.readParcelable(Object.class.getClassLoader());
Bryce Lee22571db2017-07-07 15:54:18 -07008011 mHasMaxAspectRatio = in.readBoolean();
Adrian Roos917791e2018-11-28 16:30:44 +01008012 mHasMinAspectRatio = in.readBoolean();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008013
8014 for (ActivityIntentInfo aii : intents) {
8015 aii.activity = this;
Todd Kennedy6d418b62018-02-22 14:15:18 -08008016 order = Math.max(aii.getOrder(), order);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008017 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00008018
8019 if (info.permission != null) {
8020 info.permission = info.permission.intern();
8021 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008022 }
8023
8024 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
8025 public Activity createFromParcel(Parcel in) {
8026 return new Activity(in);
8027 }
8028
8029 public Activity[] newArray(int size) {
8030 return new Activity[size];
8031 }
8032 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008033 }
8034
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008035 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008036 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
8037 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008038 if (a == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07008039 if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008040 return null;
8041 }
8042 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07008043 updateApplicationInfo(a.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008044 return a.info;
8045 }
8046 // Make shallow copies so we can store the metadata safely
8047 ActivityInfo ai = new ActivityInfo(a.info);
8048 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008049 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008050 return ai;
8051 }
8052
Dianne Hackbornace27912014-09-18 18:38:30 -07008053 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
8054 PackageUserState state, int userId) {
8055 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07008056 if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07008057 return null;
8058 }
8059 // This is only used to return the ResolverActivity; we will just always
8060 // make a copy.
8061 ai = new ActivityInfo(ai);
8062 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
8063 return ai;
8064 }
8065
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008066 public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008067 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008068 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008069
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008070 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
8071 super(args, _info);
8072 info = _info;
8073 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008074 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07008075
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008076 public void setPackageName(String packageName) {
8077 super.setPackageName(packageName);
8078 info.packageName = packageName;
8079 }
8080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008081 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008082 StringBuilder sb = new StringBuilder(128);
8083 sb.append("Service{");
8084 sb.append(Integer.toHexString(System.identityHashCode(this)));
8085 sb.append(' ');
8086 appendComponentShortName(sb);
8087 sb.append('}');
8088 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008089 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008090
8091 @Override
8092 public int describeContents() {
8093 return 0;
8094 }
8095
8096 @Override
8097 public void writeToParcel(Parcel dest, int flags) {
8098 super.writeToParcel(dest, flags);
8099 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
8100 }
8101
8102 private Service(Parcel in) {
8103 super(in);
8104 info = in.readParcelable(Object.class.getClassLoader());
8105
8106 for (ServiceIntentInfo aii : intents) {
8107 aii.service = this;
Todd Kennedy6d418b62018-02-22 14:15:18 -08008108 order = Math.max(aii.getOrder(), order);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008109 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00008110
8111 if (info.permission != null) {
8112 info.permission = info.permission.intern();
8113 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008114 }
8115
8116 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
8117 public Service createFromParcel(Parcel in) {
8118 return new Service(in);
8119 }
8120
8121 public Service[] newArray(int size) {
8122 return new Service[size];
8123 }
8124 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008125 }
8126
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008127 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008128 public static final ServiceInfo generateServiceInfo(Service s, int flags,
8129 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008130 if (s == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07008131 if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008132 return null;
8133 }
8134 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07008135 updateApplicationInfo(s.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008136 return s.info;
8137 }
8138 // Make shallow copies so we can store the metadata safely
8139 ServiceInfo si = new ServiceInfo(s.info);
8140 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008141 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008142 return si;
8143 }
8144
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008145 public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008146 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008147 public final ProviderInfo info;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008148 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008149 public boolean syncable;
8150
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008151 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
8152 super(args, _info);
8153 info = _info;
8154 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008155 syncable = false;
8156 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07008157
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008158 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008159 public Provider(Provider existingProvider) {
8160 super(existingProvider);
8161 this.info = existingProvider.info;
8162 this.syncable = existingProvider.syncable;
8163 }
8164
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008165 public void setPackageName(String packageName) {
8166 super.setPackageName(packageName);
8167 info.packageName = packageName;
8168 }
8169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008170 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008171 StringBuilder sb = new StringBuilder(128);
8172 sb.append("Provider{");
8173 sb.append(Integer.toHexString(System.identityHashCode(this)));
8174 sb.append(' ');
8175 appendComponentShortName(sb);
8176 sb.append('}');
8177 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008178 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008179
8180 @Override
8181 public int describeContents() {
8182 return 0;
8183 }
8184
8185 @Override
8186 public void writeToParcel(Parcel dest, int flags) {
8187 super.writeToParcel(dest, flags);
8188 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
8189 dest.writeInt((syncable) ? 1 : 0);
8190 }
8191
8192 private Provider(Parcel in) {
8193 super(in);
8194 info = in.readParcelable(Object.class.getClassLoader());
8195 syncable = (in.readInt() == 1);
8196
8197 for (ProviderIntentInfo aii : intents) {
8198 aii.provider = this;
8199 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00008200
8201 if (info.readPermission != null) {
8202 info.readPermission = info.readPermission.intern();
8203 }
8204
8205 if (info.writePermission != null) {
8206 info.writePermission = info.writePermission.intern();
8207 }
8208
8209 if (info.authority != null) {
8210 info.authority = info.authority.intern();
8211 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008212 }
8213
8214 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
8215 public Provider createFromParcel(Parcel in) {
8216 return new Provider(in);
8217 }
8218
8219 public Provider[] newArray(int size) {
8220 return new Provider[size];
8221 }
8222 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 }
8224
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008225 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008226 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
8227 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008228 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07008229 if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008230 return null;
8231 }
8232 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008233 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008234 || p.info.uriPermissionPatterns == null)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07008235 updateApplicationInfo(p.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008236 return p.info;
8237 }
8238 // Make shallow copies so we can store the metadata safely
8239 ProviderInfo pi = new ProviderInfo(p.info);
8240 pi.metaData = p.metaData;
8241 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
8242 pi.uriPermissionPatterns = null;
8243 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008244 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008245 return pi;
8246 }
8247
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008248 public final static class Instrumentation extends Component<IntentInfo> implements
8249 Parcelable {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008250 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008251 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008252
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008253 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
8254 super(args, _info);
8255 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008256 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07008257
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008258 public void setPackageName(String packageName) {
8259 super.setPackageName(packageName);
8260 info.packageName = packageName;
8261 }
8262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008263 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008264 StringBuilder sb = new StringBuilder(128);
8265 sb.append("Instrumentation{");
8266 sb.append(Integer.toHexString(System.identityHashCode(this)));
8267 sb.append(' ');
8268 appendComponentShortName(sb);
8269 sb.append('}');
8270 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008271 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008272
8273 @Override
8274 public int describeContents() {
8275 return 0;
8276 }
8277
8278 @Override
8279 public void writeToParcel(Parcel dest, int flags) {
8280 super.writeToParcel(dest, flags);
8281 dest.writeParcelable(info, flags);
8282 }
8283
8284 private Instrumentation(Parcel in) {
8285 super(in);
8286 info = in.readParcelable(Object.class.getClassLoader());
Narayan Kamath07ac1442017-02-10 15:08:07 +00008287
8288 if (info.targetPackage != null) {
8289 info.targetPackage = info.targetPackage.intern();
8290 }
8291
Dianne Hackborn1be53542017-04-28 13:36:00 -07008292 if (info.targetProcesses != null) {
8293 info.targetProcesses = info.targetProcesses.intern();
Narayan Kamath07ac1442017-02-10 15:08:07 +00008294 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008295 }
8296
8297 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
8298 public Instrumentation createFromParcel(Parcel in) {
8299 return new Instrumentation(in);
8300 }
8301
8302 public Instrumentation[] newArray(int size) {
8303 return new Instrumentation[size];
8304 }
8305 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008306 }
8307
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008308 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008309 public static final InstrumentationInfo generateInstrumentationInfo(
8310 Instrumentation i, int flags) {
8311 if (i == null) return null;
8312 if ((flags&PackageManager.GET_META_DATA) == 0) {
8313 return i.info;
8314 }
8315 InstrumentationInfo ii = new InstrumentationInfo(i.info);
8316 ii.metaData = i.metaData;
8317 return ii;
8318 }
8319
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008320 public static abstract class IntentInfo extends IntentFilter {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008321 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008322 public boolean hasDefault;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008323 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008324 public int labelRes;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008325 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008326 public CharSequence nonLocalizedLabel;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008327 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008328 public int icon;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008329 @UnsupportedAppUsage
Adam Powell81cd2e92010-04-21 16:35:18 -07008330 public int logo;
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008331 @UnsupportedAppUsage
Jose Limaf78e3122014-03-06 12:13:15 -08008332 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07008333 public int preferred;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008334
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008335 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008336 protected IntentInfo() {
8337 }
8338
8339 protected IntentInfo(Parcel dest) {
8340 super(dest);
8341 hasDefault = (dest.readInt() == 1);
8342 labelRes = dest.readInt();
8343 nonLocalizedLabel = dest.readCharSequence();
8344 icon = dest.readInt();
8345 logo = dest.readInt();
8346 banner = dest.readInt();
8347 preferred = dest.readInt();
8348 }
8349
8350
8351 public void writeIntentInfoToParcel(Parcel dest, int flags) {
8352 super.writeToParcel(dest, flags);
8353 dest.writeInt(hasDefault ? 1 : 0);
8354 dest.writeInt(labelRes);
8355 dest.writeCharSequence(nonLocalizedLabel);
8356 dest.writeInt(icon);
8357 dest.writeInt(logo);
8358 dest.writeInt(banner);
8359 dest.writeInt(preferred);
8360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008361 }
8362
8363 public final static class ActivityIntentInfo extends IntentInfo {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008364 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008365 public Activity activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008366
8367 public ActivityIntentInfo(Activity _activity) {
8368 activity = _activity;
8369 }
8370
8371 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008372 StringBuilder sb = new StringBuilder(128);
8373 sb.append("ActivityIntentInfo{");
8374 sb.append(Integer.toHexString(System.identityHashCode(this)));
8375 sb.append(' ');
8376 activity.appendComponentShortName(sb);
8377 sb.append('}');
8378 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008379 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008380
8381 public ActivityIntentInfo(Parcel in) {
8382 super(in);
8383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008384 }
8385
8386 public final static class ServiceIntentInfo extends IntentInfo {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008387 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008388 public Service service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008389
8390 public ServiceIntentInfo(Service _service) {
8391 service = _service;
8392 }
8393
8394 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008395 StringBuilder sb = new StringBuilder(128);
8396 sb.append("ServiceIntentInfo{");
8397 sb.append(Integer.toHexString(System.identityHashCode(this)));
8398 sb.append(' ');
8399 service.appendComponentShortName(sb);
8400 sb.append('}');
8401 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008402 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008403
8404 public ServiceIntentInfo(Parcel in) {
8405 super(in);
8406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008407 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008408
Jeff Sharkey85f5f812013-10-07 10:16:12 -07008409 public static final class ProviderIntentInfo extends IntentInfo {
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008410 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008411 public Provider provider;
Jeff Sharkey85f5f812013-10-07 10:16:12 -07008412
8413 public ProviderIntentInfo(Provider provider) {
8414 this.provider = provider;
8415 }
8416
8417 public String toString() {
8418 StringBuilder sb = new StringBuilder(128);
8419 sb.append("ProviderIntentInfo{");
8420 sb.append(Integer.toHexString(System.identityHashCode(this)));
8421 sb.append(' ');
8422 provider.appendComponentShortName(sb);
8423 sb.append('}');
8424 return sb.toString();
8425 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008426
8427 public ProviderIntentInfo(Parcel in) {
8428 super(in);
8429 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -07008430 }
8431
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008432 /**
8433 * @hide
8434 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +01008435 @UnsupportedAppUsage
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008436 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
8437 sCompatibilityModeEnabled = compatibilityModeEnabled;
8438 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07008439
8440 public static class PackageParserException extends Exception {
8441 public final int error;
8442
8443 public PackageParserException(int error, String detailMessage) {
8444 super(detailMessage);
8445 this.error = error;
8446 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07008447
8448 public PackageParserException(int error, String detailMessage, Throwable throwable) {
8449 super(detailMessage, throwable);
8450 this.error = error;
8451 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07008452 }
Jiyong Park5b1b7342019-01-18 09:45:17 +09008453
8454 public static PackageInfo generatePackageInfoFromApex(File apexFile, boolean collectCerts)
8455 throws PackageParserException {
8456 PackageInfo pi = new PackageInfo();
Martijn Coenenf4b90702019-02-27 12:37:08 +01008457 int parseFlags = 0;
8458 if (collectCerts) {
8459 parseFlags |= PARSE_COLLECT_CERTIFICATES;
8460 try {
8461 if (apexFile.getCanonicalPath().startsWith("/system")) {
8462 // Don't need verify the APK integrity of APEXes on /system, just like
8463 // we don't do that for APKs.
8464 // TODO(b/126514108): we may be able to do this for APEXes on /data as well.
8465 parseFlags |= PARSE_IS_SYSTEM_DIR;
8466 }
8467 } catch (IOException e) {
8468 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
8469 "Failed to get path for " + apexFile.getPath(), e);
8470 }
8471 }
Jeff Hamiltonacd7db82019-01-18 15:12:21 -05008472
8473 // TODO(b/123086053) properly fill in the ApplicationInfo with data from AndroidManifest
8474 // Add ApplicationInfo to the PackageInfo.
8475 ApplicationInfo ai = new ApplicationInfo();
8476 ai.sourceDir = apexFile.getPath();
8477 ai.flags = ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_INSTALLED;
8478 ai.enabled = true;
8479 ai.targetSdkVersion = 28;
8480 ai.targetSandboxVersion = 0;
8481 pi.applicationInfo = ai;
8482
8483
Jiyong Park5b1b7342019-01-18 09:45:17 +09008484 // TODO(b/123052859): We should avoid these repeated calls to parseApkLite each time
8485 // we want to generate information for APEX modules.
Martijn Coenenf4b90702019-02-27 12:37:08 +01008486 PackageParser.ApkLite apk = PackageParser.parseApkLite(apexFile, parseFlags);
Jiyong Park5b1b7342019-01-18 09:45:17 +09008487
8488 pi.packageName = apk.packageName;
Dario Freni50a21482019-01-24 11:53:59 +00008489 ai.packageName = apk.packageName;
Jiyong Park5b1b7342019-01-18 09:45:17 +09008490 pi.setLongVersionCode(apk.getLongVersionCode());
Dario Freni788ecb12019-01-23 18:49:32 +00008491 ai.setVersionCode(apk.getLongVersionCode());
Jiyong Park5b1b7342019-01-18 09:45:17 +09008492
8493 if (collectCerts) {
8494 if (apk.signingDetails.hasPastSigningCertificates()) {
8495 // Package has included signing certificate rotation information. Return
8496 // the oldest cert so that programmatic checks keep working even if unaware
8497 // of key rotation.
8498 pi.signatures = new Signature[1];
8499 pi.signatures[0] = apk.signingDetails.pastSigningCertificates[0];
8500 } else if (apk.signingDetails.hasSignatures()) {
8501 // otherwise keep old behavior
8502 int numberOfSigs = apk.signingDetails.signatures.length;
8503 pi.signatures = new Signature[numberOfSigs];
8504 System.arraycopy(apk.signingDetails.signatures, 0, pi.signatures, 0,
8505 numberOfSigs);
8506 }
8507
8508 if (apk.signingDetails != SigningDetails.UNKNOWN) {
8509 // only return a valid SigningInfo if there is signing information to report
8510 pi.signingInfo = new SigningInfo(apk.signingDetails);
8511 } else {
8512 pi.signingInfo = null;
8513 }
8514 }
8515
8516 pi.isApex = true;
8517 return pi;
8518 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008519}