blob: ecb9dbf386141d042c422823de3af36e74482805 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.content.pm;
18
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070019import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
Winson Chungd3395382016-12-13 11:49:09 -080020import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070021import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
22import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
23import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
24import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
25import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070026import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
27import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
28import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
29import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
Wale Ogunwalee633eb02017-03-30 12:57:29 -070030import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
31import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Garrett Boyer52136662017-05-23 13:47:58 -070032import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070033import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
34import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070035import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
36import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
37import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070038import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -070039import static android.os.Build.VERSION_CODES.O;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070040import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
Robert Carr427ba4f2017-07-17 18:37:06 -070041import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070042
Todd Kennedy232d29e2017-11-06 14:45:53 -080043import android.annotation.IntDef;
Alan Viverette82f4b263a2016-12-19 15:40:05 -050044import android.annotation.IntRange;
45import android.annotation.NonNull;
Fyodor Kupolov965fa692016-10-28 18:20:25 -070046import android.annotation.Nullable;
Alan Viverette82f4b263a2016-12-19 15:40:05 -050047import android.annotation.TestApi;
Mathew Inwood1c77a112018-08-14 14:06:26 +010048import android.annotation.UnsupportedAppUsage;
Dianne Hackborn852975d2014-08-22 17:42:43 -070049import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.content.ComponentName;
51import android.content.Intent;
52import android.content.IntentFilter;
Makoto Onuki4501c61d2017-07-27 15:56:40 -070053import android.content.pm.PackageParserCacheHelper.ReadHelper;
54import android.content.pm.PackageParserCacheHelper.WriteHelper;
Garrett Boyer52136662017-05-23 13:47:58 -070055import android.content.pm.split.DefaultSplitAssetLoader;
Adam Lesinski4e862812016-11-21 16:02:24 -080056import android.content.pm.split.SplitAssetDependencyLoader;
57import android.content.pm.split.SplitAssetLoader;
Adam Lesinskibebfcc42018-02-12 14:27:46 -080058import android.content.res.ApkAssets;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.res.AssetManager;
60import android.content.res.Configuration;
61import android.content.res.Resources;
62import android.content.res.TypedArray;
63import android.content.res.XmlResourceParser;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070064import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.os.Bundle;
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -070066import android.os.FileUtils;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070067import android.os.Parcel;
68import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.os.PatternMatcher;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -070070import android.os.SystemClock;
Todd Leeea2f3be2017-03-16 14:00:52 -070071import android.os.SystemProperties;
Todd Kennedy27c24fb2015-09-17 16:49:25 -070072import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070073import android.os.UserHandle;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -060074import android.os.storage.StorageManager;
Narayan Kamath988149c2016-12-01 13:32:59 +000075import android.system.ErrnoException;
76import android.system.OsConstants;
77import android.system.StructStat;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -070078import android.text.TextUtils;
Jeff Sharkey275e0852014-06-17 18:18:49 -070079import android.util.ArrayMap;
80import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.util.AttributeSet;
Kenny Root05ca4c92011-09-15 10:36:25 -070082import android.util.Base64;
Dan Cashman1dbe6d02018-01-23 11:18:28 -080083import android.util.ByteStringUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070085import android.util.Log;
Dan Cashman1dbe6d02018-01-23 11:18:28 -080086import android.util.PackageUtils;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070087import android.util.Pair;
Kenny Rootd2d29252011-08-08 11:27:57 -070088import android.util.Slog;
Adam Lesinski1665d0f2017-03-10 14:46:57 -080089import android.util.SparseArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import android.util.TypedValue;
Dan Cashmane92f8422017-12-08 14:02:51 -080091import android.util.apk.ApkSignatureVerifier;
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -070092import android.view.Gravity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070094import com.android.internal.R;
95import com.android.internal.annotations.VisibleForTesting;
Narayan Kamathf9419f02017-06-15 11:35:38 +010096import com.android.internal.os.ClassLoaderFactory;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070097import com.android.internal.util.ArrayUtils;
98import com.android.internal.util.XmlUtils;
99
100import libcore.io.IoUtils;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -0700101import libcore.util.EmptyArray;
Svet Ganov087dce22017-09-07 15:42:16 -0700102
Jeff Sharkey9bc89af2017-01-11 11:25:50 -0700103import org.xmlpull.v1.XmlPullParser;
104import org.xmlpull.v1.XmlPullParserException;
105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import java.io.File;
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700107import java.io.FileDescriptor;
Narayan Kamath988149c2016-12-01 13:32:59 +0000108import java.io.FileOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import java.io.IOException;
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -0700110import java.io.PrintWriter;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800111import java.lang.annotation.Retention;
112import java.lang.annotation.RetentionPolicy;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000113import java.lang.reflect.Constructor;
Kenny Root05ca4c92011-09-15 10:36:25 -0700114import java.security.KeyFactory;
115import java.security.NoSuchAlgorithmException;
116import java.security.PublicKey;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800117import java.security.cert.CertificateException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700118import java.security.spec.EncodedKeySpec;
119import java.security.spec.InvalidKeySpecException;
120import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121import java.util.ArrayList;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700122import java.util.Arrays;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700123import java.util.Collections;
124import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -0700126import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800127import java.util.Set;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -0600128import java.util.UUID;
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700129import java.util.concurrent.atomic.AtomicInteger;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130
131/**
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700132 * Parser for package files (APKs) on disk. This supports apps packaged either
133 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
134 * APKs in a single directory.
135 * <p>
136 * Apps packaged as multiple APKs always consist of a single "base" APK (with a
137 * {@code null} split name) and zero or more "split" APKs (with unique split
138 * names). Any subset of those split APKs are a valid install, as long as the
139 * following constraints are met:
140 * <ul>
141 * <li>All APKs must have the exact same package name, version code, and signing
142 * certificates.
143 * <li>All APKs must have unique split names.
144 * <li>All installations must contain a single base APK.
145 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700147 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 */
149public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -0700150 private static final boolean DEBUG_JAR = false;
151 private static final boolean DEBUG_PARSER = false;
152 private static final boolean DEBUG_BACKUP = false;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -0700153 private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE;
154 private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100;
Kenny Rootd2d29252011-08-08 11:27:57 -0700155
Svet Ganova3c4eb32017-04-19 23:51:33 -0700156 private static final String PROPERTY_CHILD_PACKAGES_ENABLED =
157 "persist.sys.child_packages_enabled";
158
Jeff Sharkey3f1790d2017-04-25 18:56:17 -0600159 private static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE &&
Garrett Boyer17041532017-08-01 14:11:02 -0700160 SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false);
Svet Ganova3c4eb32017-04-19 23:51:33 -0700161
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700162 private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
163
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700164 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700165 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700166
Kenny Rootbcc954d2011-08-08 16:19:08 -0700167 /** File name in an APK for the Android manifest. */
Dan Cashmane92f8422017-12-08 14:02:51 -0800168 public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
Kenny Rootbcc954d2011-08-08 16:19:08 -0700169
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700170 /** Path prefix for apps on expanded storage */
171 private static final String MNT_EXPAND = "/mnt/expand/";
172
Svet Ganov354cd3c2015-12-17 11:35:04 -0800173 private static final String TAG_MANIFEST = "manifest";
174 private static final String TAG_APPLICATION = "application";
Adam Lesinski4e862812016-11-21 16:02:24 -0800175 private static final String TAG_PACKAGE_VERIFIER = "package-verifier";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800176 private static final String TAG_OVERLAY = "overlay";
177 private static final String TAG_KEY_SETS = "key-sets";
178 private static final String TAG_PERMISSION_GROUP = "permission-group";
179 private static final String TAG_PERMISSION = "permission";
180 private static final String TAG_PERMISSION_TREE = "permission-tree";
181 private static final String TAG_USES_PERMISSION = "uses-permission";
182 private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
183 private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
184 private static final String TAG_USES_CONFIGURATION = "uses-configuration";
185 private static final String TAG_USES_FEATURE = "uses-feature";
186 private static final String TAG_FEATURE_GROUP = "feature-group";
187 private static final String TAG_USES_SDK = "uses-sdk";
188 private static final String TAG_SUPPORT_SCREENS = "supports-screens";
189 private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
190 private static final String TAG_INSTRUMENTATION = "instrumentation";
191 private static final String TAG_ORIGINAL_PACKAGE = "original-package";
192 private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
193 private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
194 private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
195 private static final String TAG_SUPPORTS_INPUT = "supports-input";
196 private static final String TAG_EAT_COMMENT = "eat-comment";
197 private static final String TAG_PACKAGE = "package";
Todd Kennedyfdd241a2016-04-28 12:26:53 -0700198 private static final String TAG_RESTRICT_UPDATE = "restrict-update";
Adam Lesinski4e862812016-11-21 16:02:24 -0800199 private static final String TAG_USES_SPLIT = "uses-split";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800200
Bryce Lee22571db2017-07-07 15:54:18 -0700201 private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
202
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800203 /**
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700204 * Bit mask of all the valid bits that can be set in recreateOnConfigChanges.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800205 * @hide
206 */
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700207 private static final int RECREATE_ON_CONFIG_CHANGES_MASK =
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800208 ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
209
Svet Ganov354cd3c2015-12-17 11:35:04 -0800210 // These are the tags supported by child packages
211 private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
212 static {
213 CHILD_PACKAGE_TAGS.add(TAG_APPLICATION);
214 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION);
215 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M);
216 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23);
217 CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
218 CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
219 CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
220 CHILD_PACKAGE_TAGS.add(TAG_USES_SDK);
221 CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
222 CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
223 CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE);
224 CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS);
225 CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
226 CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
227 }
228
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700229 private static final boolean LOG_UNSAFE_BROADCASTS = false;
230
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700231 /**
232 * Total number of packages that were read from the cache. We use it only for logging.
233 */
234 public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger();
235
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700236 // Set of broadcast actions that are safe for manifest receivers
237 private static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
238 static {
239 SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
240 }
241
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700242 /** @hide */
Calin Juravle3fc56c32017-12-11 18:26:13 -0800243 public static final String APK_FILE_EXTENSION = ".apk";
244
245 /** @hide */
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700246 public static class NewPermissionInfo {
Mathew Inwood1c77a112018-08-14 14:06:26 +0100247 @UnsupportedAppUsage
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700248 public final String name;
Mathew Inwood1c77a112018-08-14 14:06:26 +0100249 @UnsupportedAppUsage
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700250 public final int sdkVersion;
251 public final int fileVersion;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700252
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700253 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
254 this.name = name;
255 this.sdkVersion = sdkVersion;
256 this.fileVersion = fileVersion;
257 }
258 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700259
260 /** @hide */
261 public static class SplitPermissionInfo {
262 public final String rootPerm;
263 public final String[] newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700264 public final int targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700265
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700266 public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
Dianne Hackborn79245122012-03-12 10:51:26 -0700267 this.rootPerm = rootPerm;
268 this.newPerms = newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700269 this.targetSdk = targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700270 }
271 }
272
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700273 /**
274 * List of new permissions that have been added since 1.0.
275 * NOTE: These must be declared in SDK version order, with permissions
276 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700277 * If sdkVersion is 0, then this is not a permission that we want to
278 * automatically add to older apps, but we do want to allow it to be
279 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700280 * @hide
281 */
Mathew Inwood1c77a112018-08-14 14:06:26 +0100282 @UnsupportedAppUsage
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700283 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
284 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700285 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700286 android.os.Build.VERSION_CODES.DONUT, 0),
287 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
288 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700289 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
Dianne Hackborn79245122012-03-12 10:51:26 -0700291 /**
292 * List of permissions that have been split into more granular or dependent
293 * permissions.
294 * @hide
295 */
296 public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
297 new PackageParser.SplitPermissionInfo[] {
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700298 // READ_EXTERNAL_STORAGE is always required when an app requests
299 // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
300 // write access without read access. The hack here with the target
301 // target SDK version ensures that this grant is always done.
Dianne Hackborn79245122012-03-12 10:51:26 -0700302 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700303 new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700304 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700305 new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
306 new String[] { android.Manifest.permission.READ_CALL_LOG },
307 android.os.Build.VERSION_CODES.JELLY_BEAN),
308 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
309 new String[] { android.Manifest.permission.WRITE_CALL_LOG },
310 android.os.Build.VERSION_CODES.JELLY_BEAN)
Dianne Hackborn79245122012-03-12 10:51:26 -0700311 };
312
Jeff Sharkey275e0852014-06-17 18:18:49 -0700313 /**
314 * @deprecated callers should move to explicitly passing around source path.
315 */
316 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700320 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700321 private DisplayMetrics mMetrics;
Mathew Inwood1c77a112018-08-14 14:06:26 +0100322 @UnsupportedAppUsage
Dianne Hackborncd154e92017-02-28 17:37:35 -0800323 private Callback mCallback;
Narayan Kamath988149c2016-12-01 13:32:59 +0000324 private File mCacheDir;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700325
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700326 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700327 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328
329 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
330
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700331 private static boolean sCompatibilityModeEnabled = true;
Amith Yamasani655d0e22013-06-12 14:19:10 -0700332 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
333 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Todd Kennedy11e45072017-01-25 13:24:21 -0800334 private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700335
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700336 static class ParsePackageItemArgs {
337 final Package owner;
338 final String[] outError;
339 final int nameRes;
340 final int labelRes;
341 final int iconRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700342 final int roundIconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700343 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800344 final int bannerRes;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700345
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700346 String tag;
347 TypedArray sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700348
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700349 ParsePackageItemArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700350 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
351 int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700352 owner = _owner;
353 outError = _outError;
354 nameRes = _nameRes;
355 labelRes = _labelRes;
356 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700357 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800358 bannerRes = _bannerRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700359 roundIconRes = _roundIconRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700360 }
361 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700362
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000363 /** @hide */
364 @VisibleForTesting
365 public static class ParseComponentArgs extends ParsePackageItemArgs {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700366 final String[] sepProcesses;
367 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800368 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700369 final int enabledRes;
370 int flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700371
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000372 public ParseComponentArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700373 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
374 int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800375 String[] _sepProcesses, int _processRes,
376 int _descriptionRes, int _enabledRes) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700377 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes,
378 _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700379 sepProcesses = _sepProcesses;
380 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800381 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700382 enabledRes = _enabledRes;
383 }
384 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800385
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700386 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700387 * Lightweight parsed details about a single package.
388 */
389 public static class PackageLite {
Mathew Inwood1c77a112018-08-14 14:06:26 +0100390 @UnsupportedAppUsage
Jeff Sharkey73767b92014-07-04 20:18:13 -0700391 public final String packageName;
392 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700393 public final int versionCodeMajor;
Mathew Inwood1c77a112018-08-14 14:06:26 +0100394 @UnsupportedAppUsage
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700395 public final int installLocation;
396 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700397
398 /** Names of any split APKs, ordered by parsed splitName */
399 public final String[] splitNames;
400
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800401 /** Names of any split APKs that are features. Ordered by splitName */
402 public final boolean[] isFeatureSplits;
403
Adam Lesinski4e862812016-11-21 16:02:24 -0800404 /** Dependencies of any split APKs, ordered by parsed splitName */
405 public final String[] usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800406 public final String[] configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800407
Jeff Sharkey73767b92014-07-04 20:18:13 -0700408 /**
409 * Path where this package was found on disk. For monolithic packages
410 * this is path to single base APK file; for cluster packages this is
411 * path to the cluster directory.
412 */
413 public final String codePath;
414
415 /** Path of base APK */
416 public final String baseCodePath;
417 /** Paths of any split APKs, ordered by parsed splitName */
418 public final String[] splitCodePaths;
419
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800420 /** Revision code of base APK */
421 public final int baseRevisionCode;
422 /** Revision codes of any split APKs, ordered by parsed splitName */
423 public final int[] splitRevisionCodes;
424
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700425 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100426 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100427 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800428 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700429 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800430 public final boolean isolatedSplits;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100431
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700432 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800433 boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100434 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700435 this.packageName = baseApk.packageName;
436 this.versionCode = baseApk.versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700437 this.versionCodeMajor = baseApk.versionCodeMajor;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700438 this.installLocation = baseApk.installLocation;
439 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700440 this.splitNames = splitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800441 this.isFeatureSplits = isFeatureSplits;
Adam Lesinski4e862812016-11-21 16:02:24 -0800442 this.usesSplitNames = usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800443 this.configForSplit = configForSplit;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700444 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700445 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700446 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800447 this.baseRevisionCode = baseApk.revisionCode;
448 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700449 this.coreApp = baseApk.coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100450 this.debuggable = baseApk.debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100451 this.multiArch = baseApk.multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800452 this.use32bitAbi = baseApk.use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700453 this.extractNativeLibs = baseApk.extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800454 this.isolatedSplits = baseApk.isolatedSplits;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700455 }
456
457 public List<String> getAllCodePaths() {
458 ArrayList<String> paths = new ArrayList<>();
459 paths.add(baseCodePath);
460 if (!ArrayUtils.isEmpty(splitCodePaths)) {
461 Collections.addAll(paths, splitCodePaths);
462 }
463 return paths;
464 }
465 }
466
467 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700468 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800469 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700470 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700471 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700472 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700473 public final String splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800474 public boolean isFeatureSplit;
475 public final String configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800476 public final String usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700477 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700478 public final int versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800479 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700480 public final int installLocation;
481 public final VerifierInfo[] verifiers;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800482 public final SigningDetails signingDetails;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700483 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100484 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100485 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800486 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700487 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800488 public final boolean isolatedSplits;
Kenny Root05ca4c92011-09-15 10:36:25 -0700489
Patrick Baumann47117fc2017-12-19 10:17:21 -0800490 public ApkLite(String codePath, String packageName, String splitName,
491 boolean isFeatureSplit,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700492 String configForSplit, String usesSplitName, int versionCode, int versionCodeMajor,
493 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Patrick Baumann47117fc2017-12-19 10:17:21 -0800494 SigningDetails signingDetails, boolean coreApp,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700495 boolean debuggable, boolean multiArch, boolean use32bitAbi,
496 boolean extractNativeLibs, boolean isolatedSplits) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700497 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800498 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700499 this.splitName = splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800500 this.isFeatureSplit = isFeatureSplit;
501 this.configForSplit = configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800502 this.usesSplitName = usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700503 this.versionCode = versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700504 this.versionCodeMajor = versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800505 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800506 this.installLocation = installLocation;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800507 this.signingDetails = signingDetails;
Kenny Root05ca4c92011-09-15 10:36:25 -0700508 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700509 this.coreApp = coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100510 this.debuggable = debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100511 this.multiArch = multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800512 this.use32bitAbi = use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700513 this.extractNativeLibs = extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800514 this.isolatedSplits = isolatedSplits;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800515 }
Dianne Hackborn3accca02013-09-20 09:32:11 -0700516
517 public long getLongVersionCode() {
518 return PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode);
519 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800520 }
521
Garrett Boyer52136662017-05-23 13:47:58 -0700522 /**
523 * Cached parse state for new components.
524 *
525 * Allows reuse of the same parse argument records to avoid GC pressure. Lifetime is carefully
526 * scoped to the parsing of a single application element.
527 */
528 private static class CachedComponentArgs {
529 ParseComponentArgs mActivityArgs;
530 ParseComponentArgs mActivityAliasArgs;
531 ParseComponentArgs mServiceArgs;
532 ParseComponentArgs mProviderArgs;
533 }
534
535 /**
536 * Cached state for parsing instrumentation to avoid GC pressure.
537 *
538 * Must be manually reset to null for each new manifest.
539 */
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700540 private ParsePackageItemArgs mParseInstrumentationArgs;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 /** If set to true, we will only allow package files that exactly match
543 * the DTD. Otherwise, we try to get as much from the package as we
544 * can without failing. This should normally be set to false, to
545 * support extensions to the DTD in future versions. */
546 private static final boolean RIGID_PARSER = false;
547
548 private static final String TAG = "PackageParser";
549
Mathew Inwood1c77a112018-08-14 14:06:26 +0100550 @UnsupportedAppUsage
Jeff Sharkey275e0852014-06-17 18:18:49 -0700551 public PackageParser() {
552 mMetrics = new DisplayMetrics();
553 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700554 }
555
Mathew Inwood1c77a112018-08-14 14:06:26 +0100556 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 public void setSeparateProcesses(String[] procs) {
558 mSeparateProcesses = procs;
559 }
560
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700561 /**
562 * Flag indicating this parser should only consider apps with
563 * {@code coreApp} manifest attribute to be valid apps. This is useful when
564 * creating a minimalist boot environment.
565 */
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700566 public void setOnlyCoreApps(boolean onlyCoreApps) {
567 mOnlyCoreApps = onlyCoreApps;
568 }
569
Jeff Sharkey275e0852014-06-17 18:18:49 -0700570 public void setDisplayMetrics(DisplayMetrics metrics) {
571 mMetrics = metrics;
572 }
573
Narayan Kamath988149c2016-12-01 13:32:59 +0000574 /**
575 * Sets the cache directory for this package parser.
576 */
577 public void setCacheDir(File cacheDir) {
578 mCacheDir = cacheDir;
579 }
580
Dianne Hackborncd154e92017-02-28 17:37:35 -0800581 /**
582 * Callback interface for retrieving information that may be needed while parsing
583 * a package.
584 */
585 public interface Callback {
586 boolean hasFeature(String feature);
Jaekyun Seok30dc2a02017-04-11 09:41:11 +0900587 String[] getOverlayPaths(String targetPackageName, String targetPath);
588 String[] getOverlayApks(String targetPackageName);
Dianne Hackborncd154e92017-02-28 17:37:35 -0800589 }
590
591 /**
592 * Standard implementation of {@link Callback} on top of the public {@link PackageManager}
593 * class.
594 */
595 public static final class CallbackImpl implements Callback {
596 private final PackageManager mPm;
597
598 public CallbackImpl(PackageManager pm) {
599 mPm = pm;
600 }
601
602 @Override public boolean hasFeature(String feature) {
603 return mPm.hasSystemFeature(feature);
604 }
Jaekyun Seok30dc2a02017-04-11 09:41:11 +0900605
606 @Override public String[] getOverlayPaths(String targetPackageName, String targetPath) {
607 return null;
608 }
609
610 @Override public String[] getOverlayApks(String targetPackageName) {
611 return null;
612 }
Dianne Hackborncd154e92017-02-28 17:37:35 -0800613 }
614
615 /**
616 * Set the {@link Callback} that can be used while parsing.
617 */
618 public void setCallback(Callback cb) {
619 mCallback = cb;
620 }
621
Jeff Sharkey73767b92014-07-04 20:18:13 -0700622 public static final boolean isApkFile(File file) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700623 return isApkPath(file.getName());
624 }
625
Adam Lesinski4e862812016-11-21 16:02:24 -0800626 public static boolean isApkPath(String path) {
Calin Juravle3fc56c32017-12-11 18:26:13 -0800627 return path.endsWith(APK_FILE_EXTENSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628 }
629
630 /**
631 * Generate and return the {@link PackageInfo} for a parsed package.
632 *
633 * @param p the parsed package.
634 * @param flags indicating which optional information is included.
635 */
Mathew Inwood1c77a112018-08-14 14:06:26 +0100636 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800638 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svet Ganov3695b8a2015-03-24 16:30:25 -0700639 Set<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640
Amith Yamasani483f3b02012-03-13 16:08:00 -0700641 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700642 grantedPermissions, state, UserHandle.getCallingUserId());
643 }
644
Amith Yamasani655d0e22013-06-12 14:19:10 -0700645 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700646 * Returns true if the package is installed and not hidden, or if the caller
647 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700648 * @param appInfo The applicationInfo of the app being checked.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700649 */
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700650 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
651 ApplicationInfo appInfo) {
Rhed Jaoc19da782018-06-13 11:16:16 +0800652 // Returns false if the package is hidden system app until installed.
653 if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
654 && !state.installed
655 && appInfo != null && appInfo.hiddenUntilInstalled) {
656 return false;
657 }
658
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700659 // If available for the target user, or trying to match uninstalled packages and it's
660 // a system app.
661 return state.isAvailable(flags)
662 || (appInfo != null && appInfo.isSystemApp()
Rhed Jaoc19da782018-06-13 11:16:16 +0800663 && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
664 || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
Amith Yamasani483f3b02012-03-13 16:08:00 -0700665 }
666
Christopher Tateba629da2013-11-13 17:42:28 -0800667 public static boolean isAvailable(PackageUserState state) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700668 return checkUseInstalledOrHidden(0, state, null);
Christopher Tateba629da2013-11-13 17:42:28 -0800669 }
670
Mathew Inwood1c77a112018-08-14 14:06:26 +0100671 @UnsupportedAppUsage
Amith Yamasani13593602012-03-22 16:16:17 -0700672 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700673 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800674 Set<String> grantedPermissions, PackageUserState state, int userId) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700675 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700676 return null;
677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 PackageInfo pi = new PackageInfo();
679 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700680 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 pi.versionCode = p.mVersionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700682 pi.versionCodeMajor = p.mVersionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800683 pi.baseRevisionCode = p.baseRevisionCode;
684 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685 pi.versionName = p.mVersionName;
686 pi.sharedUserId = p.mSharedUserId;
687 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700688 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800689 pi.installLocation = p.installLocation;
Todd Kennedy7c8addf2017-06-27 14:13:55 -0700690 pi.isStub = p.isStub;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700691 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700692 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
693 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
694 pi.requiredForAllUsers = p.mRequiredForAllUsers;
695 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700696 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700697 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100698 pi.overlayTarget = p.mOverlayTarget;
Adrian Roosc84df772018-01-19 21:20:22 +0100699 pi.overlayCategory = p.mOverlayCategory;
Jaekyun Seok42d53f62017-04-10 13:48:58 +0900700 pi.overlayPriority = p.mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -0800701 pi.mOverlayIsStatic = p.mOverlayIsStatic;
Alan Viveretteb6a25732017-11-21 14:49:24 -0500702 pi.compileSdkVersion = p.mCompileSdkVersion;
703 pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700704 pi.firstInstallTime = firstInstallTime;
705 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 if ((flags&PackageManager.GET_GIDS) != 0) {
707 pi.gids = gids;
708 }
709 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700710 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 if (N > 0) {
712 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700713 p.configPreferences.toArray(pi.configPreferences);
714 }
715 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
716 if (N > 0) {
717 pi.reqFeatures = new FeatureInfo[N];
718 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700720 N = p.featureGroups != null ? p.featureGroups.size() : 0;
721 if (N > 0) {
722 pi.featureGroups = new FeatureGroupInfo[N];
723 p.featureGroups.toArray(pi.featureGroups);
724 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800725 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700726 if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
727 final int N = p.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700729 int num = 0;
730 final ActivityInfo[] res = new ActivityInfo[N];
731 for (int i = 0; i < N; i++) {
732 final Activity a = p.activities.get(i);
733 if (state.isMatch(a.info, flags)) {
734 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 }
736 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700737 pi.activities = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 }
739 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700740 if ((flags & PackageManager.GET_RECEIVERS) != 0) {
741 final int N = p.receivers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800742 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700743 int num = 0;
744 final ActivityInfo[] res = new ActivityInfo[N];
745 for (int i = 0; i < N; i++) {
746 final Activity a = p.receivers.get(i);
747 if (state.isMatch(a.info, flags)) {
748 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 }
750 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700751 pi.receivers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 }
753 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700754 if ((flags & PackageManager.GET_SERVICES) != 0) {
755 final int N = p.services.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700757 int num = 0;
758 final ServiceInfo[] res = new ServiceInfo[N];
759 for (int i = 0; i < N; i++) {
760 final Service s = p.services.get(i);
761 if (state.isMatch(s.info, flags)) {
762 res[num++] = generateServiceInfo(s, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 }
764 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700765 pi.services = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 }
767 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700768 if ((flags & PackageManager.GET_PROVIDERS) != 0) {
769 final int N = p.providers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700771 int num = 0;
772 final ProviderInfo[] res = new ProviderInfo[N];
773 for (int i = 0; i < N; i++) {
774 final Provider pr = p.providers.get(i);
775 if (state.isMatch(pr.info, flags)) {
776 res[num++] = generateProviderInfo(pr, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 }
778 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700779 pi.providers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 }
781 }
782 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
783 int N = p.instrumentation.size();
784 if (N > 0) {
785 pi.instrumentation = new InstrumentationInfo[N];
786 for (int i=0; i<N; i++) {
787 pi.instrumentation[i] = generateInstrumentationInfo(
788 p.instrumentation.get(i), flags);
789 }
790 }
791 }
792 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
793 int N = p.permissions.size();
794 if (N > 0) {
795 pi.permissions = new PermissionInfo[N];
796 for (int i=0; i<N; i++) {
797 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
798 }
799 }
800 N = p.requestedPermissions.size();
801 if (N > 0) {
802 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800803 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 for (int i=0; i<N; i++) {
Dianne Hackborne639da72012-02-21 15:11:13 -0800805 final String perm = p.requestedPermissions.get(i);
806 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700807 // The notion of required permissions is deprecated but for compatibility.
Svetoslavc6d1c342015-02-26 14:44:43 -0800808 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800809 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
810 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 }
813 }
814 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800815 // deprecated method of getting signing certificates
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Daniel Cashman5cdda342018-01-19 07:22:52 -0800817 if (p.mSigningDetails.hasPastSigningCertificates()) {
818 // Package has included signing certificate rotation information. Return the oldest
819 // cert so that programmatic checks keep working even if unaware of key rotation.
820 pi.signatures = new Signature[1];
821 pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0];
822 } else if (p.mSigningDetails.hasSignatures()) {
823 // otherwise keep old behavior
Patrick Baumann47117fc2017-12-19 10:17:21 -0800824 int numberOfSigs = p.mSigningDetails.signatures.length;
825 pi.signatures = new Signature[numberOfSigs];
826 System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 }
828 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800829
830 // replacement for GET_SIGNATURES
831 if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
Dan Cashman5c9f527e2018-04-03 16:42:23 -0700832 if (p.mSigningDetails != SigningDetails.UNKNOWN) {
833 // only return a valid SigningInfo if there is signing information to report
834 pi.signingInfo = new SigningInfo(p.mSigningDetails);
835 } else {
836 pi.signingInfo = null;
Daniel Cashman5cdda342018-01-19 07:22:52 -0800837 }
838 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 return pi;
840 }
841
Todd Kennedy232d29e2017-11-06 14:45:53 -0800842 public static final int PARSE_MUST_BE_APK = 1 << 0;
843 public static final int PARSE_IGNORE_PROCESSES = 1 << 1;
Todd Kennedy30a23a52018-01-04 13:27:49 -0800844 /** @deprecated forward lock no longer functional. remove. */
845 @Deprecated
Todd Kennedy232d29e2017-11-06 14:45:53 -0800846 public static final int PARSE_FORWARD_LOCK = 1 << 2;
847 public static final int PARSE_EXTERNAL_STORAGE = 1 << 3;
848 public static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
849 public static final int PARSE_COLLECT_CERTIFICATES = 1 << 5;
850 public static final int PARSE_ENFORCE_CODE = 1 << 6;
851 public static final int PARSE_FORCE_SDK = 1 << 7;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800852 public static final int PARSE_CHATTY = 1 << 31;
853
854 @IntDef(flag = true, prefix = { "PARSE_" }, value = {
855 PARSE_CHATTY,
856 PARSE_COLLECT_CERTIFICATES,
857 PARSE_ENFORCE_CODE,
858 PARSE_EXTERNAL_STORAGE,
859 PARSE_FORCE_SDK,
860 PARSE_FORWARD_LOCK,
861 PARSE_IGNORE_PROCESSES,
Todd Kennedy232d29e2017-11-06 14:45:53 -0800862 PARSE_IS_SYSTEM_DIR,
863 PARSE_MUST_BE_APK,
864 })
865 @Retention(RetentionPolicy.SOURCE)
866 public @interface ParseFlags {}
Jeff Sharkey275e0852014-06-17 18:18:49 -0700867
868 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700870 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700871 * Used to sort a set of APKs based on their split names, always placing the
872 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700873 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700874 private static class SplitNameComparator implements Comparator<String> {
875 @Override
876 public int compare(String lhs, String rhs) {
877 if (lhs == null) {
878 return -1;
879 } else if (rhs == null) {
880 return 1;
881 } else {
882 return lhs.compareTo(rhs);
883 }
884 }
885 }
886
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700887 /**
888 * Parse only lightweight details about the package at the given location.
889 * Automatically detects if the package is a monolithic style (single APK
890 * file) or cluster style (directory of APKs).
891 * <p>
892 * This performs sanity checking on cluster style packages, such as
893 * requiring identical package name and version codes, a single base APK,
894 * and unique split names.
895 *
896 * @see PackageParser#parsePackage(File, int)
897 */
Mathew Inwood1c77a112018-08-14 14:06:26 +0100898 @UnsupportedAppUsage
Jeff Sharkey73767b92014-07-04 20:18:13 -0700899 public static PackageLite parsePackageLite(File packageFile, int flags)
900 throws PackageParserException {
901 if (packageFile.isDirectory()) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800902 return parseClusterPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700903 } else {
Adam Lesinski4e862812016-11-21 16:02:24 -0800904 return parseMonolithicPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700905 }
906 }
907
Adam Lesinski4e862812016-11-21 16:02:24 -0800908 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
909 throws PackageParserException {
Todd Kennedycd029da2016-07-21 07:41:09 -0700910 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Adam Lesinski4e862812016-11-21 16:02:24 -0800911 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700912 final String packagePath = packageFile.getAbsolutePath();
Todd Kennedycd029da2016-07-21 07:41:09 -0700913 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Narayan Kamath96c11c52017-08-09 13:07:21 +0100914 return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700915 }
916
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800917 static PackageLite parseClusterPackageLite(File packageDir, int flags)
Adam Lesinski4e862812016-11-21 16:02:24 -0800918 throws PackageParserException {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700919 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700920 if (ArrayUtils.isEmpty(files)) {
921 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
922 "No packages found in split");
923 }
924
Jeff Sharkey275e0852014-06-17 18:18:49 -0700925 String packageName = null;
926 int versionCode = 0;
927
Todd Kennedycd029da2016-07-21 07:41:09 -0700928 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700929 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700930 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700931 if (isApkFile(file)) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800932 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700933
934 // Assert that all package names and version codes are
935 // consistent with the first one we encounter.
936 if (packageName == null) {
937 packageName = lite.packageName;
938 versionCode = lite.versionCode;
939 } else {
940 if (!packageName.equals(lite.packageName)) {
941 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
942 "Inconsistent package " + lite.packageName + " in " + file
943 + "; expected " + packageName);
944 }
945 if (versionCode != lite.versionCode) {
946 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
947 "Inconsistent version " + lite.versionCode + " in " + file
948 + "; expected " + versionCode);
949 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700950 }
951
Jeff Sharkey275e0852014-06-17 18:18:49 -0700952 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700953 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700954 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
955 "Split name " + lite.splitName
956 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700957 }
958 }
959 }
Todd Kennedycd029da2016-07-21 07:41:09 -0700960 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700961
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700962 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700963 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700964 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700965 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700966 }
967
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700968 // Always apply deterministic ordering based on splitName
969 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700970
Jeff Sharkey73767b92014-07-04 20:18:13 -0700971 String[] splitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800972 boolean[] isFeatureSplits = null;
Adam Lesinski4e862812016-11-21 16:02:24 -0800973 String[] usesSplitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800974 String[] configForSplits = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700975 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800976 int[] splitRevisionCodes = null;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100977 String[] splitClassLoaderNames = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700978 if (size > 0) {
979 splitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800980 isFeatureSplits = new boolean[size];
Adam Lesinski4e862812016-11-21 16:02:24 -0800981 usesSplitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800982 configForSplits = new String[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700983 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800984 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700985
986 splitNames = apks.keySet().toArray(splitNames);
987 Arrays.sort(splitNames, sSplitNameComparator);
988
989 for (int i = 0; i < size; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800990 final ApkLite apk = apks.get(splitNames[i]);
991 usesSplitNames[i] = apk.usesSplitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800992 isFeatureSplits[i] = apk.isFeatureSplit;
993 configForSplits[i] = apk.configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800994 splitCodePaths[i] = apk.codePath;
995 splitRevisionCodes[i] = apk.revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700996 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700997 }
998
Jeff Sharkey73767b92014-07-04 20:18:13 -0700999 final String codePath = packageDir.getAbsolutePath();
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001000 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames,
Narayan Kamath96c11c52017-08-09 13:07:21 +01001001 configForSplits, splitCodePaths, splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001002 }
1003
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001004 /**
1005 * Parse the package at the given location. Automatically detects if the
1006 * package is a monolithic style (single APK file) or cluster style
1007 * (directory of APKs).
1008 * <p>
1009 * This performs sanity checking on cluster style packages, such as
1010 * requiring identical package name and version codes, a single base APK,
1011 * and unique split names.
1012 * <p>
1013 * Note that this <em>does not</em> perform signature verification; that
1014 * must be done separately in {@link #collectCertificates(Package, int)}.
1015 *
Narayan Kamath988149c2016-12-01 13:32:59 +00001016 * If {@code useCaches} is true, the package parser might return a cached
1017 * result from a previous parse of the same {@code packageFile} with the same
1018 * {@code flags}. Note that this method does not check whether {@code packageFile}
1019 * has changed since the last parse, it's up to callers to do so.
1020 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001021 * @see #parsePackageLite(File, int)
1022 */
Mathew Inwood1c77a112018-08-14 14:06:26 +01001023 @UnsupportedAppUsage
Narayan Kamath988149c2016-12-01 13:32:59 +00001024 public Package parsePackage(File packageFile, int flags, boolean useCaches)
1025 throws PackageParserException {
1026 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
1027 if (parsed != null) {
1028 return parsed;
1029 }
1030
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001031 long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Jeff Sharkey73767b92014-07-04 20:18:13 -07001032 if (packageFile.isDirectory()) {
Narayan Kamath988149c2016-12-01 13:32:59 +00001033 parsed = parseClusterPackage(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001034 } else {
Narayan Kamath988149c2016-12-01 13:32:59 +00001035 parsed = parseMonolithicPackage(packageFile, flags);
1036 }
1037
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001038 long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Narayan Kamath988149c2016-12-01 13:32:59 +00001039 cacheResult(packageFile, flags, parsed);
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001040 if (LOG_PARSE_TIMINGS) {
1041 parseTime = cacheTime - parseTime;
1042 cacheTime = SystemClock.uptimeMillis() - cacheTime;
1043 if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
1044 Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
1045 + "ms, update_cache=" + cacheTime + " ms");
1046 }
1047 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001048 return parsed;
1049 }
1050
1051 /**
1052 * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}.
1053 */
Mathew Inwood1c77a112018-08-14 14:06:26 +01001054 @UnsupportedAppUsage
Narayan Kamath988149c2016-12-01 13:32:59 +00001055 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
1056 return parsePackage(packageFile, flags, false /* useCaches */);
1057 }
1058
1059 /**
1060 * Returns the cache key for a specificied {@code packageFile} and {@code flags}.
1061 */
1062 private String getCacheKey(File packageFile, int flags) {
1063 StringBuilder sb = new StringBuilder(packageFile.getName());
1064 sb.append('-');
1065 sb.append(flags);
1066
1067 return sb.toString();
1068 }
1069
1070 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001071 protected Package fromCacheEntry(byte[] bytes) {
1072 return fromCacheEntryStatic(bytes);
1073 }
1074
1075 /** static version of {@link #fromCacheEntry} for unit tests. */
1076 @VisibleForTesting
1077 public static Package fromCacheEntryStatic(byte[] bytes) {
1078 final Parcel p = Parcel.obtain();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001079 p.unmarshall(bytes, 0, bytes.length);
1080 p.setDataPosition(0);
1081
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001082 final ReadHelper helper = new ReadHelper(p);
1083 helper.startAndInstall();
1084
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001085 PackageParser.Package pkg = new PackageParser.Package(p);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001086
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001087 p.recycle();
1088
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001089 sCachedPackageReadCount.incrementAndGet();
1090
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001091 return pkg;
Narayan Kamath988149c2016-12-01 13:32:59 +00001092 }
1093
1094 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001095 protected byte[] toCacheEntry(Package pkg) {
1096 return toCacheEntryStatic(pkg);
1097
1098 }
1099
1100 /** static version of {@link #toCacheEntry} for unit tests. */
1101 @VisibleForTesting
1102 public static byte[] toCacheEntryStatic(Package pkg) {
1103 final Parcel p = Parcel.obtain();
1104 final WriteHelper helper = new WriteHelper(p);
1105
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001106 pkg.writeToParcel(p, 0 /* flags */);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001107
1108 helper.finishAndUninstall();
1109
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001110 byte[] serialized = p.marshall();
1111 p.recycle();
1112
1113 return serialized;
Narayan Kamath988149c2016-12-01 13:32:59 +00001114 }
1115
1116 /**
1117 * Given a {@code packageFile} and a {@code cacheFile} returns whether the
1118 * cache file is up to date based on the mod-time of both files.
1119 */
1120 private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
1121 try {
1122 // NOTE: We don't use the File.lastModified API because it has the very
1123 // non-ideal failure mode of returning 0 with no excepions thrown.
1124 // The nio2 Files API is a little better but is considerably more expensive.
1125 final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
1126 final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
1127 return pkg.st_mtime < cache.st_mtime;
1128 } catch (ErrnoException ee) {
1129 // The most common reason why stat fails is that a given cache file doesn't
1130 // exist. We ignore that here. It's easy to reason that it's safe to say the
1131 // cache isn't up to date if we see any sort of exception here.
1132 //
1133 // (1) Exception while stating the package file : This should never happen,
1134 // and if it does, we do a full package parse (which is likely to throw the
1135 // same exception).
1136 // (2) Exception while stating the cache file : If the file doesn't exist, the
1137 // cache is obviously out of date. If the file *does* exist, we can't read it.
1138 // We will attempt to delete and recreate it after parsing the package.
1139 if (ee.errno != OsConstants.ENOENT) {
1140 Slog.w("Error while stating package cache : ", ee);
1141 }
1142
1143 return false;
1144 }
1145 }
1146
1147 /**
1148 * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
1149 * or {@code null} if no cached result exists.
1150 */
1151 private Package getCachedResult(File packageFile, int flags) {
1152 if (mCacheDir == null) {
1153 return null;
1154 }
1155
1156 final String cacheKey = getCacheKey(packageFile, flags);
1157 final File cacheFile = new File(mCacheDir, cacheKey);
1158
Narayan Kamath988149c2016-12-01 13:32:59 +00001159 try {
Makoto Onuki48e93162017-08-18 11:00:19 -07001160 // If the cache is not up to date, return null.
1161 if (!isCacheUpToDate(packageFile, cacheFile)) {
1162 return null;
1163 }
1164
Narayan Kamath988149c2016-12-01 13:32:59 +00001165 final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001166 Package p = fromCacheEntry(bytes);
1167 if (mCallback != null) {
1168 String[] overlayApks = mCallback.getOverlayApks(p.packageName);
1169 if (overlayApks != null && overlayApks.length > 0) {
1170 for (String overlayApk : overlayApks) {
1171 // If a static RRO is updated, return null.
1172 if (!isCacheUpToDate(new File(overlayApk), cacheFile)) {
1173 return null;
1174 }
1175 }
1176 }
1177 }
1178 return p;
Makoto Onuki48e93162017-08-18 11:00:19 -07001179 } catch (Throwable e) {
Narayan Kamath21a28382017-01-13 10:34:29 +00001180 Slog.w(TAG, "Error reading package cache: ", e);
Narayan Kamath988149c2016-12-01 13:32:59 +00001181
1182 // If something went wrong while reading the cache entry, delete the cache file
1183 // so that we regenerate it the next time.
1184 cacheFile.delete();
1185 return null;
1186 }
1187 }
1188
1189 /**
1190 * Caches the parse result for {@code packageFile} with flags {@code flags}.
1191 */
1192 private void cacheResult(File packageFile, int flags, Package parsed) {
1193 if (mCacheDir == null) {
1194 return;
1195 }
1196
Makoto Onuki48e93162017-08-18 11:00:19 -07001197 try {
1198 final String cacheKey = getCacheKey(packageFile, flags);
1199 final File cacheFile = new File(mCacheDir, cacheKey);
Narayan Kamath988149c2016-12-01 13:32:59 +00001200
Makoto Onuki48e93162017-08-18 11:00:19 -07001201 if (cacheFile.exists()) {
1202 if (!cacheFile.delete()) {
1203 Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
1204 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001205 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001206
Makoto Onuki48e93162017-08-18 11:00:19 -07001207 final byte[] cacheEntry = toCacheEntry(parsed);
Narayan Kamath988149c2016-12-01 13:32:59 +00001208
Makoto Onuki48e93162017-08-18 11:00:19 -07001209 if (cacheEntry == null) {
1210 return;
1211 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001212
Makoto Onuki48e93162017-08-18 11:00:19 -07001213 try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
1214 fos.write(cacheEntry);
1215 } catch (IOException ioe) {
1216 Slog.w(TAG, "Error writing cache entry.", ioe);
1217 cacheFile.delete();
1218 }
1219 } catch (Throwable e) {
1220 Slog.w(TAG, "Error saving package cache.", e);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001221 }
1222 }
1223
1224 /**
1225 * Parse all APKs contained in the given directory, treating them as a
1226 * single package. This also performs sanity checking, such as requiring
1227 * identical package name and version codes, a single base APK, and unique
1228 * split names.
1229 * <p>
1230 * Note that this <em>does not</em> perform signature verification; that
1231 * must be done separately in {@link #collectCertificates(Package, int)}.
1232 */
1233 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001234 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001235 if (mOnlyCoreApps && !lite.coreApp) {
1236 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1237 "Not a coreApp: " + packageDir);
1238 }
1239
Adam Lesinski4e862812016-11-21 16:02:24 -08001240 // Build the split dependency tree.
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001241 SparseArray<int[]> splitDependencies = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001242 final SplitAssetLoader assetLoader;
1243 if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001244 try {
1245 splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
1246 assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
1247 } catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
1248 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
1249 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001250 } else {
1251 assetLoader = new DefaultSplitAssetLoader(lite, flags);
1252 }
1253
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001254 try {
Adam Lesinski4e862812016-11-21 16:02:24 -08001255 final AssetManager assets = assetLoader.getBaseAssetManager();
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001256 final File baseApk = new File(lite.baseCodePath);
1257 final Package pkg = parseBaseApk(baseApk, assets, flags);
1258 if (pkg == null) {
1259 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1260 "Failed to parse base APK: " + baseApk);
1261 }
1262
1263 if (!ArrayUtils.isEmpty(lite.splitNames)) {
1264 final int num = lite.splitNames.length;
1265 pkg.splitNames = lite.splitNames;
1266 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001267 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001268 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001269 pkg.splitPrivateFlags = new int[num];
Adam Lesinski4e862812016-11-21 16:02:24 -08001270 pkg.applicationInfo.splitNames = pkg.splitNames;
1271 pkg.applicationInfo.splitDependencies = splitDependencies;
Narayan Kamath96c11c52017-08-09 13:07:21 +01001272 pkg.applicationInfo.splitClassLoaderNames = new String[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001273
1274 for (int i = 0; i < num; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -08001275 final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
1276 parseSplitApk(pkg, i, splitAssets, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001277 }
1278 }
1279
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001280 pkg.setCodePath(packageDir.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001281 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001282 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001283 } catch (IOException e) {
1284 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1285 "Failed to get path: " + lite.baseCodePath, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001286 } finally {
Adam Lesinski4e862812016-11-21 16:02:24 -08001287 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001289 }
1290
Jeff Sharkey275e0852014-06-17 18:18:49 -07001291 /**
1292 * Parse the given APK file, treating it as as a single monolithic package.
1293 * <p>
1294 * Note that this <em>does not</em> perform signature verification; that
1295 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001296 *
1297 * @deprecated external callers should move to
1298 * {@link #parsePackage(File, int)}. Eventually this method will
1299 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -07001300 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001301 @Deprecated
Mathew Inwood1c77a112018-08-14 14:06:26 +01001302 @UnsupportedAppUsage
Jeff Sharkey275e0852014-06-17 18:18:49 -07001303 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001304 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001305 if (mOnlyCoreApps) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001306 if (!lite.coreApp) {
1307 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1308 "Not a coreApp: " + apkFile);
1309 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001310 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001311
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001312 final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001313 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001314 final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001315 pkg.setCodePath(apkFile.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001316 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001317 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001318 } catch (IOException e) {
1319 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1320 "Failed to get path: " + apkFile, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001321 } finally {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001322 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001323 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001324 }
1325
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001326 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
1327 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001328 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001329
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07001330 String volumeUuid = null;
1331 if (apkPath.startsWith(MNT_EXPAND)) {
1332 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
1333 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
1334 }
1335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001337 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001338
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001339 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001341 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001343 final int cookie = assets.findCookieForPath(apkPath);
1344 if (cookie == 0) {
1345 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1346 "Failed adding asset path: " + apkPath);
1347 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001348 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001349 final Resources res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001350
1351 final String[] outError = new String[1];
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001352 final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001353 if (pkg == null) {
1354 throw new PackageParserException(mParseError,
1355 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001357
Svet Ganov354cd3c2015-12-17 11:35:04 -08001358 pkg.setVolumeUuid(volumeUuid);
1359 pkg.setApplicationVolumeUuid(volumeUuid);
1360 pkg.setBaseCodePath(apkPath);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001361 pkg.setSigningDetails(SigningDetails.UNKNOWN);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001362
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001363 return pkg;
1364
1365 } catch (PackageParserException e) {
1366 throw e;
1367 } catch (Exception e) {
1368 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001369 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001370 } finally {
1371 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 }
1374
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001375 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001376 throws PackageParserException {
1377 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -07001378
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001379 mParseError = PackageManager.INSTALL_SUCCEEDED;
1380 mArchiveSourcePath = apkPath;
1381
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001382 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
1383
Adam Lesinski4e862812016-11-21 16:02:24 -08001384 final Resources res;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001385 XmlResourceParser parser = null;
1386 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001387 // This must always succeed, as the path has been added to the AssetManager before.
1388 final int cookie = assets.findCookieForPath(apkPath);
1389 if (cookie == 0) {
1390 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1391 "Failed adding asset path: " + apkPath);
1392 }
1393
Adam Lesinski56c82be2018-02-09 11:02:04 -08001394 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001395 res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001396
1397 final String[] outError = new String[1];
1398 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
1399 if (pkg == null) {
1400 throw new PackageParserException(mParseError,
1401 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
1402 }
1403
1404 } catch (PackageParserException e) {
1405 throw e;
1406 } catch (Exception e) {
1407 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001408 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001409 } finally {
1410 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001411 }
1412 }
1413
1414 /**
1415 * Parse the manifest of a <em>split APK</em>.
1416 * <p>
1417 * Note that split APKs have many more restrictions on what they're capable
1418 * of doing, so many valid features of a base APK have been carefully
1419 * omitted here.
1420 */
1421 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001422 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
1423 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001424 AttributeSet attrs = parser;
1425
Jeff Sharkey78a13012014-07-15 20:18:34 -07001426 // We parsed manifest tag earlier; just skip past it
Svet Ganov354cd3c2015-12-17 11:35:04 -08001427 parsePackageSplitNames(parser, attrs);
Jeff Sharkey78a13012014-07-15 20:18:34 -07001428
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001429 mParseInstrumentationArgs = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001430
1431 int type;
1432
1433 boolean foundApp = false;
1434
1435 int outerDepth = parser.getDepth();
1436 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1437 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1438 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1439 continue;
1440 }
1441
1442 String tagName = parser.getName();
Adam Lesinski4e862812016-11-21 16:02:24 -08001443 if (tagName.equals(TAG_APPLICATION)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001444 if (foundApp) {
1445 if (RIGID_PARSER) {
1446 outError[0] = "<manifest> has more than one <application>";
1447 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1448 return null;
1449 } else {
1450 Slog.w(TAG, "<manifest> has more than one <application>");
1451 XmlUtils.skipCurrentTag(parser);
1452 continue;
1453 }
1454 }
1455
1456 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001457 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001458 return null;
1459 }
1460
1461 } else if (RIGID_PARSER) {
1462 outError[0] = "Bad element under <manifest>: "
1463 + parser.getName();
1464 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1465 return null;
1466
1467 } else {
1468 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1469 + " at " + mArchiveSourcePath + " "
1470 + parser.getPositionDescription());
1471 XmlUtils.skipCurrentTag(parser);
1472 continue;
1473 }
1474 }
1475
1476 if (!foundApp) {
1477 outError[0] = "<manifest> does not contain an <application>";
1478 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1479 }
1480
1481 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001482 }
1483
Patrick Baumann47117fc2017-12-19 10:17:21 -08001484 /** Parses the public keys from the set of signatures. */
1485 public static ArraySet<PublicKey> toSigningKeys(Signature[] signatures)
1486 throws CertificateException {
1487 ArraySet<PublicKey> keys = new ArraySet<>(signatures.length);
1488 for (int i = 0; i < signatures.length; i++) {
1489 keys.add(signatures[i].getPublicKey());
Todd Kennedy66c55532016-02-26 16:22:11 -08001490 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001491 return keys;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001492 }
1493
1494 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -07001495 * Collect certificates from all the APKs described in the given package,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001496 * populating {@link Package#mSigningDetails}. Also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001497 * contents are signed correctly and consistently.
1498 */
Mathew Inwood1c77a112018-08-14 14:06:26 +01001499 @UnsupportedAppUsage
Victor Hsieh5f761242018-01-20 10:30:12 -08001500 public static void collectCertificates(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001501 throws PackageParserException {
Victor Hsieh5f761242018-01-20 10:30:12 -08001502 collectCertificatesInternal(pkg, skipVerify);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001503 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1504 for (int i = 0; i < childCount; i++) {
1505 Package childPkg = pkg.childPackages.get(i);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001506 childPkg.mSigningDetails = pkg.mSigningDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001507 }
1508 }
1509
Victor Hsieh5f761242018-01-20 10:30:12 -08001510 private static void collectCertificatesInternal(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001511 throws PackageParserException {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001512 pkg.mSigningDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001513
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001514 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1515 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001516 collectCertificates(pkg, new File(pkg.baseCodePath), skipVerify);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001517
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001518 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1519 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
Victor Hsieh5f761242018-01-20 10:30:12 -08001520 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001521 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001522 }
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001523 } finally {
1524 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001525 }
1526 }
1527
Mathew Inwood1c77a112018-08-14 14:06:26 +01001528 @UnsupportedAppUsage
Victor Hsieh5f761242018-01-20 10:30:12 -08001529 private static void collectCertificates(Package pkg, File apkFile, boolean skipVerify)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001530 throws PackageParserException {
1531 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532
Patrick Baumann47117fc2017-12-19 10:17:21 -08001533 int minSignatureScheme = SigningDetails.SignatureSchemeVersion.JAR;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001534 if (pkg.applicationInfo.isStaticSharedLibrary()) {
Dan Cashmane92f8422017-12-08 14:02:51 -08001535 // must use v2 signing scheme
Patrick Baumann47117fc2017-12-19 10:17:21 -08001536 minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;
Dan Cashmane92f8422017-12-08 14:02:51 -08001537 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001538 SigningDetails verified;
Victor Hsieh5f761242018-01-20 10:30:12 -08001539 if (skipVerify) {
Dan Cashman636ea5e2017-12-18 10:38:20 -08001540 // systemDir APKs are already trusted, save time by not verifying
1541 verified = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts(
1542 apkPath, minSignatureScheme);
1543 } else {
1544 verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme);
1545 }
Dan Cashman636ea5e2017-12-18 10:38:20 -08001546
1547 // Verify that entries are signed consistently with the first pkg
1548 // we encountered. Note that for splits, certificates may have
1549 // already been populated during an earlier parse of a base APK.
Patrick Baumann47117fc2017-12-19 10:17:21 -08001550 if (pkg.mSigningDetails == SigningDetails.UNKNOWN) {
1551 pkg.mSigningDetails = verified;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001552 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001553 if (!Signature.areExactMatch(pkg.mSigningDetails.signatures, verified.signatures)) {
Patrick Baumann9ff55742017-12-14 10:50:18 -08001554 throw new PackageParserException(
1555 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
1556 apkPath + " has mismatched certificates");
1557 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 }
1560
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001561 private static AssetManager newConfiguredAssetManager() {
1562 AssetManager assetManager = new AssetManager();
Romain Guy408afbf2017-01-25 10:23:03 -08001563 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 -07001564 Build.VERSION.RESOURCES_SDK_INT);
1565 return assetManager;
1566 }
1567
Jeff Sharkey275e0852014-06-17 18:18:49 -07001568 /**
1569 * Utility method that retrieves lightweight details about a single APK
1570 * file, including package name, split name, and install location.
1571 *
1572 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001573 * @param flags optional parse flags, such as
1574 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001575 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001576 public static ApkLite parseApkLite(File apkFile, int flags)
1577 throws PackageParserException {
Dianne Hackbornca3872c2017-10-30 14:19:32 -07001578 return parseApkLiteInner(apkFile, null, null, flags);
1579 }
1580
1581 /**
1582 * Utility method that retrieves lightweight details about a single APK
1583 * file, including package name, split name, and install location.
1584 *
1585 * @param fd already open file descriptor of an apk file
1586 * @param debugPathName arbitrary text name for this file, for debug output
1587 * @param flags optional parse flags, such as
1588 * {@link #PARSE_COLLECT_CERTIFICATES}
1589 */
1590 public static ApkLite parseApkLite(FileDescriptor fd, String debugPathName, int flags)
1591 throws PackageParserException {
1592 return parseApkLiteInner(null, fd, debugPathName, flags);
1593 }
1594
1595 private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName,
1596 int flags) throws PackageParserException {
1597 final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001598
Jeff Sharkey275e0852014-06-17 18:18:49 -07001599 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001601 final ApkAssets apkAssets;
1602 try {
1603 apkAssets = fd != null
1604 ? ApkAssets.loadFromFd(fd, debugPathName, false, false)
1605 : ApkAssets.loadFromPath(apkPath);
1606 } catch (IOException e) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001607 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1608 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001609 }
1610
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001611 parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001612
Patrick Baumann47117fc2017-12-19 10:17:21 -08001613 final SigningDetails signingDetails;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001614 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1615 // TODO: factor signature related items out of Package object
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001616 final Package tempPkg = new Package((String) null);
Victor Hsieh5f761242018-01-20 10:30:12 -08001617 final boolean skipVerify = (flags & PARSE_IS_SYSTEM_DIR) != 0;
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001618 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1619 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001620 collectCertificates(tempPkg, apkFile, skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001621 } finally {
1622 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1623 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001624 signingDetails = tempPkg.mSigningDetails;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001625 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001626 signingDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001627 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001628
Jeff Sharkey275e0852014-06-17 18:18:49 -07001629 final AttributeSet attrs = parser;
Patrick Baumann47117fc2017-12-19 10:17:21 -08001630 return parseApkLite(apkPath, parser, attrs, signingDetails);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001631
1632 } catch (XmlPullParserException | IOException | RuntimeException e) {
Dianne Hackborn34041732017-01-31 15:27:13 -08001633 Slog.w(TAG, "Failed to parse " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001634 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1635 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001637 IoUtils.closeQuietly(parser);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001638 // TODO(b/72056911): Implement and call close() on ApkAssets.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 }
1641
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001642 private static String validateName(String name, boolean requireSeparator,
1643 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 final int N = name.length();
1645 boolean hasSep = false;
1646 boolean front = true;
1647 for (int i=0; i<N; i++) {
1648 final char c = name.charAt(i);
1649 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1650 front = false;
1651 continue;
1652 }
1653 if (!front) {
1654 if ((c >= '0' && c <= '9') || c == '_') {
1655 continue;
1656 }
1657 }
1658 if (c == '.') {
1659 hasSep = true;
1660 front = true;
1661 continue;
1662 }
1663 return "bad character '" + c + "'";
1664 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001665 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1666 return "Invalid filename";
1667 }
1668 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001669 ? null : "must have at least one '.' separator";
1670 }
1671
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001672 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
Svet Ganov354cd3c2015-12-17 11:35:04 -08001673 AttributeSet attrs) throws IOException, XmlPullParserException,
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001674 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675
1676 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001677 while ((type = parser.next()) != XmlPullParser.START_TAG
1678 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 }
1680
Kenny Rootd2d29252011-08-08 11:27:57 -07001681 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001682 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1683 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001685 if (!parser.getName().equals(TAG_MANIFEST)) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001686 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1687 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 }
1689
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001690 final String packageName = attrs.getAttributeValue(null, "package");
1691 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001692 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001693 if (error != null) {
1694 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1695 "Invalid manifest package: " + error);
1696 }
1697 }
1698
Jeff Sharkey275e0852014-06-17 18:18:49 -07001699 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001700 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001701 if (splitName.length() == 0) {
1702 splitName = null;
1703 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001704 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001705 if (error != null) {
1706 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1707 "Invalid manifest split: " + error);
1708 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001709 }
1710 }
1711
1712 return Pair.create(packageName.intern(),
1713 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714 }
1715
Adam Lesinski4e862812016-11-21 16:02:24 -08001716 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001717 SigningDetails signingDetails)
Adam Lesinski4e862812016-11-21 16:02:24 -08001718 throws IOException, XmlPullParserException, PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001719 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001720
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001721 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001722 int versionCode = 0;
Dianne Hackborn3accca02013-09-20 09:32:11 -07001723 int versionCodeMajor = 0;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001724 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001725 boolean coreApp = false;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001726 boolean debuggable = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001727 boolean multiArch = false;
Selim Gurun2d291d82016-02-05 17:50:53 -08001728 boolean use32bitAbi = false;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001729 boolean extractNativeLibs = true;
Adam Lesinski4e862812016-11-21 16:02:24 -08001730 boolean isolatedSplits = false;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001731 boolean isFeatureSplit = false;
1732 String configForSplit = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001733 String usesSplitName = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001734
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001735 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001736 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001737 if (attr.equals("installLocation")) {
1738 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001739 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001740 } else if (attr.equals("versionCode")) {
1741 versionCode = attrs.getAttributeIntValue(i, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001742 } else if (attr.equals("versionCodeMajor")) {
1743 versionCodeMajor = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001744 } else if (attr.equals("revisionCode")) {
1745 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001746 } else if (attr.equals("coreApp")) {
1747 coreApp = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski4e862812016-11-21 16:02:24 -08001748 } else if (attr.equals("isolatedSplits")) {
1749 isolatedSplits = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001750 } else if (attr.equals("configForSplit")) {
1751 configForSplit = attrs.getAttributeValue(i);
1752 } else if (attr.equals("isFeatureSplit")) {
1753 isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001754 }
1755 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001756
1757 // Only search the tree when the tag is directly below <manifest>
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001758 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001759 final int searchDepth = parser.getDepth() + 1;
1760
1761 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1762 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1763 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1764 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1765 continue;
1766 }
1767
Adam Lesinski4e862812016-11-21 16:02:24 -08001768 if (parser.getDepth() != searchDepth) {
1769 continue;
1770 }
1771
1772 if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
1773 final VerifierInfo verifier = parseVerifier(attrs);
Kenny Root05ca4c92011-09-15 10:36:25 -07001774 if (verifier != null) {
1775 verifiers.add(verifier);
1776 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001777 } else if (TAG_APPLICATION.equals(parser.getName())) {
Narayan Kamatha8755a82014-07-15 12:26:35 +01001778 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1779 final String attr = attrs.getAttributeName(i);
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001780 if ("debuggable".equals(attr)) {
1781 debuggable = attrs.getAttributeBooleanValue(i, false);
1782 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001783 if ("multiArch".equals(attr)) {
1784 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001785 }
Selim Gurun2d291d82016-02-05 17:50:53 -08001786 if ("use32bitAbi".equals(attr)) {
1787 use32bitAbi = attrs.getAttributeBooleanValue(i, false);
Tao Baic9a02372016-01-12 15:02:24 -08001788 }
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001789 if ("extractNativeLibs".equals(attr)) {
1790 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001791 }
1792 }
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 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001805 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001806 }
1807
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001808 return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
Dianne Hackborn3accca02013-09-20 09:32:11 -07001809 configForSplit, usesSplitName, versionCode, versionCodeMajor, revisionCode,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001810 installLocation, verifiers, signingDetails, coreApp, debuggable,
Dianne Hackborn3accca02013-09-20 09:32:11 -07001811 multiArch, use32bitAbi, extractNativeLibs, isolatedSplits);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 }
1813
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001814 /**
Svet Ganov354cd3c2015-12-17 11:35:04 -08001815 * Parses a child package and adds it to the parent if successful. If you add
1816 * new tags that need to be supported by child packages make sure to add them
1817 * to {@link #CHILD_PACKAGE_TAGS}.
1818 *
1819 * @param parentPkg The parent that contains the child
1820 * @param res Resources against which to resolve values
1821 * @param parser Parser of the manifest
1822 * @param flags Flags about how to parse
1823 * @param outError Human readable error if parsing fails
1824 * @return True of parsing succeeded.
1825 *
1826 * @throws XmlPullParserException
1827 * @throws IOException
1828 */
1829 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
1830 int flags, String[] outError) throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001831 // Make sure we have a valid child package name
1832 String childPackageName = parser.getAttributeValue(null, "package");
1833 if (validateName(childPackageName, true, false) != null) {
1834 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1835 return false;
1836 }
1837
1838 // Child packages must be unique
1839 if (childPackageName.equals(parentPkg.packageName)) {
1840 String message = "Child package name cannot be equal to parent package name: "
1841 + parentPkg.packageName;
1842 Slog.w(TAG, message);
1843 outError[0] = message;
1844 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1845 return false;
1846 }
1847
1848 // Child packages must be unique
1849 if (parentPkg.hasChildPackage(childPackageName)) {
1850 String message = "Duplicate child package:" + childPackageName;
1851 Slog.w(TAG, message);
1852 outError[0] = message;
1853 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1854 return false;
1855 }
1856
1857 // Go ahead and parse the child
1858 Package childPkg = new Package(childPackageName);
1859
1860 // Child package inherits parent version code/name/target SDK
1861 childPkg.mVersionCode = parentPkg.mVersionCode;
1862 childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
1863 childPkg.mVersionName = parentPkg.mVersionName;
1864 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
Todd Kennedy89d60182016-03-11 11:18:32 -08001865 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001866
1867 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
1868 if (childPkg == null) {
1869 // If we got null then error was set during child parsing
1870 return false;
1871 }
1872
1873 // Set the parent-child relation
1874 if (parentPkg.childPackages == null) {
1875 parentPkg.childPackages = new ArrayList<>();
1876 }
1877 parentPkg.childPackages.add(childPkg);
1878 childPkg.parentPackage = parentPkg;
1879
1880 return true;
1881 }
1882
1883 /**
1884 * Parse the manifest of a <em>base APK</em>. When adding new features you
1885 * need to consider whether they should be supported by split APKs and child
1886 * packages.
1887 *
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001888 * @param apkPath The package apk file path
Svet Ganov354cd3c2015-12-17 11:35:04 -08001889 * @param res The resources from which to resolve values
1890 * @param parser The manifest parser
1891 * @param flags Flags how to parse
1892 * @param outError Human readable error message
1893 * @return Parsed package or null on error.
1894 *
1895 * @throws XmlPullParserException
1896 * @throws IOException
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001897 */
Mathew Inwood45d2c252018-09-14 12:35:36 +01001898 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001899 private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001900 String[] outError) throws XmlPullParserException, IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001901 final String splitName;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001902 final String pkgName;
1903
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001904 try {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001905 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001906 pkgName = packageSplit.first;
1907 splitName = packageSplit.second;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001908
1909 if (!TextUtils.isEmpty(splitName)) {
1910 outError[0] = "Expected base APK, but found split " + splitName;
1911 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1912 return null;
1913 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001914 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001915 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1916 return null;
1917 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001918
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001919 if (mCallback != null) {
1920 String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
1921 if (overlayPaths != null && overlayPaths.length > 0) {
1922 for (String overlayPath : overlayPaths) {
1923 res.getAssets().addOverlayPath(overlayPath);
1924 }
1925 }
1926 }
1927
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001928 final Package pkg = new Package(pkgName);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001929
Svet Ganov354cd3c2015-12-17 11:35:04 -08001930 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001931 com.android.internal.R.styleable.AndroidManifest);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001932
Dianne Hackborn3accca02013-09-20 09:32:11 -07001933 pkg.mVersionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001935 pkg.mVersionCodeMajor = sa.getInteger(
1936 com.android.internal.R.styleable.AndroidManifest_versionCodeMajor, 0);
Patrick Baumannc2def582018-04-04 12:14:15 -07001937 pkg.applicationInfo.setVersionCode(pkg.getLongVersionCode());
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001938 pkg.baseRevisionCode = sa.getInteger(
1939 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001940 pkg.mVersionName = sa.getNonConfigurationString(
1941 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 if (pkg.mVersionName != null) {
1943 pkg.mVersionName = pkg.mVersionName.intern();
1944 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001945
1946 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
1947
Alan Viveretteb6a25732017-11-21 14:49:24 -05001948 pkg.mCompileSdkVersion = sa.getInteger(
1949 com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0);
1950 pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion;
1951 pkg.mCompileSdkVersionCodename = sa.getNonConfigurationString(
1952 com.android.internal.R.styleable.AndroidManifest_compileSdkVersionCodename, 0);
1953 if (pkg.mCompileSdkVersionCodename != null) {
1954 pkg.mCompileSdkVersionCodename = pkg.mCompileSdkVersionCodename.intern();
1955 }
1956 pkg.applicationInfo.compileSdkVersionCodename = pkg.mCompileSdkVersionCodename;
1957
Svet Ganov354cd3c2015-12-17 11:35:04 -08001958 sa.recycle();
1959
1960 return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
1961 }
1962
1963 /**
1964 * This is the common parsing routing for handling parent and child
1965 * packages in a base APK. The difference between parent and child
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001966 * parsing is that some tags are not supported by child packages as
Svet Ganov354cd3c2015-12-17 11:35:04 -08001967 * well as some manifest attributes are ignored. The implementation
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001968 * assumes the calling code has already handled the manifest tag if needed
Svet Ganov354cd3c2015-12-17 11:35:04 -08001969 * (this applies to the parent only).
1970 *
1971 * @param pkg The package which to populate
1972 * @param acceptedTags Which tags to handle, null to handle all
1973 * @param res Resources against which to resolve values
1974 * @param parser Parser of the manifest
1975 * @param flags Flags about how to parse
1976 * @param outError Human readable error if parsing fails
1977 * @return The package if parsing succeeded or null.
1978 *
1979 * @throws XmlPullParserException
1980 * @throws IOException
1981 */
1982 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
1983 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
1984 IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001985 mParseInstrumentationArgs = null;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001986
1987 int type;
1988 boolean foundApp = false;
1989
1990 TypedArray sa = res.obtainAttributes(parser,
1991 com.android.internal.R.styleable.AndroidManifest);
1992
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001993 String str = sa.getNonConfigurationString(
1994 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
1995 if (str != null && str.length() > 0) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001996 String nameError = validateName(str, true, false);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001997 if (nameError != null && !"android".equals(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001998 outError[0] = "<manifest> specifies bad sharedUserId name \""
1999 + str + "\": " + nameError;
2000 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
2001 return null;
2002 }
2003 pkg.mSharedUserId = str.intern();
2004 pkg.mSharedUserLabel = sa.getResourceId(
2005 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
2006 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08002007
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08002008 pkg.installLocation = sa.getInteger(
2009 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07002010 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002011 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07002012
Todd Kennedy11e45072017-01-25 13:24:21 -08002013 final int targetSandboxVersion = sa.getInteger(
2014 com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion,
2015 PARSE_DEFAULT_TARGET_SANDBOX);
2016 pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion;
Alan Viverettefd274a02014-03-27 15:39:15 -07002017
Kenny Root7cb9be22012-05-30 15:30:37 -07002018 /* Set the global "forward lock" flag */
2019 if ((flags & PARSE_FORWARD_LOCK) != 0) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002020 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
Kenny Root7cb9be22012-05-30 15:30:37 -07002021 }
2022
2023 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07002024 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07002025 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
2026 }
2027
Adam Lesinski4e862812016-11-21 16:02:24 -08002028 if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
2029 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
2030 }
2031
Dianne Hackborn723738c2009-06-25 19:48:04 -07002032 // Resource boolean are -1, so 1 means we don't know the value.
2033 int supportsSmallScreens = 1;
2034 int supportsNormalScreens = 1;
2035 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002036 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002037 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002038 int anyDensity = 1;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002040 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07002041 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2042 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2043 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002044 continue;
2045 }
2046
2047 String tagName = parser.getName();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002048
2049 if (acceptedTags != null && !acceptedTags.contains(tagName)) {
2050 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
2051 + tagName + " at " + mArchiveSourcePath + " "
2052 + parser.getPositionDescription());
2053 XmlUtils.skipCurrentTag(parser);
2054 continue;
2055 }
2056
2057 if (tagName.equals(TAG_APPLICATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002058 if (foundApp) {
2059 if (RIGID_PARSER) {
2060 outError[0] = "<manifest> has more than one <application>";
2061 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2062 return null;
2063 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002064 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002065 XmlUtils.skipCurrentTag(parser);
2066 continue;
2067 }
2068 }
2069
2070 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002071 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 return null;
2073 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002074 } else if (tagName.equals(TAG_OVERLAY)) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002075 sa = res.obtainAttributes(parser,
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002076 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
2077 pkg.mOverlayTarget = sa.getString(
2078 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
Adrian Roosc84df772018-01-19 21:20:22 +01002079 pkg.mOverlayCategory = sa.getString(
2080 com.android.internal.R.styleable.AndroidManifestResourceOverlay_category);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002081 pkg.mOverlayPriority = sa.getInt(
2082 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
2083 0);
Adam Lesinskie7334972018-01-17 16:13:52 -08002084 pkg.mOverlayIsStatic = sa.getBoolean(
Jaekyun Seok04342892017-03-02 15:24:19 +09002085 com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
2086 false);
Todd Leeea2f3be2017-03-16 14:00:52 -07002087 final String propName = sa.getString(
2088 com.android.internal.R.styleable
2089 .AndroidManifestResourceOverlay_requiredSystemPropertyName);
2090 final String propValue = sa.getString(
2091 com.android.internal.R.styleable
2092 .AndroidManifestResourceOverlay_requiredSystemPropertyValue);
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002093 sa.recycle();
2094
2095 if (pkg.mOverlayTarget == null) {
2096 outError[0] = "<overlay> does not specify a target package";
2097 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2098 return null;
2099 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002100
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002101 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
2102 outError[0] = "<overlay> priority must be between 0 and 9999";
2103 mParseError =
2104 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2105 return null;
2106 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002107
2108 // check to see if overlay should be excluded based on system property condition
2109 if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
2110 Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
2111 + pkg.baseCodePath+ ": overlay ignored due to required system property: "
2112 + propName + " with value: " + propValue);
2113 return null;
Jaekyun Seok04342892017-03-02 15:24:19 +09002114 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002115
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002116 XmlUtils.skipCurrentTag(parser);
2117
Svet Ganov354cd3c2015-12-17 11:35:04 -08002118 } else if (tagName.equals(TAG_KEY_SETS)) {
2119 if (!parseKeySets(pkg, res, parser, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08002120 return null;
2121 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002122 } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002123 if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002124 return null;
2125 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002126 } else if (tagName.equals(TAG_PERMISSION)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002127 if (!parsePermission(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002128 return null;
2129 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002130 } else if (tagName.equals(TAG_PERMISSION_TREE)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002131 if (!parsePermissionTree(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132 return null;
2133 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002134 } else if (tagName.equals(TAG_USES_PERMISSION)) {
2135 if (!parseUsesPermission(pkg, res, parser)) {
Svetoslav96a77162015-04-03 13:58:33 -07002136 return null;
2137 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002138 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
2139 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
2140 if (!parseUsesPermission(pkg, res, parser)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002141 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002143 } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144 ConfigurationInfo cPref = new ConfigurationInfo();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002145 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
2147 cPref.reqTouchScreen = sa.getInt(
2148 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
2149 Configuration.TOUCHSCREEN_UNDEFINED);
2150 cPref.reqKeyboardType = sa.getInt(
2151 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
2152 Configuration.KEYBOARD_UNDEFINED);
2153 if (sa.getBoolean(
2154 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
2155 false)) {
2156 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
2157 }
2158 cPref.reqNavigation = sa.getInt(
2159 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
2160 Configuration.NAVIGATION_UNDEFINED);
2161 if (sa.getBoolean(
2162 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
2163 false)) {
2164 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
2165 }
2166 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002167 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002168
2169 XmlUtils.skipCurrentTag(parser);
2170
Svet Ganov354cd3c2015-12-17 11:35:04 -08002171 } else if (tagName.equals(TAG_USES_FEATURE)) {
2172 FeatureInfo fi = parseUsesFeature(res, parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002173 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
2174
Dianne Hackborn49237342009-08-27 20:08:01 -07002175 if (fi.name == null) {
2176 ConfigurationInfo cPref = new ConfigurationInfo();
2177 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002178 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07002179 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07002180
2181 XmlUtils.skipCurrentTag(parser);
2182
Svet Ganov354cd3c2015-12-17 11:35:04 -08002183 } else if (tagName.equals(TAG_FEATURE_GROUP)) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002184 FeatureGroupInfo group = new FeatureGroupInfo();
2185 ArrayList<FeatureInfo> features = null;
2186 final int innerDepth = parser.getDepth();
2187 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2188 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2189 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2190 continue;
2191 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07002192
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002193 final String innerTagName = parser.getName();
2194 if (innerTagName.equals("uses-feature")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002195 FeatureInfo featureInfo = parseUsesFeature(res, parser);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002196 // FeatureGroups are stricter and mandate that
2197 // any <uses-feature> declared are mandatory.
2198 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
2199 features = ArrayUtils.add(features, featureInfo);
2200 } else {
2201 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
2202 " at " + mArchiveSourcePath + " " +
2203 parser.getPositionDescription());
2204 }
2205 XmlUtils.skipCurrentTag(parser);
2206 }
2207
2208 if (features != null) {
2209 group.features = new FeatureInfo[features.size()];
2210 group.features = features.toArray(group.features);
2211 }
2212 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07002213
Svet Ganov354cd3c2015-12-17 11:35:04 -08002214 } else if (tagName.equals(TAG_USES_SDK)) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07002215 if (SDK_VERSION > 0) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002216 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002217 com.android.internal.R.styleable.AndroidManifestUsesSdk);
2218
Todd Kennedy4f657082016-06-28 10:31:05 -07002219 int minVers = 1;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002220 String minCode = null;
2221 int targetVers = 0;
2222 String targetCode = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002223
Dianne Hackborn851a5412009-05-08 12:06:44 -07002224 TypedValue val = sa.peekValue(
2225 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
2226 if (val != null) {
2227 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
Colin Crossf61f9e32018-06-18 11:47:45 -07002228 minCode = val.string.toString();
Dianne Hackborn851a5412009-05-08 12:06:44 -07002229 } else {
2230 // If it's not a string, it's an integer.
Colin Crossf61f9e32018-06-18 11:47:45 -07002231 minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002232 }
2233 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002234
Dianne Hackborn851a5412009-05-08 12:06:44 -07002235 val = sa.peekValue(
2236 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
2237 if (val != null) {
2238 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
Todd Kennedy89d60182016-03-11 11:18:32 -08002239 targetCode = val.string.toString();
2240 if (minCode == null) {
2241 minCode = targetCode;
2242 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002243 } else {
2244 // If it's not a string, it's an integer.
2245 targetVers = val.data;
2246 }
Colin Crossf61f9e32018-06-18 11:47:45 -07002247 } else {
2248 targetVers = minVers;
2249 targetCode = minCode;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002250 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002252 sa.recycle();
2253
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002254 final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode,
2255 SDK_VERSION, SDK_CODENAMES, outError);
2256 if (minSdkVersion < 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002257 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2258 return null;
2259 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002260
Patrick Baumannccb20b82018-01-08 13:22:46 -08002261 boolean defaultToCurrentDevBranch = (flags & PARSE_FORCE_SDK) != 0;
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002262 final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002263 targetCode, SDK_CODENAMES, outError, defaultToCurrentDevBranch);
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002264 if (targetSdkVersion < 0) {
2265 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2266 return null;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002267 }
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002268
2269 pkg.applicationInfo.minSdkVersion = minSdkVersion;
2270 pkg.applicationInfo.targetSdkVersion = targetSdkVersion;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002271 }
2272
2273 XmlUtils.skipCurrentTag(parser);
2274
Svet Ganov354cd3c2015-12-17 11:35:04 -08002275 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
2276 sa = res.obtainAttributes(parser,
Dianne Hackborn723738c2009-06-25 19:48:04 -07002277 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
2278
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002279 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
2280 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
2281 0);
2282 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
2283 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
2284 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07002285 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
2286 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
2287 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002288
Dianne Hackborn723738c2009-06-25 19:48:04 -07002289 // This is a trick to get a boolean and still able to detect
2290 // if a value was actually set.
2291 supportsSmallScreens = sa.getInteger(
2292 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
2293 supportsSmallScreens);
2294 supportsNormalScreens = sa.getInteger(
2295 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
2296 supportsNormalScreens);
2297 supportsLargeScreens = sa.getInteger(
2298 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
2299 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002300 supportsXLargeScreens = sa.getInteger(
2301 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
2302 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002303 resizeable = sa.getInteger(
2304 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002305 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002306 anyDensity = sa.getInteger(
2307 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
2308 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07002309
2310 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002311
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002312 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002313
Svet Ganov354cd3c2015-12-17 11:35:04 -08002314 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
2315 sa = res.obtainAttributes(parser,
Dianne Hackborn854060af2009-07-09 18:14:31 -07002316 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
2317
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002318 // Note: don't allow this value to be a reference to a resource
2319 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07002320 String name = sa.getNonResourceString(
2321 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
2322
2323 sa.recycle();
2324
Todd Kennedy232d29e2017-11-06 14:45:53 -08002325 if (name != null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002326 if (pkg.protectedBroadcasts == null) {
2327 pkg.protectedBroadcasts = new ArrayList<String>();
2328 }
2329 if (!pkg.protectedBroadcasts.contains(name)) {
2330 pkg.protectedBroadcasts.add(name.intern());
2331 }
2332 }
2333
2334 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002335
Svet Ganov354cd3c2015-12-17 11:35:04 -08002336 } else if (tagName.equals(TAG_INSTRUMENTATION)) {
2337 if (parseInstrumentation(pkg, res, parser, outError) == null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002338 return null;
2339 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002340 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
2341 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002342 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2343
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002344 String orig =sa.getNonConfigurationString(
2345 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002346 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002347 if (pkg.mOriginalPackages == null) {
2348 pkg.mOriginalPackages = new ArrayList<String>();
2349 pkg.mRealPackage = pkg.packageName;
2350 }
2351 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002352 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002353
2354 sa.recycle();
2355
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002356 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002357
Svet Ganov354cd3c2015-12-17 11:35:04 -08002358 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
2359 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002360 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2361
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002362 String name = sa.getNonConfigurationString(
2363 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002364
2365 sa.recycle();
2366
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002367 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002368 if (pkg.mAdoptPermissions == null) {
2369 pkg.mAdoptPermissions = new ArrayList<String>();
2370 }
2371 pkg.mAdoptPermissions.add(name);
2372 }
2373
2374 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002375
Svet Ganov354cd3c2015-12-17 11:35:04 -08002376 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002377 // Just skip this tag
2378 XmlUtils.skipCurrentTag(parser);
2379 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002380
Svet Ganov354cd3c2015-12-17 11:35:04 -08002381 } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002382 // Just skip this tag
2383 XmlUtils.skipCurrentTag(parser);
2384 continue;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002385 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
Michael Wrighteaeb1902013-09-05 18:15:57 -07002386 XmlUtils.skipCurrentTag(parser);
2387 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002388
Svet Ganov354cd3c2015-12-17 11:35:04 -08002389 } else if (tagName.equals(TAG_EAT_COMMENT)) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002390 // Just skip this tag
2391 XmlUtils.skipCurrentTag(parser);
2392 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002393
Svet Ganov354cd3c2015-12-17 11:35:04 -08002394 } else if (tagName.equals(TAG_PACKAGE)) {
Svet Ganova7532cf2016-05-02 08:13:17 -07002395 if (!MULTI_PACKAGE_APK_ENABLED) {
2396 XmlUtils.skipCurrentTag(parser);
2397 continue;
2398 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002399 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
2400 // If parsing a child failed the error is already set
2401 return null;
2402 }
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002403
2404 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
2405 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
2406 sa = res.obtainAttributes(parser,
2407 com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
2408 final String hash = sa.getNonConfigurationString(
2409 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
2410 sa.recycle();
2411
2412 pkg.restrictUpdateHash = null;
2413 if (hash != null) {
2414 final int hashLength = hash.length();
2415 final byte[] hashBytes = new byte[hashLength / 2];
2416 for (int i = 0; i < hashLength; i += 2){
2417 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
2418 + Character.digit(hash.charAt(i + 1), 16));
2419 }
2420 pkg.restrictUpdateHash = hashBytes;
2421 }
2422 }
2423
2424 XmlUtils.skipCurrentTag(parser);
2425
Dianne Hackborn854060af2009-07-09 18:14:31 -07002426 } else if (RIGID_PARSER) {
2427 outError[0] = "Bad element under <manifest>: "
2428 + parser.getName();
2429 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2430 return null;
2431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002432 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002433 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002434 + " at " + mArchiveSourcePath + " "
2435 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 XmlUtils.skipCurrentTag(parser);
2437 continue;
2438 }
2439 }
2440
2441 if (!foundApp && pkg.instrumentation.size() == 0) {
2442 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
2443 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
2444 }
2445
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002446 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002447 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002448 for (int ip=0; ip<NP; ip++) {
2449 final PackageParser.NewPermissionInfo npi
2450 = PackageParser.NEW_PERMISSIONS[ip];
2451 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
2452 break;
2453 }
2454 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002455 if (implicitPerms == null) {
2456 implicitPerms = new StringBuilder(128);
2457 implicitPerms.append(pkg.packageName);
2458 implicitPerms.append(": compat added ");
2459 } else {
2460 implicitPerms.append(' ');
2461 }
2462 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002463 pkg.requestedPermissions.add(npi.name);
2464 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002465 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002466 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002467 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002468 }
Dianne Hackborn79245122012-03-12 10:51:26 -07002469
2470 final int NS = PackageParser.SPLIT_PERMISSIONS.length;
2471 for (int is=0; is<NS; is++) {
2472 final PackageParser.SplitPermissionInfo spi
2473 = PackageParser.SPLIT_PERMISSIONS[is];
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -07002474 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
2475 || !pkg.requestedPermissions.contains(spi.rootPerm)) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07002476 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07002477 }
2478 for (int in=0; in<spi.newPerms.length; in++) {
2479 final String perm = spi.newPerms[in];
2480 if (!pkg.requestedPermissions.contains(perm)) {
2481 pkg.requestedPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07002482 }
2483 }
2484 }
2485
Dianne Hackborn723738c2009-06-25 19:48:04 -07002486 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
2487 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002488 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002489 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
2490 }
2491 if (supportsNormalScreens != 0) {
2492 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
2493 }
2494 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
2495 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002496 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002497 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
2498 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002499 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
2500 && pkg.applicationInfo.targetSdkVersion
2501 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
2502 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
2503 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002504 if (resizeable < 0 || (resizeable > 0
2505 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002506 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002507 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
2508 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002509 if (anyDensity < 0 || (anyDensity > 0
2510 && pkg.applicationInfo.targetSdkVersion
2511 >= android.os.Build.VERSION_CODES.DONUT)) {
2512 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07002513 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07002514
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002515 // At this point we can check if an application is not supporting densities and hence
2516 // cannot be windowed / resized. Note that an SDK version of 0 is common for
2517 // pre-Doughnut applications.
2518 if (pkg.applicationInfo.usesCompatibilityMode()) {
Winson Chungd3395382016-12-13 11:49:09 -08002519 adjustPackageToBeUnresizeableAndUnpipable(pkg);
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002521 return pkg;
2522 }
2523
Todd Leeea2f3be2017-03-16 14:00:52 -07002524 private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
2525
2526 if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
2527 if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
2528 // malformed condition - incomplete
2529 Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
2530 + "=" + propValue + "' - require both requiredSystemPropertyName"
2531 + " AND requiredSystemPropertyValue to be specified.");
2532 return false;
2533 }
2534 // no valid condition set - so no exclusion criteria, overlay will be included.
2535 return true;
2536 }
2537
2538 // check property value - make sure it is both set and equal to expected value
2539 final String currValue = SystemProperties.get(propName);
2540 return (currValue != null && currValue.equals(propValue));
2541 }
2542
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002543 /**
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002544 * This is a pre-density application which will get scaled - instead of being pixel perfect.
2545 * This type of application is not resizable.
2546 *
2547 * @param pkg The package which needs to be marked as unresizable.
2548 */
Winson Chungd3395382016-12-13 11:49:09 -08002549 private void adjustPackageToBeUnresizeableAndUnpipable(Package pkg) {
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002550 for (Activity a : pkg.activities) {
2551 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -08002552 a.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE;
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002553 }
2554 }
2555
2556 /**
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002557 * Computes the targetSdkVersion to use at runtime. If the package is not
2558 * compatible with this platform, populates {@code outError[0]} with an
2559 * error message.
2560 * <p>
2561 * If {@code targetCode} is not specified, e.g. the value is {@code null},
2562 * then the {@code targetVers} will be returned unmodified.
2563 * <p>
2564 * Otherwise, the behavior varies based on whether the current platform
2565 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2566 * has length > 0:
2567 * <ul>
2568 * <li>If this is a pre-release platform and the value specified by
2569 * {@code targetCode} is contained within the array of allowed pre-release
2570 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2571 * <li>If this is a released platform, this method will return -1 to
2572 * indicate that the package is not compatible with this platform.
2573 * </ul>
2574 *
2575 * @param targetVers targetSdkVersion number, if specified in the
2576 * application manifest, or 0 otherwise
2577 * @param targetCode targetSdkVersion code, if specified in the application
2578 * manifest, or {@code null} otherwise
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002579 * @param platformSdkCodenames array of allowed pre-release SDK codenames
2580 * for this platform
2581 * @param outError output array to populate with error, if applicable
Patrick Baumannccb20b82018-01-08 13:22:46 -08002582 * @param forceCurrentDev if development target code is not available, use the current
2583 * development version by default.
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002584 * @return the targetSdkVersion to use at runtime, or -1 if the package is
2585 * not compatible with this platform
2586 * @hide Exposed for unit testing only.
2587 */
2588 @TestApi
2589 public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002590 @Nullable String targetCode, @NonNull String[] platformSdkCodenames,
2591 @NonNull String[] outError, boolean forceCurrentDev) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002592 // If it's a release SDK, return the version number unmodified.
2593 if (targetCode == null) {
2594 return targetVers;
2595 }
2596
2597 // If it's a pre-release SDK and the codename matches this platform, it
2598 // definitely targets this SDK.
Patrick Baumannccb20b82018-01-08 13:22:46 -08002599 if (ArrayUtils.contains(platformSdkCodenames, targetCode) || forceCurrentDev) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002600 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2601 }
2602
2603 // Otherwise, we're looking at an incompatible pre-release SDK.
2604 if (platformSdkCodenames.length > 0) {
2605 outError[0] = "Requires development platform " + targetCode
2606 + " (current platform is any of "
2607 + Arrays.toString(platformSdkCodenames) + ")";
2608 } else {
2609 outError[0] = "Requires development platform " + targetCode
2610 + " but this is a release platform.";
2611 }
2612 return -1;
2613 }
2614
2615 /**
2616 * Computes the minSdkVersion to use at runtime. If the package is not
2617 * compatible with this platform, populates {@code outError[0]} with an
2618 * error message.
2619 * <p>
2620 * If {@code minCode} is not specified, e.g. the value is {@code null},
2621 * then behavior varies based on the {@code platformSdkVersion}:
2622 * <ul>
2623 * <li>If the platform SDK version is greater than or equal to the
2624 * {@code minVers}, returns the {@code mniVers} unmodified.
2625 * <li>Otherwise, returns -1 to indicate that the package is not
2626 * compatible with this platform.
2627 * </ul>
2628 * <p>
2629 * Otherwise, the behavior varies based on whether the current platform
2630 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2631 * has length > 0:
2632 * <ul>
2633 * <li>If this is a pre-release platform and the value specified by
2634 * {@code targetCode} is contained within the array of allowed pre-release
2635 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2636 * <li>If this is a released platform, this method will return -1 to
2637 * indicate that the package is not compatible with this platform.
2638 * </ul>
2639 *
2640 * @param minVers minSdkVersion number, if specified in the application
2641 * manifest, or 1 otherwise
2642 * @param minCode minSdkVersion code, if specified in the application
2643 * manifest, or {@code null} otherwise
2644 * @param platformSdkVersion platform SDK version number, typically
2645 * Build.VERSION.SDK_INT
2646 * @param platformSdkCodenames array of allowed prerelease SDK codenames
2647 * for this platform
2648 * @param outError output array to populate with error, if applicable
2649 * @return the minSdkVersion to use at runtime, or -1 if the package is not
2650 * compatible with this platform
2651 * @hide Exposed for unit testing only.
2652 */
2653 @TestApi
2654 public static int computeMinSdkVersion(@IntRange(from = 1) int minVers,
2655 @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion,
2656 @NonNull String[] platformSdkCodenames, @NonNull String[] outError) {
2657 // If it's a release SDK, make sure we meet the minimum SDK requirement.
2658 if (minCode == null) {
2659 if (minVers <= platformSdkVersion) {
2660 return minVers;
2661 }
2662
2663 // We don't meet the minimum SDK requirement.
2664 outError[0] = "Requires newer sdk version #" + minVers
2665 + " (current version is #" + platformSdkVersion + ")";
2666 return -1;
2667 }
2668
2669 // If it's a pre-release SDK and the codename matches this platform, we
2670 // definitely meet the minimum SDK requirement.
2671 if (ArrayUtils.contains(platformSdkCodenames, minCode)) {
2672 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2673 }
2674
2675 // Otherwise, we're looking at an incompatible pre-release SDK.
2676 if (platformSdkCodenames.length > 0) {
2677 outError[0] = "Requires development platform " + minCode
2678 + " (current platform is any of "
2679 + Arrays.toString(platformSdkCodenames) + ")";
2680 } else {
2681 outError[0] = "Requires development platform " + minCode
2682 + " but this is a release platform.";
2683 }
2684 return -1;
2685 }
2686
Todd Kennedy27c24fb2015-09-17 16:49:25 -07002687 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002688 FeatureInfo fi = new FeatureInfo();
2689 TypedArray sa = res.obtainAttributes(attrs,
2690 com.android.internal.R.styleable.AndroidManifestUsesFeature);
2691 // Note: don't allow this value to be a reference to a resource
2692 // that may change.
2693 fi.name = sa.getNonResourceString(
2694 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
Jeff Sharkey115d2c12016-02-15 17:25:57 -07002695 fi.version = sa.getInt(
2696 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002697 if (fi.name == null) {
2698 fi.reqGlEsVersion = sa.getInt(
2699 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
2700 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2701 }
2702 if (sa.getBoolean(
2703 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
2704 fi.flags |= FeatureInfo.FLAG_REQUIRED;
2705 }
2706 sa.recycle();
2707 return fi;
2708 }
2709
Svet Ganov67882122016-12-11 16:36:34 -08002710 private boolean parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser,
2711 String[] outError) throws XmlPullParserException, IOException {
2712 TypedArray sa = res.obtainAttributes(parser,
2713 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary);
2714
2715 // Note: don't allow this value to be a reference to a resource that may change.
2716 String lname = sa.getNonResourceString(
2717 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
2718 final int version = sa.getInt(
2719 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002720 String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable
Svet Ganov67882122016-12-11 16:36:34 -08002721 .AndroidManifestUsesStaticLibrary_certDigest);
2722 sa.recycle();
2723
2724 // Since an APK providing a static shared lib can only provide the lib - fail if malformed
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002725 if (lname == null || version < 0 || certSha256Digest == null) {
Svet Ganov67882122016-12-11 16:36:34 -08002726 outError[0] = "Bad uses-static-library declaration name: " + lname + " version: "
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002727 + version + " certDigest" + certSha256Digest;
Svet Ganov67882122016-12-11 16:36:34 -08002728 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2729 XmlUtils.skipCurrentTag(parser);
2730 return false;
2731 }
2732
2733 // Can depend only on one version of the same library
2734 if (pkg.usesStaticLibraries != null && pkg.usesStaticLibraries.contains(lname)) {
2735 outError[0] = "Depending on multiple versions of static library " + lname;
2736 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2737 XmlUtils.skipCurrentTag(parser);
2738 return false;
2739 }
2740
2741 lname = lname.intern();
2742 // We allow ":" delimiters in the SHA declaration as this is the format
2743 // emitted by the certtool making it easy for developers to copy/paste.
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002744 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2745
2746 // Fot apps targeting O-MR1 we require explicit enumeration of all certs.
2747 String[] additionalCertSha256Digests = EmptyArray.STRING;
Jeff Sharkeyaa1a9112018-04-10 15:18:12 -06002748 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O_MR1) {
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002749 additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError);
2750 if (additionalCertSha256Digests == null) {
2751 return false;
2752 }
2753 } else {
2754 XmlUtils.skipCurrentTag(parser);
2755 }
2756
2757 final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1];
2758 certSha256Digests[0] = certSha256Digest;
2759 System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
2760 1, additionalCertSha256Digests.length);
2761
Svet Ganov67882122016-12-11 16:36:34 -08002762 pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname);
Dianne Hackborn3accca02013-09-20 09:32:11 -07002763 pkg.usesStaticLibrariesVersions = ArrayUtils.appendLong(
Svet Ganov8a10ef52017-02-16 20:58:09 -08002764 pkg.usesStaticLibrariesVersions, version, true);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002765 pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
2766 pkg.usesStaticLibrariesCertDigests, certSha256Digests, true);
Svet Ganov67882122016-12-11 16:36:34 -08002767
2768 return true;
2769 }
2770
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002771 private String[] parseAdditionalCertificates(Resources resources, XmlResourceParser parser,
2772 String[] outError) throws XmlPullParserException, IOException {
2773 String[] certSha256Digests = EmptyArray.STRING;
2774
2775 int outerDepth = parser.getDepth();
2776 int type;
2777 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2778 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2779 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2780 continue;
2781 }
2782
2783 final String nodeName = parser.getName();
2784 if (nodeName.equals("additional-certificate")) {
2785 final TypedArray sa = resources.obtainAttributes(parser, com.android.internal.
2786 R.styleable.AndroidManifestAdditionalCertificate);
2787 String certSha256Digest = sa.getNonResourceString(com.android.internal.
2788 R.styleable.AndroidManifestAdditionalCertificate_certDigest);
2789 sa.recycle();
2790
2791 if (TextUtils.isEmpty(certSha256Digest)) {
2792 outError[0] = "Bad additional-certificate declaration with empty"
2793 + " certDigest:" + certSha256Digest;
2794 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2795 XmlUtils.skipCurrentTag(parser);
2796 sa.recycle();
2797 return null;
2798 }
2799
2800 // We allow ":" delimiters in the SHA declaration as this is the format
2801 // emitted by the certtool making it easy for developers to copy/paste.
2802 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2803 certSha256Digests = ArrayUtils.appendElement(String.class,
2804 certSha256Digests, certSha256Digest);
2805 } else {
2806 XmlUtils.skipCurrentTag(parser);
2807 }
2808 }
2809
2810 return certSha256Digests;
2811 }
2812
Svet Ganov354cd3c2015-12-17 11:35:04 -08002813 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
2814 throws XmlPullParserException, IOException {
2815 TypedArray sa = res.obtainAttributes(parser,
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002816 com.android.internal.R.styleable.AndroidManifestUsesPermission);
2817
2818 // Note: don't allow this value to be a reference to a resource
2819 // that may change.
2820 String name = sa.getNonResourceString(
2821 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002822
Christopher Tatefb0676a2013-09-16 16:34:52 -07002823 int maxSdkVersion = 0;
2824 TypedValue val = sa.peekValue(
2825 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
2826 if (val != null) {
2827 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
2828 maxSdkVersion = val.data;
2829 }
2830 }
2831
Dianne Hackborncd154e92017-02-28 17:37:35 -08002832 final String requiredFeature = sa.getNonConfigurationString(
2833 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
2834
2835 final String requiredNotfeature = sa.getNonConfigurationString(
2836 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
2837
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002838 sa.recycle();
2839
Dianne Hackborncd154e92017-02-28 17:37:35 -08002840 XmlUtils.skipCurrentTag(parser);
2841
2842 if (name == null) {
2843 return true;
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002844 }
2845
Dianne Hackborncd154e92017-02-28 17:37:35 -08002846 if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
2847 return true;
2848 }
2849
2850 // Only allow requesting this permission if the platform supports the given feature.
2851 if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
2852 return true;
2853 }
2854
2855 // Only allow requesting this permission if the platform doesn't support the given feature.
2856 if (requiredNotfeature != null && mCallback != null
2857 && mCallback.hasFeature(requiredNotfeature)) {
2858 return true;
2859 }
2860
2861 int index = pkg.requestedPermissions.indexOf(name);
2862 if (index == -1) {
2863 pkg.requestedPermissions.add(name.intern());
2864 } else {
2865 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
2866 + name + " in package: " + pkg.packageName + " at: "
2867 + parser.getPositionDescription());
2868 }
2869
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002870 return true;
2871 }
2872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002873 private static String buildClassName(String pkg, CharSequence clsSeq,
2874 String[] outError) {
2875 if (clsSeq == null || clsSeq.length() <= 0) {
2876 outError[0] = "Empty class name in package " + pkg;
2877 return null;
2878 }
2879 String cls = clsSeq.toString();
2880 char c = cls.charAt(0);
2881 if (c == '.') {
Narayan Kamath07ac1442017-02-10 15:08:07 +00002882 return pkg + cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002883 }
2884 if (cls.indexOf('.') < 0) {
2885 StringBuilder b = new StringBuilder(pkg);
2886 b.append('.');
2887 b.append(cls);
Narayan Kamath07ac1442017-02-10 15:08:07 +00002888 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002889 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002890 return cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002891 }
2892
2893 private static String buildCompoundName(String pkg,
2894 CharSequence procSeq, String type, String[] outError) {
2895 String proc = procSeq.toString();
2896 char c = proc.charAt(0);
2897 if (pkg != null && c == ':') {
2898 if (proc.length() < 2) {
2899 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
2900 + ": must be at least two characters";
2901 return null;
2902 }
2903 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002904 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905 if (nameError != null) {
2906 outError[0] = "Invalid " + type + " name " + proc + " in package "
2907 + pkg + ": " + nameError;
2908 return null;
2909 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002910 return pkg + proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002911 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002912 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002913 if (nameError != null && !"system".equals(proc)) {
2914 outError[0] = "Invalid " + type + " name " + proc + " in package "
2915 + pkg + ": " + nameError;
2916 return null;
2917 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002918 return proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002919 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002920
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002921 private static String buildProcessName(String pkg, String defProc,
2922 CharSequence procSeq, int flags, String[] separateProcesses,
2923 String[] outError) {
2924 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
2925 return defProc != null ? defProc : pkg;
2926 }
2927 if (separateProcesses != null) {
2928 for (int i=separateProcesses.length-1; i>=0; i--) {
2929 String sp = separateProcesses[i];
2930 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
2931 return pkg;
2932 }
2933 }
2934 }
2935 if (procSeq == null || procSeq.length() <= 0) {
2936 return defProc;
2937 }
Makoto Onuki812d188a2017-08-07 09:58:23 -07002938 return TextUtils.safeIntern(buildCompoundName(pkg, procSeq, "process", outError));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002939 }
2940
2941 private static String buildTaskAffinityName(String pkg, String defProc,
2942 CharSequence procSeq, String[] outError) {
2943 if (procSeq == null) {
2944 return defProc;
2945 }
2946 if (procSeq.length() <= 0) {
2947 return null;
2948 }
2949 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
2950 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002951
dcashman989eb3712014-06-17 12:56:12 -07002952 private boolean parseKeySets(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002953 XmlResourceParser parser, String[] outError)
Geremy Condraf1bcca82013-01-07 22:35:24 -08002954 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07002955 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08002956 // all the keys and keysets that we want must be defined here
2957 // so we're going to iterate over the parser and pull out the things we want
2958 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07002959 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002960 int type;
dcashman989eb3712014-06-17 12:56:12 -07002961 String currentKeySet = null;
2962 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
2963 ArraySet<String> upgradeKeySets = new ArraySet<String>();
2964 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
2965 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08002966 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2967 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2968 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07002969 if (parser.getDepth() == currentKeySetDepth) {
2970 currentKeySet = null;
2971 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07002972 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002973 continue;
2974 }
dcashman989eb3712014-06-17 12:56:12 -07002975 String tagName = parser.getName();
2976 if (tagName.equals("key-set")) {
2977 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07002978 outError[0] = "Improperly nested 'key-set' tag at "
2979 + parser.getPositionDescription();
2980 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002981 return false;
2982 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002983 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002984 com.android.internal.R.styleable.AndroidManifestKeySet);
2985 final String keysetName = sa.getNonResourceString(
2986 com.android.internal.R.styleable.AndroidManifestKeySet_name);
2987 definedKeySets.put(keysetName, new ArraySet<String>());
2988 currentKeySet = keysetName;
2989 currentKeySetDepth = parser.getDepth();
2990 sa.recycle();
2991 } else if (tagName.equals("public-key")) {
2992 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002993 outError[0] = "Improperly nested 'key-set' tag at "
2994 + parser.getPositionDescription();
2995 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002996 return false;
2997 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002998 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002999 com.android.internal.R.styleable.AndroidManifestPublicKey);
3000 final String publicKeyName = sa.getNonResourceString(
3001 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003002 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07003003 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
3004 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07003005 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
3006 + " on first use at " + parser.getPositionDescription();
3007 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07003008 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003009 return false;
3010 } else if (encodedKey != null) {
3011 PublicKey currentKey = parsePublicKey(encodedKey);
3012 if (currentKey == null) {
3013 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
3014 + parser.getPositionDescription() + " key-set " + currentKeySet
3015 + " will not be added to the package's defined key-sets.");
3016 sa.recycle();
3017 improperKeySets.add(currentKeySet);
3018 XmlUtils.skipCurrentTag(parser);
3019 continue;
3020 }
3021 if (publicKeys.get(publicKeyName) == null
3022 || publicKeys.get(publicKeyName).equals(currentKey)) {
3023
3024 /* public-key first definition, or matches old definition */
3025 publicKeys.put(publicKeyName, currentKey);
3026 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003027 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07003028 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07003029 + parser.getPositionDescription();
3030 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003031 sa.recycle();
3032 return false;
3033 }
Kenny Root37dca152013-07-10 14:01:49 -07003034 }
dcashman989eb3712014-06-17 12:56:12 -07003035 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003036 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003037 XmlUtils.skipCurrentTag(parser);
3038 } else if (tagName.equals("upgrade-key-set")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003039 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003040 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
3041 String name = sa.getNonResourceString(
3042 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
3043 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003044 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003045 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003046 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07003047 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003048 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07003049 + parser.getPositionDescription();
3050 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003051 return false;
3052 } else {
dcashman989eb3712014-06-17 12:56:12 -07003053 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003054 + " at " + mArchiveSourcePath + " "
3055 + parser.getPositionDescription());
3056 XmlUtils.skipCurrentTag(parser);
3057 continue;
3058 }
3059 }
dcashman989eb3712014-06-17 12:56:12 -07003060 Set<String> publicKeyNames = publicKeys.keySet();
3061 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07003062 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
3063 + "'key-set' and 'public-key' names must be distinct.";
3064 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003065 return false;
3066 }
3067 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
3068 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
3069 final String keySetName = e.getKey();
3070 if (e.getValue().size() == 0) {
3071 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3072 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
3073 + " Not including in package's defined key-sets.");
3074 continue;
3075 } else if (improperKeySets.contains(keySetName)) {
3076 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3077 + "'key-set' " + keySetName + " contained improper 'public-key'"
3078 + " tags. Not including in package's defined key-sets.");
3079 continue;
3080 }
3081 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
3082 for (String s : e.getValue()) {
3083 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08003084 }
3085 }
dcashman989eb3712014-06-17 12:56:12 -07003086 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
3087 owner.mUpgradeKeySets = upgradeKeySets;
3088 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003089 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
3090 + "does not define all 'upgrade-key-set's .";
3091 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003092 return false;
3093 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003094 return true;
3095 }
3096
Dianne Hackborncd154e92017-02-28 17:37:35 -08003097 private boolean parsePermissionGroup(Package owner, int flags, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003098 XmlResourceParser parser, String[] outError)
3099 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100 PermissionGroup perm = new PermissionGroup(owner);
3101
Svet Ganov354cd3c2015-12-17 11:35:04 -08003102 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003103 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003104 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003105 "<permission-group>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003106 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
3107 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003108 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003109 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003110 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
3111 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003112 sa.recycle();
3113 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003114 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003115 }
3116
3117 perm.info.descriptionRes = sa.getResourceId(
3118 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
3119 0);
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003120 perm.info.requestRes = sa.getResourceId(
3121 com.android.internal.R.styleable.AndroidManifestPermissionGroup_request, 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07003122 perm.info.flags = sa.getInt(
3123 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07003124 perm.info.priority = sa.getInt(
3125 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003126
3127 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003128
Svet Ganov354cd3c2015-12-17 11:35:04 -08003129 if (!parseAllMetaData(res, parser, "<permission-group>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003130 outError)) {
3131 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003132 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003133 }
3134
3135 owner.permissionGroups.add(perm);
3136
Dianne Hackborncd154e92017-02-28 17:37:35 -08003137 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003138 }
3139
Dianne Hackborncd154e92017-02-28 17:37:35 -08003140 private boolean parsePermission(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003141 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003142 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003143
Svet Ganov354cd3c2015-12-17 11:35:04 -08003144 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 com.android.internal.R.styleable.AndroidManifestPermission);
3146
Dianne Hackborncd154e92017-02-28 17:37:35 -08003147 Permission perm = new Permission(owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003148 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003149 "<permission>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003150 com.android.internal.R.styleable.AndroidManifestPermission_name,
3151 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003152 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003153 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003154 com.android.internal.R.styleable.AndroidManifestPermission_logo,
3155 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003156 sa.recycle();
3157 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003158 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003159 }
3160
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003161 // Note: don't allow this value to be a reference to a resource
3162 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003163 perm.info.group = sa.getNonResourceString(
3164 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
3165 if (perm.info.group != null) {
3166 perm.info.group = perm.info.group.intern();
3167 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003169 perm.info.descriptionRes = sa.getResourceId(
3170 com.android.internal.R.styleable.AndroidManifestPermission_description,
3171 0);
3172
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003173 perm.info.requestRes = sa.getResourceId(
3174 com.android.internal.R.styleable.AndroidManifestPermission_request, 0);
3175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003176 perm.info.protectionLevel = sa.getInt(
3177 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
3178 PermissionInfo.PROTECTION_NORMAL);
3179
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07003180 perm.info.flags = sa.getInt(
3181 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
3182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003183 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08003184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003185 if (perm.info.protectionLevel == -1) {
3186 outError[0] = "<permission> does not specify protectionLevel";
3187 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003188 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003189 }
Dianne Hackborne639da72012-02-21 15:11:13 -08003190
3191 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
3192
Makoto Onuki700feef2018-02-15 10:59:41 -08003193 if (perm.info.getProtectionFlags() != 0) {
Todd Kennedyc247fa12017-06-02 10:29:22 -07003194 if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_INSTANT) == 0
Chad Brubakera5d70a12017-03-23 11:04:50 -07003195 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0
Chad Brubakerc19706a2016-10-13 15:44:59 -07003196 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
Dianne Hackborne639da72012-02-21 15:11:13 -08003197 PermissionInfo.PROTECTION_SIGNATURE) {
Joe Maples39bb9e82018-01-11 11:09:46 -05003198 outError[0] = "<permission> protectionLevel specifies a non-instant flag but is "
Dianne Hackborne639da72012-02-21 15:11:13 -08003199 + "not based on signature type";
3200 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003201 return false;
Dianne Hackborne639da72012-02-21 15:11:13 -08003202 }
3203 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003204
Svet Ganov354cd3c2015-12-17 11:35:04 -08003205 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003206 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003207 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003208 }
3209
3210 owner.permissions.add(perm);
3211
Dianne Hackborncd154e92017-02-28 17:37:35 -08003212 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003213 }
3214
Dianne Hackborncd154e92017-02-28 17:37:35 -08003215 private boolean parsePermissionTree(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003216 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003217 throws XmlPullParserException, IOException {
3218 Permission perm = new Permission(owner);
3219
Svet Ganov354cd3c2015-12-17 11:35:04 -08003220 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003221 com.android.internal.R.styleable.AndroidManifestPermissionTree);
3222
3223 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003224 "<permission-tree>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003225 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
3226 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003227 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003228 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003229 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
3230 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003231 sa.recycle();
3232 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003233 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003234 }
3235
3236 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003238 int index = perm.info.name.indexOf('.');
3239 if (index > 0) {
3240 index = perm.info.name.indexOf('.', index+1);
3241 }
3242 if (index < 0) {
3243 outError[0] = "<permission-tree> name has less than three segments: "
3244 + perm.info.name;
3245 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003246 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003247 }
3248
3249 perm.info.descriptionRes = 0;
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003250 perm.info.requestRes = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
3252 perm.tree = true;
3253
Svet Ganov354cd3c2015-12-17 11:35:04 -08003254 if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 outError)) {
3256 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003257 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 }
3259
3260 owner.permissions.add(perm);
3261
Dianne Hackborncd154e92017-02-28 17:37:35 -08003262 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003263 }
3264
3265 private Instrumentation parseInstrumentation(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003266 XmlResourceParser parser, String[] outError)
3267 throws XmlPullParserException, IOException {
3268 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003269 com.android.internal.R.styleable.AndroidManifestInstrumentation);
3270
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003271 if (mParseInstrumentationArgs == null) {
3272 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
3273 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
3274 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003275 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003276 com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003277 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
3278 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003279 mParseInstrumentationArgs.tag = "<instrumentation>";
3280 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003281
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003282 mParseInstrumentationArgs.sa = sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003283
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003284 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
3285 new InstrumentationInfo());
3286 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003287 sa.recycle();
3288 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3289 return null;
3290 }
3291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003292 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003293 // Note: don't allow this value to be a reference to a resource
3294 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003295 str = sa.getNonResourceString(
3296 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
3297 a.info.targetPackage = str != null ? str.intern() : null;
3298
Dianne Hackborn34041732017-01-31 15:27:13 -08003299 str = sa.getNonResourceString(
Dianne Hackborn1be53542017-04-28 13:36:00 -07003300 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcesses);
3301 a.info.targetProcesses = str != null ? str.intern() : null;
Dianne Hackborn34041732017-01-31 15:27:13 -08003302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003303 a.info.handleProfiling = sa.getBoolean(
3304 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
3305 false);
3306
3307 a.info.functionalTest = sa.getBoolean(
3308 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
3309 false);
3310
3311 sa.recycle();
3312
3313 if (a.info.targetPackage == null) {
3314 outError[0] = "<instrumentation> does not specify targetPackage";
3315 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3316 return null;
3317 }
3318
Svet Ganov354cd3c2015-12-17 11:35:04 -08003319 if (!parseAllMetaData(res, parser, "<instrumentation>", a,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003320 outError)) {
3321 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3322 return null;
3323 }
3324
3325 owner.instrumentation.add(a);
3326
3327 return a;
3328 }
3329
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003330 /**
3331 * Parse the {@code application} XML tree at the current parse location in a
3332 * <em>base APK</em> manifest.
3333 * <p>
3334 * When adding new features, carefully consider if they should also be
3335 * supported by split APKs.
3336 */
Mathew Inwood1c77a112018-08-14 14:06:26 +01003337 @UnsupportedAppUsage
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003338 private boolean parseBaseApplication(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003339 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 throws XmlPullParserException, IOException {
3341 final ApplicationInfo ai = owner.applicationInfo;
3342 final String pkgName = owner.applicationInfo.packageName;
3343
Svet Ganov354cd3c2015-12-17 11:35:04 -08003344 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003345 com.android.internal.R.styleable.AndroidManifestApplication);
3346
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003347 if (!parsePackageItemInfo(owner, ai, outError,
3348 "<application>", sa, false /*nameRequired*/,
3349 com.android.internal.R.styleable.AndroidManifestApplication_name,
3350 com.android.internal.R.styleable.AndroidManifestApplication_label,
3351 com.android.internal.R.styleable.AndroidManifestApplication_icon,
3352 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
3353 com.android.internal.R.styleable.AndroidManifestApplication_logo,
3354 com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
3355 sa.recycle();
3356 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3357 return false;
3358 }
3359
3360 if (ai.name != null) {
Todd Kennedyafb52692016-08-22 15:44:00 -07003361 ai.className = ai.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 }
3363
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003364 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003365 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
3366 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367 if (manageSpaceActivity != null) {
3368 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
3369 outError);
3370 }
3371
Christopher Tate181fafa2009-05-14 11:12:14 -07003372 boolean allowBackup = sa.getBoolean(
3373 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
3374 if (allowBackup) {
3375 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07003376
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003377 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
3378 // and restoreAnyVersion are only relevant if backup is possible for the
3379 // given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003380 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003381 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
3382 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07003383 if (backupAgent != null) {
3384 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07003385 if (DEBUG_BACKUP) {
3386 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003387 + " from " + pkgName + "+" + backupAgent);
3388 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003389
3390 if (sa.getBoolean(
3391 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
3392 true)) {
3393 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
3394 }
3395 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08003396 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
3397 false)) {
3398 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
3399 }
Christopher Tated1de2562014-06-17 17:12:35 -07003400 if (sa.getBoolean(
3401 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
3402 false)) {
3403 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
3404 }
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003405 if (sa.getBoolean(
3406 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
3407 false)) {
3408 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
3409 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003410 }
Matthew Williams303650c2015-04-17 18:22:51 -07003411
3412 TypedValue v = sa.peekValue(
3413 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
3414 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
3415 if (DEBUG_BACKUP) {
3416 Slog.v(TAG, "fullBackupContent specified as boolean=" +
3417 (v.data == 0 ? "false" : "true"));
3418 }
3419 // "false" => -1, "true" => 0
3420 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
3421 }
3422 if (DEBUG_BACKUP) {
3423 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
3424 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003425 }
Christopher Tate4a627c72011-04-01 14:43:32 -07003426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08003428 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003429 ai.descriptionRes = sa.getResourceId(
3430 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
3431
Todd Kennedy232d29e2017-11-06 14:45:53 -08003432 if (sa.getBoolean(
3433 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
3434 false)) {
3435 // Check if persistence is based on a feature being present
3436 final String requiredFeature = sa.getNonResourceString(com.android.internal.R.styleable
3437 .AndroidManifestApplication_persistentWhenFeatureAvailable);
3438 if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
3439 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07003441 }
3442
3443 if (sa.getBoolean(
3444 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
3445 false)) {
3446 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07003447 }
3448
3449 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
3450 .AndroidManifestApplication_restrictedAccountType);
3451 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
3452 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003453 }
3454
Amith Yamasaniccbe3892013-04-12 17:52:42 -07003455 String requiredAccountType = sa.getString(com.android.internal.R.styleable
3456 .AndroidManifestApplication_requiredAccountType);
3457 if (requiredAccountType != null && requiredAccountType.length() > 0) {
3458 owner.mRequiredAccountType = requiredAccountType;
3459 }
3460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003461 if (sa.getBoolean(
3462 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
3463 false)) {
3464 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
3465 }
3466
3467 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07003468 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08003469 false)) {
3470 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
3471 }
3472
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003473 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07003474 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07003475 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07003476 if (owner.baseHardwareAccelerated) {
3477 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
3478 }
Romain Guy812ccbe2010-06-01 14:07:24 -07003479
3480 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003481 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
3482 true)) {
3483 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
3484 }
3485
3486 if (sa.getBoolean(
3487 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
3488 false)) {
3489 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
3490 }
3491
3492 if (sa.getBoolean(
3493 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
3494 true)) {
3495 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
3496 }
3497
Svet Ganov354cd3c2015-12-17 11:35:04 -08003498 // The parent package controls installation, hence specify test only installs.
3499 if (owner.parentPackage == null) {
3500 if (sa.getBoolean(
3501 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
3502 false)) {
3503 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
3504 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003505 }
3506
Jason parksa3cdaa52011-01-13 14:15:43 -06003507 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003508 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06003509 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003510 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06003511 }
3512
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003513 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07003514 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
Chad Brubaker0d285d52018-03-14 09:00:04 -07003515 owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.P)) {
Alex Klyubin01a959d2015-03-18 10:05:45 -07003516 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
3517 }
3518
3519 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003520 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
3521 false /* default is no RTL support*/)) {
3522 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
3523 }
3524
Narayan Kamath589a1bc2014-07-03 14:43:26 +01003525 if (sa.getBoolean(
3526 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
3527 false)) {
3528 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
3529 }
3530
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07003531 if (sa.getBoolean(
3532 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
3533 true)) {
3534 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
3535 }
3536
Todd Kennedyd022ac22016-04-13 10:49:29 -07003537 if (sa.getBoolean(
3538 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
3539 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003540 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003541 }
Todd Kennedyd022ac22016-04-13 10:49:29 -07003542 if (sa.getBoolean(
3543 R.styleable.AndroidManifestApplication_directBootAware,
3544 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003545 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003546 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003547
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003548 if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
3549 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003550 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
3551 } else {
3552 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003553 }
3554 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003555 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwale6afdf912016-01-30 13:01:33 -08003556 }
3557
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07003558 ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
3559
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003560 ai.networkSecurityConfigRes = sa.getResourceId(
3561 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
3562 0);
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07003563 ai.category = sa.getInt(
3564 com.android.internal.R.styleable.AndroidManifestApplication_appCategory,
3565 ApplicationInfo.CATEGORY_UNDEFINED);
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003567 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003568 str = sa.getNonConfigurationString(
3569 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003570 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
3571
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003572 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3573 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003574 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
3575 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003576 } else {
3577 // Some older apps have been seen to use a resource reference
3578 // here that on older builds was ignored (with a warning). We
3579 // need to continue to do this for them so they don't break.
3580 str = sa.getNonResourceString(
3581 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
3582 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
3584 str, outError);
Jason Monka80bfb52017-11-16 17:15:37 -05003585 String factory = sa.getNonResourceString(
3586 com.android.internal.R.styleable.AndroidManifestApplication_appComponentFactory);
3587 if (factory != null) {
3588 ai.appComponentFactory = buildClassName(ai.packageName, factory, outError);
3589 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590
David Brazdilfa5e8362018-09-06 09:49:14 +01003591 if (sa.getBoolean(
3592 com.android.internal.R.styleable.AndroidManifestApplication_usesNonSdkApi, false)) {
3593 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API;
3594 }
David Brazdilca6f81d2018-08-28 12:55:56 +01003595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003596 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003597 CharSequence pname;
3598 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3599 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003600 com.android.internal.R.styleable.AndroidManifestApplication_process,
3601 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003602 } else {
3603 // Some older apps have been seen to use a resource reference
3604 // here that on older builds was ignored (with a warning). We
3605 // need to continue to do this for them so they don't break.
3606 pname = sa.getNonResourceString(
3607 com.android.internal.R.styleable.AndroidManifestApplication_process);
3608 }
3609 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610 flags, mSeparateProcesses, outError);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003611
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003612 ai.enabled = sa.getBoolean(
3613 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003614
Jose Lima12d0b4c2014-03-14 16:55:12 -07003615 if (sa.getBoolean(
3616 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
3617 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
3618 }
3619
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003620 if (sa.getBoolean(
3621 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
3622 false)) {
3623 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07003624
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003625 // A heavy-weight application can not be in a custom process.
3626 // We can do direct compare because we intern all strings.
3627 if (ai.processName != null && !ai.processName.equals(ai.packageName)) {
3628 outError[0] = "cantSaveState applications can not use custom processes";
Dianne Hackborn860755f2010-06-03 18:47:52 -07003629 }
3630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003631 }
3632
Adam Powell269248d2011-08-02 10:26:54 -07003633 ai.uiOptions = sa.getInt(
3634 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
3635
Narayan Kamath96c11c52017-08-09 13:07:21 +01003636 ai.classLoaderName = sa.getString(
3637 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3638 if (ai.classLoaderName != null
3639 && !ClassLoaderFactory.isValidClassLoaderName(ai.classLoaderName)) {
3640 outError[0] = "Invalid class loader name: " + ai.classLoaderName;
3641 }
3642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003643 sa.recycle();
3644
3645 if (outError[0] != null) {
3646 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3647 return false;
3648 }
3649
3650 final int innerDepth = parser.getDepth();
Garrett Boyer52136662017-05-23 13:47:58 -07003651 // IMPORTANT: These must only be cached for a single <application> to avoid components
3652 // getting added to the wrong package.
3653 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003654 int type;
Todd Kennedy6d418b62018-02-22 14:15:18 -08003655 boolean hasActivityOrder = false;
3656 boolean hasReceiverOrder = false;
3657 boolean hasServiceOrder = false;
Kenny Rootd2d29252011-08-08 11:27:57 -07003658 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3659 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3660 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 continue;
3662 }
3663
3664 String tagName = parser.getName();
3665 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003666 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003667 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003668 if (a == null) {
3669 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3670 return false;
3671 }
3672
Todd Kennedy6d418b62018-02-22 14:15:18 -08003673 hasActivityOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003674 owner.activities.add(a);
3675
3676 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003677 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3678 true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003679 if (a == null) {
3680 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3681 return false;
3682 }
3683
Todd Kennedy6d418b62018-02-22 14:15:18 -08003684 hasReceiverOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685 owner.receivers.add(a);
3686
3687 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003688 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003689 if (s == null) {
3690 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3691 return false;
3692 }
3693
Todd Kennedy6d418b62018-02-22 14:15:18 -08003694 hasServiceOrder |= (s.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003695 owner.services.add(s);
3696
3697 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003698 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003699 if (p == null) {
3700 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3701 return false;
3702 }
3703
3704 owner.providers.add(p);
3705
3706 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003707 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003708 if (a == null) {
3709 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3710 return false;
3711 }
3712
Todd Kennedy6d418b62018-02-22 14:15:18 -08003713 hasActivityOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003714 owner.activities.add(a);
3715
3716 } else if (parser.getName().equals("meta-data")) {
3717 // note: application meta-data is stored off to the side, so it can
3718 // remain null in the primary copy (we like to avoid extra copies because
3719 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003720 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003721 outError)) == null) {
3722 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3723 return false;
3724 }
Svet Ganov67882122016-12-11 16:36:34 -08003725 } else if (tagName.equals("static-library")) {
3726 sa = res.obtainAttributes(parser,
3727 com.android.internal.R.styleable.AndroidManifestStaticLibrary);
3728
3729 // Note: don't allow this value to be a reference to a resource
3730 // that may change.
3731 final String lname = sa.getNonResourceString(
3732 com.android.internal.R.styleable.AndroidManifestStaticLibrary_name);
3733 final int version = sa.getInt(
3734 com.android.internal.R.styleable.AndroidManifestStaticLibrary_version, -1);
Dianne Hackborn3accca02013-09-20 09:32:11 -07003735 final int versionMajor = sa.getInt(
3736 com.android.internal.R.styleable.AndroidManifestStaticLibrary_versionMajor,
3737 0);
Svet Ganov67882122016-12-11 16:36:34 -08003738
3739 sa.recycle();
3740
3741 // Since the app canot run without a static lib - fail if malformed
3742 if (lname == null || version < 0) {
3743 outError[0] = "Bad static-library declaration name: " + lname
3744 + " version: " + version;
3745 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3746 XmlUtils.skipCurrentTag(parser);
3747 return false;
3748 }
3749
3750 if (owner.mSharedUserId != null) {
3751 outError[0] = "sharedUserId not allowed in static shared library";
3752 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
3753 XmlUtils.skipCurrentTag(parser);
3754 return false;
3755 }
3756
3757 if (owner.staticSharedLibName != null) {
3758 outError[0] = "Multiple static-shared libs for package " + pkgName;
3759 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3760 XmlUtils.skipCurrentTag(parser);
3761 return false;
3762 }
3763
3764 owner.staticSharedLibName = lname.intern();
Dianne Hackborn3accca02013-09-20 09:32:11 -07003765 if (version >= 0) {
3766 owner.staticSharedLibVersion =
3767 PackageInfo.composeLongVersionCode(versionMajor, version);
3768 } else {
3769 owner.staticSharedLibVersion = version;
3770 }
Svet Ganov67882122016-12-11 16:36:34 -08003771 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
3772
3773 XmlUtils.skipCurrentTag(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003774
Dianne Hackbornc895be72013-03-11 17:48:43 -07003775 } else if (tagName.equals("library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003776 sa = res.obtainAttributes(parser,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003777 com.android.internal.R.styleable.AndroidManifestLibrary);
3778
3779 // Note: don't allow this value to be a reference to a resource
3780 // that may change.
3781 String lname = sa.getNonResourceString(
3782 com.android.internal.R.styleable.AndroidManifestLibrary_name);
3783
3784 sa.recycle();
3785
3786 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003787 lname = lname.intern();
3788 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
Svet Ganov67882122016-12-11 16:36:34 -08003789 owner.libraryNames = ArrayUtils.add(
3790 owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07003791 }
3792 }
3793
3794 XmlUtils.skipCurrentTag(parser);
3795
Svet Ganov67882122016-12-11 16:36:34 -08003796 } else if (tagName.equals("uses-static-library")) {
3797 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3798 return false;
3799 }
3800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003801 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003802 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003803 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3804
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003805 // Note: don't allow this value to be a reference to a resource
3806 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 String lname = sa.getNonResourceString(
3808 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07003809 boolean req = sa.getBoolean(
3810 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3811 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003812
3813 sa.recycle();
3814
Dianne Hackborn49237342009-08-27 20:08:01 -07003815 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003816 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07003817 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003818 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003819 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003820 owner.usesOptionalLibraries = ArrayUtils.add(
3821 owner.usesOptionalLibraries, lname);
3822 }
3823 }
3824
3825 XmlUtils.skipCurrentTag(parser);
3826
3827 } else if (tagName.equals("uses-package")) {
3828 // Dependencies for app installers; we don't currently try to
3829 // enforce this.
3830 XmlUtils.skipCurrentTag(parser);
3831
3832 } else {
3833 if (!RIGID_PARSER) {
3834 Slog.w(TAG, "Unknown element under <application>: " + tagName
3835 + " at " + mArchiveSourcePath + " "
3836 + parser.getPositionDescription());
3837 XmlUtils.skipCurrentTag(parser);
3838 continue;
3839 } else {
3840 outError[0] = "Bad element under <application>: " + tagName;
3841 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3842 return false;
3843 }
3844 }
3845 }
3846
Todd Kennedy6d418b62018-02-22 14:15:18 -08003847 if (hasActivityOrder) {
3848 Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order));
3849 }
3850 if (hasReceiverOrder) {
3851 Collections.sort(owner.receivers, (r1, r2) -> Integer.compare(r2.order, r1.order));
3852 }
3853 if (hasServiceOrder) {
3854 Collections.sort(owner.services, (s1, s2) -> Integer.compare(s2.order, s1.order));
3855 }
Bryce Lee22571db2017-07-07 15:54:18 -07003856 // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
3857 // every activity info has had a chance to set it from its attributes.
3858 setMaxAspectRatio(owner);
3859
Paul Duffin855d7022017-07-10 15:16:07 +01003860 PackageBackwardCompatibility.modifySharedLibraries(owner);
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003861
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003862 if (hasDomainURLs(owner)) {
3863 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3864 } else {
3865 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3866 }
3867
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003868 return true;
3869 }
3870
3871 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003872 * 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 -07003873 */
3874 private static boolean hasDomainURLs(Package pkg) {
3875 if (pkg == null || pkg.activities == null) return false;
3876 final ArrayList<Activity> activities = pkg.activities;
3877 final int countActivities = activities.size();
3878 for (int n=0; n<countActivities; n++) {
3879 Activity activity = activities.get(n);
3880 ArrayList<ActivityIntentInfo> filters = activity.intents;
3881 if (filters == null) continue;
3882 final int countFilters = filters.size();
3883 for (int m=0; m<countFilters; m++) {
3884 ActivityIntentInfo aii = filters.get(m);
3885 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003886 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003887 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
3888 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
3889 return true;
3890 }
3891 }
3892 }
3893 return false;
3894 }
3895
3896 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003897 * Parse the {@code application} XML tree at the current parse location in a
3898 * <em>split APK</em> manifest.
3899 * <p>
3900 * Note that split APKs have many more restrictions on what they're capable
3901 * of doing, so many valid features of a base APK have been carefully
3902 * omitted here.
3903 */
Svet Ganov354cd3c2015-12-17 11:35:04 -08003904 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
3905 int flags, int splitIndex, String[] outError)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003906 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003907 TypedArray sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003908 com.android.internal.R.styleable.AndroidManifestApplication);
3909
3910 if (sa.getBoolean(
3911 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
3912 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
3913 }
3914
Narayan Kamath96c11c52017-08-09 13:07:21 +01003915 final String classLoaderName = sa.getString(
3916 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3917 if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
3918 owner.applicationInfo.splitClassLoaderNames[splitIndex] = classLoaderName;
3919 } else {
3920 outError[0] = "Invalid class loader name: " + classLoaderName;
3921 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3922 return false;
3923 }
3924
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003925 final int innerDepth = parser.getDepth();
3926 int type;
3927 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3928 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3929 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3930 continue;
3931 }
3932
Adam Lesinski4e862812016-11-21 16:02:24 -08003933 ComponentInfo parsedComponent = null;
3934
Garrett Boyer52136662017-05-23 13:47:58 -07003935 // IMPORTANT: These must only be cached for a single <application> to avoid components
3936 // getting added to the wrong package.
3937 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003938 String tagName = parser.getName();
3939 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003940 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003941 owner.baseHardwareAccelerated);
3942 if (a == null) {
3943 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3944 return false;
3945 }
3946
3947 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003948 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003949
3950 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003951 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3952 true, false);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003953 if (a == null) {
3954 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3955 return false;
3956 }
3957
3958 owner.receivers.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003959 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003960
3961 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003962 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003963 if (s == null) {
3964 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3965 return false;
3966 }
3967
3968 owner.services.add(s);
Adam Lesinski4e862812016-11-21 16:02:24 -08003969 parsedComponent = s.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003970
3971 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003972 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003973 if (p == null) {
3974 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3975 return false;
3976 }
3977
3978 owner.providers.add(p);
Adam Lesinski4e862812016-11-21 16:02:24 -08003979 parsedComponent = p.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003980
3981 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003982 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003983 if (a == null) {
3984 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3985 return false;
3986 }
3987
3988 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003989 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003990
3991 } else if (parser.getName().equals("meta-data")) {
3992 // note: application meta-data is stored off to the side, so it can
3993 // remain null in the primary copy (we like to avoid extra copies because
3994 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003995 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003996 outError)) == null) {
3997 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3998 return false;
3999 }
4000
Svet Ganov67882122016-12-11 16:36:34 -08004001 } else if (tagName.equals("uses-static-library")) {
4002 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
4003 return false;
4004 }
4005
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004006 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004007 sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004008 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
4009
4010 // Note: don't allow this value to be a reference to a resource
4011 // that may change.
4012 String lname = sa.getNonResourceString(
4013 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
4014 boolean req = sa.getBoolean(
4015 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
4016 true);
4017
4018 sa.recycle();
4019
4020 if (lname != null) {
4021 lname = lname.intern();
4022 if (req) {
4023 // Upgrade to treat as stronger constraint
4024 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
4025 owner.usesOptionalLibraries = ArrayUtils.remove(
4026 owner.usesOptionalLibraries, lname);
4027 } else {
4028 // Ignore if someone already defined as required
4029 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
4030 owner.usesOptionalLibraries = ArrayUtils.add(
4031 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07004032 }
4033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004034 }
4035
4036 XmlUtils.skipCurrentTag(parser);
4037
Dianne Hackborncef65ee2010-09-30 18:27:22 -07004038 } else if (tagName.equals("uses-package")) {
4039 // Dependencies for app installers; we don't currently try to
4040 // enforce this.
4041 XmlUtils.skipCurrentTag(parser);
4042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004043 } else {
4044 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004045 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004046 + " at " + mArchiveSourcePath + " "
4047 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004048 XmlUtils.skipCurrentTag(parser);
4049 continue;
4050 } else {
4051 outError[0] = "Bad element under <application>: " + tagName;
4052 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4053 return false;
4054 }
4055 }
Adam Lesinski4e862812016-11-21 16:02:24 -08004056
4057 if (parsedComponent != null && parsedComponent.splitName == null) {
4058 // If the loaded component did not specify a split, inherit the split name
4059 // based on the split it is defined in.
4060 // This is used to later load the correct split when starting this
4061 // component.
4062 parsedComponent.splitName = owner.splitNames[splitIndex];
4063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004064 }
4065
4066 return true;
4067 }
4068
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004069 private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
4070 String[] outError, String tag, TypedArray sa, boolean nameRequired,
4071 int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00004072 // This case can only happen in unit tests where we sometimes need to create fakes
4073 // of various package parser data structures.
4074 if (sa == null) {
4075 outError[0] = tag + " does not contain any attributes";
4076 return false;
4077 }
4078
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004079 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004080 if (name == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004081 if (nameRequired) {
4082 outError[0] = tag + " does not specify android:name";
4083 return false;
4084 }
4085 } else {
4086 outInfo.name
4087 = buildClassName(owner.applicationInfo.packageName, name, outError);
4088 if (outInfo.name == null) {
4089 return false;
4090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004091 }
4092
Todd Kennedya83bfca2016-06-03 07:52:17 -07004093 final boolean useRoundIcon =
4094 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
4095 int roundIconVal = useRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004096 if (roundIconVal != 0) {
4097 outInfo.icon = roundIconVal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004098 outInfo.nonLocalizedLabel = null;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004099 } else {
4100 int iconVal = sa.getResourceId(iconRes, 0);
4101 if (iconVal != 0) {
4102 outInfo.icon = iconVal;
4103 outInfo.nonLocalizedLabel = null;
4104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004105 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004106
Adam Powell81cd2e92010-04-21 16:35:18 -07004107 int logoVal = sa.getResourceId(logoRes, 0);
4108 if (logoVal != 0) {
4109 outInfo.logo = logoVal;
4110 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004111
Jose Limaf78e3122014-03-06 12:13:15 -08004112 int bannerVal = sa.getResourceId(bannerRes, 0);
4113 if (bannerVal != 0) {
4114 outInfo.banner = bannerVal;
4115 }
4116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004117 TypedValue v = sa.peekValue(labelRes);
4118 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4119 outInfo.nonLocalizedLabel = v.coerceToString();
4120 }
4121
4122 outInfo.packageName = owner.packageName;
4123
4124 return true;
4125 }
4126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004127 private Activity parseActivity(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004128 XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
Romain Guy529b60a2010-08-03 18:05:47 -07004129 boolean receiver, boolean hardwareAccelerated)
4130 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004131 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132
Garrett Boyer52136662017-05-23 13:47:58 -07004133 if (cachedArgs.mActivityArgs == null) {
4134 cachedArgs.mActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004135 R.styleable.AndroidManifestActivity_name,
4136 R.styleable.AndroidManifestActivity_label,
4137 R.styleable.AndroidManifestActivity_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004138 R.styleable.AndroidManifestActivity_roundIcon,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004139 R.styleable.AndroidManifestActivity_logo,
4140 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004141 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004142 R.styleable.AndroidManifestActivity_process,
4143 R.styleable.AndroidManifestActivity_description,
4144 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004145 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004146
Garrett Boyer52136662017-05-23 13:47:58 -07004147 cachedArgs.mActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
4148 cachedArgs.mActivityArgs.sa = sa;
4149 cachedArgs.mActivityArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004150
Garrett Boyer52136662017-05-23 13:47:58 -07004151 Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004152 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004153 sa.recycle();
4154 return null;
4155 }
4156
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004157 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004159 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004160 }
4161
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004162 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004163
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004164 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07004165 a.info.applicationInfo.uiOptions);
4166
Adam Powelldd8fab22012-03-22 17:47:27 -07004167 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004168 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004169 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004170 if (parentName != null) {
4171 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4172 if (outError[0] == null) {
4173 a.info.parentActivityName = parentClassName;
4174 } else {
4175 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
4176 parentName);
4177 outError[0] = null;
4178 }
4179 }
4180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004181 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004182 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004183 if (str == null) {
4184 a.info.permission = owner.applicationInfo.permission;
4185 } else {
4186 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4187 }
4188
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004189 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004190 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004191 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004192 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
4193 owner.applicationInfo.taskAffinity, str, outError);
4194
Todd Kennedye9d0d272017-01-23 06:49:29 -08004195 a.info.splitName =
4196 sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0);
4197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004198 a.info.flags = 0;
4199 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004200 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004201 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
4202 }
4203
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004204 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004205 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
4206 }
4207
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004208 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004209 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
4210 }
4211
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004212 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004213 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
4214 }
4215
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004216 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004217 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
4218 }
4219
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004220 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004221 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
4222 }
4223
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004224 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
4226 }
4227
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004228 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004229 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
4230 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
4231 }
4232
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004233 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07004234 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
4235 }
4236
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07004237 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
4238 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
4239 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07004240 }
4241
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004242 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04004243 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
4244 }
Craig Mautner5962b122012-10-05 14:45:52 -07004245
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07004246 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
4247 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08004248 }
4249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004250 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004251 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07004252 hardwareAccelerated)) {
4253 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
4254 }
4255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004256 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004257 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07004258 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004259 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07004260 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07004261 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004262 R.styleable.AndroidManifestActivity_maxRecents,
Dianne Hackborn852975d2014-08-22 17:42:43 -07004263 ActivityManager.getDefaultAppRecentsLimitStatic());
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004264 a.info.configChanges = getActivityConfigChanges(
4265 sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004266 sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004267 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004268 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07004269
Craig Mautner43e52ed2014-06-16 17:18:52 -07004270 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004271 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07004272 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07004273
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004274 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004275 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
4276 }
4277
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004278 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004279 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
4280 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004281
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004282 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004283 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
4284 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004285
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004286 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004287 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
4288 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004289
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004290 a.info.screenOrientation = sa.getInt(
4291 R.styleable.AndroidManifestActivity_screenOrientation,
4292 SCREEN_ORIENTATION_UNSPECIFIED);
Wale Ogunwale6a591362015-10-05 20:18:27 -07004293
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004294 setActivityResizeMode(a.info, sa, owner);
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004295
Winson Chungd3395382016-12-13 11:49:09 -08004296 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
4297 false)) {
4298 a.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE;
4299 }
4300
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004301 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004302 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004303 }
Wale Ogunwaleb60692e2015-10-24 12:35:56 -07004304
Bryce Lee22571db2017-07-07 15:54:18 -07004305 if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio)
4306 && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio)
4307 == TypedValue.TYPE_FLOAT) {
4308 a.setMaxAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio,
4309 0 /*default*/));
4310 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004311
Craig Mautner15df08a2015-04-01 12:17:18 -07004312 a.info.lockTaskLaunchMode =
4313 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004314
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004315 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4316 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004317 false);
Ruben Brunkf56c9f42016-04-22 18:20:55 -07004318
4319 a.info.requestedVrComponent =
4320 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
Robert Carr0f5d7532016-10-17 16:39:17 -07004321
4322 a.info.rotationAnimation =
Robert Carr427ba4f2017-07-17 18:37:06 -07004323 sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_UNSPECIFIED);
Romain Guy48327452017-01-23 17:03:35 -08004324
4325 a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
4326 ActivityInfo.COLOR_MODE_DEFAULT);
chaviw59b98852017-06-13 12:05:44 -07004327
4328 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) {
4329 a.info.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
4330 }
4331
4332 if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) {
4333 a.info.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON;
4334 }
4335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004336 } else {
4337 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4338 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004339
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004340 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07004341 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004342 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004343
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004344 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4345 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004346 false);
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004347 }
4348
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004349 if (a.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004350 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004351 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004352 }
4353
Todd Kennedy752fb702017-03-21 16:28:10 -07004354 // can't make this final; we may set it later via meta-data
4355 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08004356 sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004357 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004358 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004359 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004360 }
4361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004362 sa.recycle();
4363
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004364 if (receiver && (owner.applicationInfo.privateFlags
4365 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004366 // A heavy-weight application can not have receives in its main process
4367 // We can do direct compare because we intern all strings.
4368 if (a.info.processName == owner.packageName) {
4369 outError[0] = "Heavy-weight applications can not have receivers in main process";
4370 }
4371 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004373 if (outError[0] != null) {
4374 return null;
4375 }
4376
4377 int outerDepth = parser.getDepth();
4378 int type;
4379 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4380 && (type != XmlPullParser.END_TAG
4381 || parser.getDepth() > outerDepth)) {
4382 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4383 continue;
4384 }
4385
4386 if (parser.getName().equals("intent-filter")) {
4387 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004388 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4389 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004390 return null;
4391 }
4392 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004393 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004394 + mArchiveSourcePath + " "
4395 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004396 } else {
Todd Kennedy6d418b62018-02-22 14:15:18 -08004397 a.order = Math.max(intent.getOrder(), a.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004398 a.intents.add(intent);
4399 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004400 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004401 final int visibility = visibleToEphemeral
4402 ? IntentFilter.VISIBILITY_EXPLICIT
4403 : !receiver && isImplicitlyExposedIntent(intent)
4404 ? IntentFilter.VISIBILITY_IMPLICIT
4405 : IntentFilter.VISIBILITY_NONE;
4406 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004407 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004408 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4409 }
4410 if (intent.isImplicitlyVisibleToInstantApp()) {
4411 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004412 }
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -07004413 if (LOG_UNSAFE_BROADCASTS && receiver
4414 && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
4415 for (int i = 0; i < intent.countActions(); i++) {
4416 final String action = intent.getAction(i);
4417 if (action == null || !action.startsWith("android.")) continue;
4418 if (!SAFE_BROADCASTS.contains(action)) {
4419 Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
4420 + owner.packageName + " as requested at: "
4421 + parser.getPositionDescription());
4422 }
4423 }
4424 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004425 } else if (!receiver && parser.getName().equals("preferred")) {
4426 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004427 if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
4428 intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004429 return null;
4430 }
4431 if (intent.countActions() == 0) {
4432 Slog.w(TAG, "No actions in preferred at "
4433 + mArchiveSourcePath + " "
4434 + parser.getPositionDescription());
4435 } else {
4436 if (owner.preferredActivityFilters == null) {
4437 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
4438 }
4439 owner.preferredActivityFilters.add(intent);
4440 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004441 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004442 final int visibility = visibleToEphemeral
4443 ? IntentFilter.VISIBILITY_EXPLICIT
4444 : !receiver && isImplicitlyExposedIntent(intent)
4445 ? IntentFilter.VISIBILITY_IMPLICIT
4446 : IntentFilter.VISIBILITY_NONE;
4447 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004448 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004449 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4450 }
4451 if (intent.isImplicitlyVisibleToInstantApp()) {
4452 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004453 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004454 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004455 if ((a.metaData = parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004456 outError)) == null) {
4457 return null;
4458 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004459 } else if (!receiver && parser.getName().equals("layout")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004460 parseLayout(res, parser, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004461 } else {
4462 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004463 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004464 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004465 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004466 + " at " + mArchiveSourcePath + " "
4467 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004468 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004469 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004470 + " at " + mArchiveSourcePath + " "
4471 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004472 }
4473 XmlUtils.skipCurrentTag(parser);
4474 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004475 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004476 if (receiver) {
4477 outError[0] = "Bad element under <receiver>: " + parser.getName();
4478 } else {
4479 outError[0] = "Bad element under <activity>: " + parser.getName();
4480 }
4481 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004482 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004483 }
4484 }
4485
4486 if (!setExported) {
4487 a.info.exported = a.intents.size() > 0;
4488 }
4489
4490 return a;
4491 }
4492
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004493 private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004494 final boolean appExplicitDefault = (owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004495 & (PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
4496 | PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004497
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004498 if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
4499 || appExplicitDefault) {
4500 // Activity or app explicitly set if it is resizeable or not;
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004501 final boolean appResizeable = (owner.applicationInfo.privateFlags
4502 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004503 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004504 appResizeable)) {
Winson Chungd3395382016-12-13 11:49:09 -08004505 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004506 } else {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004507 aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004508 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004509 return;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004510 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004511
4512 if ((owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004513 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) != 0) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004514 // The activity or app didn't explicitly set the resizing option, however we want to
4515 // make it resize due to the sdk version it is targeting.
4516 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4517 return;
4518 }
4519
4520 // resize preference isn't set and target sdk version doesn't support resizing apps by
4521 // default. For the app to be resizeable if it isn't fixed orientation or immersive.
skuhne@google.com322347b2016-12-02 12:54:03 -08004522 if (aInfo.isFixedOrientationPortrait()) {
4523 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
4524 } else if (aInfo.isFixedOrientationLandscape()) {
4525 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
4526 } else if (aInfo.isFixedOrientation()) {
4527 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
4528 } else {
4529 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4530 }
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004531 }
4532
Bryce Lee22571db2017-07-07 15:54:18 -07004533 /**
4534 * Sets every the max aspect ratio of every child activity that doesn't already have an aspect
4535 * ratio set.
4536 */
4537 private void setMaxAspectRatio(Package owner) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004538 // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
4539 // 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 -07004540 float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004541 ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
Bryce Lee22571db2017-07-07 15:54:18 -07004542
4543 if (owner.applicationInfo.maxAspectRatio != 0) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004544 // Use the application max aspect ration as default if set.
Bryce Lee22571db2017-07-07 15:54:18 -07004545 maxAspectRatio = owner.applicationInfo.maxAspectRatio;
4546 } else if (owner.mAppMetaData != null
4547 && owner.mAppMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) {
4548 maxAspectRatio = owner.mAppMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004549 }
4550
Bryce Lee22571db2017-07-07 15:54:18 -07004551 for (Activity activity : owner.activities) {
4552 // If the max aspect ratio for the activity has already been set, skip.
4553 if (activity.hasMaxAspectRatio()) {
4554 continue;
4555 }
4556
4557 // By default we prefer to use a values defined on the activity directly than values
4558 // defined on the application. We do not check the styled attributes on the activity
4559 // as it would have already been set when we processed the activity. We wait to process
4560 // the meta data here since this method is called at the end of processing the
4561 // application and all meta data is guaranteed.
4562 final float activityAspectRatio = activity.metaData != null
4563 ? activity.metaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio)
4564 : maxAspectRatio;
4565
4566 activity.setMaxAspectRatio(activityAspectRatio);
Wale Ogunwale0cb70ac2017-03-27 09:16:38 -07004567 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004568 }
4569
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004570 /**
4571 * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004572 * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from
4573 * AndroidManifest.xml.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004574 * @hide Exposed for unit testing only.
4575 */
4576 @TestApi
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004577 public static int getActivityConfigChanges(int configChanges, int recreateOnConfigChanges) {
4578 return configChanges | ((~recreateOnConfigChanges) & RECREATE_ON_CONFIG_CHANGES_MASK);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004579 }
4580
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004581 private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004582 TypedArray sw = res.obtainAttributes(attrs,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004583 com.android.internal.R.styleable.AndroidManifestLayout);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004584 int width = -1;
4585 float widthFraction = -1f;
4586 int height = -1;
4587 float heightFraction = -1f;
4588 final int widthType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004589 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004590 if (widthType == TypedValue.TYPE_FRACTION) {
4591 widthFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004592 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004593 1, 1, -1);
4594 } else if (widthType == TypedValue.TYPE_DIMENSION) {
4595 width = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004596 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004597 -1);
4598 }
4599 final int heightType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004600 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004601 if (heightType == TypedValue.TYPE_FRACTION) {
4602 heightFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004603 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004604 1, 1, -1);
4605 } else if (heightType == TypedValue.TYPE_DIMENSION) {
4606 height = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004607 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004608 -1);
4609 }
4610 int gravity = sw.getInt(
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004611 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004612 Gravity.CENTER);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004613 int minWidth = sw.getDimensionPixelSize(
4614 com.android.internal.R.styleable.AndroidManifestLayout_minWidth,
Andrii Kulian2e751b82016-03-16 16:59:32 -07004615 -1);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004616 int minHeight = sw.getDimensionPixelSize(
4617 com.android.internal.R.styleable.AndroidManifestLayout_minHeight,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004618 -1);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004619 sw.recycle();
Andrii Kulian2e751b82016-03-16 16:59:32 -07004620 a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction,
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004621 height, heightFraction, gravity, minWidth, minHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004622 }
4623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004624 private Activity parseActivityAlias(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004625 XmlResourceParser parser, int flags, String[] outError,
4626 CachedComponentArgs cachedArgs)
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004627 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004628 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004629 com.android.internal.R.styleable.AndroidManifestActivityAlias);
4630
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004631 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004632 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
4633 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004634 if (targetActivity == null) {
4635 outError[0] = "<activity-alias> does not specify android:targetActivity";
4636 sa.recycle();
4637 return null;
4638 }
4639
4640 targetActivity = buildClassName(owner.applicationInfo.packageName,
4641 targetActivity, outError);
4642 if (targetActivity == null) {
4643 sa.recycle();
4644 return null;
4645 }
4646
Garrett Boyer52136662017-05-23 13:47:58 -07004647 if (cachedArgs.mActivityAliasArgs == null) {
4648 cachedArgs.mActivityAliasArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004649 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
4650 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
4651 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004652 com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004653 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004654 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004655 mSeparateProcesses,
4656 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004657 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004658 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004659 cachedArgs.mActivityAliasArgs.tag = "<activity-alias>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004660 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004661
Garrett Boyer52136662017-05-23 13:47:58 -07004662 cachedArgs.mActivityAliasArgs.sa = sa;
4663 cachedArgs.mActivityAliasArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004664
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004665 Activity target = null;
4666
4667 final int NA = owner.activities.size();
4668 for (int i=0; i<NA; i++) {
4669 Activity t = owner.activities.get(i);
4670 if (targetActivity.equals(t.info.name)) {
4671 target = t;
4672 break;
4673 }
4674 }
4675
4676 if (target == null) {
4677 outError[0] = "<activity-alias> target activity " + targetActivity
4678 + " not found in manifest";
4679 sa.recycle();
4680 return null;
4681 }
4682
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004683 ActivityInfo info = new ActivityInfo();
4684 info.targetActivity = targetActivity;
4685 info.configChanges = target.info.configChanges;
4686 info.flags = target.info.flags;
4687 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07004688 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08004689 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004690 info.labelRes = target.info.labelRes;
4691 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
4692 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07004693 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004694 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004695 if (info.descriptionRes == 0) {
4696 info.descriptionRes = target.info.descriptionRes;
4697 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004698 info.screenOrientation = target.info.screenOrientation;
4699 info.taskAffinity = target.info.taskAffinity;
4700 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07004701 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07004702 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07004703 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07004704 info.maxRecents = target.info.maxRecents;
Andrii Kulian2e751b82016-03-16 16:59:32 -07004705 info.windowLayout = target.info.windowLayout;
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004706 info.resizeMode = target.info.resizeMode;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004707 info.maxAspectRatio = target.info.maxAspectRatio;
rongliuc12ede42018-02-23 17:58:38 -08004708 info.requestedVrComponent = target.info.requestedVrComponent;
Bryce Lee22571db2017-07-07 15:54:18 -07004709
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004710 info.encryptionAware = info.directBootAware = target.info.directBootAware;
Craig Mautner8307ea72014-09-11 15:03:53 -07004711
Garrett Boyer52136662017-05-23 13:47:58 -07004712 Activity a = new Activity(cachedArgs.mActivityAliasArgs, info);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004713 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004714 sa.recycle();
4715 return null;
4716 }
4717
4718 final boolean setExported = sa.hasValue(
4719 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
4720 if (setExported) {
4721 a.info.exported = sa.getBoolean(
4722 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
4723 }
4724
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004725 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004726 str = sa.getNonConfigurationString(
4727 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004728 if (str != null) {
4729 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4730 }
4731
Adam Powelldd8fab22012-03-22 17:47:27 -07004732 String parentName = sa.getNonConfigurationString(
4733 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004734 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004735 if (parentName != null) {
4736 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4737 if (outError[0] == null) {
4738 a.info.parentActivityName = parentClassName;
4739 } else {
4740 Log.e(TAG, "Activity alias " + a.info.name +
4741 " specified invalid parentActivityName " + parentName);
4742 outError[0] = null;
4743 }
4744 }
4745
Chad Brubaker699c7712017-01-20 13:53:42 -08004746 // TODO add visibleToInstantApps attribute to activity alias
Todd Kennedybe0b8892017-02-15 14:13:52 -08004747 final boolean visibleToEphemeral =
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004748 ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004750 sa.recycle();
4751
4752 if (outError[0] != null) {
4753 return null;
4754 }
4755
4756 int outerDepth = parser.getDepth();
4757 int type;
4758 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4759 && (type != XmlPullParser.END_TAG
4760 || parser.getDepth() > outerDepth)) {
4761 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4762 continue;
4763 }
4764
4765 if (parser.getName().equals("intent-filter")) {
4766 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004767 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4768 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004769 return null;
4770 }
4771 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004772 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004773 + mArchiveSourcePath + " "
4774 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004775 } else {
Todd Kennedy6d418b62018-02-22 14:15:18 -08004776 a.order = Math.max(intent.getOrder(), a.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777 a.intents.add(intent);
4778 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004779 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004780 final int visibility = visibleToEphemeral
4781 ? IntentFilter.VISIBILITY_EXPLICIT
4782 : isImplicitlyExposedIntent(intent)
4783 ? IntentFilter.VISIBILITY_IMPLICIT
4784 : IntentFilter.VISIBILITY_NONE;
4785 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004786 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004787 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4788 }
4789 if (intent.isImplicitlyVisibleToInstantApp()) {
4790 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004792 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004793 if ((a.metaData=parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004794 outError)) == null) {
4795 return null;
4796 }
4797 } else {
4798 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004799 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004800 + " at " + mArchiveSourcePath + " "
4801 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004802 XmlUtils.skipCurrentTag(parser);
4803 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004804 } else {
4805 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
4806 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004807 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004808 }
4809 }
4810
4811 if (!setExported) {
4812 a.info.exported = a.intents.size() > 0;
4813 }
4814
4815 return a;
4816 }
4817
4818 private Provider parseProvider(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004819 XmlResourceParser parser, int flags, String[] outError,
4820 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004821 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004822 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004823 com.android.internal.R.styleable.AndroidManifestProvider);
4824
Garrett Boyer52136662017-05-23 13:47:58 -07004825 if (cachedArgs.mProviderArgs == null) {
4826 cachedArgs.mProviderArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004827 com.android.internal.R.styleable.AndroidManifestProvider_name,
4828 com.android.internal.R.styleable.AndroidManifestProvider_label,
4829 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004830 com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004831 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004832 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004833 mSeparateProcesses,
4834 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004835 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004836 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004837 cachedArgs.mProviderArgs.tag = "<provider>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004838 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004839
Garrett Boyer52136662017-05-23 13:47:58 -07004840 cachedArgs.mProviderArgs.sa = sa;
4841 cachedArgs.mProviderArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004842
Garrett Boyer52136662017-05-23 13:47:58 -07004843 Provider p = new Provider(cachedArgs.mProviderArgs, new ProviderInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004844 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 sa.recycle();
4846 return null;
4847 }
4848
Nick Kralevichf097b162012-07-28 12:43:48 -07004849 boolean providerExportedDefault = false;
4850
4851 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
4852 // For compatibility, applications targeting API level 16 or lower
4853 // should have their content providers exported by default, unless they
4854 // specify otherwise.
4855 providerExportedDefault = true;
4856 }
4857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07004859 com.android.internal.R.styleable.AndroidManifestProvider_exported,
4860 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004861
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004862 String cpname = sa.getNonConfigurationString(
4863 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004864
4865 p.info.isSyncable = sa.getBoolean(
4866 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
4867 false);
4868
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004869 String permission = sa.getNonConfigurationString(
4870 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
4871 String str = sa.getNonConfigurationString(
4872 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004873 if (str == null) {
4874 str = permission;
4875 }
4876 if (str == null) {
4877 p.info.readPermission = owner.applicationInfo.permission;
4878 } else {
4879 p.info.readPermission =
4880 str.length() > 0 ? str.toString().intern() : null;
4881 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004882 str = sa.getNonConfigurationString(
4883 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004884 if (str == null) {
4885 str = permission;
4886 }
4887 if (str == null) {
4888 p.info.writePermission = owner.applicationInfo.permission;
4889 } else {
4890 p.info.writePermission =
4891 str.length() > 0 ? str.toString().intern() : null;
4892 }
4893
4894 p.info.grantUriPermissions = sa.getBoolean(
4895 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
4896 false);
4897
4898 p.info.multiprocess = sa.getBoolean(
4899 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
4900 false);
4901
4902 p.info.initOrder = sa.getInt(
4903 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
4904 0);
4905
Todd Kennedye9d0d272017-01-23 06:49:29 -08004906 p.info.splitName =
4907 sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0);
4908
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004909 p.info.flags = 0;
4910
4911 if (sa.getBoolean(
4912 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
4913 false)) {
4914 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004915 }
4916
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004917 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
4918 R.styleable.AndroidManifestProvider_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004919 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004920 if (p.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004921 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004922 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004923 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004924
Todd Kennedybe0b8892017-02-15 14:13:52 -08004925 final boolean visibleToEphemeral =
4926 sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004927 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004928 p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004929 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004930 }
4931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004932 sa.recycle();
4933
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004934 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
4935 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004936 // A heavy-weight application can not have providers in its main process
4937 // We can do direct compare because we intern all strings.
4938 if (p.info.processName == owner.packageName) {
4939 outError[0] = "Heavy-weight applications can not have providers in main process";
4940 return null;
4941 }
4942 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004944 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07004945 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004946 return null;
4947 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08004948 if (cpname.length() <= 0) {
4949 outError[0] = "<provider> has empty authorities attribute";
4950 return null;
4951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 p.info.authority = cpname.intern();
4953
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004954 if (!parseProviderTags(
Patrick Baumanna2900392018-02-05 15:30:43 -08004955 res, parser, visibleToEphemeral, p, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004956 return null;
4957 }
4958
4959 return p;
4960 }
4961
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004962 private boolean parseProviderTags(Resources res, XmlResourceParser parser,
Patrick Baumanna2900392018-02-05 15:30:43 -08004963 boolean visibleToEphemeral, Provider outInfo, String[] outError)
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004964 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004965 int outerDepth = parser.getDepth();
4966 int type;
4967 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4968 && (type != XmlPullParser.END_TAG
4969 || parser.getDepth() > outerDepth)) {
4970 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4971 continue;
4972 }
4973
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004974 if (parser.getName().equals("intent-filter")) {
4975 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004976 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
4977 intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004978 return false;
4979 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004980 if (visibleToEphemeral) {
4981 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
4982 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004983 }
Todd Kennedy6d418b62018-02-22 14:15:18 -08004984 outInfo.order = Math.max(intent.getOrder(), outInfo.order);
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004985 outInfo.intents.add(intent);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004986
4987 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004988 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 outInfo.metaData, outError)) == null) {
4990 return false;
4991 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 } else if (parser.getName().equals("grant-uri-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004994 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004995 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
4996
4997 PatternMatcher pa = null;
4998
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004999 String str = sa.getNonConfigurationString(
5000 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005001 if (str != null) {
5002 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
5003 }
5004
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005005 str = sa.getNonConfigurationString(
5006 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005007 if (str != null) {
5008 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
5009 }
5010
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005011 str = sa.getNonConfigurationString(
5012 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005013 if (str != null) {
5014 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5015 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005017 sa.recycle();
5018
5019 if (pa != null) {
5020 if (outInfo.info.uriPermissionPatterns == null) {
5021 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
5022 outInfo.info.uriPermissionPatterns[0] = pa;
5023 } else {
5024 final int N = outInfo.info.uriPermissionPatterns.length;
5025 PatternMatcher[] newp = new PatternMatcher[N+1];
5026 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
5027 newp[N] = pa;
5028 outInfo.info.uriPermissionPatterns = newp;
5029 }
5030 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005031 } else {
5032 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005033 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005034 + parser.getName() + " at " + mArchiveSourcePath + " "
5035 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005036 XmlUtils.skipCurrentTag(parser);
5037 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005038 } else {
5039 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5040 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005041 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005042 }
5043 XmlUtils.skipCurrentTag(parser);
5044
5045 } else if (parser.getName().equals("path-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005046 TypedArray sa = res.obtainAttributes(parser,
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005047 com.android.internal.R.styleable.AndroidManifestPathPermission);
5048
5049 PathPermission pa = null;
5050
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005051 String permission = sa.getNonConfigurationString(
5052 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
5053 String readPermission = sa.getNonConfigurationString(
5054 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005055 if (readPermission == null) {
5056 readPermission = permission;
5057 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005058 String writePermission = sa.getNonConfigurationString(
5059 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005060 if (writePermission == null) {
5061 writePermission = permission;
5062 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005063
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005064 boolean havePerm = false;
5065 if (readPermission != null) {
5066 readPermission = readPermission.intern();
5067 havePerm = true;
5068 }
5069 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00005070 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005071 havePerm = true;
5072 }
5073
5074 if (!havePerm) {
5075 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005076 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005077 + parser.getName() + " at " + mArchiveSourcePath + " "
5078 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005079 XmlUtils.skipCurrentTag(parser);
5080 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005081 } else {
5082 outError[0] = "No readPermission or writePermssion for <path-permission>";
5083 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005084 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005085 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005086
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005087 String path = sa.getNonConfigurationString(
5088 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005089 if (path != null) {
5090 pa = new PathPermission(path,
5091 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
5092 }
5093
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005094 path = sa.getNonConfigurationString(
5095 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005096 if (path != null) {
5097 pa = new PathPermission(path,
5098 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
5099 }
5100
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005101 path = sa.getNonConfigurationString(
5102 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005103 if (path != null) {
5104 pa = new PathPermission(path,
5105 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
5106 }
5107
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005108 path = sa.getNonConfigurationString(
5109 com.android.internal.R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
5110 if (path != null) {
5111 pa = new PathPermission(path,
5112 PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission);
5113 }
5114
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005115 sa.recycle();
5116
5117 if (pa != null) {
5118 if (outInfo.info.pathPermissions == null) {
5119 outInfo.info.pathPermissions = new PathPermission[1];
5120 outInfo.info.pathPermissions[0] = pa;
5121 } else {
5122 final int N = outInfo.info.pathPermissions.length;
5123 PathPermission[] newp = new PathPermission[N+1];
5124 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
5125 newp[N] = pa;
5126 outInfo.info.pathPermissions = newp;
5127 }
5128 } else {
5129 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005130 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005131 + parser.getName() + " at " + mArchiveSourcePath + " "
5132 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005133 XmlUtils.skipCurrentTag(parser);
5134 continue;
5135 }
5136 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5137 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138 }
5139 XmlUtils.skipCurrentTag(parser);
5140
5141 } else {
5142 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005143 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005144 + parser.getName() + " at " + mArchiveSourcePath + " "
5145 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005146 XmlUtils.skipCurrentTag(parser);
5147 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005148 } else {
5149 outError[0] = "Bad element under <provider>: " + parser.getName();
5150 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005151 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005152 }
5153 }
5154 return true;
5155 }
5156
5157 private Service parseService(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07005158 XmlResourceParser parser, int flags, String[] outError,
5159 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005161 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005162 com.android.internal.R.styleable.AndroidManifestService);
5163
Garrett Boyer52136662017-05-23 13:47:58 -07005164 if (cachedArgs.mServiceArgs == null) {
5165 cachedArgs.mServiceArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005166 com.android.internal.R.styleable.AndroidManifestService_name,
5167 com.android.internal.R.styleable.AndroidManifestService_label,
5168 com.android.internal.R.styleable.AndroidManifestService_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005169 com.android.internal.R.styleable.AndroidManifestService_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07005170 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08005171 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005172 mSeparateProcesses,
5173 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005174 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005175 com.android.internal.R.styleable.AndroidManifestService_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07005176 cachedArgs.mServiceArgs.tag = "<service>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005177 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005178
Garrett Boyer52136662017-05-23 13:47:58 -07005179 cachedArgs.mServiceArgs.sa = sa;
5180 cachedArgs.mServiceArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005181
Garrett Boyer52136662017-05-23 13:47:58 -07005182 Service s = new Service(cachedArgs.mServiceArgs, new ServiceInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005183 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005184 sa.recycle();
5185 return null;
5186 }
5187
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005188 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005189 com.android.internal.R.styleable.AndroidManifestService_exported);
5190 if (setExported) {
5191 s.info.exported = sa.getBoolean(
5192 com.android.internal.R.styleable.AndroidManifestService_exported, false);
5193 }
5194
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005195 String str = sa.getNonConfigurationString(
5196 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 if (str == null) {
5198 s.info.permission = owner.applicationInfo.permission;
5199 } else {
5200 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
5201 }
5202
Todd Kennedye9d0d272017-01-23 06:49:29 -08005203 s.info.splitName =
5204 sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0);
5205
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005206 s.info.flags = 0;
5207 if (sa.getBoolean(
5208 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
5209 false)) {
5210 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
5211 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08005212 if (sa.getBoolean(
5213 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
5214 false)) {
5215 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
5216 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005217 if (sa.getBoolean(
Robert Sesekb9a86662015-12-09 16:22:45 -05005218 com.android.internal.R.styleable.AndroidManifestService_externalService,
5219 false)) {
5220 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
5221 }
5222 if (sa.getBoolean(
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005223 com.android.internal.R.styleable.AndroidManifestService_singleUser,
5224 false)) {
5225 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005226 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005227
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005228 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
5229 R.styleable.AndroidManifestService_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005230 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005231 if (s.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005232 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005233 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005234 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005235
Todd Kennedy752fb702017-03-21 16:28:10 -07005236 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08005237 sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005238 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005239 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005240 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005241 }
5242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 sa.recycle();
5244
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005245 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5246 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005247 // A heavy-weight application can not have services in its main process
5248 // We can do direct compare because we intern all strings.
5249 if (s.info.processName == owner.packageName) {
5250 outError[0] = "Heavy-weight applications can not have services in main process";
5251 return null;
5252 }
5253 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005255 int outerDepth = parser.getDepth();
5256 int type;
5257 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5258 && (type != XmlPullParser.END_TAG
5259 || parser.getDepth() > outerDepth)) {
5260 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5261 continue;
5262 }
5263
5264 if (parser.getName().equals("intent-filter")) {
5265 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005266 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5267 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005268 return null;
5269 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005270 if (visibleToEphemeral) {
5271 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5272 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005273 }
Todd Kennedy6d418b62018-02-22 14:15:18 -08005274 s.order = Math.max(intent.getOrder(), s.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005275 s.intents.add(intent);
5276 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005277 if ((s.metaData=parseMetaData(res, parser, s.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005278 outError)) == null) {
5279 return null;
5280 }
5281 } else {
5282 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005283 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005284 + parser.getName() + " at " + mArchiveSourcePath + " "
5285 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005286 XmlUtils.skipCurrentTag(parser);
5287 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005288 } else {
5289 outError[0] = "Bad element under <service>: " + parser.getName();
5290 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005292 }
5293 }
5294
5295 if (!setExported) {
5296 s.info.exported = s.intents.size() > 0;
5297 }
5298
5299 return s;
5300 }
5301
Chad Brubaker49414832017-04-13 16:13:23 -07005302 private boolean isImplicitlyExposedIntent(IntentInfo intent) {
5303 return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
5304 || intent.hasAction(Intent.ACTION_SEND)
5305 || intent.hasAction(Intent.ACTION_SENDTO)
5306 || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005307 }
5308
Svet Ganov354cd3c2015-12-17 11:35:04 -08005309 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
5310 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005311 int outerDepth = parser.getDepth();
5312 int type;
5313 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5314 && (type != XmlPullParser.END_TAG
5315 || parser.getDepth() > outerDepth)) {
5316 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5317 continue;
5318 }
5319
5320 if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005321 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005322 outInfo.metaData, outError)) == null) {
5323 return false;
5324 }
5325 } else {
5326 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005327 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005328 + parser.getName() + " at " + mArchiveSourcePath + " "
5329 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005330 XmlUtils.skipCurrentTag(parser);
5331 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005332 } else {
5333 outError[0] = "Bad element under " + tag + ": " + parser.getName();
5334 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005336 }
5337 }
5338 return true;
5339 }
5340
5341 private Bundle parseMetaData(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08005342 XmlResourceParser parser, Bundle data, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005343 throws XmlPullParserException, IOException {
5344
Svet Ganov354cd3c2015-12-17 11:35:04 -08005345 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005346 com.android.internal.R.styleable.AndroidManifestMetaData);
5347
5348 if (data == null) {
5349 data = new Bundle();
5350 }
5351
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005352 String name = sa.getNonConfigurationString(
5353 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005354 if (name == null) {
5355 outError[0] = "<meta-data> requires an android:name attribute";
5356 sa.recycle();
5357 return null;
5358 }
5359
Dianne Hackborn854060af2009-07-09 18:14:31 -07005360 name = name.intern();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005362 TypedValue v = sa.peekValue(
5363 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
5364 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005365 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005366 data.putInt(name, v.resourceId);
5367 } else {
5368 v = sa.peekValue(
5369 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07005370 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005371 if (v != null) {
5372 if (v.type == TypedValue.TYPE_STRING) {
5373 CharSequence cs = v.coerceToString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00005374 data.putString(name, cs != null ? cs.toString() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
5376 data.putBoolean(name, v.data != 0);
5377 } else if (v.type >= TypedValue.TYPE_FIRST_INT
5378 && v.type <= TypedValue.TYPE_LAST_INT) {
5379 data.putInt(name, v.data);
5380 } else if (v.type == TypedValue.TYPE_FLOAT) {
5381 data.putFloat(name, v.getFloat());
5382 } else {
5383 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005384 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005385 + parser.getName() + " at " + mArchiveSourcePath + " "
5386 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005387 } else {
5388 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
5389 data = null;
5390 }
5391 }
5392 } else {
5393 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
5394 data = null;
5395 }
5396 }
5397
5398 sa.recycle();
5399
5400 XmlUtils.skipCurrentTag(parser);
5401
5402 return data;
5403 }
5404
Adam Lesinski4e862812016-11-21 16:02:24 -08005405 private static VerifierInfo parseVerifier(AttributeSet attrs) {
5406 String packageName = null;
5407 String encodedPublicKey = null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005408
Adam Lesinski4e862812016-11-21 16:02:24 -08005409 final int attrCount = attrs.getAttributeCount();
5410 for (int i = 0; i < attrCount; i++) {
5411 final int attrResId = attrs.getAttributeNameResource(i);
5412 switch (attrResId) {
5413 case com.android.internal.R.attr.name:
5414 packageName = attrs.getAttributeValue(i);
5415 break;
Kenny Root05ca4c92011-09-15 10:36:25 -07005416
Adam Lesinski4e862812016-11-21 16:02:24 -08005417 case com.android.internal.R.attr.publicKey:
5418 encodedPublicKey = attrs.getAttributeValue(i);
5419 break;
5420 }
5421 }
Kenny Root05ca4c92011-09-15 10:36:25 -07005422
5423 if (packageName == null || packageName.length() == 0) {
5424 Slog.i(TAG, "verifier package name was null; skipping");
5425 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005426 }
5427
Christopher Tate30147332014-04-15 12:57:47 -07005428 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
5429 if (publicKey == null) {
5430 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
5431 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08005432 }
5433
Christopher Tate30147332014-04-15 12:57:47 -07005434 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08005435 }
5436
Christopher Tate30147332014-04-15 12:57:47 -07005437 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
5438 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07005439 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07005440 return null;
5441 }
5442
Kenny Root05ca4c92011-09-15 10:36:25 -07005443 EncodedKeySpec keySpec;
5444 try {
5445 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
5446 keySpec = new X509EncodedKeySpec(encoded);
5447 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07005448 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07005449 return null;
5450 }
5451
5452 /* First try the key as an RSA key. */
5453 try {
5454 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005455 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005456 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005457 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005458 } catch (InvalidKeySpecException e) {
5459 // Not a RSA public key.
5460 }
5461
dcashman1616f302015-05-29 14:47:23 -07005462 /* Now try it as a ECDSA key. */
5463 try {
5464 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
5465 return keyFactory.generatePublic(keySpec);
5466 } catch (NoSuchAlgorithmException e) {
5467 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
5468 } catch (InvalidKeySpecException e) {
5469 // Not a ECDSA public key.
5470 }
5471
Kenny Root05ca4c92011-09-15 10:36:25 -07005472 /* Now try it as a DSA key. */
5473 try {
5474 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005475 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005476 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005477 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005478 } catch (InvalidKeySpecException e) {
5479 // Not a DSA public key.
5480 }
5481
dcashman1616f302015-05-29 14:47:23 -07005482 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07005483 return null;
5484 }
5485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005486 private static final String ANDROID_RESOURCES
5487 = "http://schemas.android.com/apk/res/android";
5488
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005489 private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs,
5490 boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
5491 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005492
Svet Ganov354cd3c2015-12-17 11:35:04 -08005493 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005494 com.android.internal.R.styleable.AndroidManifestIntentFilter);
5495
5496 int priority = sa.getInt(
5497 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005498 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08005499
Todd Kennedy6d418b62018-02-22 14:15:18 -08005500 int order = sa.getInt(
5501 com.android.internal.R.styleable.AndroidManifestIntentFilter_order, 0);
5502 outInfo.setOrder(order);
5503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005504 TypedValue v = sa.peekValue(
5505 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
5506 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
5507 outInfo.nonLocalizedLabel = v.coerceToString();
5508 }
5509
Todd Kennedya83bfca2016-06-03 07:52:17 -07005510 final boolean useRoundIcon =
5511 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
5512 int roundIconVal = useRoundIcon ? sa.getResourceId(
5513 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
5514 if (roundIconVal != 0) {
5515 outInfo.icon = roundIconVal;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005516 } else {
5517 outInfo.icon = sa.getResourceId(
5518 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
5519 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005520
Adam Powell81cd2e92010-04-21 16:35:18 -07005521 outInfo.logo = sa.getResourceId(
5522 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005523
Jose Limaf78e3122014-03-06 12:13:15 -08005524 outInfo.banner = sa.getResourceId(
5525 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
5526
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08005527 if (allowAutoVerify) {
5528 outInfo.setAutoVerify(sa.getBoolean(
5529 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
5530 false));
5531 }
5532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005533 sa.recycle();
5534
5535 int outerDepth = parser.getDepth();
5536 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07005537 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
5538 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
5539 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005540 continue;
5541 }
5542
5543 String nodeName = parser.getName();
5544 if (nodeName.equals("action")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005545 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005546 ANDROID_RESOURCES, "name");
5547 if (value == null || value == "") {
5548 outError[0] = "No value supplied for <android:name>";
5549 return false;
5550 }
5551 XmlUtils.skipCurrentTag(parser);
5552
5553 outInfo.addAction(value);
5554 } else if (nodeName.equals("category")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005555 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005556 ANDROID_RESOURCES, "name");
5557 if (value == null || value == "") {
5558 outError[0] = "No value supplied for <android:name>";
5559 return false;
5560 }
5561 XmlUtils.skipCurrentTag(parser);
5562
5563 outInfo.addCategory(value);
5564
5565 } else if (nodeName.equals("data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005566 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 com.android.internal.R.styleable.AndroidManifestData);
5568
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005569 String str = sa.getNonConfigurationString(
5570 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005571 if (str != null) {
5572 try {
5573 outInfo.addDataType(str);
5574 } catch (IntentFilter.MalformedMimeTypeException e) {
5575 outError[0] = e.toString();
5576 sa.recycle();
5577 return false;
5578 }
5579 }
5580
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005581 str = sa.getNonConfigurationString(
5582 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005583 if (str != null) {
5584 outInfo.addDataScheme(str);
5585 }
5586
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005587 str = sa.getNonConfigurationString(
5588 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
5589 if (str != null) {
5590 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
5591 }
5592
5593 str = sa.getNonConfigurationString(
5594 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
5595 if (str != null) {
5596 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
5597 }
5598
5599 str = sa.getNonConfigurationString(
5600 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
5601 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005602 if (!allowGlobs) {
5603 outError[0] = "sspPattern not allowed here; ssp must be literal";
5604 return false;
5605 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005606 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5607 }
5608
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005609 String host = sa.getNonConfigurationString(
5610 com.android.internal.R.styleable.AndroidManifestData_host, 0);
5611 String port = sa.getNonConfigurationString(
5612 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005613 if (host != null) {
5614 outInfo.addDataAuthority(host, port);
5615 }
5616
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005617 str = sa.getNonConfigurationString(
5618 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005619 if (str != null) {
5620 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
5621 }
5622
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005623 str = sa.getNonConfigurationString(
5624 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005625 if (str != null) {
5626 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
5627 }
5628
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005629 str = sa.getNonConfigurationString(
5630 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005631 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005632 if (!allowGlobs) {
5633 outError[0] = "pathPattern not allowed here; path must be literal";
5634 return false;
5635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005636 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5637 }
5638
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005639 str = sa.getNonConfigurationString(
5640 com.android.internal.R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
5641 if (str != null) {
5642 if (!allowGlobs) {
5643 outError[0] = "pathAdvancedPattern not allowed here; path must be literal";
5644 return false;
5645 }
5646 outInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
5647 }
5648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005649 sa.recycle();
5650 XmlUtils.skipCurrentTag(parser);
5651 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005652 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005653 + parser.getName() + " at " + mArchiveSourcePath + " "
5654 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005655 XmlUtils.skipCurrentTag(parser);
5656 } else {
5657 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
5658 return false;
5659 }
5660 }
5661
5662 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07005663
5664 if (DEBUG_PARSER) {
5665 final StringBuilder cats = new StringBuilder("Intent d=");
5666 cats.append(outInfo.hasDefault);
5667 cats.append(", cat=");
5668
5669 final Iterator<String> it = outInfo.categoriesIterator();
5670 if (it != null) {
5671 while (it.hasNext()) {
5672 cats.append(' ');
5673 cats.append(it.next());
5674 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005675 }
Kenny Rootd2d29252011-08-08 11:27:57 -07005676 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005677 }
5678
5679 return true;
5680 }
5681
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005682 /**
5683 * A container for signing-related data of an application package.
5684 * @hide
5685 */
Patrick Baumann47117fc2017-12-19 10:17:21 -08005686 public static final class SigningDetails implements Parcelable {
5687
5688 @IntDef({SigningDetails.SignatureSchemeVersion.UNKNOWN,
5689 SigningDetails.SignatureSchemeVersion.JAR,
5690 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2,
5691 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3})
5692 public @interface SignatureSchemeVersion {
5693 int UNKNOWN = 0;
5694 int JAR = 1;
5695 int SIGNING_BLOCK_V2 = 2;
5696 int SIGNING_BLOCK_V3 = 3;
5697 }
5698
5699 @Nullable
Mathew Inwood1c77a112018-08-14 14:06:26 +01005700 @UnsupportedAppUsage
Patrick Baumann47117fc2017-12-19 10:17:21 -08005701 public final Signature[] signatures;
5702 @SignatureSchemeVersion
5703 public final int signatureSchemeVersion;
5704 @Nullable
5705 public final ArraySet<PublicKey> publicKeys;
5706
Daniel Cashman77029c52018-01-18 16:19:29 -08005707 /**
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005708 * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
5709 * contains two pieces of information:
5710 * 1) the past signing certificates
5711 * 2) the flags that APK wants to assign to each of the past signing certificates.
5712 *
5713 * This collection of {@code Signature} objects, each of which is formed from a former
5714 * signing certificate of this APK before it was changed by signing certificate rotation,
5715 * represents the first piece of information. It is the APK saying to the rest of the
5716 * world: "hey if you trust the old cert, you can trust me!" This is useful, if for
5717 * instance, the platform would like to determine whether or not to allow this APK to do
5718 * something it would've allowed it to do under the old cert (like upgrade).
Daniel Cashman77029c52018-01-18 16:19:29 -08005719 */
5720 @Nullable
5721 public final Signature[] pastSigningCertificates;
5722
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005723 /** special value used to see if cert is in package - not exposed to callers */
5724 private static final int PAST_CERT_EXISTS = 0;
5725
5726 @IntDef(
5727 flag = true,
5728 value = {CertCapabilities.INSTALLED_DATA,
5729 CertCapabilities.SHARED_USER_ID,
Daniel Cashman629a5f92018-03-30 18:54:14 -07005730 CertCapabilities.PERMISSION,
5731 CertCapabilities.ROLLBACK})
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005732 public @interface CertCapabilities {
5733
5734 /** accept data from already installed pkg with this cert */
5735 int INSTALLED_DATA = 1;
5736
5737 /** accept sharedUserId with pkg with this cert */
5738 int SHARED_USER_ID = 2;
5739
5740 /** grant SIGNATURE permissions to pkgs with this cert */
5741 int PERMISSION = 4;
Daniel Cashman629a5f92018-03-30 18:54:14 -07005742
5743 /** allow pkg to update to one signed by this certificate */
5744 int ROLLBACK = 8;
Dan Cashman303c4bb2018-04-10 07:41:16 -07005745
5746 /** allow pkg to continue to have auth access gated by this cert */
5747 int AUTH = 16;
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005748 }
5749
Daniel Cashman77029c52018-01-18 16:19:29 -08005750 /**
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005751 * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
5752 * contains two pieces of information:
5753 * 1) the past signing certificates
5754 * 2) the flags that APK wants to assign to each of the past signing certificates.
5755 *
5756 * These flags, which have a one-to-one relationship for the {@code pastSigningCertificates}
5757 * collection, represent the second piece of information and are viewed as capabilities.
5758 * They are an APK's way of telling the platform: "this is how I want to trust my old certs,
5759 * please enforce that." This is useful for situation where this app itself is using its
5760 * signing certificate as an authorization mechanism, like whether or not to allow another
5761 * app to have its SIGNATURE permission. An app could specify whether to allow other apps
5762 * signed by its old cert 'X' to still get a signature permission it defines, for example.
Daniel Cashman77029c52018-01-18 16:19:29 -08005763 */
5764 @Nullable
5765 public final int[] pastSigningCertificatesFlags;
5766
Patrick Baumann47117fc2017-12-19 10:17:21 -08005767 /** A representation of unknown signing details. Use instead of null. */
5768 public static final SigningDetails UNKNOWN =
Daniel Cashman77029c52018-01-18 16:19:29 -08005769 new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null, null);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005770
5771 @VisibleForTesting
5772 public SigningDetails(Signature[] signatures,
5773 @SignatureSchemeVersion int signatureSchemeVersion,
Daniel Cashman77029c52018-01-18 16:19:29 -08005774 ArraySet<PublicKey> keys, Signature[] pastSigningCertificates,
5775 int[] pastSigningCertificatesFlags) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08005776 this.signatures = signatures;
5777 this.signatureSchemeVersion = signatureSchemeVersion;
5778 this.publicKeys = keys;
Daniel Cashman77029c52018-01-18 16:19:29 -08005779 this.pastSigningCertificates = pastSigningCertificates;
5780 this.pastSigningCertificatesFlags = pastSigningCertificatesFlags;
5781 }
5782
5783 public SigningDetails(Signature[] signatures,
5784 @SignatureSchemeVersion int signatureSchemeVersion,
5785 Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags)
5786 throws CertificateException {
5787 this(signatures, signatureSchemeVersion, toSigningKeys(signatures),
5788 pastSigningCertificates, pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005789 }
5790
5791 public SigningDetails(Signature[] signatures,
5792 @SignatureSchemeVersion int signatureSchemeVersion)
5793 throws CertificateException {
Daniel Cashman77029c52018-01-18 16:19:29 -08005794 this(signatures, signatureSchemeVersion,
5795 null, null);
5796 }
5797
5798 public SigningDetails(SigningDetails orig) {
5799 if (orig != null) {
5800 if (orig.signatures != null) {
5801 this.signatures = orig.signatures.clone();
5802 } else {
5803 this.signatures = null;
5804 }
5805 this.signatureSchemeVersion = orig.signatureSchemeVersion;
5806 this.publicKeys = new ArraySet<>(orig.publicKeys);
5807 if (orig.pastSigningCertificates != null) {
5808 this.pastSigningCertificates = orig.pastSigningCertificates.clone();
5809 this.pastSigningCertificatesFlags = orig.pastSigningCertificatesFlags.clone();
5810 } else {
5811 this.pastSigningCertificates = null;
5812 this.pastSigningCertificatesFlags = null;
5813 }
5814 } else {
5815 this.signatures = null;
5816 this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
5817 this.publicKeys = null;
5818 this.pastSigningCertificates = null;
5819 this.pastSigningCertificatesFlags = null;
5820 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08005821 }
5822
5823 /** Returns true if the signing details have one or more signatures. */
5824 public boolean hasSignatures() {
5825 return signatures != null && signatures.length > 0;
5826 }
5827
Daniel Cashman5cdda342018-01-19 07:22:52 -08005828 /** Returns true if the signing details have past signing certificates. */
5829 public boolean hasPastSigningCertificates() {
5830 return pastSigningCertificates != null && pastSigningCertificates.length > 0;
5831 }
5832
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005833 /**
5834 * Determines if the provided {@code oldDetails} is an ancestor of or the same as this one.
5835 * If the {@code oldDetails} signing certificate appears in our pastSigningCertificates,
5836 * then that means it has authorized a signing certificate rotation, which eventually leads
5837 * to our certificate, and thus can be trusted. If this method evaluates to true, this
5838 * SigningDetails object should be trusted if the previous one is.
5839 */
5840 public boolean hasAncestorOrSelf(SigningDetails oldDetails) {
5841 if (this == UNKNOWN || oldDetails == UNKNOWN) {
5842 return false;
5843 }
5844 if (oldDetails.signatures.length > 1) {
5845
5846 // multiple-signer packages cannot rotate signing certs, so we just compare current
5847 // signers for an exact match
5848 return signaturesMatchExactly(oldDetails);
5849 } else {
5850
5851 // we may have signing certificate rotation history, check to see if the oldDetails
5852 // was one of our old signing certificates
5853 return hasCertificate(oldDetails.signatures[0]);
5854 }
5855 }
5856
5857 /**
5858 * Similar to {@code hasAncestorOrSelf}. Returns true only if this {@code SigningDetails}
5859 * is a descendant of {@code oldDetails}, not if they're the same. This is used to
5860 * determine if this object is newer than the provided one.
5861 */
5862 public boolean hasAncestor(SigningDetails oldDetails) {
5863 if (this == UNKNOWN || oldDetails == UNKNOWN) {
5864 return false;
5865 }
5866 if (this.hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
5867
5868 // the last entry in pastSigningCertificates is the current signer, ignore it
5869 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
5870 if (pastSigningCertificates[i].equals(oldDetails.signatures[i])) {
5871 return true;
5872 }
5873 }
5874 }
5875 return false;
5876 }
5877
5878 /**
5879 * Determines if the provided {@code oldDetails} is an ancestor of this one, and whether or
5880 * not this one grants it the provided capability, represented by the {@code flags}
5881 * parameter. In the event of signing certificate rotation, a package may still interact
5882 * with entities signed by its old signing certificate and not want to break previously
5883 * functioning behavior. The {@code flags} value determines which capabilities the app
5884 * signed by the newer signing certificate would like to continue to give to its previous
5885 * signing certificate(s).
5886 */
5887 public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) {
5888 if (this == UNKNOWN || oldDetails == UNKNOWN) {
5889 return false;
5890 }
5891 if (oldDetails.signatures.length > 1) {
5892
5893 // multiple-signer packages cannot rotate signing certs, so we must have an exact
5894 // match, which also means all capabilities are granted
5895 return signaturesMatchExactly(oldDetails);
5896 } else {
5897
5898 // we may have signing certificate rotation history, check to see if the oldDetails
5899 // was one of our old signing certificates, and if we grant it the capability it's
5900 // requesting
5901 return hasCertificate(oldDetails.signatures[0], flags);
5902 }
5903 }
5904
5905 /**
5906 * A special case of {@code checkCapability} which re-encodes both sets of signing
5907 * certificates to counteract a previous re-encoding.
5908 */
5909 public boolean checkCapabilityRecover(SigningDetails oldDetails,
5910 @CertCapabilities int flags) throws CertificateException {
5911 if (oldDetails == UNKNOWN || this == UNKNOWN) {
5912 return false;
5913 }
5914 if (hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
5915
5916 // signing certificates may have rotated, check entire history for effective match
5917 for (int i = 0; i < pastSigningCertificates.length; i++) {
5918 if (Signature.areEffectiveMatch(
5919 oldDetails.signatures[0],
5920 pastSigningCertificates[i])
5921 && pastSigningCertificatesFlags[i] == flags) {
5922 return true;
5923 }
5924 }
5925 } else {
5926 return Signature.areEffectiveMatch(oldDetails.signatures, signatures);
5927 }
5928 return false;
5929 }
5930
5931 /**
5932 * Determine if {@code signature} is in this SigningDetails' signing certificate history,
5933 * including the current signer. Automatically returns false if this object has multiple
5934 * signing certificates, since rotation is only supported for single-signers; this is
5935 * enforced by {@code hasCertificateInternal}.
5936 */
5937 public boolean hasCertificate(Signature signature) {
5938 return hasCertificateInternal(signature, PAST_CERT_EXISTS);
5939 }
5940
5941 /**
5942 * Determine if {@code signature} is in this SigningDetails' signing certificate history,
5943 * including the current signer, and whether or not it has the given permission.
5944 * Certificates which match our current signer automatically get all capabilities.
5945 * Automatically returns false if this object has multiple signing certificates, since
5946 * rotation is only supported for single-signers.
5947 */
5948 public boolean hasCertificate(Signature signature, @CertCapabilities int flags) {
5949 return hasCertificateInternal(signature, flags);
5950 }
5951
5952 /** Convenient wrapper for calling {@code hasCertificate} with certificate's raw bytes. */
5953 public boolean hasCertificate(byte[] certificate) {
5954 Signature signature = new Signature(certificate);
5955 return hasCertificate(signature);
5956 }
5957
5958 private boolean hasCertificateInternal(Signature signature, int flags) {
5959 if (this == UNKNOWN) {
5960 return false;
5961 }
5962
5963 // only single-signed apps can have pastSigningCertificates
5964 if (hasPastSigningCertificates()) {
5965
5966 // check all past certs, except for the current one, which automatically gets all
5967 // capabilities, since it is the same as the current signature
5968 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
5969 if (pastSigningCertificates[i].equals(signature)) {
5970 if (flags == PAST_CERT_EXISTS
5971 || (flags & pastSigningCertificatesFlags[i]) == flags) {
5972 return true;
5973 }
5974 }
5975 }
5976 }
5977
5978 // not in previous certs signing history, just check the current signer and make sure
5979 // we are singly-signed
5980 return signatures.length == 1 && signatures[0].equals(signature);
5981 }
5982
5983 /**
5984 * Determines if the provided {@code sha256String} is an ancestor of this one, and whether
5985 * or not this one grants it the provided capability, represented by the {@code flags}
5986 * parameter. In the event of signing certificate rotation, a package may still interact
5987 * with entities signed by its old signing certificate and not want to break previously
5988 * functioning behavior. The {@code flags} value determines which capabilities the app
5989 * signed by the newer signing certificate would like to continue to give to its previous
5990 * signing certificate(s).
5991 *
5992 * @param sha256String A hex-encoded representation of a sha256 digest. In the case of an
5993 * app with multiple signers, this represents the hex-encoded sha256
5994 * digest of the combined hex-encoded sha256 digests of each individual
5995 * signing certificate according to {@link
5996 * PackageUtils#computeSignaturesSha256Digest(Signature[])}
5997 */
5998 public boolean checkCapability(String sha256String, @CertCapabilities int flags) {
5999 if (this == UNKNOWN) {
6000 return false;
6001 }
6002
6003 // first see if the hash represents a single-signer in our signing history
6004 byte[] sha256Bytes = ByteStringUtils.fromHexToByteArray(sha256String);
6005 if (hasSha256Certificate(sha256Bytes, flags)) {
6006 return true;
6007 }
6008
6009 // Not in signing history, either represents multiple signatures or not a match.
6010 // Multiple signers can't rotate, so no need to check flags, just see if the SHAs match.
6011 // We already check the single-signer case above as part of hasSha256Certificate, so no
6012 // need to verify we have multiple signers, just run the old check
6013 // just consider current signing certs
6014 final String[] mSignaturesSha256Digests =
6015 PackageUtils.computeSignaturesSha256Digests(signatures);
6016 final String mSignaturesSha256Digest =
6017 PackageUtils.computeSignaturesSha256Digest(mSignaturesSha256Digests);
6018 return mSignaturesSha256Digest.equals(sha256String);
6019 }
6020
6021 /**
6022 * Determine if the {@code sha256Certificate} is in this SigningDetails' signing certificate
6023 * history, including the current signer. Automatically returns false if this object has
6024 * multiple signing certificates, since rotation is only supported for single-signers.
6025 */
6026 public boolean hasSha256Certificate(byte[] sha256Certificate) {
6027 return hasSha256CertificateInternal(sha256Certificate, PAST_CERT_EXISTS);
6028 }
6029
6030 /**
6031 * Determine if the {@code sha256Certificate} certificate hash corresponds to a signing
6032 * certificate in this SigningDetails' signing certificate history, including the current
6033 * signer, and whether or not it has the given permission. Certificates which match our
6034 * current signer automatically get all capabilities. Automatically returns false if this
6035 * object has multiple signing certificates, since rotation is only supported for
6036 * single-signers.
6037 */
6038 public boolean hasSha256Certificate(byte[] sha256Certificate, @CertCapabilities int flags) {
6039 return hasSha256CertificateInternal(sha256Certificate, flags);
6040 }
6041
6042 private boolean hasSha256CertificateInternal(byte[] sha256Certificate, int flags) {
6043 if (this == UNKNOWN) {
6044 return false;
6045 }
6046 if (hasPastSigningCertificates()) {
6047
6048 // check all past certs, except for the last one, which automatically gets all
6049 // capabilities, since it is the same as the current signature, and is checked below
6050 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
6051 byte[] digest = PackageUtils.computeSha256DigestBytes(
6052 pastSigningCertificates[i].toByteArray());
6053 if (Arrays.equals(sha256Certificate, digest)) {
6054 if (flags == PAST_CERT_EXISTS
6055 || (flags & pastSigningCertificatesFlags[i]) == flags) {
6056 return true;
6057 }
6058 }
6059 }
6060 }
6061
6062 // not in previous certs signing history, just check the current signer
6063 if (signatures.length == 1) {
6064 byte[] digest =
6065 PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray());
6066 return Arrays.equals(sha256Certificate, digest);
6067 }
6068 return false;
6069 }
6070
Patrick Baumann47117fc2017-12-19 10:17:21 -08006071 /** Returns true if the signatures in this and other match exactly. */
6072 public boolean signaturesMatchExactly(SigningDetails other) {
6073 return Signature.areExactMatch(this.signatures, other.signatures);
6074 }
6075
6076 @Override
6077 public int describeContents() {
6078 return 0;
6079 }
6080
6081 @Override
6082 public void writeToParcel(Parcel dest, int flags) {
6083 boolean isUnknown = UNKNOWN == this;
6084 dest.writeBoolean(isUnknown);
6085 if (isUnknown) {
6086 return;
6087 }
6088 dest.writeTypedArray(this.signatures, flags);
6089 dest.writeInt(this.signatureSchemeVersion);
6090 dest.writeArraySet(this.publicKeys);
Daniel Cashman77029c52018-01-18 16:19:29 -08006091 dest.writeTypedArray(this.pastSigningCertificates, flags);
6092 dest.writeIntArray(this.pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006093 }
6094
6095 protected SigningDetails(Parcel in) {
6096 final ClassLoader boot = Object.class.getClassLoader();
6097 this.signatures = in.createTypedArray(Signature.CREATOR);
6098 this.signatureSchemeVersion = in.readInt();
6099 this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot);
Daniel Cashman77029c52018-01-18 16:19:29 -08006100 this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR);
6101 this.pastSigningCertificatesFlags = in.createIntArray();
Patrick Baumann47117fc2017-12-19 10:17:21 -08006102 }
6103
6104 public static final Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() {
6105 @Override
6106 public SigningDetails createFromParcel(Parcel source) {
6107 if (source.readBoolean()) {
6108 return UNKNOWN;
6109 }
6110 return new SigningDetails(source);
6111 }
6112
6113 @Override
6114 public SigningDetails[] newArray(int size) {
6115 return new SigningDetails[size];
6116 }
6117 };
6118
6119 @Override
6120 public boolean equals(Object o) {
6121 if (this == o) return true;
6122 if (!(o instanceof SigningDetails)) return false;
6123
6124 SigningDetails that = (SigningDetails) o;
6125
6126 if (signatureSchemeVersion != that.signatureSchemeVersion) return false;
6127 if (!Signature.areExactMatch(signatures, that.signatures)) return false;
Daniel Cashman77029c52018-01-18 16:19:29 -08006128 if (publicKeys != null) {
6129 if (!publicKeys.equals((that.publicKeys))) {
6130 return false;
6131 }
6132 } else if (that.publicKeys != null) {
6133 return false;
6134 }
6135
6136 // can't use Signature.areExactMatch() because order matters with the past signing certs
6137 if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) {
6138 return false;
6139 }
6140 if (!Arrays.equals(pastSigningCertificatesFlags, that.pastSigningCertificatesFlags)) {
6141 return false;
6142 }
6143
6144 return true;
Patrick Baumann47117fc2017-12-19 10:17:21 -08006145 }
6146
6147 @Override
6148 public int hashCode() {
6149 int result = +Arrays.hashCode(signatures);
6150 result = 31 * result + signatureSchemeVersion;
6151 result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0);
Daniel Cashman77029c52018-01-18 16:19:29 -08006152 result = 31 * result + Arrays.hashCode(pastSigningCertificates);
6153 result = 31 * result + Arrays.hashCode(pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006154 return result;
6155 }
Daniel Cashman77029c52018-01-18 16:19:29 -08006156
6157 /**
6158 * Builder of {@code SigningDetails} instances.
6159 */
6160 public static class Builder {
6161 private Signature[] mSignatures;
6162 private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
6163 private Signature[] mPastSigningCertificates;
6164 private int[] mPastSigningCertificatesFlags;
6165
Mathew Inwood1c77a112018-08-14 14:06:26 +01006166 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006167 public Builder() {
6168 }
6169
6170 /** get signing certificates used to sign the current APK */
Mathew Inwood1c77a112018-08-14 14:06:26 +01006171 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006172 public Builder setSignatures(Signature[] signatures) {
6173 mSignatures = signatures;
6174 return this;
6175 }
6176
6177 /** set the signature scheme version used to sign the APK */
Mathew Inwood1c77a112018-08-14 14:06:26 +01006178 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006179 public Builder setSignatureSchemeVersion(int signatureSchemeVersion) {
6180 mSignatureSchemeVersion = signatureSchemeVersion;
6181 return this;
6182 }
6183
6184 /** set the signing certificates by which the APK proved it can be authenticated */
Mathew Inwood1c77a112018-08-14 14:06:26 +01006185 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006186 public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
6187 mPastSigningCertificates = pastSigningCertificates;
6188 return this;
6189 }
6190
6191 /** set the flags for the {@code pastSigningCertificates} */
Mathew Inwood1c77a112018-08-14 14:06:26 +01006192 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006193 public Builder setPastSigningCertificatesFlags(int[] pastSigningCertificatesFlags) {
6194 mPastSigningCertificatesFlags = pastSigningCertificatesFlags;
6195 return this;
6196 }
6197
6198 private void checkInvariants() {
6199 // must have signatures and scheme version set
6200 if (mSignatures == null) {
6201 throw new IllegalStateException("SigningDetails requires the current signing"
6202 + " certificates.");
6203 }
6204
6205 // pastSigningCerts and flags must match up
6206 boolean pastMismatch = false;
6207 if (mPastSigningCertificates != null && mPastSigningCertificatesFlags != null) {
6208 if (mPastSigningCertificates.length != mPastSigningCertificatesFlags.length) {
6209 pastMismatch = true;
6210 }
6211 } else if (!(mPastSigningCertificates == null
6212 && mPastSigningCertificatesFlags == null)) {
6213 pastMismatch = true;
6214 }
6215 if (pastMismatch) {
6216 throw new IllegalStateException("SigningDetails must have a one to one mapping "
6217 + "between pastSigningCertificates and pastSigningCertificatesFlags");
6218 }
6219 }
6220 /** build a {@code SigningDetails} object */
Mathew Inwood1c77a112018-08-14 14:06:26 +01006221 @UnsupportedAppUsage
Daniel Cashman77029c52018-01-18 16:19:29 -08006222 public SigningDetails build()
6223 throws CertificateException {
6224 checkInvariants();
6225 return new SigningDetails(mSignatures, mSignatureSchemeVersion,
6226 mPastSigningCertificates, mPastSigningCertificatesFlags);
6227 }
6228 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08006229 }
6230
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006231 /**
6232 * Representation of a full package parsed from APK files on disk. A package
6233 * consists of a single base APK, and zero or more split APKs.
6234 */
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006235 public final static class Package implements Parcelable {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006236
Mathew Inwood1c77a112018-08-14 14:06:26 +01006237 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006238 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006239
Svet Ganov67882122016-12-11 16:36:34 -08006240 // The package name declared in the manifest as the package can be
6241 // renamed, for example static shared libs use synthetic package names.
6242 public String manifestPackageName;
6243
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006244 /** Names of any split APKs, ordered by parsed splitName */
6245 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006246
6247 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07006248
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07006249 public String volumeUuid;
6250
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006251 /**
6252 * Path where this package was found on disk. For monolithic packages
6253 * this is path to single base APK file; for cluster packages this is
6254 * path to the cluster directory.
6255 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006256 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006257
6258 /** Path of base APK */
6259 public String baseCodePath;
6260 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006261 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006262
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006263 /** Revision code of base APK */
6264 public int baseRevisionCode;
6265 /** Revision codes of any split APKs, ordered by parsed splitName */
6266 public int[] splitRevisionCodes;
6267
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006268 /** Flags of any split APKs; ordered by parsed splitName */
6269 public int[] splitFlags;
6270
Alex Klyubinb9f8a522015-02-03 11:12:59 -08006271 /**
6272 * Private flags of any split APKs; ordered by parsed splitName.
6273 *
6274 * {@hide}
6275 */
6276 public int[] splitPrivateFlags;
6277
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006278 public boolean baseHardwareAccelerated;
6279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006280 // For now we only support one application per package.
Mathew Inwood1c77a112018-08-14 14:06:26 +01006281 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006282 public ApplicationInfo applicationInfo = new ApplicationInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006283
Mathew Inwood1c77a112018-08-14 14:06:26 +01006284 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006285 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
Mathew Inwood1c77a112018-08-14 14:06:26 +01006286 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006287 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
Mathew Inwood1c77a112018-08-14 14:06:26 +01006288 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006289 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
Mathew Inwood1c77a112018-08-14 14:06:26 +01006290 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006291 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
Mathew Inwood1c77a112018-08-14 14:06:26 +01006292 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006293 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
Mathew Inwood1c77a112018-08-14 14:06:26 +01006294 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006295 public final ArrayList<Service> services = new ArrayList<Service>(0);
Mathew Inwood1c77a112018-08-14 14:06:26 +01006296 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006297 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
6298
Mathew Inwood1c77a112018-08-14 14:06:26 +01006299 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006300 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
6301
Mathew Inwood1c77a112018-08-14 14:06:26 +01006302 @UnsupportedAppUsage
Dianne Hackborn854060af2009-07-09 18:14:31 -07006303 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006304
Svet Ganov354cd3c2015-12-17 11:35:04 -08006305 public Package parentPackage;
6306 public ArrayList<Package> childPackages;
6307
Svet Ganov67882122016-12-11 16:36:34 -08006308 public String staticSharedLibName = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006309 public long staticSharedLibVersion = 0;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006310 public ArrayList<String> libraryNames = null;
Mathew Inwood1c77a112018-08-14 14:06:26 +01006311 @UnsupportedAppUsage
Dianne Hackborn49237342009-08-27 20:08:01 -07006312 public ArrayList<String> usesLibraries = null;
Svet Ganov67882122016-12-11 16:36:34 -08006313 public ArrayList<String> usesStaticLibraries = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006314 public long[] usesStaticLibrariesVersions = null;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006315 public String[][] usesStaticLibrariesCertDigests = null;
Mathew Inwood1c77a112018-08-14 14:06:26 +01006316 @UnsupportedAppUsage
Dianne Hackborn49237342009-08-27 20:08:01 -07006317 public ArrayList<String> usesOptionalLibraries = null;
Mathew Inwood1c77a112018-08-14 14:06:26 +01006318 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006319 public String[] usesLibraryFiles = null;
Nicolas Geoffray103454f2018-10-22 10:23:50 +01006320 public ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006321
Dianne Hackbornb09491f2013-07-22 15:30:11 -07006322 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
6323
Dianne Hackbornc1552392010-03-03 16:19:01 -08006324 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006325 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006326 public ArrayList<String> mAdoptPermissions = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006328 // We store the application meta-data independently to avoid multiple unwanted references
Mathew Inwood1c77a112018-08-14 14:06:26 +01006329 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006330 public Bundle mAppMetaData = null;
6331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006332 // The version code declared for this package.
Mathew Inwood1c77a112018-08-14 14:06:26 +01006333 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006334 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006335
Dianne Hackborn3accca02013-09-20 09:32:11 -07006336 // The major version code declared for this package.
6337 public int mVersionCodeMajor;
6338
6339 // Return long containing mVersionCode and mVersionCodeMajor.
6340 public long getLongVersionCode() {
6341 return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
6342 }
6343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006344 // The version name declared for this package.
Mathew Inwood1c77a112018-08-14 14:06:26 +01006345 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006346 public String mVersionName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006348 // The shared user id that this package wants to use.
Mathew Inwood1c77a112018-08-14 14:06:26 +01006349 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006350 public String mSharedUserId;
6351
6352 // The shared user label that this package wants to use.
Mathew Inwood1c77a112018-08-14 14:06:26 +01006353 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006354 public int mSharedUserLabel;
6355
6356 // Signatures that were read from the package.
Mathew Inwood1c77a112018-08-14 14:06:26 +01006357 @UnsupportedAppUsage
Patrick Baumann47117fc2017-12-19 10:17:21 -08006358 @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006359
6360 // For use by package manager service for quick lookup of
6361 // preferred up order.
Mathew Inwood1c77a112018-08-14 14:06:26 +01006362 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006363 public int mPreferredOrder = 0;
6364
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006365 // For use by package manager to keep track of when a package was last used.
Brian Carlstromca82e612016-04-19 23:16:08 -07006366 public long[] mLastPackageUsageTimeInMills =
6367 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006368
Amith Yamasani13593602012-03-22 16:16:17 -07006369 // // User set enabled state.
6370 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
6371 //
6372 // // Whether the package has been stopped.
6373 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08006374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006375 // Additional data supplied by callers.
Mathew Inwood1c77a112018-08-14 14:06:26 +01006376 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006377 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07006378
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006379 // Applications hardware preferences
Mathew Inwood1c77a112018-08-14 14:06:26 +01006380 @UnsupportedAppUsage
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006381 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006382
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006383 // Applications requested features
Mathew Inwood1c77a112018-08-14 14:06:26 +01006384 @UnsupportedAppUsage
Dianne Hackborn49237342009-08-27 20:08:01 -07006385 public ArrayList<FeatureInfo> reqFeatures = null;
6386
Adam Lesinskid3edfde2014-08-08 17:32:44 -07006387 // Applications requested feature groups
6388 public ArrayList<FeatureGroupInfo> featureGroups = null;
6389
Mathew Inwood1c77a112018-08-14 14:06:26 +01006390 @UnsupportedAppUsage
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08006391 public int installLocation;
6392
Jeff Hao272bf3a2014-10-08 13:34:43 -07006393 public boolean coreApp;
6394
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08006395 /* An app that's required for all users and cannot be uninstalled for a user */
6396 public boolean mRequiredForAllUsers;
6397
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006398 /* The restricted account authenticator type that is used by this application */
6399 public String mRestrictedAccountType;
6400
Amith Yamasaniccbe3892013-04-12 17:52:42 -07006401 /* The required account type without which this application will not function */
6402 public String mRequiredAccountType;
6403
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006404 public String mOverlayTarget;
Adrian Roosc84df772018-01-19 21:20:22 +01006405 public String mOverlayCategory;
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006406 public int mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -08006407 public boolean mOverlayIsStatic;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006408
Alan Viveretteb6a25732017-11-21 14:49:24 -05006409 public int mCompileSdkVersion;
6410 public String mCompileSdkVersionCodename;
6411
Geremy Condraf1bcca82013-01-07 22:35:24 -08006412 /**
dcashman989eb3712014-06-17 12:56:12 -07006413 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08006414 */
Mathew Inwood1c77a112018-08-14 14:06:26 +01006415 @UnsupportedAppUsage
dcashman989eb3712014-06-17 12:56:12 -07006416 public ArraySet<String> mUpgradeKeySets;
Mathew Inwood1c77a112018-08-14 14:06:26 +01006417 @UnsupportedAppUsage
dcashman989eb3712014-06-17 12:56:12 -07006418 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08006419
Narayan Kamath4903f642014-08-11 13:33:45 +01006420 /**
6421 * The install time abi override for this package, if any.
6422 *
6423 * TODO: This seems like a horrible place to put the abiOverride because
6424 * this isn't something the packageParser parsers. However, this fits in with
6425 * the rest of the PackageManager where package scanning randomly pushes
6426 * and prods fields out of {@code this.applicationInfo}.
6427 */
6428 public String cpuAbiOverride;
Selim Gurun2d291d82016-02-05 17:50:53 -08006429 /**
6430 * The install time abi override to choose 32bit abi's when multiple abi's
6431 * are present. This is only meaningfull for multiarch applications.
6432 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
6433 */
6434 public boolean use32bitAbi;
Narayan Kamath4903f642014-08-11 13:33:45 +01006435
Todd Kennedyfdd241a2016-04-28 12:26:53 -07006436 public byte[] restrictUpdateHash;
6437
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006438 /** Set if the app or any of its components are visible to instant applications. */
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006439 public boolean visibleToInstantApps;
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006440 /** Whether or not the package is a stub and must be replaced by the full version. */
6441 public boolean isStub;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006442
Mathew Inwood1c77a112018-08-14 14:06:26 +01006443 @UnsupportedAppUsage
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006444 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006445 this.packageName = packageName;
Svet Ganov67882122016-12-11 16:36:34 -08006446 this.manifestPackageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006447 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006448 applicationInfo.uid = -1;
6449 }
6450
Svet Ganov354cd3c2015-12-17 11:35:04 -08006451 public void setApplicationVolumeUuid(String volumeUuid) {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006452 final UUID storageUuid = StorageManager.convert(volumeUuid);
Svet Ganov354cd3c2015-12-17 11:35:04 -08006453 this.applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006454 this.applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006455 if (childPackages != null) {
6456 final int packageCount = childPackages.size();
6457 for (int i = 0; i < packageCount; i++) {
6458 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006459 childPackages.get(i).applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006460 }
6461 }
6462 }
6463
6464 public void setApplicationInfoCodePath(String codePath) {
6465 this.applicationInfo.setCodePath(codePath);
6466 if (childPackages != null) {
6467 final int packageCount = childPackages.size();
6468 for (int i = 0; i < packageCount; i++) {
6469 childPackages.get(i).applicationInfo.setCodePath(codePath);
6470 }
6471 }
6472 }
6473
Todd Kennedy30a23a52018-01-04 13:27:49 -08006474 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6475 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006476 public void setApplicationInfoResourcePath(String resourcePath) {
6477 this.applicationInfo.setResourcePath(resourcePath);
6478 if (childPackages != null) {
6479 final int packageCount = childPackages.size();
6480 for (int i = 0; i < packageCount; i++) {
6481 childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
6482 }
6483 }
6484 }
6485
Todd Kennedy30a23a52018-01-04 13:27:49 -08006486 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6487 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006488 public void setApplicationInfoBaseResourcePath(String resourcePath) {
6489 this.applicationInfo.setBaseResourcePath(resourcePath);
6490 if (childPackages != null) {
6491 final int packageCount = childPackages.size();
6492 for (int i = 0; i < packageCount; i++) {
6493 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
6494 }
6495 }
6496 }
6497
6498 public void setApplicationInfoBaseCodePath(String baseCodePath) {
6499 this.applicationInfo.setBaseCodePath(baseCodePath);
6500 if (childPackages != null) {
6501 final int packageCount = childPackages.size();
6502 for (int i = 0; i < packageCount; i++) {
6503 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
6504 }
6505 }
6506 }
6507
Todd Kennedy13715d52016-08-01 13:38:57 -07006508 public List<String> getChildPackageNames() {
6509 if (childPackages == null) {
6510 return null;
6511 }
6512 final int childCount = childPackages.size();
6513 final List<String> childPackageNames = new ArrayList<>(childCount);
6514 for (int i = 0; i < childCount; i++) {
6515 String childPackageName = childPackages.get(i).packageName;
6516 childPackageNames.add(childPackageName);
6517 }
6518 return childPackageNames;
6519 }
6520
Svet Ganov354cd3c2015-12-17 11:35:04 -08006521 public boolean hasChildPackage(String packageName) {
6522 final int childCount = (childPackages != null) ? childPackages.size() : 0;
6523 for (int i = 0; i < childCount; i++) {
6524 if (childPackages.get(i).packageName.equals(packageName)) {
6525 return true;
6526 }
6527 }
6528 return false;
6529 }
6530
6531 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
6532 this.applicationInfo.setSplitCodePaths(splitCodePaths);
6533 // Children have no splits
6534 }
6535
Todd Kennedy30a23a52018-01-04 13:27:49 -08006536 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6537 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006538 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
6539 this.applicationInfo.setSplitResourcePaths(resroucePaths);
6540 // Children have no splits
6541 }
6542
6543 public void setSplitCodePaths(String[] codePaths) {
6544 this.splitCodePaths = codePaths;
6545 }
6546
6547 public void setCodePath(String codePath) {
6548 this.codePath = codePath;
6549 if (childPackages != null) {
6550 final int packageCount = childPackages.size();
6551 for (int i = 0; i < packageCount; i++) {
6552 childPackages.get(i).codePath = codePath;
6553 }
6554 }
6555 }
6556
6557 public void setBaseCodePath(String baseCodePath) {
6558 this.baseCodePath = baseCodePath;
6559 if (childPackages != null) {
6560 final int packageCount = childPackages.size();
6561 for (int i = 0; i < packageCount; i++) {
6562 childPackages.get(i).baseCodePath = baseCodePath;
6563 }
6564 }
6565 }
6566
Patrick Baumann47117fc2017-12-19 10:17:21 -08006567 /** Sets signing details on the package and any of its children. */
6568 public void setSigningDetails(@NonNull SigningDetails signingDetails) {
6569 mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006570 if (childPackages != null) {
6571 final int packageCount = childPackages.size();
6572 for (int i = 0; i < packageCount; i++) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08006573 childPackages.get(i).mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006574 }
6575 }
6576 }
6577
6578 public void setVolumeUuid(String volumeUuid) {
6579 this.volumeUuid = volumeUuid;
6580 if (childPackages != null) {
6581 final int packageCount = childPackages.size();
6582 for (int i = 0; i < packageCount; i++) {
6583 childPackages.get(i).volumeUuid = volumeUuid;
6584 }
6585 }
6586 }
6587
6588 public void setApplicationInfoFlags(int mask, int flags) {
6589 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
6590 if (childPackages != null) {
6591 final int packageCount = childPackages.size();
6592 for (int i = 0; i < packageCount; i++) {
6593 childPackages.get(i).applicationInfo.flags =
6594 (applicationInfo.flags & ~mask) | (mask & flags);
6595 }
6596 }
6597 }
6598
Selim Gurun75827b22016-02-09 10:55:33 -08006599 public void setUse32bitAbi(boolean use32bitAbi) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006600 this.use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006601 if (childPackages != null) {
6602 final int packageCount = childPackages.size();
6603 for (int i = 0; i < packageCount; i++) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006604 childPackages.get(i).use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006605 }
6606 }
6607 }
6608
Svetoslav Ganov40610e32017-06-20 19:35:51 -07006609 public boolean isLibrary() {
6610 return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
6611 }
6612
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006613 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07006614 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006615 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07006616 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6617 Collections.addAll(paths, splitCodePaths);
6618 }
6619 return paths;
6620 }
6621
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006622 /**
6623 * Filtered set of {@link #getAllCodePaths()} that excludes
6624 * resource-only APKs.
6625 */
6626 public List<String> getAllCodePathsExcludingResourceOnly() {
6627 ArrayList<String> paths = new ArrayList<>();
6628 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6629 paths.add(baseCodePath);
6630 }
6631 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6632 for (int i = 0; i < splitCodePaths.length; i++) {
6633 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6634 paths.add(splitCodePaths[i]);
6635 }
6636 }
6637 }
6638 return paths;
6639 }
6640
Mathew Inwood1c77a112018-08-14 14:06:26 +01006641 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006642 public void setPackageName(String newName) {
6643 packageName = newName;
6644 applicationInfo.packageName = newName;
6645 for (int i=permissions.size()-1; i>=0; i--) {
6646 permissions.get(i).setPackageName(newName);
6647 }
6648 for (int i=permissionGroups.size()-1; i>=0; i--) {
6649 permissionGroups.get(i).setPackageName(newName);
6650 }
6651 for (int i=activities.size()-1; i>=0; i--) {
6652 activities.get(i).setPackageName(newName);
6653 }
6654 for (int i=receivers.size()-1; i>=0; i--) {
6655 receivers.get(i).setPackageName(newName);
6656 }
6657 for (int i=providers.size()-1; i>=0; i--) {
6658 providers.get(i).setPackageName(newName);
6659 }
6660 for (int i=services.size()-1; i>=0; i--) {
6661 services.get(i).setPackageName(newName);
6662 }
6663 for (int i=instrumentation.size()-1; i>=0; i--) {
6664 instrumentation.get(i).setPackageName(newName);
6665 }
6666 }
Dianne Hackborn65696252012-03-05 18:49:21 -08006667
6668 public boolean hasComponentClassName(String name) {
6669 for (int i=activities.size()-1; i>=0; i--) {
6670 if (name.equals(activities.get(i).className)) {
6671 return true;
6672 }
6673 }
6674 for (int i=receivers.size()-1; i>=0; i--) {
6675 if (name.equals(receivers.get(i).className)) {
6676 return true;
6677 }
6678 }
6679 for (int i=providers.size()-1; i>=0; i--) {
6680 if (name.equals(providers.get(i).className)) {
6681 return true;
6682 }
6683 }
6684 for (int i=services.size()-1; i>=0; i--) {
6685 if (name.equals(services.get(i).className)) {
6686 return true;
6687 }
6688 }
6689 for (int i=instrumentation.size()-1; i>=0; i--) {
6690 if (name.equals(instrumentation.get(i).className)) {
6691 return true;
6692 }
6693 }
6694 return false;
6695 }
6696
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006697 /** @hide */
6698 public boolean isExternal() {
6699 return applicationInfo.isExternal();
6700 }
6701
6702 /** @hide */
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08006703 public boolean isForwardLocked() {
6704 return applicationInfo.isForwardLocked();
6705 }
6706
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006707 /** @hide */
6708 public boolean isOem() {
6709 return applicationInfo.isOem();
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006710 }
6711
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006712 /** @hide */
Jiyong Park002fdbd2017-02-13 20:50:31 +09006713 public boolean isVendor() {
6714 return applicationInfo.isVendor();
6715 }
6716
6717 /** @hide */
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09006718 public boolean isProduct() {
6719 return applicationInfo.isProduct();
6720 }
6721
6722 /** @hide */
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006723 public boolean isPrivileged() {
Svet Ganovadc1cf42015-06-15 16:36:24 -07006724 return applicationInfo.isPrivilegedApp();
6725 }
6726
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006727 /** @hide */
6728 public boolean isSystem() {
6729 return applicationInfo.isSystemApp();
6730 }
6731
6732 /** @hide */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006733 public boolean isUpdatedSystemApp() {
6734 return applicationInfo.isUpdatedSystemApp();
6735 }
6736
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006737 /** @hide */
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006738 public boolean canHaveOatDir() {
6739 // The following app types CANNOT have oat directory
6740 // - non-updated system apps
6741 // - forward-locked apps or apps installed in ASEC containers
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006742 return (!isSystem() || isUpdatedSystemApp())
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006743 && !isForwardLocked() && !applicationInfo.isExternalAsec();
6744 }
6745
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006746 public boolean isMatch(int flags) {
6747 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006748 return isSystem();
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006749 }
6750 return true;
6751 }
6752
Brian Carlstromca82e612016-04-19 23:16:08 -07006753 public long getLatestPackageUseTimeInMills() {
6754 long latestUse = 0L;
6755 for (long use : mLastPackageUsageTimeInMills) {
6756 latestUse = Math.max(latestUse, use);
6757 }
6758 return latestUse;
6759 }
6760
David Brazdil90e26992016-04-18 14:08:52 +01006761 public long getLatestForegroundPackageUseTimeInMills() {
6762 int[] foregroundReasons = {
6763 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
6764 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
6765 };
6766
6767 long latestUse = 0L;
6768 for (int reason : foregroundReasons) {
6769 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
6770 }
6771 return latestUse;
6772 }
6773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006774 public String toString() {
6775 return "Package{"
6776 + Integer.toHexString(System.identityHashCode(this))
6777 + " " + packageName + "}";
6778 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006779
6780 @Override
6781 public int describeContents() {
6782 return 0;
6783 }
6784
6785 public Package(Parcel dest) {
6786 // We use the boot classloader for all classes that we load.
6787 final ClassLoader boot = Object.class.getClassLoader();
6788
Narayan Kamath07ac1442017-02-10 15:08:07 +00006789 packageName = dest.readString().intern();
Svet Ganov67882122016-12-11 16:36:34 -08006790 manifestPackageName = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006791 splitNames = dest.readStringArray();
6792 volumeUuid = dest.readString();
6793 codePath = dest.readString();
6794 baseCodePath = dest.readString();
6795 splitCodePaths = dest.readStringArray();
6796 baseRevisionCode = dest.readInt();
6797 splitRevisionCodes = dest.createIntArray();
6798 splitFlags = dest.createIntArray();
6799 splitPrivateFlags = dest.createIntArray();
6800 baseHardwareAccelerated = (dest.readInt() == 1);
6801 applicationInfo = dest.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006802 if (applicationInfo.permission != null) {
6803 applicationInfo.permission = applicationInfo.permission.intern();
6804 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006805
6806 // We don't serialize the "owner" package and the application info object for each of
6807 // these components, in order to save space and to avoid circular dependencies while
6808 // serialization. We need to fix them all up here.
6809 dest.readParcelableList(permissions, boot);
6810 fixupOwner(permissions);
6811 dest.readParcelableList(permissionGroups, boot);
6812 fixupOwner(permissionGroups);
6813 dest.readParcelableList(activities, boot);
6814 fixupOwner(activities);
6815 dest.readParcelableList(receivers, boot);
6816 fixupOwner(receivers);
6817 dest.readParcelableList(providers, boot);
6818 fixupOwner(providers);
6819 dest.readParcelableList(services, boot);
6820 fixupOwner(services);
6821 dest.readParcelableList(instrumentation, boot);
6822 fixupOwner(instrumentation);
6823
6824 dest.readStringList(requestedPermissions);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006825 internStringArrayList(requestedPermissions);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006826 protectedBroadcasts = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006827 internStringArrayList(protectedBroadcasts);
6828
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006829 parentPackage = dest.readParcelable(boot);
6830
6831 childPackages = new ArrayList<>();
6832 dest.readParcelableList(childPackages, boot);
6833 if (childPackages.size() == 0) {
6834 childPackages = null;
6835 }
6836
Svet Ganov67882122016-12-11 16:36:34 -08006837 staticSharedLibName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006838 if (staticSharedLibName != null) {
6839 staticSharedLibName = staticSharedLibName.intern();
6840 }
Dianne Hackborn3accca02013-09-20 09:32:11 -07006841 staticSharedLibVersion = dest.readLong();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006842 libraryNames = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006843 internStringArrayList(libraryNames);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006844 usesLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006845 internStringArrayList(usesLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006846 usesOptionalLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006847 internStringArrayList(usesOptionalLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006848 usesLibraryFiles = dest.readStringArray();
6849
Nicolas Geoffray103454f2018-10-22 10:23:50 +01006850 usesLibraryInfos = dest.createTypedArrayList(SharedLibraryInfo.CREATOR);
6851
Svet Ganov67882122016-12-11 16:36:34 -08006852 final int libCount = dest.readInt();
6853 if (libCount > 0) {
6854 usesStaticLibraries = new ArrayList<>(libCount);
6855 dest.readStringList(usesStaticLibraries);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006856 internStringArrayList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006857 usesStaticLibrariesVersions = new long[libCount];
6858 dest.readLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006859 usesStaticLibrariesCertDigests = new String[libCount][];
6860 for (int i = 0; i < libCount; i++) {
6861 usesStaticLibrariesCertDigests[i] = dest.createStringArray();
6862 }
Svet Ganov67882122016-12-11 16:36:34 -08006863 }
6864
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006865 preferredActivityFilters = new ArrayList<>();
6866 dest.readParcelableList(preferredActivityFilters, boot);
6867 if (preferredActivityFilters.size() == 0) {
6868 preferredActivityFilters = null;
6869 }
6870
6871 mOriginalPackages = dest.createStringArrayList();
6872 mRealPackage = dest.readString();
6873 mAdoptPermissions = dest.createStringArrayList();
6874 mAppMetaData = dest.readBundle();
6875 mVersionCode = dest.readInt();
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08006876 mVersionCodeMajor = dest.readInt();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006877 mVersionName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006878 if (mVersionName != null) {
6879 mVersionName = mVersionName.intern();
6880 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006881 mSharedUserId = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006882 if (mSharedUserId != null) {
6883 mSharedUserId = mSharedUserId.intern();
6884 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006885 mSharedUserLabel = dest.readInt();
6886
Patrick Baumann47117fc2017-12-19 10:17:21 -08006887 mSigningDetails = dest.readParcelable(boot);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006888
6889 mPreferredOrder = dest.readInt();
6890
6891 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6892 // is parsed from the APK.
6893
6894 // Object mExtras is not persisted because it is not information that is read from
6895 // the APK, rather, it is supplied by callers.
6896
6897
6898 configPreferences = new ArrayList<>();
6899 dest.readParcelableList(configPreferences, boot);
6900 if (configPreferences.size() == 0) {
6901 configPreferences = null;
6902 }
6903
6904 reqFeatures = new ArrayList<>();
6905 dest.readParcelableList(reqFeatures, boot);
6906 if (reqFeatures.size() == 0) {
6907 reqFeatures = null;
6908 }
6909
6910 featureGroups = new ArrayList<>();
6911 dest.readParcelableList(featureGroups, boot);
6912 if (featureGroups.size() == 0) {
6913 featureGroups = null;
6914 }
6915
6916 installLocation = dest.readInt();
6917 coreApp = (dest.readInt() == 1);
6918 mRequiredForAllUsers = (dest.readInt() == 1);
6919 mRestrictedAccountType = dest.readString();
6920 mRequiredAccountType = dest.readString();
6921 mOverlayTarget = dest.readString();
Adrian Roosc84df772018-01-19 21:20:22 +01006922 mOverlayCategory = dest.readString();
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006923 mOverlayPriority = dest.readInt();
Adam Lesinskie7334972018-01-17 16:13:52 -08006924 mOverlayIsStatic = (dest.readInt() == 1);
Alan Viveretteb6a25732017-11-21 14:49:24 -05006925 mCompileSdkVersion = dest.readInt();
6926 mCompileSdkVersionCodename = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006927 mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
6928
6929 mKeySetMapping = readKeySetMapping(dest);
6930
6931 cpuAbiOverride = dest.readString();
6932 use32bitAbi = (dest.readInt() == 1);
6933 restrictUpdateHash = dest.createByteArray();
Chad Brubaker49f24c62017-04-05 13:08:21 -07006934 visibleToInstantApps = dest.readInt() == 1;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006935 }
6936
Narayan Kamath07ac1442017-02-10 15:08:07 +00006937 private static void internStringArrayList(List<String> list) {
6938 if (list != null) {
6939 final int N = list.size();
6940 for (int i = 0; i < N; ++i) {
6941 list.set(i, list.get(i).intern());
6942 }
6943 }
6944 }
6945
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006946 /**
6947 * Sets the package owner and the the {@code applicationInfo} for every component
6948 * owner by this package.
6949 */
6950 private void fixupOwner(List<? extends Component<?>> list) {
6951 if (list != null) {
6952 for (Component<?> c : list) {
6953 c.owner = this;
6954 if (c instanceof Activity) {
6955 ((Activity) c).info.applicationInfo = this.applicationInfo;
6956 } else if (c instanceof Service) {
6957 ((Service) c).info.applicationInfo = this.applicationInfo;
6958 } else if (c instanceof Provider) {
6959 ((Provider) c).info.applicationInfo = this.applicationInfo;
6960 }
6961 }
6962 }
6963 }
6964
6965 @Override
6966 public void writeToParcel(Parcel dest, int flags) {
6967 dest.writeString(packageName);
Svet Ganov67882122016-12-11 16:36:34 -08006968 dest.writeString(manifestPackageName);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006969 dest.writeStringArray(splitNames);
6970 dest.writeString(volumeUuid);
6971 dest.writeString(codePath);
6972 dest.writeString(baseCodePath);
6973 dest.writeStringArray(splitCodePaths);
6974 dest.writeInt(baseRevisionCode);
6975 dest.writeIntArray(splitRevisionCodes);
6976 dest.writeIntArray(splitFlags);
6977 dest.writeIntArray(splitPrivateFlags);
6978 dest.writeInt(baseHardwareAccelerated ? 1 : 0);
6979 dest.writeParcelable(applicationInfo, flags);
6980
6981 dest.writeParcelableList(permissions, flags);
6982 dest.writeParcelableList(permissionGroups, flags);
6983 dest.writeParcelableList(activities, flags);
6984 dest.writeParcelableList(receivers, flags);
6985 dest.writeParcelableList(providers, flags);
6986 dest.writeParcelableList(services, flags);
6987 dest.writeParcelableList(instrumentation, flags);
6988
6989 dest.writeStringList(requestedPermissions);
6990 dest.writeStringList(protectedBroadcasts);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07006991
6992 // TODO: This doesn't work: b/64295061
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006993 dest.writeParcelable(parentPackage, flags);
6994 dest.writeParcelableList(childPackages, flags);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07006995
Svet Ganov67882122016-12-11 16:36:34 -08006996 dest.writeString(staticSharedLibName);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006997 dest.writeLong(staticSharedLibVersion);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006998 dest.writeStringList(libraryNames);
6999 dest.writeStringList(usesLibraries);
7000 dest.writeStringList(usesOptionalLibraries);
7001 dest.writeStringArray(usesLibraryFiles);
Nicolas Geoffray103454f2018-10-22 10:23:50 +01007002 dest.writeTypedList(usesLibraryInfos);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007003
Svet Ganov67882122016-12-11 16:36:34 -08007004 if (ArrayUtils.isEmpty(usesStaticLibraries)) {
7005 dest.writeInt(-1);
7006 } else {
7007 dest.writeInt(usesStaticLibraries.size());
7008 dest.writeStringList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07007009 dest.writeLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07007010 for (String[] usesStaticLibrariesCertDigest : usesStaticLibrariesCertDigests) {
7011 dest.writeStringArray(usesStaticLibrariesCertDigest);
7012 }
Svet Ganov67882122016-12-11 16:36:34 -08007013 }
7014
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007015 dest.writeParcelableList(preferredActivityFilters, flags);
7016
7017 dest.writeStringList(mOriginalPackages);
7018 dest.writeString(mRealPackage);
7019 dest.writeStringList(mAdoptPermissions);
7020 dest.writeBundle(mAppMetaData);
7021 dest.writeInt(mVersionCode);
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08007022 dest.writeInt(mVersionCodeMajor);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007023 dest.writeString(mVersionName);
7024 dest.writeString(mSharedUserId);
7025 dest.writeInt(mSharedUserLabel);
7026
Patrick Baumann47117fc2017-12-19 10:17:21 -08007027 dest.writeParcelable(mSigningDetails, flags);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007028
7029 dest.writeInt(mPreferredOrder);
7030
7031 // long[] packageUsageTimeMillis is not persisted because it isn't information that
7032 // is parsed from the APK.
7033
7034 // Object mExtras is not persisted because it is not information that is read from
7035 // the APK, rather, it is supplied by callers.
7036
7037 dest.writeParcelableList(configPreferences, flags);
7038 dest.writeParcelableList(reqFeatures, flags);
7039 dest.writeParcelableList(featureGroups, flags);
7040
7041 dest.writeInt(installLocation);
7042 dest.writeInt(coreApp ? 1 : 0);
7043 dest.writeInt(mRequiredForAllUsers ? 1 : 0);
7044 dest.writeString(mRestrictedAccountType);
7045 dest.writeString(mRequiredAccountType);
7046 dest.writeString(mOverlayTarget);
Adrian Roosc84df772018-01-19 21:20:22 +01007047 dest.writeString(mOverlayCategory);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09007048 dest.writeInt(mOverlayPriority);
Adam Lesinskie7334972018-01-17 16:13:52 -08007049 dest.writeInt(mOverlayIsStatic ? 1 : 0);
Alan Viveretteb6a25732017-11-21 14:49:24 -05007050 dest.writeInt(mCompileSdkVersion);
7051 dest.writeString(mCompileSdkVersionCodename);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007052 dest.writeArraySet(mUpgradeKeySets);
7053 writeKeySetMapping(dest, mKeySetMapping);
7054 dest.writeString(cpuAbiOverride);
7055 dest.writeInt(use32bitAbi ? 1 : 0);
7056 dest.writeByteArray(restrictUpdateHash);
Chad Brubaker49f24c62017-04-05 13:08:21 -07007057 dest.writeInt(visibleToInstantApps ? 1 : 0);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007058 }
7059
7060
7061 /**
7062 * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
7063 */
7064 private static void writeKeySetMapping(
7065 Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
7066 if (keySetMapping == null) {
7067 dest.writeInt(-1);
7068 return;
7069 }
7070
7071 final int N = keySetMapping.size();
7072 dest.writeInt(N);
7073
7074 for (int i = 0; i < N; i++) {
7075 dest.writeString(keySetMapping.keyAt(i));
7076 ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
7077 if (keys == null) {
7078 dest.writeInt(-1);
7079 continue;
7080 }
7081
7082 final int M = keys.size();
7083 dest.writeInt(M);
7084 for (int j = 0; j < M; j++) {
7085 dest.writeSerializable(keys.valueAt(j));
7086 }
7087 }
7088 }
7089
7090 /**
7091 * Reads a keyset mapping from the given parcel at the given data position. May return
7092 * {@code null} if the serialized mapping was {@code null}.
7093 */
7094 private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
7095 final int N = in.readInt();
7096 if (N == -1) {
7097 return null;
7098 }
7099
7100 ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
7101 for (int i = 0; i < N; ++i) {
7102 String key = in.readString();
7103 final int M = in.readInt();
7104 if (M == -1) {
7105 keySetMapping.put(key, null);
7106 continue;
7107 }
7108
7109 ArraySet<PublicKey> keys = new ArraySet<>(M);
7110 for (int j = 0; j < M; ++j) {
7111 PublicKey pk = (PublicKey) in.readSerializable();
7112 keys.add(pk);
7113 }
7114
7115 keySetMapping.put(key, keys);
7116 }
7117
7118 return keySetMapping;
7119 }
7120
7121 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
7122 public Package createFromParcel(Parcel in) {
7123 return new Package(in);
7124 }
7125
7126 public Package[] newArray(int size) {
7127 return new Package[size];
7128 }
7129 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007130 }
7131
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007132 public static abstract class Component<II extends IntentInfo> {
Mathew Inwood1c77a112018-08-14 14:06:26 +01007133 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007134 public final ArrayList<II> intents;
Mathew Inwood1c77a112018-08-14 14:06:26 +01007135 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007136 public final String className;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007137
Mathew Inwood1c77a112018-08-14 14:06:26 +01007138 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007139 public Bundle metaData;
Mathew Inwood1c77a112018-08-14 14:06:26 +01007140 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007141 public Package owner;
Todd Kennedy6d418b62018-02-22 14:15:18 -08007142 /** The order of this component in relation to its peers */
7143 public int order;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007144
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007145 ComponentName componentName;
7146 String componentShortName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007148 public Component(Package _owner) {
7149 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007150 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007151 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007152 }
7153
7154 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
7155 owner = args.owner;
7156 intents = new ArrayList<II>(0);
Todd Kennedybb8a42d2016-06-02 14:13:56 -07007157 if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
7158 true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
7159 args.roundIconRes, args.logoRes, args.bannerRes)) {
7160 className = outInfo.name;
7161 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007162 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007163 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007164 }
7165
7166 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
7167 this(args, (PackageItemInfo)outInfo);
7168 if (args.outError[0] != null) {
7169 return;
7170 }
7171
7172 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007173 CharSequence pname;
7174 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07007175 pname = args.sa.getNonConfigurationString(args.processRes,
7176 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007177 } else {
7178 // Some older apps have been seen to use a resource reference
7179 // here that on older builds was ignored (with a warning). We
7180 // need to continue to do this for them so they don't break.
7181 pname = args.sa.getNonResourceString(args.processRes);
7182 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007183 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007184 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007185 args.flags, args.sepProcesses, args.outError);
7186 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007187
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08007188 if (args.descriptionRes != 0) {
7189 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
7190 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007191
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007192 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007193 }
7194
7195 public Component(Component<II> clone) {
7196 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007197 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007198 className = clone.className;
7199 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007200 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007201 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007202
Mathew Inwood1c77a112018-08-14 14:06:26 +01007203 @UnsupportedAppUsage
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007204 public ComponentName getComponentName() {
7205 if (componentName != null) {
7206 return componentName;
7207 }
7208 if (className != null) {
7209 componentName = new ComponentName(owner.applicationInfo.packageName,
7210 className);
7211 }
7212 return componentName;
7213 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007214
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007215 protected Component(Parcel in) {
7216 className = in.readString();
7217 metaData = in.readBundle();
7218 intents = createIntentsList(in);
7219
7220 owner = null;
7221 }
7222
7223 protected void writeToParcel(Parcel dest, int flags) {
7224 dest.writeString(className);
7225 dest.writeBundle(metaData);
7226
7227 writeIntentsList(intents, dest, flags);
7228 }
7229
7230 /**
7231 * <p>
7232 * Implementation note: The serialized form for the intent list also contains the name
7233 * of the concrete class that's stored in the list, and assumes that every element of the
7234 * list is of the same type. This is very similar to the original parcelable mechanism.
7235 * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
7236 * and is public API. It also declares Parcelable related methods as final which means
7237 * we can't extend them. The approach of using composition instead of inheritance leads to
7238 * a large set of cascading changes in the PackageManagerService, which seem undesirable.
7239 *
7240 * <p>
7241 * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
7242 * to make sure their owner fields are consistent. See {@code fixupOwner}.
7243 */
7244 private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out,
7245 int flags) {
7246 if (list == null) {
7247 out.writeInt(-1);
7248 return;
7249 }
7250
7251 final int N = list.size();
7252 out.writeInt(N);
7253
7254 // Don't bother writing the component name if the list is empty.
7255 if (N > 0) {
7256 IntentInfo info = list.get(0);
7257 out.writeString(info.getClass().getName());
7258
7259 for (int i = 0; i < N;i++) {
7260 list.get(i).writeIntentInfoToParcel(out, flags);
7261 }
7262 }
7263 }
7264
7265 private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) {
7266 int N = in.readInt();
7267 if (N == -1) {
7268 return null;
7269 }
7270
7271 if (N == 0) {
7272 return new ArrayList<>(0);
7273 }
7274
7275 String componentName = in.readString();
7276 final ArrayList<T> intentsList;
7277 try {
7278 final Class<T> cls = (Class<T>) Class.forName(componentName);
7279 final Constructor<T> cons = cls.getConstructor(Parcel.class);
7280
7281 intentsList = new ArrayList<>(N);
7282 for (int i = 0; i < N; ++i) {
7283 intentsList.add(cons.newInstance(in));
7284 }
7285 } catch (ReflectiveOperationException ree) {
7286 throw new AssertionError("Unable to construct intent list for: " + componentName);
7287 }
7288
7289 return intentsList;
7290 }
7291
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007292 public void appendComponentShortName(StringBuilder sb) {
7293 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007294 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007295
7296 public void printComponentShortName(PrintWriter pw) {
7297 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
7298 }
7299
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007300 public void setPackageName(String packageName) {
7301 componentName = null;
7302 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007303 }
7304 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007305
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007306 public final static class Permission extends Component<IntentInfo> implements Parcelable {
Mathew Inwood1c77a112018-08-14 14:06:26 +01007307 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308 public final PermissionInfo info;
Mathew Inwood1c77a112018-08-14 14:06:26 +01007309 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007310 public boolean tree;
Mathew Inwood1c77a112018-08-14 14:06:26 +01007311 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007312 public PermissionGroup group;
7313
7314 public Permission(Package _owner) {
7315 super(_owner);
7316 info = new PermissionInfo();
7317 }
7318
Mathew Inwood1c77a112018-08-14 14:06:26 +01007319 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007320 public Permission(Package _owner, PermissionInfo _info) {
7321 super(_owner);
7322 info = _info;
7323 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007324
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007325 public void setPackageName(String packageName) {
7326 super.setPackageName(packageName);
7327 info.packageName = packageName;
7328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329
7330 public String toString() {
7331 return "Permission{"
7332 + Integer.toHexString(System.identityHashCode(this))
7333 + " " + info.name + "}";
7334 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007335
7336 @Override
7337 public int describeContents() {
7338 return 0;
7339 }
7340
7341 @Override
7342 public void writeToParcel(Parcel dest, int flags) {
7343 super.writeToParcel(dest, flags);
7344 dest.writeParcelable(info, flags);
7345 dest.writeInt(tree ? 1 : 0);
7346 dest.writeParcelable(group, flags);
7347 }
7348
Todd Kennedyc8423932017-10-05 08:58:36 -07007349 /** @hide */
7350 public boolean isAppOp() {
7351 return info.isAppOp();
7352 }
7353
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007354 private Permission(Parcel in) {
7355 super(in);
7356 final ClassLoader boot = Object.class.getClassLoader();
7357 info = in.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007358 if (info.group != null) {
7359 info.group = info.group.intern();
7360 }
7361
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007362 tree = (in.readInt() == 1);
7363 group = in.readParcelable(boot);
7364 }
7365
7366 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
7367 public Permission createFromParcel(Parcel in) {
7368 return new Permission(in);
7369 }
7370
7371 public Permission[] newArray(int size) {
7372 return new Permission[size];
7373 }
7374 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007375 }
7376
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007377 public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
Mathew Inwood1c77a112018-08-14 14:06:26 +01007378 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007379 public final PermissionGroupInfo info;
7380
7381 public PermissionGroup(Package _owner) {
7382 super(_owner);
7383 info = new PermissionGroupInfo();
7384 }
7385
7386 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
7387 super(_owner);
7388 info = _info;
7389 }
7390
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007391 public void setPackageName(String packageName) {
7392 super.setPackageName(packageName);
7393 info.packageName = packageName;
7394 }
7395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007396 public String toString() {
7397 return "PermissionGroup{"
7398 + Integer.toHexString(System.identityHashCode(this))
7399 + " " + info.name + "}";
7400 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007401
7402 @Override
7403 public int describeContents() {
7404 return 0;
7405 }
7406
7407 @Override
7408 public void writeToParcel(Parcel dest, int flags) {
7409 super.writeToParcel(dest, flags);
7410 dest.writeParcelable(info, flags);
7411 }
7412
7413 private PermissionGroup(Parcel in) {
7414 super(in);
7415 info = in.readParcelable(Object.class.getClassLoader());
7416 }
7417
7418 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
7419 public PermissionGroup createFromParcel(Parcel in) {
7420 return new PermissionGroup(in);
7421 }
7422
7423 public PermissionGroup[] newArray(int size) {
7424 return new PermissionGroup[size];
7425 }
7426 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 }
7428
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007429 private static boolean copyNeeded(int flags, Package p,
7430 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07007431 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007432 // We always need to copy for other users, since we need
7433 // to fix up the uid.
7434 return true;
7435 }
7436 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
7437 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07007438 if (p.applicationInfo.enabled != enabled) {
7439 return true;
7440 }
7441 }
Rubin Xubf67c9c2016-04-20 17:09:38 +01007442 boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
7443 if (state.suspended != suspended) {
7444 return true;
7445 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007446 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007447 return true;
7448 }
7449 if (state.stopped) {
7450 return true;
7451 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007452 if (state.instantApp != p.applicationInfo.isInstantApp()) {
7453 return true;
7454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007455 if ((flags & PackageManager.GET_META_DATA) != 0
7456 && (metaData != null || p.mAppMetaData != null)) {
7457 return true;
7458 }
7459 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7460 && p.usesLibraryFiles != null) {
7461 return true;
7462 }
Nicolas Geoffray103454f2018-10-22 10:23:50 +01007463 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7464 && p.usesLibraryInfos != null) {
7465 return true;
7466 }
Svet Ganov67882122016-12-11 16:36:34 -08007467 if (p.staticSharedLibName != null) {
7468 return true;
7469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007470 return false;
7471 }
7472
Mathew Inwood1c77a112018-08-14 14:06:26 +01007473 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007474 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
7475 PackageUserState state) {
7476 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07007477 }
7478
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007479 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
7480 PackageUserState state) {
7481 // CompatibilityMode is global state.
7482 if (!sCompatibilityModeEnabled) {
7483 ai.disableCompatibilityMode();
7484 }
7485 if (state.installed) {
7486 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
7487 } else {
7488 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
7489 }
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00007490 if (state.suspended) {
7491 ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
7492 } else {
7493 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
7494 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007495 if (state.instantApp) {
7496 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
7497 } else {
7498 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
7499 }
Todd Kennedy5eb5a7d2017-08-01 07:42:47 -07007500 if (state.virtualPreload) {
7501 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7502 } else {
7503 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7504 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007505 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007506 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007507 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007508 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007509 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007510 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
7511 ai.enabled = true;
7512 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
7513 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
7514 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
7515 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
7516 ai.enabled = false;
7517 }
7518 ai.enabledSetting = state.enabled;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07007519 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7520 ai.category = state.categoryHint;
7521 }
Jeff Sharkey0078e1b2017-01-11 16:05:27 -07007522 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7523 ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
7524 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007525 ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
Todd Kennedyb2749472017-06-13 08:24:32 -07007526 ai.resourceDirs = state.overlayPaths;
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007527 }
7528
Mathew Inwood1c77a112018-08-14 14:06:26 +01007529 @UnsupportedAppUsage
Amith Yamasani13593602012-03-22 16:16:17 -07007530 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007531 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007532 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007533 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007534 return null;
7535 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007536 if (!copyNeeded(flags, p, state, null, userId)
7537 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
7538 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
7539 // In this case it is safe to directly modify the internal ApplicationInfo state:
7540 // - CompatibilityMode is global state, so will be the same for every call.
7541 // - We only come in to here if the app should reported as installed; this is the
7542 // default state, and we will do a copy otherwise.
7543 // - The enable state will always be reported the same for the application across
7544 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
7545 // be doing a copy.
7546 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007547 return p.applicationInfo;
7548 }
7549
7550 // Make shallow copy so we can store the metadata/libraries safely
7551 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Jeff Sharkey15447792015-11-05 16:18:51 -08007552 ai.initForUser(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007553 if ((flags & PackageManager.GET_META_DATA) != 0) {
7554 ai.metaData = p.mAppMetaData;
7555 }
7556 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
7557 ai.sharedLibraryFiles = p.usesLibraryFiles;
Nicolas Geoffray972b39e2018-11-15 12:59:52 +00007558 ai.sharedLibraryInfos = p.usesLibraryInfos;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007559 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007560 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007561 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007562 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007563 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007564 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007565 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007566 return ai;
7567 }
7568
Dianne Hackbornace27912014-09-18 18:38:30 -07007569 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
7570 PackageUserState state, int userId) {
7571 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007572 if (!checkUseInstalledOrHidden(flags, state, ai)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007573 return null;
7574 }
7575 // This is only used to return the ResolverActivity; we will just always
7576 // make a copy.
7577 ai = new ApplicationInfo(ai);
Jeff Sharkey15447792015-11-05 16:18:51 -08007578 ai.initForUser(userId);
Dianne Hackbornace27912014-09-18 18:38:30 -07007579 if (state.stopped) {
7580 ai.flags |= ApplicationInfo.FLAG_STOPPED;
7581 } else {
7582 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
7583 }
7584 updateApplicationInfo(ai, flags, state);
7585 return ai;
7586 }
7587
Mathew Inwood1c77a112018-08-14 14:06:26 +01007588 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007589 public static final PermissionInfo generatePermissionInfo(
7590 Permission p, int flags) {
7591 if (p == null) return null;
7592 if ((flags&PackageManager.GET_META_DATA) == 0) {
7593 return p.info;
7594 }
7595 PermissionInfo pi = new PermissionInfo(p.info);
7596 pi.metaData = p.metaData;
7597 return pi;
7598 }
7599
Mathew Inwood1c77a112018-08-14 14:06:26 +01007600 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007601 public static final PermissionGroupInfo generatePermissionGroupInfo(
7602 PermissionGroup pg, int flags) {
7603 if (pg == null) return null;
7604 if ((flags&PackageManager.GET_META_DATA) == 0) {
7605 return pg.info;
7606 }
7607 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
7608 pgi.metaData = pg.metaData;
7609 return pgi;
7610 }
7611
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007612 public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
Mathew Inwood1c77a112018-08-14 14:06:26 +01007613 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007614 public final ActivityInfo info;
Bryce Lee22571db2017-07-07 15:54:18 -07007615 private boolean mHasMaxAspectRatio;
7616
7617 private boolean hasMaxAspectRatio() {
7618 return mHasMaxAspectRatio;
7619 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007620
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007621 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
7622 super(args, _info);
7623 info = _info;
7624 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007625 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007626
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007627 public void setPackageName(String packageName) {
7628 super.setPackageName(packageName);
7629 info.packageName = packageName;
7630 }
7631
Bryce Lee22571db2017-07-07 15:54:18 -07007632
7633 private void setMaxAspectRatio(float maxAspectRatio) {
7634 if (info.resizeMode == RESIZE_MODE_RESIZEABLE
7635 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
7636 // Resizeable activities can be put in any aspect ratio.
7637 return;
7638 }
7639
7640 if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
7641 // Ignore any value lesser than 1.0.
7642 return;
7643 }
7644
7645 info.maxAspectRatio = maxAspectRatio;
7646 mHasMaxAspectRatio = true;
7647 }
7648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007649 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007650 StringBuilder sb = new StringBuilder(128);
7651 sb.append("Activity{");
7652 sb.append(Integer.toHexString(System.identityHashCode(this)));
7653 sb.append(' ');
7654 appendComponentShortName(sb);
7655 sb.append('}');
7656 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007657 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007658
7659 @Override
7660 public int describeContents() {
7661 return 0;
7662 }
7663
7664 @Override
7665 public void writeToParcel(Parcel dest, int flags) {
7666 super.writeToParcel(dest, flags);
7667 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
Bryce Lee22571db2017-07-07 15:54:18 -07007668 dest.writeBoolean(mHasMaxAspectRatio);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007669 }
7670
7671 private Activity(Parcel in) {
7672 super(in);
7673 info = in.readParcelable(Object.class.getClassLoader());
Bryce Lee22571db2017-07-07 15:54:18 -07007674 mHasMaxAspectRatio = in.readBoolean();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007675
7676 for (ActivityIntentInfo aii : intents) {
7677 aii.activity = this;
Todd Kennedy6d418b62018-02-22 14:15:18 -08007678 order = Math.max(aii.getOrder(), order);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007679 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007680
7681 if (info.permission != null) {
7682 info.permission = info.permission.intern();
7683 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007684 }
7685
7686 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
7687 public Activity createFromParcel(Parcel in) {
7688 return new Activity(in);
7689 }
7690
7691 public Activity[] newArray(int size) {
7692 return new Activity[size];
7693 }
7694 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007695 }
7696
Mathew Inwood1c77a112018-08-14 14:06:26 +01007697 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007698 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
7699 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007700 if (a == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007701 if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007702 return null;
7703 }
7704 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007705 updateApplicationInfo(a.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007706 return a.info;
7707 }
7708 // Make shallow copies so we can store the metadata safely
7709 ActivityInfo ai = new ActivityInfo(a.info);
7710 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007711 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007712 return ai;
7713 }
7714
Dianne Hackbornace27912014-09-18 18:38:30 -07007715 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
7716 PackageUserState state, int userId) {
7717 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007718 if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007719 return null;
7720 }
7721 // This is only used to return the ResolverActivity; we will just always
7722 // make a copy.
7723 ai = new ActivityInfo(ai);
7724 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
7725 return ai;
7726 }
7727
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007728 public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
Mathew Inwood1c77a112018-08-14 14:06:26 +01007729 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007730 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007731
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007732 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
7733 super(args, _info);
7734 info = _info;
7735 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007736 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007737
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007738 public void setPackageName(String packageName) {
7739 super.setPackageName(packageName);
7740 info.packageName = packageName;
7741 }
7742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007743 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007744 StringBuilder sb = new StringBuilder(128);
7745 sb.append("Service{");
7746 sb.append(Integer.toHexString(System.identityHashCode(this)));
7747 sb.append(' ');
7748 appendComponentShortName(sb);
7749 sb.append('}');
7750 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007751 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007752
7753 @Override
7754 public int describeContents() {
7755 return 0;
7756 }
7757
7758 @Override
7759 public void writeToParcel(Parcel dest, int flags) {
7760 super.writeToParcel(dest, flags);
7761 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7762 }
7763
7764 private Service(Parcel in) {
7765 super(in);
7766 info = in.readParcelable(Object.class.getClassLoader());
7767
7768 for (ServiceIntentInfo aii : intents) {
7769 aii.service = this;
Todd Kennedy6d418b62018-02-22 14:15:18 -08007770 order = Math.max(aii.getOrder(), order);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007771 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007772
7773 if (info.permission != null) {
7774 info.permission = info.permission.intern();
7775 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007776 }
7777
7778 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
7779 public Service createFromParcel(Parcel in) {
7780 return new Service(in);
7781 }
7782
7783 public Service[] newArray(int size) {
7784 return new Service[size];
7785 }
7786 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007787 }
7788
Mathew Inwood1c77a112018-08-14 14:06:26 +01007789 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007790 public static final ServiceInfo generateServiceInfo(Service s, int flags,
7791 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792 if (s == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007793 if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007794 return null;
7795 }
7796 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007797 updateApplicationInfo(s.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007798 return s.info;
7799 }
7800 // Make shallow copies so we can store the metadata safely
7801 ServiceInfo si = new ServiceInfo(s.info);
7802 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007803 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007804 return si;
7805 }
7806
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007807 public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
Mathew Inwood1c77a112018-08-14 14:06:26 +01007808 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007809 public final ProviderInfo info;
Mathew Inwood1c77a112018-08-14 14:06:26 +01007810 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007811 public boolean syncable;
7812
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007813 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
7814 super(args, _info);
7815 info = _info;
7816 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007817 syncable = false;
7818 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007819
Mathew Inwood1c77a112018-08-14 14:06:26 +01007820 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007821 public Provider(Provider existingProvider) {
7822 super(existingProvider);
7823 this.info = existingProvider.info;
7824 this.syncable = existingProvider.syncable;
7825 }
7826
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007827 public void setPackageName(String packageName) {
7828 super.setPackageName(packageName);
7829 info.packageName = packageName;
7830 }
7831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007832 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007833 StringBuilder sb = new StringBuilder(128);
7834 sb.append("Provider{");
7835 sb.append(Integer.toHexString(System.identityHashCode(this)));
7836 sb.append(' ');
7837 appendComponentShortName(sb);
7838 sb.append('}');
7839 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007840 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007841
7842 @Override
7843 public int describeContents() {
7844 return 0;
7845 }
7846
7847 @Override
7848 public void writeToParcel(Parcel dest, int flags) {
7849 super.writeToParcel(dest, flags);
7850 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7851 dest.writeInt((syncable) ? 1 : 0);
7852 }
7853
7854 private Provider(Parcel in) {
7855 super(in);
7856 info = in.readParcelable(Object.class.getClassLoader());
7857 syncable = (in.readInt() == 1);
7858
7859 for (ProviderIntentInfo aii : intents) {
7860 aii.provider = this;
7861 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007862
7863 if (info.readPermission != null) {
7864 info.readPermission = info.readPermission.intern();
7865 }
7866
7867 if (info.writePermission != null) {
7868 info.writePermission = info.writePermission.intern();
7869 }
7870
7871 if (info.authority != null) {
7872 info.authority = info.authority.intern();
7873 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007874 }
7875
7876 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
7877 public Provider createFromParcel(Parcel in) {
7878 return new Provider(in);
7879 }
7880
7881 public Provider[] newArray(int size) {
7882 return new Provider[size];
7883 }
7884 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007885 }
7886
Mathew Inwood1c77a112018-08-14 14:06:26 +01007887 @UnsupportedAppUsage
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007888 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
7889 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007891 if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007892 return null;
7893 }
7894 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007895 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007896 || p.info.uriPermissionPatterns == null)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007897 updateApplicationInfo(p.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007898 return p.info;
7899 }
7900 // Make shallow copies so we can store the metadata safely
7901 ProviderInfo pi = new ProviderInfo(p.info);
7902 pi.metaData = p.metaData;
7903 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
7904 pi.uriPermissionPatterns = null;
7905 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007906 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007907 return pi;
7908 }
7909
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007910 public final static class Instrumentation extends Component<IntentInfo> implements
7911 Parcelable {
Mathew Inwood1c77a112018-08-14 14:06:26 +01007912 @UnsupportedAppUsage
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007913 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007914
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007915 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
7916 super(args, _info);
7917 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007918 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007919
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007920 public void setPackageName(String packageName) {
7921 super.setPackageName(packageName);
7922 info.packageName = packageName;
7923 }
7924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007925 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007926 StringBuilder sb = new StringBuilder(128);
7927 sb.append("Instrumentation{");
7928 sb.append(Integer.toHexString(System.identityHashCode(this)));
7929 sb.append(' ');
7930 appendComponentShortName(sb);
7931 sb.append('}');
7932 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007933 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007934
7935 @Override
7936 public int describeContents() {
7937 return 0;
7938 }
7939
7940 @Override
7941 public void writeToParcel(Parcel dest, int flags) {
7942 super.writeToParcel(dest, flags);
7943 dest.writeParcelable(info, flags);
7944 }
7945
7946 private Instrumentation(Parcel in) {
7947 super(in);
7948 info = in.readParcelable(Object.class.getClassLoader());
Narayan Kamath07ac1442017-02-10 15:08:07 +00007949
7950 if (info.targetPackage != null) {
7951 info.targetPackage = info.targetPackage.intern();
7952 }
7953
Dianne Hackborn1be53542017-04-28 13:36:00 -07007954 if (info.targetProcesses != null) {
7955 info.targetProcesses = info.targetProcesses.intern();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007956 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007957 }
7958
7959 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
7960 public Instrumentation createFromParcel(Parcel in) {
7961 return new Instrumentation(in);
7962 }
7963
7964 public Instrumentation[] newArray(int size) {
7965 return new Instrumentation[size];
7966 }
7967 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007968 }
7969
Mathew Inwood1c77a112018-08-14 14:06:26 +01007970 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007971 public static final InstrumentationInfo generateInstrumentationInfo(
7972 Instrumentation i, int flags) {
7973 if (i == null) return null;
7974 if ((flags&PackageManager.GET_META_DATA) == 0) {
7975 return i.info;
7976 }
7977 InstrumentationInfo ii = new InstrumentationInfo(i.info);
7978 ii.metaData = i.metaData;
7979 return ii;
7980 }
7981
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007982 public static abstract class IntentInfo extends IntentFilter {
Mathew Inwood1c77a112018-08-14 14:06:26 +01007983 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007984 public boolean hasDefault;
Mathew Inwood1c77a112018-08-14 14:06:26 +01007985 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007986 public int labelRes;
Mathew Inwood1c77a112018-08-14 14:06:26 +01007987 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007988 public CharSequence nonLocalizedLabel;
Mathew Inwood1c77a112018-08-14 14:06:26 +01007989 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007990 public int icon;
Mathew Inwood1c77a112018-08-14 14:06:26 +01007991 @UnsupportedAppUsage
Adam Powell81cd2e92010-04-21 16:35:18 -07007992 public int logo;
Mathew Inwood1c77a112018-08-14 14:06:26 +01007993 @UnsupportedAppUsage
Jose Limaf78e3122014-03-06 12:13:15 -08007994 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07007995 public int preferred;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007996
Mathew Inwood1c77a112018-08-14 14:06:26 +01007997 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007998 protected IntentInfo() {
7999 }
8000
8001 protected IntentInfo(Parcel dest) {
8002 super(dest);
8003 hasDefault = (dest.readInt() == 1);
8004 labelRes = dest.readInt();
8005 nonLocalizedLabel = dest.readCharSequence();
8006 icon = dest.readInt();
8007 logo = dest.readInt();
8008 banner = dest.readInt();
8009 preferred = dest.readInt();
8010 }
8011
8012
8013 public void writeIntentInfoToParcel(Parcel dest, int flags) {
8014 super.writeToParcel(dest, flags);
8015 dest.writeInt(hasDefault ? 1 : 0);
8016 dest.writeInt(labelRes);
8017 dest.writeCharSequence(nonLocalizedLabel);
8018 dest.writeInt(icon);
8019 dest.writeInt(logo);
8020 dest.writeInt(banner);
8021 dest.writeInt(preferred);
8022 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008023 }
8024
8025 public final static class ActivityIntentInfo extends IntentInfo {
Mathew Inwood1c77a112018-08-14 14:06:26 +01008026 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008027 public Activity activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008028
8029 public ActivityIntentInfo(Activity _activity) {
8030 activity = _activity;
8031 }
8032
8033 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008034 StringBuilder sb = new StringBuilder(128);
8035 sb.append("ActivityIntentInfo{");
8036 sb.append(Integer.toHexString(System.identityHashCode(this)));
8037 sb.append(' ');
8038 activity.appendComponentShortName(sb);
8039 sb.append('}');
8040 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008041 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008042
8043 public ActivityIntentInfo(Parcel in) {
8044 super(in);
8045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008046 }
8047
8048 public final static class ServiceIntentInfo extends IntentInfo {
Mathew Inwood1c77a112018-08-14 14:06:26 +01008049 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008050 public Service service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008051
8052 public ServiceIntentInfo(Service _service) {
8053 service = _service;
8054 }
8055
8056 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07008057 StringBuilder sb = new StringBuilder(128);
8058 sb.append("ServiceIntentInfo{");
8059 sb.append(Integer.toHexString(System.identityHashCode(this)));
8060 sb.append(' ');
8061 service.appendComponentShortName(sb);
8062 sb.append('}');
8063 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008064 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008065
8066 public ServiceIntentInfo(Parcel in) {
8067 super(in);
8068 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008069 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008070
Jeff Sharkey85f5f812013-10-07 10:16:12 -07008071 public static final class ProviderIntentInfo extends IntentInfo {
Mathew Inwood1c77a112018-08-14 14:06:26 +01008072 @UnsupportedAppUsage
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008073 public Provider provider;
Jeff Sharkey85f5f812013-10-07 10:16:12 -07008074
8075 public ProviderIntentInfo(Provider provider) {
8076 this.provider = provider;
8077 }
8078
8079 public String toString() {
8080 StringBuilder sb = new StringBuilder(128);
8081 sb.append("ProviderIntentInfo{");
8082 sb.append(Integer.toHexString(System.identityHashCode(this)));
8083 sb.append(' ');
8084 provider.appendComponentShortName(sb);
8085 sb.append('}');
8086 return sb.toString();
8087 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00008088
8089 public ProviderIntentInfo(Parcel in) {
8090 super(in);
8091 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -07008092 }
8093
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008094 /**
8095 * @hide
8096 */
Mathew Inwood1c77a112018-08-14 14:06:26 +01008097 @UnsupportedAppUsage
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008098 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
8099 sCompatibilityModeEnabled = compatibilityModeEnabled;
8100 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07008101
8102 public static class PackageParserException extends Exception {
8103 public final int error;
8104
8105 public PackageParserException(int error, String detailMessage) {
8106 super(detailMessage);
8107 this.error = error;
8108 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07008109
8110 public PackageParserException(int error, String detailMessage, Throwable throwable) {
8111 super(detailMessage, throwable);
8112 this.error = error;
8113 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07008114 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008115}