blob: 3f8a390c215e64af355f3633cfe4eb0c1a654d03 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.content.pm;
18
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070019import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
Winson Chungd3395382016-12-13 11:49:09 -080020import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070021import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
22import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
23import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
24import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
25import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070026import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
27import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
28import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
29import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
Wale Ogunwalee633eb02017-03-30 12:57:29 -070030import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
31import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Garrett Boyer52136662017-05-23 13:47:58 -070032import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070033import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
34import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070035import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
36import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
37import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070038import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -070039import static android.os.Build.VERSION_CODES.O;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070040import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
Robert Carr427ba4f2017-07-17 18:37:06 -070041import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070042
Todd Kennedy232d29e2017-11-06 14:45:53 -080043import android.annotation.IntDef;
Alan Viverette82f4b263a2016-12-19 15:40:05 -050044import android.annotation.IntRange;
45import android.annotation.NonNull;
Fyodor Kupolov965fa692016-10-28 18:20:25 -070046import android.annotation.Nullable;
Alan Viverette82f4b263a2016-12-19 15:40:05 -050047import android.annotation.TestApi;
Dianne Hackborn852975d2014-08-22 17:42:43 -070048import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.content.ComponentName;
50import android.content.Intent;
51import android.content.IntentFilter;
Makoto Onuki4501c61d2017-07-27 15:56:40 -070052import android.content.pm.PackageParserCacheHelper.ReadHelper;
53import android.content.pm.PackageParserCacheHelper.WriteHelper;
Garrett Boyer52136662017-05-23 13:47:58 -070054import android.content.pm.split.DefaultSplitAssetLoader;
Adam Lesinski4e862812016-11-21 16:02:24 -080055import android.content.pm.split.SplitAssetDependencyLoader;
56import android.content.pm.split.SplitAssetLoader;
Adam Lesinskibebfcc42018-02-12 14:27:46 -080057import android.content.res.ApkAssets;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.content.res.AssetManager;
59import android.content.res.Configuration;
60import android.content.res.Resources;
61import android.content.res.TypedArray;
62import android.content.res.XmlResourceParser;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070063import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.os.Bundle;
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -070065import android.os.FileUtils;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070066import android.os.Parcel;
67import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import android.os.PatternMatcher;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -070069import android.os.SystemClock;
Todd Leeea2f3be2017-03-16 14:00:52 -070070import android.os.SystemProperties;
Todd Kennedy27c24fb2015-09-17 16:49:25 -070071import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070072import android.os.UserHandle;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -060073import android.os.storage.StorageManager;
Narayan Kamath988149c2016-12-01 13:32:59 +000074import android.system.ErrnoException;
75import android.system.OsConstants;
76import android.system.StructStat;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -070077import android.text.TextUtils;
Jeff Sharkey275e0852014-06-17 18:18:49 -070078import android.util.ArrayMap;
79import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.util.AttributeSet;
Kenny Root05ca4c92011-09-15 10:36:25 -070081import android.util.Base64;
Dan Cashman1dbe6d02018-01-23 11:18:28 -080082import android.util.ByteStringUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070084import android.util.Log;
Dan Cashman1dbe6d02018-01-23 11:18:28 -080085import android.util.PackageUtils;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070086import android.util.Pair;
Kenny Rootd2d29252011-08-08 11:27:57 -070087import android.util.Slog;
Adam Lesinski1665d0f2017-03-10 14:46:57 -080088import android.util.SparseArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import android.util.TypedValue;
Dan Cashmane92f8422017-12-08 14:02:51 -080090import android.util.apk.ApkSignatureVerifier;
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -070091import android.view.Gravity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070093import com.android.internal.R;
94import com.android.internal.annotations.VisibleForTesting;
Narayan Kamathf9419f02017-06-15 11:35:38 +010095import com.android.internal.os.ClassLoaderFactory;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070096import com.android.internal.util.ArrayUtils;
97import com.android.internal.util.XmlUtils;
98
99import libcore.io.IoUtils;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -0700100import libcore.util.EmptyArray;
Svet Ganov087dce22017-09-07 15:42:16 -0700101
Jeff Sharkey9bc89af2017-01-11 11:25:50 -0700102import org.xmlpull.v1.XmlPullParser;
103import org.xmlpull.v1.XmlPullParserException;
104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import java.io.File;
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700106import java.io.FileDescriptor;
Narayan Kamath988149c2016-12-01 13:32:59 +0000107import java.io.FileOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import java.io.IOException;
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -0700109import java.io.PrintWriter;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800110import java.lang.annotation.Retention;
111import java.lang.annotation.RetentionPolicy;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000112import java.lang.reflect.Constructor;
Kenny Root05ca4c92011-09-15 10:36:25 -0700113import java.security.KeyFactory;
114import java.security.NoSuchAlgorithmException;
115import java.security.PublicKey;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800116import java.security.cert.CertificateException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700117import java.security.spec.EncodedKeySpec;
118import java.security.spec.InvalidKeySpecException;
119import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import java.util.ArrayList;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700121import java.util.Arrays;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700122import java.util.Collections;
123import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -0700125import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800126import java.util.Set;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -0600127import java.util.UUID;
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700128import java.util.concurrent.atomic.AtomicInteger;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129
130/**
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700131 * Parser for package files (APKs) on disk. This supports apps packaged either
132 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
133 * APKs in a single directory.
134 * <p>
135 * Apps packaged as multiple APKs always consist of a single "base" APK (with a
136 * {@code null} split name) and zero or more "split" APKs (with unique split
137 * names). Any subset of those split APKs are a valid install, as long as the
138 * following constraints are met:
139 * <ul>
140 * <li>All APKs must have the exact same package name, version code, and signing
141 * certificates.
142 * <li>All APKs must have unique split names.
143 * <li>All installations must contain a single base APK.
144 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700146 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 */
148public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -0700149 private static final boolean DEBUG_JAR = false;
150 private static final boolean DEBUG_PARSER = false;
151 private static final boolean DEBUG_BACKUP = false;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -0700152 private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE;
153 private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100;
Kenny Rootd2d29252011-08-08 11:27:57 -0700154
Svet Ganova3c4eb32017-04-19 23:51:33 -0700155 private static final String PROPERTY_CHILD_PACKAGES_ENABLED =
156 "persist.sys.child_packages_enabled";
157
Jeff Sharkey3f1790d2017-04-25 18:56:17 -0600158 private static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE &&
Garrett Boyer17041532017-08-01 14:11:02 -0700159 SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false);
Svet Ganova3c4eb32017-04-19 23:51:33 -0700160
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700161 private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
162
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700163 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700164 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700165
Kenny Rootbcc954d2011-08-08 16:19:08 -0700166 /** File name in an APK for the Android manifest. */
Dan Cashmane92f8422017-12-08 14:02:51 -0800167 public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
Kenny Rootbcc954d2011-08-08 16:19:08 -0700168
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700169 /** Path prefix for apps on expanded storage */
170 private static final String MNT_EXPAND = "/mnt/expand/";
171
Svet Ganov354cd3c2015-12-17 11:35:04 -0800172 private static final String TAG_MANIFEST = "manifest";
173 private static final String TAG_APPLICATION = "application";
Adam Lesinski4e862812016-11-21 16:02:24 -0800174 private static final String TAG_PACKAGE_VERIFIER = "package-verifier";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800175 private static final String TAG_OVERLAY = "overlay";
176 private static final String TAG_KEY_SETS = "key-sets";
177 private static final String TAG_PERMISSION_GROUP = "permission-group";
178 private static final String TAG_PERMISSION = "permission";
179 private static final String TAG_PERMISSION_TREE = "permission-tree";
180 private static final String TAG_USES_PERMISSION = "uses-permission";
181 private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
182 private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
183 private static final String TAG_USES_CONFIGURATION = "uses-configuration";
184 private static final String TAG_USES_FEATURE = "uses-feature";
185 private static final String TAG_FEATURE_GROUP = "feature-group";
186 private static final String TAG_USES_SDK = "uses-sdk";
187 private static final String TAG_SUPPORT_SCREENS = "supports-screens";
188 private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
189 private static final String TAG_INSTRUMENTATION = "instrumentation";
190 private static final String TAG_ORIGINAL_PACKAGE = "original-package";
191 private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
192 private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
193 private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
194 private static final String TAG_SUPPORTS_INPUT = "supports-input";
195 private static final String TAG_EAT_COMMENT = "eat-comment";
196 private static final String TAG_PACKAGE = "package";
Todd Kennedyfdd241a2016-04-28 12:26:53 -0700197 private static final String TAG_RESTRICT_UPDATE = "restrict-update";
Adam Lesinski4e862812016-11-21 16:02:24 -0800198 private static final String TAG_USES_SPLIT = "uses-split";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800199
Bryce Lee22571db2017-07-07 15:54:18 -0700200 private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
201
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800202 /**
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700203 * Bit mask of all the valid bits that can be set in recreateOnConfigChanges.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800204 * @hide
205 */
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700206 private static final int RECREATE_ON_CONFIG_CHANGES_MASK =
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800207 ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
208
Svet Ganov354cd3c2015-12-17 11:35:04 -0800209 // These are the tags supported by child packages
210 private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
211 static {
212 CHILD_PACKAGE_TAGS.add(TAG_APPLICATION);
213 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION);
214 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M);
215 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23);
216 CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
217 CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
218 CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
219 CHILD_PACKAGE_TAGS.add(TAG_USES_SDK);
220 CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
221 CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
222 CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE);
223 CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS);
224 CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
225 CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
226 }
227
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700228 private static final boolean LOG_UNSAFE_BROADCASTS = false;
229
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700230 /**
231 * Total number of packages that were read from the cache. We use it only for logging.
232 */
233 public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger();
234
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700235 // Set of broadcast actions that are safe for manifest receivers
236 private static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
237 static {
238 SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
239 }
240
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700241 /** @hide */
Calin Juravle3fc56c32017-12-11 18:26:13 -0800242 public static final String APK_FILE_EXTENSION = ".apk";
243
244 /** @hide */
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700245 public static class NewPermissionInfo {
246 public final String name;
247 public final int sdkVersion;
248 public final int fileVersion;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700249
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700250 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
251 this.name = name;
252 this.sdkVersion = sdkVersion;
253 this.fileVersion = fileVersion;
254 }
255 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700256
257 /** @hide */
258 public static class SplitPermissionInfo {
259 public final String rootPerm;
260 public final String[] newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700261 public final int targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700262
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700263 public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
Dianne Hackborn79245122012-03-12 10:51:26 -0700264 this.rootPerm = rootPerm;
265 this.newPerms = newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700266 this.targetSdk = targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700267 }
268 }
269
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700270 /**
271 * List of new permissions that have been added since 1.0.
272 * NOTE: These must be declared in SDK version order, with permissions
273 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700274 * If sdkVersion is 0, then this is not a permission that we want to
275 * automatically add to older apps, but we do want to allow it to be
276 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700277 * @hide
278 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700279 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
280 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700281 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700282 android.os.Build.VERSION_CODES.DONUT, 0),
283 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
284 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700285 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286
Dianne Hackborn79245122012-03-12 10:51:26 -0700287 /**
288 * List of permissions that have been split into more granular or dependent
289 * permissions.
290 * @hide
291 */
292 public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
293 new PackageParser.SplitPermissionInfo[] {
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700294 // READ_EXTERNAL_STORAGE is always required when an app requests
295 // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
296 // write access without read access. The hack here with the target
297 // target SDK version ensures that this grant is always done.
Dianne Hackborn79245122012-03-12 10:51:26 -0700298 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700299 new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700300 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700301 new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
302 new String[] { android.Manifest.permission.READ_CALL_LOG },
303 android.os.Build.VERSION_CODES.JELLY_BEAN),
304 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
305 new String[] { android.Manifest.permission.WRITE_CALL_LOG },
306 android.os.Build.VERSION_CODES.JELLY_BEAN)
Dianne Hackborn79245122012-03-12 10:51:26 -0700307 };
308
Jeff Sharkey275e0852014-06-17 18:18:49 -0700309 /**
310 * @deprecated callers should move to explicitly passing around source path.
311 */
312 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700316 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700317 private DisplayMetrics mMetrics;
Dianne Hackborncd154e92017-02-28 17:37:35 -0800318 private Callback mCallback;
Narayan Kamath988149c2016-12-01 13:32:59 +0000319 private File mCacheDir;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700320
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700321 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700322 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323
324 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
325
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700326 private static boolean sCompatibilityModeEnabled = true;
Amith Yamasani655d0e22013-06-12 14:19:10 -0700327 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
328 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Todd Kennedy11e45072017-01-25 13:24:21 -0800329 private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700330
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700331 static class ParsePackageItemArgs {
332 final Package owner;
333 final String[] outError;
334 final int nameRes;
335 final int labelRes;
336 final int iconRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700337 final int roundIconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700338 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800339 final int bannerRes;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700340
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700341 String tag;
342 TypedArray sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700343
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700344 ParsePackageItemArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700345 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
346 int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700347 owner = _owner;
348 outError = _outError;
349 nameRes = _nameRes;
350 labelRes = _labelRes;
351 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700352 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800353 bannerRes = _bannerRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700354 roundIconRes = _roundIconRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700355 }
356 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700357
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000358 /** @hide */
359 @VisibleForTesting
360 public static class ParseComponentArgs extends ParsePackageItemArgs {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700361 final String[] sepProcesses;
362 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800363 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700364 final int enabledRes;
365 int flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700366
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000367 public ParseComponentArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700368 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
369 int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800370 String[] _sepProcesses, int _processRes,
371 int _descriptionRes, int _enabledRes) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700372 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes,
373 _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700374 sepProcesses = _sepProcesses;
375 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800376 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700377 enabledRes = _enabledRes;
378 }
379 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800380
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700381 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700382 * Lightweight parsed details about a single package.
383 */
384 public static class PackageLite {
385 public final String packageName;
386 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700387 public final int versionCodeMajor;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700388 public final int installLocation;
389 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700390
391 /** Names of any split APKs, ordered by parsed splitName */
392 public final String[] splitNames;
393
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800394 /** Names of any split APKs that are features. Ordered by splitName */
395 public final boolean[] isFeatureSplits;
396
Adam Lesinski4e862812016-11-21 16:02:24 -0800397 /** Dependencies of any split APKs, ordered by parsed splitName */
398 public final String[] usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800399 public final String[] configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800400
Jeff Sharkey73767b92014-07-04 20:18:13 -0700401 /**
402 * Path where this package was found on disk. For monolithic packages
403 * this is path to single base APK file; for cluster packages this is
404 * path to the cluster directory.
405 */
406 public final String codePath;
407
408 /** Path of base APK */
409 public final String baseCodePath;
410 /** Paths of any split APKs, ordered by parsed splitName */
411 public final String[] splitCodePaths;
412
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800413 /** Revision code of base APK */
414 public final int baseRevisionCode;
415 /** Revision codes of any split APKs, ordered by parsed splitName */
416 public final int[] splitRevisionCodes;
417
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700418 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100419 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100420 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800421 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700422 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800423 public final boolean isolatedSplits;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100424
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700425 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800426 boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100427 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700428 this.packageName = baseApk.packageName;
429 this.versionCode = baseApk.versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700430 this.versionCodeMajor = baseApk.versionCodeMajor;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700431 this.installLocation = baseApk.installLocation;
432 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700433 this.splitNames = splitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800434 this.isFeatureSplits = isFeatureSplits;
Adam Lesinski4e862812016-11-21 16:02:24 -0800435 this.usesSplitNames = usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800436 this.configForSplit = configForSplit;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700437 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700438 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700439 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800440 this.baseRevisionCode = baseApk.revisionCode;
441 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700442 this.coreApp = baseApk.coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100443 this.debuggable = baseApk.debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100444 this.multiArch = baseApk.multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800445 this.use32bitAbi = baseApk.use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700446 this.extractNativeLibs = baseApk.extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800447 this.isolatedSplits = baseApk.isolatedSplits;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700448 }
449
450 public List<String> getAllCodePaths() {
451 ArrayList<String> paths = new ArrayList<>();
452 paths.add(baseCodePath);
453 if (!ArrayUtils.isEmpty(splitCodePaths)) {
454 Collections.addAll(paths, splitCodePaths);
455 }
456 return paths;
457 }
458 }
459
460 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700461 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800462 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700463 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700464 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700465 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700466 public final String splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800467 public boolean isFeatureSplit;
468 public final String configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800469 public final String usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700470 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700471 public final int versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800472 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700473 public final int installLocation;
474 public final VerifierInfo[] verifiers;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800475 public final SigningDetails signingDetails;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700476 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100477 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100478 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800479 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700480 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800481 public final boolean isolatedSplits;
Kenny Root05ca4c92011-09-15 10:36:25 -0700482
Patrick Baumann47117fc2017-12-19 10:17:21 -0800483 public ApkLite(String codePath, String packageName, String splitName,
484 boolean isFeatureSplit,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700485 String configForSplit, String usesSplitName, int versionCode, int versionCodeMajor,
486 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Patrick Baumann47117fc2017-12-19 10:17:21 -0800487 SigningDetails signingDetails, boolean coreApp,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700488 boolean debuggable, boolean multiArch, boolean use32bitAbi,
489 boolean extractNativeLibs, boolean isolatedSplits) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700490 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800491 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700492 this.splitName = splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800493 this.isFeatureSplit = isFeatureSplit;
494 this.configForSplit = configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800495 this.usesSplitName = usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700496 this.versionCode = versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700497 this.versionCodeMajor = versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800498 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800499 this.installLocation = installLocation;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800500 this.signingDetails = signingDetails;
Kenny Root05ca4c92011-09-15 10:36:25 -0700501 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700502 this.coreApp = coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100503 this.debuggable = debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100504 this.multiArch = multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800505 this.use32bitAbi = use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700506 this.extractNativeLibs = extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800507 this.isolatedSplits = isolatedSplits;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800508 }
Dianne Hackborn3accca02013-09-20 09:32:11 -0700509
510 public long getLongVersionCode() {
511 return PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode);
512 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800513 }
514
Garrett Boyer52136662017-05-23 13:47:58 -0700515 /**
516 * Cached parse state for new components.
517 *
518 * Allows reuse of the same parse argument records to avoid GC pressure. Lifetime is carefully
519 * scoped to the parsing of a single application element.
520 */
521 private static class CachedComponentArgs {
522 ParseComponentArgs mActivityArgs;
523 ParseComponentArgs mActivityAliasArgs;
524 ParseComponentArgs mServiceArgs;
525 ParseComponentArgs mProviderArgs;
526 }
527
528 /**
529 * Cached state for parsing instrumentation to avoid GC pressure.
530 *
531 * Must be manually reset to null for each new manifest.
532 */
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700533 private ParsePackageItemArgs mParseInstrumentationArgs;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 /** If set to true, we will only allow package files that exactly match
536 * the DTD. Otherwise, we try to get as much from the package as we
537 * can without failing. This should normally be set to false, to
538 * support extensions to the DTD in future versions. */
539 private static final boolean RIGID_PARSER = false;
540
541 private static final String TAG = "PackageParser";
542
Jeff Sharkey275e0852014-06-17 18:18:49 -0700543 public PackageParser() {
544 mMetrics = new DisplayMetrics();
545 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700546 }
547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 public void setSeparateProcesses(String[] procs) {
549 mSeparateProcesses = procs;
550 }
551
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700552 /**
553 * Flag indicating this parser should only consider apps with
554 * {@code coreApp} manifest attribute to be valid apps. This is useful when
555 * creating a minimalist boot environment.
556 */
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700557 public void setOnlyCoreApps(boolean onlyCoreApps) {
558 mOnlyCoreApps = onlyCoreApps;
559 }
560
Jeff Sharkey275e0852014-06-17 18:18:49 -0700561 public void setDisplayMetrics(DisplayMetrics metrics) {
562 mMetrics = metrics;
563 }
564
Narayan Kamath988149c2016-12-01 13:32:59 +0000565 /**
566 * Sets the cache directory for this package parser.
567 */
568 public void setCacheDir(File cacheDir) {
569 mCacheDir = cacheDir;
570 }
571
Dianne Hackborncd154e92017-02-28 17:37:35 -0800572 /**
573 * Callback interface for retrieving information that may be needed while parsing
574 * a package.
575 */
576 public interface Callback {
577 boolean hasFeature(String feature);
Jaekyun Seok30dc2a02017-04-11 09:41:11 +0900578 String[] getOverlayPaths(String targetPackageName, String targetPath);
579 String[] getOverlayApks(String targetPackageName);
Dianne Hackborncd154e92017-02-28 17:37:35 -0800580 }
581
582 /**
583 * Standard implementation of {@link Callback} on top of the public {@link PackageManager}
584 * class.
585 */
586 public static final class CallbackImpl implements Callback {
587 private final PackageManager mPm;
588
589 public CallbackImpl(PackageManager pm) {
590 mPm = pm;
591 }
592
593 @Override public boolean hasFeature(String feature) {
594 return mPm.hasSystemFeature(feature);
595 }
Jaekyun Seok30dc2a02017-04-11 09:41:11 +0900596
597 @Override public String[] getOverlayPaths(String targetPackageName, String targetPath) {
598 return null;
599 }
600
601 @Override public String[] getOverlayApks(String targetPackageName) {
602 return null;
603 }
Dianne Hackborncd154e92017-02-28 17:37:35 -0800604 }
605
606 /**
607 * Set the {@link Callback} that can be used while parsing.
608 */
609 public void setCallback(Callback cb) {
610 mCallback = cb;
611 }
612
Jeff Sharkey73767b92014-07-04 20:18:13 -0700613 public static final boolean isApkFile(File file) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700614 return isApkPath(file.getName());
615 }
616
Adam Lesinski4e862812016-11-21 16:02:24 -0800617 public static boolean isApkPath(String path) {
Calin Juravle3fc56c32017-12-11 18:26:13 -0800618 return path.endsWith(APK_FILE_EXTENSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 }
620
621 /**
622 * Generate and return the {@link PackageInfo} for a parsed package.
623 *
624 * @param p the parsed package.
625 * @param flags indicating which optional information is included.
626 */
627 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800628 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svet Ganov3695b8a2015-03-24 16:30:25 -0700629 Set<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630
Amith Yamasani483f3b02012-03-13 16:08:00 -0700631 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700632 grantedPermissions, state, UserHandle.getCallingUserId());
633 }
634
Amith Yamasani655d0e22013-06-12 14:19:10 -0700635 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700636 * Returns true if the package is installed and not hidden, or if the caller
637 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700638 * @param appInfo The applicationInfo of the app being checked.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700639 */
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700640 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
641 ApplicationInfo appInfo) {
642 // If available for the target user, or trying to match uninstalled packages and it's
643 // a system app.
644 return state.isAvailable(flags)
645 || (appInfo != null && appInfo.isSystemApp()
Sanry Huangafef5da2018-06-06 17:34:34 +0000646 && (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0);
Amith Yamasani483f3b02012-03-13 16:08:00 -0700647 }
648
Christopher Tateba629da2013-11-13 17:42:28 -0800649 public static boolean isAvailable(PackageUserState state) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700650 return checkUseInstalledOrHidden(0, state, null);
Christopher Tateba629da2013-11-13 17:42:28 -0800651 }
652
Amith Yamasani13593602012-03-22 16:16:17 -0700653 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700654 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800655 Set<String> grantedPermissions, PackageUserState state, int userId) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700656 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700657 return null;
658 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 PackageInfo pi = new PackageInfo();
660 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700661 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662 pi.versionCode = p.mVersionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700663 pi.versionCodeMajor = p.mVersionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800664 pi.baseRevisionCode = p.baseRevisionCode;
665 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666 pi.versionName = p.mVersionName;
667 pi.sharedUserId = p.mSharedUserId;
668 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700669 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800670 pi.installLocation = p.installLocation;
Todd Kennedy7c8addf2017-06-27 14:13:55 -0700671 pi.isStub = p.isStub;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700672 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700673 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
674 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
675 pi.requiredForAllUsers = p.mRequiredForAllUsers;
676 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700677 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700678 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100679 pi.overlayTarget = p.mOverlayTarget;
Adrian Roosc84df772018-01-19 21:20:22 +0100680 pi.overlayCategory = p.mOverlayCategory;
Jaekyun Seok42d53f62017-04-10 13:48:58 +0900681 pi.overlayPriority = p.mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -0800682 pi.mOverlayIsStatic = p.mOverlayIsStatic;
Alan Viveretteb6a25732017-11-21 14:49:24 -0500683 pi.compileSdkVersion = p.mCompileSdkVersion;
684 pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700685 pi.firstInstallTime = firstInstallTime;
686 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800687 if ((flags&PackageManager.GET_GIDS) != 0) {
688 pi.gids = gids;
689 }
690 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700691 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692 if (N > 0) {
693 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700694 p.configPreferences.toArray(pi.configPreferences);
695 }
696 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
697 if (N > 0) {
698 pi.reqFeatures = new FeatureInfo[N];
699 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700701 N = p.featureGroups != null ? p.featureGroups.size() : 0;
702 if (N > 0) {
703 pi.featureGroups = new FeatureGroupInfo[N];
704 p.featureGroups.toArray(pi.featureGroups);
705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700707 if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
708 final int N = p.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700710 int num = 0;
711 final ActivityInfo[] res = new ActivityInfo[N];
712 for (int i = 0; i < N; i++) {
713 final Activity a = p.activities.get(i);
714 if (state.isMatch(a.info, flags)) {
715 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 }
717 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700718 pi.activities = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 }
720 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700721 if ((flags & PackageManager.GET_RECEIVERS) != 0) {
722 final int N = p.receivers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700724 int num = 0;
725 final ActivityInfo[] res = new ActivityInfo[N];
726 for (int i = 0; i < N; i++) {
727 final Activity a = p.receivers.get(i);
728 if (state.isMatch(a.info, flags)) {
729 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800730 }
731 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700732 pi.receivers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 }
734 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700735 if ((flags & PackageManager.GET_SERVICES) != 0) {
736 final int N = p.services.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800737 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700738 int num = 0;
739 final ServiceInfo[] res = new ServiceInfo[N];
740 for (int i = 0; i < N; i++) {
741 final Service s = p.services.get(i);
742 if (state.isMatch(s.info, flags)) {
743 res[num++] = generateServiceInfo(s, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 }
745 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700746 pi.services = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 }
748 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700749 if ((flags & PackageManager.GET_PROVIDERS) != 0) {
750 final int N = p.providers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800751 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700752 int num = 0;
753 final ProviderInfo[] res = new ProviderInfo[N];
754 for (int i = 0; i < N; i++) {
755 final Provider pr = p.providers.get(i);
756 if (state.isMatch(pr.info, flags)) {
757 res[num++] = generateProviderInfo(pr, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800758 }
759 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700760 pi.providers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 }
762 }
763 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
764 int N = p.instrumentation.size();
765 if (N > 0) {
766 pi.instrumentation = new InstrumentationInfo[N];
767 for (int i=0; i<N; i++) {
768 pi.instrumentation[i] = generateInstrumentationInfo(
769 p.instrumentation.get(i), flags);
770 }
771 }
772 }
773 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
774 int N = p.permissions.size();
775 if (N > 0) {
776 pi.permissions = new PermissionInfo[N];
777 for (int i=0; i<N; i++) {
778 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
779 }
780 }
781 N = p.requestedPermissions.size();
782 if (N > 0) {
783 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800784 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 for (int i=0; i<N; i++) {
Dianne Hackborne639da72012-02-21 15:11:13 -0800786 final String perm = p.requestedPermissions.get(i);
787 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700788 // The notion of required permissions is deprecated but for compatibility.
Svetoslavc6d1c342015-02-26 14:44:43 -0800789 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800790 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
791 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
792 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 }
794 }
795 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800796 // deprecated method of getting signing certificates
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Daniel Cashman5cdda342018-01-19 07:22:52 -0800798 if (p.mSigningDetails.hasPastSigningCertificates()) {
799 // Package has included signing certificate rotation information. Return the oldest
800 // cert so that programmatic checks keep working even if unaware of key rotation.
801 pi.signatures = new Signature[1];
802 pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0];
803 } else if (p.mSigningDetails.hasSignatures()) {
804 // otherwise keep old behavior
Patrick Baumann47117fc2017-12-19 10:17:21 -0800805 int numberOfSigs = p.mSigningDetails.signatures.length;
806 pi.signatures = new Signature[numberOfSigs];
807 System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808 }
809 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800810
811 // replacement for GET_SIGNATURES
812 if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
Dan Cashman5c9f527e2018-04-03 16:42:23 -0700813 if (p.mSigningDetails != SigningDetails.UNKNOWN) {
814 // only return a valid SigningInfo if there is signing information to report
815 pi.signingInfo = new SigningInfo(p.mSigningDetails);
816 } else {
817 pi.signingInfo = null;
Daniel Cashman5cdda342018-01-19 07:22:52 -0800818 }
819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820 return pi;
821 }
822
Todd Kennedy232d29e2017-11-06 14:45:53 -0800823 public static final int PARSE_MUST_BE_APK = 1 << 0;
824 public static final int PARSE_IGNORE_PROCESSES = 1 << 1;
Todd Kennedy30a23a52018-01-04 13:27:49 -0800825 /** @deprecated forward lock no longer functional. remove. */
826 @Deprecated
Todd Kennedy232d29e2017-11-06 14:45:53 -0800827 public static final int PARSE_FORWARD_LOCK = 1 << 2;
828 public static final int PARSE_EXTERNAL_STORAGE = 1 << 3;
829 public static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
830 public static final int PARSE_COLLECT_CERTIFICATES = 1 << 5;
831 public static final int PARSE_ENFORCE_CODE = 1 << 6;
832 public static final int PARSE_FORCE_SDK = 1 << 7;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800833 public static final int PARSE_CHATTY = 1 << 31;
834
835 @IntDef(flag = true, prefix = { "PARSE_" }, value = {
836 PARSE_CHATTY,
837 PARSE_COLLECT_CERTIFICATES,
838 PARSE_ENFORCE_CODE,
839 PARSE_EXTERNAL_STORAGE,
840 PARSE_FORCE_SDK,
841 PARSE_FORWARD_LOCK,
842 PARSE_IGNORE_PROCESSES,
Todd Kennedy232d29e2017-11-06 14:45:53 -0800843 PARSE_IS_SYSTEM_DIR,
844 PARSE_MUST_BE_APK,
845 })
846 @Retention(RetentionPolicy.SOURCE)
847 public @interface ParseFlags {}
Jeff Sharkey275e0852014-06-17 18:18:49 -0700848
849 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700851 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700852 * Used to sort a set of APKs based on their split names, always placing the
853 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700854 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700855 private static class SplitNameComparator implements Comparator<String> {
856 @Override
857 public int compare(String lhs, String rhs) {
858 if (lhs == null) {
859 return -1;
860 } else if (rhs == null) {
861 return 1;
862 } else {
863 return lhs.compareTo(rhs);
864 }
865 }
866 }
867
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700868 /**
869 * Parse only lightweight details about the package at the given location.
870 * Automatically detects if the package is a monolithic style (single APK
871 * file) or cluster style (directory of APKs).
872 * <p>
873 * This performs sanity checking on cluster style packages, such as
874 * requiring identical package name and version codes, a single base APK,
875 * and unique split names.
876 *
877 * @see PackageParser#parsePackage(File, int)
878 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700879 public static PackageLite parsePackageLite(File packageFile, int flags)
880 throws PackageParserException {
881 if (packageFile.isDirectory()) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800882 return parseClusterPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700883 } else {
Adam Lesinski4e862812016-11-21 16:02:24 -0800884 return parseMonolithicPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700885 }
886 }
887
Adam Lesinski4e862812016-11-21 16:02:24 -0800888 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
889 throws PackageParserException {
Todd Kennedycd029da2016-07-21 07:41:09 -0700890 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Adam Lesinski4e862812016-11-21 16:02:24 -0800891 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700892 final String packagePath = packageFile.getAbsolutePath();
Todd Kennedycd029da2016-07-21 07:41:09 -0700893 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Narayan Kamath96c11c52017-08-09 13:07:21 +0100894 return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700895 }
896
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800897 static PackageLite parseClusterPackageLite(File packageDir, int flags)
Adam Lesinski4e862812016-11-21 16:02:24 -0800898 throws PackageParserException {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700899 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700900 if (ArrayUtils.isEmpty(files)) {
901 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
902 "No packages found in split");
903 }
904
Jeff Sharkey275e0852014-06-17 18:18:49 -0700905 String packageName = null;
906 int versionCode = 0;
907
Todd Kennedycd029da2016-07-21 07:41:09 -0700908 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700909 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700910 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700911 if (isApkFile(file)) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800912 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700913
914 // Assert that all package names and version codes are
915 // consistent with the first one we encounter.
916 if (packageName == null) {
917 packageName = lite.packageName;
918 versionCode = lite.versionCode;
919 } else {
920 if (!packageName.equals(lite.packageName)) {
921 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
922 "Inconsistent package " + lite.packageName + " in " + file
923 + "; expected " + packageName);
924 }
925 if (versionCode != lite.versionCode) {
926 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
927 "Inconsistent version " + lite.versionCode + " in " + file
928 + "; expected " + versionCode);
929 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700930 }
931
Jeff Sharkey275e0852014-06-17 18:18:49 -0700932 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700933 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700934 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
935 "Split name " + lite.splitName
936 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700937 }
938 }
939 }
Todd Kennedycd029da2016-07-21 07:41:09 -0700940 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700941
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700942 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700943 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700944 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700945 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700946 }
947
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700948 // Always apply deterministic ordering based on splitName
949 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700950
Jeff Sharkey73767b92014-07-04 20:18:13 -0700951 String[] splitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800952 boolean[] isFeatureSplits = null;
Adam Lesinski4e862812016-11-21 16:02:24 -0800953 String[] usesSplitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800954 String[] configForSplits = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700955 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800956 int[] splitRevisionCodes = null;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100957 String[] splitClassLoaderNames = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700958 if (size > 0) {
959 splitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800960 isFeatureSplits = new boolean[size];
Adam Lesinski4e862812016-11-21 16:02:24 -0800961 usesSplitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800962 configForSplits = new String[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700963 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800964 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700965
966 splitNames = apks.keySet().toArray(splitNames);
967 Arrays.sort(splitNames, sSplitNameComparator);
968
969 for (int i = 0; i < size; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800970 final ApkLite apk = apks.get(splitNames[i]);
971 usesSplitNames[i] = apk.usesSplitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800972 isFeatureSplits[i] = apk.isFeatureSplit;
973 configForSplits[i] = apk.configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800974 splitCodePaths[i] = apk.codePath;
975 splitRevisionCodes[i] = apk.revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700976 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700977 }
978
Jeff Sharkey73767b92014-07-04 20:18:13 -0700979 final String codePath = packageDir.getAbsolutePath();
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800980 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100981 configForSplits, splitCodePaths, splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700982 }
983
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700984 /**
985 * Parse the package at the given location. Automatically detects if the
986 * package is a monolithic style (single APK file) or cluster style
987 * (directory of APKs).
988 * <p>
989 * This performs sanity checking on cluster style packages, such as
990 * requiring identical package name and version codes, a single base APK,
991 * and unique split names.
992 * <p>
993 * Note that this <em>does not</em> perform signature verification; that
994 * must be done separately in {@link #collectCertificates(Package, int)}.
995 *
Narayan Kamath988149c2016-12-01 13:32:59 +0000996 * If {@code useCaches} is true, the package parser might return a cached
997 * result from a previous parse of the same {@code packageFile} with the same
998 * {@code flags}. Note that this method does not check whether {@code packageFile}
999 * has changed since the last parse, it's up to callers to do so.
1000 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001001 * @see #parsePackageLite(File, int)
1002 */
Narayan Kamath988149c2016-12-01 13:32:59 +00001003 public Package parsePackage(File packageFile, int flags, boolean useCaches)
1004 throws PackageParserException {
1005 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
1006 if (parsed != null) {
1007 return parsed;
1008 }
1009
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001010 long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Jeff Sharkey73767b92014-07-04 20:18:13 -07001011 if (packageFile.isDirectory()) {
Narayan Kamath988149c2016-12-01 13:32:59 +00001012 parsed = parseClusterPackage(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001013 } else {
Narayan Kamath988149c2016-12-01 13:32:59 +00001014 parsed = parseMonolithicPackage(packageFile, flags);
1015 }
1016
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001017 long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Narayan Kamath988149c2016-12-01 13:32:59 +00001018 cacheResult(packageFile, flags, parsed);
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001019 if (LOG_PARSE_TIMINGS) {
1020 parseTime = cacheTime - parseTime;
1021 cacheTime = SystemClock.uptimeMillis() - cacheTime;
1022 if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
1023 Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
1024 + "ms, update_cache=" + cacheTime + " ms");
1025 }
1026 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001027 return parsed;
1028 }
1029
1030 /**
1031 * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}.
1032 */
1033 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
1034 return parsePackage(packageFile, flags, false /* useCaches */);
1035 }
1036
1037 /**
1038 * Returns the cache key for a specificied {@code packageFile} and {@code flags}.
1039 */
1040 private String getCacheKey(File packageFile, int flags) {
1041 StringBuilder sb = new StringBuilder(packageFile.getName());
1042 sb.append('-');
1043 sb.append(flags);
1044
1045 return sb.toString();
1046 }
1047
1048 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001049 protected Package fromCacheEntry(byte[] bytes) {
1050 return fromCacheEntryStatic(bytes);
1051 }
1052
1053 /** static version of {@link #fromCacheEntry} for unit tests. */
1054 @VisibleForTesting
1055 public static Package fromCacheEntryStatic(byte[] bytes) {
1056 final Parcel p = Parcel.obtain();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001057 p.unmarshall(bytes, 0, bytes.length);
1058 p.setDataPosition(0);
1059
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001060 final ReadHelper helper = new ReadHelper(p);
1061 helper.startAndInstall();
1062
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001063 PackageParser.Package pkg = new PackageParser.Package(p);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001064
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001065 p.recycle();
1066
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001067 sCachedPackageReadCount.incrementAndGet();
1068
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001069 return pkg;
Narayan Kamath988149c2016-12-01 13:32:59 +00001070 }
1071
1072 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001073 protected byte[] toCacheEntry(Package pkg) {
1074 return toCacheEntryStatic(pkg);
1075
1076 }
1077
1078 /** static version of {@link #toCacheEntry} for unit tests. */
1079 @VisibleForTesting
1080 public static byte[] toCacheEntryStatic(Package pkg) {
1081 final Parcel p = Parcel.obtain();
1082 final WriteHelper helper = new WriteHelper(p);
1083
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001084 pkg.writeToParcel(p, 0 /* flags */);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001085
1086 helper.finishAndUninstall();
1087
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001088 byte[] serialized = p.marshall();
1089 p.recycle();
1090
1091 return serialized;
Narayan Kamath988149c2016-12-01 13:32:59 +00001092 }
1093
1094 /**
1095 * Given a {@code packageFile} and a {@code cacheFile} returns whether the
1096 * cache file is up to date based on the mod-time of both files.
1097 */
1098 private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
1099 try {
1100 // NOTE: We don't use the File.lastModified API because it has the very
1101 // non-ideal failure mode of returning 0 with no excepions thrown.
1102 // The nio2 Files API is a little better but is considerably more expensive.
1103 final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
1104 final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
1105 return pkg.st_mtime < cache.st_mtime;
1106 } catch (ErrnoException ee) {
1107 // The most common reason why stat fails is that a given cache file doesn't
1108 // exist. We ignore that here. It's easy to reason that it's safe to say the
1109 // cache isn't up to date if we see any sort of exception here.
1110 //
1111 // (1) Exception while stating the package file : This should never happen,
1112 // and if it does, we do a full package parse (which is likely to throw the
1113 // same exception).
1114 // (2) Exception while stating the cache file : If the file doesn't exist, the
1115 // cache is obviously out of date. If the file *does* exist, we can't read it.
1116 // We will attempt to delete and recreate it after parsing the package.
1117 if (ee.errno != OsConstants.ENOENT) {
1118 Slog.w("Error while stating package cache : ", ee);
1119 }
1120
1121 return false;
1122 }
1123 }
1124
1125 /**
1126 * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
1127 * or {@code null} if no cached result exists.
1128 */
1129 private Package getCachedResult(File packageFile, int flags) {
1130 if (mCacheDir == null) {
1131 return null;
1132 }
1133
1134 final String cacheKey = getCacheKey(packageFile, flags);
1135 final File cacheFile = new File(mCacheDir, cacheKey);
1136
Narayan Kamath988149c2016-12-01 13:32:59 +00001137 try {
Makoto Onuki48e93162017-08-18 11:00:19 -07001138 // If the cache is not up to date, return null.
1139 if (!isCacheUpToDate(packageFile, cacheFile)) {
1140 return null;
1141 }
1142
Narayan Kamath988149c2016-12-01 13:32:59 +00001143 final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001144 Package p = fromCacheEntry(bytes);
1145 if (mCallback != null) {
1146 String[] overlayApks = mCallback.getOverlayApks(p.packageName);
1147 if (overlayApks != null && overlayApks.length > 0) {
1148 for (String overlayApk : overlayApks) {
1149 // If a static RRO is updated, return null.
1150 if (!isCacheUpToDate(new File(overlayApk), cacheFile)) {
1151 return null;
1152 }
1153 }
1154 }
1155 }
1156 return p;
Makoto Onuki48e93162017-08-18 11:00:19 -07001157 } catch (Throwable e) {
Narayan Kamath21a28382017-01-13 10:34:29 +00001158 Slog.w(TAG, "Error reading package cache: ", e);
Narayan Kamath988149c2016-12-01 13:32:59 +00001159
1160 // If something went wrong while reading the cache entry, delete the cache file
1161 // so that we regenerate it the next time.
1162 cacheFile.delete();
1163 return null;
1164 }
1165 }
1166
1167 /**
1168 * Caches the parse result for {@code packageFile} with flags {@code flags}.
1169 */
1170 private void cacheResult(File packageFile, int flags, Package parsed) {
1171 if (mCacheDir == null) {
1172 return;
1173 }
1174
Makoto Onuki48e93162017-08-18 11:00:19 -07001175 try {
1176 final String cacheKey = getCacheKey(packageFile, flags);
1177 final File cacheFile = new File(mCacheDir, cacheKey);
Narayan Kamath988149c2016-12-01 13:32:59 +00001178
Makoto Onuki48e93162017-08-18 11:00:19 -07001179 if (cacheFile.exists()) {
1180 if (!cacheFile.delete()) {
1181 Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
1182 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001183 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001184
Makoto Onuki48e93162017-08-18 11:00:19 -07001185 final byte[] cacheEntry = toCacheEntry(parsed);
Narayan Kamath988149c2016-12-01 13:32:59 +00001186
Makoto Onuki48e93162017-08-18 11:00:19 -07001187 if (cacheEntry == null) {
1188 return;
1189 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001190
Makoto Onuki48e93162017-08-18 11:00:19 -07001191 try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
1192 fos.write(cacheEntry);
1193 } catch (IOException ioe) {
1194 Slog.w(TAG, "Error writing cache entry.", ioe);
1195 cacheFile.delete();
1196 }
1197 } catch (Throwable e) {
1198 Slog.w(TAG, "Error saving package cache.", e);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001199 }
1200 }
1201
1202 /**
1203 * Parse all APKs contained in the given directory, treating them as a
1204 * single package. This also performs sanity checking, such as requiring
1205 * identical package name and version codes, a single base APK, and unique
1206 * split names.
1207 * <p>
1208 * Note that this <em>does not</em> perform signature verification; that
1209 * must be done separately in {@link #collectCertificates(Package, int)}.
1210 */
1211 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001212 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001213 if (mOnlyCoreApps && !lite.coreApp) {
1214 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1215 "Not a coreApp: " + packageDir);
1216 }
1217
Adam Lesinski4e862812016-11-21 16:02:24 -08001218 // Build the split dependency tree.
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001219 SparseArray<int[]> splitDependencies = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001220 final SplitAssetLoader assetLoader;
1221 if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001222 try {
1223 splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
1224 assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
1225 } catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
1226 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
1227 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001228 } else {
1229 assetLoader = new DefaultSplitAssetLoader(lite, flags);
1230 }
1231
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001232 try {
Adam Lesinski4e862812016-11-21 16:02:24 -08001233 final AssetManager assets = assetLoader.getBaseAssetManager();
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001234 final File baseApk = new File(lite.baseCodePath);
1235 final Package pkg = parseBaseApk(baseApk, assets, flags);
1236 if (pkg == null) {
1237 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1238 "Failed to parse base APK: " + baseApk);
1239 }
1240
1241 if (!ArrayUtils.isEmpty(lite.splitNames)) {
1242 final int num = lite.splitNames.length;
1243 pkg.splitNames = lite.splitNames;
1244 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001245 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001246 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001247 pkg.splitPrivateFlags = new int[num];
Adam Lesinski4e862812016-11-21 16:02:24 -08001248 pkg.applicationInfo.splitNames = pkg.splitNames;
1249 pkg.applicationInfo.splitDependencies = splitDependencies;
Narayan Kamath96c11c52017-08-09 13:07:21 +01001250 pkg.applicationInfo.splitClassLoaderNames = new String[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001251
1252 for (int i = 0; i < num; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -08001253 final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
1254 parseSplitApk(pkg, i, splitAssets, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001255 }
1256 }
1257
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001258 pkg.setCodePath(packageDir.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001259 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001260 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001261 } catch (IOException e) {
1262 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1263 "Failed to get path: " + lite.baseCodePath, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001264 } finally {
Adam Lesinski4e862812016-11-21 16:02:24 -08001265 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001266 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 }
1268
Jeff Sharkey275e0852014-06-17 18:18:49 -07001269 /**
1270 * Parse the given APK file, treating it as as a single monolithic package.
1271 * <p>
1272 * Note that this <em>does not</em> perform signature verification; that
1273 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001274 *
1275 * @deprecated external callers should move to
1276 * {@link #parsePackage(File, int)}. Eventually this method will
1277 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -07001278 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001279 @Deprecated
Jeff Sharkey275e0852014-06-17 18:18:49 -07001280 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001281 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001282 if (mOnlyCoreApps) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001283 if (!lite.coreApp) {
1284 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1285 "Not a coreApp: " + apkFile);
1286 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001287 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001288
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001289 final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001290 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001291 final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001292 pkg.setCodePath(apkFile.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001293 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001294 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001295 } catch (IOException e) {
1296 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1297 "Failed to get path: " + apkFile, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001298 } finally {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001299 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001300 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001301 }
1302
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001303 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
1304 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001305 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001306
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07001307 String volumeUuid = null;
1308 if (apkPath.startsWith(MNT_EXPAND)) {
1309 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
1310 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
1311 }
1312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001313 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001314 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001315
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001316 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001317
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001318 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001320 final int cookie = assets.findCookieForPath(apkPath);
1321 if (cookie == 0) {
1322 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1323 "Failed adding asset path: " + apkPath);
1324 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001325 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001326 final Resources res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001327
1328 final String[] outError = new String[1];
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001329 final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001330 if (pkg == null) {
1331 throw new PackageParserException(mParseError,
1332 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001333 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001334
Svet Ganov354cd3c2015-12-17 11:35:04 -08001335 pkg.setVolumeUuid(volumeUuid);
1336 pkg.setApplicationVolumeUuid(volumeUuid);
1337 pkg.setBaseCodePath(apkPath);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001338 pkg.setSigningDetails(SigningDetails.UNKNOWN);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001339
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001340 return pkg;
1341
1342 } catch (PackageParserException e) {
1343 throw e;
1344 } catch (Exception e) {
1345 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001346 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001347 } finally {
1348 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001350 }
1351
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001352 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001353 throws PackageParserException {
1354 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -07001355
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001356 mParseError = PackageManager.INSTALL_SUCCEEDED;
1357 mArchiveSourcePath = apkPath;
1358
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001359 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
1360
Adam Lesinski4e862812016-11-21 16:02:24 -08001361 final Resources res;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001362 XmlResourceParser parser = null;
1363 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001364 // This must always succeed, as the path has been added to the AssetManager before.
1365 final int cookie = assets.findCookieForPath(apkPath);
1366 if (cookie == 0) {
1367 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1368 "Failed adding asset path: " + apkPath);
1369 }
1370
Adam Lesinski56c82be2018-02-09 11:02:04 -08001371 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001372 res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001373
1374 final String[] outError = new String[1];
1375 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
1376 if (pkg == null) {
1377 throw new PackageParserException(mParseError,
1378 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
1379 }
1380
1381 } catch (PackageParserException e) {
1382 throw e;
1383 } catch (Exception e) {
1384 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001385 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001386 } finally {
1387 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001388 }
1389 }
1390
1391 /**
1392 * Parse the manifest of a <em>split APK</em>.
1393 * <p>
1394 * Note that split APKs have many more restrictions on what they're capable
1395 * of doing, so many valid features of a base APK have been carefully
1396 * omitted here.
1397 */
1398 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001399 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
1400 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001401 AttributeSet attrs = parser;
1402
Jeff Sharkey78a13012014-07-15 20:18:34 -07001403 // We parsed manifest tag earlier; just skip past it
Svet Ganov354cd3c2015-12-17 11:35:04 -08001404 parsePackageSplitNames(parser, attrs);
Jeff Sharkey78a13012014-07-15 20:18:34 -07001405
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001406 mParseInstrumentationArgs = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001407
1408 int type;
1409
1410 boolean foundApp = false;
1411
1412 int outerDepth = parser.getDepth();
1413 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1414 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1415 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1416 continue;
1417 }
1418
1419 String tagName = parser.getName();
Adam Lesinski4e862812016-11-21 16:02:24 -08001420 if (tagName.equals(TAG_APPLICATION)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001421 if (foundApp) {
1422 if (RIGID_PARSER) {
1423 outError[0] = "<manifest> has more than one <application>";
1424 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1425 return null;
1426 } else {
1427 Slog.w(TAG, "<manifest> has more than one <application>");
1428 XmlUtils.skipCurrentTag(parser);
1429 continue;
1430 }
1431 }
1432
1433 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001434 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001435 return null;
1436 }
1437
1438 } else if (RIGID_PARSER) {
1439 outError[0] = "Bad element under <manifest>: "
1440 + parser.getName();
1441 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1442 return null;
1443
1444 } else {
1445 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1446 + " at " + mArchiveSourcePath + " "
1447 + parser.getPositionDescription());
1448 XmlUtils.skipCurrentTag(parser);
1449 continue;
1450 }
1451 }
1452
1453 if (!foundApp) {
1454 outError[0] = "<manifest> does not contain an <application>";
1455 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1456 }
1457
1458 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001459 }
1460
Patrick Baumann47117fc2017-12-19 10:17:21 -08001461 /** Parses the public keys from the set of signatures. */
1462 public static ArraySet<PublicKey> toSigningKeys(Signature[] signatures)
1463 throws CertificateException {
1464 ArraySet<PublicKey> keys = new ArraySet<>(signatures.length);
1465 for (int i = 0; i < signatures.length; i++) {
1466 keys.add(signatures[i].getPublicKey());
Todd Kennedy66c55532016-02-26 16:22:11 -08001467 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001468 return keys;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001469 }
1470
1471 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -07001472 * Collect certificates from all the APKs described in the given package,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001473 * populating {@link Package#mSigningDetails}. Also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001474 * contents are signed correctly and consistently.
1475 */
Victor Hsieh5f761242018-01-20 10:30:12 -08001476 public static void collectCertificates(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001477 throws PackageParserException {
Victor Hsieh5f761242018-01-20 10:30:12 -08001478 collectCertificatesInternal(pkg, skipVerify);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001479 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1480 for (int i = 0; i < childCount; i++) {
1481 Package childPkg = pkg.childPackages.get(i);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001482 childPkg.mSigningDetails = pkg.mSigningDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001483 }
1484 }
1485
Victor Hsieh5f761242018-01-20 10:30:12 -08001486 private static void collectCertificatesInternal(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001487 throws PackageParserException {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001488 pkg.mSigningDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001489
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001490 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1491 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001492 collectCertificates(pkg, new File(pkg.baseCodePath), skipVerify);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001493
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001494 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1495 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
Victor Hsieh5f761242018-01-20 10:30:12 -08001496 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001497 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001498 }
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001499 } finally {
1500 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001501 }
1502 }
1503
Victor Hsieh5f761242018-01-20 10:30:12 -08001504 private static void collectCertificates(Package pkg, File apkFile, boolean skipVerify)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001505 throws PackageParserException {
1506 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507
Patrick Baumann47117fc2017-12-19 10:17:21 -08001508 int minSignatureScheme = SigningDetails.SignatureSchemeVersion.JAR;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001509 if (pkg.applicationInfo.isStaticSharedLibrary()) {
Dan Cashmane92f8422017-12-08 14:02:51 -08001510 // must use v2 signing scheme
Patrick Baumann47117fc2017-12-19 10:17:21 -08001511 minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;
Dan Cashmane92f8422017-12-08 14:02:51 -08001512 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001513 SigningDetails verified;
Victor Hsieh5f761242018-01-20 10:30:12 -08001514 if (skipVerify) {
Dan Cashman636ea5e2017-12-18 10:38:20 -08001515 // systemDir APKs are already trusted, save time by not verifying
1516 verified = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts(
1517 apkPath, minSignatureScheme);
1518 } else {
1519 verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme);
1520 }
Dan Cashman636ea5e2017-12-18 10:38:20 -08001521
1522 // Verify that entries are signed consistently with the first pkg
1523 // we encountered. Note that for splits, certificates may have
1524 // already been populated during an earlier parse of a base APK.
Patrick Baumann47117fc2017-12-19 10:17:21 -08001525 if (pkg.mSigningDetails == SigningDetails.UNKNOWN) {
1526 pkg.mSigningDetails = verified;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001527 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001528 if (!Signature.areExactMatch(pkg.mSigningDetails.signatures, verified.signatures)) {
Patrick Baumann9ff55742017-12-14 10:50:18 -08001529 throw new PackageParserException(
1530 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
1531 apkPath + " has mismatched certificates");
1532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 }
1535
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001536 private static AssetManager newConfiguredAssetManager() {
1537 AssetManager assetManager = new AssetManager();
Romain Guy408afbf2017-01-25 10:23:03 -08001538 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 -07001539 Build.VERSION.RESOURCES_SDK_INT);
1540 return assetManager;
1541 }
1542
Jeff Sharkey275e0852014-06-17 18:18:49 -07001543 /**
1544 * Utility method that retrieves lightweight details about a single APK
1545 * file, including package name, split name, and install location.
1546 *
1547 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001548 * @param flags optional parse flags, such as
1549 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001550 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001551 public static ApkLite parseApkLite(File apkFile, int flags)
1552 throws PackageParserException {
Dianne Hackbornca3872c2017-10-30 14:19:32 -07001553 return parseApkLiteInner(apkFile, null, null, flags);
1554 }
1555
1556 /**
1557 * Utility method that retrieves lightweight details about a single APK
1558 * file, including package name, split name, and install location.
1559 *
1560 * @param fd already open file descriptor of an apk file
1561 * @param debugPathName arbitrary text name for this file, for debug output
1562 * @param flags optional parse flags, such as
1563 * {@link #PARSE_COLLECT_CERTIFICATES}
1564 */
1565 public static ApkLite parseApkLite(FileDescriptor fd, String debugPathName, int flags)
1566 throws PackageParserException {
1567 return parseApkLiteInner(null, fd, debugPathName, flags);
1568 }
1569
1570 private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName,
1571 int flags) throws PackageParserException {
1572 final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001573
Jeff Sharkey275e0852014-06-17 18:18:49 -07001574 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001576 final ApkAssets apkAssets;
1577 try {
1578 apkAssets = fd != null
1579 ? ApkAssets.loadFromFd(fd, debugPathName, false, false)
1580 : ApkAssets.loadFromPath(apkPath);
1581 } catch (IOException e) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001582 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1583 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001584 }
1585
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001586 parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001587
Patrick Baumann47117fc2017-12-19 10:17:21 -08001588 final SigningDetails signingDetails;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001589 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1590 // TODO: factor signature related items out of Package object
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001591 final Package tempPkg = new Package((String) null);
Victor Hsieh5f761242018-01-20 10:30:12 -08001592 final boolean skipVerify = (flags & PARSE_IS_SYSTEM_DIR) != 0;
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001593 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1594 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001595 collectCertificates(tempPkg, apkFile, skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001596 } finally {
1597 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1598 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001599 signingDetails = tempPkg.mSigningDetails;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001600 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001601 signingDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001602 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001603
Jeff Sharkey275e0852014-06-17 18:18:49 -07001604 final AttributeSet attrs = parser;
Patrick Baumann47117fc2017-12-19 10:17:21 -08001605 return parseApkLite(apkPath, parser, attrs, signingDetails);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001606
1607 } catch (XmlPullParserException | IOException | RuntimeException e) {
Dianne Hackborn34041732017-01-31 15:27:13 -08001608 Slog.w(TAG, "Failed to parse " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001609 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1610 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001612 IoUtils.closeQuietly(parser);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001613 // TODO(b/72056911): Implement and call close() on ApkAssets.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 }
1616
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001617 private static String validateName(String name, boolean requireSeparator,
1618 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 final int N = name.length();
1620 boolean hasSep = false;
1621 boolean front = true;
1622 for (int i=0; i<N; i++) {
1623 final char c = name.charAt(i);
1624 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1625 front = false;
1626 continue;
1627 }
1628 if (!front) {
1629 if ((c >= '0' && c <= '9') || c == '_') {
1630 continue;
1631 }
1632 }
1633 if (c == '.') {
1634 hasSep = true;
1635 front = true;
1636 continue;
1637 }
1638 return "bad character '" + c + "'";
1639 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001640 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1641 return "Invalid filename";
1642 }
1643 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 ? null : "must have at least one '.' separator";
1645 }
1646
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001647 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
Svet Ganov354cd3c2015-12-17 11:35:04 -08001648 AttributeSet attrs) throws IOException, XmlPullParserException,
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001649 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650
1651 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001652 while ((type = parser.next()) != XmlPullParser.START_TAG
1653 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 }
1655
Kenny Rootd2d29252011-08-08 11:27:57 -07001656 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001657 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1658 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001660 if (!parser.getName().equals(TAG_MANIFEST)) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001661 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1662 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001663 }
1664
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001665 final String packageName = attrs.getAttributeValue(null, "package");
1666 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001667 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001668 if (error != null) {
1669 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1670 "Invalid manifest package: " + error);
1671 }
1672 }
1673
Jeff Sharkey275e0852014-06-17 18:18:49 -07001674 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001675 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001676 if (splitName.length() == 0) {
1677 splitName = null;
1678 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001679 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001680 if (error != null) {
1681 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1682 "Invalid manifest split: " + error);
1683 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001684 }
1685 }
1686
1687 return Pair.create(packageName.intern(),
1688 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001689 }
1690
Adam Lesinski4e862812016-11-21 16:02:24 -08001691 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001692 SigningDetails signingDetails)
Adam Lesinski4e862812016-11-21 16:02:24 -08001693 throws IOException, XmlPullParserException, PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001694 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001695
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001696 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001697 int versionCode = 0;
Dianne Hackborn3accca02013-09-20 09:32:11 -07001698 int versionCodeMajor = 0;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001699 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001700 boolean coreApp = false;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001701 boolean debuggable = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001702 boolean multiArch = false;
Selim Gurun2d291d82016-02-05 17:50:53 -08001703 boolean use32bitAbi = false;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001704 boolean extractNativeLibs = true;
Adam Lesinski4e862812016-11-21 16:02:24 -08001705 boolean isolatedSplits = false;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001706 boolean isFeatureSplit = false;
1707 String configForSplit = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001708 String usesSplitName = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001709
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001710 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001711 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001712 if (attr.equals("installLocation")) {
1713 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001714 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001715 } else if (attr.equals("versionCode")) {
1716 versionCode = attrs.getAttributeIntValue(i, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001717 } else if (attr.equals("versionCodeMajor")) {
1718 versionCodeMajor = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001719 } else if (attr.equals("revisionCode")) {
1720 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001721 } else if (attr.equals("coreApp")) {
1722 coreApp = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski4e862812016-11-21 16:02:24 -08001723 } else if (attr.equals("isolatedSplits")) {
1724 isolatedSplits = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001725 } else if (attr.equals("configForSplit")) {
1726 configForSplit = attrs.getAttributeValue(i);
1727 } else if (attr.equals("isFeatureSplit")) {
1728 isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001729 }
1730 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001731
1732 // Only search the tree when the tag is directly below <manifest>
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001733 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001734 final int searchDepth = parser.getDepth() + 1;
1735
1736 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1737 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1738 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1739 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1740 continue;
1741 }
1742
Adam Lesinski4e862812016-11-21 16:02:24 -08001743 if (parser.getDepth() != searchDepth) {
1744 continue;
1745 }
1746
1747 if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
1748 final VerifierInfo verifier = parseVerifier(attrs);
Kenny Root05ca4c92011-09-15 10:36:25 -07001749 if (verifier != null) {
1750 verifiers.add(verifier);
1751 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001752 } else if (TAG_APPLICATION.equals(parser.getName())) {
Narayan Kamatha8755a82014-07-15 12:26:35 +01001753 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1754 final String attr = attrs.getAttributeName(i);
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001755 if ("debuggable".equals(attr)) {
1756 debuggable = attrs.getAttributeBooleanValue(i, false);
1757 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001758 if ("multiArch".equals(attr)) {
1759 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001760 }
Selim Gurun2d291d82016-02-05 17:50:53 -08001761 if ("use32bitAbi".equals(attr)) {
1762 use32bitAbi = attrs.getAttributeBooleanValue(i, false);
Tao Baic9a02372016-01-12 15:02:24 -08001763 }
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001764 if ("extractNativeLibs".equals(attr)) {
1765 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001766 }
1767 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001768 } else if (TAG_USES_SPLIT.equals(parser.getName())) {
1769 if (usesSplitName != null) {
1770 Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
1771 continue;
1772 }
1773
1774 usesSplitName = attrs.getAttributeValue(ANDROID_RESOURCES, "name");
1775 if (usesSplitName == null) {
1776 throw new PackageParserException(
1777 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1778 "<uses-split> tag requires 'android:name' attribute");
1779 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001780 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001781 }
1782
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001783 return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
Dianne Hackborn3accca02013-09-20 09:32:11 -07001784 configForSplit, usesSplitName, versionCode, versionCodeMajor, revisionCode,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001785 installLocation, verifiers, signingDetails, coreApp, debuggable,
Dianne Hackborn3accca02013-09-20 09:32:11 -07001786 multiArch, use32bitAbi, extractNativeLibs, isolatedSplits);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 }
1788
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001789 /**
Svet Ganov354cd3c2015-12-17 11:35:04 -08001790 * Parses a child package and adds it to the parent if successful. If you add
1791 * new tags that need to be supported by child packages make sure to add them
1792 * to {@link #CHILD_PACKAGE_TAGS}.
1793 *
1794 * @param parentPkg The parent that contains the child
1795 * @param res Resources against which to resolve values
1796 * @param parser Parser of the manifest
1797 * @param flags Flags about how to parse
1798 * @param outError Human readable error if parsing fails
1799 * @return True of parsing succeeded.
1800 *
1801 * @throws XmlPullParserException
1802 * @throws IOException
1803 */
1804 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
1805 int flags, String[] outError) throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001806 // Make sure we have a valid child package name
1807 String childPackageName = parser.getAttributeValue(null, "package");
1808 if (validateName(childPackageName, true, false) != null) {
1809 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1810 return false;
1811 }
1812
1813 // Child packages must be unique
1814 if (childPackageName.equals(parentPkg.packageName)) {
1815 String message = "Child package name cannot be equal to parent package name: "
1816 + parentPkg.packageName;
1817 Slog.w(TAG, message);
1818 outError[0] = message;
1819 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1820 return false;
1821 }
1822
1823 // Child packages must be unique
1824 if (parentPkg.hasChildPackage(childPackageName)) {
1825 String message = "Duplicate child package:" + childPackageName;
1826 Slog.w(TAG, message);
1827 outError[0] = message;
1828 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1829 return false;
1830 }
1831
1832 // Go ahead and parse the child
1833 Package childPkg = new Package(childPackageName);
1834
1835 // Child package inherits parent version code/name/target SDK
1836 childPkg.mVersionCode = parentPkg.mVersionCode;
1837 childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
1838 childPkg.mVersionName = parentPkg.mVersionName;
1839 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
Todd Kennedy89d60182016-03-11 11:18:32 -08001840 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001841
1842 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
1843 if (childPkg == null) {
1844 // If we got null then error was set during child parsing
1845 return false;
1846 }
1847
1848 // Set the parent-child relation
1849 if (parentPkg.childPackages == null) {
1850 parentPkg.childPackages = new ArrayList<>();
1851 }
1852 parentPkg.childPackages.add(childPkg);
1853 childPkg.parentPackage = parentPkg;
1854
1855 return true;
1856 }
1857
1858 /**
1859 * Parse the manifest of a <em>base APK</em>. When adding new features you
1860 * need to consider whether they should be supported by split APKs and child
1861 * packages.
1862 *
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001863 * @param apkPath The package apk file path
Svet Ganov354cd3c2015-12-17 11:35:04 -08001864 * @param res The resources from which to resolve values
1865 * @param parser The manifest parser
1866 * @param flags Flags how to parse
1867 * @param outError Human readable error message
1868 * @return Parsed package or null on error.
1869 *
1870 * @throws XmlPullParserException
1871 * @throws IOException
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001872 */
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001873 private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001874 String[] outError) throws XmlPullParserException, IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001875 final String splitName;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001876 final String pkgName;
1877
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001878 try {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001879 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001880 pkgName = packageSplit.first;
1881 splitName = packageSplit.second;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001882
1883 if (!TextUtils.isEmpty(splitName)) {
1884 outError[0] = "Expected base APK, but found split " + splitName;
1885 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1886 return null;
1887 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001888 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001889 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1890 return null;
1891 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001892
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001893 if (mCallback != null) {
1894 String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
1895 if (overlayPaths != null && overlayPaths.length > 0) {
1896 for (String overlayPath : overlayPaths) {
1897 res.getAssets().addOverlayPath(overlayPath);
1898 }
1899 }
1900 }
1901
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001902 final Package pkg = new Package(pkgName);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001903
Svet Ganov354cd3c2015-12-17 11:35:04 -08001904 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001905 com.android.internal.R.styleable.AndroidManifest);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001906
Dianne Hackborn3accca02013-09-20 09:32:11 -07001907 pkg.mVersionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001908 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001909 pkg.mVersionCodeMajor = sa.getInteger(
1910 com.android.internal.R.styleable.AndroidManifest_versionCodeMajor, 0);
Patrick Baumannc2def582018-04-04 12:14:15 -07001911 pkg.applicationInfo.setVersionCode(pkg.getLongVersionCode());
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001912 pkg.baseRevisionCode = sa.getInteger(
1913 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001914 pkg.mVersionName = sa.getNonConfigurationString(
1915 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001916 if (pkg.mVersionName != null) {
1917 pkg.mVersionName = pkg.mVersionName.intern();
1918 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001919
1920 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
1921
Alan Viveretteb6a25732017-11-21 14:49:24 -05001922 pkg.mCompileSdkVersion = sa.getInteger(
1923 com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0);
1924 pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion;
1925 pkg.mCompileSdkVersionCodename = sa.getNonConfigurationString(
1926 com.android.internal.R.styleable.AndroidManifest_compileSdkVersionCodename, 0);
1927 if (pkg.mCompileSdkVersionCodename != null) {
1928 pkg.mCompileSdkVersionCodename = pkg.mCompileSdkVersionCodename.intern();
1929 }
1930 pkg.applicationInfo.compileSdkVersionCodename = pkg.mCompileSdkVersionCodename;
1931
Svet Ganov354cd3c2015-12-17 11:35:04 -08001932 sa.recycle();
1933
1934 return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
1935 }
1936
1937 /**
1938 * This is the common parsing routing for handling parent and child
1939 * packages in a base APK. The difference between parent and child
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001940 * parsing is that some tags are not supported by child packages as
Svet Ganov354cd3c2015-12-17 11:35:04 -08001941 * well as some manifest attributes are ignored. The implementation
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001942 * assumes the calling code has already handled the manifest tag if needed
Svet Ganov354cd3c2015-12-17 11:35:04 -08001943 * (this applies to the parent only).
1944 *
1945 * @param pkg The package which to populate
1946 * @param acceptedTags Which tags to handle, null to handle all
1947 * @param res Resources against which to resolve values
1948 * @param parser Parser of the manifest
1949 * @param flags Flags about how to parse
1950 * @param outError Human readable error if parsing fails
1951 * @return The package if parsing succeeded or null.
1952 *
1953 * @throws XmlPullParserException
1954 * @throws IOException
1955 */
1956 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
1957 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
1958 IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001959 mParseInstrumentationArgs = null;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001960
1961 int type;
1962 boolean foundApp = false;
1963
1964 TypedArray sa = res.obtainAttributes(parser,
1965 com.android.internal.R.styleable.AndroidManifest);
1966
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001967 String str = sa.getNonConfigurationString(
1968 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
1969 if (str != null && str.length() > 0) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001970 String nameError = validateName(str, true, false);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001971 if (nameError != null && !"android".equals(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001972 outError[0] = "<manifest> specifies bad sharedUserId name \""
1973 + str + "\": " + nameError;
1974 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
1975 return null;
1976 }
1977 pkg.mSharedUserId = str.intern();
1978 pkg.mSharedUserLabel = sa.getResourceId(
1979 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
1980 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08001981
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08001982 pkg.installLocation = sa.getInteger(
1983 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001984 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07001985 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07001986
Todd Kennedy11e45072017-01-25 13:24:21 -08001987 final int targetSandboxVersion = sa.getInteger(
1988 com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion,
1989 PARSE_DEFAULT_TARGET_SANDBOX);
1990 pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion;
Alan Viverettefd274a02014-03-27 15:39:15 -07001991
Kenny Root7cb9be22012-05-30 15:30:37 -07001992 /* Set the global "forward lock" flag */
1993 if ((flags & PARSE_FORWARD_LOCK) != 0) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001994 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
Kenny Root7cb9be22012-05-30 15:30:37 -07001995 }
1996
1997 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001998 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07001999 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
2000 }
2001
Adam Lesinski4e862812016-11-21 16:02:24 -08002002 if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
2003 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
2004 }
2005
Dianne Hackborn723738c2009-06-25 19:48:04 -07002006 // Resource boolean are -1, so 1 means we don't know the value.
2007 int supportsSmallScreens = 1;
2008 int supportsNormalScreens = 1;
2009 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002010 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002011 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002012 int anyDensity = 1;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002014 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07002015 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2016 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2017 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002018 continue;
2019 }
2020
2021 String tagName = parser.getName();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002022
2023 if (acceptedTags != null && !acceptedTags.contains(tagName)) {
2024 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
2025 + tagName + " at " + mArchiveSourcePath + " "
2026 + parser.getPositionDescription());
2027 XmlUtils.skipCurrentTag(parser);
2028 continue;
2029 }
2030
2031 if (tagName.equals(TAG_APPLICATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002032 if (foundApp) {
2033 if (RIGID_PARSER) {
2034 outError[0] = "<manifest> has more than one <application>";
2035 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2036 return null;
2037 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002038 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002039 XmlUtils.skipCurrentTag(parser);
2040 continue;
2041 }
2042 }
2043
2044 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002045 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 return null;
2047 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002048 } else if (tagName.equals(TAG_OVERLAY)) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002049 sa = res.obtainAttributes(parser,
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002050 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
2051 pkg.mOverlayTarget = sa.getString(
2052 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
Adrian Roosc84df772018-01-19 21:20:22 +01002053 pkg.mOverlayCategory = sa.getString(
2054 com.android.internal.R.styleable.AndroidManifestResourceOverlay_category);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002055 pkg.mOverlayPriority = sa.getInt(
2056 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
2057 0);
Adam Lesinskie7334972018-01-17 16:13:52 -08002058 pkg.mOverlayIsStatic = sa.getBoolean(
Jaekyun Seok04342892017-03-02 15:24:19 +09002059 com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
2060 false);
Todd Leeea2f3be2017-03-16 14:00:52 -07002061 final String propName = sa.getString(
2062 com.android.internal.R.styleable
2063 .AndroidManifestResourceOverlay_requiredSystemPropertyName);
2064 final String propValue = sa.getString(
2065 com.android.internal.R.styleable
2066 .AndroidManifestResourceOverlay_requiredSystemPropertyValue);
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002067 sa.recycle();
2068
2069 if (pkg.mOverlayTarget == null) {
2070 outError[0] = "<overlay> does not specify a target package";
2071 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2072 return null;
2073 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002074
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002075 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
2076 outError[0] = "<overlay> priority must be between 0 and 9999";
2077 mParseError =
2078 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2079 return null;
2080 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002081
2082 // check to see if overlay should be excluded based on system property condition
2083 if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
2084 Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
2085 + pkg.baseCodePath+ ": overlay ignored due to required system property: "
2086 + propName + " with value: " + propValue);
2087 return null;
Jaekyun Seok04342892017-03-02 15:24:19 +09002088 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002089
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002090 XmlUtils.skipCurrentTag(parser);
2091
Svet Ganov354cd3c2015-12-17 11:35:04 -08002092 } else if (tagName.equals(TAG_KEY_SETS)) {
2093 if (!parseKeySets(pkg, res, parser, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08002094 return null;
2095 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002096 } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002097 if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002098 return null;
2099 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002100 } else if (tagName.equals(TAG_PERMISSION)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002101 if (!parsePermission(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002102 return null;
2103 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002104 } else if (tagName.equals(TAG_PERMISSION_TREE)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002105 if (!parsePermissionTree(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002106 return null;
2107 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002108 } else if (tagName.equals(TAG_USES_PERMISSION)) {
2109 if (!parseUsesPermission(pkg, res, parser)) {
Svetoslav96a77162015-04-03 13:58:33 -07002110 return null;
2111 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002112 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
2113 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
2114 if (!parseUsesPermission(pkg, res, parser)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002115 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002116 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002117 } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002118 ConfigurationInfo cPref = new ConfigurationInfo();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002119 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002120 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
2121 cPref.reqTouchScreen = sa.getInt(
2122 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
2123 Configuration.TOUCHSCREEN_UNDEFINED);
2124 cPref.reqKeyboardType = sa.getInt(
2125 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
2126 Configuration.KEYBOARD_UNDEFINED);
2127 if (sa.getBoolean(
2128 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
2129 false)) {
2130 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
2131 }
2132 cPref.reqNavigation = sa.getInt(
2133 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
2134 Configuration.NAVIGATION_UNDEFINED);
2135 if (sa.getBoolean(
2136 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
2137 false)) {
2138 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
2139 }
2140 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002141 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142
2143 XmlUtils.skipCurrentTag(parser);
2144
Svet Ganov354cd3c2015-12-17 11:35:04 -08002145 } else if (tagName.equals(TAG_USES_FEATURE)) {
2146 FeatureInfo fi = parseUsesFeature(res, parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002147 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
2148
Dianne Hackborn49237342009-08-27 20:08:01 -07002149 if (fi.name == null) {
2150 ConfigurationInfo cPref = new ConfigurationInfo();
2151 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002152 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07002153 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07002154
2155 XmlUtils.skipCurrentTag(parser);
2156
Svet Ganov354cd3c2015-12-17 11:35:04 -08002157 } else if (tagName.equals(TAG_FEATURE_GROUP)) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002158 FeatureGroupInfo group = new FeatureGroupInfo();
2159 ArrayList<FeatureInfo> features = null;
2160 final int innerDepth = parser.getDepth();
2161 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2162 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2163 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2164 continue;
2165 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07002166
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002167 final String innerTagName = parser.getName();
2168 if (innerTagName.equals("uses-feature")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002169 FeatureInfo featureInfo = parseUsesFeature(res, parser);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002170 // FeatureGroups are stricter and mandate that
2171 // any <uses-feature> declared are mandatory.
2172 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
2173 features = ArrayUtils.add(features, featureInfo);
2174 } else {
2175 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
2176 " at " + mArchiveSourcePath + " " +
2177 parser.getPositionDescription());
2178 }
2179 XmlUtils.skipCurrentTag(parser);
2180 }
2181
2182 if (features != null) {
2183 group.features = new FeatureInfo[features.size()];
2184 group.features = features.toArray(group.features);
2185 }
2186 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07002187
Svet Ganov354cd3c2015-12-17 11:35:04 -08002188 } else if (tagName.equals(TAG_USES_SDK)) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07002189 if (SDK_VERSION > 0) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002190 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002191 com.android.internal.R.styleable.AndroidManifestUsesSdk);
2192
Todd Kennedy4f657082016-06-28 10:31:05 -07002193 int minVers = 1;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002194 String minCode = null;
2195 int targetVers = 0;
2196 String targetCode = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002197
Dianne Hackborn851a5412009-05-08 12:06:44 -07002198 TypedValue val = sa.peekValue(
2199 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
2200 if (val != null) {
2201 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
Colin Crossf61f9e32018-06-18 11:47:45 -07002202 minCode = val.string.toString();
Dianne Hackborn851a5412009-05-08 12:06:44 -07002203 } else {
2204 // If it's not a string, it's an integer.
Colin Crossf61f9e32018-06-18 11:47:45 -07002205 minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002206 }
2207 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002208
Dianne Hackborn851a5412009-05-08 12:06:44 -07002209 val = sa.peekValue(
2210 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
2211 if (val != null) {
2212 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
Todd Kennedy89d60182016-03-11 11:18:32 -08002213 targetCode = val.string.toString();
2214 if (minCode == null) {
2215 minCode = targetCode;
2216 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002217 } else {
2218 // If it's not a string, it's an integer.
2219 targetVers = val.data;
2220 }
Colin Crossf61f9e32018-06-18 11:47:45 -07002221 } else {
2222 targetVers = minVers;
2223 targetCode = minCode;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002224 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002226 sa.recycle();
2227
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002228 final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode,
2229 SDK_VERSION, SDK_CODENAMES, outError);
2230 if (minSdkVersion < 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002231 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2232 return null;
2233 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002234
Patrick Baumannccb20b82018-01-08 13:22:46 -08002235 boolean defaultToCurrentDevBranch = (flags & PARSE_FORCE_SDK) != 0;
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002236 final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002237 targetCode, SDK_CODENAMES, outError, defaultToCurrentDevBranch);
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002238 if (targetSdkVersion < 0) {
2239 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2240 return null;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002241 }
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002242
2243 pkg.applicationInfo.minSdkVersion = minSdkVersion;
2244 pkg.applicationInfo.targetSdkVersion = targetSdkVersion;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002245 }
2246
2247 XmlUtils.skipCurrentTag(parser);
2248
Svet Ganov354cd3c2015-12-17 11:35:04 -08002249 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
2250 sa = res.obtainAttributes(parser,
Dianne Hackborn723738c2009-06-25 19:48:04 -07002251 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
2252
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002253 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
2254 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
2255 0);
2256 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
2257 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
2258 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07002259 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
2260 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
2261 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002262
Dianne Hackborn723738c2009-06-25 19:48:04 -07002263 // This is a trick to get a boolean and still able to detect
2264 // if a value was actually set.
2265 supportsSmallScreens = sa.getInteger(
2266 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
2267 supportsSmallScreens);
2268 supportsNormalScreens = sa.getInteger(
2269 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
2270 supportsNormalScreens);
2271 supportsLargeScreens = sa.getInteger(
2272 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
2273 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002274 supportsXLargeScreens = sa.getInteger(
2275 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
2276 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002277 resizeable = sa.getInteger(
2278 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002279 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002280 anyDensity = sa.getInteger(
2281 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
2282 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07002283
2284 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002285
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002286 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002287
Svet Ganov354cd3c2015-12-17 11:35:04 -08002288 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
2289 sa = res.obtainAttributes(parser,
Dianne Hackborn854060af2009-07-09 18:14:31 -07002290 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
2291
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002292 // Note: don't allow this value to be a reference to a resource
2293 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07002294 String name = sa.getNonResourceString(
2295 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
2296
2297 sa.recycle();
2298
Todd Kennedy232d29e2017-11-06 14:45:53 -08002299 if (name != null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002300 if (pkg.protectedBroadcasts == null) {
2301 pkg.protectedBroadcasts = new ArrayList<String>();
2302 }
2303 if (!pkg.protectedBroadcasts.contains(name)) {
2304 pkg.protectedBroadcasts.add(name.intern());
2305 }
2306 }
2307
2308 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002309
Svet Ganov354cd3c2015-12-17 11:35:04 -08002310 } else if (tagName.equals(TAG_INSTRUMENTATION)) {
2311 if (parseInstrumentation(pkg, res, parser, outError) == null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002312 return null;
2313 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002314 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
2315 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002316 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2317
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002318 String orig =sa.getNonConfigurationString(
2319 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002320 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002321 if (pkg.mOriginalPackages == null) {
2322 pkg.mOriginalPackages = new ArrayList<String>();
2323 pkg.mRealPackage = pkg.packageName;
2324 }
2325 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002326 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002327
2328 sa.recycle();
2329
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002330 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002331
Svet Ganov354cd3c2015-12-17 11:35:04 -08002332 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
2333 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002334 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2335
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002336 String name = sa.getNonConfigurationString(
2337 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002338
2339 sa.recycle();
2340
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002341 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002342 if (pkg.mAdoptPermissions == null) {
2343 pkg.mAdoptPermissions = new ArrayList<String>();
2344 }
2345 pkg.mAdoptPermissions.add(name);
2346 }
2347
2348 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002349
Svet Ganov354cd3c2015-12-17 11:35:04 -08002350 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002351 // Just skip this tag
2352 XmlUtils.skipCurrentTag(parser);
2353 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002354
Svet Ganov354cd3c2015-12-17 11:35:04 -08002355 } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002356 // Just skip this tag
2357 XmlUtils.skipCurrentTag(parser);
2358 continue;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002359 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
Michael Wrighteaeb1902013-09-05 18:15:57 -07002360 XmlUtils.skipCurrentTag(parser);
2361 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002362
Svet Ganov354cd3c2015-12-17 11:35:04 -08002363 } else if (tagName.equals(TAG_EAT_COMMENT)) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002364 // Just skip this tag
2365 XmlUtils.skipCurrentTag(parser);
2366 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002367
Svet Ganov354cd3c2015-12-17 11:35:04 -08002368 } else if (tagName.equals(TAG_PACKAGE)) {
Svet Ganova7532cf2016-05-02 08:13:17 -07002369 if (!MULTI_PACKAGE_APK_ENABLED) {
2370 XmlUtils.skipCurrentTag(parser);
2371 continue;
2372 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002373 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
2374 // If parsing a child failed the error is already set
2375 return null;
2376 }
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002377
2378 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
2379 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
2380 sa = res.obtainAttributes(parser,
2381 com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
2382 final String hash = sa.getNonConfigurationString(
2383 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
2384 sa.recycle();
2385
2386 pkg.restrictUpdateHash = null;
2387 if (hash != null) {
2388 final int hashLength = hash.length();
2389 final byte[] hashBytes = new byte[hashLength / 2];
2390 for (int i = 0; i < hashLength; i += 2){
2391 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
2392 + Character.digit(hash.charAt(i + 1), 16));
2393 }
2394 pkg.restrictUpdateHash = hashBytes;
2395 }
2396 }
2397
2398 XmlUtils.skipCurrentTag(parser);
2399
Dianne Hackborn854060af2009-07-09 18:14:31 -07002400 } else if (RIGID_PARSER) {
2401 outError[0] = "Bad element under <manifest>: "
2402 + parser.getName();
2403 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2404 return null;
2405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002406 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002407 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002408 + " at " + mArchiveSourcePath + " "
2409 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002410 XmlUtils.skipCurrentTag(parser);
2411 continue;
2412 }
2413 }
2414
2415 if (!foundApp && pkg.instrumentation.size() == 0) {
2416 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
2417 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
2418 }
2419
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002420 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002421 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002422 for (int ip=0; ip<NP; ip++) {
2423 final PackageParser.NewPermissionInfo npi
2424 = PackageParser.NEW_PERMISSIONS[ip];
2425 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
2426 break;
2427 }
2428 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002429 if (implicitPerms == null) {
2430 implicitPerms = new StringBuilder(128);
2431 implicitPerms.append(pkg.packageName);
2432 implicitPerms.append(": compat added ");
2433 } else {
2434 implicitPerms.append(' ');
2435 }
2436 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002437 pkg.requestedPermissions.add(npi.name);
2438 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002439 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002440 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002441 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002442 }
Dianne Hackborn79245122012-03-12 10:51:26 -07002443
2444 final int NS = PackageParser.SPLIT_PERMISSIONS.length;
2445 for (int is=0; is<NS; is++) {
2446 final PackageParser.SplitPermissionInfo spi
2447 = PackageParser.SPLIT_PERMISSIONS[is];
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -07002448 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
2449 || !pkg.requestedPermissions.contains(spi.rootPerm)) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07002450 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07002451 }
2452 for (int in=0; in<spi.newPerms.length; in++) {
2453 final String perm = spi.newPerms[in];
2454 if (!pkg.requestedPermissions.contains(perm)) {
2455 pkg.requestedPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07002456 }
2457 }
2458 }
2459
Dianne Hackborn723738c2009-06-25 19:48:04 -07002460 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
2461 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002462 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002463 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
2464 }
2465 if (supportsNormalScreens != 0) {
2466 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
2467 }
2468 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
2469 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002470 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002471 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
2472 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002473 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
2474 && pkg.applicationInfo.targetSdkVersion
2475 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
2476 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
2477 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002478 if (resizeable < 0 || (resizeable > 0
2479 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002480 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002481 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
2482 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002483 if (anyDensity < 0 || (anyDensity > 0
2484 && pkg.applicationInfo.targetSdkVersion
2485 >= android.os.Build.VERSION_CODES.DONUT)) {
2486 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07002487 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07002488
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002489 // At this point we can check if an application is not supporting densities and hence
2490 // cannot be windowed / resized. Note that an SDK version of 0 is common for
2491 // pre-Doughnut applications.
2492 if (pkg.applicationInfo.usesCompatibilityMode()) {
Winson Chungd3395382016-12-13 11:49:09 -08002493 adjustPackageToBeUnresizeableAndUnpipable(pkg);
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002495 return pkg;
2496 }
2497
Todd Leeea2f3be2017-03-16 14:00:52 -07002498 private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
2499
2500 if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
2501 if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
2502 // malformed condition - incomplete
2503 Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
2504 + "=" + propValue + "' - require both requiredSystemPropertyName"
2505 + " AND requiredSystemPropertyValue to be specified.");
2506 return false;
2507 }
2508 // no valid condition set - so no exclusion criteria, overlay will be included.
2509 return true;
2510 }
2511
2512 // check property value - make sure it is both set and equal to expected value
2513 final String currValue = SystemProperties.get(propName);
2514 return (currValue != null && currValue.equals(propValue));
2515 }
2516
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002517 /**
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002518 * This is a pre-density application which will get scaled - instead of being pixel perfect.
2519 * This type of application is not resizable.
2520 *
2521 * @param pkg The package which needs to be marked as unresizable.
2522 */
Winson Chungd3395382016-12-13 11:49:09 -08002523 private void adjustPackageToBeUnresizeableAndUnpipable(Package pkg) {
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002524 for (Activity a : pkg.activities) {
2525 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -08002526 a.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE;
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002527 }
2528 }
2529
2530 /**
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002531 * Computes the targetSdkVersion to use at runtime. If the package is not
2532 * compatible with this platform, populates {@code outError[0]} with an
2533 * error message.
2534 * <p>
2535 * If {@code targetCode} is not specified, e.g. the value is {@code null},
2536 * then the {@code targetVers} will be returned unmodified.
2537 * <p>
2538 * Otherwise, the behavior varies based on whether the current platform
2539 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2540 * has length > 0:
2541 * <ul>
2542 * <li>If this is a pre-release platform and the value specified by
2543 * {@code targetCode} is contained within the array of allowed pre-release
2544 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2545 * <li>If this is a released platform, this method will return -1 to
2546 * indicate that the package is not compatible with this platform.
2547 * </ul>
2548 *
2549 * @param targetVers targetSdkVersion number, if specified in the
2550 * application manifest, or 0 otherwise
2551 * @param targetCode targetSdkVersion code, if specified in the application
2552 * manifest, or {@code null} otherwise
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002553 * @param platformSdkCodenames array of allowed pre-release SDK codenames
2554 * for this platform
2555 * @param outError output array to populate with error, if applicable
Patrick Baumannccb20b82018-01-08 13:22:46 -08002556 * @param forceCurrentDev if development target code is not available, use the current
2557 * development version by default.
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002558 * @return the targetSdkVersion to use at runtime, or -1 if the package is
2559 * not compatible with this platform
2560 * @hide Exposed for unit testing only.
2561 */
2562 @TestApi
2563 public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002564 @Nullable String targetCode, @NonNull String[] platformSdkCodenames,
2565 @NonNull String[] outError, boolean forceCurrentDev) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002566 // If it's a release SDK, return the version number unmodified.
2567 if (targetCode == null) {
2568 return targetVers;
2569 }
2570
2571 // If it's a pre-release SDK and the codename matches this platform, it
2572 // definitely targets this SDK.
Patrick Baumannccb20b82018-01-08 13:22:46 -08002573 if (ArrayUtils.contains(platformSdkCodenames, targetCode) || forceCurrentDev) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002574 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2575 }
2576
2577 // Otherwise, we're looking at an incompatible pre-release SDK.
2578 if (platformSdkCodenames.length > 0) {
2579 outError[0] = "Requires development platform " + targetCode
2580 + " (current platform is any of "
2581 + Arrays.toString(platformSdkCodenames) + ")";
2582 } else {
2583 outError[0] = "Requires development platform " + targetCode
2584 + " but this is a release platform.";
2585 }
2586 return -1;
2587 }
2588
2589 /**
2590 * Computes the minSdkVersion to use at runtime. If the package is not
2591 * compatible with this platform, populates {@code outError[0]} with an
2592 * error message.
2593 * <p>
2594 * If {@code minCode} is not specified, e.g. the value is {@code null},
2595 * then behavior varies based on the {@code platformSdkVersion}:
2596 * <ul>
2597 * <li>If the platform SDK version is greater than or equal to the
2598 * {@code minVers}, returns the {@code mniVers} unmodified.
2599 * <li>Otherwise, returns -1 to indicate that the package is not
2600 * compatible with this platform.
2601 * </ul>
2602 * <p>
2603 * Otherwise, the behavior varies based on whether the current platform
2604 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2605 * has length > 0:
2606 * <ul>
2607 * <li>If this is a pre-release platform and the value specified by
2608 * {@code targetCode} is contained within the array of allowed pre-release
2609 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2610 * <li>If this is a released platform, this method will return -1 to
2611 * indicate that the package is not compatible with this platform.
2612 * </ul>
2613 *
2614 * @param minVers minSdkVersion number, if specified in the application
2615 * manifest, or 1 otherwise
2616 * @param minCode minSdkVersion code, if specified in the application
2617 * manifest, or {@code null} otherwise
2618 * @param platformSdkVersion platform SDK version number, typically
2619 * Build.VERSION.SDK_INT
2620 * @param platformSdkCodenames array of allowed prerelease SDK codenames
2621 * for this platform
2622 * @param outError output array to populate with error, if applicable
2623 * @return the minSdkVersion to use at runtime, or -1 if the package is not
2624 * compatible with this platform
2625 * @hide Exposed for unit testing only.
2626 */
2627 @TestApi
2628 public static int computeMinSdkVersion(@IntRange(from = 1) int minVers,
2629 @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion,
2630 @NonNull String[] platformSdkCodenames, @NonNull String[] outError) {
2631 // If it's a release SDK, make sure we meet the minimum SDK requirement.
2632 if (minCode == null) {
2633 if (minVers <= platformSdkVersion) {
2634 return minVers;
2635 }
2636
2637 // We don't meet the minimum SDK requirement.
2638 outError[0] = "Requires newer sdk version #" + minVers
2639 + " (current version is #" + platformSdkVersion + ")";
2640 return -1;
2641 }
2642
2643 // If it's a pre-release SDK and the codename matches this platform, we
2644 // definitely meet the minimum SDK requirement.
2645 if (ArrayUtils.contains(platformSdkCodenames, minCode)) {
2646 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2647 }
2648
2649 // Otherwise, we're looking at an incompatible pre-release SDK.
2650 if (platformSdkCodenames.length > 0) {
2651 outError[0] = "Requires development platform " + minCode
2652 + " (current platform is any of "
2653 + Arrays.toString(platformSdkCodenames) + ")";
2654 } else {
2655 outError[0] = "Requires development platform " + minCode
2656 + " but this is a release platform.";
2657 }
2658 return -1;
2659 }
2660
Todd Kennedy27c24fb2015-09-17 16:49:25 -07002661 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002662 FeatureInfo fi = new FeatureInfo();
2663 TypedArray sa = res.obtainAttributes(attrs,
2664 com.android.internal.R.styleable.AndroidManifestUsesFeature);
2665 // Note: don't allow this value to be a reference to a resource
2666 // that may change.
2667 fi.name = sa.getNonResourceString(
2668 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
Jeff Sharkey115d2c12016-02-15 17:25:57 -07002669 fi.version = sa.getInt(
2670 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002671 if (fi.name == null) {
2672 fi.reqGlEsVersion = sa.getInt(
2673 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
2674 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2675 }
2676 if (sa.getBoolean(
2677 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
2678 fi.flags |= FeatureInfo.FLAG_REQUIRED;
2679 }
2680 sa.recycle();
2681 return fi;
2682 }
2683
Svet Ganov67882122016-12-11 16:36:34 -08002684 private boolean parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser,
2685 String[] outError) throws XmlPullParserException, IOException {
2686 TypedArray sa = res.obtainAttributes(parser,
2687 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary);
2688
2689 // Note: don't allow this value to be a reference to a resource that may change.
2690 String lname = sa.getNonResourceString(
2691 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
2692 final int version = sa.getInt(
2693 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002694 String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable
Svet Ganov67882122016-12-11 16:36:34 -08002695 .AndroidManifestUsesStaticLibrary_certDigest);
2696 sa.recycle();
2697
2698 // Since an APK providing a static shared lib can only provide the lib - fail if malformed
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002699 if (lname == null || version < 0 || certSha256Digest == null) {
Svet Ganov67882122016-12-11 16:36:34 -08002700 outError[0] = "Bad uses-static-library declaration name: " + lname + " version: "
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002701 + version + " certDigest" + certSha256Digest;
Svet Ganov67882122016-12-11 16:36:34 -08002702 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2703 XmlUtils.skipCurrentTag(parser);
2704 return false;
2705 }
2706
2707 // Can depend only on one version of the same library
2708 if (pkg.usesStaticLibraries != null && pkg.usesStaticLibraries.contains(lname)) {
2709 outError[0] = "Depending on multiple versions of static library " + lname;
2710 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2711 XmlUtils.skipCurrentTag(parser);
2712 return false;
2713 }
2714
2715 lname = lname.intern();
2716 // We allow ":" delimiters in the SHA declaration as this is the format
2717 // emitted by the certtool making it easy for developers to copy/paste.
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002718 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2719
2720 // Fot apps targeting O-MR1 we require explicit enumeration of all certs.
2721 String[] additionalCertSha256Digests = EmptyArray.STRING;
Jeff Sharkeyaa1a9112018-04-10 15:18:12 -06002722 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O_MR1) {
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002723 additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError);
2724 if (additionalCertSha256Digests == null) {
2725 return false;
2726 }
2727 } else {
2728 XmlUtils.skipCurrentTag(parser);
2729 }
2730
2731 final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1];
2732 certSha256Digests[0] = certSha256Digest;
2733 System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
2734 1, additionalCertSha256Digests.length);
2735
Svet Ganov67882122016-12-11 16:36:34 -08002736 pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname);
Dianne Hackborn3accca02013-09-20 09:32:11 -07002737 pkg.usesStaticLibrariesVersions = ArrayUtils.appendLong(
Svet Ganov8a10ef52017-02-16 20:58:09 -08002738 pkg.usesStaticLibrariesVersions, version, true);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002739 pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
2740 pkg.usesStaticLibrariesCertDigests, certSha256Digests, true);
Svet Ganov67882122016-12-11 16:36:34 -08002741
2742 return true;
2743 }
2744
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002745 private String[] parseAdditionalCertificates(Resources resources, XmlResourceParser parser,
2746 String[] outError) throws XmlPullParserException, IOException {
2747 String[] certSha256Digests = EmptyArray.STRING;
2748
2749 int outerDepth = parser.getDepth();
2750 int type;
2751 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2752 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2753 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2754 continue;
2755 }
2756
2757 final String nodeName = parser.getName();
2758 if (nodeName.equals("additional-certificate")) {
2759 final TypedArray sa = resources.obtainAttributes(parser, com.android.internal.
2760 R.styleable.AndroidManifestAdditionalCertificate);
2761 String certSha256Digest = sa.getNonResourceString(com.android.internal.
2762 R.styleable.AndroidManifestAdditionalCertificate_certDigest);
2763 sa.recycle();
2764
2765 if (TextUtils.isEmpty(certSha256Digest)) {
2766 outError[0] = "Bad additional-certificate declaration with empty"
2767 + " certDigest:" + certSha256Digest;
2768 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2769 XmlUtils.skipCurrentTag(parser);
2770 sa.recycle();
2771 return null;
2772 }
2773
2774 // We allow ":" delimiters in the SHA declaration as this is the format
2775 // emitted by the certtool making it easy for developers to copy/paste.
2776 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2777 certSha256Digests = ArrayUtils.appendElement(String.class,
2778 certSha256Digests, certSha256Digest);
2779 } else {
2780 XmlUtils.skipCurrentTag(parser);
2781 }
2782 }
2783
2784 return certSha256Digests;
2785 }
2786
Svet Ganov354cd3c2015-12-17 11:35:04 -08002787 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
2788 throws XmlPullParserException, IOException {
2789 TypedArray sa = res.obtainAttributes(parser,
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002790 com.android.internal.R.styleable.AndroidManifestUsesPermission);
2791
2792 // Note: don't allow this value to be a reference to a resource
2793 // that may change.
2794 String name = sa.getNonResourceString(
2795 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002796
Christopher Tatefb0676a2013-09-16 16:34:52 -07002797 int maxSdkVersion = 0;
2798 TypedValue val = sa.peekValue(
2799 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
2800 if (val != null) {
2801 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
2802 maxSdkVersion = val.data;
2803 }
2804 }
2805
Dianne Hackborncd154e92017-02-28 17:37:35 -08002806 final String requiredFeature = sa.getNonConfigurationString(
2807 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
2808
2809 final String requiredNotfeature = sa.getNonConfigurationString(
2810 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
2811
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002812 sa.recycle();
2813
Dianne Hackborncd154e92017-02-28 17:37:35 -08002814 XmlUtils.skipCurrentTag(parser);
2815
2816 if (name == null) {
2817 return true;
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002818 }
2819
Dianne Hackborncd154e92017-02-28 17:37:35 -08002820 if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
2821 return true;
2822 }
2823
2824 // Only allow requesting this permission if the platform supports the given feature.
2825 if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
2826 return true;
2827 }
2828
2829 // Only allow requesting this permission if the platform doesn't support the given feature.
2830 if (requiredNotfeature != null && mCallback != null
2831 && mCallback.hasFeature(requiredNotfeature)) {
2832 return true;
2833 }
2834
2835 int index = pkg.requestedPermissions.indexOf(name);
2836 if (index == -1) {
2837 pkg.requestedPermissions.add(name.intern());
2838 } else {
2839 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
2840 + name + " in package: " + pkg.packageName + " at: "
2841 + parser.getPositionDescription());
2842 }
2843
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002844 return true;
2845 }
2846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002847 private static String buildClassName(String pkg, CharSequence clsSeq,
2848 String[] outError) {
2849 if (clsSeq == null || clsSeq.length() <= 0) {
2850 outError[0] = "Empty class name in package " + pkg;
2851 return null;
2852 }
2853 String cls = clsSeq.toString();
2854 char c = cls.charAt(0);
2855 if (c == '.') {
Narayan Kamath07ac1442017-02-10 15:08:07 +00002856 return pkg + cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002857 }
2858 if (cls.indexOf('.') < 0) {
2859 StringBuilder b = new StringBuilder(pkg);
2860 b.append('.');
2861 b.append(cls);
Narayan Kamath07ac1442017-02-10 15:08:07 +00002862 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002863 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002864 return cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002865 }
2866
2867 private static String buildCompoundName(String pkg,
2868 CharSequence procSeq, String type, String[] outError) {
2869 String proc = procSeq.toString();
2870 char c = proc.charAt(0);
2871 if (pkg != null && c == ':') {
2872 if (proc.length() < 2) {
2873 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
2874 + ": must be at least two characters";
2875 return null;
2876 }
2877 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002878 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002879 if (nameError != null) {
2880 outError[0] = "Invalid " + type + " name " + proc + " in package "
2881 + pkg + ": " + nameError;
2882 return null;
2883 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002884 return pkg + proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002885 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002886 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 if (nameError != null && !"system".equals(proc)) {
2888 outError[0] = "Invalid " + type + " name " + proc + " in package "
2889 + pkg + ": " + nameError;
2890 return null;
2891 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002892 return proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002893 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002895 private static String buildProcessName(String pkg, String defProc,
2896 CharSequence procSeq, int flags, String[] separateProcesses,
2897 String[] outError) {
2898 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
2899 return defProc != null ? defProc : pkg;
2900 }
2901 if (separateProcesses != null) {
2902 for (int i=separateProcesses.length-1; i>=0; i--) {
2903 String sp = separateProcesses[i];
2904 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
2905 return pkg;
2906 }
2907 }
2908 }
2909 if (procSeq == null || procSeq.length() <= 0) {
2910 return defProc;
2911 }
Makoto Onuki812d188a2017-08-07 09:58:23 -07002912 return TextUtils.safeIntern(buildCompoundName(pkg, procSeq, "process", outError));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002913 }
2914
2915 private static String buildTaskAffinityName(String pkg, String defProc,
2916 CharSequence procSeq, String[] outError) {
2917 if (procSeq == null) {
2918 return defProc;
2919 }
2920 if (procSeq.length() <= 0) {
2921 return null;
2922 }
2923 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
2924 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002925
dcashman989eb3712014-06-17 12:56:12 -07002926 private boolean parseKeySets(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002927 XmlResourceParser parser, String[] outError)
Geremy Condraf1bcca82013-01-07 22:35:24 -08002928 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07002929 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08002930 // all the keys and keysets that we want must be defined here
2931 // so we're going to iterate over the parser and pull out the things we want
2932 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07002933 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002934 int type;
dcashman989eb3712014-06-17 12:56:12 -07002935 String currentKeySet = null;
2936 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
2937 ArraySet<String> upgradeKeySets = new ArraySet<String>();
2938 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
2939 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08002940 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2941 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2942 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07002943 if (parser.getDepth() == currentKeySetDepth) {
2944 currentKeySet = null;
2945 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07002946 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002947 continue;
2948 }
dcashman989eb3712014-06-17 12:56:12 -07002949 String tagName = parser.getName();
2950 if (tagName.equals("key-set")) {
2951 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07002952 outError[0] = "Improperly nested 'key-set' tag at "
2953 + parser.getPositionDescription();
2954 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002955 return false;
2956 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002957 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002958 com.android.internal.R.styleable.AndroidManifestKeySet);
2959 final String keysetName = sa.getNonResourceString(
2960 com.android.internal.R.styleable.AndroidManifestKeySet_name);
2961 definedKeySets.put(keysetName, new ArraySet<String>());
2962 currentKeySet = keysetName;
2963 currentKeySetDepth = parser.getDepth();
2964 sa.recycle();
2965 } else if (tagName.equals("public-key")) {
2966 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002967 outError[0] = "Improperly nested 'key-set' tag at "
2968 + parser.getPositionDescription();
2969 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002970 return false;
2971 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002972 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002973 com.android.internal.R.styleable.AndroidManifestPublicKey);
2974 final String publicKeyName = sa.getNonResourceString(
2975 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002976 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07002977 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
2978 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002979 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
2980 + " on first use at " + parser.getPositionDescription();
2981 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07002982 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002983 return false;
2984 } else if (encodedKey != null) {
2985 PublicKey currentKey = parsePublicKey(encodedKey);
2986 if (currentKey == null) {
2987 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
2988 + parser.getPositionDescription() + " key-set " + currentKeySet
2989 + " will not be added to the package's defined key-sets.");
2990 sa.recycle();
2991 improperKeySets.add(currentKeySet);
2992 XmlUtils.skipCurrentTag(parser);
2993 continue;
2994 }
2995 if (publicKeys.get(publicKeyName) == null
2996 || publicKeys.get(publicKeyName).equals(currentKey)) {
2997
2998 /* public-key first definition, or matches old definition */
2999 publicKeys.put(publicKeyName, currentKey);
3000 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003001 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07003002 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07003003 + parser.getPositionDescription();
3004 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003005 sa.recycle();
3006 return false;
3007 }
Kenny Root37dca152013-07-10 14:01:49 -07003008 }
dcashman989eb3712014-06-17 12:56:12 -07003009 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003010 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003011 XmlUtils.skipCurrentTag(parser);
3012 } else if (tagName.equals("upgrade-key-set")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003013 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003014 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
3015 String name = sa.getNonResourceString(
3016 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
3017 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003018 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003019 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003020 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07003021 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003022 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07003023 + parser.getPositionDescription();
3024 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003025 return false;
3026 } else {
dcashman989eb3712014-06-17 12:56:12 -07003027 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003028 + " at " + mArchiveSourcePath + " "
3029 + parser.getPositionDescription());
3030 XmlUtils.skipCurrentTag(parser);
3031 continue;
3032 }
3033 }
dcashman989eb3712014-06-17 12:56:12 -07003034 Set<String> publicKeyNames = publicKeys.keySet();
3035 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07003036 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
3037 + "'key-set' and 'public-key' names must be distinct.";
3038 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003039 return false;
3040 }
3041 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
3042 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
3043 final String keySetName = e.getKey();
3044 if (e.getValue().size() == 0) {
3045 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3046 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
3047 + " Not including in package's defined key-sets.");
3048 continue;
3049 } else if (improperKeySets.contains(keySetName)) {
3050 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3051 + "'key-set' " + keySetName + " contained improper 'public-key'"
3052 + " tags. Not including in package's defined key-sets.");
3053 continue;
3054 }
3055 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
3056 for (String s : e.getValue()) {
3057 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08003058 }
3059 }
dcashman989eb3712014-06-17 12:56:12 -07003060 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
3061 owner.mUpgradeKeySets = upgradeKeySets;
3062 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003063 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
3064 + "does not define all 'upgrade-key-set's .";
3065 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003066 return false;
3067 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003068 return true;
3069 }
3070
Dianne Hackborncd154e92017-02-28 17:37:35 -08003071 private boolean parsePermissionGroup(Package owner, int flags, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003072 XmlResourceParser parser, String[] outError)
3073 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003074 PermissionGroup perm = new PermissionGroup(owner);
3075
Svet Ganov354cd3c2015-12-17 11:35:04 -08003076 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003077 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003078 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003079 "<permission-group>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003080 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
3081 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003082 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003083 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003084 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
3085 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 sa.recycle();
3087 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003088 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003089 }
3090
3091 perm.info.descriptionRes = sa.getResourceId(
3092 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
3093 0);
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003094 perm.info.requestRes = sa.getResourceId(
3095 com.android.internal.R.styleable.AndroidManifestPermissionGroup_request, 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07003096 perm.info.flags = sa.getInt(
3097 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07003098 perm.info.priority = sa.getInt(
3099 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100
3101 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003102
Svet Ganov354cd3c2015-12-17 11:35:04 -08003103 if (!parseAllMetaData(res, parser, "<permission-group>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003104 outError)) {
3105 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003106 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003107 }
3108
3109 owner.permissionGroups.add(perm);
3110
Dianne Hackborncd154e92017-02-28 17:37:35 -08003111 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003112 }
3113
Dianne Hackborncd154e92017-02-28 17:37:35 -08003114 private boolean parsePermission(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003115 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003116 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003117
Svet Ganov354cd3c2015-12-17 11:35:04 -08003118 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003119 com.android.internal.R.styleable.AndroidManifestPermission);
3120
Dianne Hackborncd154e92017-02-28 17:37:35 -08003121 Permission perm = new Permission(owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003122 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003123 "<permission>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003124 com.android.internal.R.styleable.AndroidManifestPermission_name,
3125 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003126 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003127 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003128 com.android.internal.R.styleable.AndroidManifestPermission_logo,
3129 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003130 sa.recycle();
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
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003135 // Note: don't allow this value to be a reference to a resource
3136 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003137 perm.info.group = sa.getNonResourceString(
3138 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
3139 if (perm.info.group != null) {
3140 perm.info.group = perm.info.group.intern();
3141 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003142
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003143 perm.info.descriptionRes = sa.getResourceId(
3144 com.android.internal.R.styleable.AndroidManifestPermission_description,
3145 0);
3146
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003147 perm.info.requestRes = sa.getResourceId(
3148 com.android.internal.R.styleable.AndroidManifestPermission_request, 0);
3149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003150 perm.info.protectionLevel = sa.getInt(
3151 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
3152 PermissionInfo.PROTECTION_NORMAL);
3153
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07003154 perm.info.flags = sa.getInt(
3155 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
3156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003157 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08003158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003159 if (perm.info.protectionLevel == -1) {
3160 outError[0] = "<permission> does not specify protectionLevel";
3161 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003162 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003163 }
Dianne Hackborne639da72012-02-21 15:11:13 -08003164
3165 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
3166
Makoto Onuki700feef2018-02-15 10:59:41 -08003167 if (perm.info.getProtectionFlags() != 0) {
Todd Kennedyc247fa12017-06-02 10:29:22 -07003168 if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_INSTANT) == 0
Chad Brubakera5d70a12017-03-23 11:04:50 -07003169 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0
Chad Brubakerc19706a2016-10-13 15:44:59 -07003170 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
Dianne Hackborne639da72012-02-21 15:11:13 -08003171 PermissionInfo.PROTECTION_SIGNATURE) {
Joe Maples39bb9e82018-01-11 11:09:46 -05003172 outError[0] = "<permission> protectionLevel specifies a non-instant flag but is "
Dianne Hackborne639da72012-02-21 15:11:13 -08003173 + "not based on signature type";
3174 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003175 return false;
Dianne Hackborne639da72012-02-21 15:11:13 -08003176 }
3177 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003178
Svet Ganov354cd3c2015-12-17 11:35:04 -08003179 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003181 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003182 }
3183
3184 owner.permissions.add(perm);
3185
Dianne Hackborncd154e92017-02-28 17:37:35 -08003186 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003187 }
3188
Dianne Hackborncd154e92017-02-28 17:37:35 -08003189 private boolean parsePermissionTree(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003190 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003191 throws XmlPullParserException, IOException {
3192 Permission perm = new Permission(owner);
3193
Svet Ganov354cd3c2015-12-17 11:35:04 -08003194 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195 com.android.internal.R.styleable.AndroidManifestPermissionTree);
3196
3197 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003198 "<permission-tree>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003199 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
3200 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003201 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003202 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003203 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
3204 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 sa.recycle();
3206 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 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003212 int index = perm.info.name.indexOf('.');
3213 if (index > 0) {
3214 index = perm.info.name.indexOf('.', index+1);
3215 }
3216 if (index < 0) {
3217 outError[0] = "<permission-tree> name has less than three segments: "
3218 + perm.info.name;
3219 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003220 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003221 }
3222
3223 perm.info.descriptionRes = 0;
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003224 perm.info.requestRes = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003225 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
3226 perm.tree = true;
3227
Svet Ganov354cd3c2015-12-17 11:35:04 -08003228 if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003229 outError)) {
3230 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003231 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003232 }
3233
3234 owner.permissions.add(perm);
3235
Dianne Hackborncd154e92017-02-28 17:37:35 -08003236 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237 }
3238
3239 private Instrumentation parseInstrumentation(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003240 XmlResourceParser parser, String[] outError)
3241 throws XmlPullParserException, IOException {
3242 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003243 com.android.internal.R.styleable.AndroidManifestInstrumentation);
3244
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003245 if (mParseInstrumentationArgs == null) {
3246 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
3247 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
3248 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003249 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003250 com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003251 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
3252 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003253 mParseInstrumentationArgs.tag = "<instrumentation>";
3254 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003255
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003256 mParseInstrumentationArgs.sa = sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003257
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003258 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
3259 new InstrumentationInfo());
3260 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003261 sa.recycle();
3262 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3263 return null;
3264 }
3265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003266 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003267 // Note: don't allow this value to be a reference to a resource
3268 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003269 str = sa.getNonResourceString(
3270 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
3271 a.info.targetPackage = str != null ? str.intern() : null;
3272
Dianne Hackborn34041732017-01-31 15:27:13 -08003273 str = sa.getNonResourceString(
Dianne Hackborn1be53542017-04-28 13:36:00 -07003274 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcesses);
3275 a.info.targetProcesses = str != null ? str.intern() : null;
Dianne Hackborn34041732017-01-31 15:27:13 -08003276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003277 a.info.handleProfiling = sa.getBoolean(
3278 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
3279 false);
3280
3281 a.info.functionalTest = sa.getBoolean(
3282 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
3283 false);
3284
3285 sa.recycle();
3286
3287 if (a.info.targetPackage == null) {
3288 outError[0] = "<instrumentation> does not specify targetPackage";
3289 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3290 return null;
3291 }
3292
Svet Ganov354cd3c2015-12-17 11:35:04 -08003293 if (!parseAllMetaData(res, parser, "<instrumentation>", a,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 outError)) {
3295 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3296 return null;
3297 }
3298
3299 owner.instrumentation.add(a);
3300
3301 return a;
3302 }
3303
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003304 /**
3305 * Parse the {@code application} XML tree at the current parse location in a
3306 * <em>base APK</em> manifest.
3307 * <p>
3308 * When adding new features, carefully consider if they should also be
3309 * supported by split APKs.
3310 */
3311 private boolean parseBaseApplication(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003312 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003313 throws XmlPullParserException, IOException {
3314 final ApplicationInfo ai = owner.applicationInfo;
3315 final String pkgName = owner.applicationInfo.packageName;
3316
Svet Ganov354cd3c2015-12-17 11:35:04 -08003317 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003318 com.android.internal.R.styleable.AndroidManifestApplication);
3319
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003320 if (!parsePackageItemInfo(owner, ai, outError,
3321 "<application>", sa, false /*nameRequired*/,
3322 com.android.internal.R.styleable.AndroidManifestApplication_name,
3323 com.android.internal.R.styleable.AndroidManifestApplication_label,
3324 com.android.internal.R.styleable.AndroidManifestApplication_icon,
3325 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
3326 com.android.internal.R.styleable.AndroidManifestApplication_logo,
3327 com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
3328 sa.recycle();
3329 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3330 return false;
3331 }
3332
3333 if (ai.name != null) {
Todd Kennedyafb52692016-08-22 15:44:00 -07003334 ai.className = ai.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003335 }
3336
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003337 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003338 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
3339 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 if (manageSpaceActivity != null) {
3341 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
3342 outError);
3343 }
3344
Christopher Tate181fafa2009-05-14 11:12:14 -07003345 boolean allowBackup = sa.getBoolean(
3346 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
3347 if (allowBackup) {
3348 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07003349
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003350 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
3351 // and restoreAnyVersion are only relevant if backup is possible for the
3352 // given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003353 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003354 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
3355 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07003356 if (backupAgent != null) {
3357 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07003358 if (DEBUG_BACKUP) {
3359 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003360 + " from " + pkgName + "+" + backupAgent);
3361 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003362
3363 if (sa.getBoolean(
3364 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
3365 true)) {
3366 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
3367 }
3368 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08003369 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
3370 false)) {
3371 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
3372 }
Christopher Tated1de2562014-06-17 17:12:35 -07003373 if (sa.getBoolean(
3374 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
3375 false)) {
3376 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
3377 }
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003378 if (sa.getBoolean(
3379 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
3380 false)) {
3381 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
3382 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003383 }
Matthew Williams303650c2015-04-17 18:22:51 -07003384
3385 TypedValue v = sa.peekValue(
3386 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
3387 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
3388 if (DEBUG_BACKUP) {
3389 Slog.v(TAG, "fullBackupContent specified as boolean=" +
3390 (v.data == 0 ? "false" : "true"));
3391 }
3392 // "false" => -1, "true" => 0
3393 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
3394 }
3395 if (DEBUG_BACKUP) {
3396 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
3397 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003398 }
Christopher Tate4a627c72011-04-01 14:43:32 -07003399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003400 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08003401 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003402 ai.descriptionRes = sa.getResourceId(
3403 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
3404
Todd Kennedy232d29e2017-11-06 14:45:53 -08003405 if (sa.getBoolean(
3406 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
3407 false)) {
3408 // Check if persistence is based on a feature being present
3409 final String requiredFeature = sa.getNonResourceString(com.android.internal.R.styleable
3410 .AndroidManifestApplication_persistentWhenFeatureAvailable);
3411 if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
3412 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003413 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07003414 }
3415
3416 if (sa.getBoolean(
3417 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
3418 false)) {
3419 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07003420 }
3421
3422 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
3423 .AndroidManifestApplication_restrictedAccountType);
3424 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
3425 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 }
3427
Amith Yamasaniccbe3892013-04-12 17:52:42 -07003428 String requiredAccountType = sa.getString(com.android.internal.R.styleable
3429 .AndroidManifestApplication_requiredAccountType);
3430 if (requiredAccountType != null && requiredAccountType.length() > 0) {
3431 owner.mRequiredAccountType = requiredAccountType;
3432 }
3433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003434 if (sa.getBoolean(
3435 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
3436 false)) {
3437 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
3438 }
3439
3440 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07003441 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08003442 false)) {
3443 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
3444 }
3445
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003446 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07003447 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07003448 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07003449 if (owner.baseHardwareAccelerated) {
3450 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
3451 }
Romain Guy812ccbe2010-06-01 14:07:24 -07003452
3453 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003454 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
3455 true)) {
3456 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
3457 }
3458
3459 if (sa.getBoolean(
3460 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
3461 false)) {
3462 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
3463 }
3464
3465 if (sa.getBoolean(
3466 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
3467 true)) {
3468 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
3469 }
3470
Svet Ganov354cd3c2015-12-17 11:35:04 -08003471 // The parent package controls installation, hence specify test only installs.
3472 if (owner.parentPackage == null) {
3473 if (sa.getBoolean(
3474 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
3475 false)) {
3476 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
3477 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003478 }
3479
Jason parksa3cdaa52011-01-13 14:15:43 -06003480 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003481 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06003482 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003483 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06003484 }
3485
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003486 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07003487 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
Chad Brubaker0d285d52018-03-14 09:00:04 -07003488 owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.P)) {
Alex Klyubin01a959d2015-03-18 10:05:45 -07003489 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
3490 }
3491
3492 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003493 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
3494 false /* default is no RTL support*/)) {
3495 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
3496 }
3497
Narayan Kamath589a1bc2014-07-03 14:43:26 +01003498 if (sa.getBoolean(
3499 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
3500 false)) {
3501 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
3502 }
3503
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07003504 if (sa.getBoolean(
3505 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
3506 true)) {
3507 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
3508 }
3509
Todd Kennedyd022ac22016-04-13 10:49:29 -07003510 if (sa.getBoolean(
3511 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
3512 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003513 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003514 }
Todd Kennedyd022ac22016-04-13 10:49:29 -07003515 if (sa.getBoolean(
3516 R.styleable.AndroidManifestApplication_directBootAware,
3517 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003518 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003519 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003520
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003521 if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
3522 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003523 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
3524 } else {
3525 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003526 }
3527 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003528 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwale6afdf912016-01-30 13:01:33 -08003529 }
3530
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07003531 ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
3532
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003533 ai.networkSecurityConfigRes = sa.getResourceId(
3534 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
3535 0);
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07003536 ai.category = sa.getInt(
3537 com.android.internal.R.styleable.AndroidManifestApplication_appCategory,
3538 ApplicationInfo.CATEGORY_UNDEFINED);
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003540 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003541 str = sa.getNonConfigurationString(
3542 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003543 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
3544
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003545 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3546 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003547 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
3548 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003549 } else {
3550 // Some older apps have been seen to use a resource reference
3551 // here that on older builds was ignored (with a warning). We
3552 // need to continue to do this for them so they don't break.
3553 str = sa.getNonResourceString(
3554 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
3555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
3557 str, outError);
Jason Monka80bfb52017-11-16 17:15:37 -05003558 String factory = sa.getNonResourceString(
3559 com.android.internal.R.styleable.AndroidManifestApplication_appComponentFactory);
3560 if (factory != null) {
3561 ai.appComponentFactory = buildClassName(ai.packageName, factory, outError);
3562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003563
3564 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003565 CharSequence pname;
3566 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3567 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003568 com.android.internal.R.styleable.AndroidManifestApplication_process,
3569 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003570 } else {
3571 // Some older apps have been seen to use a resource reference
3572 // here that on older builds was ignored (with a warning). We
3573 // need to continue to do this for them so they don't break.
3574 pname = sa.getNonResourceString(
3575 com.android.internal.R.styleable.AndroidManifestApplication_process);
3576 }
3577 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 flags, mSeparateProcesses, outError);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003579
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003580 ai.enabled = sa.getBoolean(
3581 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003582
Jose Lima12d0b4c2014-03-14 16:55:12 -07003583 if (sa.getBoolean(
3584 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
3585 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
3586 }
3587
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003588 if (sa.getBoolean(
3589 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
3590 false)) {
3591 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07003592
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003593 // A heavy-weight application can not be in a custom process.
3594 // We can do direct compare because we intern all strings.
3595 if (ai.processName != null && !ai.processName.equals(ai.packageName)) {
3596 outError[0] = "cantSaveState applications can not use custom processes";
Dianne Hackborn860755f2010-06-03 18:47:52 -07003597 }
3598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599 }
3600
Adam Powell269248d2011-08-02 10:26:54 -07003601 ai.uiOptions = sa.getInt(
3602 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
3603
Narayan Kamath96c11c52017-08-09 13:07:21 +01003604 ai.classLoaderName = sa.getString(
3605 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3606 if (ai.classLoaderName != null
3607 && !ClassLoaderFactory.isValidClassLoaderName(ai.classLoaderName)) {
3608 outError[0] = "Invalid class loader name: " + ai.classLoaderName;
3609 }
3610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003611 sa.recycle();
3612
3613 if (outError[0] != null) {
3614 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3615 return false;
3616 }
3617
3618 final int innerDepth = parser.getDepth();
Garrett Boyer52136662017-05-23 13:47:58 -07003619 // IMPORTANT: These must only be cached for a single <application> to avoid components
3620 // getting added to the wrong package.
3621 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003622 int type;
Todd Kennedy6d418b62018-02-22 14:15:18 -08003623 boolean hasActivityOrder = false;
3624 boolean hasReceiverOrder = false;
3625 boolean hasServiceOrder = false;
Kenny Rootd2d29252011-08-08 11:27:57 -07003626 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3627 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3628 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003629 continue;
3630 }
3631
3632 String tagName = parser.getName();
3633 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003634 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003635 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003636 if (a == null) {
3637 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3638 return false;
3639 }
3640
Todd Kennedy6d418b62018-02-22 14:15:18 -08003641 hasActivityOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003642 owner.activities.add(a);
3643
3644 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003645 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3646 true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003647 if (a == null) {
3648 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3649 return false;
3650 }
3651
Todd Kennedy6d418b62018-02-22 14:15:18 -08003652 hasReceiverOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003653 owner.receivers.add(a);
3654
3655 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003656 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003657 if (s == null) {
3658 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3659 return false;
3660 }
3661
Todd Kennedy6d418b62018-02-22 14:15:18 -08003662 hasServiceOrder |= (s.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663 owner.services.add(s);
3664
3665 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003666 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003667 if (p == null) {
3668 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3669 return false;
3670 }
3671
3672 owner.providers.add(p);
3673
3674 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003675 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003676 if (a == null) {
3677 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3678 return false;
3679 }
3680
Todd Kennedy6d418b62018-02-22 14:15:18 -08003681 hasActivityOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682 owner.activities.add(a);
3683
3684 } else if (parser.getName().equals("meta-data")) {
3685 // note: application meta-data is stored off to the side, so it can
3686 // remain null in the primary copy (we like to avoid extra copies because
3687 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003688 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003689 outError)) == null) {
3690 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3691 return false;
3692 }
Svet Ganov67882122016-12-11 16:36:34 -08003693 } else if (tagName.equals("static-library")) {
3694 sa = res.obtainAttributes(parser,
3695 com.android.internal.R.styleable.AndroidManifestStaticLibrary);
3696
3697 // Note: don't allow this value to be a reference to a resource
3698 // that may change.
3699 final String lname = sa.getNonResourceString(
3700 com.android.internal.R.styleable.AndroidManifestStaticLibrary_name);
3701 final int version = sa.getInt(
3702 com.android.internal.R.styleable.AndroidManifestStaticLibrary_version, -1);
Dianne Hackborn3accca02013-09-20 09:32:11 -07003703 final int versionMajor = sa.getInt(
3704 com.android.internal.R.styleable.AndroidManifestStaticLibrary_versionMajor,
3705 0);
Svet Ganov67882122016-12-11 16:36:34 -08003706
3707 sa.recycle();
3708
3709 // Since the app canot run without a static lib - fail if malformed
3710 if (lname == null || version < 0) {
3711 outError[0] = "Bad static-library declaration name: " + lname
3712 + " version: " + version;
3713 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3714 XmlUtils.skipCurrentTag(parser);
3715 return false;
3716 }
3717
3718 if (owner.mSharedUserId != null) {
3719 outError[0] = "sharedUserId not allowed in static shared library";
3720 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
3721 XmlUtils.skipCurrentTag(parser);
3722 return false;
3723 }
3724
3725 if (owner.staticSharedLibName != null) {
3726 outError[0] = "Multiple static-shared libs for package " + pkgName;
3727 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3728 XmlUtils.skipCurrentTag(parser);
3729 return false;
3730 }
3731
3732 owner.staticSharedLibName = lname.intern();
Dianne Hackborn3accca02013-09-20 09:32:11 -07003733 if (version >= 0) {
3734 owner.staticSharedLibVersion =
3735 PackageInfo.composeLongVersionCode(versionMajor, version);
3736 } else {
3737 owner.staticSharedLibVersion = version;
3738 }
Svet Ganov67882122016-12-11 16:36:34 -08003739 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
3740
3741 XmlUtils.skipCurrentTag(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003742
Dianne Hackbornc895be72013-03-11 17:48:43 -07003743 } else if (tagName.equals("library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003744 sa = res.obtainAttributes(parser,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003745 com.android.internal.R.styleable.AndroidManifestLibrary);
3746
3747 // Note: don't allow this value to be a reference to a resource
3748 // that may change.
3749 String lname = sa.getNonResourceString(
3750 com.android.internal.R.styleable.AndroidManifestLibrary_name);
3751
3752 sa.recycle();
3753
3754 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003755 lname = lname.intern();
3756 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
Svet Ganov67882122016-12-11 16:36:34 -08003757 owner.libraryNames = ArrayUtils.add(
3758 owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07003759 }
3760 }
3761
3762 XmlUtils.skipCurrentTag(parser);
3763
Svet Ganov67882122016-12-11 16:36:34 -08003764 } else if (tagName.equals("uses-static-library")) {
3765 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3766 return false;
3767 }
3768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003769 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003770 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003771 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3772
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003773 // Note: don't allow this value to be a reference to a resource
3774 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003775 String lname = sa.getNonResourceString(
3776 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07003777 boolean req = sa.getBoolean(
3778 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3779 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003780
3781 sa.recycle();
3782
Dianne Hackborn49237342009-08-27 20:08:01 -07003783 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003784 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07003785 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003786 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003787 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003788 owner.usesOptionalLibraries = ArrayUtils.add(
3789 owner.usesOptionalLibraries, lname);
3790 }
3791 }
3792
3793 XmlUtils.skipCurrentTag(parser);
3794
3795 } else if (tagName.equals("uses-package")) {
3796 // Dependencies for app installers; we don't currently try to
3797 // enforce this.
3798 XmlUtils.skipCurrentTag(parser);
3799
3800 } else {
3801 if (!RIGID_PARSER) {
3802 Slog.w(TAG, "Unknown element under <application>: " + tagName
3803 + " at " + mArchiveSourcePath + " "
3804 + parser.getPositionDescription());
3805 XmlUtils.skipCurrentTag(parser);
3806 continue;
3807 } else {
3808 outError[0] = "Bad element under <application>: " + tagName;
3809 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3810 return false;
3811 }
3812 }
3813 }
3814
Todd Kennedy6d418b62018-02-22 14:15:18 -08003815 if (hasActivityOrder) {
3816 Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order));
3817 }
3818 if (hasReceiverOrder) {
3819 Collections.sort(owner.receivers, (r1, r2) -> Integer.compare(r2.order, r1.order));
3820 }
3821 if (hasServiceOrder) {
3822 Collections.sort(owner.services, (s1, s2) -> Integer.compare(s2.order, s1.order));
3823 }
Bryce Lee22571db2017-07-07 15:54:18 -07003824 // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
3825 // every activity info has had a chance to set it from its attributes.
3826 setMaxAspectRatio(owner);
3827
Paul Duffin855d7022017-07-10 15:16:07 +01003828 PackageBackwardCompatibility.modifySharedLibraries(owner);
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003829
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003830 if (hasDomainURLs(owner)) {
3831 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3832 } else {
3833 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3834 }
3835
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003836 return true;
3837 }
3838
3839 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003840 * 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 -07003841 */
3842 private static boolean hasDomainURLs(Package pkg) {
3843 if (pkg == null || pkg.activities == null) return false;
3844 final ArrayList<Activity> activities = pkg.activities;
3845 final int countActivities = activities.size();
3846 for (int n=0; n<countActivities; n++) {
3847 Activity activity = activities.get(n);
3848 ArrayList<ActivityIntentInfo> filters = activity.intents;
3849 if (filters == null) continue;
3850 final int countFilters = filters.size();
3851 for (int m=0; m<countFilters; m++) {
3852 ActivityIntentInfo aii = filters.get(m);
3853 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003854 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003855 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
3856 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
3857 return true;
3858 }
3859 }
3860 }
3861 return false;
3862 }
3863
3864 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003865 * Parse the {@code application} XML tree at the current parse location in a
3866 * <em>split APK</em> manifest.
3867 * <p>
3868 * Note that split APKs have many more restrictions on what they're capable
3869 * of doing, so many valid features of a base APK have been carefully
3870 * omitted here.
3871 */
Svet Ganov354cd3c2015-12-17 11:35:04 -08003872 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
3873 int flags, int splitIndex, String[] outError)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003874 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003875 TypedArray sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003876 com.android.internal.R.styleable.AndroidManifestApplication);
3877
3878 if (sa.getBoolean(
3879 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
3880 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
3881 }
3882
Narayan Kamath96c11c52017-08-09 13:07:21 +01003883 final String classLoaderName = sa.getString(
3884 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3885 if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
3886 owner.applicationInfo.splitClassLoaderNames[splitIndex] = classLoaderName;
3887 } else {
3888 outError[0] = "Invalid class loader name: " + classLoaderName;
3889 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3890 return false;
3891 }
3892
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003893 final int innerDepth = parser.getDepth();
3894 int type;
3895 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3896 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3897 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3898 continue;
3899 }
3900
Adam Lesinski4e862812016-11-21 16:02:24 -08003901 ComponentInfo parsedComponent = null;
3902
Garrett Boyer52136662017-05-23 13:47:58 -07003903 // IMPORTANT: These must only be cached for a single <application> to avoid components
3904 // getting added to the wrong package.
3905 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003906 String tagName = parser.getName();
3907 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003908 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003909 owner.baseHardwareAccelerated);
3910 if (a == null) {
3911 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3912 return false;
3913 }
3914
3915 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003916 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003917
3918 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003919 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3920 true, false);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003921 if (a == null) {
3922 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3923 return false;
3924 }
3925
3926 owner.receivers.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003927 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003928
3929 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003930 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003931 if (s == null) {
3932 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3933 return false;
3934 }
3935
3936 owner.services.add(s);
Adam Lesinski4e862812016-11-21 16:02:24 -08003937 parsedComponent = s.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003938
3939 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003940 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003941 if (p == null) {
3942 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3943 return false;
3944 }
3945
3946 owner.providers.add(p);
Adam Lesinski4e862812016-11-21 16:02:24 -08003947 parsedComponent = p.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003948
3949 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003950 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003951 if (a == null) {
3952 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3953 return false;
3954 }
3955
3956 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003957 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003958
3959 } else if (parser.getName().equals("meta-data")) {
3960 // note: application meta-data is stored off to the side, so it can
3961 // remain null in the primary copy (we like to avoid extra copies because
3962 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003963 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003964 outError)) == null) {
3965 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3966 return false;
3967 }
3968
Svet Ganov67882122016-12-11 16:36:34 -08003969 } else if (tagName.equals("uses-static-library")) {
3970 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3971 return false;
3972 }
3973
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003974 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003975 sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003976 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3977
3978 // Note: don't allow this value to be a reference to a resource
3979 // that may change.
3980 String lname = sa.getNonResourceString(
3981 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
3982 boolean req = sa.getBoolean(
3983 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3984 true);
3985
3986 sa.recycle();
3987
3988 if (lname != null) {
3989 lname = lname.intern();
3990 if (req) {
3991 // Upgrade to treat as stronger constraint
3992 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
3993 owner.usesOptionalLibraries = ArrayUtils.remove(
3994 owner.usesOptionalLibraries, lname);
3995 } else {
3996 // Ignore if someone already defined as required
3997 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
3998 owner.usesOptionalLibraries = ArrayUtils.add(
3999 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07004000 }
4001 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004002 }
4003
4004 XmlUtils.skipCurrentTag(parser);
4005
Dianne Hackborncef65ee2010-09-30 18:27:22 -07004006 } else if (tagName.equals("uses-package")) {
4007 // Dependencies for app installers; we don't currently try to
4008 // enforce this.
4009 XmlUtils.skipCurrentTag(parser);
4010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004011 } else {
4012 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004013 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004014 + " at " + mArchiveSourcePath + " "
4015 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004016 XmlUtils.skipCurrentTag(parser);
4017 continue;
4018 } else {
4019 outError[0] = "Bad element under <application>: " + tagName;
4020 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4021 return false;
4022 }
4023 }
Adam Lesinski4e862812016-11-21 16:02:24 -08004024
4025 if (parsedComponent != null && parsedComponent.splitName == null) {
4026 // If the loaded component did not specify a split, inherit the split name
4027 // based on the split it is defined in.
4028 // This is used to later load the correct split when starting this
4029 // component.
4030 parsedComponent.splitName = owner.splitNames[splitIndex];
4031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004032 }
4033
4034 return true;
4035 }
4036
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004037 private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
4038 String[] outError, String tag, TypedArray sa, boolean nameRequired,
4039 int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00004040 // This case can only happen in unit tests where we sometimes need to create fakes
4041 // of various package parser data structures.
4042 if (sa == null) {
4043 outError[0] = tag + " does not contain any attributes";
4044 return false;
4045 }
4046
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004047 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004048 if (name == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004049 if (nameRequired) {
4050 outError[0] = tag + " does not specify android:name";
4051 return false;
4052 }
4053 } else {
4054 outInfo.name
4055 = buildClassName(owner.applicationInfo.packageName, name, outError);
4056 if (outInfo.name == null) {
4057 return false;
4058 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004059 }
4060
Todd Kennedya83bfca2016-06-03 07:52:17 -07004061 final boolean useRoundIcon =
4062 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
4063 int roundIconVal = useRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004064 if (roundIconVal != 0) {
4065 outInfo.icon = roundIconVal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004066 outInfo.nonLocalizedLabel = null;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004067 } else {
4068 int iconVal = sa.getResourceId(iconRes, 0);
4069 if (iconVal != 0) {
4070 outInfo.icon = iconVal;
4071 outInfo.nonLocalizedLabel = null;
4072 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004073 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004074
Adam Powell81cd2e92010-04-21 16:35:18 -07004075 int logoVal = sa.getResourceId(logoRes, 0);
4076 if (logoVal != 0) {
4077 outInfo.logo = logoVal;
4078 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004079
Jose Limaf78e3122014-03-06 12:13:15 -08004080 int bannerVal = sa.getResourceId(bannerRes, 0);
4081 if (bannerVal != 0) {
4082 outInfo.banner = bannerVal;
4083 }
4084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004085 TypedValue v = sa.peekValue(labelRes);
4086 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4087 outInfo.nonLocalizedLabel = v.coerceToString();
4088 }
4089
4090 outInfo.packageName = owner.packageName;
4091
4092 return true;
4093 }
4094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004095 private Activity parseActivity(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004096 XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
Romain Guy529b60a2010-08-03 18:05:47 -07004097 boolean receiver, boolean hardwareAccelerated)
4098 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004099 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004100
Garrett Boyer52136662017-05-23 13:47:58 -07004101 if (cachedArgs.mActivityArgs == null) {
4102 cachedArgs.mActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004103 R.styleable.AndroidManifestActivity_name,
4104 R.styleable.AndroidManifestActivity_label,
4105 R.styleable.AndroidManifestActivity_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004106 R.styleable.AndroidManifestActivity_roundIcon,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004107 R.styleable.AndroidManifestActivity_logo,
4108 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004109 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004110 R.styleable.AndroidManifestActivity_process,
4111 R.styleable.AndroidManifestActivity_description,
4112 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004113 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004114
Garrett Boyer52136662017-05-23 13:47:58 -07004115 cachedArgs.mActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
4116 cachedArgs.mActivityArgs.sa = sa;
4117 cachedArgs.mActivityArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004118
Garrett Boyer52136662017-05-23 13:47:58 -07004119 Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004120 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004121 sa.recycle();
4122 return null;
4123 }
4124
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004125 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004126 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004127 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 }
4129
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004130 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004131
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004132 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07004133 a.info.applicationInfo.uiOptions);
4134
Adam Powelldd8fab22012-03-22 17:47:27 -07004135 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004136 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004137 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004138 if (parentName != null) {
4139 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4140 if (outError[0] == null) {
4141 a.info.parentActivityName = parentClassName;
4142 } else {
4143 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
4144 parentName);
4145 outError[0] = null;
4146 }
4147 }
4148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004149 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004150 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004151 if (str == null) {
4152 a.info.permission = owner.applicationInfo.permission;
4153 } else {
4154 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4155 }
4156
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004157 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004158 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004159 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004160 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
4161 owner.applicationInfo.taskAffinity, str, outError);
4162
Todd Kennedye9d0d272017-01-23 06:49:29 -08004163 a.info.splitName =
4164 sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0);
4165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004166 a.info.flags = 0;
4167 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004168 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004169 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
4170 }
4171
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004172 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
4174 }
4175
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004176 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004177 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
4178 }
4179
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004180 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004181 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
4182 }
4183
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004184 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004185 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
4186 }
4187
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004188 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004189 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
4190 }
4191
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004192 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004193 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
4194 }
4195
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004196 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
4198 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
4199 }
4200
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004201 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07004202 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
4203 }
4204
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07004205 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
4206 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
4207 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07004208 }
4209
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004210 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04004211 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
4212 }
Craig Mautner5962b122012-10-05 14:45:52 -07004213
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07004214 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
4215 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08004216 }
4217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004218 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004219 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07004220 hardwareAccelerated)) {
4221 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
4222 }
4223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004224 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004225 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07004226 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004227 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07004228 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07004229 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004230 R.styleable.AndroidManifestActivity_maxRecents,
Dianne Hackborn852975d2014-08-22 17:42:43 -07004231 ActivityManager.getDefaultAppRecentsLimitStatic());
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004232 a.info.configChanges = getActivityConfigChanges(
4233 sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004234 sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004235 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004236 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07004237
Craig Mautner43e52ed2014-06-16 17:18:52 -07004238 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004239 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07004240 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07004241
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004242 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004243 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
4244 }
4245
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004246 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004247 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
4248 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004249
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004250 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004251 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
4252 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004253
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004254 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004255 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
4256 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004257
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004258 a.info.screenOrientation = sa.getInt(
4259 R.styleable.AndroidManifestActivity_screenOrientation,
4260 SCREEN_ORIENTATION_UNSPECIFIED);
Wale Ogunwale6a591362015-10-05 20:18:27 -07004261
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004262 setActivityResizeMode(a.info, sa, owner);
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004263
Winson Chungd3395382016-12-13 11:49:09 -08004264 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
4265 false)) {
4266 a.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE;
4267 }
4268
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004269 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004270 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004271 }
Wale Ogunwaleb60692e2015-10-24 12:35:56 -07004272
Bryce Lee22571db2017-07-07 15:54:18 -07004273 if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio)
4274 && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio)
4275 == TypedValue.TYPE_FLOAT) {
4276 a.setMaxAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio,
4277 0 /*default*/));
4278 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004279
Craig Mautner15df08a2015-04-01 12:17:18 -07004280 a.info.lockTaskLaunchMode =
4281 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004282
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004283 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4284 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004285 false);
Ruben Brunkf56c9f42016-04-22 18:20:55 -07004286
4287 a.info.requestedVrComponent =
4288 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
Robert Carr0f5d7532016-10-17 16:39:17 -07004289
4290 a.info.rotationAnimation =
Robert Carr427ba4f2017-07-17 18:37:06 -07004291 sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_UNSPECIFIED);
Romain Guy48327452017-01-23 17:03:35 -08004292
4293 a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
4294 ActivityInfo.COLOR_MODE_DEFAULT);
chaviw59b98852017-06-13 12:05:44 -07004295
4296 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) {
4297 a.info.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
4298 }
4299
4300 if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) {
4301 a.info.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON;
4302 }
4303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 } else {
4305 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4306 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004308 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07004309 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004310 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004311
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004312 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4313 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004314 false);
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004315 }
4316
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004317 if (a.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004318 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004319 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004320 }
4321
Todd Kennedy752fb702017-03-21 16:28:10 -07004322 // can't make this final; we may set it later via meta-data
4323 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08004324 sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004325 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004326 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004327 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004328 }
4329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004330 sa.recycle();
4331
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004332 if (receiver && (owner.applicationInfo.privateFlags
4333 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004334 // A heavy-weight application can not have receives in its main process
4335 // We can do direct compare because we intern all strings.
4336 if (a.info.processName == owner.packageName) {
4337 outError[0] = "Heavy-weight applications can not have receivers in main process";
4338 }
4339 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004341 if (outError[0] != null) {
4342 return null;
4343 }
4344
4345 int outerDepth = parser.getDepth();
4346 int type;
4347 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4348 && (type != XmlPullParser.END_TAG
4349 || parser.getDepth() > outerDepth)) {
4350 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4351 continue;
4352 }
4353
4354 if (parser.getName().equals("intent-filter")) {
4355 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004356 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4357 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004358 return null;
4359 }
4360 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004361 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004362 + mArchiveSourcePath + " "
4363 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004364 } else {
Todd Kennedy6d418b62018-02-22 14:15:18 -08004365 a.order = Math.max(intent.getOrder(), a.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004366 a.intents.add(intent);
4367 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004368 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004369 final int visibility = visibleToEphemeral
4370 ? IntentFilter.VISIBILITY_EXPLICIT
4371 : !receiver && isImplicitlyExposedIntent(intent)
4372 ? IntentFilter.VISIBILITY_IMPLICIT
4373 : IntentFilter.VISIBILITY_NONE;
4374 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004375 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004376 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4377 }
4378 if (intent.isImplicitlyVisibleToInstantApp()) {
4379 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004380 }
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -07004381 if (LOG_UNSAFE_BROADCASTS && receiver
4382 && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
4383 for (int i = 0; i < intent.countActions(); i++) {
4384 final String action = intent.getAction(i);
4385 if (action == null || !action.startsWith("android.")) continue;
4386 if (!SAFE_BROADCASTS.contains(action)) {
4387 Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
4388 + owner.packageName + " as requested at: "
4389 + parser.getPositionDescription());
4390 }
4391 }
4392 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004393 } else if (!receiver && parser.getName().equals("preferred")) {
4394 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004395 if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
4396 intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004397 return null;
4398 }
4399 if (intent.countActions() == 0) {
4400 Slog.w(TAG, "No actions in preferred at "
4401 + mArchiveSourcePath + " "
4402 + parser.getPositionDescription());
4403 } else {
4404 if (owner.preferredActivityFilters == null) {
4405 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
4406 }
4407 owner.preferredActivityFilters.add(intent);
4408 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004409 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004410 final int visibility = visibleToEphemeral
4411 ? IntentFilter.VISIBILITY_EXPLICIT
4412 : !receiver && isImplicitlyExposedIntent(intent)
4413 ? IntentFilter.VISIBILITY_IMPLICIT
4414 : IntentFilter.VISIBILITY_NONE;
4415 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004416 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004417 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4418 }
4419 if (intent.isImplicitlyVisibleToInstantApp()) {
4420 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004421 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004422 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004423 if ((a.metaData = parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004424 outError)) == null) {
4425 return null;
4426 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004427 } else if (!receiver && parser.getName().equals("layout")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004428 parseLayout(res, parser, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004429 } else {
4430 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004431 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004432 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004433 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004434 + " at " + mArchiveSourcePath + " "
4435 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004437 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004438 + " at " + mArchiveSourcePath + " "
4439 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004440 }
4441 XmlUtils.skipCurrentTag(parser);
4442 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004443 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004444 if (receiver) {
4445 outError[0] = "Bad element under <receiver>: " + parser.getName();
4446 } else {
4447 outError[0] = "Bad element under <activity>: " + parser.getName();
4448 }
4449 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004450 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 }
4452 }
4453
4454 if (!setExported) {
4455 a.info.exported = a.intents.size() > 0;
4456 }
4457
4458 return a;
4459 }
4460
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004461 private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004462 final boolean appExplicitDefault = (owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004463 & (PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
4464 | PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004465
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004466 if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
4467 || appExplicitDefault) {
4468 // Activity or app explicitly set if it is resizeable or not;
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004469 final boolean appResizeable = (owner.applicationInfo.privateFlags
4470 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004471 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004472 appResizeable)) {
Winson Chungd3395382016-12-13 11:49:09 -08004473 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004474 } else {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004475 aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004476 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004477 return;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004478 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004479
4480 if ((owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004481 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) != 0) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004482 // The activity or app didn't explicitly set the resizing option, however we want to
4483 // make it resize due to the sdk version it is targeting.
4484 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4485 return;
4486 }
4487
4488 // resize preference isn't set and target sdk version doesn't support resizing apps by
4489 // default. For the app to be resizeable if it isn't fixed orientation or immersive.
skuhne@google.com322347b2016-12-02 12:54:03 -08004490 if (aInfo.isFixedOrientationPortrait()) {
4491 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
4492 } else if (aInfo.isFixedOrientationLandscape()) {
4493 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
4494 } else if (aInfo.isFixedOrientation()) {
4495 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
4496 } else {
4497 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4498 }
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004499 }
4500
Bryce Lee22571db2017-07-07 15:54:18 -07004501 /**
4502 * Sets every the max aspect ratio of every child activity that doesn't already have an aspect
4503 * ratio set.
4504 */
4505 private void setMaxAspectRatio(Package owner) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004506 // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
4507 // 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 -07004508 float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004509 ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
Bryce Lee22571db2017-07-07 15:54:18 -07004510
4511 if (owner.applicationInfo.maxAspectRatio != 0) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004512 // Use the application max aspect ration as default if set.
Bryce Lee22571db2017-07-07 15:54:18 -07004513 maxAspectRatio = owner.applicationInfo.maxAspectRatio;
4514 } else if (owner.mAppMetaData != null
4515 && owner.mAppMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) {
4516 maxAspectRatio = owner.mAppMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004517 }
4518
Bryce Lee22571db2017-07-07 15:54:18 -07004519 for (Activity activity : owner.activities) {
4520 // If the max aspect ratio for the activity has already been set, skip.
4521 if (activity.hasMaxAspectRatio()) {
4522 continue;
4523 }
4524
4525 // By default we prefer to use a values defined on the activity directly than values
4526 // defined on the application. We do not check the styled attributes on the activity
4527 // as it would have already been set when we processed the activity. We wait to process
4528 // the meta data here since this method is called at the end of processing the
4529 // application and all meta data is guaranteed.
4530 final float activityAspectRatio = activity.metaData != null
4531 ? activity.metaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio)
4532 : maxAspectRatio;
4533
4534 activity.setMaxAspectRatio(activityAspectRatio);
Wale Ogunwale0cb70ac2017-03-27 09:16:38 -07004535 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004536 }
4537
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004538 /**
4539 * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004540 * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from
4541 * AndroidManifest.xml.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004542 * @hide Exposed for unit testing only.
4543 */
4544 @TestApi
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004545 public static int getActivityConfigChanges(int configChanges, int recreateOnConfigChanges) {
4546 return configChanges | ((~recreateOnConfigChanges) & RECREATE_ON_CONFIG_CHANGES_MASK);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004547 }
4548
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004549 private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004550 TypedArray sw = res.obtainAttributes(attrs,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004551 com.android.internal.R.styleable.AndroidManifestLayout);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004552 int width = -1;
4553 float widthFraction = -1f;
4554 int height = -1;
4555 float heightFraction = -1f;
4556 final int widthType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004557 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004558 if (widthType == TypedValue.TYPE_FRACTION) {
4559 widthFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004560 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004561 1, 1, -1);
4562 } else if (widthType == TypedValue.TYPE_DIMENSION) {
4563 width = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004564 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004565 -1);
4566 }
4567 final int heightType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004568 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004569 if (heightType == TypedValue.TYPE_FRACTION) {
4570 heightFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004571 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004572 1, 1, -1);
4573 } else if (heightType == TypedValue.TYPE_DIMENSION) {
4574 height = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004575 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004576 -1);
4577 }
4578 int gravity = sw.getInt(
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004579 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004580 Gravity.CENTER);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004581 int minWidth = sw.getDimensionPixelSize(
4582 com.android.internal.R.styleable.AndroidManifestLayout_minWidth,
Andrii Kulian2e751b82016-03-16 16:59:32 -07004583 -1);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004584 int minHeight = sw.getDimensionPixelSize(
4585 com.android.internal.R.styleable.AndroidManifestLayout_minHeight,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004586 -1);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004587 sw.recycle();
Andrii Kulian2e751b82016-03-16 16:59:32 -07004588 a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction,
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004589 height, heightFraction, gravity, minWidth, minHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004590 }
4591
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004592 private Activity parseActivityAlias(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004593 XmlResourceParser parser, int flags, String[] outError,
4594 CachedComponentArgs cachedArgs)
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004595 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004596 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004597 com.android.internal.R.styleable.AndroidManifestActivityAlias);
4598
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004599 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004600 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
4601 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 if (targetActivity == null) {
4603 outError[0] = "<activity-alias> does not specify android:targetActivity";
4604 sa.recycle();
4605 return null;
4606 }
4607
4608 targetActivity = buildClassName(owner.applicationInfo.packageName,
4609 targetActivity, outError);
4610 if (targetActivity == null) {
4611 sa.recycle();
4612 return null;
4613 }
4614
Garrett Boyer52136662017-05-23 13:47:58 -07004615 if (cachedArgs.mActivityAliasArgs == null) {
4616 cachedArgs.mActivityAliasArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004617 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
4618 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
4619 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004620 com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004621 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004622 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004623 mSeparateProcesses,
4624 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004625 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004626 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004627 cachedArgs.mActivityAliasArgs.tag = "<activity-alias>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004628 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004629
Garrett Boyer52136662017-05-23 13:47:58 -07004630 cachedArgs.mActivityAliasArgs.sa = sa;
4631 cachedArgs.mActivityAliasArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004633 Activity target = null;
4634
4635 final int NA = owner.activities.size();
4636 for (int i=0; i<NA; i++) {
4637 Activity t = owner.activities.get(i);
4638 if (targetActivity.equals(t.info.name)) {
4639 target = t;
4640 break;
4641 }
4642 }
4643
4644 if (target == null) {
4645 outError[0] = "<activity-alias> target activity " + targetActivity
4646 + " not found in manifest";
4647 sa.recycle();
4648 return null;
4649 }
4650
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004651 ActivityInfo info = new ActivityInfo();
4652 info.targetActivity = targetActivity;
4653 info.configChanges = target.info.configChanges;
4654 info.flags = target.info.flags;
4655 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07004656 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08004657 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004658 info.labelRes = target.info.labelRes;
4659 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
4660 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07004661 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004662 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004663 if (info.descriptionRes == 0) {
4664 info.descriptionRes = target.info.descriptionRes;
4665 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004666 info.screenOrientation = target.info.screenOrientation;
4667 info.taskAffinity = target.info.taskAffinity;
4668 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07004669 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07004670 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07004671 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07004672 info.maxRecents = target.info.maxRecents;
Andrii Kulian2e751b82016-03-16 16:59:32 -07004673 info.windowLayout = target.info.windowLayout;
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004674 info.resizeMode = target.info.resizeMode;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004675 info.maxAspectRatio = target.info.maxAspectRatio;
rongliuc12ede42018-02-23 17:58:38 -08004676 info.requestedVrComponent = target.info.requestedVrComponent;
Bryce Lee22571db2017-07-07 15:54:18 -07004677
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004678 info.encryptionAware = info.directBootAware = target.info.directBootAware;
Craig Mautner8307ea72014-09-11 15:03:53 -07004679
Garrett Boyer52136662017-05-23 13:47:58 -07004680 Activity a = new Activity(cachedArgs.mActivityAliasArgs, info);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004681 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004682 sa.recycle();
4683 return null;
4684 }
4685
4686 final boolean setExported = sa.hasValue(
4687 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
4688 if (setExported) {
4689 a.info.exported = sa.getBoolean(
4690 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
4691 }
4692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004693 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004694 str = sa.getNonConfigurationString(
4695 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004696 if (str != null) {
4697 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4698 }
4699
Adam Powelldd8fab22012-03-22 17:47:27 -07004700 String parentName = sa.getNonConfigurationString(
4701 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004702 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004703 if (parentName != null) {
4704 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4705 if (outError[0] == null) {
4706 a.info.parentActivityName = parentClassName;
4707 } else {
4708 Log.e(TAG, "Activity alias " + a.info.name +
4709 " specified invalid parentActivityName " + parentName);
4710 outError[0] = null;
4711 }
4712 }
4713
Chad Brubaker699c7712017-01-20 13:53:42 -08004714 // TODO add visibleToInstantApps attribute to activity alias
Todd Kennedybe0b8892017-02-15 14:13:52 -08004715 final boolean visibleToEphemeral =
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004716 ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004718 sa.recycle();
4719
4720 if (outError[0] != null) {
4721 return null;
4722 }
4723
4724 int outerDepth = parser.getDepth();
4725 int type;
4726 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4727 && (type != XmlPullParser.END_TAG
4728 || parser.getDepth() > outerDepth)) {
4729 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4730 continue;
4731 }
4732
4733 if (parser.getName().equals("intent-filter")) {
4734 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004735 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4736 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004737 return null;
4738 }
4739 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004740 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004741 + mArchiveSourcePath + " "
4742 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004743 } else {
Todd Kennedy6d418b62018-02-22 14:15:18 -08004744 a.order = Math.max(intent.getOrder(), a.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004745 a.intents.add(intent);
4746 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004747 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004748 final int visibility = visibleToEphemeral
4749 ? IntentFilter.VISIBILITY_EXPLICIT
4750 : isImplicitlyExposedIntent(intent)
4751 ? IntentFilter.VISIBILITY_IMPLICIT
4752 : IntentFilter.VISIBILITY_NONE;
4753 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004754 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004755 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4756 }
4757 if (intent.isImplicitlyVisibleToInstantApp()) {
4758 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004759 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004760 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004761 if ((a.metaData=parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004762 outError)) == null) {
4763 return null;
4764 }
4765 } else {
4766 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004767 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004768 + " at " + mArchiveSourcePath + " "
4769 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004770 XmlUtils.skipCurrentTag(parser);
4771 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004772 } else {
4773 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
4774 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004776 }
4777 }
4778
4779 if (!setExported) {
4780 a.info.exported = a.intents.size() > 0;
4781 }
4782
4783 return a;
4784 }
4785
4786 private Provider parseProvider(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004787 XmlResourceParser parser, int flags, String[] outError,
4788 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004789 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004790 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004791 com.android.internal.R.styleable.AndroidManifestProvider);
4792
Garrett Boyer52136662017-05-23 13:47:58 -07004793 if (cachedArgs.mProviderArgs == null) {
4794 cachedArgs.mProviderArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004795 com.android.internal.R.styleable.AndroidManifestProvider_name,
4796 com.android.internal.R.styleable.AndroidManifestProvider_label,
4797 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004798 com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004799 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004800 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004801 mSeparateProcesses,
4802 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004803 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004804 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004805 cachedArgs.mProviderArgs.tag = "<provider>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004806 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004807
Garrett Boyer52136662017-05-23 13:47:58 -07004808 cachedArgs.mProviderArgs.sa = sa;
4809 cachedArgs.mProviderArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004810
Garrett Boyer52136662017-05-23 13:47:58 -07004811 Provider p = new Provider(cachedArgs.mProviderArgs, new ProviderInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004812 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004813 sa.recycle();
4814 return null;
4815 }
4816
Nick Kralevichf097b162012-07-28 12:43:48 -07004817 boolean providerExportedDefault = false;
4818
4819 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
4820 // For compatibility, applications targeting API level 16 or lower
4821 // should have their content providers exported by default, unless they
4822 // specify otherwise.
4823 providerExportedDefault = true;
4824 }
4825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07004827 com.android.internal.R.styleable.AndroidManifestProvider_exported,
4828 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004829
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004830 String cpname = sa.getNonConfigurationString(
4831 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832
4833 p.info.isSyncable = sa.getBoolean(
4834 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
4835 false);
4836
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004837 String permission = sa.getNonConfigurationString(
4838 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
4839 String str = sa.getNonConfigurationString(
4840 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004841 if (str == null) {
4842 str = permission;
4843 }
4844 if (str == null) {
4845 p.info.readPermission = owner.applicationInfo.permission;
4846 } else {
4847 p.info.readPermission =
4848 str.length() > 0 ? str.toString().intern() : null;
4849 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004850 str = sa.getNonConfigurationString(
4851 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004852 if (str == null) {
4853 str = permission;
4854 }
4855 if (str == null) {
4856 p.info.writePermission = owner.applicationInfo.permission;
4857 } else {
4858 p.info.writePermission =
4859 str.length() > 0 ? str.toString().intern() : null;
4860 }
4861
4862 p.info.grantUriPermissions = sa.getBoolean(
4863 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
4864 false);
4865
4866 p.info.multiprocess = sa.getBoolean(
4867 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
4868 false);
4869
4870 p.info.initOrder = sa.getInt(
4871 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
4872 0);
4873
Todd Kennedye9d0d272017-01-23 06:49:29 -08004874 p.info.splitName =
4875 sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0);
4876
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004877 p.info.flags = 0;
4878
4879 if (sa.getBoolean(
4880 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
4881 false)) {
4882 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004883 }
4884
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004885 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
4886 R.styleable.AndroidManifestProvider_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004887 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004888 if (p.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004889 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004890 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004891 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004892
Todd Kennedybe0b8892017-02-15 14:13:52 -08004893 final boolean visibleToEphemeral =
4894 sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004895 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004896 p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004897 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004898 }
4899
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004900 sa.recycle();
4901
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004902 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
4903 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004904 // A heavy-weight application can not have providers in its main process
4905 // We can do direct compare because we intern all strings.
4906 if (p.info.processName == owner.packageName) {
4907 outError[0] = "Heavy-weight applications can not have providers in main process";
4908 return null;
4909 }
4910 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004912 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07004913 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004914 return null;
4915 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08004916 if (cpname.length() <= 0) {
4917 outError[0] = "<provider> has empty authorities attribute";
4918 return null;
4919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004920 p.info.authority = cpname.intern();
4921
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004922 if (!parseProviderTags(
Patrick Baumanna2900392018-02-05 15:30:43 -08004923 res, parser, visibleToEphemeral, p, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004924 return null;
4925 }
4926
4927 return p;
4928 }
4929
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004930 private boolean parseProviderTags(Resources res, XmlResourceParser parser,
Patrick Baumanna2900392018-02-05 15:30:43 -08004931 boolean visibleToEphemeral, Provider outInfo, String[] outError)
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004932 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 int outerDepth = parser.getDepth();
4934 int type;
4935 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4936 && (type != XmlPullParser.END_TAG
4937 || parser.getDepth() > outerDepth)) {
4938 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4939 continue;
4940 }
4941
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004942 if (parser.getName().equals("intent-filter")) {
4943 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004944 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
4945 intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004946 return false;
4947 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004948 if (visibleToEphemeral) {
4949 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
4950 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004951 }
Todd Kennedy6d418b62018-02-22 14:15:18 -08004952 outInfo.order = Math.max(intent.getOrder(), outInfo.order);
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004953 outInfo.intents.add(intent);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004954
4955 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004956 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004957 outInfo.metaData, outError)) == null) {
4958 return false;
4959 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004961 } else if (parser.getName().equals("grant-uri-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004962 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
4964
4965 PatternMatcher pa = null;
4966
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004967 String str = sa.getNonConfigurationString(
4968 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004969 if (str != null) {
4970 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
4971 }
4972
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004973 str = sa.getNonConfigurationString(
4974 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004975 if (str != null) {
4976 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
4977 }
4978
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004979 str = sa.getNonConfigurationString(
4980 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004981 if (str != null) {
4982 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4983 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004985 sa.recycle();
4986
4987 if (pa != null) {
4988 if (outInfo.info.uriPermissionPatterns == null) {
4989 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
4990 outInfo.info.uriPermissionPatterns[0] = pa;
4991 } else {
4992 final int N = outInfo.info.uriPermissionPatterns.length;
4993 PatternMatcher[] newp = new PatternMatcher[N+1];
4994 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
4995 newp[N] = pa;
4996 outInfo.info.uriPermissionPatterns = newp;
4997 }
4998 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004999 } else {
5000 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005001 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005002 + parser.getName() + " at " + mArchiveSourcePath + " "
5003 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005004 XmlUtils.skipCurrentTag(parser);
5005 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005006 } else {
5007 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5008 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005009 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005010 }
5011 XmlUtils.skipCurrentTag(parser);
5012
5013 } else if (parser.getName().equals("path-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005014 TypedArray sa = res.obtainAttributes(parser,
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005015 com.android.internal.R.styleable.AndroidManifestPathPermission);
5016
5017 PathPermission pa = null;
5018
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005019 String permission = sa.getNonConfigurationString(
5020 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
5021 String readPermission = sa.getNonConfigurationString(
5022 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005023 if (readPermission == null) {
5024 readPermission = permission;
5025 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005026 String writePermission = sa.getNonConfigurationString(
5027 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005028 if (writePermission == null) {
5029 writePermission = permission;
5030 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005031
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005032 boolean havePerm = false;
5033 if (readPermission != null) {
5034 readPermission = readPermission.intern();
5035 havePerm = true;
5036 }
5037 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00005038 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005039 havePerm = true;
5040 }
5041
5042 if (!havePerm) {
5043 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005044 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005045 + parser.getName() + " at " + mArchiveSourcePath + " "
5046 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005047 XmlUtils.skipCurrentTag(parser);
5048 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005049 } else {
5050 outError[0] = "No readPermission or writePermssion for <path-permission>";
5051 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005052 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005053 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005054
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005055 String path = sa.getNonConfigurationString(
5056 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005057 if (path != null) {
5058 pa = new PathPermission(path,
5059 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
5060 }
5061
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005062 path = sa.getNonConfigurationString(
5063 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005064 if (path != null) {
5065 pa = new PathPermission(path,
5066 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
5067 }
5068
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005069 path = sa.getNonConfigurationString(
5070 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005071 if (path != null) {
5072 pa = new PathPermission(path,
5073 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
5074 }
5075
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005076 path = sa.getNonConfigurationString(
5077 com.android.internal.R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
5078 if (path != null) {
5079 pa = new PathPermission(path,
5080 PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission);
5081 }
5082
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005083 sa.recycle();
5084
5085 if (pa != null) {
5086 if (outInfo.info.pathPermissions == null) {
5087 outInfo.info.pathPermissions = new PathPermission[1];
5088 outInfo.info.pathPermissions[0] = pa;
5089 } else {
5090 final int N = outInfo.info.pathPermissions.length;
5091 PathPermission[] newp = new PathPermission[N+1];
5092 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
5093 newp[N] = pa;
5094 outInfo.info.pathPermissions = newp;
5095 }
5096 } else {
5097 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005098 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005099 + parser.getName() + " at " + mArchiveSourcePath + " "
5100 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005101 XmlUtils.skipCurrentTag(parser);
5102 continue;
5103 }
5104 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5105 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005106 }
5107 XmlUtils.skipCurrentTag(parser);
5108
5109 } else {
5110 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005111 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005112 + parser.getName() + " at " + mArchiveSourcePath + " "
5113 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005114 XmlUtils.skipCurrentTag(parser);
5115 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005116 } else {
5117 outError[0] = "Bad element under <provider>: " + parser.getName();
5118 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005120 }
5121 }
5122 return true;
5123 }
5124
5125 private Service parseService(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07005126 XmlResourceParser parser, int flags, String[] outError,
5127 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005128 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005129 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 com.android.internal.R.styleable.AndroidManifestService);
5131
Garrett Boyer52136662017-05-23 13:47:58 -07005132 if (cachedArgs.mServiceArgs == null) {
5133 cachedArgs.mServiceArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005134 com.android.internal.R.styleable.AndroidManifestService_name,
5135 com.android.internal.R.styleable.AndroidManifestService_label,
5136 com.android.internal.R.styleable.AndroidManifestService_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005137 com.android.internal.R.styleable.AndroidManifestService_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07005138 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08005139 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005140 mSeparateProcesses,
5141 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005142 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005143 com.android.internal.R.styleable.AndroidManifestService_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07005144 cachedArgs.mServiceArgs.tag = "<service>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005145 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005146
Garrett Boyer52136662017-05-23 13:47:58 -07005147 cachedArgs.mServiceArgs.sa = sa;
5148 cachedArgs.mServiceArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005149
Garrett Boyer52136662017-05-23 13:47:58 -07005150 Service s = new Service(cachedArgs.mServiceArgs, new ServiceInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005151 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005152 sa.recycle();
5153 return null;
5154 }
5155
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005156 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005157 com.android.internal.R.styleable.AndroidManifestService_exported);
5158 if (setExported) {
5159 s.info.exported = sa.getBoolean(
5160 com.android.internal.R.styleable.AndroidManifestService_exported, false);
5161 }
5162
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005163 String str = sa.getNonConfigurationString(
5164 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005165 if (str == null) {
5166 s.info.permission = owner.applicationInfo.permission;
5167 } else {
5168 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
5169 }
5170
Todd Kennedye9d0d272017-01-23 06:49:29 -08005171 s.info.splitName =
5172 sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0);
5173
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005174 s.info.flags = 0;
5175 if (sa.getBoolean(
5176 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
5177 false)) {
5178 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
5179 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08005180 if (sa.getBoolean(
5181 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
5182 false)) {
5183 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
5184 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005185 if (sa.getBoolean(
Robert Sesekb9a86662015-12-09 16:22:45 -05005186 com.android.internal.R.styleable.AndroidManifestService_externalService,
5187 false)) {
5188 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
5189 }
5190 if (sa.getBoolean(
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005191 com.android.internal.R.styleable.AndroidManifestService_singleUser,
5192 false)) {
5193 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005194 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005195
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005196 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
5197 R.styleable.AndroidManifestService_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005198 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005199 if (s.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005200 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005201 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005202 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005203
Todd Kennedy752fb702017-03-21 16:28:10 -07005204 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08005205 sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005206 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005207 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005208 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005209 }
5210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005211 sa.recycle();
5212
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005213 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5214 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005215 // A heavy-weight application can not have services in its main process
5216 // We can do direct compare because we intern all strings.
5217 if (s.info.processName == owner.packageName) {
5218 outError[0] = "Heavy-weight applications can not have services in main process";
5219 return null;
5220 }
5221 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005223 int outerDepth = parser.getDepth();
5224 int type;
5225 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5226 && (type != XmlPullParser.END_TAG
5227 || parser.getDepth() > outerDepth)) {
5228 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5229 continue;
5230 }
5231
5232 if (parser.getName().equals("intent-filter")) {
5233 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005234 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5235 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005236 return null;
5237 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005238 if (visibleToEphemeral) {
5239 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5240 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005241 }
Todd Kennedy6d418b62018-02-22 14:15:18 -08005242 s.order = Math.max(intent.getOrder(), s.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 s.intents.add(intent);
5244 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005245 if ((s.metaData=parseMetaData(res, parser, s.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005246 outError)) == null) {
5247 return null;
5248 }
5249 } else {
5250 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005251 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005252 + parser.getName() + " at " + mArchiveSourcePath + " "
5253 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005254 XmlUtils.skipCurrentTag(parser);
5255 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005256 } else {
5257 outError[0] = "Bad element under <service>: " + parser.getName();
5258 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005260 }
5261 }
5262
5263 if (!setExported) {
5264 s.info.exported = s.intents.size() > 0;
5265 }
5266
5267 return s;
5268 }
5269
Chad Brubaker49414832017-04-13 16:13:23 -07005270 private boolean isImplicitlyExposedIntent(IntentInfo intent) {
5271 return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
5272 || intent.hasAction(Intent.ACTION_SEND)
5273 || intent.hasAction(Intent.ACTION_SENDTO)
5274 || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005275 }
5276
Svet Ganov354cd3c2015-12-17 11:35:04 -08005277 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
5278 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005279 int outerDepth = parser.getDepth();
5280 int type;
5281 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5282 && (type != XmlPullParser.END_TAG
5283 || parser.getDepth() > outerDepth)) {
5284 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5285 continue;
5286 }
5287
5288 if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005289 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005290 outInfo.metaData, outError)) == null) {
5291 return false;
5292 }
5293 } else {
5294 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005295 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005296 + parser.getName() + " at " + mArchiveSourcePath + " "
5297 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005298 XmlUtils.skipCurrentTag(parser);
5299 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005300 } else {
5301 outError[0] = "Bad element under " + tag + ": " + parser.getName();
5302 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005304 }
5305 }
5306 return true;
5307 }
5308
5309 private Bundle parseMetaData(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08005310 XmlResourceParser parser, Bundle data, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005311 throws XmlPullParserException, IOException {
5312
Svet Ganov354cd3c2015-12-17 11:35:04 -08005313 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005314 com.android.internal.R.styleable.AndroidManifestMetaData);
5315
5316 if (data == null) {
5317 data = new Bundle();
5318 }
5319
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005320 String name = sa.getNonConfigurationString(
5321 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005322 if (name == null) {
5323 outError[0] = "<meta-data> requires an android:name attribute";
5324 sa.recycle();
5325 return null;
5326 }
5327
Dianne Hackborn854060af2009-07-09 18:14:31 -07005328 name = name.intern();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005330 TypedValue v = sa.peekValue(
5331 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
5332 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005333 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005334 data.putInt(name, v.resourceId);
5335 } else {
5336 v = sa.peekValue(
5337 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07005338 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005339 if (v != null) {
5340 if (v.type == TypedValue.TYPE_STRING) {
5341 CharSequence cs = v.coerceToString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00005342 data.putString(name, cs != null ? cs.toString() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005343 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
5344 data.putBoolean(name, v.data != 0);
5345 } else if (v.type >= TypedValue.TYPE_FIRST_INT
5346 && v.type <= TypedValue.TYPE_LAST_INT) {
5347 data.putInt(name, v.data);
5348 } else if (v.type == TypedValue.TYPE_FLOAT) {
5349 data.putFloat(name, v.getFloat());
5350 } else {
5351 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005352 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005353 + parser.getName() + " at " + mArchiveSourcePath + " "
5354 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005355 } else {
5356 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
5357 data = null;
5358 }
5359 }
5360 } else {
5361 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
5362 data = null;
5363 }
5364 }
5365
5366 sa.recycle();
5367
5368 XmlUtils.skipCurrentTag(parser);
5369
5370 return data;
5371 }
5372
Adam Lesinski4e862812016-11-21 16:02:24 -08005373 private static VerifierInfo parseVerifier(AttributeSet attrs) {
5374 String packageName = null;
5375 String encodedPublicKey = null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005376
Adam Lesinski4e862812016-11-21 16:02:24 -08005377 final int attrCount = attrs.getAttributeCount();
5378 for (int i = 0; i < attrCount; i++) {
5379 final int attrResId = attrs.getAttributeNameResource(i);
5380 switch (attrResId) {
5381 case com.android.internal.R.attr.name:
5382 packageName = attrs.getAttributeValue(i);
5383 break;
Kenny Root05ca4c92011-09-15 10:36:25 -07005384
Adam Lesinski4e862812016-11-21 16:02:24 -08005385 case com.android.internal.R.attr.publicKey:
5386 encodedPublicKey = attrs.getAttributeValue(i);
5387 break;
5388 }
5389 }
Kenny Root05ca4c92011-09-15 10:36:25 -07005390
5391 if (packageName == null || packageName.length() == 0) {
5392 Slog.i(TAG, "verifier package name was null; skipping");
5393 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005394 }
5395
Christopher Tate30147332014-04-15 12:57:47 -07005396 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
5397 if (publicKey == null) {
5398 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
5399 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08005400 }
5401
Christopher Tate30147332014-04-15 12:57:47 -07005402 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08005403 }
5404
Christopher Tate30147332014-04-15 12:57:47 -07005405 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
5406 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07005407 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07005408 return null;
5409 }
5410
Kenny Root05ca4c92011-09-15 10:36:25 -07005411 EncodedKeySpec keySpec;
5412 try {
5413 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
5414 keySpec = new X509EncodedKeySpec(encoded);
5415 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07005416 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07005417 return null;
5418 }
5419
5420 /* First try the key as an RSA key. */
5421 try {
5422 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005423 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005424 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005425 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005426 } catch (InvalidKeySpecException e) {
5427 // Not a RSA public key.
5428 }
5429
dcashman1616f302015-05-29 14:47:23 -07005430 /* Now try it as a ECDSA key. */
5431 try {
5432 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
5433 return keyFactory.generatePublic(keySpec);
5434 } catch (NoSuchAlgorithmException e) {
5435 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
5436 } catch (InvalidKeySpecException e) {
5437 // Not a ECDSA public key.
5438 }
5439
Kenny Root05ca4c92011-09-15 10:36:25 -07005440 /* Now try it as a DSA key. */
5441 try {
5442 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005443 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005444 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005445 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005446 } catch (InvalidKeySpecException e) {
5447 // Not a DSA public key.
5448 }
5449
dcashman1616f302015-05-29 14:47:23 -07005450 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07005451 return null;
5452 }
5453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005454 private static final String ANDROID_RESOURCES
5455 = "http://schemas.android.com/apk/res/android";
5456
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005457 private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs,
5458 boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
5459 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005460
Svet Ganov354cd3c2015-12-17 11:35:04 -08005461 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005462 com.android.internal.R.styleable.AndroidManifestIntentFilter);
5463
5464 int priority = sa.getInt(
5465 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005466 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08005467
Todd Kennedy6d418b62018-02-22 14:15:18 -08005468 int order = sa.getInt(
5469 com.android.internal.R.styleable.AndroidManifestIntentFilter_order, 0);
5470 outInfo.setOrder(order);
5471
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005472 TypedValue v = sa.peekValue(
5473 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
5474 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
5475 outInfo.nonLocalizedLabel = v.coerceToString();
5476 }
5477
Todd Kennedya83bfca2016-06-03 07:52:17 -07005478 final boolean useRoundIcon =
5479 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
5480 int roundIconVal = useRoundIcon ? sa.getResourceId(
5481 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
5482 if (roundIconVal != 0) {
5483 outInfo.icon = roundIconVal;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005484 } else {
5485 outInfo.icon = sa.getResourceId(
5486 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
5487 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005488
Adam Powell81cd2e92010-04-21 16:35:18 -07005489 outInfo.logo = sa.getResourceId(
5490 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005491
Jose Limaf78e3122014-03-06 12:13:15 -08005492 outInfo.banner = sa.getResourceId(
5493 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
5494
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08005495 if (allowAutoVerify) {
5496 outInfo.setAutoVerify(sa.getBoolean(
5497 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
5498 false));
5499 }
5500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005501 sa.recycle();
5502
5503 int outerDepth = parser.getDepth();
5504 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07005505 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
5506 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
5507 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005508 continue;
5509 }
5510
5511 String nodeName = parser.getName();
5512 if (nodeName.equals("action")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005513 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005514 ANDROID_RESOURCES, "name");
5515 if (value == null || value == "") {
5516 outError[0] = "No value supplied for <android:name>";
5517 return false;
5518 }
5519 XmlUtils.skipCurrentTag(parser);
5520
5521 outInfo.addAction(value);
5522 } else if (nodeName.equals("category")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005523 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005524 ANDROID_RESOURCES, "name");
5525 if (value == null || value == "") {
5526 outError[0] = "No value supplied for <android:name>";
5527 return false;
5528 }
5529 XmlUtils.skipCurrentTag(parser);
5530
5531 outInfo.addCategory(value);
5532
5533 } else if (nodeName.equals("data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005534 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005535 com.android.internal.R.styleable.AndroidManifestData);
5536
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005537 String str = sa.getNonConfigurationString(
5538 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005539 if (str != null) {
5540 try {
5541 outInfo.addDataType(str);
5542 } catch (IntentFilter.MalformedMimeTypeException e) {
5543 outError[0] = e.toString();
5544 sa.recycle();
5545 return false;
5546 }
5547 }
5548
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005549 str = sa.getNonConfigurationString(
5550 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005551 if (str != null) {
5552 outInfo.addDataScheme(str);
5553 }
5554
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005555 str = sa.getNonConfigurationString(
5556 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
5557 if (str != null) {
5558 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
5559 }
5560
5561 str = sa.getNonConfigurationString(
5562 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
5563 if (str != null) {
5564 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
5565 }
5566
5567 str = sa.getNonConfigurationString(
5568 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
5569 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005570 if (!allowGlobs) {
5571 outError[0] = "sspPattern not allowed here; ssp must be literal";
5572 return false;
5573 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005574 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5575 }
5576
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005577 String host = sa.getNonConfigurationString(
5578 com.android.internal.R.styleable.AndroidManifestData_host, 0);
5579 String port = sa.getNonConfigurationString(
5580 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005581 if (host != null) {
5582 outInfo.addDataAuthority(host, port);
5583 }
5584
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005585 str = sa.getNonConfigurationString(
5586 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005587 if (str != null) {
5588 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
5589 }
5590
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005591 str = sa.getNonConfigurationString(
5592 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005593 if (str != null) {
5594 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
5595 }
5596
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005597 str = sa.getNonConfigurationString(
5598 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005599 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005600 if (!allowGlobs) {
5601 outError[0] = "pathPattern not allowed here; path must be literal";
5602 return false;
5603 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005604 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5605 }
5606
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005607 str = sa.getNonConfigurationString(
5608 com.android.internal.R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
5609 if (str != null) {
5610 if (!allowGlobs) {
5611 outError[0] = "pathAdvancedPattern not allowed here; path must be literal";
5612 return false;
5613 }
5614 outInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
5615 }
5616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005617 sa.recycle();
5618 XmlUtils.skipCurrentTag(parser);
5619 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005620 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005621 + parser.getName() + " at " + mArchiveSourcePath + " "
5622 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005623 XmlUtils.skipCurrentTag(parser);
5624 } else {
5625 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
5626 return false;
5627 }
5628 }
5629
5630 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07005631
5632 if (DEBUG_PARSER) {
5633 final StringBuilder cats = new StringBuilder("Intent d=");
5634 cats.append(outInfo.hasDefault);
5635 cats.append(", cat=");
5636
5637 final Iterator<String> it = outInfo.categoriesIterator();
5638 if (it != null) {
5639 while (it.hasNext()) {
5640 cats.append(' ');
5641 cats.append(it.next());
5642 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005643 }
Kenny Rootd2d29252011-08-08 11:27:57 -07005644 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005645 }
5646
5647 return true;
5648 }
5649
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005650 /**
5651 * A container for signing-related data of an application package.
5652 * @hide
5653 */
Patrick Baumann47117fc2017-12-19 10:17:21 -08005654 public static final class SigningDetails implements Parcelable {
5655
5656 @IntDef({SigningDetails.SignatureSchemeVersion.UNKNOWN,
5657 SigningDetails.SignatureSchemeVersion.JAR,
5658 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2,
5659 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3})
5660 public @interface SignatureSchemeVersion {
5661 int UNKNOWN = 0;
5662 int JAR = 1;
5663 int SIGNING_BLOCK_V2 = 2;
5664 int SIGNING_BLOCK_V3 = 3;
5665 }
5666
5667 @Nullable
5668 public final Signature[] signatures;
5669 @SignatureSchemeVersion
5670 public final int signatureSchemeVersion;
5671 @Nullable
5672 public final ArraySet<PublicKey> publicKeys;
5673
Daniel Cashman77029c52018-01-18 16:19:29 -08005674 /**
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005675 * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
5676 * contains two pieces of information:
5677 * 1) the past signing certificates
5678 * 2) the flags that APK wants to assign to each of the past signing certificates.
5679 *
5680 * This collection of {@code Signature} objects, each of which is formed from a former
5681 * signing certificate of this APK before it was changed by signing certificate rotation,
5682 * represents the first piece of information. It is the APK saying to the rest of the
5683 * world: "hey if you trust the old cert, you can trust me!" This is useful, if for
5684 * instance, the platform would like to determine whether or not to allow this APK to do
5685 * something it would've allowed it to do under the old cert (like upgrade).
Daniel Cashman77029c52018-01-18 16:19:29 -08005686 */
5687 @Nullable
5688 public final Signature[] pastSigningCertificates;
5689
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005690 /** special value used to see if cert is in package - not exposed to callers */
5691 private static final int PAST_CERT_EXISTS = 0;
5692
5693 @IntDef(
5694 flag = true,
5695 value = {CertCapabilities.INSTALLED_DATA,
5696 CertCapabilities.SHARED_USER_ID,
Daniel Cashman629a5f92018-03-30 18:54:14 -07005697 CertCapabilities.PERMISSION,
5698 CertCapabilities.ROLLBACK})
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005699 public @interface CertCapabilities {
5700
5701 /** accept data from already installed pkg with this cert */
5702 int INSTALLED_DATA = 1;
5703
5704 /** accept sharedUserId with pkg with this cert */
5705 int SHARED_USER_ID = 2;
5706
5707 /** grant SIGNATURE permissions to pkgs with this cert */
5708 int PERMISSION = 4;
Daniel Cashman629a5f92018-03-30 18:54:14 -07005709
5710 /** allow pkg to update to one signed by this certificate */
5711 int ROLLBACK = 8;
Dan Cashman303c4bb2018-04-10 07:41:16 -07005712
5713 /** allow pkg to continue to have auth access gated by this cert */
5714 int AUTH = 16;
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005715 }
5716
Daniel Cashman77029c52018-01-18 16:19:29 -08005717 /**
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005718 * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
5719 * contains two pieces of information:
5720 * 1) the past signing certificates
5721 * 2) the flags that APK wants to assign to each of the past signing certificates.
5722 *
5723 * These flags, which have a one-to-one relationship for the {@code pastSigningCertificates}
5724 * collection, represent the second piece of information and are viewed as capabilities.
5725 * They are an APK's way of telling the platform: "this is how I want to trust my old certs,
5726 * please enforce that." This is useful for situation where this app itself is using its
5727 * signing certificate as an authorization mechanism, like whether or not to allow another
5728 * app to have its SIGNATURE permission. An app could specify whether to allow other apps
5729 * signed by its old cert 'X' to still get a signature permission it defines, for example.
Daniel Cashman77029c52018-01-18 16:19:29 -08005730 */
5731 @Nullable
5732 public final int[] pastSigningCertificatesFlags;
5733
Patrick Baumann47117fc2017-12-19 10:17:21 -08005734 /** A representation of unknown signing details. Use instead of null. */
5735 public static final SigningDetails UNKNOWN =
Daniel Cashman77029c52018-01-18 16:19:29 -08005736 new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null, null);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005737
5738 @VisibleForTesting
5739 public SigningDetails(Signature[] signatures,
5740 @SignatureSchemeVersion int signatureSchemeVersion,
Daniel Cashman77029c52018-01-18 16:19:29 -08005741 ArraySet<PublicKey> keys, Signature[] pastSigningCertificates,
5742 int[] pastSigningCertificatesFlags) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08005743 this.signatures = signatures;
5744 this.signatureSchemeVersion = signatureSchemeVersion;
5745 this.publicKeys = keys;
Daniel Cashman77029c52018-01-18 16:19:29 -08005746 this.pastSigningCertificates = pastSigningCertificates;
5747 this.pastSigningCertificatesFlags = pastSigningCertificatesFlags;
5748 }
5749
5750 public SigningDetails(Signature[] signatures,
5751 @SignatureSchemeVersion int signatureSchemeVersion,
5752 Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags)
5753 throws CertificateException {
5754 this(signatures, signatureSchemeVersion, toSigningKeys(signatures),
5755 pastSigningCertificates, pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005756 }
5757
5758 public SigningDetails(Signature[] signatures,
5759 @SignatureSchemeVersion int signatureSchemeVersion)
5760 throws CertificateException {
Daniel Cashman77029c52018-01-18 16:19:29 -08005761 this(signatures, signatureSchemeVersion,
5762 null, null);
5763 }
5764
5765 public SigningDetails(SigningDetails orig) {
5766 if (orig != null) {
5767 if (orig.signatures != null) {
5768 this.signatures = orig.signatures.clone();
5769 } else {
5770 this.signatures = null;
5771 }
5772 this.signatureSchemeVersion = orig.signatureSchemeVersion;
5773 this.publicKeys = new ArraySet<>(orig.publicKeys);
5774 if (orig.pastSigningCertificates != null) {
5775 this.pastSigningCertificates = orig.pastSigningCertificates.clone();
5776 this.pastSigningCertificatesFlags = orig.pastSigningCertificatesFlags.clone();
5777 } else {
5778 this.pastSigningCertificates = null;
5779 this.pastSigningCertificatesFlags = null;
5780 }
5781 } else {
5782 this.signatures = null;
5783 this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
5784 this.publicKeys = null;
5785 this.pastSigningCertificates = null;
5786 this.pastSigningCertificatesFlags = null;
5787 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08005788 }
5789
5790 /** Returns true if the signing details have one or more signatures. */
5791 public boolean hasSignatures() {
5792 return signatures != null && signatures.length > 0;
5793 }
5794
Daniel Cashman5cdda342018-01-19 07:22:52 -08005795 /** Returns true if the signing details have past signing certificates. */
5796 public boolean hasPastSigningCertificates() {
5797 return pastSigningCertificates != null && pastSigningCertificates.length > 0;
5798 }
5799
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005800 /**
5801 * Determines if the provided {@code oldDetails} is an ancestor of or the same as this one.
5802 * If the {@code oldDetails} signing certificate appears in our pastSigningCertificates,
5803 * then that means it has authorized a signing certificate rotation, which eventually leads
5804 * to our certificate, and thus can be trusted. If this method evaluates to true, this
5805 * SigningDetails object should be trusted if the previous one is.
5806 */
5807 public boolean hasAncestorOrSelf(SigningDetails oldDetails) {
5808 if (this == UNKNOWN || oldDetails == UNKNOWN) {
5809 return false;
5810 }
5811 if (oldDetails.signatures.length > 1) {
5812
5813 // multiple-signer packages cannot rotate signing certs, so we just compare current
5814 // signers for an exact match
5815 return signaturesMatchExactly(oldDetails);
5816 } else {
5817
5818 // we may have signing certificate rotation history, check to see if the oldDetails
5819 // was one of our old signing certificates
5820 return hasCertificate(oldDetails.signatures[0]);
5821 }
5822 }
5823
5824 /**
5825 * Similar to {@code hasAncestorOrSelf}. Returns true only if this {@code SigningDetails}
5826 * is a descendant of {@code oldDetails}, not if they're the same. This is used to
5827 * determine if this object is newer than the provided one.
5828 */
5829 public boolean hasAncestor(SigningDetails oldDetails) {
5830 if (this == UNKNOWN || oldDetails == UNKNOWN) {
5831 return false;
5832 }
5833 if (this.hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
5834
5835 // the last entry in pastSigningCertificates is the current signer, ignore it
5836 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
5837 if (pastSigningCertificates[i].equals(oldDetails.signatures[i])) {
5838 return true;
5839 }
5840 }
5841 }
5842 return false;
5843 }
5844
5845 /**
5846 * Determines if the provided {@code oldDetails} is an ancestor of this one, and whether or
5847 * not this one grants it the provided capability, represented by the {@code flags}
5848 * parameter. In the event of signing certificate rotation, a package may still interact
5849 * with entities signed by its old signing certificate and not want to break previously
5850 * functioning behavior. The {@code flags} value determines which capabilities the app
5851 * signed by the newer signing certificate would like to continue to give to its previous
5852 * signing certificate(s).
5853 */
5854 public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) {
5855 if (this == UNKNOWN || oldDetails == UNKNOWN) {
5856 return false;
5857 }
5858 if (oldDetails.signatures.length > 1) {
5859
5860 // multiple-signer packages cannot rotate signing certs, so we must have an exact
5861 // match, which also means all capabilities are granted
5862 return signaturesMatchExactly(oldDetails);
5863 } else {
5864
5865 // we may have signing certificate rotation history, check to see if the oldDetails
5866 // was one of our old signing certificates, and if we grant it the capability it's
5867 // requesting
5868 return hasCertificate(oldDetails.signatures[0], flags);
5869 }
5870 }
5871
5872 /**
5873 * A special case of {@code checkCapability} which re-encodes both sets of signing
5874 * certificates to counteract a previous re-encoding.
5875 */
5876 public boolean checkCapabilityRecover(SigningDetails oldDetails,
5877 @CertCapabilities int flags) throws CertificateException {
5878 if (oldDetails == UNKNOWN || this == UNKNOWN) {
5879 return false;
5880 }
5881 if (hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
5882
5883 // signing certificates may have rotated, check entire history for effective match
5884 for (int i = 0; i < pastSigningCertificates.length; i++) {
5885 if (Signature.areEffectiveMatch(
5886 oldDetails.signatures[0],
5887 pastSigningCertificates[i])
5888 && pastSigningCertificatesFlags[i] == flags) {
5889 return true;
5890 }
5891 }
5892 } else {
5893 return Signature.areEffectiveMatch(oldDetails.signatures, signatures);
5894 }
5895 return false;
5896 }
5897
5898 /**
5899 * Determine if {@code signature} is in this SigningDetails' signing certificate history,
5900 * including the current signer. Automatically returns false if this object has multiple
5901 * signing certificates, since rotation is only supported for single-signers; this is
5902 * enforced by {@code hasCertificateInternal}.
5903 */
5904 public boolean hasCertificate(Signature signature) {
5905 return hasCertificateInternal(signature, PAST_CERT_EXISTS);
5906 }
5907
5908 /**
5909 * Determine if {@code signature} is in this SigningDetails' signing certificate history,
5910 * including the current signer, and whether or not it has the given permission.
5911 * Certificates which match our current signer automatically get all capabilities.
5912 * Automatically returns false if this object has multiple signing certificates, since
5913 * rotation is only supported for single-signers.
5914 */
5915 public boolean hasCertificate(Signature signature, @CertCapabilities int flags) {
5916 return hasCertificateInternal(signature, flags);
5917 }
5918
5919 /** Convenient wrapper for calling {@code hasCertificate} with certificate's raw bytes. */
5920 public boolean hasCertificate(byte[] certificate) {
5921 Signature signature = new Signature(certificate);
5922 return hasCertificate(signature);
5923 }
5924
5925 private boolean hasCertificateInternal(Signature signature, int flags) {
5926 if (this == UNKNOWN) {
5927 return false;
5928 }
5929
5930 // only single-signed apps can have pastSigningCertificates
5931 if (hasPastSigningCertificates()) {
5932
5933 // check all past certs, except for the current one, which automatically gets all
5934 // capabilities, since it is the same as the current signature
5935 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
5936 if (pastSigningCertificates[i].equals(signature)) {
5937 if (flags == PAST_CERT_EXISTS
5938 || (flags & pastSigningCertificatesFlags[i]) == flags) {
5939 return true;
5940 }
5941 }
5942 }
5943 }
5944
5945 // not in previous certs signing history, just check the current signer and make sure
5946 // we are singly-signed
5947 return signatures.length == 1 && signatures[0].equals(signature);
5948 }
5949
5950 /**
5951 * Determines if the provided {@code sha256String} is an ancestor of this one, and whether
5952 * or not this one grants it the provided capability, represented by the {@code flags}
5953 * parameter. In the event of signing certificate rotation, a package may still interact
5954 * with entities signed by its old signing certificate and not want to break previously
5955 * functioning behavior. The {@code flags} value determines which capabilities the app
5956 * signed by the newer signing certificate would like to continue to give to its previous
5957 * signing certificate(s).
5958 *
5959 * @param sha256String A hex-encoded representation of a sha256 digest. In the case of an
5960 * app with multiple signers, this represents the hex-encoded sha256
5961 * digest of the combined hex-encoded sha256 digests of each individual
5962 * signing certificate according to {@link
5963 * PackageUtils#computeSignaturesSha256Digest(Signature[])}
5964 */
5965 public boolean checkCapability(String sha256String, @CertCapabilities int flags) {
5966 if (this == UNKNOWN) {
5967 return false;
5968 }
5969
5970 // first see if the hash represents a single-signer in our signing history
5971 byte[] sha256Bytes = ByteStringUtils.fromHexToByteArray(sha256String);
5972 if (hasSha256Certificate(sha256Bytes, flags)) {
5973 return true;
5974 }
5975
5976 // Not in signing history, either represents multiple signatures or not a match.
5977 // Multiple signers can't rotate, so no need to check flags, just see if the SHAs match.
5978 // We already check the single-signer case above as part of hasSha256Certificate, so no
5979 // need to verify we have multiple signers, just run the old check
5980 // just consider current signing certs
5981 final String[] mSignaturesSha256Digests =
5982 PackageUtils.computeSignaturesSha256Digests(signatures);
5983 final String mSignaturesSha256Digest =
5984 PackageUtils.computeSignaturesSha256Digest(mSignaturesSha256Digests);
5985 return mSignaturesSha256Digest.equals(sha256String);
5986 }
5987
5988 /**
5989 * Determine if the {@code sha256Certificate} is in this SigningDetails' signing certificate
5990 * history, including the current signer. Automatically returns false if this object has
5991 * multiple signing certificates, since rotation is only supported for single-signers.
5992 */
5993 public boolean hasSha256Certificate(byte[] sha256Certificate) {
5994 return hasSha256CertificateInternal(sha256Certificate, PAST_CERT_EXISTS);
5995 }
5996
5997 /**
5998 * Determine if the {@code sha256Certificate} certificate hash corresponds to a signing
5999 * certificate in this SigningDetails' signing certificate history, including the current
6000 * signer, and whether or not it has the given permission. Certificates which match our
6001 * current signer automatically get all capabilities. Automatically returns false if this
6002 * object has multiple signing certificates, since rotation is only supported for
6003 * single-signers.
6004 */
6005 public boolean hasSha256Certificate(byte[] sha256Certificate, @CertCapabilities int flags) {
6006 return hasSha256CertificateInternal(sha256Certificate, flags);
6007 }
6008
6009 private boolean hasSha256CertificateInternal(byte[] sha256Certificate, int flags) {
6010 if (this == UNKNOWN) {
6011 return false;
6012 }
6013 if (hasPastSigningCertificates()) {
6014
6015 // check all past certs, except for the last one, which automatically gets all
6016 // capabilities, since it is the same as the current signature, and is checked below
6017 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
6018 byte[] digest = PackageUtils.computeSha256DigestBytes(
6019 pastSigningCertificates[i].toByteArray());
6020 if (Arrays.equals(sha256Certificate, digest)) {
6021 if (flags == PAST_CERT_EXISTS
6022 || (flags & pastSigningCertificatesFlags[i]) == flags) {
6023 return true;
6024 }
6025 }
6026 }
6027 }
6028
6029 // not in previous certs signing history, just check the current signer
6030 if (signatures.length == 1) {
6031 byte[] digest =
6032 PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray());
6033 return Arrays.equals(sha256Certificate, digest);
6034 }
6035 return false;
6036 }
6037
Patrick Baumann47117fc2017-12-19 10:17:21 -08006038 /** Returns true if the signatures in this and other match exactly. */
6039 public boolean signaturesMatchExactly(SigningDetails other) {
6040 return Signature.areExactMatch(this.signatures, other.signatures);
6041 }
6042
6043 @Override
6044 public int describeContents() {
6045 return 0;
6046 }
6047
6048 @Override
6049 public void writeToParcel(Parcel dest, int flags) {
6050 boolean isUnknown = UNKNOWN == this;
6051 dest.writeBoolean(isUnknown);
6052 if (isUnknown) {
6053 return;
6054 }
6055 dest.writeTypedArray(this.signatures, flags);
6056 dest.writeInt(this.signatureSchemeVersion);
6057 dest.writeArraySet(this.publicKeys);
Daniel Cashman77029c52018-01-18 16:19:29 -08006058 dest.writeTypedArray(this.pastSigningCertificates, flags);
6059 dest.writeIntArray(this.pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006060 }
6061
6062 protected SigningDetails(Parcel in) {
6063 final ClassLoader boot = Object.class.getClassLoader();
6064 this.signatures = in.createTypedArray(Signature.CREATOR);
6065 this.signatureSchemeVersion = in.readInt();
6066 this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot);
Daniel Cashman77029c52018-01-18 16:19:29 -08006067 this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR);
6068 this.pastSigningCertificatesFlags = in.createIntArray();
Patrick Baumann47117fc2017-12-19 10:17:21 -08006069 }
6070
6071 public static final Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() {
6072 @Override
6073 public SigningDetails createFromParcel(Parcel source) {
6074 if (source.readBoolean()) {
6075 return UNKNOWN;
6076 }
6077 return new SigningDetails(source);
6078 }
6079
6080 @Override
6081 public SigningDetails[] newArray(int size) {
6082 return new SigningDetails[size];
6083 }
6084 };
6085
6086 @Override
6087 public boolean equals(Object o) {
6088 if (this == o) return true;
6089 if (!(o instanceof SigningDetails)) return false;
6090
6091 SigningDetails that = (SigningDetails) o;
6092
6093 if (signatureSchemeVersion != that.signatureSchemeVersion) return false;
6094 if (!Signature.areExactMatch(signatures, that.signatures)) return false;
Daniel Cashman77029c52018-01-18 16:19:29 -08006095 if (publicKeys != null) {
6096 if (!publicKeys.equals((that.publicKeys))) {
6097 return false;
6098 }
6099 } else if (that.publicKeys != null) {
6100 return false;
6101 }
6102
6103 // can't use Signature.areExactMatch() because order matters with the past signing certs
6104 if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) {
6105 return false;
6106 }
6107 if (!Arrays.equals(pastSigningCertificatesFlags, that.pastSigningCertificatesFlags)) {
6108 return false;
6109 }
6110
6111 return true;
Patrick Baumann47117fc2017-12-19 10:17:21 -08006112 }
6113
6114 @Override
6115 public int hashCode() {
6116 int result = +Arrays.hashCode(signatures);
6117 result = 31 * result + signatureSchemeVersion;
6118 result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0);
Daniel Cashman77029c52018-01-18 16:19:29 -08006119 result = 31 * result + Arrays.hashCode(pastSigningCertificates);
6120 result = 31 * result + Arrays.hashCode(pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006121 return result;
6122 }
Daniel Cashman77029c52018-01-18 16:19:29 -08006123
6124 /**
6125 * Builder of {@code SigningDetails} instances.
6126 */
6127 public static class Builder {
6128 private Signature[] mSignatures;
6129 private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
6130 private Signature[] mPastSigningCertificates;
6131 private int[] mPastSigningCertificatesFlags;
6132
6133 public Builder() {
6134 }
6135
6136 /** get signing certificates used to sign the current APK */
6137 public Builder setSignatures(Signature[] signatures) {
6138 mSignatures = signatures;
6139 return this;
6140 }
6141
6142 /** set the signature scheme version used to sign the APK */
6143 public Builder setSignatureSchemeVersion(int signatureSchemeVersion) {
6144 mSignatureSchemeVersion = signatureSchemeVersion;
6145 return this;
6146 }
6147
6148 /** set the signing certificates by which the APK proved it can be authenticated */
6149 public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
6150 mPastSigningCertificates = pastSigningCertificates;
6151 return this;
6152 }
6153
6154 /** set the flags for the {@code pastSigningCertificates} */
6155 public Builder setPastSigningCertificatesFlags(int[] pastSigningCertificatesFlags) {
6156 mPastSigningCertificatesFlags = pastSigningCertificatesFlags;
6157 return this;
6158 }
6159
6160 private void checkInvariants() {
6161 // must have signatures and scheme version set
6162 if (mSignatures == null) {
6163 throw new IllegalStateException("SigningDetails requires the current signing"
6164 + " certificates.");
6165 }
6166
6167 // pastSigningCerts and flags must match up
6168 boolean pastMismatch = false;
6169 if (mPastSigningCertificates != null && mPastSigningCertificatesFlags != null) {
6170 if (mPastSigningCertificates.length != mPastSigningCertificatesFlags.length) {
6171 pastMismatch = true;
6172 }
6173 } else if (!(mPastSigningCertificates == null
6174 && mPastSigningCertificatesFlags == null)) {
6175 pastMismatch = true;
6176 }
6177 if (pastMismatch) {
6178 throw new IllegalStateException("SigningDetails must have a one to one mapping "
6179 + "between pastSigningCertificates and pastSigningCertificatesFlags");
6180 }
6181 }
6182 /** build a {@code SigningDetails} object */
6183 public SigningDetails build()
6184 throws CertificateException {
6185 checkInvariants();
6186 return new SigningDetails(mSignatures, mSignatureSchemeVersion,
6187 mPastSigningCertificates, mPastSigningCertificatesFlags);
6188 }
6189 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08006190 }
6191
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006192 /**
6193 * Representation of a full package parsed from APK files on disk. A package
6194 * consists of a single base APK, and zero or more split APKs.
6195 */
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006196 public final static class Package implements Parcelable {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006197
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006198 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006199
Svet Ganov67882122016-12-11 16:36:34 -08006200 // The package name declared in the manifest as the package can be
6201 // renamed, for example static shared libs use synthetic package names.
6202 public String manifestPackageName;
6203
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006204 /** Names of any split APKs, ordered by parsed splitName */
6205 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006206
6207 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07006208
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07006209 public String volumeUuid;
6210
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006211 /**
6212 * Path where this package was found on disk. For monolithic packages
6213 * this is path to single base APK file; for cluster packages this is
6214 * path to the cluster directory.
6215 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006216 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006217
6218 /** Path of base APK */
6219 public String baseCodePath;
6220 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006221 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006222
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006223 /** Revision code of base APK */
6224 public int baseRevisionCode;
6225 /** Revision codes of any split APKs, ordered by parsed splitName */
6226 public int[] splitRevisionCodes;
6227
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006228 /** Flags of any split APKs; ordered by parsed splitName */
6229 public int[] splitFlags;
6230
Alex Klyubinb9f8a522015-02-03 11:12:59 -08006231 /**
6232 * Private flags of any split APKs; ordered by parsed splitName.
6233 *
6234 * {@hide}
6235 */
6236 public int[] splitPrivateFlags;
6237
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006238 public boolean baseHardwareAccelerated;
6239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006240 // For now we only support one application per package.
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006241 public ApplicationInfo applicationInfo = new ApplicationInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006242
6243 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
6244 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
6245 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
6246 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
6247 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
6248 public final ArrayList<Service> services = new ArrayList<Service>(0);
6249 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
6250
6251 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
6252
Dianne Hackborn854060af2009-07-09 18:14:31 -07006253 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006254
Svet Ganov354cd3c2015-12-17 11:35:04 -08006255 public Package parentPackage;
6256 public ArrayList<Package> childPackages;
6257
Svet Ganov67882122016-12-11 16:36:34 -08006258 public String staticSharedLibName = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006259 public long staticSharedLibVersion = 0;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006260 public ArrayList<String> libraryNames = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07006261 public ArrayList<String> usesLibraries = null;
Svet Ganov67882122016-12-11 16:36:34 -08006262 public ArrayList<String> usesStaticLibraries = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006263 public long[] usesStaticLibrariesVersions = null;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006264 public String[][] usesStaticLibrariesCertDigests = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07006265 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006266 public String[] usesLibraryFiles = null;
6267
Dianne Hackbornb09491f2013-07-22 15:30:11 -07006268 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
6269
Dianne Hackbornc1552392010-03-03 16:19:01 -08006270 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006271 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006272 public ArrayList<String> mAdoptPermissions = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006274 // We store the application meta-data independently to avoid multiple unwanted references
6275 public Bundle mAppMetaData = null;
6276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006277 // The version code declared for this package.
6278 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006279
Dianne Hackborn3accca02013-09-20 09:32:11 -07006280 // The major version code declared for this package.
6281 public int mVersionCodeMajor;
6282
6283 // Return long containing mVersionCode and mVersionCodeMajor.
6284 public long getLongVersionCode() {
6285 return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
6286 }
6287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006288 // The version name declared for this package.
6289 public String mVersionName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006291 // The shared user id that this package wants to use.
6292 public String mSharedUserId;
6293
6294 // The shared user label that this package wants to use.
6295 public int mSharedUserLabel;
6296
6297 // Signatures that were read from the package.
Patrick Baumann47117fc2017-12-19 10:17:21 -08006298 @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006299
6300 // For use by package manager service for quick lookup of
6301 // preferred up order.
6302 public int mPreferredOrder = 0;
6303
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006304 // For use by package manager to keep track of when a package was last used.
Brian Carlstromca82e612016-04-19 23:16:08 -07006305 public long[] mLastPackageUsageTimeInMills =
6306 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006307
Amith Yamasani13593602012-03-22 16:16:17 -07006308 // // User set enabled state.
6309 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
6310 //
6311 // // Whether the package has been stopped.
6312 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08006313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006314 // Additional data supplied by callers.
6315 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07006316
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006317 // Applications hardware preferences
6318 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006319
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006320 // Applications requested features
Dianne Hackborn49237342009-08-27 20:08:01 -07006321 public ArrayList<FeatureInfo> reqFeatures = null;
6322
Adam Lesinskid3edfde2014-08-08 17:32:44 -07006323 // Applications requested feature groups
6324 public ArrayList<FeatureGroupInfo> featureGroups = null;
6325
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08006326 public int installLocation;
6327
Jeff Hao272bf3a2014-10-08 13:34:43 -07006328 public boolean coreApp;
6329
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08006330 /* An app that's required for all users and cannot be uninstalled for a user */
6331 public boolean mRequiredForAllUsers;
6332
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006333 /* The restricted account authenticator type that is used by this application */
6334 public String mRestrictedAccountType;
6335
Amith Yamasaniccbe3892013-04-12 17:52:42 -07006336 /* The required account type without which this application will not function */
6337 public String mRequiredAccountType;
6338
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006339 public String mOverlayTarget;
Adrian Roosc84df772018-01-19 21:20:22 +01006340 public String mOverlayCategory;
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006341 public int mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -08006342 public boolean mOverlayIsStatic;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006343
Alan Viveretteb6a25732017-11-21 14:49:24 -05006344 public int mCompileSdkVersion;
6345 public String mCompileSdkVersionCodename;
6346
Geremy Condraf1bcca82013-01-07 22:35:24 -08006347 /**
dcashman989eb3712014-06-17 12:56:12 -07006348 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08006349 */
dcashman989eb3712014-06-17 12:56:12 -07006350 public ArraySet<String> mUpgradeKeySets;
6351 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08006352
Narayan Kamath4903f642014-08-11 13:33:45 +01006353 /**
6354 * The install time abi override for this package, if any.
6355 *
6356 * TODO: This seems like a horrible place to put the abiOverride because
6357 * this isn't something the packageParser parsers. However, this fits in with
6358 * the rest of the PackageManager where package scanning randomly pushes
6359 * and prods fields out of {@code this.applicationInfo}.
6360 */
6361 public String cpuAbiOverride;
Selim Gurun2d291d82016-02-05 17:50:53 -08006362 /**
6363 * The install time abi override to choose 32bit abi's when multiple abi's
6364 * are present. This is only meaningfull for multiarch applications.
6365 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
6366 */
6367 public boolean use32bitAbi;
Narayan Kamath4903f642014-08-11 13:33:45 +01006368
Todd Kennedyfdd241a2016-04-28 12:26:53 -07006369 public byte[] restrictUpdateHash;
6370
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006371 /** Set if the app or any of its components are visible to instant applications. */
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006372 public boolean visibleToInstantApps;
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006373 /** Whether or not the package is a stub and must be replaced by the full version. */
6374 public boolean isStub;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006375
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006376 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006377 this.packageName = packageName;
Svet Ganov67882122016-12-11 16:36:34 -08006378 this.manifestPackageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006379 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 applicationInfo.uid = -1;
6381 }
6382
Svet Ganov354cd3c2015-12-17 11:35:04 -08006383 public void setApplicationVolumeUuid(String volumeUuid) {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006384 final UUID storageUuid = StorageManager.convert(volumeUuid);
Svet Ganov354cd3c2015-12-17 11:35:04 -08006385 this.applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006386 this.applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006387 if (childPackages != null) {
6388 final int packageCount = childPackages.size();
6389 for (int i = 0; i < packageCount; i++) {
6390 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006391 childPackages.get(i).applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006392 }
6393 }
6394 }
6395
6396 public void setApplicationInfoCodePath(String codePath) {
6397 this.applicationInfo.setCodePath(codePath);
6398 if (childPackages != null) {
6399 final int packageCount = childPackages.size();
6400 for (int i = 0; i < packageCount; i++) {
6401 childPackages.get(i).applicationInfo.setCodePath(codePath);
6402 }
6403 }
6404 }
6405
Todd Kennedy30a23a52018-01-04 13:27:49 -08006406 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6407 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006408 public void setApplicationInfoResourcePath(String resourcePath) {
6409 this.applicationInfo.setResourcePath(resourcePath);
6410 if (childPackages != null) {
6411 final int packageCount = childPackages.size();
6412 for (int i = 0; i < packageCount; i++) {
6413 childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
6414 }
6415 }
6416 }
6417
Todd Kennedy30a23a52018-01-04 13:27:49 -08006418 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6419 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006420 public void setApplicationInfoBaseResourcePath(String resourcePath) {
6421 this.applicationInfo.setBaseResourcePath(resourcePath);
6422 if (childPackages != null) {
6423 final int packageCount = childPackages.size();
6424 for (int i = 0; i < packageCount; i++) {
6425 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
6426 }
6427 }
6428 }
6429
6430 public void setApplicationInfoBaseCodePath(String baseCodePath) {
6431 this.applicationInfo.setBaseCodePath(baseCodePath);
6432 if (childPackages != null) {
6433 final int packageCount = childPackages.size();
6434 for (int i = 0; i < packageCount; i++) {
6435 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
6436 }
6437 }
6438 }
6439
Todd Kennedy13715d52016-08-01 13:38:57 -07006440 public List<String> getChildPackageNames() {
6441 if (childPackages == null) {
6442 return null;
6443 }
6444 final int childCount = childPackages.size();
6445 final List<String> childPackageNames = new ArrayList<>(childCount);
6446 for (int i = 0; i < childCount; i++) {
6447 String childPackageName = childPackages.get(i).packageName;
6448 childPackageNames.add(childPackageName);
6449 }
6450 return childPackageNames;
6451 }
6452
Svet Ganov354cd3c2015-12-17 11:35:04 -08006453 public boolean hasChildPackage(String packageName) {
6454 final int childCount = (childPackages != null) ? childPackages.size() : 0;
6455 for (int i = 0; i < childCount; i++) {
6456 if (childPackages.get(i).packageName.equals(packageName)) {
6457 return true;
6458 }
6459 }
6460 return false;
6461 }
6462
6463 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
6464 this.applicationInfo.setSplitCodePaths(splitCodePaths);
6465 // Children have no splits
6466 }
6467
Todd Kennedy30a23a52018-01-04 13:27:49 -08006468 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6469 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006470 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
6471 this.applicationInfo.setSplitResourcePaths(resroucePaths);
6472 // Children have no splits
6473 }
6474
6475 public void setSplitCodePaths(String[] codePaths) {
6476 this.splitCodePaths = codePaths;
6477 }
6478
6479 public void setCodePath(String codePath) {
6480 this.codePath = codePath;
6481 if (childPackages != null) {
6482 final int packageCount = childPackages.size();
6483 for (int i = 0; i < packageCount; i++) {
6484 childPackages.get(i).codePath = codePath;
6485 }
6486 }
6487 }
6488
6489 public void setBaseCodePath(String baseCodePath) {
6490 this.baseCodePath = baseCodePath;
6491 if (childPackages != null) {
6492 final int packageCount = childPackages.size();
6493 for (int i = 0; i < packageCount; i++) {
6494 childPackages.get(i).baseCodePath = baseCodePath;
6495 }
6496 }
6497 }
6498
Patrick Baumann47117fc2017-12-19 10:17:21 -08006499 /** Sets signing details on the package and any of its children. */
6500 public void setSigningDetails(@NonNull SigningDetails signingDetails) {
6501 mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006502 if (childPackages != null) {
6503 final int packageCount = childPackages.size();
6504 for (int i = 0; i < packageCount; i++) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08006505 childPackages.get(i).mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006506 }
6507 }
6508 }
6509
6510 public void setVolumeUuid(String volumeUuid) {
6511 this.volumeUuid = volumeUuid;
6512 if (childPackages != null) {
6513 final int packageCount = childPackages.size();
6514 for (int i = 0; i < packageCount; i++) {
6515 childPackages.get(i).volumeUuid = volumeUuid;
6516 }
6517 }
6518 }
6519
6520 public void setApplicationInfoFlags(int mask, int flags) {
6521 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
6522 if (childPackages != null) {
6523 final int packageCount = childPackages.size();
6524 for (int i = 0; i < packageCount; i++) {
6525 childPackages.get(i).applicationInfo.flags =
6526 (applicationInfo.flags & ~mask) | (mask & flags);
6527 }
6528 }
6529 }
6530
Selim Gurun75827b22016-02-09 10:55:33 -08006531 public void setUse32bitAbi(boolean use32bitAbi) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006532 this.use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006533 if (childPackages != null) {
6534 final int packageCount = childPackages.size();
6535 for (int i = 0; i < packageCount; i++) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006536 childPackages.get(i).use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006537 }
6538 }
6539 }
6540
Svetoslav Ganov40610e32017-06-20 19:35:51 -07006541 public boolean isLibrary() {
6542 return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
6543 }
6544
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006545 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07006546 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006547 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07006548 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6549 Collections.addAll(paths, splitCodePaths);
6550 }
6551 return paths;
6552 }
6553
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006554 /**
6555 * Filtered set of {@link #getAllCodePaths()} that excludes
6556 * resource-only APKs.
6557 */
6558 public List<String> getAllCodePathsExcludingResourceOnly() {
6559 ArrayList<String> paths = new ArrayList<>();
6560 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6561 paths.add(baseCodePath);
6562 }
6563 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6564 for (int i = 0; i < splitCodePaths.length; i++) {
6565 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6566 paths.add(splitCodePaths[i]);
6567 }
6568 }
6569 }
6570 return paths;
6571 }
6572
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006573 public void setPackageName(String newName) {
6574 packageName = newName;
6575 applicationInfo.packageName = newName;
6576 for (int i=permissions.size()-1; i>=0; i--) {
6577 permissions.get(i).setPackageName(newName);
6578 }
6579 for (int i=permissionGroups.size()-1; i>=0; i--) {
6580 permissionGroups.get(i).setPackageName(newName);
6581 }
6582 for (int i=activities.size()-1; i>=0; i--) {
6583 activities.get(i).setPackageName(newName);
6584 }
6585 for (int i=receivers.size()-1; i>=0; i--) {
6586 receivers.get(i).setPackageName(newName);
6587 }
6588 for (int i=providers.size()-1; i>=0; i--) {
6589 providers.get(i).setPackageName(newName);
6590 }
6591 for (int i=services.size()-1; i>=0; i--) {
6592 services.get(i).setPackageName(newName);
6593 }
6594 for (int i=instrumentation.size()-1; i>=0; i--) {
6595 instrumentation.get(i).setPackageName(newName);
6596 }
6597 }
Dianne Hackborn65696252012-03-05 18:49:21 -08006598
6599 public boolean hasComponentClassName(String name) {
6600 for (int i=activities.size()-1; i>=0; i--) {
6601 if (name.equals(activities.get(i).className)) {
6602 return true;
6603 }
6604 }
6605 for (int i=receivers.size()-1; i>=0; i--) {
6606 if (name.equals(receivers.get(i).className)) {
6607 return true;
6608 }
6609 }
6610 for (int i=providers.size()-1; i>=0; i--) {
6611 if (name.equals(providers.get(i).className)) {
6612 return true;
6613 }
6614 }
6615 for (int i=services.size()-1; i>=0; i--) {
6616 if (name.equals(services.get(i).className)) {
6617 return true;
6618 }
6619 }
6620 for (int i=instrumentation.size()-1; i>=0; i--) {
6621 if (name.equals(instrumentation.get(i).className)) {
6622 return true;
6623 }
6624 }
6625 return false;
6626 }
6627
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006628 /** @hide */
6629 public boolean isExternal() {
6630 return applicationInfo.isExternal();
6631 }
6632
6633 /** @hide */
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08006634 public boolean isForwardLocked() {
6635 return applicationInfo.isForwardLocked();
6636 }
6637
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006638 /** @hide */
6639 public boolean isOem() {
6640 return applicationInfo.isOem();
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006641 }
6642
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006643 /** @hide */
Jiyong Park002fdbd2017-02-13 20:50:31 +09006644 public boolean isVendor() {
6645 return applicationInfo.isVendor();
6646 }
6647
6648 /** @hide */
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09006649 public boolean isProduct() {
6650 return applicationInfo.isProduct();
6651 }
6652
6653 /** @hide */
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006654 public boolean isPrivileged() {
Svet Ganovadc1cf42015-06-15 16:36:24 -07006655 return applicationInfo.isPrivilegedApp();
6656 }
6657
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006658 /** @hide */
6659 public boolean isSystem() {
6660 return applicationInfo.isSystemApp();
6661 }
6662
6663 /** @hide */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006664 public boolean isUpdatedSystemApp() {
6665 return applicationInfo.isUpdatedSystemApp();
6666 }
6667
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006668 /** @hide */
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006669 public boolean canHaveOatDir() {
6670 // The following app types CANNOT have oat directory
6671 // - non-updated system apps
6672 // - forward-locked apps or apps installed in ASEC containers
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006673 return (!isSystem() || isUpdatedSystemApp())
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006674 && !isForwardLocked() && !applicationInfo.isExternalAsec();
6675 }
6676
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006677 public boolean isMatch(int flags) {
6678 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006679 return isSystem();
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006680 }
6681 return true;
6682 }
6683
Brian Carlstromca82e612016-04-19 23:16:08 -07006684 public long getLatestPackageUseTimeInMills() {
6685 long latestUse = 0L;
6686 for (long use : mLastPackageUsageTimeInMills) {
6687 latestUse = Math.max(latestUse, use);
6688 }
6689 return latestUse;
6690 }
6691
David Brazdil90e26992016-04-18 14:08:52 +01006692 public long getLatestForegroundPackageUseTimeInMills() {
6693 int[] foregroundReasons = {
6694 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
6695 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
6696 };
6697
6698 long latestUse = 0L;
6699 for (int reason : foregroundReasons) {
6700 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
6701 }
6702 return latestUse;
6703 }
6704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006705 public String toString() {
6706 return "Package{"
6707 + Integer.toHexString(System.identityHashCode(this))
6708 + " " + packageName + "}";
6709 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006710
6711 @Override
6712 public int describeContents() {
6713 return 0;
6714 }
6715
6716 public Package(Parcel dest) {
6717 // We use the boot classloader for all classes that we load.
6718 final ClassLoader boot = Object.class.getClassLoader();
6719
Narayan Kamath07ac1442017-02-10 15:08:07 +00006720 packageName = dest.readString().intern();
Svet Ganov67882122016-12-11 16:36:34 -08006721 manifestPackageName = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006722 splitNames = dest.readStringArray();
6723 volumeUuid = dest.readString();
6724 codePath = dest.readString();
6725 baseCodePath = dest.readString();
6726 splitCodePaths = dest.readStringArray();
6727 baseRevisionCode = dest.readInt();
6728 splitRevisionCodes = dest.createIntArray();
6729 splitFlags = dest.createIntArray();
6730 splitPrivateFlags = dest.createIntArray();
6731 baseHardwareAccelerated = (dest.readInt() == 1);
6732 applicationInfo = dest.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006733 if (applicationInfo.permission != null) {
6734 applicationInfo.permission = applicationInfo.permission.intern();
6735 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006736
6737 // We don't serialize the "owner" package and the application info object for each of
6738 // these components, in order to save space and to avoid circular dependencies while
6739 // serialization. We need to fix them all up here.
6740 dest.readParcelableList(permissions, boot);
6741 fixupOwner(permissions);
6742 dest.readParcelableList(permissionGroups, boot);
6743 fixupOwner(permissionGroups);
6744 dest.readParcelableList(activities, boot);
6745 fixupOwner(activities);
6746 dest.readParcelableList(receivers, boot);
6747 fixupOwner(receivers);
6748 dest.readParcelableList(providers, boot);
6749 fixupOwner(providers);
6750 dest.readParcelableList(services, boot);
6751 fixupOwner(services);
6752 dest.readParcelableList(instrumentation, boot);
6753 fixupOwner(instrumentation);
6754
6755 dest.readStringList(requestedPermissions);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006756 internStringArrayList(requestedPermissions);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006757 protectedBroadcasts = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006758 internStringArrayList(protectedBroadcasts);
6759
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006760 parentPackage = dest.readParcelable(boot);
6761
6762 childPackages = new ArrayList<>();
6763 dest.readParcelableList(childPackages, boot);
6764 if (childPackages.size() == 0) {
6765 childPackages = null;
6766 }
6767
Svet Ganov67882122016-12-11 16:36:34 -08006768 staticSharedLibName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006769 if (staticSharedLibName != null) {
6770 staticSharedLibName = staticSharedLibName.intern();
6771 }
Dianne Hackborn3accca02013-09-20 09:32:11 -07006772 staticSharedLibVersion = dest.readLong();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006773 libraryNames = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006774 internStringArrayList(libraryNames);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006775 usesLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006776 internStringArrayList(usesLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006777 usesOptionalLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006778 internStringArrayList(usesOptionalLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006779 usesLibraryFiles = dest.readStringArray();
6780
Svet Ganov67882122016-12-11 16:36:34 -08006781 final int libCount = dest.readInt();
6782 if (libCount > 0) {
6783 usesStaticLibraries = new ArrayList<>(libCount);
6784 dest.readStringList(usesStaticLibraries);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006785 internStringArrayList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006786 usesStaticLibrariesVersions = new long[libCount];
6787 dest.readLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006788 usesStaticLibrariesCertDigests = new String[libCount][];
6789 for (int i = 0; i < libCount; i++) {
6790 usesStaticLibrariesCertDigests[i] = dest.createStringArray();
6791 }
Svet Ganov67882122016-12-11 16:36:34 -08006792 }
6793
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006794 preferredActivityFilters = new ArrayList<>();
6795 dest.readParcelableList(preferredActivityFilters, boot);
6796 if (preferredActivityFilters.size() == 0) {
6797 preferredActivityFilters = null;
6798 }
6799
6800 mOriginalPackages = dest.createStringArrayList();
6801 mRealPackage = dest.readString();
6802 mAdoptPermissions = dest.createStringArrayList();
6803 mAppMetaData = dest.readBundle();
6804 mVersionCode = dest.readInt();
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08006805 mVersionCodeMajor = dest.readInt();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006806 mVersionName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006807 if (mVersionName != null) {
6808 mVersionName = mVersionName.intern();
6809 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006810 mSharedUserId = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006811 if (mSharedUserId != null) {
6812 mSharedUserId = mSharedUserId.intern();
6813 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006814 mSharedUserLabel = dest.readInt();
6815
Patrick Baumann47117fc2017-12-19 10:17:21 -08006816 mSigningDetails = dest.readParcelable(boot);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006817
6818 mPreferredOrder = dest.readInt();
6819
6820 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6821 // is parsed from the APK.
6822
6823 // Object mExtras is not persisted because it is not information that is read from
6824 // the APK, rather, it is supplied by callers.
6825
6826
6827 configPreferences = new ArrayList<>();
6828 dest.readParcelableList(configPreferences, boot);
6829 if (configPreferences.size() == 0) {
6830 configPreferences = null;
6831 }
6832
6833 reqFeatures = new ArrayList<>();
6834 dest.readParcelableList(reqFeatures, boot);
6835 if (reqFeatures.size() == 0) {
6836 reqFeatures = null;
6837 }
6838
6839 featureGroups = new ArrayList<>();
6840 dest.readParcelableList(featureGroups, boot);
6841 if (featureGroups.size() == 0) {
6842 featureGroups = null;
6843 }
6844
6845 installLocation = dest.readInt();
6846 coreApp = (dest.readInt() == 1);
6847 mRequiredForAllUsers = (dest.readInt() == 1);
6848 mRestrictedAccountType = dest.readString();
6849 mRequiredAccountType = dest.readString();
6850 mOverlayTarget = dest.readString();
Adrian Roosc84df772018-01-19 21:20:22 +01006851 mOverlayCategory = dest.readString();
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006852 mOverlayPriority = dest.readInt();
Adam Lesinskie7334972018-01-17 16:13:52 -08006853 mOverlayIsStatic = (dest.readInt() == 1);
Alan Viveretteb6a25732017-11-21 14:49:24 -05006854 mCompileSdkVersion = dest.readInt();
6855 mCompileSdkVersionCodename = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006856 mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
6857
6858 mKeySetMapping = readKeySetMapping(dest);
6859
6860 cpuAbiOverride = dest.readString();
6861 use32bitAbi = (dest.readInt() == 1);
6862 restrictUpdateHash = dest.createByteArray();
Chad Brubaker49f24c62017-04-05 13:08:21 -07006863 visibleToInstantApps = dest.readInt() == 1;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006864 }
6865
Narayan Kamath07ac1442017-02-10 15:08:07 +00006866 private static void internStringArrayList(List<String> list) {
6867 if (list != null) {
6868 final int N = list.size();
6869 for (int i = 0; i < N; ++i) {
6870 list.set(i, list.get(i).intern());
6871 }
6872 }
6873 }
6874
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006875 /**
6876 * Sets the package owner and the the {@code applicationInfo} for every component
6877 * owner by this package.
6878 */
6879 private void fixupOwner(List<? extends Component<?>> list) {
6880 if (list != null) {
6881 for (Component<?> c : list) {
6882 c.owner = this;
6883 if (c instanceof Activity) {
6884 ((Activity) c).info.applicationInfo = this.applicationInfo;
6885 } else if (c instanceof Service) {
6886 ((Service) c).info.applicationInfo = this.applicationInfo;
6887 } else if (c instanceof Provider) {
6888 ((Provider) c).info.applicationInfo = this.applicationInfo;
6889 }
6890 }
6891 }
6892 }
6893
6894 @Override
6895 public void writeToParcel(Parcel dest, int flags) {
6896 dest.writeString(packageName);
Svet Ganov67882122016-12-11 16:36:34 -08006897 dest.writeString(manifestPackageName);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006898 dest.writeStringArray(splitNames);
6899 dest.writeString(volumeUuid);
6900 dest.writeString(codePath);
6901 dest.writeString(baseCodePath);
6902 dest.writeStringArray(splitCodePaths);
6903 dest.writeInt(baseRevisionCode);
6904 dest.writeIntArray(splitRevisionCodes);
6905 dest.writeIntArray(splitFlags);
6906 dest.writeIntArray(splitPrivateFlags);
6907 dest.writeInt(baseHardwareAccelerated ? 1 : 0);
6908 dest.writeParcelable(applicationInfo, flags);
6909
6910 dest.writeParcelableList(permissions, flags);
6911 dest.writeParcelableList(permissionGroups, flags);
6912 dest.writeParcelableList(activities, flags);
6913 dest.writeParcelableList(receivers, flags);
6914 dest.writeParcelableList(providers, flags);
6915 dest.writeParcelableList(services, flags);
6916 dest.writeParcelableList(instrumentation, flags);
6917
6918 dest.writeStringList(requestedPermissions);
6919 dest.writeStringList(protectedBroadcasts);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07006920
6921 // TODO: This doesn't work: b/64295061
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006922 dest.writeParcelable(parentPackage, flags);
6923 dest.writeParcelableList(childPackages, flags);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07006924
Svet Ganov67882122016-12-11 16:36:34 -08006925 dest.writeString(staticSharedLibName);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006926 dest.writeLong(staticSharedLibVersion);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006927 dest.writeStringList(libraryNames);
6928 dest.writeStringList(usesLibraries);
6929 dest.writeStringList(usesOptionalLibraries);
6930 dest.writeStringArray(usesLibraryFiles);
6931
Svet Ganov67882122016-12-11 16:36:34 -08006932 if (ArrayUtils.isEmpty(usesStaticLibraries)) {
6933 dest.writeInt(-1);
6934 } else {
6935 dest.writeInt(usesStaticLibraries.size());
6936 dest.writeStringList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006937 dest.writeLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006938 for (String[] usesStaticLibrariesCertDigest : usesStaticLibrariesCertDigests) {
6939 dest.writeStringArray(usesStaticLibrariesCertDigest);
6940 }
Svet Ganov67882122016-12-11 16:36:34 -08006941 }
6942
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006943 dest.writeParcelableList(preferredActivityFilters, flags);
6944
6945 dest.writeStringList(mOriginalPackages);
6946 dest.writeString(mRealPackage);
6947 dest.writeStringList(mAdoptPermissions);
6948 dest.writeBundle(mAppMetaData);
6949 dest.writeInt(mVersionCode);
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08006950 dest.writeInt(mVersionCodeMajor);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006951 dest.writeString(mVersionName);
6952 dest.writeString(mSharedUserId);
6953 dest.writeInt(mSharedUserLabel);
6954
Patrick Baumann47117fc2017-12-19 10:17:21 -08006955 dest.writeParcelable(mSigningDetails, flags);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006956
6957 dest.writeInt(mPreferredOrder);
6958
6959 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6960 // is parsed from the APK.
6961
6962 // Object mExtras is not persisted because it is not information that is read from
6963 // the APK, rather, it is supplied by callers.
6964
6965 dest.writeParcelableList(configPreferences, flags);
6966 dest.writeParcelableList(reqFeatures, flags);
6967 dest.writeParcelableList(featureGroups, flags);
6968
6969 dest.writeInt(installLocation);
6970 dest.writeInt(coreApp ? 1 : 0);
6971 dest.writeInt(mRequiredForAllUsers ? 1 : 0);
6972 dest.writeString(mRestrictedAccountType);
6973 dest.writeString(mRequiredAccountType);
6974 dest.writeString(mOverlayTarget);
Adrian Roosc84df772018-01-19 21:20:22 +01006975 dest.writeString(mOverlayCategory);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006976 dest.writeInt(mOverlayPriority);
Adam Lesinskie7334972018-01-17 16:13:52 -08006977 dest.writeInt(mOverlayIsStatic ? 1 : 0);
Alan Viveretteb6a25732017-11-21 14:49:24 -05006978 dest.writeInt(mCompileSdkVersion);
6979 dest.writeString(mCompileSdkVersionCodename);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006980 dest.writeArraySet(mUpgradeKeySets);
6981 writeKeySetMapping(dest, mKeySetMapping);
6982 dest.writeString(cpuAbiOverride);
6983 dest.writeInt(use32bitAbi ? 1 : 0);
6984 dest.writeByteArray(restrictUpdateHash);
Chad Brubaker49f24c62017-04-05 13:08:21 -07006985 dest.writeInt(visibleToInstantApps ? 1 : 0);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006986 }
6987
6988
6989 /**
6990 * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
6991 */
6992 private static void writeKeySetMapping(
6993 Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
6994 if (keySetMapping == null) {
6995 dest.writeInt(-1);
6996 return;
6997 }
6998
6999 final int N = keySetMapping.size();
7000 dest.writeInt(N);
7001
7002 for (int i = 0; i < N; i++) {
7003 dest.writeString(keySetMapping.keyAt(i));
7004 ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
7005 if (keys == null) {
7006 dest.writeInt(-1);
7007 continue;
7008 }
7009
7010 final int M = keys.size();
7011 dest.writeInt(M);
7012 for (int j = 0; j < M; j++) {
7013 dest.writeSerializable(keys.valueAt(j));
7014 }
7015 }
7016 }
7017
7018 /**
7019 * Reads a keyset mapping from the given parcel at the given data position. May return
7020 * {@code null} if the serialized mapping was {@code null}.
7021 */
7022 private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
7023 final int N = in.readInt();
7024 if (N == -1) {
7025 return null;
7026 }
7027
7028 ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
7029 for (int i = 0; i < N; ++i) {
7030 String key = in.readString();
7031 final int M = in.readInt();
7032 if (M == -1) {
7033 keySetMapping.put(key, null);
7034 continue;
7035 }
7036
7037 ArraySet<PublicKey> keys = new ArraySet<>(M);
7038 for (int j = 0; j < M; ++j) {
7039 PublicKey pk = (PublicKey) in.readSerializable();
7040 keys.add(pk);
7041 }
7042
7043 keySetMapping.put(key, keys);
7044 }
7045
7046 return keySetMapping;
7047 }
7048
7049 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
7050 public Package createFromParcel(Parcel in) {
7051 return new Package(in);
7052 }
7053
7054 public Package[] newArray(int size) {
7055 return new Package[size];
7056 }
7057 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007058 }
7059
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007060 public static abstract class Component<II extends IntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007061 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007062 public final String className;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007063
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007064 public Bundle metaData;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007065 public Package owner;
Todd Kennedy6d418b62018-02-22 14:15:18 -08007066 /** The order of this component in relation to its peers */
7067 public int order;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007068
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007069 ComponentName componentName;
7070 String componentShortName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007072 public Component(Package _owner) {
7073 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007074 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007075 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007076 }
7077
7078 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
7079 owner = args.owner;
7080 intents = new ArrayList<II>(0);
Todd Kennedybb8a42d2016-06-02 14:13:56 -07007081 if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
7082 true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
7083 args.roundIconRes, args.logoRes, args.bannerRes)) {
7084 className = outInfo.name;
7085 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007086 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007087 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007088 }
7089
7090 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
7091 this(args, (PackageItemInfo)outInfo);
7092 if (args.outError[0] != null) {
7093 return;
7094 }
7095
7096 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007097 CharSequence pname;
7098 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07007099 pname = args.sa.getNonConfigurationString(args.processRes,
7100 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007101 } else {
7102 // Some older apps have been seen to use a resource reference
7103 // here that on older builds was ignored (with a warning). We
7104 // need to continue to do this for them so they don't break.
7105 pname = args.sa.getNonResourceString(args.processRes);
7106 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007107 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007108 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007109 args.flags, args.sepProcesses, args.outError);
7110 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007111
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08007112 if (args.descriptionRes != 0) {
7113 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
7114 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007115
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007116 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007117 }
7118
7119 public Component(Component<II> clone) {
7120 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007121 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007122 className = clone.className;
7123 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007124 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007125 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007126
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007127 public ComponentName getComponentName() {
7128 if (componentName != null) {
7129 return componentName;
7130 }
7131 if (className != null) {
7132 componentName = new ComponentName(owner.applicationInfo.packageName,
7133 className);
7134 }
7135 return componentName;
7136 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007137
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007138 protected Component(Parcel in) {
7139 className = in.readString();
7140 metaData = in.readBundle();
7141 intents = createIntentsList(in);
7142
7143 owner = null;
7144 }
7145
7146 protected void writeToParcel(Parcel dest, int flags) {
7147 dest.writeString(className);
7148 dest.writeBundle(metaData);
7149
7150 writeIntentsList(intents, dest, flags);
7151 }
7152
7153 /**
7154 * <p>
7155 * Implementation note: The serialized form for the intent list also contains the name
7156 * of the concrete class that's stored in the list, and assumes that every element of the
7157 * list is of the same type. This is very similar to the original parcelable mechanism.
7158 * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
7159 * and is public API. It also declares Parcelable related methods as final which means
7160 * we can't extend them. The approach of using composition instead of inheritance leads to
7161 * a large set of cascading changes in the PackageManagerService, which seem undesirable.
7162 *
7163 * <p>
7164 * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
7165 * to make sure their owner fields are consistent. See {@code fixupOwner}.
7166 */
7167 private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out,
7168 int flags) {
7169 if (list == null) {
7170 out.writeInt(-1);
7171 return;
7172 }
7173
7174 final int N = list.size();
7175 out.writeInt(N);
7176
7177 // Don't bother writing the component name if the list is empty.
7178 if (N > 0) {
7179 IntentInfo info = list.get(0);
7180 out.writeString(info.getClass().getName());
7181
7182 for (int i = 0; i < N;i++) {
7183 list.get(i).writeIntentInfoToParcel(out, flags);
7184 }
7185 }
7186 }
7187
7188 private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) {
7189 int N = in.readInt();
7190 if (N == -1) {
7191 return null;
7192 }
7193
7194 if (N == 0) {
7195 return new ArrayList<>(0);
7196 }
7197
7198 String componentName = in.readString();
7199 final ArrayList<T> intentsList;
7200 try {
7201 final Class<T> cls = (Class<T>) Class.forName(componentName);
7202 final Constructor<T> cons = cls.getConstructor(Parcel.class);
7203
7204 intentsList = new ArrayList<>(N);
7205 for (int i = 0; i < N; ++i) {
7206 intentsList.add(cons.newInstance(in));
7207 }
7208 } catch (ReflectiveOperationException ree) {
7209 throw new AssertionError("Unable to construct intent list for: " + componentName);
7210 }
7211
7212 return intentsList;
7213 }
7214
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007215 public void appendComponentShortName(StringBuilder sb) {
7216 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007217 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007218
7219 public void printComponentShortName(PrintWriter pw) {
7220 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
7221 }
7222
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007223 public void setPackageName(String packageName) {
7224 componentName = null;
7225 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007226 }
7227 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007228
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007229 public final static class Permission extends Component<IntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007230 public final PermissionInfo info;
7231 public boolean tree;
7232 public PermissionGroup group;
7233
7234 public Permission(Package _owner) {
7235 super(_owner);
7236 info = new PermissionInfo();
7237 }
7238
7239 public Permission(Package _owner, PermissionInfo _info) {
7240 super(_owner);
7241 info = _info;
7242 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007243
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007244 public void setPackageName(String packageName) {
7245 super.setPackageName(packageName);
7246 info.packageName = packageName;
7247 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007248
7249 public String toString() {
7250 return "Permission{"
7251 + Integer.toHexString(System.identityHashCode(this))
7252 + " " + info.name + "}";
7253 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007254
7255 @Override
7256 public int describeContents() {
7257 return 0;
7258 }
7259
7260 @Override
7261 public void writeToParcel(Parcel dest, int flags) {
7262 super.writeToParcel(dest, flags);
7263 dest.writeParcelable(info, flags);
7264 dest.writeInt(tree ? 1 : 0);
7265 dest.writeParcelable(group, flags);
7266 }
7267
Todd Kennedyc8423932017-10-05 08:58:36 -07007268 /** @hide */
7269 public boolean isAppOp() {
7270 return info.isAppOp();
7271 }
7272
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007273 private Permission(Parcel in) {
7274 super(in);
7275 final ClassLoader boot = Object.class.getClassLoader();
7276 info = in.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007277 if (info.group != null) {
7278 info.group = info.group.intern();
7279 }
7280
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007281 tree = (in.readInt() == 1);
7282 group = in.readParcelable(boot);
7283 }
7284
7285 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
7286 public Permission createFromParcel(Parcel in) {
7287 return new Permission(in);
7288 }
7289
7290 public Permission[] newArray(int size) {
7291 return new Permission[size];
7292 }
7293 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007294 }
7295
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007296 public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007297 public final PermissionGroupInfo info;
7298
7299 public PermissionGroup(Package _owner) {
7300 super(_owner);
7301 info = new PermissionGroupInfo();
7302 }
7303
7304 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
7305 super(_owner);
7306 info = _info;
7307 }
7308
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007309 public void setPackageName(String packageName) {
7310 super.setPackageName(packageName);
7311 info.packageName = packageName;
7312 }
7313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007314 public String toString() {
7315 return "PermissionGroup{"
7316 + Integer.toHexString(System.identityHashCode(this))
7317 + " " + info.name + "}";
7318 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007319
7320 @Override
7321 public int describeContents() {
7322 return 0;
7323 }
7324
7325 @Override
7326 public void writeToParcel(Parcel dest, int flags) {
7327 super.writeToParcel(dest, flags);
7328 dest.writeParcelable(info, flags);
7329 }
7330
7331 private PermissionGroup(Parcel in) {
7332 super(in);
7333 info = in.readParcelable(Object.class.getClassLoader());
7334 }
7335
7336 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
7337 public PermissionGroup createFromParcel(Parcel in) {
7338 return new PermissionGroup(in);
7339 }
7340
7341 public PermissionGroup[] newArray(int size) {
7342 return new PermissionGroup[size];
7343 }
7344 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007345 }
7346
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007347 private static boolean copyNeeded(int flags, Package p,
7348 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07007349 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007350 // We always need to copy for other users, since we need
7351 // to fix up the uid.
7352 return true;
7353 }
7354 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
7355 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07007356 if (p.applicationInfo.enabled != enabled) {
7357 return true;
7358 }
7359 }
Rubin Xubf67c9c2016-04-20 17:09:38 +01007360 boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
7361 if (state.suspended != suspended) {
7362 return true;
7363 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007364 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007365 return true;
7366 }
7367 if (state.stopped) {
7368 return true;
7369 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007370 if (state.instantApp != p.applicationInfo.isInstantApp()) {
7371 return true;
7372 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007373 if ((flags & PackageManager.GET_META_DATA) != 0
7374 && (metaData != null || p.mAppMetaData != null)) {
7375 return true;
7376 }
7377 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7378 && p.usesLibraryFiles != null) {
7379 return true;
7380 }
Svet Ganov67882122016-12-11 16:36:34 -08007381 if (p.staticSharedLibName != null) {
7382 return true;
7383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007384 return false;
7385 }
7386
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007387 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
7388 PackageUserState state) {
7389 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07007390 }
7391
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007392 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
7393 PackageUserState state) {
7394 // CompatibilityMode is global state.
7395 if (!sCompatibilityModeEnabled) {
7396 ai.disableCompatibilityMode();
7397 }
7398 if (state.installed) {
7399 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
7400 } else {
7401 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
7402 }
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00007403 if (state.suspended) {
7404 ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
7405 } else {
7406 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
7407 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007408 if (state.instantApp) {
7409 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
7410 } else {
7411 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
7412 }
Todd Kennedy5eb5a7d2017-08-01 07:42:47 -07007413 if (state.virtualPreload) {
7414 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7415 } else {
7416 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7417 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007418 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007419 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007420 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007421 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007422 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007423 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
7424 ai.enabled = true;
7425 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
7426 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
7427 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
7428 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
7429 ai.enabled = false;
7430 }
7431 ai.enabledSetting = state.enabled;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07007432 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7433 ai.category = state.categoryHint;
7434 }
Jeff Sharkey0078e1b2017-01-11 16:05:27 -07007435 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7436 ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
7437 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007438 ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
Todd Kennedyb2749472017-06-13 08:24:32 -07007439 ai.resourceDirs = state.overlayPaths;
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007440 }
7441
Amith Yamasani13593602012-03-22 16:16:17 -07007442 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007443 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007444 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007445 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007446 return null;
7447 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007448 if (!copyNeeded(flags, p, state, null, userId)
7449 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
7450 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
7451 // In this case it is safe to directly modify the internal ApplicationInfo state:
7452 // - CompatibilityMode is global state, so will be the same for every call.
7453 // - We only come in to here if the app should reported as installed; this is the
7454 // default state, and we will do a copy otherwise.
7455 // - The enable state will always be reported the same for the application across
7456 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
7457 // be doing a copy.
7458 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007459 return p.applicationInfo;
7460 }
7461
7462 // Make shallow copy so we can store the metadata/libraries safely
7463 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Jeff Sharkey15447792015-11-05 16:18:51 -08007464 ai.initForUser(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007465 if ((flags & PackageManager.GET_META_DATA) != 0) {
7466 ai.metaData = p.mAppMetaData;
7467 }
7468 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
7469 ai.sharedLibraryFiles = p.usesLibraryFiles;
7470 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007471 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007472 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007473 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007474 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007475 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007476 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007477 return ai;
7478 }
7479
Dianne Hackbornace27912014-09-18 18:38:30 -07007480 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
7481 PackageUserState state, int userId) {
7482 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007483 if (!checkUseInstalledOrHidden(flags, state, ai)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007484 return null;
7485 }
7486 // This is only used to return the ResolverActivity; we will just always
7487 // make a copy.
7488 ai = new ApplicationInfo(ai);
Jeff Sharkey15447792015-11-05 16:18:51 -08007489 ai.initForUser(userId);
Dianne Hackbornace27912014-09-18 18:38:30 -07007490 if (state.stopped) {
7491 ai.flags |= ApplicationInfo.FLAG_STOPPED;
7492 } else {
7493 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
7494 }
7495 updateApplicationInfo(ai, flags, state);
7496 return ai;
7497 }
7498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007499 public static final PermissionInfo generatePermissionInfo(
7500 Permission p, int flags) {
7501 if (p == null) return null;
7502 if ((flags&PackageManager.GET_META_DATA) == 0) {
7503 return p.info;
7504 }
7505 PermissionInfo pi = new PermissionInfo(p.info);
7506 pi.metaData = p.metaData;
7507 return pi;
7508 }
7509
7510 public static final PermissionGroupInfo generatePermissionGroupInfo(
7511 PermissionGroup pg, int flags) {
7512 if (pg == null) return null;
7513 if ((flags&PackageManager.GET_META_DATA) == 0) {
7514 return pg.info;
7515 }
7516 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
7517 pgi.metaData = pg.metaData;
7518 return pgi;
7519 }
7520
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007521 public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007522 public final ActivityInfo info;
Bryce Lee22571db2017-07-07 15:54:18 -07007523 private boolean mHasMaxAspectRatio;
7524
7525 private boolean hasMaxAspectRatio() {
7526 return mHasMaxAspectRatio;
7527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007528
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007529 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
7530 super(args, _info);
7531 info = _info;
7532 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007533 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007534
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007535 public void setPackageName(String packageName) {
7536 super.setPackageName(packageName);
7537 info.packageName = packageName;
7538 }
7539
Bryce Lee22571db2017-07-07 15:54:18 -07007540
7541 private void setMaxAspectRatio(float maxAspectRatio) {
7542 if (info.resizeMode == RESIZE_MODE_RESIZEABLE
7543 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
7544 // Resizeable activities can be put in any aspect ratio.
7545 return;
7546 }
7547
7548 if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
7549 // Ignore any value lesser than 1.0.
7550 return;
7551 }
7552
7553 info.maxAspectRatio = maxAspectRatio;
7554 mHasMaxAspectRatio = true;
7555 }
7556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007557 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007558 StringBuilder sb = new StringBuilder(128);
7559 sb.append("Activity{");
7560 sb.append(Integer.toHexString(System.identityHashCode(this)));
7561 sb.append(' ');
7562 appendComponentShortName(sb);
7563 sb.append('}');
7564 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007565 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007566
7567 @Override
7568 public int describeContents() {
7569 return 0;
7570 }
7571
7572 @Override
7573 public void writeToParcel(Parcel dest, int flags) {
7574 super.writeToParcel(dest, flags);
7575 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
Bryce Lee22571db2017-07-07 15:54:18 -07007576 dest.writeBoolean(mHasMaxAspectRatio);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007577 }
7578
7579 private Activity(Parcel in) {
7580 super(in);
7581 info = in.readParcelable(Object.class.getClassLoader());
Bryce Lee22571db2017-07-07 15:54:18 -07007582 mHasMaxAspectRatio = in.readBoolean();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007583
7584 for (ActivityIntentInfo aii : intents) {
7585 aii.activity = this;
Todd Kennedy6d418b62018-02-22 14:15:18 -08007586 order = Math.max(aii.getOrder(), order);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007587 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007588
7589 if (info.permission != null) {
7590 info.permission = info.permission.intern();
7591 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007592 }
7593
7594 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
7595 public Activity createFromParcel(Parcel in) {
7596 return new Activity(in);
7597 }
7598
7599 public Activity[] newArray(int size) {
7600 return new Activity[size];
7601 }
7602 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007603 }
7604
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007605 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
7606 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007607 if (a == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007608 if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007609 return null;
7610 }
7611 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007612 updateApplicationInfo(a.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007613 return a.info;
7614 }
7615 // Make shallow copies so we can store the metadata safely
7616 ActivityInfo ai = new ActivityInfo(a.info);
7617 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007618 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007619 return ai;
7620 }
7621
Dianne Hackbornace27912014-09-18 18:38:30 -07007622 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
7623 PackageUserState state, int userId) {
7624 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007625 if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007626 return null;
7627 }
7628 // This is only used to return the ResolverActivity; we will just always
7629 // make a copy.
7630 ai = new ActivityInfo(ai);
7631 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
7632 return ai;
7633 }
7634
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007635 public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007636 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007637
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007638 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
7639 super(args, _info);
7640 info = _info;
7641 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007642 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007643
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007644 public void setPackageName(String packageName) {
7645 super.setPackageName(packageName);
7646 info.packageName = packageName;
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("Service{");
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);
7668 }
7669
7670 private Service(Parcel in) {
7671 super(in);
7672 info = in.readParcelable(Object.class.getClassLoader());
7673
7674 for (ServiceIntentInfo aii : intents) {
7675 aii.service = this;
Todd Kennedy6d418b62018-02-22 14:15:18 -08007676 order = Math.max(aii.getOrder(), order);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007677 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007678
7679 if (info.permission != null) {
7680 info.permission = info.permission.intern();
7681 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007682 }
7683
7684 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
7685 public Service createFromParcel(Parcel in) {
7686 return new Service(in);
7687 }
7688
7689 public Service[] newArray(int size) {
7690 return new Service[size];
7691 }
7692 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007693 }
7694
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007695 public static final ServiceInfo generateServiceInfo(Service s, int flags,
7696 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007697 if (s == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007698 if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007699 return null;
7700 }
7701 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007702 updateApplicationInfo(s.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007703 return s.info;
7704 }
7705 // Make shallow copies so we can store the metadata safely
7706 ServiceInfo si = new ServiceInfo(s.info);
7707 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007708 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007709 return si;
7710 }
7711
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007712 public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007713 public final ProviderInfo info;
7714 public boolean syncable;
7715
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007716 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
7717 super(args, _info);
7718 info = _info;
7719 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007720 syncable = false;
7721 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007723 public Provider(Provider existingProvider) {
7724 super(existingProvider);
7725 this.info = existingProvider.info;
7726 this.syncable = existingProvider.syncable;
7727 }
7728
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007729 public void setPackageName(String packageName) {
7730 super.setPackageName(packageName);
7731 info.packageName = packageName;
7732 }
7733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007734 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007735 StringBuilder sb = new StringBuilder(128);
7736 sb.append("Provider{");
7737 sb.append(Integer.toHexString(System.identityHashCode(this)));
7738 sb.append(' ');
7739 appendComponentShortName(sb);
7740 sb.append('}');
7741 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007742 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007743
7744 @Override
7745 public int describeContents() {
7746 return 0;
7747 }
7748
7749 @Override
7750 public void writeToParcel(Parcel dest, int flags) {
7751 super.writeToParcel(dest, flags);
7752 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7753 dest.writeInt((syncable) ? 1 : 0);
7754 }
7755
7756 private Provider(Parcel in) {
7757 super(in);
7758 info = in.readParcelable(Object.class.getClassLoader());
7759 syncable = (in.readInt() == 1);
7760
7761 for (ProviderIntentInfo aii : intents) {
7762 aii.provider = this;
7763 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007764
7765 if (info.readPermission != null) {
7766 info.readPermission = info.readPermission.intern();
7767 }
7768
7769 if (info.writePermission != null) {
7770 info.writePermission = info.writePermission.intern();
7771 }
7772
7773 if (info.authority != null) {
7774 info.authority = info.authority.intern();
7775 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007776 }
7777
7778 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
7779 public Provider createFromParcel(Parcel in) {
7780 return new Provider(in);
7781 }
7782
7783 public Provider[] newArray(int size) {
7784 return new Provider[size];
7785 }
7786 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007787 }
7788
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007789 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
7790 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007791 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007792 if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007793 return null;
7794 }
7795 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007796 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007797 || p.info.uriPermissionPatterns == null)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007798 updateApplicationInfo(p.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007799 return p.info;
7800 }
7801 // Make shallow copies so we can store the metadata safely
7802 ProviderInfo pi = new ProviderInfo(p.info);
7803 pi.metaData = p.metaData;
7804 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
7805 pi.uriPermissionPatterns = null;
7806 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007807 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007808 return pi;
7809 }
7810
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007811 public final static class Instrumentation extends Component<IntentInfo> implements
7812 Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007813 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007814
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007815 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
7816 super(args, _info);
7817 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007818 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007819
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007820 public void setPackageName(String packageName) {
7821 super.setPackageName(packageName);
7822 info.packageName = packageName;
7823 }
7824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007825 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007826 StringBuilder sb = new StringBuilder(128);
7827 sb.append("Instrumentation{");
7828 sb.append(Integer.toHexString(System.identityHashCode(this)));
7829 sb.append(' ');
7830 appendComponentShortName(sb);
7831 sb.append('}');
7832 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007833 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007834
7835 @Override
7836 public int describeContents() {
7837 return 0;
7838 }
7839
7840 @Override
7841 public void writeToParcel(Parcel dest, int flags) {
7842 super.writeToParcel(dest, flags);
7843 dest.writeParcelable(info, flags);
7844 }
7845
7846 private Instrumentation(Parcel in) {
7847 super(in);
7848 info = in.readParcelable(Object.class.getClassLoader());
Narayan Kamath07ac1442017-02-10 15:08:07 +00007849
7850 if (info.targetPackage != null) {
7851 info.targetPackage = info.targetPackage.intern();
7852 }
7853
Dianne Hackborn1be53542017-04-28 13:36:00 -07007854 if (info.targetProcesses != null) {
7855 info.targetProcesses = info.targetProcesses.intern();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007856 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007857 }
7858
7859 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
7860 public Instrumentation createFromParcel(Parcel in) {
7861 return new Instrumentation(in);
7862 }
7863
7864 public Instrumentation[] newArray(int size) {
7865 return new Instrumentation[size];
7866 }
7867 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007868 }
7869
7870 public static final InstrumentationInfo generateInstrumentationInfo(
7871 Instrumentation i, int flags) {
7872 if (i == null) return null;
7873 if ((flags&PackageManager.GET_META_DATA) == 0) {
7874 return i.info;
7875 }
7876 InstrumentationInfo ii = new InstrumentationInfo(i.info);
7877 ii.metaData = i.metaData;
7878 return ii;
7879 }
7880
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007881 public static abstract class IntentInfo extends IntentFilter {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 public boolean hasDefault;
7883 public int labelRes;
7884 public CharSequence nonLocalizedLabel;
7885 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07007886 public int logo;
Jose Limaf78e3122014-03-06 12:13:15 -08007887 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07007888 public int preferred;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007889
7890 protected IntentInfo() {
7891 }
7892
7893 protected IntentInfo(Parcel dest) {
7894 super(dest);
7895 hasDefault = (dest.readInt() == 1);
7896 labelRes = dest.readInt();
7897 nonLocalizedLabel = dest.readCharSequence();
7898 icon = dest.readInt();
7899 logo = dest.readInt();
7900 banner = dest.readInt();
7901 preferred = dest.readInt();
7902 }
7903
7904
7905 public void writeIntentInfoToParcel(Parcel dest, int flags) {
7906 super.writeToParcel(dest, flags);
7907 dest.writeInt(hasDefault ? 1 : 0);
7908 dest.writeInt(labelRes);
7909 dest.writeCharSequence(nonLocalizedLabel);
7910 dest.writeInt(icon);
7911 dest.writeInt(logo);
7912 dest.writeInt(banner);
7913 dest.writeInt(preferred);
7914 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007915 }
7916
7917 public final static class ActivityIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007918 public Activity activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007919
7920 public ActivityIntentInfo(Activity _activity) {
7921 activity = _activity;
7922 }
7923
7924 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007925 StringBuilder sb = new StringBuilder(128);
7926 sb.append("ActivityIntentInfo{");
7927 sb.append(Integer.toHexString(System.identityHashCode(this)));
7928 sb.append(' ');
7929 activity.appendComponentShortName(sb);
7930 sb.append('}');
7931 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007932 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007933
7934 public ActivityIntentInfo(Parcel in) {
7935 super(in);
7936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007937 }
7938
7939 public final static class ServiceIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007940 public Service service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007941
7942 public ServiceIntentInfo(Service _service) {
7943 service = _service;
7944 }
7945
7946 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007947 StringBuilder sb = new StringBuilder(128);
7948 sb.append("ServiceIntentInfo{");
7949 sb.append(Integer.toHexString(System.identityHashCode(this)));
7950 sb.append(' ');
7951 service.appendComponentShortName(sb);
7952 sb.append('}');
7953 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007954 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007955
7956 public ServiceIntentInfo(Parcel in) {
7957 super(in);
7958 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007959 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007960
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007961 public static final class ProviderIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007962 public Provider provider;
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007963
7964 public ProviderIntentInfo(Provider provider) {
7965 this.provider = provider;
7966 }
7967
7968 public String toString() {
7969 StringBuilder sb = new StringBuilder(128);
7970 sb.append("ProviderIntentInfo{");
7971 sb.append(Integer.toHexString(System.identityHashCode(this)));
7972 sb.append(' ');
7973 provider.appendComponentShortName(sb);
7974 sb.append('}');
7975 return sb.toString();
7976 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007977
7978 public ProviderIntentInfo(Parcel in) {
7979 super(in);
7980 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007981 }
7982
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007983 /**
7984 * @hide
7985 */
7986 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
7987 sCompatibilityModeEnabled = compatibilityModeEnabled;
7988 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07007989
7990 public static class PackageParserException extends Exception {
7991 public final int error;
7992
7993 public PackageParserException(int error, String detailMessage) {
7994 super(detailMessage);
7995 this.error = error;
7996 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07007997
7998 public PackageParserException(int error, String detailMessage, Throwable throwable) {
7999 super(detailMessage, throwable);
8000 this.error = error;
8001 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07008002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008003}