blob: 79f3e53f1c9ed4a0a8dec6e379197df3758c1701 [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) {
Rhed Jaoc19da782018-06-13 11:16:16 +0800642 // Returns false if the package is hidden system app until installed.
643 if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
644 && !state.installed
645 && appInfo != null && appInfo.hiddenUntilInstalled) {
646 return false;
647 }
648
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700649 // If available for the target user, or trying to match uninstalled packages and it's
650 // a system app.
651 return state.isAvailable(flags)
652 || (appInfo != null && appInfo.isSystemApp()
Rhed Jaoc19da782018-06-13 11:16:16 +0800653 && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
654 || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
Amith Yamasani483f3b02012-03-13 16:08:00 -0700655 }
656
Christopher Tateba629da2013-11-13 17:42:28 -0800657 public static boolean isAvailable(PackageUserState state) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700658 return checkUseInstalledOrHidden(0, state, null);
Christopher Tateba629da2013-11-13 17:42:28 -0800659 }
660
Amith Yamasani13593602012-03-22 16:16:17 -0700661 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700662 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800663 Set<String> grantedPermissions, PackageUserState state, int userId) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700664 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700665 return null;
666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 PackageInfo pi = new PackageInfo();
668 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700669 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 pi.versionCode = p.mVersionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700671 pi.versionCodeMajor = p.mVersionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800672 pi.baseRevisionCode = p.baseRevisionCode;
673 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 pi.versionName = p.mVersionName;
675 pi.sharedUserId = p.mSharedUserId;
676 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700677 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800678 pi.installLocation = p.installLocation;
Todd Kennedy7c8addf2017-06-27 14:13:55 -0700679 pi.isStub = p.isStub;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700680 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700681 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
682 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
683 pi.requiredForAllUsers = p.mRequiredForAllUsers;
684 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700685 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700686 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100687 pi.overlayTarget = p.mOverlayTarget;
Adrian Roosc84df772018-01-19 21:20:22 +0100688 pi.overlayCategory = p.mOverlayCategory;
Jaekyun Seok42d53f62017-04-10 13:48:58 +0900689 pi.overlayPriority = p.mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -0800690 pi.mOverlayIsStatic = p.mOverlayIsStatic;
Alan Viveretteb6a25732017-11-21 14:49:24 -0500691 pi.compileSdkVersion = p.mCompileSdkVersion;
692 pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700693 pi.firstInstallTime = firstInstallTime;
694 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695 if ((flags&PackageManager.GET_GIDS) != 0) {
696 pi.gids = gids;
697 }
698 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700699 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 if (N > 0) {
701 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700702 p.configPreferences.toArray(pi.configPreferences);
703 }
704 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
705 if (N > 0) {
706 pi.reqFeatures = new FeatureInfo[N];
707 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700709 N = p.featureGroups != null ? p.featureGroups.size() : 0;
710 if (N > 0) {
711 pi.featureGroups = new FeatureGroupInfo[N];
712 p.featureGroups.toArray(pi.featureGroups);
713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700715 if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
716 final int N = p.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700718 int num = 0;
719 final ActivityInfo[] res = new ActivityInfo[N];
720 for (int i = 0; i < N; i++) {
721 final Activity a = p.activities.get(i);
722 if (state.isMatch(a.info, flags)) {
723 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800724 }
725 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700726 pi.activities = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 }
728 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700729 if ((flags & PackageManager.GET_RECEIVERS) != 0) {
730 final int N = p.receivers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700732 int num = 0;
733 final ActivityInfo[] res = new ActivityInfo[N];
734 for (int i = 0; i < N; i++) {
735 final Activity a = p.receivers.get(i);
736 if (state.isMatch(a.info, flags)) {
737 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 }
739 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700740 pi.receivers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800741 }
742 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700743 if ((flags & PackageManager.GET_SERVICES) != 0) {
744 final int N = p.services.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800745 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700746 int num = 0;
747 final ServiceInfo[] res = new ServiceInfo[N];
748 for (int i = 0; i < N; i++) {
749 final Service s = p.services.get(i);
750 if (state.isMatch(s.info, flags)) {
751 res[num++] = generateServiceInfo(s, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 }
753 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700754 pi.services = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 }
756 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700757 if ((flags & PackageManager.GET_PROVIDERS) != 0) {
758 final int N = p.providers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700760 int num = 0;
761 final ProviderInfo[] res = new ProviderInfo[N];
762 for (int i = 0; i < N; i++) {
763 final Provider pr = p.providers.get(i);
764 if (state.isMatch(pr.info, flags)) {
765 res[num++] = generateProviderInfo(pr, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 }
767 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700768 pi.providers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 }
770 }
771 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
772 int N = p.instrumentation.size();
773 if (N > 0) {
774 pi.instrumentation = new InstrumentationInfo[N];
775 for (int i=0; i<N; i++) {
776 pi.instrumentation[i] = generateInstrumentationInfo(
777 p.instrumentation.get(i), flags);
778 }
779 }
780 }
781 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
782 int N = p.permissions.size();
783 if (N > 0) {
784 pi.permissions = new PermissionInfo[N];
785 for (int i=0; i<N; i++) {
786 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
787 }
788 }
789 N = p.requestedPermissions.size();
790 if (N > 0) {
791 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800792 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 for (int i=0; i<N; i++) {
Dianne Hackborne639da72012-02-21 15:11:13 -0800794 final String perm = p.requestedPermissions.get(i);
795 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700796 // The notion of required permissions is deprecated but for compatibility.
Svetoslavc6d1c342015-02-26 14:44:43 -0800797 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800798 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
799 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
800 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 }
802 }
803 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800804 // deprecated method of getting signing certificates
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Daniel Cashman5cdda342018-01-19 07:22:52 -0800806 if (p.mSigningDetails.hasPastSigningCertificates()) {
807 // Package has included signing certificate rotation information. Return the oldest
808 // cert so that programmatic checks keep working even if unaware of key rotation.
809 pi.signatures = new Signature[1];
810 pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0];
811 } else if (p.mSigningDetails.hasSignatures()) {
812 // otherwise keep old behavior
Patrick Baumann47117fc2017-12-19 10:17:21 -0800813 int numberOfSigs = p.mSigningDetails.signatures.length;
814 pi.signatures = new Signature[numberOfSigs];
815 System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 }
817 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800818
819 // replacement for GET_SIGNATURES
820 if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
Dan Cashman5c9f527e2018-04-03 16:42:23 -0700821 if (p.mSigningDetails != SigningDetails.UNKNOWN) {
822 // only return a valid SigningInfo if there is signing information to report
823 pi.signingInfo = new SigningInfo(p.mSigningDetails);
824 } else {
825 pi.signingInfo = null;
Daniel Cashman5cdda342018-01-19 07:22:52 -0800826 }
827 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828 return pi;
829 }
830
Todd Kennedy232d29e2017-11-06 14:45:53 -0800831 public static final int PARSE_MUST_BE_APK = 1 << 0;
832 public static final int PARSE_IGNORE_PROCESSES = 1 << 1;
Todd Kennedy30a23a52018-01-04 13:27:49 -0800833 /** @deprecated forward lock no longer functional. remove. */
834 @Deprecated
Todd Kennedy232d29e2017-11-06 14:45:53 -0800835 public static final int PARSE_FORWARD_LOCK = 1 << 2;
836 public static final int PARSE_EXTERNAL_STORAGE = 1 << 3;
837 public static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
838 public static final int PARSE_COLLECT_CERTIFICATES = 1 << 5;
839 public static final int PARSE_ENFORCE_CODE = 1 << 6;
840 public static final int PARSE_FORCE_SDK = 1 << 7;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800841 public static final int PARSE_CHATTY = 1 << 31;
842
843 @IntDef(flag = true, prefix = { "PARSE_" }, value = {
844 PARSE_CHATTY,
845 PARSE_COLLECT_CERTIFICATES,
846 PARSE_ENFORCE_CODE,
847 PARSE_EXTERNAL_STORAGE,
848 PARSE_FORCE_SDK,
849 PARSE_FORWARD_LOCK,
850 PARSE_IGNORE_PROCESSES,
Todd Kennedy232d29e2017-11-06 14:45:53 -0800851 PARSE_IS_SYSTEM_DIR,
852 PARSE_MUST_BE_APK,
853 })
854 @Retention(RetentionPolicy.SOURCE)
855 public @interface ParseFlags {}
Jeff Sharkey275e0852014-06-17 18:18:49 -0700856
857 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800858
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700859 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700860 * Used to sort a set of APKs based on their split names, always placing the
861 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700862 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700863 private static class SplitNameComparator implements Comparator<String> {
864 @Override
865 public int compare(String lhs, String rhs) {
866 if (lhs == null) {
867 return -1;
868 } else if (rhs == null) {
869 return 1;
870 } else {
871 return lhs.compareTo(rhs);
872 }
873 }
874 }
875
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700876 /**
877 * Parse only lightweight details about the package at the given location.
878 * Automatically detects if the package is a monolithic style (single APK
879 * file) or cluster style (directory of APKs).
880 * <p>
881 * This performs sanity checking on cluster style packages, such as
882 * requiring identical package name and version codes, a single base APK,
883 * and unique split names.
884 *
885 * @see PackageParser#parsePackage(File, int)
886 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700887 public static PackageLite parsePackageLite(File packageFile, int flags)
888 throws PackageParserException {
889 if (packageFile.isDirectory()) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800890 return parseClusterPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700891 } else {
Adam Lesinski4e862812016-11-21 16:02:24 -0800892 return parseMonolithicPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700893 }
894 }
895
Adam Lesinski4e862812016-11-21 16:02:24 -0800896 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
897 throws PackageParserException {
Todd Kennedycd029da2016-07-21 07:41:09 -0700898 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Adam Lesinski4e862812016-11-21 16:02:24 -0800899 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700900 final String packagePath = packageFile.getAbsolutePath();
Todd Kennedycd029da2016-07-21 07:41:09 -0700901 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Narayan Kamath96c11c52017-08-09 13:07:21 +0100902 return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700903 }
904
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800905 static PackageLite parseClusterPackageLite(File packageDir, int flags)
Adam Lesinski4e862812016-11-21 16:02:24 -0800906 throws PackageParserException {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700907 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700908 if (ArrayUtils.isEmpty(files)) {
909 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
910 "No packages found in split");
911 }
912
Jeff Sharkey275e0852014-06-17 18:18:49 -0700913 String packageName = null;
914 int versionCode = 0;
915
Todd Kennedycd029da2016-07-21 07:41:09 -0700916 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700917 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700918 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700919 if (isApkFile(file)) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800920 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700921
922 // Assert that all package names and version codes are
923 // consistent with the first one we encounter.
924 if (packageName == null) {
925 packageName = lite.packageName;
926 versionCode = lite.versionCode;
927 } else {
928 if (!packageName.equals(lite.packageName)) {
929 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
930 "Inconsistent package " + lite.packageName + " in " + file
931 + "; expected " + packageName);
932 }
933 if (versionCode != lite.versionCode) {
934 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
935 "Inconsistent version " + lite.versionCode + " in " + file
936 + "; expected " + versionCode);
937 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700938 }
939
Jeff Sharkey275e0852014-06-17 18:18:49 -0700940 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700941 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700942 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
943 "Split name " + lite.splitName
944 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700945 }
946 }
947 }
Todd Kennedycd029da2016-07-21 07:41:09 -0700948 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700949
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700950 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700951 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700952 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700953 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700954 }
955
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700956 // Always apply deterministic ordering based on splitName
957 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700958
Jeff Sharkey73767b92014-07-04 20:18:13 -0700959 String[] splitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800960 boolean[] isFeatureSplits = null;
Adam Lesinski4e862812016-11-21 16:02:24 -0800961 String[] usesSplitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800962 String[] configForSplits = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700963 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800964 int[] splitRevisionCodes = null;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100965 String[] splitClassLoaderNames = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700966 if (size > 0) {
967 splitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800968 isFeatureSplits = new boolean[size];
Adam Lesinski4e862812016-11-21 16:02:24 -0800969 usesSplitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800970 configForSplits = new String[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700971 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800972 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700973
974 splitNames = apks.keySet().toArray(splitNames);
975 Arrays.sort(splitNames, sSplitNameComparator);
976
977 for (int i = 0; i < size; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800978 final ApkLite apk = apks.get(splitNames[i]);
979 usesSplitNames[i] = apk.usesSplitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800980 isFeatureSplits[i] = apk.isFeatureSplit;
981 configForSplits[i] = apk.configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800982 splitCodePaths[i] = apk.codePath;
983 splitRevisionCodes[i] = apk.revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700984 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700985 }
986
Jeff Sharkey73767b92014-07-04 20:18:13 -0700987 final String codePath = packageDir.getAbsolutePath();
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800988 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100989 configForSplits, splitCodePaths, splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700990 }
991
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700992 /**
993 * Parse the package at the given location. Automatically detects if the
994 * package is a monolithic style (single APK file) or cluster style
995 * (directory of APKs).
996 * <p>
997 * This performs sanity checking on cluster style packages, such as
998 * requiring identical package name and version codes, a single base APK,
999 * and unique split names.
1000 * <p>
1001 * Note that this <em>does not</em> perform signature verification; that
1002 * must be done separately in {@link #collectCertificates(Package, int)}.
1003 *
Narayan Kamath988149c2016-12-01 13:32:59 +00001004 * If {@code useCaches} is true, the package parser might return a cached
1005 * result from a previous parse of the same {@code packageFile} with the same
1006 * {@code flags}. Note that this method does not check whether {@code packageFile}
1007 * has changed since the last parse, it's up to callers to do so.
1008 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001009 * @see #parsePackageLite(File, int)
1010 */
Narayan Kamath988149c2016-12-01 13:32:59 +00001011 public Package parsePackage(File packageFile, int flags, boolean useCaches)
1012 throws PackageParserException {
1013 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
1014 if (parsed != null) {
1015 return parsed;
1016 }
1017
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001018 long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Jeff Sharkey73767b92014-07-04 20:18:13 -07001019 if (packageFile.isDirectory()) {
Narayan Kamath988149c2016-12-01 13:32:59 +00001020 parsed = parseClusterPackage(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001021 } else {
Narayan Kamath988149c2016-12-01 13:32:59 +00001022 parsed = parseMonolithicPackage(packageFile, flags);
1023 }
1024
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001025 long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Narayan Kamath988149c2016-12-01 13:32:59 +00001026 cacheResult(packageFile, flags, parsed);
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001027 if (LOG_PARSE_TIMINGS) {
1028 parseTime = cacheTime - parseTime;
1029 cacheTime = SystemClock.uptimeMillis() - cacheTime;
1030 if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
1031 Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
1032 + "ms, update_cache=" + cacheTime + " ms");
1033 }
1034 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001035 return parsed;
1036 }
1037
1038 /**
1039 * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}.
1040 */
1041 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
1042 return parsePackage(packageFile, flags, false /* useCaches */);
1043 }
1044
1045 /**
1046 * Returns the cache key for a specificied {@code packageFile} and {@code flags}.
1047 */
1048 private String getCacheKey(File packageFile, int flags) {
1049 StringBuilder sb = new StringBuilder(packageFile.getName());
1050 sb.append('-');
1051 sb.append(flags);
1052
1053 return sb.toString();
1054 }
1055
1056 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001057 protected Package fromCacheEntry(byte[] bytes) {
1058 return fromCacheEntryStatic(bytes);
1059 }
1060
1061 /** static version of {@link #fromCacheEntry} for unit tests. */
1062 @VisibleForTesting
1063 public static Package fromCacheEntryStatic(byte[] bytes) {
1064 final Parcel p = Parcel.obtain();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001065 p.unmarshall(bytes, 0, bytes.length);
1066 p.setDataPosition(0);
1067
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001068 final ReadHelper helper = new ReadHelper(p);
1069 helper.startAndInstall();
1070
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001071 PackageParser.Package pkg = new PackageParser.Package(p);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001072
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001073 p.recycle();
1074
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001075 sCachedPackageReadCount.incrementAndGet();
1076
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001077 return pkg;
Narayan Kamath988149c2016-12-01 13:32:59 +00001078 }
1079
1080 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001081 protected byte[] toCacheEntry(Package pkg) {
1082 return toCacheEntryStatic(pkg);
1083
1084 }
1085
1086 /** static version of {@link #toCacheEntry} for unit tests. */
1087 @VisibleForTesting
1088 public static byte[] toCacheEntryStatic(Package pkg) {
1089 final Parcel p = Parcel.obtain();
1090 final WriteHelper helper = new WriteHelper(p);
1091
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001092 pkg.writeToParcel(p, 0 /* flags */);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001093
1094 helper.finishAndUninstall();
1095
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001096 byte[] serialized = p.marshall();
1097 p.recycle();
1098
1099 return serialized;
Narayan Kamath988149c2016-12-01 13:32:59 +00001100 }
1101
1102 /**
1103 * Given a {@code packageFile} and a {@code cacheFile} returns whether the
1104 * cache file is up to date based on the mod-time of both files.
1105 */
1106 private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
1107 try {
1108 // NOTE: We don't use the File.lastModified API because it has the very
1109 // non-ideal failure mode of returning 0 with no excepions thrown.
1110 // The nio2 Files API is a little better but is considerably more expensive.
1111 final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
1112 final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
1113 return pkg.st_mtime < cache.st_mtime;
1114 } catch (ErrnoException ee) {
1115 // The most common reason why stat fails is that a given cache file doesn't
1116 // exist. We ignore that here. It's easy to reason that it's safe to say the
1117 // cache isn't up to date if we see any sort of exception here.
1118 //
1119 // (1) Exception while stating the package file : This should never happen,
1120 // and if it does, we do a full package parse (which is likely to throw the
1121 // same exception).
1122 // (2) Exception while stating the cache file : If the file doesn't exist, the
1123 // cache is obviously out of date. If the file *does* exist, we can't read it.
1124 // We will attempt to delete and recreate it after parsing the package.
1125 if (ee.errno != OsConstants.ENOENT) {
1126 Slog.w("Error while stating package cache : ", ee);
1127 }
1128
1129 return false;
1130 }
1131 }
1132
1133 /**
1134 * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
1135 * or {@code null} if no cached result exists.
1136 */
1137 private Package getCachedResult(File packageFile, int flags) {
1138 if (mCacheDir == null) {
1139 return null;
1140 }
1141
1142 final String cacheKey = getCacheKey(packageFile, flags);
1143 final File cacheFile = new File(mCacheDir, cacheKey);
1144
Narayan Kamath988149c2016-12-01 13:32:59 +00001145 try {
Makoto Onuki48e93162017-08-18 11:00:19 -07001146 // If the cache is not up to date, return null.
1147 if (!isCacheUpToDate(packageFile, cacheFile)) {
1148 return null;
1149 }
1150
Narayan Kamath988149c2016-12-01 13:32:59 +00001151 final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001152 Package p = fromCacheEntry(bytes);
1153 if (mCallback != null) {
1154 String[] overlayApks = mCallback.getOverlayApks(p.packageName);
1155 if (overlayApks != null && overlayApks.length > 0) {
1156 for (String overlayApk : overlayApks) {
1157 // If a static RRO is updated, return null.
1158 if (!isCacheUpToDate(new File(overlayApk), cacheFile)) {
1159 return null;
1160 }
1161 }
1162 }
1163 }
1164 return p;
Makoto Onuki48e93162017-08-18 11:00:19 -07001165 } catch (Throwable e) {
Narayan Kamath21a28382017-01-13 10:34:29 +00001166 Slog.w(TAG, "Error reading package cache: ", e);
Narayan Kamath988149c2016-12-01 13:32:59 +00001167
1168 // If something went wrong while reading the cache entry, delete the cache file
1169 // so that we regenerate it the next time.
1170 cacheFile.delete();
1171 return null;
1172 }
1173 }
1174
1175 /**
1176 * Caches the parse result for {@code packageFile} with flags {@code flags}.
1177 */
1178 private void cacheResult(File packageFile, int flags, Package parsed) {
1179 if (mCacheDir == null) {
1180 return;
1181 }
1182
Makoto Onuki48e93162017-08-18 11:00:19 -07001183 try {
1184 final String cacheKey = getCacheKey(packageFile, flags);
1185 final File cacheFile = new File(mCacheDir, cacheKey);
Narayan Kamath988149c2016-12-01 13:32:59 +00001186
Makoto Onuki48e93162017-08-18 11:00:19 -07001187 if (cacheFile.exists()) {
1188 if (!cacheFile.delete()) {
1189 Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
1190 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001191 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001192
Makoto Onuki48e93162017-08-18 11:00:19 -07001193 final byte[] cacheEntry = toCacheEntry(parsed);
Narayan Kamath988149c2016-12-01 13:32:59 +00001194
Makoto Onuki48e93162017-08-18 11:00:19 -07001195 if (cacheEntry == null) {
1196 return;
1197 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001198
Makoto Onuki48e93162017-08-18 11:00:19 -07001199 try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
1200 fos.write(cacheEntry);
1201 } catch (IOException ioe) {
1202 Slog.w(TAG, "Error writing cache entry.", ioe);
1203 cacheFile.delete();
1204 }
1205 } catch (Throwable e) {
1206 Slog.w(TAG, "Error saving package cache.", e);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001207 }
1208 }
1209
1210 /**
1211 * Parse all APKs contained in the given directory, treating them as a
1212 * single package. This also performs sanity checking, such as requiring
1213 * identical package name and version codes, a single base APK, and unique
1214 * split names.
1215 * <p>
1216 * Note that this <em>does not</em> perform signature verification; that
1217 * must be done separately in {@link #collectCertificates(Package, int)}.
1218 */
1219 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001220 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001221 if (mOnlyCoreApps && !lite.coreApp) {
1222 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1223 "Not a coreApp: " + packageDir);
1224 }
1225
Adam Lesinski4e862812016-11-21 16:02:24 -08001226 // Build the split dependency tree.
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001227 SparseArray<int[]> splitDependencies = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001228 final SplitAssetLoader assetLoader;
1229 if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001230 try {
1231 splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
1232 assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
1233 } catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
1234 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
1235 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001236 } else {
1237 assetLoader = new DefaultSplitAssetLoader(lite, flags);
1238 }
1239
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001240 try {
Adam Lesinski4e862812016-11-21 16:02:24 -08001241 final AssetManager assets = assetLoader.getBaseAssetManager();
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001242 final File baseApk = new File(lite.baseCodePath);
1243 final Package pkg = parseBaseApk(baseApk, assets, flags);
1244 if (pkg == null) {
1245 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1246 "Failed to parse base APK: " + baseApk);
1247 }
1248
1249 if (!ArrayUtils.isEmpty(lite.splitNames)) {
1250 final int num = lite.splitNames.length;
1251 pkg.splitNames = lite.splitNames;
1252 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001253 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001254 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001255 pkg.splitPrivateFlags = new int[num];
Adam Lesinski4e862812016-11-21 16:02:24 -08001256 pkg.applicationInfo.splitNames = pkg.splitNames;
1257 pkg.applicationInfo.splitDependencies = splitDependencies;
Narayan Kamath96c11c52017-08-09 13:07:21 +01001258 pkg.applicationInfo.splitClassLoaderNames = new String[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001259
1260 for (int i = 0; i < num; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -08001261 final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
1262 parseSplitApk(pkg, i, splitAssets, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001263 }
1264 }
1265
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001266 pkg.setCodePath(packageDir.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001267 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001268 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001269 } catch (IOException e) {
1270 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1271 "Failed to get path: " + lite.baseCodePath, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001272 } finally {
Adam Lesinski4e862812016-11-21 16:02:24 -08001273 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001274 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001275 }
1276
Jeff Sharkey275e0852014-06-17 18:18:49 -07001277 /**
1278 * Parse the given APK file, treating it as as a single monolithic package.
1279 * <p>
1280 * Note that this <em>does not</em> perform signature verification; that
1281 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001282 *
1283 * @deprecated external callers should move to
1284 * {@link #parsePackage(File, int)}. Eventually this method will
1285 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -07001286 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001287 @Deprecated
Jeff Sharkey275e0852014-06-17 18:18:49 -07001288 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001289 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001290 if (mOnlyCoreApps) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001291 if (!lite.coreApp) {
1292 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1293 "Not a coreApp: " + apkFile);
1294 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001295 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001296
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001297 final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001298 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001299 final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001300 pkg.setCodePath(apkFile.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001301 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001302 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001303 } catch (IOException e) {
1304 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1305 "Failed to get path: " + apkFile, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001306 } finally {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001307 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001308 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001309 }
1310
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001311 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
1312 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001313 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001314
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07001315 String volumeUuid = null;
1316 if (apkPath.startsWith(MNT_EXPAND)) {
1317 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
1318 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
1319 }
1320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001321 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001322 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001323
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001324 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001325
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001326 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001328 final int cookie = assets.findCookieForPath(apkPath);
1329 if (cookie == 0) {
1330 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1331 "Failed adding asset path: " + apkPath);
1332 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001333 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001334 final Resources res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001335
1336 final String[] outError = new String[1];
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001337 final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001338 if (pkg == null) {
1339 throw new PackageParserException(mParseError,
1340 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001341 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001342
Svet Ganov354cd3c2015-12-17 11:35:04 -08001343 pkg.setVolumeUuid(volumeUuid);
1344 pkg.setApplicationVolumeUuid(volumeUuid);
1345 pkg.setBaseCodePath(apkPath);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001346 pkg.setSigningDetails(SigningDetails.UNKNOWN);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001347
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001348 return pkg;
1349
1350 } catch (PackageParserException e) {
1351 throw e;
1352 } catch (Exception e) {
1353 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001354 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001355 } finally {
1356 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 }
1359
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001360 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001361 throws PackageParserException {
1362 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -07001363
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001364 mParseError = PackageManager.INSTALL_SUCCEEDED;
1365 mArchiveSourcePath = apkPath;
1366
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001367 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
1368
Adam Lesinski4e862812016-11-21 16:02:24 -08001369 final Resources res;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001370 XmlResourceParser parser = null;
1371 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001372 // This must always succeed, as the path has been added to the AssetManager before.
1373 final int cookie = assets.findCookieForPath(apkPath);
1374 if (cookie == 0) {
1375 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1376 "Failed adding asset path: " + apkPath);
1377 }
1378
Adam Lesinski56c82be2018-02-09 11:02:04 -08001379 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001380 res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001381
1382 final String[] outError = new String[1];
1383 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
1384 if (pkg == null) {
1385 throw new PackageParserException(mParseError,
1386 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
1387 }
1388
1389 } catch (PackageParserException e) {
1390 throw e;
1391 } catch (Exception e) {
1392 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001393 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001394 } finally {
1395 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001396 }
1397 }
1398
1399 /**
1400 * Parse the manifest of a <em>split APK</em>.
1401 * <p>
1402 * Note that split APKs have many more restrictions on what they're capable
1403 * of doing, so many valid features of a base APK have been carefully
1404 * omitted here.
1405 */
1406 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001407 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
1408 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001409 AttributeSet attrs = parser;
1410
Jeff Sharkey78a13012014-07-15 20:18:34 -07001411 // We parsed manifest tag earlier; just skip past it
Svet Ganov354cd3c2015-12-17 11:35:04 -08001412 parsePackageSplitNames(parser, attrs);
Jeff Sharkey78a13012014-07-15 20:18:34 -07001413
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001414 mParseInstrumentationArgs = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001415
1416 int type;
1417
1418 boolean foundApp = false;
1419
1420 int outerDepth = parser.getDepth();
1421 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1422 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1423 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1424 continue;
1425 }
1426
1427 String tagName = parser.getName();
Adam Lesinski4e862812016-11-21 16:02:24 -08001428 if (tagName.equals(TAG_APPLICATION)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001429 if (foundApp) {
1430 if (RIGID_PARSER) {
1431 outError[0] = "<manifest> has more than one <application>";
1432 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1433 return null;
1434 } else {
1435 Slog.w(TAG, "<manifest> has more than one <application>");
1436 XmlUtils.skipCurrentTag(parser);
1437 continue;
1438 }
1439 }
1440
1441 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001442 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001443 return null;
1444 }
1445
1446 } else if (RIGID_PARSER) {
1447 outError[0] = "Bad element under <manifest>: "
1448 + parser.getName();
1449 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1450 return null;
1451
1452 } else {
1453 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1454 + " at " + mArchiveSourcePath + " "
1455 + parser.getPositionDescription());
1456 XmlUtils.skipCurrentTag(parser);
1457 continue;
1458 }
1459 }
1460
1461 if (!foundApp) {
1462 outError[0] = "<manifest> does not contain an <application>";
1463 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1464 }
1465
1466 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001467 }
1468
Patrick Baumann47117fc2017-12-19 10:17:21 -08001469 /** Parses the public keys from the set of signatures. */
1470 public static ArraySet<PublicKey> toSigningKeys(Signature[] signatures)
1471 throws CertificateException {
1472 ArraySet<PublicKey> keys = new ArraySet<>(signatures.length);
1473 for (int i = 0; i < signatures.length; i++) {
1474 keys.add(signatures[i].getPublicKey());
Todd Kennedy66c55532016-02-26 16:22:11 -08001475 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001476 return keys;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001477 }
1478
1479 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -07001480 * Collect certificates from all the APKs described in the given package,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001481 * populating {@link Package#mSigningDetails}. Also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001482 * contents are signed correctly and consistently.
1483 */
Victor Hsieh5f761242018-01-20 10:30:12 -08001484 public static void collectCertificates(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001485 throws PackageParserException {
Victor Hsieh5f761242018-01-20 10:30:12 -08001486 collectCertificatesInternal(pkg, skipVerify);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001487 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1488 for (int i = 0; i < childCount; i++) {
1489 Package childPkg = pkg.childPackages.get(i);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001490 childPkg.mSigningDetails = pkg.mSigningDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001491 }
1492 }
1493
Victor Hsieh5f761242018-01-20 10:30:12 -08001494 private static void collectCertificatesInternal(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001495 throws PackageParserException {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001496 pkg.mSigningDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001497
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001498 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1499 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001500 collectCertificates(pkg, new File(pkg.baseCodePath), skipVerify);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001501
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001502 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1503 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
Victor Hsieh5f761242018-01-20 10:30:12 -08001504 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001505 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001506 }
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001507 } finally {
1508 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001509 }
1510 }
1511
Victor Hsieh5f761242018-01-20 10:30:12 -08001512 private static void collectCertificates(Package pkg, File apkFile, boolean skipVerify)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001513 throws PackageParserException {
1514 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515
Patrick Baumann47117fc2017-12-19 10:17:21 -08001516 int minSignatureScheme = SigningDetails.SignatureSchemeVersion.JAR;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001517 if (pkg.applicationInfo.isStaticSharedLibrary()) {
Dan Cashmane92f8422017-12-08 14:02:51 -08001518 // must use v2 signing scheme
Patrick Baumann47117fc2017-12-19 10:17:21 -08001519 minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;
Dan Cashmane92f8422017-12-08 14:02:51 -08001520 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001521 SigningDetails verified;
Victor Hsieh5f761242018-01-20 10:30:12 -08001522 if (skipVerify) {
Dan Cashman636ea5e2017-12-18 10:38:20 -08001523 // systemDir APKs are already trusted, save time by not verifying
1524 verified = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts(
1525 apkPath, minSignatureScheme);
1526 } else {
1527 verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme);
1528 }
Dan Cashman636ea5e2017-12-18 10:38:20 -08001529
1530 // Verify that entries are signed consistently with the first pkg
1531 // we encountered. Note that for splits, certificates may have
1532 // already been populated during an earlier parse of a base APK.
Patrick Baumann47117fc2017-12-19 10:17:21 -08001533 if (pkg.mSigningDetails == SigningDetails.UNKNOWN) {
1534 pkg.mSigningDetails = verified;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001535 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001536 if (!Signature.areExactMatch(pkg.mSigningDetails.signatures, verified.signatures)) {
Patrick Baumann9ff55742017-12-14 10:50:18 -08001537 throw new PackageParserException(
1538 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
1539 apkPath + " has mismatched certificates");
1540 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 }
1543
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001544 private static AssetManager newConfiguredAssetManager() {
1545 AssetManager assetManager = new AssetManager();
Romain Guy408afbf2017-01-25 10:23:03 -08001546 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 -07001547 Build.VERSION.RESOURCES_SDK_INT);
1548 return assetManager;
1549 }
1550
Jeff Sharkey275e0852014-06-17 18:18:49 -07001551 /**
1552 * Utility method that retrieves lightweight details about a single APK
1553 * file, including package name, split name, and install location.
1554 *
1555 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001556 * @param flags optional parse flags, such as
1557 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001558 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001559 public static ApkLite parseApkLite(File apkFile, int flags)
1560 throws PackageParserException {
Dianne Hackbornca3872c2017-10-30 14:19:32 -07001561 return parseApkLiteInner(apkFile, null, null, flags);
1562 }
1563
1564 /**
1565 * Utility method that retrieves lightweight details about a single APK
1566 * file, including package name, split name, and install location.
1567 *
1568 * @param fd already open file descriptor of an apk file
1569 * @param debugPathName arbitrary text name for this file, for debug output
1570 * @param flags optional parse flags, such as
1571 * {@link #PARSE_COLLECT_CERTIFICATES}
1572 */
1573 public static ApkLite parseApkLite(FileDescriptor fd, String debugPathName, int flags)
1574 throws PackageParserException {
1575 return parseApkLiteInner(null, fd, debugPathName, flags);
1576 }
1577
1578 private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName,
1579 int flags) throws PackageParserException {
1580 final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001581
Jeff Sharkey275e0852014-06-17 18:18:49 -07001582 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001583 try {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001584 final ApkAssets apkAssets;
1585 try {
1586 apkAssets = fd != null
1587 ? ApkAssets.loadFromFd(fd, debugPathName, false, false)
1588 : ApkAssets.loadFromPath(apkPath);
1589 } catch (IOException e) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001590 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1591 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001592 }
1593
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001594 parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001595
Patrick Baumann47117fc2017-12-19 10:17:21 -08001596 final SigningDetails signingDetails;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001597 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1598 // TODO: factor signature related items out of Package object
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001599 final Package tempPkg = new Package((String) null);
Victor Hsieh5f761242018-01-20 10:30:12 -08001600 final boolean skipVerify = (flags & PARSE_IS_SYSTEM_DIR) != 0;
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001601 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1602 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001603 collectCertificates(tempPkg, apkFile, skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001604 } finally {
1605 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1606 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001607 signingDetails = tempPkg.mSigningDetails;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001608 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001609 signingDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001610 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001611
Jeff Sharkey275e0852014-06-17 18:18:49 -07001612 final AttributeSet attrs = parser;
Patrick Baumann47117fc2017-12-19 10:17:21 -08001613 return parseApkLite(apkPath, parser, attrs, signingDetails);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001614
1615 } catch (XmlPullParserException | IOException | RuntimeException e) {
Dianne Hackborn34041732017-01-31 15:27:13 -08001616 Slog.w(TAG, "Failed to parse " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001617 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1618 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001620 IoUtils.closeQuietly(parser);
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001621 // TODO(b/72056911): Implement and call close() on ApkAssets.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 }
1624
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001625 private static String validateName(String name, boolean requireSeparator,
1626 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001627 final int N = name.length();
1628 boolean hasSep = false;
1629 boolean front = true;
1630 for (int i=0; i<N; i++) {
1631 final char c = name.charAt(i);
1632 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1633 front = false;
1634 continue;
1635 }
1636 if (!front) {
1637 if ((c >= '0' && c <= '9') || c == '_') {
1638 continue;
1639 }
1640 }
1641 if (c == '.') {
1642 hasSep = true;
1643 front = true;
1644 continue;
1645 }
1646 return "bad character '" + c + "'";
1647 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001648 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1649 return "Invalid filename";
1650 }
1651 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 ? null : "must have at least one '.' separator";
1653 }
1654
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001655 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
Svet Ganov354cd3c2015-12-17 11:35:04 -08001656 AttributeSet attrs) throws IOException, XmlPullParserException,
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001657 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658
1659 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001660 while ((type = parser.next()) != XmlPullParser.START_TAG
1661 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 }
1663
Kenny Rootd2d29252011-08-08 11:27:57 -07001664 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001665 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1666 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001667 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001668 if (!parser.getName().equals(TAG_MANIFEST)) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001669 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1670 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 }
1672
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001673 final String packageName = attrs.getAttributeValue(null, "package");
1674 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001675 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001676 if (error != null) {
1677 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1678 "Invalid manifest package: " + error);
1679 }
1680 }
1681
Jeff Sharkey275e0852014-06-17 18:18:49 -07001682 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001683 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001684 if (splitName.length() == 0) {
1685 splitName = null;
1686 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001687 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001688 if (error != null) {
1689 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1690 "Invalid manifest split: " + error);
1691 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001692 }
1693 }
1694
1695 return Pair.create(packageName.intern(),
1696 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 }
1698
Adam Lesinski4e862812016-11-21 16:02:24 -08001699 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001700 SigningDetails signingDetails)
Adam Lesinski4e862812016-11-21 16:02:24 -08001701 throws IOException, XmlPullParserException, PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001702 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001703
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001704 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001705 int versionCode = 0;
Dianne Hackborn3accca02013-09-20 09:32:11 -07001706 int versionCodeMajor = 0;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001707 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001708 boolean coreApp = false;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001709 boolean debuggable = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001710 boolean multiArch = false;
Selim Gurun2d291d82016-02-05 17:50:53 -08001711 boolean use32bitAbi = false;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001712 boolean extractNativeLibs = true;
Adam Lesinski4e862812016-11-21 16:02:24 -08001713 boolean isolatedSplits = false;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001714 boolean isFeatureSplit = false;
1715 String configForSplit = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001716 String usesSplitName = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001717
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001718 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001719 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001720 if (attr.equals("installLocation")) {
1721 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001722 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001723 } else if (attr.equals("versionCode")) {
1724 versionCode = attrs.getAttributeIntValue(i, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001725 } else if (attr.equals("versionCodeMajor")) {
1726 versionCodeMajor = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001727 } else if (attr.equals("revisionCode")) {
1728 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001729 } else if (attr.equals("coreApp")) {
1730 coreApp = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski4e862812016-11-21 16:02:24 -08001731 } else if (attr.equals("isolatedSplits")) {
1732 isolatedSplits = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001733 } else if (attr.equals("configForSplit")) {
1734 configForSplit = attrs.getAttributeValue(i);
1735 } else if (attr.equals("isFeatureSplit")) {
1736 isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001737 }
1738 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001739
1740 // Only search the tree when the tag is directly below <manifest>
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001741 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001742 final int searchDepth = parser.getDepth() + 1;
1743
1744 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1745 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1746 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1747 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1748 continue;
1749 }
1750
Adam Lesinski4e862812016-11-21 16:02:24 -08001751 if (parser.getDepth() != searchDepth) {
1752 continue;
1753 }
1754
1755 if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
1756 final VerifierInfo verifier = parseVerifier(attrs);
Kenny Root05ca4c92011-09-15 10:36:25 -07001757 if (verifier != null) {
1758 verifiers.add(verifier);
1759 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001760 } else if (TAG_APPLICATION.equals(parser.getName())) {
Narayan Kamatha8755a82014-07-15 12:26:35 +01001761 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1762 final String attr = attrs.getAttributeName(i);
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001763 if ("debuggable".equals(attr)) {
1764 debuggable = attrs.getAttributeBooleanValue(i, false);
1765 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001766 if ("multiArch".equals(attr)) {
1767 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001768 }
Selim Gurun2d291d82016-02-05 17:50:53 -08001769 if ("use32bitAbi".equals(attr)) {
1770 use32bitAbi = attrs.getAttributeBooleanValue(i, false);
Tao Baic9a02372016-01-12 15:02:24 -08001771 }
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001772 if ("extractNativeLibs".equals(attr)) {
1773 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001774 }
1775 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001776 } else if (TAG_USES_SPLIT.equals(parser.getName())) {
1777 if (usesSplitName != null) {
1778 Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
1779 continue;
1780 }
1781
1782 usesSplitName = attrs.getAttributeValue(ANDROID_RESOURCES, "name");
1783 if (usesSplitName == null) {
1784 throw new PackageParserException(
1785 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1786 "<uses-split> tag requires 'android:name' attribute");
1787 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001788 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001789 }
1790
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001791 return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
Dianne Hackborn3accca02013-09-20 09:32:11 -07001792 configForSplit, usesSplitName, versionCode, versionCodeMajor, revisionCode,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001793 installLocation, verifiers, signingDetails, coreApp, debuggable,
Dianne Hackborn3accca02013-09-20 09:32:11 -07001794 multiArch, use32bitAbi, extractNativeLibs, isolatedSplits);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001795 }
1796
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001797 /**
Svet Ganov354cd3c2015-12-17 11:35:04 -08001798 * Parses a child package and adds it to the parent if successful. If you add
1799 * new tags that need to be supported by child packages make sure to add them
1800 * to {@link #CHILD_PACKAGE_TAGS}.
1801 *
1802 * @param parentPkg The parent that contains the child
1803 * @param res Resources against which to resolve values
1804 * @param parser Parser of the manifest
1805 * @param flags Flags about how to parse
1806 * @param outError Human readable error if parsing fails
1807 * @return True of parsing succeeded.
1808 *
1809 * @throws XmlPullParserException
1810 * @throws IOException
1811 */
1812 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
1813 int flags, String[] outError) throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001814 // Make sure we have a valid child package name
1815 String childPackageName = parser.getAttributeValue(null, "package");
1816 if (validateName(childPackageName, true, false) != null) {
1817 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1818 return false;
1819 }
1820
1821 // Child packages must be unique
1822 if (childPackageName.equals(parentPkg.packageName)) {
1823 String message = "Child package name cannot be equal to parent package name: "
1824 + parentPkg.packageName;
1825 Slog.w(TAG, message);
1826 outError[0] = message;
1827 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1828 return false;
1829 }
1830
1831 // Child packages must be unique
1832 if (parentPkg.hasChildPackage(childPackageName)) {
1833 String message = "Duplicate child package:" + childPackageName;
1834 Slog.w(TAG, message);
1835 outError[0] = message;
1836 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1837 return false;
1838 }
1839
1840 // Go ahead and parse the child
1841 Package childPkg = new Package(childPackageName);
1842
1843 // Child package inherits parent version code/name/target SDK
1844 childPkg.mVersionCode = parentPkg.mVersionCode;
1845 childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
1846 childPkg.mVersionName = parentPkg.mVersionName;
1847 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
Todd Kennedy89d60182016-03-11 11:18:32 -08001848 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001849
1850 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
1851 if (childPkg == null) {
1852 // If we got null then error was set during child parsing
1853 return false;
1854 }
1855
1856 // Set the parent-child relation
1857 if (parentPkg.childPackages == null) {
1858 parentPkg.childPackages = new ArrayList<>();
1859 }
1860 parentPkg.childPackages.add(childPkg);
1861 childPkg.parentPackage = parentPkg;
1862
1863 return true;
1864 }
1865
1866 /**
1867 * Parse the manifest of a <em>base APK</em>. When adding new features you
1868 * need to consider whether they should be supported by split APKs and child
1869 * packages.
1870 *
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001871 * @param apkPath The package apk file path
Svet Ganov354cd3c2015-12-17 11:35:04 -08001872 * @param res The resources from which to resolve values
1873 * @param parser The manifest parser
1874 * @param flags Flags how to parse
1875 * @param outError Human readable error message
1876 * @return Parsed package or null on error.
1877 *
1878 * @throws XmlPullParserException
1879 * @throws IOException
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001880 */
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001881 private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001882 String[] outError) throws XmlPullParserException, IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001883 final String splitName;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001884 final String pkgName;
1885
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001886 try {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001887 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001888 pkgName = packageSplit.first;
1889 splitName = packageSplit.second;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001890
1891 if (!TextUtils.isEmpty(splitName)) {
1892 outError[0] = "Expected base APK, but found split " + splitName;
1893 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1894 return null;
1895 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001896 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001897 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1898 return null;
1899 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001900
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001901 if (mCallback != null) {
1902 String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
1903 if (overlayPaths != null && overlayPaths.length > 0) {
1904 for (String overlayPath : overlayPaths) {
1905 res.getAssets().addOverlayPath(overlayPath);
1906 }
1907 }
1908 }
1909
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001910 final Package pkg = new Package(pkgName);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001911
Svet Ganov354cd3c2015-12-17 11:35:04 -08001912 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913 com.android.internal.R.styleable.AndroidManifest);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001914
Dianne Hackborn3accca02013-09-20 09:32:11 -07001915 pkg.mVersionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001916 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001917 pkg.mVersionCodeMajor = sa.getInteger(
1918 com.android.internal.R.styleable.AndroidManifest_versionCodeMajor, 0);
Patrick Baumannc2def582018-04-04 12:14:15 -07001919 pkg.applicationInfo.setVersionCode(pkg.getLongVersionCode());
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001920 pkg.baseRevisionCode = sa.getInteger(
1921 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001922 pkg.mVersionName = sa.getNonConfigurationString(
1923 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 if (pkg.mVersionName != null) {
1925 pkg.mVersionName = pkg.mVersionName.intern();
1926 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001927
1928 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
1929
Alan Viveretteb6a25732017-11-21 14:49:24 -05001930 pkg.mCompileSdkVersion = sa.getInteger(
1931 com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0);
1932 pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion;
1933 pkg.mCompileSdkVersionCodename = sa.getNonConfigurationString(
1934 com.android.internal.R.styleable.AndroidManifest_compileSdkVersionCodename, 0);
1935 if (pkg.mCompileSdkVersionCodename != null) {
1936 pkg.mCompileSdkVersionCodename = pkg.mCompileSdkVersionCodename.intern();
1937 }
1938 pkg.applicationInfo.compileSdkVersionCodename = pkg.mCompileSdkVersionCodename;
1939
Svet Ganov354cd3c2015-12-17 11:35:04 -08001940 sa.recycle();
1941
1942 return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
1943 }
1944
1945 /**
1946 * This is the common parsing routing for handling parent and child
1947 * packages in a base APK. The difference between parent and child
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001948 * parsing is that some tags are not supported by child packages as
Svet Ganov354cd3c2015-12-17 11:35:04 -08001949 * well as some manifest attributes are ignored. The implementation
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001950 * assumes the calling code has already handled the manifest tag if needed
Svet Ganov354cd3c2015-12-17 11:35:04 -08001951 * (this applies to the parent only).
1952 *
1953 * @param pkg The package which to populate
1954 * @param acceptedTags Which tags to handle, null to handle all
1955 * @param res Resources against which to resolve values
1956 * @param parser Parser of the manifest
1957 * @param flags Flags about how to parse
1958 * @param outError Human readable error if parsing fails
1959 * @return The package if parsing succeeded or null.
1960 *
1961 * @throws XmlPullParserException
1962 * @throws IOException
1963 */
1964 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
1965 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
1966 IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001967 mParseInstrumentationArgs = null;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001968
1969 int type;
1970 boolean foundApp = false;
1971
1972 TypedArray sa = res.obtainAttributes(parser,
1973 com.android.internal.R.styleable.AndroidManifest);
1974
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001975 String str = sa.getNonConfigurationString(
1976 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
1977 if (str != null && str.length() > 0) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001978 String nameError = validateName(str, true, false);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001979 if (nameError != null && !"android".equals(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001980 outError[0] = "<manifest> specifies bad sharedUserId name \""
1981 + str + "\": " + nameError;
1982 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
1983 return null;
1984 }
1985 pkg.mSharedUserId = str.intern();
1986 pkg.mSharedUserLabel = sa.getResourceId(
1987 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
1988 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08001989
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08001990 pkg.installLocation = sa.getInteger(
1991 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001992 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07001993 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07001994
Todd Kennedy11e45072017-01-25 13:24:21 -08001995 final int targetSandboxVersion = sa.getInteger(
1996 com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion,
1997 PARSE_DEFAULT_TARGET_SANDBOX);
1998 pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion;
Alan Viverettefd274a02014-03-27 15:39:15 -07001999
Kenny Root7cb9be22012-05-30 15:30:37 -07002000 /* Set the global "forward lock" flag */
2001 if ((flags & PARSE_FORWARD_LOCK) != 0) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002002 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
Kenny Root7cb9be22012-05-30 15:30:37 -07002003 }
2004
2005 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07002006 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07002007 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
2008 }
2009
Adam Lesinski4e862812016-11-21 16:02:24 -08002010 if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
2011 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
2012 }
2013
Dianne Hackborn723738c2009-06-25 19:48:04 -07002014 // Resource boolean are -1, so 1 means we don't know the value.
2015 int supportsSmallScreens = 1;
2016 int supportsNormalScreens = 1;
2017 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002018 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002019 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002020 int anyDensity = 1;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002022 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07002023 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2024 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2025 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002026 continue;
2027 }
2028
2029 String tagName = parser.getName();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002030
2031 if (acceptedTags != null && !acceptedTags.contains(tagName)) {
2032 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
2033 + tagName + " at " + mArchiveSourcePath + " "
2034 + parser.getPositionDescription());
2035 XmlUtils.skipCurrentTag(parser);
2036 continue;
2037 }
2038
2039 if (tagName.equals(TAG_APPLICATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002040 if (foundApp) {
2041 if (RIGID_PARSER) {
2042 outError[0] = "<manifest> has more than one <application>";
2043 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2044 return null;
2045 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002046 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002047 XmlUtils.skipCurrentTag(parser);
2048 continue;
2049 }
2050 }
2051
2052 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002053 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054 return null;
2055 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002056 } else if (tagName.equals(TAG_OVERLAY)) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002057 sa = res.obtainAttributes(parser,
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002058 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
2059 pkg.mOverlayTarget = sa.getString(
2060 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
Adrian Roosc84df772018-01-19 21:20:22 +01002061 pkg.mOverlayCategory = sa.getString(
2062 com.android.internal.R.styleable.AndroidManifestResourceOverlay_category);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002063 pkg.mOverlayPriority = sa.getInt(
2064 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
2065 0);
Adam Lesinskie7334972018-01-17 16:13:52 -08002066 pkg.mOverlayIsStatic = sa.getBoolean(
Jaekyun Seok04342892017-03-02 15:24:19 +09002067 com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
2068 false);
Todd Leeea2f3be2017-03-16 14:00:52 -07002069 final String propName = sa.getString(
2070 com.android.internal.R.styleable
2071 .AndroidManifestResourceOverlay_requiredSystemPropertyName);
2072 final String propValue = sa.getString(
2073 com.android.internal.R.styleable
2074 .AndroidManifestResourceOverlay_requiredSystemPropertyValue);
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002075 sa.recycle();
2076
2077 if (pkg.mOverlayTarget == null) {
2078 outError[0] = "<overlay> does not specify a target package";
2079 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2080 return null;
2081 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002082
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002083 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
2084 outError[0] = "<overlay> priority must be between 0 and 9999";
2085 mParseError =
2086 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2087 return null;
2088 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002089
2090 // check to see if overlay should be excluded based on system property condition
2091 if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
2092 Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
2093 + pkg.baseCodePath+ ": overlay ignored due to required system property: "
2094 + propName + " with value: " + propValue);
2095 return null;
Jaekyun Seok04342892017-03-02 15:24:19 +09002096 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002097
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002098 XmlUtils.skipCurrentTag(parser);
2099
Svet Ganov354cd3c2015-12-17 11:35:04 -08002100 } else if (tagName.equals(TAG_KEY_SETS)) {
2101 if (!parseKeySets(pkg, res, parser, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08002102 return null;
2103 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002104 } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002105 if (!parsePermissionGroup(pkg, flags, 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_PERMISSION)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002109 if (!parsePermission(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110 return null;
2111 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002112 } else if (tagName.equals(TAG_PERMISSION_TREE)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002113 if (!parsePermissionTree(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002114 return null;
2115 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002116 } else if (tagName.equals(TAG_USES_PERMISSION)) {
2117 if (!parseUsesPermission(pkg, res, parser)) {
Svetoslav96a77162015-04-03 13:58:33 -07002118 return null;
2119 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002120 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
2121 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
2122 if (!parseUsesPermission(pkg, res, parser)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002123 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002124 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002125 } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 ConfigurationInfo cPref = new ConfigurationInfo();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002127 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002128 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
2129 cPref.reqTouchScreen = sa.getInt(
2130 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
2131 Configuration.TOUCHSCREEN_UNDEFINED);
2132 cPref.reqKeyboardType = sa.getInt(
2133 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
2134 Configuration.KEYBOARD_UNDEFINED);
2135 if (sa.getBoolean(
2136 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
2137 false)) {
2138 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
2139 }
2140 cPref.reqNavigation = sa.getInt(
2141 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
2142 Configuration.NAVIGATION_UNDEFINED);
2143 if (sa.getBoolean(
2144 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
2145 false)) {
2146 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
2147 }
2148 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002149 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002150
2151 XmlUtils.skipCurrentTag(parser);
2152
Svet Ganov354cd3c2015-12-17 11:35:04 -08002153 } else if (tagName.equals(TAG_USES_FEATURE)) {
2154 FeatureInfo fi = parseUsesFeature(res, parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002155 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
2156
Dianne Hackborn49237342009-08-27 20:08:01 -07002157 if (fi.name == null) {
2158 ConfigurationInfo cPref = new ConfigurationInfo();
2159 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002160 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07002161 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07002162
2163 XmlUtils.skipCurrentTag(parser);
2164
Svet Ganov354cd3c2015-12-17 11:35:04 -08002165 } else if (tagName.equals(TAG_FEATURE_GROUP)) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002166 FeatureGroupInfo group = new FeatureGroupInfo();
2167 ArrayList<FeatureInfo> features = null;
2168 final int innerDepth = parser.getDepth();
2169 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2170 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2171 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2172 continue;
2173 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07002174
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002175 final String innerTagName = parser.getName();
2176 if (innerTagName.equals("uses-feature")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002177 FeatureInfo featureInfo = parseUsesFeature(res, parser);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002178 // FeatureGroups are stricter and mandate that
2179 // any <uses-feature> declared are mandatory.
2180 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
2181 features = ArrayUtils.add(features, featureInfo);
2182 } else {
2183 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
2184 " at " + mArchiveSourcePath + " " +
2185 parser.getPositionDescription());
2186 }
2187 XmlUtils.skipCurrentTag(parser);
2188 }
2189
2190 if (features != null) {
2191 group.features = new FeatureInfo[features.size()];
2192 group.features = features.toArray(group.features);
2193 }
2194 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07002195
Svet Ganov354cd3c2015-12-17 11:35:04 -08002196 } else if (tagName.equals(TAG_USES_SDK)) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07002197 if (SDK_VERSION > 0) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002198 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002199 com.android.internal.R.styleable.AndroidManifestUsesSdk);
2200
Todd Kennedy4f657082016-06-28 10:31:05 -07002201 int minVers = 1;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002202 String minCode = null;
2203 int targetVers = 0;
2204 String targetCode = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002205
Dianne Hackborn851a5412009-05-08 12:06:44 -07002206 TypedValue val = sa.peekValue(
2207 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
2208 if (val != null) {
2209 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
Colin Crossf61f9e32018-06-18 11:47:45 -07002210 minCode = val.string.toString();
Dianne Hackborn851a5412009-05-08 12:06:44 -07002211 } else {
2212 // If it's not a string, it's an integer.
Colin Crossf61f9e32018-06-18 11:47:45 -07002213 minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002214 }
2215 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002216
Dianne Hackborn851a5412009-05-08 12:06:44 -07002217 val = sa.peekValue(
2218 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
2219 if (val != null) {
2220 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
Todd Kennedy89d60182016-03-11 11:18:32 -08002221 targetCode = val.string.toString();
2222 if (minCode == null) {
2223 minCode = targetCode;
2224 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002225 } else {
2226 // If it's not a string, it's an integer.
2227 targetVers = val.data;
2228 }
Colin Crossf61f9e32018-06-18 11:47:45 -07002229 } else {
2230 targetVers = minVers;
2231 targetCode = minCode;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002232 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002234 sa.recycle();
2235
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002236 final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode,
2237 SDK_VERSION, SDK_CODENAMES, outError);
2238 if (minSdkVersion < 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002239 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2240 return null;
2241 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002242
Patrick Baumannccb20b82018-01-08 13:22:46 -08002243 boolean defaultToCurrentDevBranch = (flags & PARSE_FORCE_SDK) != 0;
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002244 final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002245 targetCode, SDK_CODENAMES, outError, defaultToCurrentDevBranch);
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002246 if (targetSdkVersion < 0) {
2247 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2248 return null;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002249 }
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002250
2251 pkg.applicationInfo.minSdkVersion = minSdkVersion;
2252 pkg.applicationInfo.targetSdkVersion = targetSdkVersion;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002253 }
2254
2255 XmlUtils.skipCurrentTag(parser);
2256
Svet Ganov354cd3c2015-12-17 11:35:04 -08002257 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
2258 sa = res.obtainAttributes(parser,
Dianne Hackborn723738c2009-06-25 19:48:04 -07002259 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
2260
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002261 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
2262 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
2263 0);
2264 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
2265 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
2266 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07002267 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
2268 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
2269 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002270
Dianne Hackborn723738c2009-06-25 19:48:04 -07002271 // This is a trick to get a boolean and still able to detect
2272 // if a value was actually set.
2273 supportsSmallScreens = sa.getInteger(
2274 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
2275 supportsSmallScreens);
2276 supportsNormalScreens = sa.getInteger(
2277 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
2278 supportsNormalScreens);
2279 supportsLargeScreens = sa.getInteger(
2280 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
2281 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002282 supportsXLargeScreens = sa.getInteger(
2283 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
2284 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002285 resizeable = sa.getInteger(
2286 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002287 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002288 anyDensity = sa.getInteger(
2289 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
2290 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07002291
2292 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002293
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002294 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002295
Svet Ganov354cd3c2015-12-17 11:35:04 -08002296 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
2297 sa = res.obtainAttributes(parser,
Dianne Hackborn854060af2009-07-09 18:14:31 -07002298 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
2299
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002300 // Note: don't allow this value to be a reference to a resource
2301 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07002302 String name = sa.getNonResourceString(
2303 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
2304
2305 sa.recycle();
2306
Todd Kennedy232d29e2017-11-06 14:45:53 -08002307 if (name != null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002308 if (pkg.protectedBroadcasts == null) {
2309 pkg.protectedBroadcasts = new ArrayList<String>();
2310 }
2311 if (!pkg.protectedBroadcasts.contains(name)) {
2312 pkg.protectedBroadcasts.add(name.intern());
2313 }
2314 }
2315
2316 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002317
Svet Ganov354cd3c2015-12-17 11:35:04 -08002318 } else if (tagName.equals(TAG_INSTRUMENTATION)) {
2319 if (parseInstrumentation(pkg, res, parser, outError) == null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002320 return null;
2321 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002322 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
2323 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002324 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2325
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002326 String orig =sa.getNonConfigurationString(
2327 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002328 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002329 if (pkg.mOriginalPackages == null) {
2330 pkg.mOriginalPackages = new ArrayList<String>();
2331 pkg.mRealPackage = pkg.packageName;
2332 }
2333 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002334 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002335
2336 sa.recycle();
2337
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002338 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002339
Svet Ganov354cd3c2015-12-17 11:35:04 -08002340 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
2341 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002342 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2343
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002344 String name = sa.getNonConfigurationString(
2345 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002346
2347 sa.recycle();
2348
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002349 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002350 if (pkg.mAdoptPermissions == null) {
2351 pkg.mAdoptPermissions = new ArrayList<String>();
2352 }
2353 pkg.mAdoptPermissions.add(name);
2354 }
2355
2356 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002357
Svet Ganov354cd3c2015-12-17 11:35:04 -08002358 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002359 // Just skip this tag
2360 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_COMPATIBLE_SCREENS)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002364 // Just skip this tag
2365 XmlUtils.skipCurrentTag(parser);
2366 continue;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002367 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
Michael Wrighteaeb1902013-09-05 18:15:57 -07002368 XmlUtils.skipCurrentTag(parser);
2369 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002370
Svet Ganov354cd3c2015-12-17 11:35:04 -08002371 } else if (tagName.equals(TAG_EAT_COMMENT)) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002372 // Just skip this tag
2373 XmlUtils.skipCurrentTag(parser);
2374 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002375
Svet Ganov354cd3c2015-12-17 11:35:04 -08002376 } else if (tagName.equals(TAG_PACKAGE)) {
Svet Ganova7532cf2016-05-02 08:13:17 -07002377 if (!MULTI_PACKAGE_APK_ENABLED) {
2378 XmlUtils.skipCurrentTag(parser);
2379 continue;
2380 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002381 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
2382 // If parsing a child failed the error is already set
2383 return null;
2384 }
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002385
2386 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
2387 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
2388 sa = res.obtainAttributes(parser,
2389 com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
2390 final String hash = sa.getNonConfigurationString(
2391 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
2392 sa.recycle();
2393
2394 pkg.restrictUpdateHash = null;
2395 if (hash != null) {
2396 final int hashLength = hash.length();
2397 final byte[] hashBytes = new byte[hashLength / 2];
2398 for (int i = 0; i < hashLength; i += 2){
2399 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
2400 + Character.digit(hash.charAt(i + 1), 16));
2401 }
2402 pkg.restrictUpdateHash = hashBytes;
2403 }
2404 }
2405
2406 XmlUtils.skipCurrentTag(parser);
2407
Dianne Hackborn854060af2009-07-09 18:14:31 -07002408 } else if (RIGID_PARSER) {
2409 outError[0] = "Bad element under <manifest>: "
2410 + parser.getName();
2411 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2412 return null;
2413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002414 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002415 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002416 + " at " + mArchiveSourcePath + " "
2417 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002418 XmlUtils.skipCurrentTag(parser);
2419 continue;
2420 }
2421 }
2422
2423 if (!foundApp && pkg.instrumentation.size() == 0) {
2424 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
2425 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
2426 }
2427
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002428 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002429 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002430 for (int ip=0; ip<NP; ip++) {
2431 final PackageParser.NewPermissionInfo npi
2432 = PackageParser.NEW_PERMISSIONS[ip];
2433 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
2434 break;
2435 }
2436 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002437 if (implicitPerms == null) {
2438 implicitPerms = new StringBuilder(128);
2439 implicitPerms.append(pkg.packageName);
2440 implicitPerms.append(": compat added ");
2441 } else {
2442 implicitPerms.append(' ');
2443 }
2444 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002445 pkg.requestedPermissions.add(npi.name);
2446 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002447 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002448 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002449 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002450 }
Dianne Hackborn79245122012-03-12 10:51:26 -07002451
2452 final int NS = PackageParser.SPLIT_PERMISSIONS.length;
2453 for (int is=0; is<NS; is++) {
2454 final PackageParser.SplitPermissionInfo spi
2455 = PackageParser.SPLIT_PERMISSIONS[is];
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -07002456 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
2457 || !pkg.requestedPermissions.contains(spi.rootPerm)) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07002458 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07002459 }
2460 for (int in=0; in<spi.newPerms.length; in++) {
2461 final String perm = spi.newPerms[in];
2462 if (!pkg.requestedPermissions.contains(perm)) {
2463 pkg.requestedPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07002464 }
2465 }
2466 }
2467
Dianne Hackborn723738c2009-06-25 19:48:04 -07002468 if (supportsSmallScreens < 0 || (supportsSmallScreens > 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_SMALL_SCREENS;
2472 }
2473 if (supportsNormalScreens != 0) {
2474 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
2475 }
2476 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
2477 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002478 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002479 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
2480 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002481 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
2482 && pkg.applicationInfo.targetSdkVersion
2483 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
2484 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
2485 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002486 if (resizeable < 0 || (resizeable > 0
2487 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002488 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002489 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
2490 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002491 if (anyDensity < 0 || (anyDensity > 0
2492 && pkg.applicationInfo.targetSdkVersion
2493 >= android.os.Build.VERSION_CODES.DONUT)) {
2494 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07002495 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07002496
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002497 // At this point we can check if an application is not supporting densities and hence
2498 // cannot be windowed / resized. Note that an SDK version of 0 is common for
2499 // pre-Doughnut applications.
2500 if (pkg.applicationInfo.usesCompatibilityMode()) {
Winson Chungd3395382016-12-13 11:49:09 -08002501 adjustPackageToBeUnresizeableAndUnpipable(pkg);
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002502 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002503 return pkg;
2504 }
2505
Todd Leeea2f3be2017-03-16 14:00:52 -07002506 private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
2507
2508 if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
2509 if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
2510 // malformed condition - incomplete
2511 Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
2512 + "=" + propValue + "' - require both requiredSystemPropertyName"
2513 + " AND requiredSystemPropertyValue to be specified.");
2514 return false;
2515 }
2516 // no valid condition set - so no exclusion criteria, overlay will be included.
2517 return true;
2518 }
2519
2520 // check property value - make sure it is both set and equal to expected value
2521 final String currValue = SystemProperties.get(propName);
2522 return (currValue != null && currValue.equals(propValue));
2523 }
2524
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002525 /**
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002526 * This is a pre-density application which will get scaled - instead of being pixel perfect.
2527 * This type of application is not resizable.
2528 *
2529 * @param pkg The package which needs to be marked as unresizable.
2530 */
Winson Chungd3395382016-12-13 11:49:09 -08002531 private void adjustPackageToBeUnresizeableAndUnpipable(Package pkg) {
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002532 for (Activity a : pkg.activities) {
2533 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -08002534 a.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE;
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002535 }
2536 }
2537
2538 /**
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002539 * Computes the targetSdkVersion to use at runtime. If the package is not
2540 * compatible with this platform, populates {@code outError[0]} with an
2541 * error message.
2542 * <p>
2543 * If {@code targetCode} is not specified, e.g. the value is {@code null},
2544 * then the {@code targetVers} will be returned unmodified.
2545 * <p>
2546 * Otherwise, the behavior varies based on whether the current platform
2547 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2548 * has length > 0:
2549 * <ul>
2550 * <li>If this is a pre-release platform and the value specified by
2551 * {@code targetCode} is contained within the array of allowed pre-release
2552 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2553 * <li>If this is a released platform, this method will return -1 to
2554 * indicate that the package is not compatible with this platform.
2555 * </ul>
2556 *
2557 * @param targetVers targetSdkVersion number, if specified in the
2558 * application manifest, or 0 otherwise
2559 * @param targetCode targetSdkVersion code, if specified in the application
2560 * manifest, or {@code null} otherwise
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002561 * @param platformSdkCodenames array of allowed pre-release SDK codenames
2562 * for this platform
2563 * @param outError output array to populate with error, if applicable
Patrick Baumannccb20b82018-01-08 13:22:46 -08002564 * @param forceCurrentDev if development target code is not available, use the current
2565 * development version by default.
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002566 * @return the targetSdkVersion to use at runtime, or -1 if the package is
2567 * not compatible with this platform
2568 * @hide Exposed for unit testing only.
2569 */
2570 @TestApi
2571 public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002572 @Nullable String targetCode, @NonNull String[] platformSdkCodenames,
2573 @NonNull String[] outError, boolean forceCurrentDev) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002574 // If it's a release SDK, return the version number unmodified.
2575 if (targetCode == null) {
2576 return targetVers;
2577 }
2578
2579 // If it's a pre-release SDK and the codename matches this platform, it
2580 // definitely targets this SDK.
Patrick Baumannccb20b82018-01-08 13:22:46 -08002581 if (ArrayUtils.contains(platformSdkCodenames, targetCode) || forceCurrentDev) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002582 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2583 }
2584
2585 // Otherwise, we're looking at an incompatible pre-release SDK.
2586 if (platformSdkCodenames.length > 0) {
2587 outError[0] = "Requires development platform " + targetCode
2588 + " (current platform is any of "
2589 + Arrays.toString(platformSdkCodenames) + ")";
2590 } else {
2591 outError[0] = "Requires development platform " + targetCode
2592 + " but this is a release platform.";
2593 }
2594 return -1;
2595 }
2596
2597 /**
2598 * Computes the minSdkVersion to use at runtime. If the package is not
2599 * compatible with this platform, populates {@code outError[0]} with an
2600 * error message.
2601 * <p>
2602 * If {@code minCode} is not specified, e.g. the value is {@code null},
2603 * then behavior varies based on the {@code platformSdkVersion}:
2604 * <ul>
2605 * <li>If the platform SDK version is greater than or equal to the
2606 * {@code minVers}, returns the {@code mniVers} unmodified.
2607 * <li>Otherwise, returns -1 to indicate that the package is not
2608 * compatible with this platform.
2609 * </ul>
2610 * <p>
2611 * Otherwise, the behavior varies based on whether the current platform
2612 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2613 * has length > 0:
2614 * <ul>
2615 * <li>If this is a pre-release platform and the value specified by
2616 * {@code targetCode} is contained within the array of allowed pre-release
2617 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2618 * <li>If this is a released platform, this method will return -1 to
2619 * indicate that the package is not compatible with this platform.
2620 * </ul>
2621 *
2622 * @param minVers minSdkVersion number, if specified in the application
2623 * manifest, or 1 otherwise
2624 * @param minCode minSdkVersion code, if specified in the application
2625 * manifest, or {@code null} otherwise
2626 * @param platformSdkVersion platform SDK version number, typically
2627 * Build.VERSION.SDK_INT
2628 * @param platformSdkCodenames array of allowed prerelease SDK codenames
2629 * for this platform
2630 * @param outError output array to populate with error, if applicable
2631 * @return the minSdkVersion to use at runtime, or -1 if the package is not
2632 * compatible with this platform
2633 * @hide Exposed for unit testing only.
2634 */
2635 @TestApi
2636 public static int computeMinSdkVersion(@IntRange(from = 1) int minVers,
2637 @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion,
2638 @NonNull String[] platformSdkCodenames, @NonNull String[] outError) {
2639 // If it's a release SDK, make sure we meet the minimum SDK requirement.
2640 if (minCode == null) {
2641 if (minVers <= platformSdkVersion) {
2642 return minVers;
2643 }
2644
2645 // We don't meet the minimum SDK requirement.
2646 outError[0] = "Requires newer sdk version #" + minVers
2647 + " (current version is #" + platformSdkVersion + ")";
2648 return -1;
2649 }
2650
2651 // If it's a pre-release SDK and the codename matches this platform, we
2652 // definitely meet the minimum SDK requirement.
2653 if (ArrayUtils.contains(platformSdkCodenames, minCode)) {
2654 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2655 }
2656
2657 // Otherwise, we're looking at an incompatible pre-release SDK.
2658 if (platformSdkCodenames.length > 0) {
2659 outError[0] = "Requires development platform " + minCode
2660 + " (current platform is any of "
2661 + Arrays.toString(platformSdkCodenames) + ")";
2662 } else {
2663 outError[0] = "Requires development platform " + minCode
2664 + " but this is a release platform.";
2665 }
2666 return -1;
2667 }
2668
Todd Kennedy27c24fb2015-09-17 16:49:25 -07002669 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002670 FeatureInfo fi = new FeatureInfo();
2671 TypedArray sa = res.obtainAttributes(attrs,
2672 com.android.internal.R.styleable.AndroidManifestUsesFeature);
2673 // Note: don't allow this value to be a reference to a resource
2674 // that may change.
2675 fi.name = sa.getNonResourceString(
2676 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
Jeff Sharkey115d2c12016-02-15 17:25:57 -07002677 fi.version = sa.getInt(
2678 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002679 if (fi.name == null) {
2680 fi.reqGlEsVersion = sa.getInt(
2681 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
2682 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2683 }
2684 if (sa.getBoolean(
2685 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
2686 fi.flags |= FeatureInfo.FLAG_REQUIRED;
2687 }
2688 sa.recycle();
2689 return fi;
2690 }
2691
Svet Ganov67882122016-12-11 16:36:34 -08002692 private boolean parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser,
2693 String[] outError) throws XmlPullParserException, IOException {
2694 TypedArray sa = res.obtainAttributes(parser,
2695 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary);
2696
2697 // Note: don't allow this value to be a reference to a resource that may change.
2698 String lname = sa.getNonResourceString(
2699 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
2700 final int version = sa.getInt(
2701 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002702 String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable
Svet Ganov67882122016-12-11 16:36:34 -08002703 .AndroidManifestUsesStaticLibrary_certDigest);
2704 sa.recycle();
2705
2706 // Since an APK providing a static shared lib can only provide the lib - fail if malformed
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002707 if (lname == null || version < 0 || certSha256Digest == null) {
Svet Ganov67882122016-12-11 16:36:34 -08002708 outError[0] = "Bad uses-static-library declaration name: " + lname + " version: "
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002709 + version + " certDigest" + certSha256Digest;
Svet Ganov67882122016-12-11 16:36:34 -08002710 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2711 XmlUtils.skipCurrentTag(parser);
2712 return false;
2713 }
2714
2715 // Can depend only on one version of the same library
2716 if (pkg.usesStaticLibraries != null && pkg.usesStaticLibraries.contains(lname)) {
2717 outError[0] = "Depending on multiple versions of static library " + lname;
2718 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2719 XmlUtils.skipCurrentTag(parser);
2720 return false;
2721 }
2722
2723 lname = lname.intern();
2724 // We allow ":" delimiters in the SHA declaration as this is the format
2725 // emitted by the certtool making it easy for developers to copy/paste.
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002726 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2727
2728 // Fot apps targeting O-MR1 we require explicit enumeration of all certs.
2729 String[] additionalCertSha256Digests = EmptyArray.STRING;
Jeff Sharkeyaa1a9112018-04-10 15:18:12 -06002730 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O_MR1) {
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002731 additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError);
2732 if (additionalCertSha256Digests == null) {
2733 return false;
2734 }
2735 } else {
2736 XmlUtils.skipCurrentTag(parser);
2737 }
2738
2739 final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1];
2740 certSha256Digests[0] = certSha256Digest;
2741 System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
2742 1, additionalCertSha256Digests.length);
2743
Svet Ganov67882122016-12-11 16:36:34 -08002744 pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname);
Dianne Hackborn3accca02013-09-20 09:32:11 -07002745 pkg.usesStaticLibrariesVersions = ArrayUtils.appendLong(
Svet Ganov8a10ef52017-02-16 20:58:09 -08002746 pkg.usesStaticLibrariesVersions, version, true);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002747 pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
2748 pkg.usesStaticLibrariesCertDigests, certSha256Digests, true);
Svet Ganov67882122016-12-11 16:36:34 -08002749
2750 return true;
2751 }
2752
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002753 private String[] parseAdditionalCertificates(Resources resources, XmlResourceParser parser,
2754 String[] outError) throws XmlPullParserException, IOException {
2755 String[] certSha256Digests = EmptyArray.STRING;
2756
2757 int outerDepth = parser.getDepth();
2758 int type;
2759 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2760 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2761 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2762 continue;
2763 }
2764
2765 final String nodeName = parser.getName();
2766 if (nodeName.equals("additional-certificate")) {
2767 final TypedArray sa = resources.obtainAttributes(parser, com.android.internal.
2768 R.styleable.AndroidManifestAdditionalCertificate);
2769 String certSha256Digest = sa.getNonResourceString(com.android.internal.
2770 R.styleable.AndroidManifestAdditionalCertificate_certDigest);
2771 sa.recycle();
2772
2773 if (TextUtils.isEmpty(certSha256Digest)) {
2774 outError[0] = "Bad additional-certificate declaration with empty"
2775 + " certDigest:" + certSha256Digest;
2776 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2777 XmlUtils.skipCurrentTag(parser);
2778 sa.recycle();
2779 return null;
2780 }
2781
2782 // We allow ":" delimiters in the SHA declaration as this is the format
2783 // emitted by the certtool making it easy for developers to copy/paste.
2784 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2785 certSha256Digests = ArrayUtils.appendElement(String.class,
2786 certSha256Digests, certSha256Digest);
2787 } else {
2788 XmlUtils.skipCurrentTag(parser);
2789 }
2790 }
2791
2792 return certSha256Digests;
2793 }
2794
Svet Ganov354cd3c2015-12-17 11:35:04 -08002795 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
2796 throws XmlPullParserException, IOException {
2797 TypedArray sa = res.obtainAttributes(parser,
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002798 com.android.internal.R.styleable.AndroidManifestUsesPermission);
2799
2800 // Note: don't allow this value to be a reference to a resource
2801 // that may change.
2802 String name = sa.getNonResourceString(
2803 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002804
Christopher Tatefb0676a2013-09-16 16:34:52 -07002805 int maxSdkVersion = 0;
2806 TypedValue val = sa.peekValue(
2807 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
2808 if (val != null) {
2809 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
2810 maxSdkVersion = val.data;
2811 }
2812 }
2813
Dianne Hackborncd154e92017-02-28 17:37:35 -08002814 final String requiredFeature = sa.getNonConfigurationString(
2815 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
2816
2817 final String requiredNotfeature = sa.getNonConfigurationString(
2818 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
2819
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002820 sa.recycle();
2821
Dianne Hackborncd154e92017-02-28 17:37:35 -08002822 XmlUtils.skipCurrentTag(parser);
2823
2824 if (name == null) {
2825 return true;
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002826 }
2827
Dianne Hackborncd154e92017-02-28 17:37:35 -08002828 if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
2829 return true;
2830 }
2831
2832 // Only allow requesting this permission if the platform supports the given feature.
2833 if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
2834 return true;
2835 }
2836
2837 // Only allow requesting this permission if the platform doesn't support the given feature.
2838 if (requiredNotfeature != null && mCallback != null
2839 && mCallback.hasFeature(requiredNotfeature)) {
2840 return true;
2841 }
2842
2843 int index = pkg.requestedPermissions.indexOf(name);
2844 if (index == -1) {
2845 pkg.requestedPermissions.add(name.intern());
2846 } else {
2847 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
2848 + name + " in package: " + pkg.packageName + " at: "
2849 + parser.getPositionDescription());
2850 }
2851
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002852 return true;
2853 }
2854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002855 private static String buildClassName(String pkg, CharSequence clsSeq,
2856 String[] outError) {
2857 if (clsSeq == null || clsSeq.length() <= 0) {
2858 outError[0] = "Empty class name in package " + pkg;
2859 return null;
2860 }
2861 String cls = clsSeq.toString();
2862 char c = cls.charAt(0);
2863 if (c == '.') {
Narayan Kamath07ac1442017-02-10 15:08:07 +00002864 return pkg + cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002865 }
2866 if (cls.indexOf('.') < 0) {
2867 StringBuilder b = new StringBuilder(pkg);
2868 b.append('.');
2869 b.append(cls);
Narayan Kamath07ac1442017-02-10 15:08:07 +00002870 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002871 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002872 return cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002873 }
2874
2875 private static String buildCompoundName(String pkg,
2876 CharSequence procSeq, String type, String[] outError) {
2877 String proc = procSeq.toString();
2878 char c = proc.charAt(0);
2879 if (pkg != null && c == ':') {
2880 if (proc.length() < 2) {
2881 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
2882 + ": must be at least two characters";
2883 return null;
2884 }
2885 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002886 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 if (nameError != null) {
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 pkg + proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002893 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002894 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002895 if (nameError != null && !"system".equals(proc)) {
2896 outError[0] = "Invalid " + type + " name " + proc + " in package "
2897 + pkg + ": " + nameError;
2898 return null;
2899 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002900 return proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002901 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 private static String buildProcessName(String pkg, String defProc,
2904 CharSequence procSeq, int flags, String[] separateProcesses,
2905 String[] outError) {
2906 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
2907 return defProc != null ? defProc : pkg;
2908 }
2909 if (separateProcesses != null) {
2910 for (int i=separateProcesses.length-1; i>=0; i--) {
2911 String sp = separateProcesses[i];
2912 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
2913 return pkg;
2914 }
2915 }
2916 }
2917 if (procSeq == null || procSeq.length() <= 0) {
2918 return defProc;
2919 }
Makoto Onuki812d188a2017-08-07 09:58:23 -07002920 return TextUtils.safeIntern(buildCompoundName(pkg, procSeq, "process", outError));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002921 }
2922
2923 private static String buildTaskAffinityName(String pkg, String defProc,
2924 CharSequence procSeq, String[] outError) {
2925 if (procSeq == null) {
2926 return defProc;
2927 }
2928 if (procSeq.length() <= 0) {
2929 return null;
2930 }
2931 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
2932 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002933
dcashman989eb3712014-06-17 12:56:12 -07002934 private boolean parseKeySets(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002935 XmlResourceParser parser, String[] outError)
Geremy Condraf1bcca82013-01-07 22:35:24 -08002936 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07002937 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08002938 // all the keys and keysets that we want must be defined here
2939 // so we're going to iterate over the parser and pull out the things we want
2940 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07002941 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002942 int type;
dcashman989eb3712014-06-17 12:56:12 -07002943 String currentKeySet = null;
2944 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
2945 ArraySet<String> upgradeKeySets = new ArraySet<String>();
2946 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
2947 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08002948 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2949 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2950 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07002951 if (parser.getDepth() == currentKeySetDepth) {
2952 currentKeySet = null;
2953 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07002954 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002955 continue;
2956 }
dcashman989eb3712014-06-17 12:56:12 -07002957 String tagName = parser.getName();
2958 if (tagName.equals("key-set")) {
2959 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07002960 outError[0] = "Improperly nested 'key-set' tag at "
2961 + parser.getPositionDescription();
2962 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002963 return false;
2964 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002965 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002966 com.android.internal.R.styleable.AndroidManifestKeySet);
2967 final String keysetName = sa.getNonResourceString(
2968 com.android.internal.R.styleable.AndroidManifestKeySet_name);
2969 definedKeySets.put(keysetName, new ArraySet<String>());
2970 currentKeySet = keysetName;
2971 currentKeySetDepth = parser.getDepth();
2972 sa.recycle();
2973 } else if (tagName.equals("public-key")) {
2974 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002975 outError[0] = "Improperly nested 'key-set' tag at "
2976 + parser.getPositionDescription();
2977 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002978 return false;
2979 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002980 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002981 com.android.internal.R.styleable.AndroidManifestPublicKey);
2982 final String publicKeyName = sa.getNonResourceString(
2983 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002984 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07002985 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
2986 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002987 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
2988 + " on first use at " + parser.getPositionDescription();
2989 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07002990 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002991 return false;
2992 } else if (encodedKey != null) {
2993 PublicKey currentKey = parsePublicKey(encodedKey);
2994 if (currentKey == null) {
2995 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
2996 + parser.getPositionDescription() + " key-set " + currentKeySet
2997 + " will not be added to the package's defined key-sets.");
2998 sa.recycle();
2999 improperKeySets.add(currentKeySet);
3000 XmlUtils.skipCurrentTag(parser);
3001 continue;
3002 }
3003 if (publicKeys.get(publicKeyName) == null
3004 || publicKeys.get(publicKeyName).equals(currentKey)) {
3005
3006 /* public-key first definition, or matches old definition */
3007 publicKeys.put(publicKeyName, currentKey);
3008 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003009 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07003010 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07003011 + parser.getPositionDescription();
3012 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003013 sa.recycle();
3014 return false;
3015 }
Kenny Root37dca152013-07-10 14:01:49 -07003016 }
dcashman989eb3712014-06-17 12:56:12 -07003017 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003018 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003019 XmlUtils.skipCurrentTag(parser);
3020 } else if (tagName.equals("upgrade-key-set")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003021 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003022 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
3023 String name = sa.getNonResourceString(
3024 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
3025 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003026 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003027 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003028 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07003029 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003030 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07003031 + parser.getPositionDescription();
3032 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003033 return false;
3034 } else {
dcashman989eb3712014-06-17 12:56:12 -07003035 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003036 + " at " + mArchiveSourcePath + " "
3037 + parser.getPositionDescription());
3038 XmlUtils.skipCurrentTag(parser);
3039 continue;
3040 }
3041 }
dcashman989eb3712014-06-17 12:56:12 -07003042 Set<String> publicKeyNames = publicKeys.keySet();
3043 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07003044 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
3045 + "'key-set' and 'public-key' names must be distinct.";
3046 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003047 return false;
3048 }
3049 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
3050 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
3051 final String keySetName = e.getKey();
3052 if (e.getValue().size() == 0) {
3053 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3054 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
3055 + " Not including in package's defined key-sets.");
3056 continue;
3057 } else if (improperKeySets.contains(keySetName)) {
3058 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3059 + "'key-set' " + keySetName + " contained improper 'public-key'"
3060 + " tags. Not including in package's defined key-sets.");
3061 continue;
3062 }
3063 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
3064 for (String s : e.getValue()) {
3065 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08003066 }
3067 }
dcashman989eb3712014-06-17 12:56:12 -07003068 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
3069 owner.mUpgradeKeySets = upgradeKeySets;
3070 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003071 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
3072 + "does not define all 'upgrade-key-set's .";
3073 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003074 return false;
3075 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003076 return true;
3077 }
3078
Dianne Hackborncd154e92017-02-28 17:37:35 -08003079 private boolean parsePermissionGroup(Package owner, int flags, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003080 XmlResourceParser parser, String[] outError)
3081 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003082 PermissionGroup perm = new PermissionGroup(owner);
3083
Svet Ganov354cd3c2015-12-17 11:35:04 -08003084 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003085 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003087 "<permission-group>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003088 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
3089 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003090 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003091 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003092 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
3093 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003094 sa.recycle();
3095 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003096 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003097 }
3098
3099 perm.info.descriptionRes = sa.getResourceId(
3100 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
3101 0);
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003102 perm.info.requestRes = sa.getResourceId(
3103 com.android.internal.R.styleable.AndroidManifestPermissionGroup_request, 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07003104 perm.info.flags = sa.getInt(
3105 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07003106 perm.info.priority = sa.getInt(
3107 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003108
3109 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003110
Svet Ganov354cd3c2015-12-17 11:35:04 -08003111 if (!parseAllMetaData(res, parser, "<permission-group>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003112 outError)) {
3113 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003114 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003115 }
3116
3117 owner.permissionGroups.add(perm);
3118
Dianne Hackborncd154e92017-02-28 17:37:35 -08003119 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003120 }
3121
Dianne Hackborncd154e92017-02-28 17:37:35 -08003122 private boolean parsePermission(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003123 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003124 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003125
Svet Ganov354cd3c2015-12-17 11:35:04 -08003126 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003127 com.android.internal.R.styleable.AndroidManifestPermission);
3128
Dianne Hackborncd154e92017-02-28 17:37:35 -08003129 Permission perm = new Permission(owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003130 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003131 "<permission>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003132 com.android.internal.R.styleable.AndroidManifestPermission_name,
3133 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003134 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003135 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003136 com.android.internal.R.styleable.AndroidManifestPermission_logo,
3137 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003138 sa.recycle();
3139 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003140 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003141 }
3142
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003143 // Note: don't allow this value to be a reference to a resource
3144 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 perm.info.group = sa.getNonResourceString(
3146 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
3147 if (perm.info.group != null) {
3148 perm.info.group = perm.info.group.intern();
3149 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003151 perm.info.descriptionRes = sa.getResourceId(
3152 com.android.internal.R.styleable.AndroidManifestPermission_description,
3153 0);
3154
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003155 perm.info.requestRes = sa.getResourceId(
3156 com.android.internal.R.styleable.AndroidManifestPermission_request, 0);
3157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003158 perm.info.protectionLevel = sa.getInt(
3159 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
3160 PermissionInfo.PROTECTION_NORMAL);
3161
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07003162 perm.info.flags = sa.getInt(
3163 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
3164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003165 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08003166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003167 if (perm.info.protectionLevel == -1) {
3168 outError[0] = "<permission> does not specify protectionLevel";
3169 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003170 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003171 }
Dianne Hackborne639da72012-02-21 15:11:13 -08003172
3173 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
3174
Makoto Onuki700feef2018-02-15 10:59:41 -08003175 if (perm.info.getProtectionFlags() != 0) {
Todd Kennedyc247fa12017-06-02 10:29:22 -07003176 if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_INSTANT) == 0
Chad Brubakera5d70a12017-03-23 11:04:50 -07003177 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0
Chad Brubakerc19706a2016-10-13 15:44:59 -07003178 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
Dianne Hackborne639da72012-02-21 15:11:13 -08003179 PermissionInfo.PROTECTION_SIGNATURE) {
Joe Maples39bb9e82018-01-11 11:09:46 -05003180 outError[0] = "<permission> protectionLevel specifies a non-instant flag but is "
Dianne Hackborne639da72012-02-21 15:11:13 -08003181 + "not based on signature type";
3182 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003183 return false;
Dianne Hackborne639da72012-02-21 15:11:13 -08003184 }
3185 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003186
Svet Ganov354cd3c2015-12-17 11:35:04 -08003187 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003188 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003189 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003190 }
3191
3192 owner.permissions.add(perm);
3193
Dianne Hackborncd154e92017-02-28 17:37:35 -08003194 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195 }
3196
Dianne Hackborncd154e92017-02-28 17:37:35 -08003197 private boolean parsePermissionTree(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003198 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003199 throws XmlPullParserException, IOException {
3200 Permission perm = new Permission(owner);
3201
Svet Ganov354cd3c2015-12-17 11:35:04 -08003202 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003203 com.android.internal.R.styleable.AndroidManifestPermissionTree);
3204
3205 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003206 "<permission-tree>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003207 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
3208 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003209 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003210 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003211 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
3212 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003213 sa.recycle();
3214 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003215 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003216 }
3217
3218 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003220 int index = perm.info.name.indexOf('.');
3221 if (index > 0) {
3222 index = perm.info.name.indexOf('.', index+1);
3223 }
3224 if (index < 0) {
3225 outError[0] = "<permission-tree> name has less than three segments: "
3226 + perm.info.name;
3227 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003228 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003229 }
3230
3231 perm.info.descriptionRes = 0;
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003232 perm.info.requestRes = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003233 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
3234 perm.tree = true;
3235
Svet Ganov354cd3c2015-12-17 11:35:04 -08003236 if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237 outError)) {
3238 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003239 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003240 }
3241
3242 owner.permissions.add(perm);
3243
Dianne Hackborncd154e92017-02-28 17:37:35 -08003244 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003245 }
3246
3247 private Instrumentation parseInstrumentation(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003248 XmlResourceParser parser, String[] outError)
3249 throws XmlPullParserException, IOException {
3250 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251 com.android.internal.R.styleable.AndroidManifestInstrumentation);
3252
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003253 if (mParseInstrumentationArgs == null) {
3254 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
3255 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
3256 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003257 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003258 com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003259 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
3260 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003261 mParseInstrumentationArgs.tag = "<instrumentation>";
3262 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003263
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003264 mParseInstrumentationArgs.sa = sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003265
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003266 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
3267 new InstrumentationInfo());
3268 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003269 sa.recycle();
3270 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3271 return null;
3272 }
3273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003274 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003275 // Note: don't allow this value to be a reference to a resource
3276 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003277 str = sa.getNonResourceString(
3278 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
3279 a.info.targetPackage = str != null ? str.intern() : null;
3280
Dianne Hackborn34041732017-01-31 15:27:13 -08003281 str = sa.getNonResourceString(
Dianne Hackborn1be53542017-04-28 13:36:00 -07003282 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcesses);
3283 a.info.targetProcesses = str != null ? str.intern() : null;
Dianne Hackborn34041732017-01-31 15:27:13 -08003284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003285 a.info.handleProfiling = sa.getBoolean(
3286 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
3287 false);
3288
3289 a.info.functionalTest = sa.getBoolean(
3290 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
3291 false);
3292
3293 sa.recycle();
3294
3295 if (a.info.targetPackage == null) {
3296 outError[0] = "<instrumentation> does not specify targetPackage";
3297 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3298 return null;
3299 }
3300
Svet Ganov354cd3c2015-12-17 11:35:04 -08003301 if (!parseAllMetaData(res, parser, "<instrumentation>", a,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003302 outError)) {
3303 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3304 return null;
3305 }
3306
3307 owner.instrumentation.add(a);
3308
3309 return a;
3310 }
3311
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003312 /**
3313 * Parse the {@code application} XML tree at the current parse location in a
3314 * <em>base APK</em> manifest.
3315 * <p>
3316 * When adding new features, carefully consider if they should also be
3317 * supported by split APKs.
3318 */
3319 private boolean parseBaseApplication(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003320 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003321 throws XmlPullParserException, IOException {
3322 final ApplicationInfo ai = owner.applicationInfo;
3323 final String pkgName = owner.applicationInfo.packageName;
3324
Svet Ganov354cd3c2015-12-17 11:35:04 -08003325 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003326 com.android.internal.R.styleable.AndroidManifestApplication);
3327
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003328 if (!parsePackageItemInfo(owner, ai, outError,
3329 "<application>", sa, false /*nameRequired*/,
3330 com.android.internal.R.styleable.AndroidManifestApplication_name,
3331 com.android.internal.R.styleable.AndroidManifestApplication_label,
3332 com.android.internal.R.styleable.AndroidManifestApplication_icon,
3333 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
3334 com.android.internal.R.styleable.AndroidManifestApplication_logo,
3335 com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
3336 sa.recycle();
3337 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3338 return false;
3339 }
3340
3341 if (ai.name != null) {
Todd Kennedyafb52692016-08-22 15:44:00 -07003342 ai.className = ai.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003343 }
3344
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003345 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003346 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
3347 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003348 if (manageSpaceActivity != null) {
3349 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
3350 outError);
3351 }
3352
Christopher Tate181fafa2009-05-14 11:12:14 -07003353 boolean allowBackup = sa.getBoolean(
3354 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
3355 if (allowBackup) {
3356 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07003357
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003358 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
3359 // and restoreAnyVersion are only relevant if backup is possible for the
3360 // given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003361 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003362 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
3363 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07003364 if (backupAgent != null) {
3365 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07003366 if (DEBUG_BACKUP) {
3367 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003368 + " from " + pkgName + "+" + backupAgent);
3369 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003370
3371 if (sa.getBoolean(
3372 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
3373 true)) {
3374 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
3375 }
3376 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08003377 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
3378 false)) {
3379 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
3380 }
Christopher Tated1de2562014-06-17 17:12:35 -07003381 if (sa.getBoolean(
3382 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
3383 false)) {
3384 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
3385 }
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003386 if (sa.getBoolean(
3387 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
3388 false)) {
3389 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
3390 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003391 }
Matthew Williams303650c2015-04-17 18:22:51 -07003392
3393 TypedValue v = sa.peekValue(
3394 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
3395 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
3396 if (DEBUG_BACKUP) {
3397 Slog.v(TAG, "fullBackupContent specified as boolean=" +
3398 (v.data == 0 ? "false" : "true"));
3399 }
3400 // "false" => -1, "true" => 0
3401 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
3402 }
3403 if (DEBUG_BACKUP) {
3404 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
3405 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003406 }
Christopher Tate4a627c72011-04-01 14:43:32 -07003407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003408 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08003409 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410 ai.descriptionRes = sa.getResourceId(
3411 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
3412
Todd Kennedy232d29e2017-11-06 14:45:53 -08003413 if (sa.getBoolean(
3414 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
3415 false)) {
3416 // Check if persistence is based on a feature being present
3417 final String requiredFeature = sa.getNonResourceString(com.android.internal.R.styleable
3418 .AndroidManifestApplication_persistentWhenFeatureAvailable);
3419 if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
3420 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003421 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07003422 }
3423
3424 if (sa.getBoolean(
3425 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
3426 false)) {
3427 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07003428 }
3429
3430 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
3431 .AndroidManifestApplication_restrictedAccountType);
3432 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
3433 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003434 }
3435
Amith Yamasaniccbe3892013-04-12 17:52:42 -07003436 String requiredAccountType = sa.getString(com.android.internal.R.styleable
3437 .AndroidManifestApplication_requiredAccountType);
3438 if (requiredAccountType != null && requiredAccountType.length() > 0) {
3439 owner.mRequiredAccountType = requiredAccountType;
3440 }
3441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003442 if (sa.getBoolean(
3443 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
3444 false)) {
3445 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
3446 }
3447
3448 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07003449 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08003450 false)) {
3451 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
3452 }
3453
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003454 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07003455 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07003456 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07003457 if (owner.baseHardwareAccelerated) {
3458 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
3459 }
Romain Guy812ccbe2010-06-01 14:07:24 -07003460
3461 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003462 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
3463 true)) {
3464 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
3465 }
3466
3467 if (sa.getBoolean(
3468 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
3469 false)) {
3470 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
3471 }
3472
3473 if (sa.getBoolean(
3474 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
3475 true)) {
3476 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
3477 }
3478
Svet Ganov354cd3c2015-12-17 11:35:04 -08003479 // The parent package controls installation, hence specify test only installs.
3480 if (owner.parentPackage == null) {
3481 if (sa.getBoolean(
3482 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
3483 false)) {
3484 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
3485 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003486 }
3487
Jason parksa3cdaa52011-01-13 14:15:43 -06003488 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003489 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06003490 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003491 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06003492 }
3493
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003494 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07003495 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
Chad Brubaker0d285d52018-03-14 09:00:04 -07003496 owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.P)) {
Alex Klyubin01a959d2015-03-18 10:05:45 -07003497 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
3498 }
3499
3500 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003501 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
3502 false /* default is no RTL support*/)) {
3503 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
3504 }
3505
Narayan Kamath589a1bc2014-07-03 14:43:26 +01003506 if (sa.getBoolean(
3507 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
3508 false)) {
3509 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
3510 }
3511
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07003512 if (sa.getBoolean(
3513 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
3514 true)) {
3515 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
3516 }
3517
Todd Kennedyd022ac22016-04-13 10:49:29 -07003518 if (sa.getBoolean(
3519 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
3520 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003521 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003522 }
Todd Kennedyd022ac22016-04-13 10:49:29 -07003523 if (sa.getBoolean(
3524 R.styleable.AndroidManifestApplication_directBootAware,
3525 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003526 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003527 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003528
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003529 if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
3530 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003531 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
3532 } else {
3533 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003534 }
3535 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003536 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwale6afdf912016-01-30 13:01:33 -08003537 }
3538
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07003539 ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
3540
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003541 ai.networkSecurityConfigRes = sa.getResourceId(
3542 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
3543 0);
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07003544 ai.category = sa.getInt(
3545 com.android.internal.R.styleable.AndroidManifestApplication_appCategory,
3546 ApplicationInfo.CATEGORY_UNDEFINED);
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003548 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003549 str = sa.getNonConfigurationString(
3550 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
3552
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003553 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3554 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003555 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
3556 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003557 } else {
3558 // Some older apps have been seen to use a resource reference
3559 // here that on older builds was ignored (with a warning). We
3560 // need to continue to do this for them so they don't break.
3561 str = sa.getNonResourceString(
3562 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
3563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003564 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
3565 str, outError);
Jason Monka80bfb52017-11-16 17:15:37 -05003566 String factory = sa.getNonResourceString(
3567 com.android.internal.R.styleable.AndroidManifestApplication_appComponentFactory);
3568 if (factory != null) {
3569 ai.appComponentFactory = buildClassName(ai.packageName, factory, outError);
3570 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003571
3572 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003573 CharSequence pname;
3574 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3575 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003576 com.android.internal.R.styleable.AndroidManifestApplication_process,
3577 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003578 } else {
3579 // Some older apps have been seen to use a resource reference
3580 // here that on older builds was ignored (with a warning). We
3581 // need to continue to do this for them so they don't break.
3582 pname = sa.getNonResourceString(
3583 com.android.internal.R.styleable.AndroidManifestApplication_process);
3584 }
3585 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003586 flags, mSeparateProcesses, outError);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003587
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003588 ai.enabled = sa.getBoolean(
3589 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003590
Jose Lima12d0b4c2014-03-14 16:55:12 -07003591 if (sa.getBoolean(
3592 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
3593 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
3594 }
3595
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003596 if (sa.getBoolean(
3597 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
3598 false)) {
3599 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07003600
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003601 // A heavy-weight application can not be in a custom process.
3602 // We can do direct compare because we intern all strings.
3603 if (ai.processName != null && !ai.processName.equals(ai.packageName)) {
3604 outError[0] = "cantSaveState applications can not use custom processes";
Dianne Hackborn860755f2010-06-03 18:47:52 -07003605 }
3606 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003607 }
3608
Adam Powell269248d2011-08-02 10:26:54 -07003609 ai.uiOptions = sa.getInt(
3610 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
3611
Narayan Kamath96c11c52017-08-09 13:07:21 +01003612 ai.classLoaderName = sa.getString(
3613 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3614 if (ai.classLoaderName != null
3615 && !ClassLoaderFactory.isValidClassLoaderName(ai.classLoaderName)) {
3616 outError[0] = "Invalid class loader name: " + ai.classLoaderName;
3617 }
3618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003619 sa.recycle();
3620
3621 if (outError[0] != null) {
3622 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3623 return false;
3624 }
3625
3626 final int innerDepth = parser.getDepth();
Garrett Boyer52136662017-05-23 13:47:58 -07003627 // IMPORTANT: These must only be cached for a single <application> to avoid components
3628 // getting added to the wrong package.
3629 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 int type;
Todd Kennedy6d418b62018-02-22 14:15:18 -08003631 boolean hasActivityOrder = false;
3632 boolean hasReceiverOrder = false;
3633 boolean hasServiceOrder = false;
Kenny Rootd2d29252011-08-08 11:27:57 -07003634 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3635 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3636 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003637 continue;
3638 }
3639
3640 String tagName = parser.getName();
3641 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003642 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003643 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003644 if (a == null) {
3645 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3646 return false;
3647 }
3648
Todd Kennedy6d418b62018-02-22 14:15:18 -08003649 hasActivityOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003650 owner.activities.add(a);
3651
3652 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003653 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3654 true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003655 if (a == null) {
3656 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3657 return false;
3658 }
3659
Todd Kennedy6d418b62018-02-22 14:15:18 -08003660 hasReceiverOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 owner.receivers.add(a);
3662
3663 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003664 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003665 if (s == null) {
3666 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3667 return false;
3668 }
3669
Todd Kennedy6d418b62018-02-22 14:15:18 -08003670 hasServiceOrder |= (s.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003671 owner.services.add(s);
3672
3673 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003674 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003675 if (p == null) {
3676 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3677 return false;
3678 }
3679
3680 owner.providers.add(p);
3681
3682 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003683 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003684 if (a == null) {
3685 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3686 return false;
3687 }
3688
Todd Kennedy6d418b62018-02-22 14:15:18 -08003689 hasActivityOrder |= (a.order != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003690 owner.activities.add(a);
3691
3692 } else if (parser.getName().equals("meta-data")) {
3693 // note: application meta-data is stored off to the side, so it can
3694 // remain null in the primary copy (we like to avoid extra copies because
3695 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003696 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 outError)) == null) {
3698 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3699 return false;
3700 }
Svet Ganov67882122016-12-11 16:36:34 -08003701 } else if (tagName.equals("static-library")) {
3702 sa = res.obtainAttributes(parser,
3703 com.android.internal.R.styleable.AndroidManifestStaticLibrary);
3704
3705 // Note: don't allow this value to be a reference to a resource
3706 // that may change.
3707 final String lname = sa.getNonResourceString(
3708 com.android.internal.R.styleable.AndroidManifestStaticLibrary_name);
3709 final int version = sa.getInt(
3710 com.android.internal.R.styleable.AndroidManifestStaticLibrary_version, -1);
Dianne Hackborn3accca02013-09-20 09:32:11 -07003711 final int versionMajor = sa.getInt(
3712 com.android.internal.R.styleable.AndroidManifestStaticLibrary_versionMajor,
3713 0);
Svet Ganov67882122016-12-11 16:36:34 -08003714
3715 sa.recycle();
3716
3717 // Since the app canot run without a static lib - fail if malformed
3718 if (lname == null || version < 0) {
3719 outError[0] = "Bad static-library declaration name: " + lname
3720 + " version: " + version;
3721 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3722 XmlUtils.skipCurrentTag(parser);
3723 return false;
3724 }
3725
3726 if (owner.mSharedUserId != null) {
3727 outError[0] = "sharedUserId not allowed in static shared library";
3728 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
3729 XmlUtils.skipCurrentTag(parser);
3730 return false;
3731 }
3732
3733 if (owner.staticSharedLibName != null) {
3734 outError[0] = "Multiple static-shared libs for package " + pkgName;
3735 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3736 XmlUtils.skipCurrentTag(parser);
3737 return false;
3738 }
3739
3740 owner.staticSharedLibName = lname.intern();
Dianne Hackborn3accca02013-09-20 09:32:11 -07003741 if (version >= 0) {
3742 owner.staticSharedLibVersion =
3743 PackageInfo.composeLongVersionCode(versionMajor, version);
3744 } else {
3745 owner.staticSharedLibVersion = version;
3746 }
Svet Ganov67882122016-12-11 16:36:34 -08003747 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
3748
3749 XmlUtils.skipCurrentTag(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003750
Dianne Hackbornc895be72013-03-11 17:48:43 -07003751 } else if (tagName.equals("library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003752 sa = res.obtainAttributes(parser,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003753 com.android.internal.R.styleable.AndroidManifestLibrary);
3754
3755 // Note: don't allow this value to be a reference to a resource
3756 // that may change.
3757 String lname = sa.getNonResourceString(
3758 com.android.internal.R.styleable.AndroidManifestLibrary_name);
3759
3760 sa.recycle();
3761
3762 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003763 lname = lname.intern();
3764 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
Svet Ganov67882122016-12-11 16:36:34 -08003765 owner.libraryNames = ArrayUtils.add(
3766 owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07003767 }
3768 }
3769
3770 XmlUtils.skipCurrentTag(parser);
3771
Svet Ganov67882122016-12-11 16:36:34 -08003772 } else if (tagName.equals("uses-static-library")) {
3773 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3774 return false;
3775 }
3776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003777 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003778 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003779 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3780
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003781 // Note: don't allow this value to be a reference to a resource
3782 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 String lname = sa.getNonResourceString(
3784 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07003785 boolean req = sa.getBoolean(
3786 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3787 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003788
3789 sa.recycle();
3790
Dianne Hackborn49237342009-08-27 20:08:01 -07003791 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003792 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07003793 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003794 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003795 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003796 owner.usesOptionalLibraries = ArrayUtils.add(
3797 owner.usesOptionalLibraries, lname);
3798 }
3799 }
3800
3801 XmlUtils.skipCurrentTag(parser);
3802
3803 } else if (tagName.equals("uses-package")) {
3804 // Dependencies for app installers; we don't currently try to
3805 // enforce this.
3806 XmlUtils.skipCurrentTag(parser);
3807
3808 } else {
3809 if (!RIGID_PARSER) {
3810 Slog.w(TAG, "Unknown element under <application>: " + tagName
3811 + " at " + mArchiveSourcePath + " "
3812 + parser.getPositionDescription());
3813 XmlUtils.skipCurrentTag(parser);
3814 continue;
3815 } else {
3816 outError[0] = "Bad element under <application>: " + tagName;
3817 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3818 return false;
3819 }
3820 }
3821 }
3822
Todd Kennedy6d418b62018-02-22 14:15:18 -08003823 if (hasActivityOrder) {
3824 Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order));
3825 }
3826 if (hasReceiverOrder) {
3827 Collections.sort(owner.receivers, (r1, r2) -> Integer.compare(r2.order, r1.order));
3828 }
3829 if (hasServiceOrder) {
3830 Collections.sort(owner.services, (s1, s2) -> Integer.compare(s2.order, s1.order));
3831 }
Bryce Lee22571db2017-07-07 15:54:18 -07003832 // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
3833 // every activity info has had a chance to set it from its attributes.
3834 setMaxAspectRatio(owner);
3835
Paul Duffin855d7022017-07-10 15:16:07 +01003836 PackageBackwardCompatibility.modifySharedLibraries(owner);
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003837
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003838 if (hasDomainURLs(owner)) {
3839 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3840 } else {
3841 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3842 }
3843
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003844 return true;
3845 }
3846
3847 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003848 * 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 -07003849 */
3850 private static boolean hasDomainURLs(Package pkg) {
3851 if (pkg == null || pkg.activities == null) return false;
3852 final ArrayList<Activity> activities = pkg.activities;
3853 final int countActivities = activities.size();
3854 for (int n=0; n<countActivities; n++) {
3855 Activity activity = activities.get(n);
3856 ArrayList<ActivityIntentInfo> filters = activity.intents;
3857 if (filters == null) continue;
3858 final int countFilters = filters.size();
3859 for (int m=0; m<countFilters; m++) {
3860 ActivityIntentInfo aii = filters.get(m);
3861 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003862 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003863 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
3864 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
3865 return true;
3866 }
3867 }
3868 }
3869 return false;
3870 }
3871
3872 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003873 * Parse the {@code application} XML tree at the current parse location in a
3874 * <em>split APK</em> manifest.
3875 * <p>
3876 * Note that split APKs have many more restrictions on what they're capable
3877 * of doing, so many valid features of a base APK have been carefully
3878 * omitted here.
3879 */
Svet Ganov354cd3c2015-12-17 11:35:04 -08003880 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
3881 int flags, int splitIndex, String[] outError)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003882 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003883 TypedArray sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003884 com.android.internal.R.styleable.AndroidManifestApplication);
3885
3886 if (sa.getBoolean(
3887 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
3888 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
3889 }
3890
Narayan Kamath96c11c52017-08-09 13:07:21 +01003891 final String classLoaderName = sa.getString(
3892 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3893 if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
3894 owner.applicationInfo.splitClassLoaderNames[splitIndex] = classLoaderName;
3895 } else {
3896 outError[0] = "Invalid class loader name: " + classLoaderName;
3897 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3898 return false;
3899 }
3900
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003901 final int innerDepth = parser.getDepth();
3902 int type;
3903 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3904 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3905 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3906 continue;
3907 }
3908
Adam Lesinski4e862812016-11-21 16:02:24 -08003909 ComponentInfo parsedComponent = null;
3910
Garrett Boyer52136662017-05-23 13:47:58 -07003911 // IMPORTANT: These must only be cached for a single <application> to avoid components
3912 // getting added to the wrong package.
3913 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003914 String tagName = parser.getName();
3915 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003916 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003917 owner.baseHardwareAccelerated);
3918 if (a == null) {
3919 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3920 return false;
3921 }
3922
3923 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003924 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003925
3926 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003927 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3928 true, false);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003929 if (a == null) {
3930 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3931 return false;
3932 }
3933
3934 owner.receivers.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003935 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003936
3937 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003938 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003939 if (s == null) {
3940 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3941 return false;
3942 }
3943
3944 owner.services.add(s);
Adam Lesinski4e862812016-11-21 16:02:24 -08003945 parsedComponent = s.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003946
3947 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003948 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003949 if (p == null) {
3950 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3951 return false;
3952 }
3953
3954 owner.providers.add(p);
Adam Lesinski4e862812016-11-21 16:02:24 -08003955 parsedComponent = p.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003956
3957 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003958 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003959 if (a == null) {
3960 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3961 return false;
3962 }
3963
3964 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003965 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003966
3967 } else if (parser.getName().equals("meta-data")) {
3968 // note: application meta-data is stored off to the side, so it can
3969 // remain null in the primary copy (we like to avoid extra copies because
3970 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003971 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003972 outError)) == null) {
3973 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3974 return false;
3975 }
3976
Svet Ganov67882122016-12-11 16:36:34 -08003977 } else if (tagName.equals("uses-static-library")) {
3978 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3979 return false;
3980 }
3981
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003982 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003983 sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003984 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3985
3986 // Note: don't allow this value to be a reference to a resource
3987 // that may change.
3988 String lname = sa.getNonResourceString(
3989 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
3990 boolean req = sa.getBoolean(
3991 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3992 true);
3993
3994 sa.recycle();
3995
3996 if (lname != null) {
3997 lname = lname.intern();
3998 if (req) {
3999 // Upgrade to treat as stronger constraint
4000 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
4001 owner.usesOptionalLibraries = ArrayUtils.remove(
4002 owner.usesOptionalLibraries, lname);
4003 } else {
4004 // Ignore if someone already defined as required
4005 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
4006 owner.usesOptionalLibraries = ArrayUtils.add(
4007 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07004008 }
4009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004010 }
4011
4012 XmlUtils.skipCurrentTag(parser);
4013
Dianne Hackborncef65ee2010-09-30 18:27:22 -07004014 } else if (tagName.equals("uses-package")) {
4015 // Dependencies for app installers; we don't currently try to
4016 // enforce this.
4017 XmlUtils.skipCurrentTag(parser);
4018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004019 } else {
4020 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004021 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004022 + " at " + mArchiveSourcePath + " "
4023 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004024 XmlUtils.skipCurrentTag(parser);
4025 continue;
4026 } else {
4027 outError[0] = "Bad element under <application>: " + tagName;
4028 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4029 return false;
4030 }
4031 }
Adam Lesinski4e862812016-11-21 16:02:24 -08004032
4033 if (parsedComponent != null && parsedComponent.splitName == null) {
4034 // If the loaded component did not specify a split, inherit the split name
4035 // based on the split it is defined in.
4036 // This is used to later load the correct split when starting this
4037 // component.
4038 parsedComponent.splitName = owner.splitNames[splitIndex];
4039 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004040 }
4041
4042 return true;
4043 }
4044
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004045 private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
4046 String[] outError, String tag, TypedArray sa, boolean nameRequired,
4047 int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00004048 // This case can only happen in unit tests where we sometimes need to create fakes
4049 // of various package parser data structures.
4050 if (sa == null) {
4051 outError[0] = tag + " does not contain any attributes";
4052 return false;
4053 }
4054
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004055 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004056 if (name == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004057 if (nameRequired) {
4058 outError[0] = tag + " does not specify android:name";
4059 return false;
4060 }
4061 } else {
4062 outInfo.name
4063 = buildClassName(owner.applicationInfo.packageName, name, outError);
4064 if (outInfo.name == null) {
4065 return false;
4066 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004067 }
4068
Todd Kennedya83bfca2016-06-03 07:52:17 -07004069 final boolean useRoundIcon =
4070 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
4071 int roundIconVal = useRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004072 if (roundIconVal != 0) {
4073 outInfo.icon = roundIconVal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004074 outInfo.nonLocalizedLabel = null;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004075 } else {
4076 int iconVal = sa.getResourceId(iconRes, 0);
4077 if (iconVal != 0) {
4078 outInfo.icon = iconVal;
4079 outInfo.nonLocalizedLabel = null;
4080 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004081 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004082
Adam Powell81cd2e92010-04-21 16:35:18 -07004083 int logoVal = sa.getResourceId(logoRes, 0);
4084 if (logoVal != 0) {
4085 outInfo.logo = logoVal;
4086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004087
Jose Limaf78e3122014-03-06 12:13:15 -08004088 int bannerVal = sa.getResourceId(bannerRes, 0);
4089 if (bannerVal != 0) {
4090 outInfo.banner = bannerVal;
4091 }
4092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004093 TypedValue v = sa.peekValue(labelRes);
4094 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4095 outInfo.nonLocalizedLabel = v.coerceToString();
4096 }
4097
4098 outInfo.packageName = owner.packageName;
4099
4100 return true;
4101 }
4102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004103 private Activity parseActivity(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004104 XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
Romain Guy529b60a2010-08-03 18:05:47 -07004105 boolean receiver, boolean hardwareAccelerated)
4106 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004107 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004108
Garrett Boyer52136662017-05-23 13:47:58 -07004109 if (cachedArgs.mActivityArgs == null) {
4110 cachedArgs.mActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004111 R.styleable.AndroidManifestActivity_name,
4112 R.styleable.AndroidManifestActivity_label,
4113 R.styleable.AndroidManifestActivity_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004114 R.styleable.AndroidManifestActivity_roundIcon,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004115 R.styleable.AndroidManifestActivity_logo,
4116 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004117 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004118 R.styleable.AndroidManifestActivity_process,
4119 R.styleable.AndroidManifestActivity_description,
4120 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004121 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004122
Garrett Boyer52136662017-05-23 13:47:58 -07004123 cachedArgs.mActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
4124 cachedArgs.mActivityArgs.sa = sa;
4125 cachedArgs.mActivityArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004126
Garrett Boyer52136662017-05-23 13:47:58 -07004127 Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004128 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004129 sa.recycle();
4130 return null;
4131 }
4132
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004133 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004134 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004135 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004136 }
4137
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004138 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004139
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004140 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07004141 a.info.applicationInfo.uiOptions);
4142
Adam Powelldd8fab22012-03-22 17:47:27 -07004143 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004144 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004145 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004146 if (parentName != null) {
4147 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4148 if (outError[0] == null) {
4149 a.info.parentActivityName = parentClassName;
4150 } else {
4151 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
4152 parentName);
4153 outError[0] = null;
4154 }
4155 }
4156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004157 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004158 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004159 if (str == null) {
4160 a.info.permission = owner.applicationInfo.permission;
4161 } else {
4162 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4163 }
4164
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004165 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004166 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004167 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004168 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
4169 owner.applicationInfo.taskAffinity, str, outError);
4170
Todd Kennedye9d0d272017-01-23 06:49:29 -08004171 a.info.splitName =
4172 sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0);
4173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004174 a.info.flags = 0;
4175 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004176 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004177 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
4178 }
4179
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004180 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004181 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
4182 }
4183
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004184 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004185 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
4186 }
4187
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004188 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004189 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
4190 }
4191
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004192 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004193 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
4194 }
4195
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004196 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
4198 }
4199
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004200 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004201 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
4202 }
4203
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004204 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004205 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
4206 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
4207 }
4208
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004209 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07004210 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
4211 }
4212
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07004213 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
4214 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
4215 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07004216 }
4217
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004218 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04004219 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
4220 }
Craig Mautner5962b122012-10-05 14:45:52 -07004221
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07004222 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
4223 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08004224 }
4225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004226 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004227 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07004228 hardwareAccelerated)) {
4229 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
4230 }
4231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004232 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004233 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07004234 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004235 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07004236 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07004237 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004238 R.styleable.AndroidManifestActivity_maxRecents,
Dianne Hackborn852975d2014-08-22 17:42:43 -07004239 ActivityManager.getDefaultAppRecentsLimitStatic());
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004240 a.info.configChanges = getActivityConfigChanges(
4241 sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004242 sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004243 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004244 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07004245
Craig Mautner43e52ed2014-06-16 17:18:52 -07004246 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004247 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07004248 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07004249
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004250 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004251 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
4252 }
4253
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004254 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004255 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
4256 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004257
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004258 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004259 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
4260 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004261
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004262 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004263 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
4264 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004265
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004266 a.info.screenOrientation = sa.getInt(
4267 R.styleable.AndroidManifestActivity_screenOrientation,
4268 SCREEN_ORIENTATION_UNSPECIFIED);
Wale Ogunwale6a591362015-10-05 20:18:27 -07004269
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004270 setActivityResizeMode(a.info, sa, owner);
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004271
Winson Chungd3395382016-12-13 11:49:09 -08004272 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
4273 false)) {
4274 a.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE;
4275 }
4276
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004277 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004278 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004279 }
Wale Ogunwaleb60692e2015-10-24 12:35:56 -07004280
Bryce Lee22571db2017-07-07 15:54:18 -07004281 if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio)
4282 && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio)
4283 == TypedValue.TYPE_FLOAT) {
4284 a.setMaxAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio,
4285 0 /*default*/));
4286 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004287
Craig Mautner15df08a2015-04-01 12:17:18 -07004288 a.info.lockTaskLaunchMode =
4289 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004290
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004291 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4292 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004293 false);
Ruben Brunkf56c9f42016-04-22 18:20:55 -07004294
4295 a.info.requestedVrComponent =
4296 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
Robert Carr0f5d7532016-10-17 16:39:17 -07004297
4298 a.info.rotationAnimation =
Robert Carr427ba4f2017-07-17 18:37:06 -07004299 sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_UNSPECIFIED);
Romain Guy48327452017-01-23 17:03:35 -08004300
4301 a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
4302 ActivityInfo.COLOR_MODE_DEFAULT);
chaviw59b98852017-06-13 12:05:44 -07004303
4304 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) {
4305 a.info.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
4306 }
4307
4308 if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) {
4309 a.info.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON;
4310 }
4311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004312 } else {
4313 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4314 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004315
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004316 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07004317 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004318 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004319
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004320 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4321 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004322 false);
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004323 }
4324
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004325 if (a.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004326 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004327 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004328 }
4329
Todd Kennedy752fb702017-03-21 16:28:10 -07004330 // can't make this final; we may set it later via meta-data
4331 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08004332 sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004333 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004334 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004335 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004336 }
4337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004338 sa.recycle();
4339
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004340 if (receiver && (owner.applicationInfo.privateFlags
4341 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004342 // A heavy-weight application can not have receives in its main process
4343 // We can do direct compare because we intern all strings.
4344 if (a.info.processName == owner.packageName) {
4345 outError[0] = "Heavy-weight applications can not have receivers in main process";
4346 }
4347 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004349 if (outError[0] != null) {
4350 return null;
4351 }
4352
4353 int outerDepth = parser.getDepth();
4354 int type;
4355 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4356 && (type != XmlPullParser.END_TAG
4357 || parser.getDepth() > outerDepth)) {
4358 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4359 continue;
4360 }
4361
4362 if (parser.getName().equals("intent-filter")) {
4363 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004364 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4365 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004366 return null;
4367 }
4368 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004369 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004370 + mArchiveSourcePath + " "
4371 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004372 } else {
Todd Kennedy6d418b62018-02-22 14:15:18 -08004373 a.order = Math.max(intent.getOrder(), a.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374 a.intents.add(intent);
4375 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004376 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004377 final int visibility = visibleToEphemeral
4378 ? IntentFilter.VISIBILITY_EXPLICIT
4379 : !receiver && isImplicitlyExposedIntent(intent)
4380 ? IntentFilter.VISIBILITY_IMPLICIT
4381 : IntentFilter.VISIBILITY_NONE;
4382 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004383 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004384 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4385 }
4386 if (intent.isImplicitlyVisibleToInstantApp()) {
4387 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004388 }
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -07004389 if (LOG_UNSAFE_BROADCASTS && receiver
4390 && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
4391 for (int i = 0; i < intent.countActions(); i++) {
4392 final String action = intent.getAction(i);
4393 if (action == null || !action.startsWith("android.")) continue;
4394 if (!SAFE_BROADCASTS.contains(action)) {
4395 Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
4396 + owner.packageName + " as requested at: "
4397 + parser.getPositionDescription());
4398 }
4399 }
4400 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004401 } else if (!receiver && parser.getName().equals("preferred")) {
4402 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004403 if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
4404 intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004405 return null;
4406 }
4407 if (intent.countActions() == 0) {
4408 Slog.w(TAG, "No actions in preferred at "
4409 + mArchiveSourcePath + " "
4410 + parser.getPositionDescription());
4411 } else {
4412 if (owner.preferredActivityFilters == null) {
4413 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
4414 }
4415 owner.preferredActivityFilters.add(intent);
4416 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004417 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004418 final int visibility = visibleToEphemeral
4419 ? IntentFilter.VISIBILITY_EXPLICIT
4420 : !receiver && isImplicitlyExposedIntent(intent)
4421 ? IntentFilter.VISIBILITY_IMPLICIT
4422 : IntentFilter.VISIBILITY_NONE;
4423 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004424 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004425 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4426 }
4427 if (intent.isImplicitlyVisibleToInstantApp()) {
4428 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004430 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004431 if ((a.metaData = parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004432 outError)) == null) {
4433 return null;
4434 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004435 } else if (!receiver && parser.getName().equals("layout")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004436 parseLayout(res, parser, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004437 } else {
4438 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004439 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004440 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004441 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004442 + " at " + mArchiveSourcePath + " "
4443 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004444 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004445 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004446 + " at " + mArchiveSourcePath + " "
4447 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004448 }
4449 XmlUtils.skipCurrentTag(parser);
4450 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004452 if (receiver) {
4453 outError[0] = "Bad element under <receiver>: " + parser.getName();
4454 } else {
4455 outError[0] = "Bad element under <activity>: " + parser.getName();
4456 }
4457 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004458 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004459 }
4460 }
4461
4462 if (!setExported) {
4463 a.info.exported = a.intents.size() > 0;
4464 }
4465
4466 return a;
4467 }
4468
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004469 private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004470 final boolean appExplicitDefault = (owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004471 & (PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
4472 | PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004473
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004474 if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
4475 || appExplicitDefault) {
4476 // Activity or app explicitly set if it is resizeable or not;
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004477 final boolean appResizeable = (owner.applicationInfo.privateFlags
4478 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004479 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004480 appResizeable)) {
Winson Chungd3395382016-12-13 11:49:09 -08004481 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004482 } else {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004483 aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004484 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004485 return;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004486 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004487
4488 if ((owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004489 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) != 0) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004490 // The activity or app didn't explicitly set the resizing option, however we want to
4491 // make it resize due to the sdk version it is targeting.
4492 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4493 return;
4494 }
4495
4496 // resize preference isn't set and target sdk version doesn't support resizing apps by
4497 // default. For the app to be resizeable if it isn't fixed orientation or immersive.
skuhne@google.com322347b2016-12-02 12:54:03 -08004498 if (aInfo.isFixedOrientationPortrait()) {
4499 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
4500 } else if (aInfo.isFixedOrientationLandscape()) {
4501 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
4502 } else if (aInfo.isFixedOrientation()) {
4503 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
4504 } else {
4505 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4506 }
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004507 }
4508
Bryce Lee22571db2017-07-07 15:54:18 -07004509 /**
4510 * Sets every the max aspect ratio of every child activity that doesn't already have an aspect
4511 * ratio set.
4512 */
4513 private void setMaxAspectRatio(Package owner) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004514 // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
4515 // 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 -07004516 float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004517 ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
Bryce Lee22571db2017-07-07 15:54:18 -07004518
4519 if (owner.applicationInfo.maxAspectRatio != 0) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004520 // Use the application max aspect ration as default if set.
Bryce Lee22571db2017-07-07 15:54:18 -07004521 maxAspectRatio = owner.applicationInfo.maxAspectRatio;
4522 } else if (owner.mAppMetaData != null
4523 && owner.mAppMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) {
4524 maxAspectRatio = owner.mAppMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004525 }
4526
Bryce Lee22571db2017-07-07 15:54:18 -07004527 for (Activity activity : owner.activities) {
4528 // If the max aspect ratio for the activity has already been set, skip.
4529 if (activity.hasMaxAspectRatio()) {
4530 continue;
4531 }
4532
4533 // By default we prefer to use a values defined on the activity directly than values
4534 // defined on the application. We do not check the styled attributes on the activity
4535 // as it would have already been set when we processed the activity. We wait to process
4536 // the meta data here since this method is called at the end of processing the
4537 // application and all meta data is guaranteed.
4538 final float activityAspectRatio = activity.metaData != null
4539 ? activity.metaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio)
4540 : maxAspectRatio;
4541
4542 activity.setMaxAspectRatio(activityAspectRatio);
Wale Ogunwale0cb70ac2017-03-27 09:16:38 -07004543 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004544 }
4545
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004546 /**
4547 * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004548 * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from
4549 * AndroidManifest.xml.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004550 * @hide Exposed for unit testing only.
4551 */
4552 @TestApi
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004553 public static int getActivityConfigChanges(int configChanges, int recreateOnConfigChanges) {
4554 return configChanges | ((~recreateOnConfigChanges) & RECREATE_ON_CONFIG_CHANGES_MASK);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004555 }
4556
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004557 private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004558 TypedArray sw = res.obtainAttributes(attrs,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004559 com.android.internal.R.styleable.AndroidManifestLayout);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004560 int width = -1;
4561 float widthFraction = -1f;
4562 int height = -1;
4563 float heightFraction = -1f;
4564 final int widthType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004565 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004566 if (widthType == TypedValue.TYPE_FRACTION) {
4567 widthFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004568 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004569 1, 1, -1);
4570 } else if (widthType == TypedValue.TYPE_DIMENSION) {
4571 width = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004572 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004573 -1);
4574 }
4575 final int heightType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004576 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004577 if (heightType == TypedValue.TYPE_FRACTION) {
4578 heightFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004579 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004580 1, 1, -1);
4581 } else if (heightType == TypedValue.TYPE_DIMENSION) {
4582 height = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004583 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004584 -1);
4585 }
4586 int gravity = sw.getInt(
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004587 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004588 Gravity.CENTER);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004589 int minWidth = sw.getDimensionPixelSize(
4590 com.android.internal.R.styleable.AndroidManifestLayout_minWidth,
Andrii Kulian2e751b82016-03-16 16:59:32 -07004591 -1);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004592 int minHeight = sw.getDimensionPixelSize(
4593 com.android.internal.R.styleable.AndroidManifestLayout_minHeight,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004594 -1);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004595 sw.recycle();
Andrii Kulian2e751b82016-03-16 16:59:32 -07004596 a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction,
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004597 height, heightFraction, gravity, minWidth, minHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004598 }
4599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004600 private Activity parseActivityAlias(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004601 XmlResourceParser parser, int flags, String[] outError,
4602 CachedComponentArgs cachedArgs)
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004603 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004604 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004605 com.android.internal.R.styleable.AndroidManifestActivityAlias);
4606
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004607 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004608 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
4609 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004610 if (targetActivity == null) {
4611 outError[0] = "<activity-alias> does not specify android:targetActivity";
4612 sa.recycle();
4613 return null;
4614 }
4615
4616 targetActivity = buildClassName(owner.applicationInfo.packageName,
4617 targetActivity, outError);
4618 if (targetActivity == null) {
4619 sa.recycle();
4620 return null;
4621 }
4622
Garrett Boyer52136662017-05-23 13:47:58 -07004623 if (cachedArgs.mActivityAliasArgs == null) {
4624 cachedArgs.mActivityAliasArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004625 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
4626 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
4627 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004628 com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004629 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004630 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004631 mSeparateProcesses,
4632 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004633 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004634 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004635 cachedArgs.mActivityAliasArgs.tag = "<activity-alias>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004636 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004637
Garrett Boyer52136662017-05-23 13:47:58 -07004638 cachedArgs.mActivityAliasArgs.sa = sa;
4639 cachedArgs.mActivityAliasArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 Activity target = null;
4642
4643 final int NA = owner.activities.size();
4644 for (int i=0; i<NA; i++) {
4645 Activity t = owner.activities.get(i);
4646 if (targetActivity.equals(t.info.name)) {
4647 target = t;
4648 break;
4649 }
4650 }
4651
4652 if (target == null) {
4653 outError[0] = "<activity-alias> target activity " + targetActivity
4654 + " not found in manifest";
4655 sa.recycle();
4656 return null;
4657 }
4658
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004659 ActivityInfo info = new ActivityInfo();
4660 info.targetActivity = targetActivity;
4661 info.configChanges = target.info.configChanges;
4662 info.flags = target.info.flags;
4663 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07004664 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08004665 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004666 info.labelRes = target.info.labelRes;
4667 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
4668 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07004669 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004670 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004671 if (info.descriptionRes == 0) {
4672 info.descriptionRes = target.info.descriptionRes;
4673 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004674 info.screenOrientation = target.info.screenOrientation;
4675 info.taskAffinity = target.info.taskAffinity;
4676 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07004677 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07004678 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07004679 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07004680 info.maxRecents = target.info.maxRecents;
Andrii Kulian2e751b82016-03-16 16:59:32 -07004681 info.windowLayout = target.info.windowLayout;
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004682 info.resizeMode = target.info.resizeMode;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004683 info.maxAspectRatio = target.info.maxAspectRatio;
rongliuc12ede42018-02-23 17:58:38 -08004684 info.requestedVrComponent = target.info.requestedVrComponent;
Bryce Lee22571db2017-07-07 15:54:18 -07004685
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004686 info.encryptionAware = info.directBootAware = target.info.directBootAware;
Craig Mautner8307ea72014-09-11 15:03:53 -07004687
Garrett Boyer52136662017-05-23 13:47:58 -07004688 Activity a = new Activity(cachedArgs.mActivityAliasArgs, info);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004689 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004690 sa.recycle();
4691 return null;
4692 }
4693
4694 final boolean setExported = sa.hasValue(
4695 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
4696 if (setExported) {
4697 a.info.exported = sa.getBoolean(
4698 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
4699 }
4700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004701 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004702 str = sa.getNonConfigurationString(
4703 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004704 if (str != null) {
4705 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4706 }
4707
Adam Powelldd8fab22012-03-22 17:47:27 -07004708 String parentName = sa.getNonConfigurationString(
4709 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004710 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004711 if (parentName != null) {
4712 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4713 if (outError[0] == null) {
4714 a.info.parentActivityName = parentClassName;
4715 } else {
4716 Log.e(TAG, "Activity alias " + a.info.name +
4717 " specified invalid parentActivityName " + parentName);
4718 outError[0] = null;
4719 }
4720 }
4721
Chad Brubaker699c7712017-01-20 13:53:42 -08004722 // TODO add visibleToInstantApps attribute to activity alias
Todd Kennedybe0b8892017-02-15 14:13:52 -08004723 final boolean visibleToEphemeral =
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004724 ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004726 sa.recycle();
4727
4728 if (outError[0] != null) {
4729 return null;
4730 }
4731
4732 int outerDepth = parser.getDepth();
4733 int type;
4734 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4735 && (type != XmlPullParser.END_TAG
4736 || parser.getDepth() > outerDepth)) {
4737 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4738 continue;
4739 }
4740
4741 if (parser.getName().equals("intent-filter")) {
4742 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004743 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4744 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004745 return null;
4746 }
4747 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004748 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004749 + mArchiveSourcePath + " "
4750 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004751 } else {
Todd Kennedy6d418b62018-02-22 14:15:18 -08004752 a.order = Math.max(intent.getOrder(), a.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004753 a.intents.add(intent);
4754 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004755 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004756 final int visibility = visibleToEphemeral
4757 ? IntentFilter.VISIBILITY_EXPLICIT
4758 : isImplicitlyExposedIntent(intent)
4759 ? IntentFilter.VISIBILITY_IMPLICIT
4760 : IntentFilter.VISIBILITY_NONE;
4761 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004762 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004763 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4764 }
4765 if (intent.isImplicitlyVisibleToInstantApp()) {
4766 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004767 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004768 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004769 if ((a.metaData=parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004770 outError)) == null) {
4771 return null;
4772 }
4773 } else {
4774 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004775 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004776 + " at " + mArchiveSourcePath + " "
4777 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004778 XmlUtils.skipCurrentTag(parser);
4779 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004780 } else {
4781 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
4782 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004783 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004784 }
4785 }
4786
4787 if (!setExported) {
4788 a.info.exported = a.intents.size() > 0;
4789 }
4790
4791 return a;
4792 }
4793
4794 private Provider parseProvider(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004795 XmlResourceParser parser, int flags, String[] outError,
4796 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004798 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004799 com.android.internal.R.styleable.AndroidManifestProvider);
4800
Garrett Boyer52136662017-05-23 13:47:58 -07004801 if (cachedArgs.mProviderArgs == null) {
4802 cachedArgs.mProviderArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004803 com.android.internal.R.styleable.AndroidManifestProvider_name,
4804 com.android.internal.R.styleable.AndroidManifestProvider_label,
4805 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004806 com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004807 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004808 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004809 mSeparateProcesses,
4810 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004811 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004812 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004813 cachedArgs.mProviderArgs.tag = "<provider>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004814 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004815
Garrett Boyer52136662017-05-23 13:47:58 -07004816 cachedArgs.mProviderArgs.sa = sa;
4817 cachedArgs.mProviderArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004818
Garrett Boyer52136662017-05-23 13:47:58 -07004819 Provider p = new Provider(cachedArgs.mProviderArgs, new ProviderInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004820 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004821 sa.recycle();
4822 return null;
4823 }
4824
Nick Kralevichf097b162012-07-28 12:43:48 -07004825 boolean providerExportedDefault = false;
4826
4827 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
4828 // For compatibility, applications targeting API level 16 or lower
4829 // should have their content providers exported by default, unless they
4830 // specify otherwise.
4831 providerExportedDefault = true;
4832 }
4833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004834 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07004835 com.android.internal.R.styleable.AndroidManifestProvider_exported,
4836 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004837
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004838 String cpname = sa.getNonConfigurationString(
4839 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004840
4841 p.info.isSyncable = sa.getBoolean(
4842 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
4843 false);
4844
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004845 String permission = sa.getNonConfigurationString(
4846 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
4847 String str = sa.getNonConfigurationString(
4848 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004849 if (str == null) {
4850 str = permission;
4851 }
4852 if (str == null) {
4853 p.info.readPermission = owner.applicationInfo.permission;
4854 } else {
4855 p.info.readPermission =
4856 str.length() > 0 ? str.toString().intern() : null;
4857 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004858 str = sa.getNonConfigurationString(
4859 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004860 if (str == null) {
4861 str = permission;
4862 }
4863 if (str == null) {
4864 p.info.writePermission = owner.applicationInfo.permission;
4865 } else {
4866 p.info.writePermission =
4867 str.length() > 0 ? str.toString().intern() : null;
4868 }
4869
4870 p.info.grantUriPermissions = sa.getBoolean(
4871 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
4872 false);
4873
4874 p.info.multiprocess = sa.getBoolean(
4875 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
4876 false);
4877
4878 p.info.initOrder = sa.getInt(
4879 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
4880 0);
4881
Todd Kennedye9d0d272017-01-23 06:49:29 -08004882 p.info.splitName =
4883 sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0);
4884
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004885 p.info.flags = 0;
4886
4887 if (sa.getBoolean(
4888 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
4889 false)) {
4890 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004891 }
4892
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004893 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
4894 R.styleable.AndroidManifestProvider_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004895 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004896 if (p.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004897 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004898 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004899 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004900
Todd Kennedybe0b8892017-02-15 14:13:52 -08004901 final boolean visibleToEphemeral =
4902 sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004903 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004904 p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004905 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004906 }
4907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004908 sa.recycle();
4909
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004910 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
4911 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004912 // A heavy-weight application can not have providers in its main process
4913 // We can do direct compare because we intern all strings.
4914 if (p.info.processName == owner.packageName) {
4915 outError[0] = "Heavy-weight applications can not have providers in main process";
4916 return null;
4917 }
4918 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004919
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004920 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07004921 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004922 return null;
4923 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08004924 if (cpname.length() <= 0) {
4925 outError[0] = "<provider> has empty authorities attribute";
4926 return null;
4927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004928 p.info.authority = cpname.intern();
4929
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004930 if (!parseProviderTags(
Patrick Baumanna2900392018-02-05 15:30:43 -08004931 res, parser, visibleToEphemeral, p, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004932 return null;
4933 }
4934
4935 return p;
4936 }
4937
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004938 private boolean parseProviderTags(Resources res, XmlResourceParser parser,
Patrick Baumanna2900392018-02-05 15:30:43 -08004939 boolean visibleToEphemeral, Provider outInfo, String[] outError)
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004940 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004941 int outerDepth = parser.getDepth();
4942 int type;
4943 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4944 && (type != XmlPullParser.END_TAG
4945 || parser.getDepth() > outerDepth)) {
4946 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4947 continue;
4948 }
4949
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004950 if (parser.getName().equals("intent-filter")) {
4951 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004952 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
4953 intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004954 return false;
4955 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004956 if (visibleToEphemeral) {
4957 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
4958 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004959 }
Todd Kennedy6d418b62018-02-22 14:15:18 -08004960 outInfo.order = Math.max(intent.getOrder(), outInfo.order);
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004961 outInfo.intents.add(intent);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004962
4963 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004964 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004965 outInfo.metaData, outError)) == null) {
4966 return false;
4967 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004968
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004969 } else if (parser.getName().equals("grant-uri-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004970 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004971 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
4972
4973 PatternMatcher pa = null;
4974
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004975 String str = sa.getNonConfigurationString(
4976 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 if (str != null) {
4978 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
4979 }
4980
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004981 str = sa.getNonConfigurationString(
4982 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004983 if (str != null) {
4984 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
4985 }
4986
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004987 str = sa.getNonConfigurationString(
4988 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 if (str != null) {
4990 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4991 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 sa.recycle();
4994
4995 if (pa != null) {
4996 if (outInfo.info.uriPermissionPatterns == null) {
4997 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
4998 outInfo.info.uriPermissionPatterns[0] = pa;
4999 } else {
5000 final int N = outInfo.info.uriPermissionPatterns.length;
5001 PatternMatcher[] newp = new PatternMatcher[N+1];
5002 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
5003 newp[N] = pa;
5004 outInfo.info.uriPermissionPatterns = newp;
5005 }
5006 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005007 } else {
5008 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005009 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005010 + parser.getName() + " at " + mArchiveSourcePath + " "
5011 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005012 XmlUtils.skipCurrentTag(parser);
5013 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005014 } else {
5015 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5016 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005017 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005018 }
5019 XmlUtils.skipCurrentTag(parser);
5020
5021 } else if (parser.getName().equals("path-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005022 TypedArray sa = res.obtainAttributes(parser,
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005023 com.android.internal.R.styleable.AndroidManifestPathPermission);
5024
5025 PathPermission pa = null;
5026
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005027 String permission = sa.getNonConfigurationString(
5028 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
5029 String readPermission = sa.getNonConfigurationString(
5030 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005031 if (readPermission == null) {
5032 readPermission = permission;
5033 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005034 String writePermission = sa.getNonConfigurationString(
5035 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005036 if (writePermission == null) {
5037 writePermission = permission;
5038 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005039
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005040 boolean havePerm = false;
5041 if (readPermission != null) {
5042 readPermission = readPermission.intern();
5043 havePerm = true;
5044 }
5045 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00005046 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005047 havePerm = true;
5048 }
5049
5050 if (!havePerm) {
5051 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005052 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005053 + parser.getName() + " at " + mArchiveSourcePath + " "
5054 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005055 XmlUtils.skipCurrentTag(parser);
5056 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005057 } else {
5058 outError[0] = "No readPermission or writePermssion for <path-permission>";
5059 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005060 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005061 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005062
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005063 String path = sa.getNonConfigurationString(
5064 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005065 if (path != null) {
5066 pa = new PathPermission(path,
5067 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
5068 }
5069
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005070 path = sa.getNonConfigurationString(
5071 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005072 if (path != null) {
5073 pa = new PathPermission(path,
5074 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
5075 }
5076
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005077 path = sa.getNonConfigurationString(
5078 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005079 if (path != null) {
5080 pa = new PathPermission(path,
5081 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
5082 }
5083
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005084 path = sa.getNonConfigurationString(
5085 com.android.internal.R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
5086 if (path != null) {
5087 pa = new PathPermission(path,
5088 PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission);
5089 }
5090
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005091 sa.recycle();
5092
5093 if (pa != null) {
5094 if (outInfo.info.pathPermissions == null) {
5095 outInfo.info.pathPermissions = new PathPermission[1];
5096 outInfo.info.pathPermissions[0] = pa;
5097 } else {
5098 final int N = outInfo.info.pathPermissions.length;
5099 PathPermission[] newp = new PathPermission[N+1];
5100 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
5101 newp[N] = pa;
5102 outInfo.info.pathPermissions = newp;
5103 }
5104 } else {
5105 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005106 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005107 + parser.getName() + " at " + mArchiveSourcePath + " "
5108 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005109 XmlUtils.skipCurrentTag(parser);
5110 continue;
5111 }
5112 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5113 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005114 }
5115 XmlUtils.skipCurrentTag(parser);
5116
5117 } else {
5118 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005119 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005120 + parser.getName() + " at " + mArchiveSourcePath + " "
5121 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005122 XmlUtils.skipCurrentTag(parser);
5123 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005124 } else {
5125 outError[0] = "Bad element under <provider>: " + parser.getName();
5126 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005127 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005128 }
5129 }
5130 return true;
5131 }
5132
5133 private Service parseService(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07005134 XmlResourceParser parser, int flags, String[] outError,
5135 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005136 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005137 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138 com.android.internal.R.styleable.AndroidManifestService);
5139
Garrett Boyer52136662017-05-23 13:47:58 -07005140 if (cachedArgs.mServiceArgs == null) {
5141 cachedArgs.mServiceArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005142 com.android.internal.R.styleable.AndroidManifestService_name,
5143 com.android.internal.R.styleable.AndroidManifestService_label,
5144 com.android.internal.R.styleable.AndroidManifestService_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005145 com.android.internal.R.styleable.AndroidManifestService_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07005146 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08005147 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005148 mSeparateProcesses,
5149 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005150 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005151 com.android.internal.R.styleable.AndroidManifestService_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07005152 cachedArgs.mServiceArgs.tag = "<service>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005153 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005154
Garrett Boyer52136662017-05-23 13:47:58 -07005155 cachedArgs.mServiceArgs.sa = sa;
5156 cachedArgs.mServiceArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005157
Garrett Boyer52136662017-05-23 13:47:58 -07005158 Service s = new Service(cachedArgs.mServiceArgs, new ServiceInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005159 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 sa.recycle();
5161 return null;
5162 }
5163
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005164 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005165 com.android.internal.R.styleable.AndroidManifestService_exported);
5166 if (setExported) {
5167 s.info.exported = sa.getBoolean(
5168 com.android.internal.R.styleable.AndroidManifestService_exported, false);
5169 }
5170
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005171 String str = sa.getNonConfigurationString(
5172 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005173 if (str == null) {
5174 s.info.permission = owner.applicationInfo.permission;
5175 } else {
5176 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
5177 }
5178
Todd Kennedye9d0d272017-01-23 06:49:29 -08005179 s.info.splitName =
5180 sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0);
5181
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005182 s.info.flags = 0;
5183 if (sa.getBoolean(
5184 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
5185 false)) {
5186 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
5187 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08005188 if (sa.getBoolean(
5189 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
5190 false)) {
5191 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
5192 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005193 if (sa.getBoolean(
Robert Sesekb9a86662015-12-09 16:22:45 -05005194 com.android.internal.R.styleable.AndroidManifestService_externalService,
5195 false)) {
5196 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
5197 }
5198 if (sa.getBoolean(
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005199 com.android.internal.R.styleable.AndroidManifestService_singleUser,
5200 false)) {
5201 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005202 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005203
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005204 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
5205 R.styleable.AndroidManifestService_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005206 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005207 if (s.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005208 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005209 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005210 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005211
Todd Kennedy752fb702017-03-21 16:28:10 -07005212 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08005213 sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005214 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005215 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005216 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005217 }
5218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005219 sa.recycle();
5220
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005221 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5222 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005223 // A heavy-weight application can not have services in its main process
5224 // We can do direct compare because we intern all strings.
5225 if (s.info.processName == owner.packageName) {
5226 outError[0] = "Heavy-weight applications can not have services in main process";
5227 return null;
5228 }
5229 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005231 int outerDepth = parser.getDepth();
5232 int type;
5233 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5234 && (type != XmlPullParser.END_TAG
5235 || parser.getDepth() > outerDepth)) {
5236 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5237 continue;
5238 }
5239
5240 if (parser.getName().equals("intent-filter")) {
5241 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005242 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5243 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005244 return null;
5245 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005246 if (visibleToEphemeral) {
5247 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5248 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005249 }
Todd Kennedy6d418b62018-02-22 14:15:18 -08005250 s.order = Math.max(intent.getOrder(), s.order);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005251 s.intents.add(intent);
5252 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005253 if ((s.metaData=parseMetaData(res, parser, s.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005254 outError)) == null) {
5255 return null;
5256 }
5257 } else {
5258 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005259 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005260 + parser.getName() + " at " + mArchiveSourcePath + " "
5261 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005262 XmlUtils.skipCurrentTag(parser);
5263 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005264 } else {
5265 outError[0] = "Bad element under <service>: " + parser.getName();
5266 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005268 }
5269 }
5270
5271 if (!setExported) {
5272 s.info.exported = s.intents.size() > 0;
5273 }
5274
5275 return s;
5276 }
5277
Chad Brubaker49414832017-04-13 16:13:23 -07005278 private boolean isImplicitlyExposedIntent(IntentInfo intent) {
5279 return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
5280 || intent.hasAction(Intent.ACTION_SEND)
5281 || intent.hasAction(Intent.ACTION_SENDTO)
5282 || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005283 }
5284
Svet Ganov354cd3c2015-12-17 11:35:04 -08005285 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
5286 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005287 int outerDepth = parser.getDepth();
5288 int type;
5289 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5290 && (type != XmlPullParser.END_TAG
5291 || parser.getDepth() > outerDepth)) {
5292 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5293 continue;
5294 }
5295
5296 if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005297 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005298 outInfo.metaData, outError)) == null) {
5299 return false;
5300 }
5301 } else {
5302 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005303 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005304 + parser.getName() + " at " + mArchiveSourcePath + " "
5305 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005306 XmlUtils.skipCurrentTag(parser);
5307 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005308 } else {
5309 outError[0] = "Bad element under " + tag + ": " + parser.getName();
5310 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005311 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005312 }
5313 }
5314 return true;
5315 }
5316
5317 private Bundle parseMetaData(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08005318 XmlResourceParser parser, Bundle data, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005319 throws XmlPullParserException, IOException {
5320
Svet Ganov354cd3c2015-12-17 11:35:04 -08005321 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005322 com.android.internal.R.styleable.AndroidManifestMetaData);
5323
5324 if (data == null) {
5325 data = new Bundle();
5326 }
5327
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005328 String name = sa.getNonConfigurationString(
5329 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005330 if (name == null) {
5331 outError[0] = "<meta-data> requires an android:name attribute";
5332 sa.recycle();
5333 return null;
5334 }
5335
Dianne Hackborn854060af2009-07-09 18:14:31 -07005336 name = name.intern();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005338 TypedValue v = sa.peekValue(
5339 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
5340 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005341 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005342 data.putInt(name, v.resourceId);
5343 } else {
5344 v = sa.peekValue(
5345 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07005346 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005347 if (v != null) {
5348 if (v.type == TypedValue.TYPE_STRING) {
5349 CharSequence cs = v.coerceToString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00005350 data.putString(name, cs != null ? cs.toString() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005351 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
5352 data.putBoolean(name, v.data != 0);
5353 } else if (v.type >= TypedValue.TYPE_FIRST_INT
5354 && v.type <= TypedValue.TYPE_LAST_INT) {
5355 data.putInt(name, v.data);
5356 } else if (v.type == TypedValue.TYPE_FLOAT) {
5357 data.putFloat(name, v.getFloat());
5358 } else {
5359 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005360 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005361 + parser.getName() + " at " + mArchiveSourcePath + " "
5362 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363 } else {
5364 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
5365 data = null;
5366 }
5367 }
5368 } else {
5369 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
5370 data = null;
5371 }
5372 }
5373
5374 sa.recycle();
5375
5376 XmlUtils.skipCurrentTag(parser);
5377
5378 return data;
5379 }
5380
Adam Lesinski4e862812016-11-21 16:02:24 -08005381 private static VerifierInfo parseVerifier(AttributeSet attrs) {
5382 String packageName = null;
5383 String encodedPublicKey = null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005384
Adam Lesinski4e862812016-11-21 16:02:24 -08005385 final int attrCount = attrs.getAttributeCount();
5386 for (int i = 0; i < attrCount; i++) {
5387 final int attrResId = attrs.getAttributeNameResource(i);
5388 switch (attrResId) {
5389 case com.android.internal.R.attr.name:
5390 packageName = attrs.getAttributeValue(i);
5391 break;
Kenny Root05ca4c92011-09-15 10:36:25 -07005392
Adam Lesinski4e862812016-11-21 16:02:24 -08005393 case com.android.internal.R.attr.publicKey:
5394 encodedPublicKey = attrs.getAttributeValue(i);
5395 break;
5396 }
5397 }
Kenny Root05ca4c92011-09-15 10:36:25 -07005398
5399 if (packageName == null || packageName.length() == 0) {
5400 Slog.i(TAG, "verifier package name was null; skipping");
5401 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005402 }
5403
Christopher Tate30147332014-04-15 12:57:47 -07005404 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
5405 if (publicKey == null) {
5406 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
5407 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08005408 }
5409
Christopher Tate30147332014-04-15 12:57:47 -07005410 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08005411 }
5412
Christopher Tate30147332014-04-15 12:57:47 -07005413 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
5414 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07005415 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07005416 return null;
5417 }
5418
Kenny Root05ca4c92011-09-15 10:36:25 -07005419 EncodedKeySpec keySpec;
5420 try {
5421 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
5422 keySpec = new X509EncodedKeySpec(encoded);
5423 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07005424 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07005425 return null;
5426 }
5427
5428 /* First try the key as an RSA key. */
5429 try {
5430 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005431 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005432 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005433 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005434 } catch (InvalidKeySpecException e) {
5435 // Not a RSA public key.
5436 }
5437
dcashman1616f302015-05-29 14:47:23 -07005438 /* Now try it as a ECDSA key. */
5439 try {
5440 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
5441 return keyFactory.generatePublic(keySpec);
5442 } catch (NoSuchAlgorithmException e) {
5443 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
5444 } catch (InvalidKeySpecException e) {
5445 // Not a ECDSA public key.
5446 }
5447
Kenny Root05ca4c92011-09-15 10:36:25 -07005448 /* Now try it as a DSA key. */
5449 try {
5450 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005451 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005452 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005453 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005454 } catch (InvalidKeySpecException e) {
5455 // Not a DSA public key.
5456 }
5457
dcashman1616f302015-05-29 14:47:23 -07005458 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07005459 return null;
5460 }
5461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005462 private static final String ANDROID_RESOURCES
5463 = "http://schemas.android.com/apk/res/android";
5464
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005465 private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs,
5466 boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
5467 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005468
Svet Ganov354cd3c2015-12-17 11:35:04 -08005469 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005470 com.android.internal.R.styleable.AndroidManifestIntentFilter);
5471
5472 int priority = sa.getInt(
5473 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005474 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08005475
Todd Kennedy6d418b62018-02-22 14:15:18 -08005476 int order = sa.getInt(
5477 com.android.internal.R.styleable.AndroidManifestIntentFilter_order, 0);
5478 outInfo.setOrder(order);
5479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005480 TypedValue v = sa.peekValue(
5481 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
5482 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
5483 outInfo.nonLocalizedLabel = v.coerceToString();
5484 }
5485
Todd Kennedya83bfca2016-06-03 07:52:17 -07005486 final boolean useRoundIcon =
5487 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
5488 int roundIconVal = useRoundIcon ? sa.getResourceId(
5489 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
5490 if (roundIconVal != 0) {
5491 outInfo.icon = roundIconVal;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005492 } else {
5493 outInfo.icon = sa.getResourceId(
5494 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
5495 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005496
Adam Powell81cd2e92010-04-21 16:35:18 -07005497 outInfo.logo = sa.getResourceId(
5498 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499
Jose Limaf78e3122014-03-06 12:13:15 -08005500 outInfo.banner = sa.getResourceId(
5501 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
5502
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08005503 if (allowAutoVerify) {
5504 outInfo.setAutoVerify(sa.getBoolean(
5505 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
5506 false));
5507 }
5508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509 sa.recycle();
5510
5511 int outerDepth = parser.getDepth();
5512 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07005513 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
5514 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
5515 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005516 continue;
5517 }
5518
5519 String nodeName = parser.getName();
5520 if (nodeName.equals("action")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005521 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005522 ANDROID_RESOURCES, "name");
5523 if (value == null || value == "") {
5524 outError[0] = "No value supplied for <android:name>";
5525 return false;
5526 }
5527 XmlUtils.skipCurrentTag(parser);
5528
5529 outInfo.addAction(value);
5530 } else if (nodeName.equals("category")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005531 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005532 ANDROID_RESOURCES, "name");
5533 if (value == null || value == "") {
5534 outError[0] = "No value supplied for <android:name>";
5535 return false;
5536 }
5537 XmlUtils.skipCurrentTag(parser);
5538
5539 outInfo.addCategory(value);
5540
5541 } else if (nodeName.equals("data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005542 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005543 com.android.internal.R.styleable.AndroidManifestData);
5544
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005545 String str = sa.getNonConfigurationString(
5546 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005547 if (str != null) {
5548 try {
5549 outInfo.addDataType(str);
5550 } catch (IntentFilter.MalformedMimeTypeException e) {
5551 outError[0] = e.toString();
5552 sa.recycle();
5553 return false;
5554 }
5555 }
5556
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005557 str = sa.getNonConfigurationString(
5558 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005559 if (str != null) {
5560 outInfo.addDataScheme(str);
5561 }
5562
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005563 str = sa.getNonConfigurationString(
5564 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
5565 if (str != null) {
5566 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
5567 }
5568
5569 str = sa.getNonConfigurationString(
5570 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
5571 if (str != null) {
5572 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
5573 }
5574
5575 str = sa.getNonConfigurationString(
5576 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
5577 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005578 if (!allowGlobs) {
5579 outError[0] = "sspPattern not allowed here; ssp must be literal";
5580 return false;
5581 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005582 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5583 }
5584
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005585 String host = sa.getNonConfigurationString(
5586 com.android.internal.R.styleable.AndroidManifestData_host, 0);
5587 String port = sa.getNonConfigurationString(
5588 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005589 if (host != null) {
5590 outInfo.addDataAuthority(host, port);
5591 }
5592
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005593 str = sa.getNonConfigurationString(
5594 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005595 if (str != null) {
5596 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
5597 }
5598
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005599 str = sa.getNonConfigurationString(
5600 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005601 if (str != null) {
5602 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
5603 }
5604
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005605 str = sa.getNonConfigurationString(
5606 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005607 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005608 if (!allowGlobs) {
5609 outError[0] = "pathPattern not allowed here; path must be literal";
5610 return false;
5611 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005612 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5613 }
5614
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005615 str = sa.getNonConfigurationString(
5616 com.android.internal.R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
5617 if (str != null) {
5618 if (!allowGlobs) {
5619 outError[0] = "pathAdvancedPattern not allowed here; path must be literal";
5620 return false;
5621 }
5622 outInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
5623 }
5624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005625 sa.recycle();
5626 XmlUtils.skipCurrentTag(parser);
5627 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005628 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005629 + parser.getName() + " at " + mArchiveSourcePath + " "
5630 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005631 XmlUtils.skipCurrentTag(parser);
5632 } else {
5633 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
5634 return false;
5635 }
5636 }
5637
5638 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07005639
5640 if (DEBUG_PARSER) {
5641 final StringBuilder cats = new StringBuilder("Intent d=");
5642 cats.append(outInfo.hasDefault);
5643 cats.append(", cat=");
5644
5645 final Iterator<String> it = outInfo.categoriesIterator();
5646 if (it != null) {
5647 while (it.hasNext()) {
5648 cats.append(' ');
5649 cats.append(it.next());
5650 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005651 }
Kenny Rootd2d29252011-08-08 11:27:57 -07005652 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005653 }
5654
5655 return true;
5656 }
5657
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005658 /**
5659 * A container for signing-related data of an application package.
5660 * @hide
5661 */
Patrick Baumann47117fc2017-12-19 10:17:21 -08005662 public static final class SigningDetails implements Parcelable {
5663
5664 @IntDef({SigningDetails.SignatureSchemeVersion.UNKNOWN,
5665 SigningDetails.SignatureSchemeVersion.JAR,
5666 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2,
5667 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3})
5668 public @interface SignatureSchemeVersion {
5669 int UNKNOWN = 0;
5670 int JAR = 1;
5671 int SIGNING_BLOCK_V2 = 2;
5672 int SIGNING_BLOCK_V3 = 3;
5673 }
5674
5675 @Nullable
5676 public final Signature[] signatures;
5677 @SignatureSchemeVersion
5678 public final int signatureSchemeVersion;
5679 @Nullable
5680 public final ArraySet<PublicKey> publicKeys;
5681
Daniel Cashman77029c52018-01-18 16:19:29 -08005682 /**
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005683 * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
5684 * contains two pieces of information:
5685 * 1) the past signing certificates
5686 * 2) the flags that APK wants to assign to each of the past signing certificates.
5687 *
5688 * This collection of {@code Signature} objects, each of which is formed from a former
5689 * signing certificate of this APK before it was changed by signing certificate rotation,
5690 * represents the first piece of information. It is the APK saying to the rest of the
5691 * world: "hey if you trust the old cert, you can trust me!" This is useful, if for
5692 * instance, the platform would like to determine whether or not to allow this APK to do
5693 * something it would've allowed it to do under the old cert (like upgrade).
Daniel Cashman77029c52018-01-18 16:19:29 -08005694 */
5695 @Nullable
5696 public final Signature[] pastSigningCertificates;
5697
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005698 /** special value used to see if cert is in package - not exposed to callers */
5699 private static final int PAST_CERT_EXISTS = 0;
5700
5701 @IntDef(
5702 flag = true,
5703 value = {CertCapabilities.INSTALLED_DATA,
5704 CertCapabilities.SHARED_USER_ID,
Daniel Cashman629a5f92018-03-30 18:54:14 -07005705 CertCapabilities.PERMISSION,
5706 CertCapabilities.ROLLBACK})
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005707 public @interface CertCapabilities {
5708
5709 /** accept data from already installed pkg with this cert */
5710 int INSTALLED_DATA = 1;
5711
5712 /** accept sharedUserId with pkg with this cert */
5713 int SHARED_USER_ID = 2;
5714
5715 /** grant SIGNATURE permissions to pkgs with this cert */
5716 int PERMISSION = 4;
Daniel Cashman629a5f92018-03-30 18:54:14 -07005717
5718 /** allow pkg to update to one signed by this certificate */
5719 int ROLLBACK = 8;
Dan Cashman303c4bb2018-04-10 07:41:16 -07005720
5721 /** allow pkg to continue to have auth access gated by this cert */
5722 int AUTH = 16;
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005723 }
5724
Daniel Cashman77029c52018-01-18 16:19:29 -08005725 /**
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005726 * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
5727 * contains two pieces of information:
5728 * 1) the past signing certificates
5729 * 2) the flags that APK wants to assign to each of the past signing certificates.
5730 *
5731 * These flags, which have a one-to-one relationship for the {@code pastSigningCertificates}
5732 * collection, represent the second piece of information and are viewed as capabilities.
5733 * They are an APK's way of telling the platform: "this is how I want to trust my old certs,
5734 * please enforce that." This is useful for situation where this app itself is using its
5735 * signing certificate as an authorization mechanism, like whether or not to allow another
5736 * app to have its SIGNATURE permission. An app could specify whether to allow other apps
5737 * signed by its old cert 'X' to still get a signature permission it defines, for example.
Daniel Cashman77029c52018-01-18 16:19:29 -08005738 */
5739 @Nullable
5740 public final int[] pastSigningCertificatesFlags;
5741
Patrick Baumann47117fc2017-12-19 10:17:21 -08005742 /** A representation of unknown signing details. Use instead of null. */
5743 public static final SigningDetails UNKNOWN =
Daniel Cashman77029c52018-01-18 16:19:29 -08005744 new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null, null);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005745
5746 @VisibleForTesting
5747 public SigningDetails(Signature[] signatures,
5748 @SignatureSchemeVersion int signatureSchemeVersion,
Daniel Cashman77029c52018-01-18 16:19:29 -08005749 ArraySet<PublicKey> keys, Signature[] pastSigningCertificates,
5750 int[] pastSigningCertificatesFlags) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08005751 this.signatures = signatures;
5752 this.signatureSchemeVersion = signatureSchemeVersion;
5753 this.publicKeys = keys;
Daniel Cashman77029c52018-01-18 16:19:29 -08005754 this.pastSigningCertificates = pastSigningCertificates;
5755 this.pastSigningCertificatesFlags = pastSigningCertificatesFlags;
5756 }
5757
5758 public SigningDetails(Signature[] signatures,
5759 @SignatureSchemeVersion int signatureSchemeVersion,
5760 Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags)
5761 throws CertificateException {
5762 this(signatures, signatureSchemeVersion, toSigningKeys(signatures),
5763 pastSigningCertificates, pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005764 }
5765
5766 public SigningDetails(Signature[] signatures,
5767 @SignatureSchemeVersion int signatureSchemeVersion)
5768 throws CertificateException {
Daniel Cashman77029c52018-01-18 16:19:29 -08005769 this(signatures, signatureSchemeVersion,
5770 null, null);
5771 }
5772
5773 public SigningDetails(SigningDetails orig) {
5774 if (orig != null) {
5775 if (orig.signatures != null) {
5776 this.signatures = orig.signatures.clone();
5777 } else {
5778 this.signatures = null;
5779 }
5780 this.signatureSchemeVersion = orig.signatureSchemeVersion;
5781 this.publicKeys = new ArraySet<>(orig.publicKeys);
5782 if (orig.pastSigningCertificates != null) {
5783 this.pastSigningCertificates = orig.pastSigningCertificates.clone();
5784 this.pastSigningCertificatesFlags = orig.pastSigningCertificatesFlags.clone();
5785 } else {
5786 this.pastSigningCertificates = null;
5787 this.pastSigningCertificatesFlags = null;
5788 }
5789 } else {
5790 this.signatures = null;
5791 this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
5792 this.publicKeys = null;
5793 this.pastSigningCertificates = null;
5794 this.pastSigningCertificatesFlags = null;
5795 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08005796 }
5797
5798 /** Returns true if the signing details have one or more signatures. */
5799 public boolean hasSignatures() {
5800 return signatures != null && signatures.length > 0;
5801 }
5802
Daniel Cashman5cdda342018-01-19 07:22:52 -08005803 /** Returns true if the signing details have past signing certificates. */
5804 public boolean hasPastSigningCertificates() {
5805 return pastSigningCertificates != null && pastSigningCertificates.length > 0;
5806 }
5807
Dan Cashman1dbe6d02018-01-23 11:18:28 -08005808 /**
5809 * Determines if the provided {@code oldDetails} is an ancestor of or the same as this one.
5810 * If the {@code oldDetails} signing certificate appears in our pastSigningCertificates,
5811 * then that means it has authorized a signing certificate rotation, which eventually leads
5812 * to our certificate, and thus can be trusted. If this method evaluates to true, this
5813 * SigningDetails object should be trusted if the previous one is.
5814 */
5815 public boolean hasAncestorOrSelf(SigningDetails oldDetails) {
5816 if (this == UNKNOWN || oldDetails == UNKNOWN) {
5817 return false;
5818 }
5819 if (oldDetails.signatures.length > 1) {
5820
5821 // multiple-signer packages cannot rotate signing certs, so we just compare current
5822 // signers for an exact match
5823 return signaturesMatchExactly(oldDetails);
5824 } else {
5825
5826 // we may have signing certificate rotation history, check to see if the oldDetails
5827 // was one of our old signing certificates
5828 return hasCertificate(oldDetails.signatures[0]);
5829 }
5830 }
5831
5832 /**
5833 * Similar to {@code hasAncestorOrSelf}. Returns true only if this {@code SigningDetails}
5834 * is a descendant of {@code oldDetails}, not if they're the same. This is used to
5835 * determine if this object is newer than the provided one.
5836 */
5837 public boolean hasAncestor(SigningDetails oldDetails) {
5838 if (this == UNKNOWN || oldDetails == UNKNOWN) {
5839 return false;
5840 }
5841 if (this.hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
5842
5843 // the last entry in pastSigningCertificates is the current signer, ignore it
5844 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
5845 if (pastSigningCertificates[i].equals(oldDetails.signatures[i])) {
5846 return true;
5847 }
5848 }
5849 }
5850 return false;
5851 }
5852
5853 /**
5854 * Determines if the provided {@code oldDetails} is an ancestor of this one, and whether or
5855 * not this one grants it the provided capability, represented by the {@code flags}
5856 * parameter. In the event of signing certificate rotation, a package may still interact
5857 * with entities signed by its old signing certificate and not want to break previously
5858 * functioning behavior. The {@code flags} value determines which capabilities the app
5859 * signed by the newer signing certificate would like to continue to give to its previous
5860 * signing certificate(s).
5861 */
5862 public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) {
5863 if (this == UNKNOWN || oldDetails == UNKNOWN) {
5864 return false;
5865 }
5866 if (oldDetails.signatures.length > 1) {
5867
5868 // multiple-signer packages cannot rotate signing certs, so we must have an exact
5869 // match, which also means all capabilities are granted
5870 return signaturesMatchExactly(oldDetails);
5871 } else {
5872
5873 // we may have signing certificate rotation history, check to see if the oldDetails
5874 // was one of our old signing certificates, and if we grant it the capability it's
5875 // requesting
5876 return hasCertificate(oldDetails.signatures[0], flags);
5877 }
5878 }
5879
5880 /**
5881 * A special case of {@code checkCapability} which re-encodes both sets of signing
5882 * certificates to counteract a previous re-encoding.
5883 */
5884 public boolean checkCapabilityRecover(SigningDetails oldDetails,
5885 @CertCapabilities int flags) throws CertificateException {
5886 if (oldDetails == UNKNOWN || this == UNKNOWN) {
5887 return false;
5888 }
5889 if (hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
5890
5891 // signing certificates may have rotated, check entire history for effective match
5892 for (int i = 0; i < pastSigningCertificates.length; i++) {
5893 if (Signature.areEffectiveMatch(
5894 oldDetails.signatures[0],
5895 pastSigningCertificates[i])
5896 && pastSigningCertificatesFlags[i] == flags) {
5897 return true;
5898 }
5899 }
5900 } else {
5901 return Signature.areEffectiveMatch(oldDetails.signatures, signatures);
5902 }
5903 return false;
5904 }
5905
5906 /**
5907 * Determine if {@code signature} is in this SigningDetails' signing certificate history,
5908 * including the current signer. Automatically returns false if this object has multiple
5909 * signing certificates, since rotation is only supported for single-signers; this is
5910 * enforced by {@code hasCertificateInternal}.
5911 */
5912 public boolean hasCertificate(Signature signature) {
5913 return hasCertificateInternal(signature, PAST_CERT_EXISTS);
5914 }
5915
5916 /**
5917 * Determine if {@code signature} is in this SigningDetails' signing certificate history,
5918 * including the current signer, and whether or not it has the given permission.
5919 * Certificates which match our current signer automatically get all capabilities.
5920 * Automatically returns false if this object has multiple signing certificates, since
5921 * rotation is only supported for single-signers.
5922 */
5923 public boolean hasCertificate(Signature signature, @CertCapabilities int flags) {
5924 return hasCertificateInternal(signature, flags);
5925 }
5926
5927 /** Convenient wrapper for calling {@code hasCertificate} with certificate's raw bytes. */
5928 public boolean hasCertificate(byte[] certificate) {
5929 Signature signature = new Signature(certificate);
5930 return hasCertificate(signature);
5931 }
5932
5933 private boolean hasCertificateInternal(Signature signature, int flags) {
5934 if (this == UNKNOWN) {
5935 return false;
5936 }
5937
5938 // only single-signed apps can have pastSigningCertificates
5939 if (hasPastSigningCertificates()) {
5940
5941 // check all past certs, except for the current one, which automatically gets all
5942 // capabilities, since it is the same as the current signature
5943 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
5944 if (pastSigningCertificates[i].equals(signature)) {
5945 if (flags == PAST_CERT_EXISTS
5946 || (flags & pastSigningCertificatesFlags[i]) == flags) {
5947 return true;
5948 }
5949 }
5950 }
5951 }
5952
5953 // not in previous certs signing history, just check the current signer and make sure
5954 // we are singly-signed
5955 return signatures.length == 1 && signatures[0].equals(signature);
5956 }
5957
5958 /**
5959 * Determines if the provided {@code sha256String} is an ancestor of this one, and whether
5960 * or not this one grants it the provided capability, represented by the {@code flags}
5961 * parameter. In the event of signing certificate rotation, a package may still interact
5962 * with entities signed by its old signing certificate and not want to break previously
5963 * functioning behavior. The {@code flags} value determines which capabilities the app
5964 * signed by the newer signing certificate would like to continue to give to its previous
5965 * signing certificate(s).
5966 *
5967 * @param sha256String A hex-encoded representation of a sha256 digest. In the case of an
5968 * app with multiple signers, this represents the hex-encoded sha256
5969 * digest of the combined hex-encoded sha256 digests of each individual
5970 * signing certificate according to {@link
5971 * PackageUtils#computeSignaturesSha256Digest(Signature[])}
5972 */
5973 public boolean checkCapability(String sha256String, @CertCapabilities int flags) {
5974 if (this == UNKNOWN) {
5975 return false;
5976 }
5977
5978 // first see if the hash represents a single-signer in our signing history
5979 byte[] sha256Bytes = ByteStringUtils.fromHexToByteArray(sha256String);
5980 if (hasSha256Certificate(sha256Bytes, flags)) {
5981 return true;
5982 }
5983
5984 // Not in signing history, either represents multiple signatures or not a match.
5985 // Multiple signers can't rotate, so no need to check flags, just see if the SHAs match.
5986 // We already check the single-signer case above as part of hasSha256Certificate, so no
5987 // need to verify we have multiple signers, just run the old check
5988 // just consider current signing certs
5989 final String[] mSignaturesSha256Digests =
5990 PackageUtils.computeSignaturesSha256Digests(signatures);
5991 final String mSignaturesSha256Digest =
5992 PackageUtils.computeSignaturesSha256Digest(mSignaturesSha256Digests);
5993 return mSignaturesSha256Digest.equals(sha256String);
5994 }
5995
5996 /**
5997 * Determine if the {@code sha256Certificate} is in this SigningDetails' signing certificate
5998 * history, including the current signer. Automatically returns false if this object has
5999 * multiple signing certificates, since rotation is only supported for single-signers.
6000 */
6001 public boolean hasSha256Certificate(byte[] sha256Certificate) {
6002 return hasSha256CertificateInternal(sha256Certificate, PAST_CERT_EXISTS);
6003 }
6004
6005 /**
6006 * Determine if the {@code sha256Certificate} certificate hash corresponds to a signing
6007 * certificate in this SigningDetails' signing certificate history, including the current
6008 * signer, and whether or not it has the given permission. Certificates which match our
6009 * current signer automatically get all capabilities. Automatically returns false if this
6010 * object has multiple signing certificates, since rotation is only supported for
6011 * single-signers.
6012 */
6013 public boolean hasSha256Certificate(byte[] sha256Certificate, @CertCapabilities int flags) {
6014 return hasSha256CertificateInternal(sha256Certificate, flags);
6015 }
6016
6017 private boolean hasSha256CertificateInternal(byte[] sha256Certificate, int flags) {
6018 if (this == UNKNOWN) {
6019 return false;
6020 }
6021 if (hasPastSigningCertificates()) {
6022
6023 // check all past certs, except for the last one, which automatically gets all
6024 // capabilities, since it is the same as the current signature, and is checked below
6025 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
6026 byte[] digest = PackageUtils.computeSha256DigestBytes(
6027 pastSigningCertificates[i].toByteArray());
6028 if (Arrays.equals(sha256Certificate, digest)) {
6029 if (flags == PAST_CERT_EXISTS
6030 || (flags & pastSigningCertificatesFlags[i]) == flags) {
6031 return true;
6032 }
6033 }
6034 }
6035 }
6036
6037 // not in previous certs signing history, just check the current signer
6038 if (signatures.length == 1) {
6039 byte[] digest =
6040 PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray());
6041 return Arrays.equals(sha256Certificate, digest);
6042 }
6043 return false;
6044 }
6045
Patrick Baumann47117fc2017-12-19 10:17:21 -08006046 /** Returns true if the signatures in this and other match exactly. */
6047 public boolean signaturesMatchExactly(SigningDetails other) {
6048 return Signature.areExactMatch(this.signatures, other.signatures);
6049 }
6050
6051 @Override
6052 public int describeContents() {
6053 return 0;
6054 }
6055
6056 @Override
6057 public void writeToParcel(Parcel dest, int flags) {
6058 boolean isUnknown = UNKNOWN == this;
6059 dest.writeBoolean(isUnknown);
6060 if (isUnknown) {
6061 return;
6062 }
6063 dest.writeTypedArray(this.signatures, flags);
6064 dest.writeInt(this.signatureSchemeVersion);
6065 dest.writeArraySet(this.publicKeys);
Daniel Cashman77029c52018-01-18 16:19:29 -08006066 dest.writeTypedArray(this.pastSigningCertificates, flags);
6067 dest.writeIntArray(this.pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006068 }
6069
6070 protected SigningDetails(Parcel in) {
6071 final ClassLoader boot = Object.class.getClassLoader();
6072 this.signatures = in.createTypedArray(Signature.CREATOR);
6073 this.signatureSchemeVersion = in.readInt();
6074 this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot);
Daniel Cashman77029c52018-01-18 16:19:29 -08006075 this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR);
6076 this.pastSigningCertificatesFlags = in.createIntArray();
Patrick Baumann47117fc2017-12-19 10:17:21 -08006077 }
6078
6079 public static final Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() {
6080 @Override
6081 public SigningDetails createFromParcel(Parcel source) {
6082 if (source.readBoolean()) {
6083 return UNKNOWN;
6084 }
6085 return new SigningDetails(source);
6086 }
6087
6088 @Override
6089 public SigningDetails[] newArray(int size) {
6090 return new SigningDetails[size];
6091 }
6092 };
6093
6094 @Override
6095 public boolean equals(Object o) {
6096 if (this == o) return true;
6097 if (!(o instanceof SigningDetails)) return false;
6098
6099 SigningDetails that = (SigningDetails) o;
6100
6101 if (signatureSchemeVersion != that.signatureSchemeVersion) return false;
6102 if (!Signature.areExactMatch(signatures, that.signatures)) return false;
Daniel Cashman77029c52018-01-18 16:19:29 -08006103 if (publicKeys != null) {
6104 if (!publicKeys.equals((that.publicKeys))) {
6105 return false;
6106 }
6107 } else if (that.publicKeys != null) {
6108 return false;
6109 }
6110
6111 // can't use Signature.areExactMatch() because order matters with the past signing certs
6112 if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) {
6113 return false;
6114 }
6115 if (!Arrays.equals(pastSigningCertificatesFlags, that.pastSigningCertificatesFlags)) {
6116 return false;
6117 }
6118
6119 return true;
Patrick Baumann47117fc2017-12-19 10:17:21 -08006120 }
6121
6122 @Override
6123 public int hashCode() {
6124 int result = +Arrays.hashCode(signatures);
6125 result = 31 * result + signatureSchemeVersion;
6126 result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0);
Daniel Cashman77029c52018-01-18 16:19:29 -08006127 result = 31 * result + Arrays.hashCode(pastSigningCertificates);
6128 result = 31 * result + Arrays.hashCode(pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08006129 return result;
6130 }
Daniel Cashman77029c52018-01-18 16:19:29 -08006131
6132 /**
6133 * Builder of {@code SigningDetails} instances.
6134 */
6135 public static class Builder {
6136 private Signature[] mSignatures;
6137 private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
6138 private Signature[] mPastSigningCertificates;
6139 private int[] mPastSigningCertificatesFlags;
6140
6141 public Builder() {
6142 }
6143
6144 /** get signing certificates used to sign the current APK */
6145 public Builder setSignatures(Signature[] signatures) {
6146 mSignatures = signatures;
6147 return this;
6148 }
6149
6150 /** set the signature scheme version used to sign the APK */
6151 public Builder setSignatureSchemeVersion(int signatureSchemeVersion) {
6152 mSignatureSchemeVersion = signatureSchemeVersion;
6153 return this;
6154 }
6155
6156 /** set the signing certificates by which the APK proved it can be authenticated */
6157 public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
6158 mPastSigningCertificates = pastSigningCertificates;
6159 return this;
6160 }
6161
6162 /** set the flags for the {@code pastSigningCertificates} */
6163 public Builder setPastSigningCertificatesFlags(int[] pastSigningCertificatesFlags) {
6164 mPastSigningCertificatesFlags = pastSigningCertificatesFlags;
6165 return this;
6166 }
6167
6168 private void checkInvariants() {
6169 // must have signatures and scheme version set
6170 if (mSignatures == null) {
6171 throw new IllegalStateException("SigningDetails requires the current signing"
6172 + " certificates.");
6173 }
6174
6175 // pastSigningCerts and flags must match up
6176 boolean pastMismatch = false;
6177 if (mPastSigningCertificates != null && mPastSigningCertificatesFlags != null) {
6178 if (mPastSigningCertificates.length != mPastSigningCertificatesFlags.length) {
6179 pastMismatch = true;
6180 }
6181 } else if (!(mPastSigningCertificates == null
6182 && mPastSigningCertificatesFlags == null)) {
6183 pastMismatch = true;
6184 }
6185 if (pastMismatch) {
6186 throw new IllegalStateException("SigningDetails must have a one to one mapping "
6187 + "between pastSigningCertificates and pastSigningCertificatesFlags");
6188 }
6189 }
6190 /** build a {@code SigningDetails} object */
6191 public SigningDetails build()
6192 throws CertificateException {
6193 checkInvariants();
6194 return new SigningDetails(mSignatures, mSignatureSchemeVersion,
6195 mPastSigningCertificates, mPastSigningCertificatesFlags);
6196 }
6197 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08006198 }
6199
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006200 /**
6201 * Representation of a full package parsed from APK files on disk. A package
6202 * consists of a single base APK, and zero or more split APKs.
6203 */
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006204 public final static class Package implements Parcelable {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006205
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006206 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006207
Svet Ganov67882122016-12-11 16:36:34 -08006208 // The package name declared in the manifest as the package can be
6209 // renamed, for example static shared libs use synthetic package names.
6210 public String manifestPackageName;
6211
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006212 /** Names of any split APKs, ordered by parsed splitName */
6213 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006214
6215 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07006216
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07006217 public String volumeUuid;
6218
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006219 /**
6220 * Path where this package was found on disk. For monolithic packages
6221 * this is path to single base APK file; for cluster packages this is
6222 * path to the cluster directory.
6223 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006224 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006225
6226 /** Path of base APK */
6227 public String baseCodePath;
6228 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006229 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006230
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006231 /** Revision code of base APK */
6232 public int baseRevisionCode;
6233 /** Revision codes of any split APKs, ordered by parsed splitName */
6234 public int[] splitRevisionCodes;
6235
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006236 /** Flags of any split APKs; ordered by parsed splitName */
6237 public int[] splitFlags;
6238
Alex Klyubinb9f8a522015-02-03 11:12:59 -08006239 /**
6240 * Private flags of any split APKs; ordered by parsed splitName.
6241 *
6242 * {@hide}
6243 */
6244 public int[] splitPrivateFlags;
6245
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006246 public boolean baseHardwareAccelerated;
6247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006248 // For now we only support one application per package.
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006249 public ApplicationInfo applicationInfo = new ApplicationInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006250
6251 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
6252 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
6253 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
6254 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
6255 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
6256 public final ArrayList<Service> services = new ArrayList<Service>(0);
6257 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
6258
6259 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
6260
Dianne Hackborn854060af2009-07-09 18:14:31 -07006261 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006262
Svet Ganov354cd3c2015-12-17 11:35:04 -08006263 public Package parentPackage;
6264 public ArrayList<Package> childPackages;
6265
Svet Ganov67882122016-12-11 16:36:34 -08006266 public String staticSharedLibName = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006267 public long staticSharedLibVersion = 0;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006268 public ArrayList<String> libraryNames = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07006269 public ArrayList<String> usesLibraries = null;
Svet Ganov67882122016-12-11 16:36:34 -08006270 public ArrayList<String> usesStaticLibraries = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006271 public long[] usesStaticLibrariesVersions = null;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006272 public String[][] usesStaticLibrariesCertDigests = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07006273 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006274 public String[] usesLibraryFiles = null;
6275
Dianne Hackbornb09491f2013-07-22 15:30:11 -07006276 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
6277
Dianne Hackbornc1552392010-03-03 16:19:01 -08006278 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006279 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006280 public ArrayList<String> mAdoptPermissions = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006282 // We store the application meta-data independently to avoid multiple unwanted references
6283 public Bundle mAppMetaData = null;
6284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006285 // The version code declared for this package.
6286 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006287
Dianne Hackborn3accca02013-09-20 09:32:11 -07006288 // The major version code declared for this package.
6289 public int mVersionCodeMajor;
6290
6291 // Return long containing mVersionCode and mVersionCodeMajor.
6292 public long getLongVersionCode() {
6293 return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
6294 }
6295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006296 // The version name declared for this package.
6297 public String mVersionName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006299 // The shared user id that this package wants to use.
6300 public String mSharedUserId;
6301
6302 // The shared user label that this package wants to use.
6303 public int mSharedUserLabel;
6304
6305 // Signatures that were read from the package.
Patrick Baumann47117fc2017-12-19 10:17:21 -08006306 @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006307
6308 // For use by package manager service for quick lookup of
6309 // preferred up order.
6310 public int mPreferredOrder = 0;
6311
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006312 // For use by package manager to keep track of when a package was last used.
Brian Carlstromca82e612016-04-19 23:16:08 -07006313 public long[] mLastPackageUsageTimeInMills =
6314 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006315
Amith Yamasani13593602012-03-22 16:16:17 -07006316 // // User set enabled state.
6317 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
6318 //
6319 // // Whether the package has been stopped.
6320 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08006321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006322 // Additional data supplied by callers.
6323 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07006324
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006325 // Applications hardware preferences
6326 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006327
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006328 // Applications requested features
Dianne Hackborn49237342009-08-27 20:08:01 -07006329 public ArrayList<FeatureInfo> reqFeatures = null;
6330
Adam Lesinskid3edfde2014-08-08 17:32:44 -07006331 // Applications requested feature groups
6332 public ArrayList<FeatureGroupInfo> featureGroups = null;
6333
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08006334 public int installLocation;
6335
Jeff Hao272bf3a2014-10-08 13:34:43 -07006336 public boolean coreApp;
6337
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08006338 /* An app that's required for all users and cannot be uninstalled for a user */
6339 public boolean mRequiredForAllUsers;
6340
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006341 /* The restricted account authenticator type that is used by this application */
6342 public String mRestrictedAccountType;
6343
Amith Yamasaniccbe3892013-04-12 17:52:42 -07006344 /* The required account type without which this application will not function */
6345 public String mRequiredAccountType;
6346
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006347 public String mOverlayTarget;
Adrian Roosc84df772018-01-19 21:20:22 +01006348 public String mOverlayCategory;
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006349 public int mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -08006350 public boolean mOverlayIsStatic;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006351
Alan Viveretteb6a25732017-11-21 14:49:24 -05006352 public int mCompileSdkVersion;
6353 public String mCompileSdkVersionCodename;
6354
Geremy Condraf1bcca82013-01-07 22:35:24 -08006355 /**
dcashman989eb3712014-06-17 12:56:12 -07006356 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08006357 */
dcashman989eb3712014-06-17 12:56:12 -07006358 public ArraySet<String> mUpgradeKeySets;
6359 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08006360
Narayan Kamath4903f642014-08-11 13:33:45 +01006361 /**
6362 * The install time abi override for this package, if any.
6363 *
6364 * TODO: This seems like a horrible place to put the abiOverride because
6365 * this isn't something the packageParser parsers. However, this fits in with
6366 * the rest of the PackageManager where package scanning randomly pushes
6367 * and prods fields out of {@code this.applicationInfo}.
6368 */
6369 public String cpuAbiOverride;
Selim Gurun2d291d82016-02-05 17:50:53 -08006370 /**
6371 * The install time abi override to choose 32bit abi's when multiple abi's
6372 * are present. This is only meaningfull for multiarch applications.
6373 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
6374 */
6375 public boolean use32bitAbi;
Narayan Kamath4903f642014-08-11 13:33:45 +01006376
Todd Kennedyfdd241a2016-04-28 12:26:53 -07006377 public byte[] restrictUpdateHash;
6378
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006379 /** Set if the app or any of its components are visible to instant applications. */
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006380 public boolean visibleToInstantApps;
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006381 /** Whether or not the package is a stub and must be replaced by the full version. */
6382 public boolean isStub;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006383
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006384 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006385 this.packageName = packageName;
Svet Ganov67882122016-12-11 16:36:34 -08006386 this.manifestPackageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006387 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006388 applicationInfo.uid = -1;
6389 }
6390
Svet Ganov354cd3c2015-12-17 11:35:04 -08006391 public void setApplicationVolumeUuid(String volumeUuid) {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006392 final UUID storageUuid = StorageManager.convert(volumeUuid);
Svet Ganov354cd3c2015-12-17 11:35:04 -08006393 this.applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006394 this.applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006395 if (childPackages != null) {
6396 final int packageCount = childPackages.size();
6397 for (int i = 0; i < packageCount; i++) {
6398 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006399 childPackages.get(i).applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006400 }
6401 }
6402 }
6403
6404 public void setApplicationInfoCodePath(String codePath) {
6405 this.applicationInfo.setCodePath(codePath);
6406 if (childPackages != null) {
6407 final int packageCount = childPackages.size();
6408 for (int i = 0; i < packageCount; i++) {
6409 childPackages.get(i).applicationInfo.setCodePath(codePath);
6410 }
6411 }
6412 }
6413
Todd Kennedy30a23a52018-01-04 13:27:49 -08006414 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6415 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006416 public void setApplicationInfoResourcePath(String resourcePath) {
6417 this.applicationInfo.setResourcePath(resourcePath);
6418 if (childPackages != null) {
6419 final int packageCount = childPackages.size();
6420 for (int i = 0; i < packageCount; i++) {
6421 childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
6422 }
6423 }
6424 }
6425
Todd Kennedy30a23a52018-01-04 13:27:49 -08006426 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6427 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006428 public void setApplicationInfoBaseResourcePath(String resourcePath) {
6429 this.applicationInfo.setBaseResourcePath(resourcePath);
6430 if (childPackages != null) {
6431 final int packageCount = childPackages.size();
6432 for (int i = 0; i < packageCount; i++) {
6433 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
6434 }
6435 }
6436 }
6437
6438 public void setApplicationInfoBaseCodePath(String baseCodePath) {
6439 this.applicationInfo.setBaseCodePath(baseCodePath);
6440 if (childPackages != null) {
6441 final int packageCount = childPackages.size();
6442 for (int i = 0; i < packageCount; i++) {
6443 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
6444 }
6445 }
6446 }
6447
Todd Kennedy13715d52016-08-01 13:38:57 -07006448 public List<String> getChildPackageNames() {
6449 if (childPackages == null) {
6450 return null;
6451 }
6452 final int childCount = childPackages.size();
6453 final List<String> childPackageNames = new ArrayList<>(childCount);
6454 for (int i = 0; i < childCount; i++) {
6455 String childPackageName = childPackages.get(i).packageName;
6456 childPackageNames.add(childPackageName);
6457 }
6458 return childPackageNames;
6459 }
6460
Svet Ganov354cd3c2015-12-17 11:35:04 -08006461 public boolean hasChildPackage(String packageName) {
6462 final int childCount = (childPackages != null) ? childPackages.size() : 0;
6463 for (int i = 0; i < childCount; i++) {
6464 if (childPackages.get(i).packageName.equals(packageName)) {
6465 return true;
6466 }
6467 }
6468 return false;
6469 }
6470
6471 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
6472 this.applicationInfo.setSplitCodePaths(splitCodePaths);
6473 // Children have no splits
6474 }
6475
Todd Kennedy30a23a52018-01-04 13:27:49 -08006476 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6477 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006478 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
6479 this.applicationInfo.setSplitResourcePaths(resroucePaths);
6480 // Children have no splits
6481 }
6482
6483 public void setSplitCodePaths(String[] codePaths) {
6484 this.splitCodePaths = codePaths;
6485 }
6486
6487 public void setCodePath(String codePath) {
6488 this.codePath = codePath;
6489 if (childPackages != null) {
6490 final int packageCount = childPackages.size();
6491 for (int i = 0; i < packageCount; i++) {
6492 childPackages.get(i).codePath = codePath;
6493 }
6494 }
6495 }
6496
6497 public void setBaseCodePath(String baseCodePath) {
6498 this.baseCodePath = baseCodePath;
6499 if (childPackages != null) {
6500 final int packageCount = childPackages.size();
6501 for (int i = 0; i < packageCount; i++) {
6502 childPackages.get(i).baseCodePath = baseCodePath;
6503 }
6504 }
6505 }
6506
Patrick Baumann47117fc2017-12-19 10:17:21 -08006507 /** Sets signing details on the package and any of its children. */
6508 public void setSigningDetails(@NonNull SigningDetails signingDetails) {
6509 mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006510 if (childPackages != null) {
6511 final int packageCount = childPackages.size();
6512 for (int i = 0; i < packageCount; i++) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08006513 childPackages.get(i).mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006514 }
6515 }
6516 }
6517
6518 public void setVolumeUuid(String volumeUuid) {
6519 this.volumeUuid = volumeUuid;
6520 if (childPackages != null) {
6521 final int packageCount = childPackages.size();
6522 for (int i = 0; i < packageCount; i++) {
6523 childPackages.get(i).volumeUuid = volumeUuid;
6524 }
6525 }
6526 }
6527
6528 public void setApplicationInfoFlags(int mask, int flags) {
6529 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
6530 if (childPackages != null) {
6531 final int packageCount = childPackages.size();
6532 for (int i = 0; i < packageCount; i++) {
6533 childPackages.get(i).applicationInfo.flags =
6534 (applicationInfo.flags & ~mask) | (mask & flags);
6535 }
6536 }
6537 }
6538
Selim Gurun75827b22016-02-09 10:55:33 -08006539 public void setUse32bitAbi(boolean use32bitAbi) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006540 this.use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006541 if (childPackages != null) {
6542 final int packageCount = childPackages.size();
6543 for (int i = 0; i < packageCount; i++) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006544 childPackages.get(i).use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006545 }
6546 }
6547 }
6548
Svetoslav Ganov40610e32017-06-20 19:35:51 -07006549 public boolean isLibrary() {
6550 return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
6551 }
6552
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006553 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07006554 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006555 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07006556 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6557 Collections.addAll(paths, splitCodePaths);
6558 }
6559 return paths;
6560 }
6561
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006562 /**
6563 * Filtered set of {@link #getAllCodePaths()} that excludes
6564 * resource-only APKs.
6565 */
6566 public List<String> getAllCodePathsExcludingResourceOnly() {
6567 ArrayList<String> paths = new ArrayList<>();
6568 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6569 paths.add(baseCodePath);
6570 }
6571 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6572 for (int i = 0; i < splitCodePaths.length; i++) {
6573 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6574 paths.add(splitCodePaths[i]);
6575 }
6576 }
6577 }
6578 return paths;
6579 }
6580
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006581 public void setPackageName(String newName) {
6582 packageName = newName;
6583 applicationInfo.packageName = newName;
6584 for (int i=permissions.size()-1; i>=0; i--) {
6585 permissions.get(i).setPackageName(newName);
6586 }
6587 for (int i=permissionGroups.size()-1; i>=0; i--) {
6588 permissionGroups.get(i).setPackageName(newName);
6589 }
6590 for (int i=activities.size()-1; i>=0; i--) {
6591 activities.get(i).setPackageName(newName);
6592 }
6593 for (int i=receivers.size()-1; i>=0; i--) {
6594 receivers.get(i).setPackageName(newName);
6595 }
6596 for (int i=providers.size()-1; i>=0; i--) {
6597 providers.get(i).setPackageName(newName);
6598 }
6599 for (int i=services.size()-1; i>=0; i--) {
6600 services.get(i).setPackageName(newName);
6601 }
6602 for (int i=instrumentation.size()-1; i>=0; i--) {
6603 instrumentation.get(i).setPackageName(newName);
6604 }
6605 }
Dianne Hackborn65696252012-03-05 18:49:21 -08006606
6607 public boolean hasComponentClassName(String name) {
6608 for (int i=activities.size()-1; i>=0; i--) {
6609 if (name.equals(activities.get(i).className)) {
6610 return true;
6611 }
6612 }
6613 for (int i=receivers.size()-1; i>=0; i--) {
6614 if (name.equals(receivers.get(i).className)) {
6615 return true;
6616 }
6617 }
6618 for (int i=providers.size()-1; i>=0; i--) {
6619 if (name.equals(providers.get(i).className)) {
6620 return true;
6621 }
6622 }
6623 for (int i=services.size()-1; i>=0; i--) {
6624 if (name.equals(services.get(i).className)) {
6625 return true;
6626 }
6627 }
6628 for (int i=instrumentation.size()-1; i>=0; i--) {
6629 if (name.equals(instrumentation.get(i).className)) {
6630 return true;
6631 }
6632 }
6633 return false;
6634 }
6635
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006636 /** @hide */
6637 public boolean isExternal() {
6638 return applicationInfo.isExternal();
6639 }
6640
6641 /** @hide */
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08006642 public boolean isForwardLocked() {
6643 return applicationInfo.isForwardLocked();
6644 }
6645
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006646 /** @hide */
6647 public boolean isOem() {
6648 return applicationInfo.isOem();
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006649 }
6650
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006651 /** @hide */
Jiyong Park002fdbd2017-02-13 20:50:31 +09006652 public boolean isVendor() {
6653 return applicationInfo.isVendor();
6654 }
6655
6656 /** @hide */
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09006657 public boolean isProduct() {
6658 return applicationInfo.isProduct();
6659 }
6660
6661 /** @hide */
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006662 public boolean isPrivileged() {
Svet Ganovadc1cf42015-06-15 16:36:24 -07006663 return applicationInfo.isPrivilegedApp();
6664 }
6665
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006666 /** @hide */
6667 public boolean isSystem() {
6668 return applicationInfo.isSystemApp();
6669 }
6670
6671 /** @hide */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006672 public boolean isUpdatedSystemApp() {
6673 return applicationInfo.isUpdatedSystemApp();
6674 }
6675
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006676 /** @hide */
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006677 public boolean canHaveOatDir() {
6678 // The following app types CANNOT have oat directory
6679 // - non-updated system apps
6680 // - forward-locked apps or apps installed in ASEC containers
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006681 return (!isSystem() || isUpdatedSystemApp())
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006682 && !isForwardLocked() && !applicationInfo.isExternalAsec();
6683 }
6684
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006685 public boolean isMatch(int flags) {
6686 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006687 return isSystem();
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006688 }
6689 return true;
6690 }
6691
Brian Carlstromca82e612016-04-19 23:16:08 -07006692 public long getLatestPackageUseTimeInMills() {
6693 long latestUse = 0L;
6694 for (long use : mLastPackageUsageTimeInMills) {
6695 latestUse = Math.max(latestUse, use);
6696 }
6697 return latestUse;
6698 }
6699
David Brazdil90e26992016-04-18 14:08:52 +01006700 public long getLatestForegroundPackageUseTimeInMills() {
6701 int[] foregroundReasons = {
6702 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
6703 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
6704 };
6705
6706 long latestUse = 0L;
6707 for (int reason : foregroundReasons) {
6708 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
6709 }
6710 return latestUse;
6711 }
6712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006713 public String toString() {
6714 return "Package{"
6715 + Integer.toHexString(System.identityHashCode(this))
6716 + " " + packageName + "}";
6717 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006718
6719 @Override
6720 public int describeContents() {
6721 return 0;
6722 }
6723
6724 public Package(Parcel dest) {
6725 // We use the boot classloader for all classes that we load.
6726 final ClassLoader boot = Object.class.getClassLoader();
6727
Narayan Kamath07ac1442017-02-10 15:08:07 +00006728 packageName = dest.readString().intern();
Svet Ganov67882122016-12-11 16:36:34 -08006729 manifestPackageName = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006730 splitNames = dest.readStringArray();
6731 volumeUuid = dest.readString();
6732 codePath = dest.readString();
6733 baseCodePath = dest.readString();
6734 splitCodePaths = dest.readStringArray();
6735 baseRevisionCode = dest.readInt();
6736 splitRevisionCodes = dest.createIntArray();
6737 splitFlags = dest.createIntArray();
6738 splitPrivateFlags = dest.createIntArray();
6739 baseHardwareAccelerated = (dest.readInt() == 1);
6740 applicationInfo = dest.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006741 if (applicationInfo.permission != null) {
6742 applicationInfo.permission = applicationInfo.permission.intern();
6743 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006744
6745 // We don't serialize the "owner" package and the application info object for each of
6746 // these components, in order to save space and to avoid circular dependencies while
6747 // serialization. We need to fix them all up here.
6748 dest.readParcelableList(permissions, boot);
6749 fixupOwner(permissions);
6750 dest.readParcelableList(permissionGroups, boot);
6751 fixupOwner(permissionGroups);
6752 dest.readParcelableList(activities, boot);
6753 fixupOwner(activities);
6754 dest.readParcelableList(receivers, boot);
6755 fixupOwner(receivers);
6756 dest.readParcelableList(providers, boot);
6757 fixupOwner(providers);
6758 dest.readParcelableList(services, boot);
6759 fixupOwner(services);
6760 dest.readParcelableList(instrumentation, boot);
6761 fixupOwner(instrumentation);
6762
6763 dest.readStringList(requestedPermissions);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006764 internStringArrayList(requestedPermissions);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006765 protectedBroadcasts = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006766 internStringArrayList(protectedBroadcasts);
6767
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006768 parentPackage = dest.readParcelable(boot);
6769
6770 childPackages = new ArrayList<>();
6771 dest.readParcelableList(childPackages, boot);
6772 if (childPackages.size() == 0) {
6773 childPackages = null;
6774 }
6775
Svet Ganov67882122016-12-11 16:36:34 -08006776 staticSharedLibName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006777 if (staticSharedLibName != null) {
6778 staticSharedLibName = staticSharedLibName.intern();
6779 }
Dianne Hackborn3accca02013-09-20 09:32:11 -07006780 staticSharedLibVersion = dest.readLong();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006781 libraryNames = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006782 internStringArrayList(libraryNames);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006783 usesLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006784 internStringArrayList(usesLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006785 usesOptionalLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006786 internStringArrayList(usesOptionalLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006787 usesLibraryFiles = dest.readStringArray();
6788
Svet Ganov67882122016-12-11 16:36:34 -08006789 final int libCount = dest.readInt();
6790 if (libCount > 0) {
6791 usesStaticLibraries = new ArrayList<>(libCount);
6792 dest.readStringList(usesStaticLibraries);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006793 internStringArrayList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006794 usesStaticLibrariesVersions = new long[libCount];
6795 dest.readLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006796 usesStaticLibrariesCertDigests = new String[libCount][];
6797 for (int i = 0; i < libCount; i++) {
6798 usesStaticLibrariesCertDigests[i] = dest.createStringArray();
6799 }
Svet Ganov67882122016-12-11 16:36:34 -08006800 }
6801
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006802 preferredActivityFilters = new ArrayList<>();
6803 dest.readParcelableList(preferredActivityFilters, boot);
6804 if (preferredActivityFilters.size() == 0) {
6805 preferredActivityFilters = null;
6806 }
6807
6808 mOriginalPackages = dest.createStringArrayList();
6809 mRealPackage = dest.readString();
6810 mAdoptPermissions = dest.createStringArrayList();
6811 mAppMetaData = dest.readBundle();
6812 mVersionCode = dest.readInt();
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08006813 mVersionCodeMajor = dest.readInt();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006814 mVersionName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006815 if (mVersionName != null) {
6816 mVersionName = mVersionName.intern();
6817 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006818 mSharedUserId = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006819 if (mSharedUserId != null) {
6820 mSharedUserId = mSharedUserId.intern();
6821 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006822 mSharedUserLabel = dest.readInt();
6823
Patrick Baumann47117fc2017-12-19 10:17:21 -08006824 mSigningDetails = dest.readParcelable(boot);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006825
6826 mPreferredOrder = dest.readInt();
6827
6828 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6829 // is parsed from the APK.
6830
6831 // Object mExtras is not persisted because it is not information that is read from
6832 // the APK, rather, it is supplied by callers.
6833
6834
6835 configPreferences = new ArrayList<>();
6836 dest.readParcelableList(configPreferences, boot);
6837 if (configPreferences.size() == 0) {
6838 configPreferences = null;
6839 }
6840
6841 reqFeatures = new ArrayList<>();
6842 dest.readParcelableList(reqFeatures, boot);
6843 if (reqFeatures.size() == 0) {
6844 reqFeatures = null;
6845 }
6846
6847 featureGroups = new ArrayList<>();
6848 dest.readParcelableList(featureGroups, boot);
6849 if (featureGroups.size() == 0) {
6850 featureGroups = null;
6851 }
6852
6853 installLocation = dest.readInt();
6854 coreApp = (dest.readInt() == 1);
6855 mRequiredForAllUsers = (dest.readInt() == 1);
6856 mRestrictedAccountType = dest.readString();
6857 mRequiredAccountType = dest.readString();
6858 mOverlayTarget = dest.readString();
Adrian Roosc84df772018-01-19 21:20:22 +01006859 mOverlayCategory = dest.readString();
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006860 mOverlayPriority = dest.readInt();
Adam Lesinskie7334972018-01-17 16:13:52 -08006861 mOverlayIsStatic = (dest.readInt() == 1);
Alan Viveretteb6a25732017-11-21 14:49:24 -05006862 mCompileSdkVersion = dest.readInt();
6863 mCompileSdkVersionCodename = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006864 mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
6865
6866 mKeySetMapping = readKeySetMapping(dest);
6867
6868 cpuAbiOverride = dest.readString();
6869 use32bitAbi = (dest.readInt() == 1);
6870 restrictUpdateHash = dest.createByteArray();
Chad Brubaker49f24c62017-04-05 13:08:21 -07006871 visibleToInstantApps = dest.readInt() == 1;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006872 }
6873
Narayan Kamath07ac1442017-02-10 15:08:07 +00006874 private static void internStringArrayList(List<String> list) {
6875 if (list != null) {
6876 final int N = list.size();
6877 for (int i = 0; i < N; ++i) {
6878 list.set(i, list.get(i).intern());
6879 }
6880 }
6881 }
6882
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006883 /**
6884 * Sets the package owner and the the {@code applicationInfo} for every component
6885 * owner by this package.
6886 */
6887 private void fixupOwner(List<? extends Component<?>> list) {
6888 if (list != null) {
6889 for (Component<?> c : list) {
6890 c.owner = this;
6891 if (c instanceof Activity) {
6892 ((Activity) c).info.applicationInfo = this.applicationInfo;
6893 } else if (c instanceof Service) {
6894 ((Service) c).info.applicationInfo = this.applicationInfo;
6895 } else if (c instanceof Provider) {
6896 ((Provider) c).info.applicationInfo = this.applicationInfo;
6897 }
6898 }
6899 }
6900 }
6901
6902 @Override
6903 public void writeToParcel(Parcel dest, int flags) {
6904 dest.writeString(packageName);
Svet Ganov67882122016-12-11 16:36:34 -08006905 dest.writeString(manifestPackageName);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006906 dest.writeStringArray(splitNames);
6907 dest.writeString(volumeUuid);
6908 dest.writeString(codePath);
6909 dest.writeString(baseCodePath);
6910 dest.writeStringArray(splitCodePaths);
6911 dest.writeInt(baseRevisionCode);
6912 dest.writeIntArray(splitRevisionCodes);
6913 dest.writeIntArray(splitFlags);
6914 dest.writeIntArray(splitPrivateFlags);
6915 dest.writeInt(baseHardwareAccelerated ? 1 : 0);
6916 dest.writeParcelable(applicationInfo, flags);
6917
6918 dest.writeParcelableList(permissions, flags);
6919 dest.writeParcelableList(permissionGroups, flags);
6920 dest.writeParcelableList(activities, flags);
6921 dest.writeParcelableList(receivers, flags);
6922 dest.writeParcelableList(providers, flags);
6923 dest.writeParcelableList(services, flags);
6924 dest.writeParcelableList(instrumentation, flags);
6925
6926 dest.writeStringList(requestedPermissions);
6927 dest.writeStringList(protectedBroadcasts);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07006928
6929 // TODO: This doesn't work: b/64295061
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006930 dest.writeParcelable(parentPackage, flags);
6931 dest.writeParcelableList(childPackages, flags);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07006932
Svet Ganov67882122016-12-11 16:36:34 -08006933 dest.writeString(staticSharedLibName);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006934 dest.writeLong(staticSharedLibVersion);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006935 dest.writeStringList(libraryNames);
6936 dest.writeStringList(usesLibraries);
6937 dest.writeStringList(usesOptionalLibraries);
6938 dest.writeStringArray(usesLibraryFiles);
6939
Svet Ganov67882122016-12-11 16:36:34 -08006940 if (ArrayUtils.isEmpty(usesStaticLibraries)) {
6941 dest.writeInt(-1);
6942 } else {
6943 dest.writeInt(usesStaticLibraries.size());
6944 dest.writeStringList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006945 dest.writeLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006946 for (String[] usesStaticLibrariesCertDigest : usesStaticLibrariesCertDigests) {
6947 dest.writeStringArray(usesStaticLibrariesCertDigest);
6948 }
Svet Ganov67882122016-12-11 16:36:34 -08006949 }
6950
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006951 dest.writeParcelableList(preferredActivityFilters, flags);
6952
6953 dest.writeStringList(mOriginalPackages);
6954 dest.writeString(mRealPackage);
6955 dest.writeStringList(mAdoptPermissions);
6956 dest.writeBundle(mAppMetaData);
6957 dest.writeInt(mVersionCode);
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08006958 dest.writeInt(mVersionCodeMajor);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006959 dest.writeString(mVersionName);
6960 dest.writeString(mSharedUserId);
6961 dest.writeInt(mSharedUserLabel);
6962
Patrick Baumann47117fc2017-12-19 10:17:21 -08006963 dest.writeParcelable(mSigningDetails, flags);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006964
6965 dest.writeInt(mPreferredOrder);
6966
6967 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6968 // is parsed from the APK.
6969
6970 // Object mExtras is not persisted because it is not information that is read from
6971 // the APK, rather, it is supplied by callers.
6972
6973 dest.writeParcelableList(configPreferences, flags);
6974 dest.writeParcelableList(reqFeatures, flags);
6975 dest.writeParcelableList(featureGroups, flags);
6976
6977 dest.writeInt(installLocation);
6978 dest.writeInt(coreApp ? 1 : 0);
6979 dest.writeInt(mRequiredForAllUsers ? 1 : 0);
6980 dest.writeString(mRestrictedAccountType);
6981 dest.writeString(mRequiredAccountType);
6982 dest.writeString(mOverlayTarget);
Adrian Roosc84df772018-01-19 21:20:22 +01006983 dest.writeString(mOverlayCategory);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006984 dest.writeInt(mOverlayPriority);
Adam Lesinskie7334972018-01-17 16:13:52 -08006985 dest.writeInt(mOverlayIsStatic ? 1 : 0);
Alan Viveretteb6a25732017-11-21 14:49:24 -05006986 dest.writeInt(mCompileSdkVersion);
6987 dest.writeString(mCompileSdkVersionCodename);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006988 dest.writeArraySet(mUpgradeKeySets);
6989 writeKeySetMapping(dest, mKeySetMapping);
6990 dest.writeString(cpuAbiOverride);
6991 dest.writeInt(use32bitAbi ? 1 : 0);
6992 dest.writeByteArray(restrictUpdateHash);
Chad Brubaker49f24c62017-04-05 13:08:21 -07006993 dest.writeInt(visibleToInstantApps ? 1 : 0);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006994 }
6995
6996
6997 /**
6998 * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
6999 */
7000 private static void writeKeySetMapping(
7001 Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
7002 if (keySetMapping == null) {
7003 dest.writeInt(-1);
7004 return;
7005 }
7006
7007 final int N = keySetMapping.size();
7008 dest.writeInt(N);
7009
7010 for (int i = 0; i < N; i++) {
7011 dest.writeString(keySetMapping.keyAt(i));
7012 ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
7013 if (keys == null) {
7014 dest.writeInt(-1);
7015 continue;
7016 }
7017
7018 final int M = keys.size();
7019 dest.writeInt(M);
7020 for (int j = 0; j < M; j++) {
7021 dest.writeSerializable(keys.valueAt(j));
7022 }
7023 }
7024 }
7025
7026 /**
7027 * Reads a keyset mapping from the given parcel at the given data position. May return
7028 * {@code null} if the serialized mapping was {@code null}.
7029 */
7030 private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
7031 final int N = in.readInt();
7032 if (N == -1) {
7033 return null;
7034 }
7035
7036 ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
7037 for (int i = 0; i < N; ++i) {
7038 String key = in.readString();
7039 final int M = in.readInt();
7040 if (M == -1) {
7041 keySetMapping.put(key, null);
7042 continue;
7043 }
7044
7045 ArraySet<PublicKey> keys = new ArraySet<>(M);
7046 for (int j = 0; j < M; ++j) {
7047 PublicKey pk = (PublicKey) in.readSerializable();
7048 keys.add(pk);
7049 }
7050
7051 keySetMapping.put(key, keys);
7052 }
7053
7054 return keySetMapping;
7055 }
7056
7057 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
7058 public Package createFromParcel(Parcel in) {
7059 return new Package(in);
7060 }
7061
7062 public Package[] newArray(int size) {
7063 return new Package[size];
7064 }
7065 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007066 }
7067
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007068 public static abstract class Component<II extends IntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007069 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007070 public final String className;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007072 public Bundle metaData;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007073 public Package owner;
Todd Kennedy6d418b62018-02-22 14:15:18 -08007074 /** The order of this component in relation to its peers */
7075 public int order;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007076
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007077 ComponentName componentName;
7078 String componentShortName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007080 public Component(Package _owner) {
7081 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007082 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007083 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007084 }
7085
7086 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
7087 owner = args.owner;
7088 intents = new ArrayList<II>(0);
Todd Kennedybb8a42d2016-06-02 14:13:56 -07007089 if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
7090 true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
7091 args.roundIconRes, args.logoRes, args.bannerRes)) {
7092 className = outInfo.name;
7093 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007094 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007095 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007096 }
7097
7098 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
7099 this(args, (PackageItemInfo)outInfo);
7100 if (args.outError[0] != null) {
7101 return;
7102 }
7103
7104 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007105 CharSequence pname;
7106 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07007107 pname = args.sa.getNonConfigurationString(args.processRes,
7108 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007109 } else {
7110 // Some older apps have been seen to use a resource reference
7111 // here that on older builds was ignored (with a warning). We
7112 // need to continue to do this for them so they don't break.
7113 pname = args.sa.getNonResourceString(args.processRes);
7114 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007115 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07007116 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007117 args.flags, args.sepProcesses, args.outError);
7118 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007119
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08007120 if (args.descriptionRes != 0) {
7121 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
7122 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007123
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007124 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007125 }
7126
7127 public Component(Component<II> clone) {
7128 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007129 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007130 className = clone.className;
7131 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007132 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007133 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007134
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007135 public ComponentName getComponentName() {
7136 if (componentName != null) {
7137 return componentName;
7138 }
7139 if (className != null) {
7140 componentName = new ComponentName(owner.applicationInfo.packageName,
7141 className);
7142 }
7143 return componentName;
7144 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007145
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007146 protected Component(Parcel in) {
7147 className = in.readString();
7148 metaData = in.readBundle();
7149 intents = createIntentsList(in);
7150
7151 owner = null;
7152 }
7153
7154 protected void writeToParcel(Parcel dest, int flags) {
7155 dest.writeString(className);
7156 dest.writeBundle(metaData);
7157
7158 writeIntentsList(intents, dest, flags);
7159 }
7160
7161 /**
7162 * <p>
7163 * Implementation note: The serialized form for the intent list also contains the name
7164 * of the concrete class that's stored in the list, and assumes that every element of the
7165 * list is of the same type. This is very similar to the original parcelable mechanism.
7166 * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
7167 * and is public API. It also declares Parcelable related methods as final which means
7168 * we can't extend them. The approach of using composition instead of inheritance leads to
7169 * a large set of cascading changes in the PackageManagerService, which seem undesirable.
7170 *
7171 * <p>
7172 * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
7173 * to make sure their owner fields are consistent. See {@code fixupOwner}.
7174 */
7175 private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out,
7176 int flags) {
7177 if (list == null) {
7178 out.writeInt(-1);
7179 return;
7180 }
7181
7182 final int N = list.size();
7183 out.writeInt(N);
7184
7185 // Don't bother writing the component name if the list is empty.
7186 if (N > 0) {
7187 IntentInfo info = list.get(0);
7188 out.writeString(info.getClass().getName());
7189
7190 for (int i = 0; i < N;i++) {
7191 list.get(i).writeIntentInfoToParcel(out, flags);
7192 }
7193 }
7194 }
7195
7196 private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) {
7197 int N = in.readInt();
7198 if (N == -1) {
7199 return null;
7200 }
7201
7202 if (N == 0) {
7203 return new ArrayList<>(0);
7204 }
7205
7206 String componentName = in.readString();
7207 final ArrayList<T> intentsList;
7208 try {
7209 final Class<T> cls = (Class<T>) Class.forName(componentName);
7210 final Constructor<T> cons = cls.getConstructor(Parcel.class);
7211
7212 intentsList = new ArrayList<>(N);
7213 for (int i = 0; i < N; ++i) {
7214 intentsList.add(cons.newInstance(in));
7215 }
7216 } catch (ReflectiveOperationException ree) {
7217 throw new AssertionError("Unable to construct intent list for: " + componentName);
7218 }
7219
7220 return intentsList;
7221 }
7222
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007223 public void appendComponentShortName(StringBuilder sb) {
7224 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007225 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007226
7227 public void printComponentShortName(PrintWriter pw) {
7228 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
7229 }
7230
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007231 public void setPackageName(String packageName) {
7232 componentName = null;
7233 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007234 }
7235 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007236
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007237 public final static class Permission extends Component<IntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007238 public final PermissionInfo info;
7239 public boolean tree;
7240 public PermissionGroup group;
7241
7242 public Permission(Package _owner) {
7243 super(_owner);
7244 info = new PermissionInfo();
7245 }
7246
7247 public Permission(Package _owner, PermissionInfo _info) {
7248 super(_owner);
7249 info = _info;
7250 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007251
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007252 public void setPackageName(String packageName) {
7253 super.setPackageName(packageName);
7254 info.packageName = packageName;
7255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007256
7257 public String toString() {
7258 return "Permission{"
7259 + Integer.toHexString(System.identityHashCode(this))
7260 + " " + info.name + "}";
7261 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007262
7263 @Override
7264 public int describeContents() {
7265 return 0;
7266 }
7267
7268 @Override
7269 public void writeToParcel(Parcel dest, int flags) {
7270 super.writeToParcel(dest, flags);
7271 dest.writeParcelable(info, flags);
7272 dest.writeInt(tree ? 1 : 0);
7273 dest.writeParcelable(group, flags);
7274 }
7275
Todd Kennedyc8423932017-10-05 08:58:36 -07007276 /** @hide */
7277 public boolean isAppOp() {
7278 return info.isAppOp();
7279 }
7280
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007281 private Permission(Parcel in) {
7282 super(in);
7283 final ClassLoader boot = Object.class.getClassLoader();
7284 info = in.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007285 if (info.group != null) {
7286 info.group = info.group.intern();
7287 }
7288
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007289 tree = (in.readInt() == 1);
7290 group = in.readParcelable(boot);
7291 }
7292
7293 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
7294 public Permission createFromParcel(Parcel in) {
7295 return new Permission(in);
7296 }
7297
7298 public Permission[] newArray(int size) {
7299 return new Permission[size];
7300 }
7301 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007302 }
7303
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007304 public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007305 public final PermissionGroupInfo info;
7306
7307 public PermissionGroup(Package _owner) {
7308 super(_owner);
7309 info = new PermissionGroupInfo();
7310 }
7311
7312 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
7313 super(_owner);
7314 info = _info;
7315 }
7316
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007317 public void setPackageName(String packageName) {
7318 super.setPackageName(packageName);
7319 info.packageName = packageName;
7320 }
7321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007322 public String toString() {
7323 return "PermissionGroup{"
7324 + Integer.toHexString(System.identityHashCode(this))
7325 + " " + info.name + "}";
7326 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007327
7328 @Override
7329 public int describeContents() {
7330 return 0;
7331 }
7332
7333 @Override
7334 public void writeToParcel(Parcel dest, int flags) {
7335 super.writeToParcel(dest, flags);
7336 dest.writeParcelable(info, flags);
7337 }
7338
7339 private PermissionGroup(Parcel in) {
7340 super(in);
7341 info = in.readParcelable(Object.class.getClassLoader());
7342 }
7343
7344 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
7345 public PermissionGroup createFromParcel(Parcel in) {
7346 return new PermissionGroup(in);
7347 }
7348
7349 public PermissionGroup[] newArray(int size) {
7350 return new PermissionGroup[size];
7351 }
7352 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007353 }
7354
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007355 private static boolean copyNeeded(int flags, Package p,
7356 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07007357 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007358 // We always need to copy for other users, since we need
7359 // to fix up the uid.
7360 return true;
7361 }
7362 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
7363 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07007364 if (p.applicationInfo.enabled != enabled) {
7365 return true;
7366 }
7367 }
Rubin Xubf67c9c2016-04-20 17:09:38 +01007368 boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
7369 if (state.suspended != suspended) {
7370 return true;
7371 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007372 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007373 return true;
7374 }
7375 if (state.stopped) {
7376 return true;
7377 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007378 if (state.instantApp != p.applicationInfo.isInstantApp()) {
7379 return true;
7380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007381 if ((flags & PackageManager.GET_META_DATA) != 0
7382 && (metaData != null || p.mAppMetaData != null)) {
7383 return true;
7384 }
7385 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7386 && p.usesLibraryFiles != null) {
7387 return true;
7388 }
Svet Ganov67882122016-12-11 16:36:34 -08007389 if (p.staticSharedLibName != null) {
7390 return true;
7391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007392 return false;
7393 }
7394
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007395 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
7396 PackageUserState state) {
7397 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07007398 }
7399
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007400 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
7401 PackageUserState state) {
7402 // CompatibilityMode is global state.
7403 if (!sCompatibilityModeEnabled) {
7404 ai.disableCompatibilityMode();
7405 }
7406 if (state.installed) {
7407 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
7408 } else {
7409 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
7410 }
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00007411 if (state.suspended) {
7412 ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
7413 } else {
7414 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
7415 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007416 if (state.instantApp) {
7417 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
7418 } else {
7419 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
7420 }
Todd Kennedy5eb5a7d2017-08-01 07:42:47 -07007421 if (state.virtualPreload) {
7422 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7423 } else {
7424 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7425 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007426 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007427 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007428 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007429 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007430 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007431 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
7432 ai.enabled = true;
7433 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
7434 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
7435 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
7436 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
7437 ai.enabled = false;
7438 }
7439 ai.enabledSetting = state.enabled;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07007440 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7441 ai.category = state.categoryHint;
7442 }
Jeff Sharkey0078e1b2017-01-11 16:05:27 -07007443 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7444 ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
7445 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007446 ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
Todd Kennedyb2749472017-06-13 08:24:32 -07007447 ai.resourceDirs = state.overlayPaths;
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007448 }
7449
Amith Yamasani13593602012-03-22 16:16:17 -07007450 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007451 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007452 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007453 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007454 return null;
7455 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007456 if (!copyNeeded(flags, p, state, null, userId)
7457 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
7458 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
7459 // In this case it is safe to directly modify the internal ApplicationInfo state:
7460 // - CompatibilityMode is global state, so will be the same for every call.
7461 // - We only come in to here if the app should reported as installed; this is the
7462 // default state, and we will do a copy otherwise.
7463 // - The enable state will always be reported the same for the application across
7464 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
7465 // be doing a copy.
7466 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007467 return p.applicationInfo;
7468 }
7469
7470 // Make shallow copy so we can store the metadata/libraries safely
7471 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Jeff Sharkey15447792015-11-05 16:18:51 -08007472 ai.initForUser(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007473 if ((flags & PackageManager.GET_META_DATA) != 0) {
7474 ai.metaData = p.mAppMetaData;
7475 }
7476 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
7477 ai.sharedLibraryFiles = p.usesLibraryFiles;
7478 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007479 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007480 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007481 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007482 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007483 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007484 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007485 return ai;
7486 }
7487
Dianne Hackbornace27912014-09-18 18:38:30 -07007488 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
7489 PackageUserState state, int userId) {
7490 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007491 if (!checkUseInstalledOrHidden(flags, state, ai)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007492 return null;
7493 }
7494 // This is only used to return the ResolverActivity; we will just always
7495 // make a copy.
7496 ai = new ApplicationInfo(ai);
Jeff Sharkey15447792015-11-05 16:18:51 -08007497 ai.initForUser(userId);
Dianne Hackbornace27912014-09-18 18:38:30 -07007498 if (state.stopped) {
7499 ai.flags |= ApplicationInfo.FLAG_STOPPED;
7500 } else {
7501 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
7502 }
7503 updateApplicationInfo(ai, flags, state);
7504 return ai;
7505 }
7506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007507 public static final PermissionInfo generatePermissionInfo(
7508 Permission p, int flags) {
7509 if (p == null) return null;
7510 if ((flags&PackageManager.GET_META_DATA) == 0) {
7511 return p.info;
7512 }
7513 PermissionInfo pi = new PermissionInfo(p.info);
7514 pi.metaData = p.metaData;
7515 return pi;
7516 }
7517
7518 public static final PermissionGroupInfo generatePermissionGroupInfo(
7519 PermissionGroup pg, int flags) {
7520 if (pg == null) return null;
7521 if ((flags&PackageManager.GET_META_DATA) == 0) {
7522 return pg.info;
7523 }
7524 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
7525 pgi.metaData = pg.metaData;
7526 return pgi;
7527 }
7528
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007529 public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007530 public final ActivityInfo info;
Bryce Lee22571db2017-07-07 15:54:18 -07007531 private boolean mHasMaxAspectRatio;
7532
7533 private boolean hasMaxAspectRatio() {
7534 return mHasMaxAspectRatio;
7535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007536
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007537 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
7538 super(args, _info);
7539 info = _info;
7540 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007541 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007542
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007543 public void setPackageName(String packageName) {
7544 super.setPackageName(packageName);
7545 info.packageName = packageName;
7546 }
7547
Bryce Lee22571db2017-07-07 15:54:18 -07007548
7549 private void setMaxAspectRatio(float maxAspectRatio) {
7550 if (info.resizeMode == RESIZE_MODE_RESIZEABLE
7551 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
7552 // Resizeable activities can be put in any aspect ratio.
7553 return;
7554 }
7555
7556 if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
7557 // Ignore any value lesser than 1.0.
7558 return;
7559 }
7560
7561 info.maxAspectRatio = maxAspectRatio;
7562 mHasMaxAspectRatio = true;
7563 }
7564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007565 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007566 StringBuilder sb = new StringBuilder(128);
7567 sb.append("Activity{");
7568 sb.append(Integer.toHexString(System.identityHashCode(this)));
7569 sb.append(' ');
7570 appendComponentShortName(sb);
7571 sb.append('}');
7572 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007573 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007574
7575 @Override
7576 public int describeContents() {
7577 return 0;
7578 }
7579
7580 @Override
7581 public void writeToParcel(Parcel dest, int flags) {
7582 super.writeToParcel(dest, flags);
7583 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
Bryce Lee22571db2017-07-07 15:54:18 -07007584 dest.writeBoolean(mHasMaxAspectRatio);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007585 }
7586
7587 private Activity(Parcel in) {
7588 super(in);
7589 info = in.readParcelable(Object.class.getClassLoader());
Bryce Lee22571db2017-07-07 15:54:18 -07007590 mHasMaxAspectRatio = in.readBoolean();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007591
7592 for (ActivityIntentInfo aii : intents) {
7593 aii.activity = this;
Todd Kennedy6d418b62018-02-22 14:15:18 -08007594 order = Math.max(aii.getOrder(), order);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007595 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007596
7597 if (info.permission != null) {
7598 info.permission = info.permission.intern();
7599 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007600 }
7601
7602 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
7603 public Activity createFromParcel(Parcel in) {
7604 return new Activity(in);
7605 }
7606
7607 public Activity[] newArray(int size) {
7608 return new Activity[size];
7609 }
7610 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007611 }
7612
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007613 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
7614 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007615 if (a == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007616 if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007617 return null;
7618 }
7619 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007620 updateApplicationInfo(a.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007621 return a.info;
7622 }
7623 // Make shallow copies so we can store the metadata safely
7624 ActivityInfo ai = new ActivityInfo(a.info);
7625 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007626 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007627 return ai;
7628 }
7629
Dianne Hackbornace27912014-09-18 18:38:30 -07007630 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
7631 PackageUserState state, int userId) {
7632 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007633 if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007634 return null;
7635 }
7636 // This is only used to return the ResolverActivity; we will just always
7637 // make a copy.
7638 ai = new ActivityInfo(ai);
7639 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
7640 return ai;
7641 }
7642
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007643 public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007644 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007645
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007646 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
7647 super(args, _info);
7648 info = _info;
7649 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007650 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007651
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007652 public void setPackageName(String packageName) {
7653 super.setPackageName(packageName);
7654 info.packageName = packageName;
7655 }
7656
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007657 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007658 StringBuilder sb = new StringBuilder(128);
7659 sb.append("Service{");
7660 sb.append(Integer.toHexString(System.identityHashCode(this)));
7661 sb.append(' ');
7662 appendComponentShortName(sb);
7663 sb.append('}');
7664 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007665 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007666
7667 @Override
7668 public int describeContents() {
7669 return 0;
7670 }
7671
7672 @Override
7673 public void writeToParcel(Parcel dest, int flags) {
7674 super.writeToParcel(dest, flags);
7675 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7676 }
7677
7678 private Service(Parcel in) {
7679 super(in);
7680 info = in.readParcelable(Object.class.getClassLoader());
7681
7682 for (ServiceIntentInfo aii : intents) {
7683 aii.service = this;
Todd Kennedy6d418b62018-02-22 14:15:18 -08007684 order = Math.max(aii.getOrder(), order);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007685 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007686
7687 if (info.permission != null) {
7688 info.permission = info.permission.intern();
7689 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007690 }
7691
7692 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
7693 public Service createFromParcel(Parcel in) {
7694 return new Service(in);
7695 }
7696
7697 public Service[] newArray(int size) {
7698 return new Service[size];
7699 }
7700 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007701 }
7702
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007703 public static final ServiceInfo generateServiceInfo(Service s, int flags,
7704 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007705 if (s == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007706 if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007707 return null;
7708 }
7709 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007710 updateApplicationInfo(s.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007711 return s.info;
7712 }
7713 // Make shallow copies so we can store the metadata safely
7714 ServiceInfo si = new ServiceInfo(s.info);
7715 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007716 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007717 return si;
7718 }
7719
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007720 public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007721 public final ProviderInfo info;
7722 public boolean syncable;
7723
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007724 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
7725 super(args, _info);
7726 info = _info;
7727 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007728 syncable = false;
7729 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007731 public Provider(Provider existingProvider) {
7732 super(existingProvider);
7733 this.info = existingProvider.info;
7734 this.syncable = existingProvider.syncable;
7735 }
7736
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007737 public void setPackageName(String packageName) {
7738 super.setPackageName(packageName);
7739 info.packageName = packageName;
7740 }
7741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007742 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007743 StringBuilder sb = new StringBuilder(128);
7744 sb.append("Provider{");
7745 sb.append(Integer.toHexString(System.identityHashCode(this)));
7746 sb.append(' ');
7747 appendComponentShortName(sb);
7748 sb.append('}');
7749 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007750 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007751
7752 @Override
7753 public int describeContents() {
7754 return 0;
7755 }
7756
7757 @Override
7758 public void writeToParcel(Parcel dest, int flags) {
7759 super.writeToParcel(dest, flags);
7760 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7761 dest.writeInt((syncable) ? 1 : 0);
7762 }
7763
7764 private Provider(Parcel in) {
7765 super(in);
7766 info = in.readParcelable(Object.class.getClassLoader());
7767 syncable = (in.readInt() == 1);
7768
7769 for (ProviderIntentInfo aii : intents) {
7770 aii.provider = this;
7771 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007772
7773 if (info.readPermission != null) {
7774 info.readPermission = info.readPermission.intern();
7775 }
7776
7777 if (info.writePermission != null) {
7778 info.writePermission = info.writePermission.intern();
7779 }
7780
7781 if (info.authority != null) {
7782 info.authority = info.authority.intern();
7783 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007784 }
7785
7786 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
7787 public Provider createFromParcel(Parcel in) {
7788 return new Provider(in);
7789 }
7790
7791 public Provider[] newArray(int size) {
7792 return new Provider[size];
7793 }
7794 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007795 }
7796
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007797 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
7798 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007799 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007800 if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007801 return null;
7802 }
7803 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007804 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007805 || p.info.uriPermissionPatterns == null)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007806 updateApplicationInfo(p.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007807 return p.info;
7808 }
7809 // Make shallow copies so we can store the metadata safely
7810 ProviderInfo pi = new ProviderInfo(p.info);
7811 pi.metaData = p.metaData;
7812 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
7813 pi.uriPermissionPatterns = null;
7814 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007815 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007816 return pi;
7817 }
7818
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007819 public final static class Instrumentation extends Component<IntentInfo> implements
7820 Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007821 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007822
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007823 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
7824 super(args, _info);
7825 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007826 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007827
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007828 public void setPackageName(String packageName) {
7829 super.setPackageName(packageName);
7830 info.packageName = packageName;
7831 }
7832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007833 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007834 StringBuilder sb = new StringBuilder(128);
7835 sb.append("Instrumentation{");
7836 sb.append(Integer.toHexString(System.identityHashCode(this)));
7837 sb.append(' ');
7838 appendComponentShortName(sb);
7839 sb.append('}');
7840 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007841 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007842
7843 @Override
7844 public int describeContents() {
7845 return 0;
7846 }
7847
7848 @Override
7849 public void writeToParcel(Parcel dest, int flags) {
7850 super.writeToParcel(dest, flags);
7851 dest.writeParcelable(info, flags);
7852 }
7853
7854 private Instrumentation(Parcel in) {
7855 super(in);
7856 info = in.readParcelable(Object.class.getClassLoader());
Narayan Kamath07ac1442017-02-10 15:08:07 +00007857
7858 if (info.targetPackage != null) {
7859 info.targetPackage = info.targetPackage.intern();
7860 }
7861
Dianne Hackborn1be53542017-04-28 13:36:00 -07007862 if (info.targetProcesses != null) {
7863 info.targetProcesses = info.targetProcesses.intern();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007864 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007865 }
7866
7867 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
7868 public Instrumentation createFromParcel(Parcel in) {
7869 return new Instrumentation(in);
7870 }
7871
7872 public Instrumentation[] newArray(int size) {
7873 return new Instrumentation[size];
7874 }
7875 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007876 }
7877
7878 public static final InstrumentationInfo generateInstrumentationInfo(
7879 Instrumentation i, int flags) {
7880 if (i == null) return null;
7881 if ((flags&PackageManager.GET_META_DATA) == 0) {
7882 return i.info;
7883 }
7884 InstrumentationInfo ii = new InstrumentationInfo(i.info);
7885 ii.metaData = i.metaData;
7886 return ii;
7887 }
7888
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007889 public static abstract class IntentInfo extends IntentFilter {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890 public boolean hasDefault;
7891 public int labelRes;
7892 public CharSequence nonLocalizedLabel;
7893 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07007894 public int logo;
Jose Limaf78e3122014-03-06 12:13:15 -08007895 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07007896 public int preferred;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007897
7898 protected IntentInfo() {
7899 }
7900
7901 protected IntentInfo(Parcel dest) {
7902 super(dest);
7903 hasDefault = (dest.readInt() == 1);
7904 labelRes = dest.readInt();
7905 nonLocalizedLabel = dest.readCharSequence();
7906 icon = dest.readInt();
7907 logo = dest.readInt();
7908 banner = dest.readInt();
7909 preferred = dest.readInt();
7910 }
7911
7912
7913 public void writeIntentInfoToParcel(Parcel dest, int flags) {
7914 super.writeToParcel(dest, flags);
7915 dest.writeInt(hasDefault ? 1 : 0);
7916 dest.writeInt(labelRes);
7917 dest.writeCharSequence(nonLocalizedLabel);
7918 dest.writeInt(icon);
7919 dest.writeInt(logo);
7920 dest.writeInt(banner);
7921 dest.writeInt(preferred);
7922 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007923 }
7924
7925 public final static class ActivityIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007926 public Activity activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007927
7928 public ActivityIntentInfo(Activity _activity) {
7929 activity = _activity;
7930 }
7931
7932 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007933 StringBuilder sb = new StringBuilder(128);
7934 sb.append("ActivityIntentInfo{");
7935 sb.append(Integer.toHexString(System.identityHashCode(this)));
7936 sb.append(' ');
7937 activity.appendComponentShortName(sb);
7938 sb.append('}');
7939 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007940 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007941
7942 public ActivityIntentInfo(Parcel in) {
7943 super(in);
7944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007945 }
7946
7947 public final static class ServiceIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007948 public Service service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007949
7950 public ServiceIntentInfo(Service _service) {
7951 service = _service;
7952 }
7953
7954 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007955 StringBuilder sb = new StringBuilder(128);
7956 sb.append("ServiceIntentInfo{");
7957 sb.append(Integer.toHexString(System.identityHashCode(this)));
7958 sb.append(' ');
7959 service.appendComponentShortName(sb);
7960 sb.append('}');
7961 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007962 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007963
7964 public ServiceIntentInfo(Parcel in) {
7965 super(in);
7966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007967 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007968
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007969 public static final class ProviderIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007970 public Provider provider;
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007971
7972 public ProviderIntentInfo(Provider provider) {
7973 this.provider = provider;
7974 }
7975
7976 public String toString() {
7977 StringBuilder sb = new StringBuilder(128);
7978 sb.append("ProviderIntentInfo{");
7979 sb.append(Integer.toHexString(System.identityHashCode(this)));
7980 sb.append(' ');
7981 provider.appendComponentShortName(sb);
7982 sb.append('}');
7983 return sb.toString();
7984 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007985
7986 public ProviderIntentInfo(Parcel in) {
7987 super(in);
7988 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007989 }
7990
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007991 /**
7992 * @hide
7993 */
7994 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
7995 sCompatibilityModeEnabled = compatibilityModeEnabled;
7996 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07007997
7998 public static class PackageParserException extends Exception {
7999 public final int error;
8000
8001 public PackageParserException(int error, String detailMessage) {
8002 super(detailMessage);
8003 this.error = error;
8004 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07008005
8006 public PackageParserException(int error, String detailMessage, Throwable throwable) {
8007 super(detailMessage, throwable);
8008 this.error = error;
8009 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07008010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008011}