blob: e4db0f07b80180ec6e46aa6be13f01eb61480399 [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_UNRESIZEABLE;
31import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
32import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
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;
35import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
36import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
37import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
38import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
39import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
40import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -070041import static android.os.Build.VERSION_CODES.O;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070042import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
43import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070044
Alan Viverette82f4b263a2016-12-19 15:40:05 -050045import android.annotation.IntRange;
46import android.annotation.NonNull;
Fyodor Kupolov965fa692016-10-28 18:20:25 -070047import android.annotation.Nullable;
Alan Viverette82f4b263a2016-12-19 15:40:05 -050048import android.annotation.TestApi;
Dianne Hackborn852975d2014-08-22 17:42:43 -070049import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.content.ComponentName;
51import android.content.Intent;
52import android.content.IntentFilter;
Adam Lesinski4e862812016-11-21 16:02:24 -080053import android.content.pm.split.SplitAssetDependencyLoader;
54import android.content.pm.split.SplitAssetLoader;
55import android.content.pm.split.DefaultSplitAssetLoader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056import android.content.res.AssetManager;
57import android.content.res.Configuration;
58import android.content.res.Resources;
59import android.content.res.TypedArray;
60import android.content.res.XmlResourceParser;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070061import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062import android.os.Bundle;
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -070063import android.os.FileUtils;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070064import android.os.Parcel;
65import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.os.PatternMatcher;
Todd Leeea2f3be2017-03-16 14:00:52 -070067import android.os.SystemProperties;
Todd Kennedy27c24fb2015-09-17 16:49:25 -070068import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070069import android.os.UserHandle;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -060070import android.os.storage.StorageManager;
Narayan Kamath988149c2016-12-01 13:32:59 +000071import android.system.ErrnoException;
72import android.system.OsConstants;
73import android.system.StructStat;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -070074import android.text.TextUtils;
Jeff Sharkey275e0852014-06-17 18:18:49 -070075import android.util.ArrayMap;
76import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.util.AttributeSet;
Kenny Root05ca4c92011-09-15 10:36:25 -070078import android.util.Base64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070080import android.util.Log;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070081import android.util.Pair;
Kenny Rootd2d29252011-08-08 11:27:57 -070082import android.util.Slog;
Adam Lesinski1665d0f2017-03-10 14:46:57 -080083import android.util.SparseArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.util.TypedValue;
Alex Klyubine4157182016-01-05 13:27:05 -080085import android.util.apk.ApkSignatureSchemeV2Verifier;
Jeff Sharkeyc5967e92016-01-07 18:50:29 -070086import android.util.jar.StrictJarFile;
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -070087import android.view.Gravity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070089import com.android.internal.R;
90import com.android.internal.annotations.VisibleForTesting;
91import com.android.internal.util.ArrayUtils;
92import com.android.internal.util.XmlUtils;
93
94import libcore.io.IoUtils;
95
96import org.xmlpull.v1.XmlPullParser;
97import org.xmlpull.v1.XmlPullParserException;
98
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import java.io.File;
Narayan Kamath988149c2016-12-01 13:32:59 +0000100import java.io.FileOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import java.io.IOException;
102import java.io.InputStream;
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -0700103import java.io.PrintWriter;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000104import java.lang.reflect.Constructor;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700105import java.security.GeneralSecurityException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700106import java.security.KeyFactory;
107import java.security.NoSuchAlgorithmException;
108import java.security.PublicKey;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import java.security.cert.Certificate;
110import java.security.cert.CertificateEncodingException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700111import java.security.spec.EncodedKeySpec;
112import java.security.spec.InvalidKeySpecException;
113import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import java.util.ArrayList;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700115import java.util.Arrays;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700116import java.util.Collections;
117import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -0700119import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800120import java.util.Set;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -0600121import java.util.UUID;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700122import java.util.concurrent.atomic.AtomicReference;
Kenny Root6c918ce2013-04-02 14:04:24 -0700123import java.util.zip.ZipEntry;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124
125/**
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700126 * Parser for package files (APKs) on disk. This supports apps packaged either
127 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
128 * APKs in a single directory.
129 * <p>
130 * Apps packaged as multiple APKs always consist of a single "base" APK (with a
131 * {@code null} split name) and zero or more "split" APKs (with unique split
132 * names). Any subset of those split APKs are a valid install, as long as the
133 * following constraints are met:
134 * <ul>
135 * <li>All APKs must have the exact same package name, version code, and signing
136 * certificates.
137 * <li>All APKs must have unique split names.
138 * <li>All installations must contain a single base APK.
139 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700141 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 */
143public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -0700144 private static final boolean DEBUG_JAR = false;
145 private static final boolean DEBUG_PARSER = false;
146 private static final boolean DEBUG_BACKUP = false;
147
Svet Ganova3c4eb32017-04-19 23:51:33 -0700148 private static final String PROPERTY_CHILD_PACKAGES_ENABLED =
149 "persist.sys.child_packages_enabled";
150
151 private static final boolean MULTI_PACKAGE_APK_ENABLED =
152 SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false);
153
Svet Ganov354cd3c2015-12-17 11:35:04 -0800154 private static final int MAX_PACKAGES_PER_APK = 5;
155
Todd Kennedy66c55532016-02-26 16:22:11 -0800156 public static final int APK_SIGNING_UNKNOWN = 0;
157 public static final int APK_SIGNING_V1 = 1;
158 public static final int APK_SIGNING_V2 = 2;
159
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700160 private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
161
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700162 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700163 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700164
Kenny Rootbcc954d2011-08-08 16:19:08 -0700165 /** File name in an APK for the Android manifest. */
166 private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
167
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700168 /** Path prefix for apps on expanded storage */
169 private static final String MNT_EXPAND = "/mnt/expand/";
170
Svet Ganov354cd3c2015-12-17 11:35:04 -0800171 private static final String TAG_MANIFEST = "manifest";
172 private static final String TAG_APPLICATION = "application";
Adam Lesinski4e862812016-11-21 16:02:24 -0800173 private static final String TAG_PACKAGE_VERIFIER = "package-verifier";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800174 private static final String TAG_OVERLAY = "overlay";
175 private static final String TAG_KEY_SETS = "key-sets";
176 private static final String TAG_PERMISSION_GROUP = "permission-group";
177 private static final String TAG_PERMISSION = "permission";
178 private static final String TAG_PERMISSION_TREE = "permission-tree";
179 private static final String TAG_USES_PERMISSION = "uses-permission";
180 private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
181 private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
182 private static final String TAG_USES_CONFIGURATION = "uses-configuration";
183 private static final String TAG_USES_FEATURE = "uses-feature";
184 private static final String TAG_FEATURE_GROUP = "feature-group";
185 private static final String TAG_USES_SDK = "uses-sdk";
186 private static final String TAG_SUPPORT_SCREENS = "supports-screens";
187 private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
188 private static final String TAG_INSTRUMENTATION = "instrumentation";
189 private static final String TAG_ORIGINAL_PACKAGE = "original-package";
190 private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
191 private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
192 private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
193 private static final String TAG_SUPPORTS_INPUT = "supports-input";
194 private static final String TAG_EAT_COMMENT = "eat-comment";
195 private static final String TAG_PACKAGE = "package";
Todd Kennedyfdd241a2016-04-28 12:26:53 -0700196 private static final String TAG_RESTRICT_UPDATE = "restrict-update";
Adam Lesinski4e862812016-11-21 16:02:24 -0800197 private static final String TAG_USES_SPLIT = "uses-split";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800198
Todd Kennedyfe7f38c32017-03-23 09:51:21 -0700199 // [b/36551762] STOPSHIP remove the ability to expose components via meta-data
Todd Kennedy752fb702017-03-21 16:28:10 -0700200 // Temporary workaround; allow meta-data to expose components to instant apps
201 private static final String META_DATA_INSTANT_APPS = "instantapps.clients.allowed";
202
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800203 /**
204 * Bit mask of all the valid bits that can be set in restartOnConfigChanges.
205 * @hide
206 */
207 private static final int RESTART_ON_CONFIG_CHANGES_MASK =
208 ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
209
Svet Ganov354cd3c2015-12-17 11:35:04 -0800210 // These are the tags supported by child packages
211 private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
212 static {
213 CHILD_PACKAGE_TAGS.add(TAG_APPLICATION);
214 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION);
215 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M);
216 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23);
217 CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
218 CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
219 CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
220 CHILD_PACKAGE_TAGS.add(TAG_USES_SDK);
221 CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
222 CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
223 CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE);
224 CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS);
225 CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
226 CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
227 }
228
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700229 private static final boolean LOG_UNSAFE_BROADCASTS = false;
230
231 // Set of broadcast actions that are safe for manifest receivers
232 private static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
233 static {
234 SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
235 }
236
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700237 /** @hide */
238 public static class NewPermissionInfo {
239 public final String name;
240 public final int sdkVersion;
241 public final int fileVersion;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700242
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700243 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
244 this.name = name;
245 this.sdkVersion = sdkVersion;
246 this.fileVersion = fileVersion;
247 }
248 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700249
250 /** @hide */
251 public static class SplitPermissionInfo {
252 public final String rootPerm;
253 public final String[] newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700254 public final int targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700255
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700256 public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
Dianne Hackborn79245122012-03-12 10:51:26 -0700257 this.rootPerm = rootPerm;
258 this.newPerms = newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700259 this.targetSdk = targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700260 }
261 }
262
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700263 /**
264 * List of new permissions that have been added since 1.0.
265 * NOTE: These must be declared in SDK version order, with permissions
266 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700267 * If sdkVersion is 0, then this is not a permission that we want to
268 * automatically add to older apps, but we do want to allow it to be
269 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700270 * @hide
271 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700272 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
273 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700274 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700275 android.os.Build.VERSION_CODES.DONUT, 0),
276 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
277 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700278 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279
Dianne Hackborn79245122012-03-12 10:51:26 -0700280 /**
281 * List of permissions that have been split into more granular or dependent
282 * permissions.
283 * @hide
284 */
285 public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
286 new PackageParser.SplitPermissionInfo[] {
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700287 // READ_EXTERNAL_STORAGE is always required when an app requests
288 // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
289 // write access without read access. The hack here with the target
290 // target SDK version ensures that this grant is always done.
Dianne Hackborn79245122012-03-12 10:51:26 -0700291 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700292 new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700293 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700294 new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
295 new String[] { android.Manifest.permission.READ_CALL_LOG },
296 android.os.Build.VERSION_CODES.JELLY_BEAN),
297 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
298 new String[] { android.Manifest.permission.WRITE_CALL_LOG },
299 android.os.Build.VERSION_CODES.JELLY_BEAN)
Dianne Hackborn79245122012-03-12 10:51:26 -0700300 };
301
Jeff Sharkey275e0852014-06-17 18:18:49 -0700302 /**
303 * @deprecated callers should move to explicitly passing around source path.
304 */
305 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700309 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700310 private DisplayMetrics mMetrics;
Dianne Hackborncd154e92017-02-28 17:37:35 -0800311 private Callback mCallback;
Narayan Kamath988149c2016-12-01 13:32:59 +0000312 private File mCacheDir;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700313
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700314 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700315 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316
317 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
318
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700319 private static boolean sCompatibilityModeEnabled = true;
Amith Yamasani655d0e22013-06-12 14:19:10 -0700320 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
321 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Todd Kennedy11e45072017-01-25 13:24:21 -0800322 private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700323
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700324 static class ParsePackageItemArgs {
325 final Package owner;
326 final String[] outError;
327 final int nameRes;
328 final int labelRes;
329 final int iconRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700330 final int roundIconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700331 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800332 final int bannerRes;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700333
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700334 String tag;
335 TypedArray sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700336
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700337 ParsePackageItemArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700338 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
339 int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700340 owner = _owner;
341 outError = _outError;
342 nameRes = _nameRes;
343 labelRes = _labelRes;
344 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700345 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800346 bannerRes = _bannerRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700347 roundIconRes = _roundIconRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700348 }
349 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700350
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000351 /** @hide */
352 @VisibleForTesting
353 public static class ParseComponentArgs extends ParsePackageItemArgs {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700354 final String[] sepProcesses;
355 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800356 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700357 final int enabledRes;
358 int flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700359
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000360 public ParseComponentArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700361 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
362 int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800363 String[] _sepProcesses, int _processRes,
364 int _descriptionRes, int _enabledRes) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700365 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes,
366 _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700367 sepProcesses = _sepProcesses;
368 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800369 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700370 enabledRes = _enabledRes;
371 }
372 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800373
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700374 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700375 * Lightweight parsed details about a single package.
376 */
377 public static class PackageLite {
378 public final String packageName;
379 public final int versionCode;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700380 public final int installLocation;
381 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700382
383 /** Names of any split APKs, ordered by parsed splitName */
384 public final String[] splitNames;
385
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800386 /** Names of any split APKs that are features. Ordered by splitName */
387 public final boolean[] isFeatureSplits;
388
Adam Lesinski4e862812016-11-21 16:02:24 -0800389 /** Dependencies of any split APKs, ordered by parsed splitName */
390 public final String[] usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800391 public final String[] configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800392
Jeff Sharkey73767b92014-07-04 20:18:13 -0700393 /**
394 * Path where this package was found on disk. For monolithic packages
395 * this is path to single base APK file; for cluster packages this is
396 * path to the cluster directory.
397 */
398 public final String codePath;
399
400 /** Path of base APK */
401 public final String baseCodePath;
402 /** Paths of any split APKs, ordered by parsed splitName */
403 public final String[] splitCodePaths;
404
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800405 /** Revision code of base APK */
406 public final int baseRevisionCode;
407 /** Revision codes of any split APKs, ordered by parsed splitName */
408 public final int[] splitRevisionCodes;
409
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700410 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100411 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100412 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800413 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700414 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800415 public final boolean isolatedSplits;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100416
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700417 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800418 boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit,
419 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700420 this.packageName = baseApk.packageName;
421 this.versionCode = baseApk.versionCode;
422 this.installLocation = baseApk.installLocation;
423 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700424 this.splitNames = splitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800425 this.isFeatureSplits = isFeatureSplits;
Adam Lesinski4e862812016-11-21 16:02:24 -0800426 this.usesSplitNames = usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800427 this.configForSplit = configForSplit;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700428 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700429 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700430 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800431 this.baseRevisionCode = baseApk.revisionCode;
432 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700433 this.coreApp = baseApk.coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100434 this.debuggable = baseApk.debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100435 this.multiArch = baseApk.multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800436 this.use32bitAbi = baseApk.use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700437 this.extractNativeLibs = baseApk.extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800438 this.isolatedSplits = baseApk.isolatedSplits;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700439 }
440
441 public List<String> getAllCodePaths() {
442 ArrayList<String> paths = new ArrayList<>();
443 paths.add(baseCodePath);
444 if (!ArrayUtils.isEmpty(splitCodePaths)) {
445 Collections.addAll(paths, splitCodePaths);
446 }
447 return paths;
448 }
449 }
450
451 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700452 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800453 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700454 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700455 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700456 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700457 public final String splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800458 public boolean isFeatureSplit;
459 public final String configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800460 public final String usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700461 public final int versionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800462 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700463 public final int installLocation;
464 public final VerifierInfo[] verifiers;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700465 public final Signature[] signatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -0700466 public final Certificate[][] certificates;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700467 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100468 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100469 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800470 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700471 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800472 public final boolean isolatedSplits;
Kenny Root05ca4c92011-09-15 10:36:25 -0700473
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800474 public ApkLite(String codePath, String packageName, String splitName, boolean isFeatureSplit,
475 String configForSplit, String usesSplitName, int versionCode, int revisionCode,
476 int installLocation, List<VerifierInfo> verifiers, Signature[] signatures,
477 Certificate[][] certificates, boolean coreApp, boolean debuggable,
478 boolean multiArch, boolean use32bitAbi, boolean extractNativeLibs,
479 boolean isolatedSplits) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700480 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800481 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700482 this.splitName = splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800483 this.isFeatureSplit = isFeatureSplit;
484 this.configForSplit = configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800485 this.usesSplitName = usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700486 this.versionCode = versionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800487 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800488 this.installLocation = installLocation;
Kenny Root05ca4c92011-09-15 10:36:25 -0700489 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700490 this.signatures = signatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -0700491 this.certificates = certificates;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700492 this.coreApp = coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100493 this.debuggable = debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100494 this.multiArch = multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800495 this.use32bitAbi = use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700496 this.extractNativeLibs = extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800497 this.isolatedSplits = isolatedSplits;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800498 }
499 }
500
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700501 private ParsePackageItemArgs mParseInstrumentationArgs;
502 private ParseComponentArgs mParseActivityArgs;
503 private ParseComponentArgs mParseActivityAliasArgs;
504 private ParseComponentArgs mParseServiceArgs;
505 private ParseComponentArgs mParseProviderArgs;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 /** If set to true, we will only allow package files that exactly match
508 * the DTD. Otherwise, we try to get as much from the package as we
509 * can without failing. This should normally be set to false, to
510 * support extensions to the DTD in future versions. */
511 private static final boolean RIGID_PARSER = false;
512
513 private static final String TAG = "PackageParser";
514
Jeff Sharkey275e0852014-06-17 18:18:49 -0700515 public PackageParser() {
516 mMetrics = new DisplayMetrics();
517 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700518 }
519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 public void setSeparateProcesses(String[] procs) {
521 mSeparateProcesses = procs;
522 }
523
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700524 /**
525 * Flag indicating this parser should only consider apps with
526 * {@code coreApp} manifest attribute to be valid apps. This is useful when
527 * creating a minimalist boot environment.
528 */
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700529 public void setOnlyCoreApps(boolean onlyCoreApps) {
530 mOnlyCoreApps = onlyCoreApps;
531 }
532
Jeff Sharkey275e0852014-06-17 18:18:49 -0700533 public void setDisplayMetrics(DisplayMetrics metrics) {
534 mMetrics = metrics;
535 }
536
Narayan Kamath988149c2016-12-01 13:32:59 +0000537 /**
538 * Sets the cache directory for this package parser.
539 */
540 public void setCacheDir(File cacheDir) {
541 mCacheDir = cacheDir;
542 }
543
Dianne Hackborncd154e92017-02-28 17:37:35 -0800544 /**
545 * Callback interface for retrieving information that may be needed while parsing
546 * a package.
547 */
548 public interface Callback {
549 boolean hasFeature(String feature);
550 }
551
552 /**
553 * Standard implementation of {@link Callback} on top of the public {@link PackageManager}
554 * class.
555 */
556 public static final class CallbackImpl implements Callback {
557 private final PackageManager mPm;
558
559 public CallbackImpl(PackageManager pm) {
560 mPm = pm;
561 }
562
563 @Override public boolean hasFeature(String feature) {
564 return mPm.hasSystemFeature(feature);
565 }
566 }
567
568 /**
569 * Set the {@link Callback} that can be used while parsing.
570 */
571 public void setCallback(Callback cb) {
572 mCallback = cb;
573 }
574
Jeff Sharkey73767b92014-07-04 20:18:13 -0700575 public static final boolean isApkFile(File file) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700576 return isApkPath(file.getName());
577 }
578
Adam Lesinski4e862812016-11-21 16:02:24 -0800579 public static boolean isApkPath(String path) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700580 return path.endsWith(".apk");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 }
582
583 /**
584 * Generate and return the {@link PackageInfo} for a parsed package.
585 *
586 * @param p the parsed package.
587 * @param flags indicating which optional information is included.
588 */
589 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800590 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svet Ganov3695b8a2015-03-24 16:30:25 -0700591 Set<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800592
Amith Yamasani483f3b02012-03-13 16:08:00 -0700593 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700594 grantedPermissions, state, UserHandle.getCallingUserId());
595 }
596
Amith Yamasani655d0e22013-06-12 14:19:10 -0700597 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700598 * Returns true if the package is installed and not hidden, or if the caller
599 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700600 * @param appInfo The applicationInfo of the app being checked.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700601 */
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700602 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
603 ApplicationInfo appInfo) {
604 // If available for the target user, or trying to match uninstalled packages and it's
605 // a system app.
606 return state.isAvailable(flags)
607 || (appInfo != null && appInfo.isSystemApp()
608 && (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0);
Amith Yamasani483f3b02012-03-13 16:08:00 -0700609 }
610
Christopher Tateba629da2013-11-13 17:42:28 -0800611 public static boolean isAvailable(PackageUserState state) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700612 return checkUseInstalledOrHidden(0, state, null);
Christopher Tateba629da2013-11-13 17:42:28 -0800613 }
614
Amith Yamasani13593602012-03-22 16:16:17 -0700615 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700616 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800617 Set<String> grantedPermissions, PackageUserState state, int userId) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700618 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700619 return null;
620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 PackageInfo pi = new PackageInfo();
622 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700623 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 pi.versionCode = p.mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800625 pi.baseRevisionCode = p.baseRevisionCode;
626 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800627 pi.versionName = p.mVersionName;
628 pi.sharedUserId = p.mSharedUserId;
629 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700630 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800631 pi.installLocation = p.installLocation;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700632 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700633 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
634 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
635 pi.requiredForAllUsers = p.mRequiredForAllUsers;
636 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700637 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700638 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100639 pi.overlayTarget = p.mOverlayTarget;
Jaekyun Seok42d53f62017-04-10 13:48:58 +0900640 pi.overlayPriority = p.mOverlayPriority;
Jaekyun Seok04342892017-03-02 15:24:19 +0900641 pi.isStaticOverlay = p.mIsStaticOverlay;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700642 pi.firstInstallTime = firstInstallTime;
643 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644 if ((flags&PackageManager.GET_GIDS) != 0) {
645 pi.gids = gids;
646 }
647 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700648 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 if (N > 0) {
650 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700651 p.configPreferences.toArray(pi.configPreferences);
652 }
653 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
654 if (N > 0) {
655 pi.reqFeatures = new FeatureInfo[N];
656 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800657 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700658 N = p.featureGroups != null ? p.featureGroups.size() : 0;
659 if (N > 0) {
660 pi.featureGroups = new FeatureGroupInfo[N];
661 p.featureGroups.toArray(pi.featureGroups);
662 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700664 if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
665 final int N = p.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700667 int num = 0;
668 final ActivityInfo[] res = new ActivityInfo[N];
669 for (int i = 0; i < N; i++) {
670 final Activity a = p.activities.get(i);
671 if (state.isMatch(a.info, flags)) {
672 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800673 }
674 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700675 pi.activities = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 }
677 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700678 if ((flags & PackageManager.GET_RECEIVERS) != 0) {
679 final int N = p.receivers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700681 int num = 0;
682 final ActivityInfo[] res = new ActivityInfo[N];
683 for (int i = 0; i < N; i++) {
684 final Activity a = p.receivers.get(i);
685 if (state.isMatch(a.info, flags)) {
686 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800687 }
688 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700689 pi.receivers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690 }
691 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700692 if ((flags & PackageManager.GET_SERVICES) != 0) {
693 final int N = p.services.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700695 int num = 0;
696 final ServiceInfo[] res = new ServiceInfo[N];
697 for (int i = 0; i < N; i++) {
698 final Service s = p.services.get(i);
699 if (state.isMatch(s.info, flags)) {
700 res[num++] = generateServiceInfo(s, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800701 }
702 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700703 pi.services = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 }
705 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700706 if ((flags & PackageManager.GET_PROVIDERS) != 0) {
707 final int N = p.providers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700709 int num = 0;
710 final ProviderInfo[] res = new ProviderInfo[N];
711 for (int i = 0; i < N; i++) {
712 final Provider pr = p.providers.get(i);
713 if (state.isMatch(pr.info, flags)) {
714 res[num++] = generateProviderInfo(pr, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715 }
716 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700717 pi.providers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718 }
719 }
720 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
721 int N = p.instrumentation.size();
722 if (N > 0) {
723 pi.instrumentation = new InstrumentationInfo[N];
724 for (int i=0; i<N; i++) {
725 pi.instrumentation[i] = generateInstrumentationInfo(
726 p.instrumentation.get(i), flags);
727 }
728 }
729 }
730 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
731 int N = p.permissions.size();
732 if (N > 0) {
733 pi.permissions = new PermissionInfo[N];
734 for (int i=0; i<N; i++) {
735 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
736 }
737 }
738 N = p.requestedPermissions.size();
739 if (N > 0) {
740 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800741 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800742 for (int i=0; i<N; i++) {
Dianne Hackborne639da72012-02-21 15:11:13 -0800743 final String perm = p.requestedPermissions.get(i);
744 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700745 // The notion of required permissions is deprecated but for compatibility.
Svetoslavc6d1c342015-02-26 14:44:43 -0800746 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800747 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
748 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
749 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 }
751 }
752 }
753 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700754 int N = (p.mSignatures != null) ? p.mSignatures.length : 0;
755 if (N > 0) {
756 pi.signatures = new Signature[N];
757 System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800758 }
759 }
760 return pi;
761 }
762
Jeff Sharkey275e0852014-06-17 18:18:49 -0700763 private static Certificate[][] loadCertificates(StrictJarFile jarFile, ZipEntry entry)
764 throws PackageParserException {
765 InputStream is = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 try {
767 // We must read the stream for the JarEntry to retrieve
768 // its certificates.
Jeff Sharkey275e0852014-06-17 18:18:49 -0700769 is = jarFile.getInputStream(entry);
770 readFullyIgnoringContents(is);
771 return jarFile.getCertificateChains(entry);
772 } catch (IOException | RuntimeException e) {
773 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
774 "Failed reading " + entry.getName() + " in " + jarFile, e);
775 } finally {
776 IoUtils.closeQuietly(is);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 }
779
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800780 public final static int PARSE_IS_SYSTEM = 1<<0;
781 public final static int PARSE_CHATTY = 1<<1;
782 public final static int PARSE_MUST_BE_APK = 1<<2;
783 public final static int PARSE_IGNORE_PROCESSES = 1<<3;
784 public final static int PARSE_FORWARD_LOCK = 1<<4;
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -0700785 public final static int PARSE_EXTERNAL_STORAGE = 1<<5;
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700786 public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
Christopher Tateccbf84f2013-05-08 15:25:41 -0700787 public final static int PARSE_IS_PRIVILEGED = 1<<7;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700788 public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700789 public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
Christopher Tatef3d939c2015-09-17 12:25:51 -0700790 public final static int PARSE_ENFORCE_CODE = 1<<10;
Todd Kennedybe0b8892017-02-15 14:13:52 -0800791 /** @deprecated remove when fixing b/34761192 */
792 @Deprecated
Todd Kennedy373f0b42015-12-16 14:45:14 -0800793 public final static int PARSE_IS_EPHEMERAL = 1<<11;
Todd Kennedyb1072712016-04-26 15:41:20 -0700794 public final static int PARSE_FORCE_SDK = 1<<12;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700795
796 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700798 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700799 * Used to sort a set of APKs based on their split names, always placing the
800 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700801 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700802 private static class SplitNameComparator implements Comparator<String> {
803 @Override
804 public int compare(String lhs, String rhs) {
805 if (lhs == null) {
806 return -1;
807 } else if (rhs == null) {
808 return 1;
809 } else {
810 return lhs.compareTo(rhs);
811 }
812 }
813 }
814
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700815 /**
816 * Parse only lightweight details about the package at the given location.
817 * Automatically detects if the package is a monolithic style (single APK
818 * file) or cluster style (directory of APKs).
819 * <p>
820 * This performs sanity checking on cluster style packages, such as
821 * requiring identical package name and version codes, a single base APK,
822 * and unique split names.
823 *
824 * @see PackageParser#parsePackage(File, int)
825 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700826 public static PackageLite parsePackageLite(File packageFile, int flags)
827 throws PackageParserException {
828 if (packageFile.isDirectory()) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800829 return parseClusterPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700830 } else {
Adam Lesinski4e862812016-11-21 16:02:24 -0800831 return parseMonolithicPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700832 }
833 }
834
Adam Lesinski4e862812016-11-21 16:02:24 -0800835 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
836 throws PackageParserException {
Todd Kennedycd029da2016-07-21 07:41:09 -0700837 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Adam Lesinski4e862812016-11-21 16:02:24 -0800838 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700839 final String packagePath = packageFile.getAbsolutePath();
Todd Kennedycd029da2016-07-21 07:41:09 -0700840 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800841 return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700842 }
843
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800844 static PackageLite parseClusterPackageLite(File packageDir, int flags)
Adam Lesinski4e862812016-11-21 16:02:24 -0800845 throws PackageParserException {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700846 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700847 if (ArrayUtils.isEmpty(files)) {
848 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
849 "No packages found in split");
850 }
851
Jeff Sharkey275e0852014-06-17 18:18:49 -0700852 String packageName = null;
853 int versionCode = 0;
854
Todd Kennedycd029da2016-07-21 07:41:09 -0700855 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700856 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700857 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700858 if (isApkFile(file)) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800859 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700860
861 // Assert that all package names and version codes are
862 // consistent with the first one we encounter.
863 if (packageName == null) {
864 packageName = lite.packageName;
865 versionCode = lite.versionCode;
866 } else {
867 if (!packageName.equals(lite.packageName)) {
868 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
869 "Inconsistent package " + lite.packageName + " in " + file
870 + "; expected " + packageName);
871 }
872 if (versionCode != lite.versionCode) {
873 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
874 "Inconsistent version " + lite.versionCode + " in " + file
875 + "; expected " + versionCode);
876 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700877 }
878
Jeff Sharkey275e0852014-06-17 18:18:49 -0700879 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700880 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700881 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
882 "Split name " + lite.splitName
883 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700884 }
885 }
886 }
Todd Kennedycd029da2016-07-21 07:41:09 -0700887 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700888
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700889 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700890 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700891 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700892 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700893 }
894
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700895 // Always apply deterministic ordering based on splitName
896 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700897
Jeff Sharkey73767b92014-07-04 20:18:13 -0700898 String[] splitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800899 boolean[] isFeatureSplits = null;
Adam Lesinski4e862812016-11-21 16:02:24 -0800900 String[] usesSplitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800901 String[] configForSplits = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700902 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800903 int[] splitRevisionCodes = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700904 if (size > 0) {
905 splitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800906 isFeatureSplits = new boolean[size];
Adam Lesinski4e862812016-11-21 16:02:24 -0800907 usesSplitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800908 configForSplits = new String[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700909 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800910 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700911
912 splitNames = apks.keySet().toArray(splitNames);
913 Arrays.sort(splitNames, sSplitNameComparator);
914
915 for (int i = 0; i < size; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800916 final ApkLite apk = apks.get(splitNames[i]);
917 usesSplitNames[i] = apk.usesSplitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800918 isFeatureSplits[i] = apk.isFeatureSplit;
919 configForSplits[i] = apk.configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800920 splitCodePaths[i] = apk.codePath;
921 splitRevisionCodes[i] = apk.revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700922 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700923 }
924
Jeff Sharkey73767b92014-07-04 20:18:13 -0700925 final String codePath = packageDir.getAbsolutePath();
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800926 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames,
927 configForSplits, splitCodePaths, splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700928 }
929
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700930 /**
931 * Parse the package at the given location. Automatically detects if the
932 * package is a monolithic style (single APK file) or cluster style
933 * (directory of APKs).
934 * <p>
935 * This performs sanity checking on cluster style packages, such as
936 * requiring identical package name and version codes, a single base APK,
937 * and unique split names.
938 * <p>
939 * Note that this <em>does not</em> perform signature verification; that
940 * must be done separately in {@link #collectCertificates(Package, int)}.
941 *
Narayan Kamath988149c2016-12-01 13:32:59 +0000942 * If {@code useCaches} is true, the package parser might return a cached
943 * result from a previous parse of the same {@code packageFile} with the same
944 * {@code flags}. Note that this method does not check whether {@code packageFile}
945 * has changed since the last parse, it's up to callers to do so.
946 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700947 * @see #parsePackageLite(File, int)
948 */
Narayan Kamath988149c2016-12-01 13:32:59 +0000949 public Package parsePackage(File packageFile, int flags, boolean useCaches)
950 throws PackageParserException {
951 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
952 if (parsed != null) {
953 return parsed;
954 }
955
Jeff Sharkey73767b92014-07-04 20:18:13 -0700956 if (packageFile.isDirectory()) {
Narayan Kamath988149c2016-12-01 13:32:59 +0000957 parsed = parseClusterPackage(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700958 } else {
Narayan Kamath988149c2016-12-01 13:32:59 +0000959 parsed = parseMonolithicPackage(packageFile, flags);
960 }
961
962 cacheResult(packageFile, flags, parsed);
963
964 return parsed;
965 }
966
967 /**
968 * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}.
969 */
970 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
971 return parsePackage(packageFile, flags, false /* useCaches */);
972 }
973
974 /**
975 * Returns the cache key for a specificied {@code packageFile} and {@code flags}.
976 */
977 private String getCacheKey(File packageFile, int flags) {
978 StringBuilder sb = new StringBuilder(packageFile.getName());
979 sb.append('-');
980 sb.append(flags);
981
982 return sb.toString();
983 }
984
985 @VisibleForTesting
986 protected Package fromCacheEntry(byte[] bytes) throws IOException {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000987 Parcel p = Parcel.obtain();
988 p.unmarshall(bytes, 0, bytes.length);
989 p.setDataPosition(0);
990
991 PackageParser.Package pkg = new PackageParser.Package(p);
992 p.recycle();
993
994 return pkg;
Narayan Kamath988149c2016-12-01 13:32:59 +0000995 }
996
997 @VisibleForTesting
998 protected byte[] toCacheEntry(Package pkg) throws IOException {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000999 Parcel p = Parcel.obtain();
1000 pkg.writeToParcel(p, 0 /* flags */);
1001 byte[] serialized = p.marshall();
1002 p.recycle();
1003
1004 return serialized;
Narayan Kamath988149c2016-12-01 13:32:59 +00001005 }
1006
1007 /**
1008 * Given a {@code packageFile} and a {@code cacheFile} returns whether the
1009 * cache file is up to date based on the mod-time of both files.
1010 */
1011 private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
1012 try {
1013 // NOTE: We don't use the File.lastModified API because it has the very
1014 // non-ideal failure mode of returning 0 with no excepions thrown.
1015 // The nio2 Files API is a little better but is considerably more expensive.
1016 final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
1017 final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
1018 return pkg.st_mtime < cache.st_mtime;
1019 } catch (ErrnoException ee) {
1020 // The most common reason why stat fails is that a given cache file doesn't
1021 // exist. We ignore that here. It's easy to reason that it's safe to say the
1022 // cache isn't up to date if we see any sort of exception here.
1023 //
1024 // (1) Exception while stating the package file : This should never happen,
1025 // and if it does, we do a full package parse (which is likely to throw the
1026 // same exception).
1027 // (2) Exception while stating the cache file : If the file doesn't exist, the
1028 // cache is obviously out of date. If the file *does* exist, we can't read it.
1029 // We will attempt to delete and recreate it after parsing the package.
1030 if (ee.errno != OsConstants.ENOENT) {
1031 Slog.w("Error while stating package cache : ", ee);
1032 }
1033
1034 return false;
1035 }
1036 }
1037
1038 /**
1039 * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
1040 * or {@code null} if no cached result exists.
1041 */
1042 private Package getCachedResult(File packageFile, int flags) {
1043 if (mCacheDir == null) {
1044 return null;
1045 }
1046
1047 final String cacheKey = getCacheKey(packageFile, flags);
1048 final File cacheFile = new File(mCacheDir, cacheKey);
1049
1050 // If the cache is not up to date, return null.
1051 if (!isCacheUpToDate(packageFile, cacheFile)) {
1052 return null;
1053 }
1054
1055 try {
1056 final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
1057 return fromCacheEntry(bytes);
Narayan Kamath21a28382017-01-13 10:34:29 +00001058 } catch (Exception e) {
1059 Slog.w(TAG, "Error reading package cache: ", e);
Narayan Kamath988149c2016-12-01 13:32:59 +00001060
1061 // If something went wrong while reading the cache entry, delete the cache file
1062 // so that we regenerate it the next time.
1063 cacheFile.delete();
1064 return null;
1065 }
1066 }
1067
1068 /**
1069 * Caches the parse result for {@code packageFile} with flags {@code flags}.
1070 */
1071 private void cacheResult(File packageFile, int flags, Package parsed) {
1072 if (mCacheDir == null) {
1073 return;
1074 }
1075
1076 final String cacheKey = getCacheKey(packageFile, flags);
1077 final File cacheFile = new File(mCacheDir, cacheKey);
1078
1079 if (cacheFile.exists()) {
1080 if (!cacheFile.delete()) {
1081 Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
1082 }
1083 }
1084
1085 final byte[] cacheEntry;
1086 try {
1087 cacheEntry = toCacheEntry(parsed);
1088 } catch (IOException ioe) {
1089 Slog.e(TAG, "Unable to serialize parsed package for: " + packageFile);
1090 return;
1091 }
1092
1093 if (cacheEntry == null) {
1094 return;
1095 }
1096
1097 try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
1098 fos.write(cacheEntry);
1099 } catch (IOException ioe) {
1100 Slog.w(TAG, "Error writing cache entry.", ioe);
1101 cacheFile.delete();
Jeff Sharkey73767b92014-07-04 20:18:13 -07001102 }
1103 }
1104
1105 /**
1106 * Parse all APKs contained in the given directory, treating them as a
1107 * single package. This also performs sanity checking, such as requiring
1108 * identical package name and version codes, a single base APK, and unique
1109 * split names.
1110 * <p>
1111 * Note that this <em>does not</em> perform signature verification; that
1112 * must be done separately in {@link #collectCertificates(Package, int)}.
1113 */
1114 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001115 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001116 if (mOnlyCoreApps && !lite.coreApp) {
1117 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1118 "Not a coreApp: " + packageDir);
1119 }
1120
Adam Lesinski4e862812016-11-21 16:02:24 -08001121 // Build the split dependency tree.
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001122 SparseArray<int[]> splitDependencies = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001123 final SplitAssetLoader assetLoader;
1124 if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001125 try {
1126 splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
1127 assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
1128 } catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
1129 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
1130 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001131 } else {
1132 assetLoader = new DefaultSplitAssetLoader(lite, flags);
1133 }
1134
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001135 try {
Adam Lesinski4e862812016-11-21 16:02:24 -08001136 final AssetManager assets = assetLoader.getBaseAssetManager();
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001137 final File baseApk = new File(lite.baseCodePath);
1138 final Package pkg = parseBaseApk(baseApk, assets, flags);
1139 if (pkg == null) {
1140 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1141 "Failed to parse base APK: " + baseApk);
1142 }
1143
1144 if (!ArrayUtils.isEmpty(lite.splitNames)) {
1145 final int num = lite.splitNames.length;
1146 pkg.splitNames = lite.splitNames;
1147 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001148 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001149 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001150 pkg.splitPrivateFlags = new int[num];
Adam Lesinski4e862812016-11-21 16:02:24 -08001151 pkg.applicationInfo.splitNames = pkg.splitNames;
1152 pkg.applicationInfo.splitDependencies = splitDependencies;
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001153
1154 for (int i = 0; i < num; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -08001155 final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
1156 parseSplitApk(pkg, i, splitAssets, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001157 }
1158 }
1159
Svet Ganov354cd3c2015-12-17 11:35:04 -08001160 pkg.setCodePath(packageDir.getAbsolutePath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001161 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001162 return pkg;
1163 } finally {
Adam Lesinski4e862812016-11-21 16:02:24 -08001164 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001165 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166 }
1167
Jeff Sharkey275e0852014-06-17 18:18:49 -07001168 /**
1169 * Parse the given APK file, treating it as as a single monolithic package.
1170 * <p>
1171 * Note that this <em>does not</em> perform signature verification; that
1172 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001173 *
1174 * @deprecated external callers should move to
1175 * {@link #parsePackage(File, int)}. Eventually this method will
1176 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -07001177 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001178 @Deprecated
Jeff Sharkey275e0852014-06-17 18:18:49 -07001179 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001180 final AssetManager assets = newConfiguredAssetManager();
Adam Lesinski4e862812016-11-21 16:02:24 -08001181 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001182 if (mOnlyCoreApps) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001183 if (!lite.coreApp) {
1184 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1185 "Not a coreApp: " + apkFile);
1186 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001187 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001188
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001189 try {
1190 final Package pkg = parseBaseApk(apkFile, assets, flags);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001191 pkg.setCodePath(apkFile.getAbsolutePath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001192 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001193 return pkg;
1194 } finally {
1195 IoUtils.closeQuietly(assets);
1196 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001197 }
1198
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001199 private static int loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags)
1200 throws PackageParserException {
1201 if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkPath(apkPath)) {
1202 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1203 "Invalid package file: " + apkPath);
1204 }
1205
1206 // The AssetManager guarantees uniqueness for asset paths, so if this asset path
1207 // already exists in the AssetManager, addAssetPath will only return the cookie
1208 // assigned to it.
1209 int cookie = assets.addAssetPath(apkPath);
1210 if (cookie == 0) {
1211 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1212 "Failed adding asset path: " + apkPath);
1213 }
1214 return cookie;
1215 }
1216
1217 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
1218 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001219 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001220
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07001221 String volumeUuid = null;
1222 if (apkPath.startsWith(MNT_EXPAND)) {
1223 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
1224 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
1225 }
1226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001227 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001228 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001229
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001230 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001232 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
1233
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08001234 Resources res = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001235 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001237 res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001238 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
1239
1240 final String[] outError = new String[1];
1241 final Package pkg = parseBaseApk(res, parser, flags, outError);
1242 if (pkg == null) {
1243 throw new PackageParserException(mParseError,
1244 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001245 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001246
Svet Ganov354cd3c2015-12-17 11:35:04 -08001247 pkg.setVolumeUuid(volumeUuid);
1248 pkg.setApplicationVolumeUuid(volumeUuid);
1249 pkg.setBaseCodePath(apkPath);
1250 pkg.setSignatures(null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001251
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001252 return pkg;
1253
1254 } catch (PackageParserException e) {
1255 throw e;
1256 } catch (Exception e) {
1257 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001258 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001259 } finally {
1260 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001261 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001262 }
1263
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001264 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001265 throws PackageParserException {
1266 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -07001267
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001268 mParseError = PackageManager.INSTALL_SUCCEEDED;
1269 mArchiveSourcePath = apkPath;
1270
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001271 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
1272
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001273 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
1274
Adam Lesinski4e862812016-11-21 16:02:24 -08001275 final Resources res;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001276 XmlResourceParser parser = null;
1277 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001278 res = new Resources(assets, mMetrics, null);
Romain Guy408afbf2017-01-25 10:23:03 -08001279 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001280 Build.VERSION.RESOURCES_SDK_INT);
1281 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
1282
1283 final String[] outError = new String[1];
1284 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
1285 if (pkg == null) {
1286 throw new PackageParserException(mParseError,
1287 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
1288 }
1289
1290 } catch (PackageParserException e) {
1291 throw e;
1292 } catch (Exception e) {
1293 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001294 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001295 } finally {
1296 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001297 }
1298 }
1299
1300 /**
1301 * Parse the manifest of a <em>split APK</em>.
1302 * <p>
1303 * Note that split APKs have many more restrictions on what they're capable
1304 * of doing, so many valid features of a base APK have been carefully
1305 * omitted here.
1306 */
1307 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001308 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
1309 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001310 AttributeSet attrs = parser;
1311
Jeff Sharkey78a13012014-07-15 20:18:34 -07001312 // We parsed manifest tag earlier; just skip past it
Svet Ganov354cd3c2015-12-17 11:35:04 -08001313 parsePackageSplitNames(parser, attrs);
Jeff Sharkey78a13012014-07-15 20:18:34 -07001314
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001315 mParseInstrumentationArgs = null;
1316 mParseActivityArgs = null;
1317 mParseServiceArgs = null;
1318 mParseProviderArgs = null;
1319
1320 int type;
1321
1322 boolean foundApp = false;
1323
1324 int outerDepth = parser.getDepth();
1325 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1326 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1327 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1328 continue;
1329 }
1330
1331 String tagName = parser.getName();
Adam Lesinski4e862812016-11-21 16:02:24 -08001332 if (tagName.equals(TAG_APPLICATION)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001333 if (foundApp) {
1334 if (RIGID_PARSER) {
1335 outError[0] = "<manifest> has more than one <application>";
1336 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1337 return null;
1338 } else {
1339 Slog.w(TAG, "<manifest> has more than one <application>");
1340 XmlUtils.skipCurrentTag(parser);
1341 continue;
1342 }
1343 }
1344
1345 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001346 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001347 return null;
1348 }
1349
1350 } else if (RIGID_PARSER) {
1351 outError[0] = "Bad element under <manifest>: "
1352 + parser.getName();
1353 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1354 return null;
1355
1356 } else {
1357 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1358 + " at " + mArchiveSourcePath + " "
1359 + parser.getPositionDescription());
1360 XmlUtils.skipCurrentTag(parser);
1361 continue;
1362 }
1363 }
1364
1365 if (!foundApp) {
1366 outError[0] = "<manifest> does not contain an <application>";
1367 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1368 }
1369
1370 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001371 }
1372
Todd Kennedy66c55532016-02-26 16:22:11 -08001373 public static int getApkSigningVersion(Package pkg) {
1374 try {
1375 if (ApkSignatureSchemeV2Verifier.hasSignature(pkg.baseCodePath)) {
1376 return APK_SIGNING_V2;
1377 }
1378 return APK_SIGNING_V1;
1379 } catch (IOException e) {
1380 }
1381 return APK_SIGNING_UNKNOWN;
1382 }
1383
Kenny Root6c918ce2013-04-02 14:04:24 -07001384 /**
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001385 * Populates the correct packages fields with the given certificates.
1386 * <p>
1387 * This is useful when we've already processed the certificates [such as during package
1388 * installation through an installer session]. We don't re-process the archive and
1389 * simply populate the correct fields.
1390 */
1391 public static void populateCertificates(Package pkg, Certificate[][] certificates)
1392 throws PackageParserException {
1393 pkg.mCertificates = null;
1394 pkg.mSignatures = null;
1395 pkg.mSigningKeys = null;
1396
1397 pkg.mCertificates = certificates;
1398 try {
1399 pkg.mSignatures = convertToSignatures(certificates);
1400 } catch (CertificateEncodingException e) {
1401 // certificates weren't encoded properly; something went wrong
1402 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1403 "Failed to collect certificates from " + pkg.baseCodePath, e);
1404 }
1405 pkg.mSigningKeys = new ArraySet<>(certificates.length);
1406 for (int i = 0; i < certificates.length; i++) {
1407 Certificate[] signerCerts = certificates[i];
1408 Certificate signerCert = signerCerts[0];
1409 pkg.mSigningKeys.add(signerCert.getPublicKey());
1410 }
1411 // add signatures to child packages
1412 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1413 for (int i = 0; i < childCount; i++) {
1414 Package childPkg = pkg.childPackages.get(i);
1415 childPkg.mCertificates = pkg.mCertificates;
1416 childPkg.mSignatures = pkg.mSignatures;
1417 childPkg.mSigningKeys = pkg.mSigningKeys;
1418 }
1419 }
1420
1421 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -07001422 * Collect certificates from all the APKs described in the given package,
Todd Kennedy373f0b42015-12-16 14:45:14 -08001423 * populating {@link Package#mSignatures}. Also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001424 * contents are signed correctly and consistently.
1425 */
Todd Kennedy66c55532016-02-26 16:22:11 -08001426 public static void collectCertificates(Package pkg, int parseFlags)
1427 throws PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001428 collectCertificatesInternal(pkg, parseFlags);
1429 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1430 for (int i = 0; i < childCount; i++) {
1431 Package childPkg = pkg.childPackages.get(i);
1432 childPkg.mCertificates = pkg.mCertificates;
1433 childPkg.mSignatures = pkg.mSignatures;
1434 childPkg.mSigningKeys = pkg.mSigningKeys;
1435 }
1436 }
1437
Todd Kennedy66c55532016-02-26 16:22:11 -08001438 private static void collectCertificatesInternal(Package pkg, int parseFlags)
1439 throws PackageParserException {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001440 pkg.mCertificates = null;
1441 pkg.mSignatures = null;
1442 pkg.mSigningKeys = null;
1443
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001444 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1445 try {
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001446 collectCertificates(pkg, new File(pkg.baseCodePath), parseFlags);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001447
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001448 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1449 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001450 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), parseFlags);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001451 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001452 }
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001453 } finally {
1454 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001455 }
1456 }
1457
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001458 private static void collectCertificates(Package pkg, File apkFile, int parseFlags)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001459 throws PackageParserException {
1460 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461
Alex Klyubine4157182016-01-05 13:27:05 -08001462 // Try to verify the APK using APK Signature Scheme v2.
1463 boolean verified = false;
1464 {
1465 Certificate[][] allSignersCerts = null;
1466 Signature[] signatures = null;
1467 try {
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001468 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV2");
Alex Klyubine4157182016-01-05 13:27:05 -08001469 allSignersCerts = ApkSignatureSchemeV2Verifier.verify(apkPath);
1470 signatures = convertToSignatures(allSignersCerts);
1471 // APK verified using APK Signature Scheme v2.
1472 verified = true;
1473 } catch (ApkSignatureSchemeV2Verifier.SignatureNotFoundException e) {
1474 // No APK Signature Scheme v2 signature found
Alex Klyubinabbc2bad2017-01-04 11:28:47 -08001475 if ((parseFlags & PARSE_IS_EPHEMERAL) != 0) {
1476 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1477 "No APK Signature Scheme v2 signature in ephemeral package " + apkPath,
1478 e);
1479 }
Svet Ganov67882122016-12-11 16:36:34 -08001480 // Static shared libraries must use only the V2 signing scheme
1481 if (pkg.applicationInfo.isStaticSharedLibrary()) {
1482 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1483 "Static shared libs must use v2 signature scheme " + apkPath);
1484 }
Alex Klyubine4157182016-01-05 13:27:05 -08001485 } catch (Exception e) {
1486 // APK Signature Scheme v2 signature was found but did not verify
1487 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1488 "Failed to collect certificates from " + apkPath
1489 + " using APK Signature Scheme v2",
1490 e);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001491 } finally {
1492 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Alex Klyubine4157182016-01-05 13:27:05 -08001493 }
1494
1495 if (verified) {
1496 if (pkg.mCertificates == null) {
1497 pkg.mCertificates = allSignersCerts;
1498 pkg.mSignatures = signatures;
1499 pkg.mSigningKeys = new ArraySet<>(allSignersCerts.length);
1500 for (int i = 0; i < allSignersCerts.length; i++) {
1501 Certificate[] signerCerts = allSignersCerts[i];
1502 Certificate signerCert = signerCerts[0];
1503 pkg.mSigningKeys.add(signerCert.getPublicKey());
1504 }
1505 } else {
1506 if (!Signature.areExactMatch(pkg.mSignatures, signatures)) {
1507 throw new PackageParserException(
1508 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
1509 apkPath + " has mismatched certificates");
1510 }
1511 }
1512 // Not yet done, because we need to confirm that AndroidManifest.xml exists and,
1513 // if requested, that classes.dex exists.
1514 }
1515 }
1516
Jeff Sharkey275e0852014-06-17 18:18:49 -07001517 StrictJarFile jarFile = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 try {
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001519 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
Alex Klyubin9b59bc42016-03-24 12:02:20 -07001520 // Ignore signature stripping protections when verifying APKs from system partition.
1521 // For those APKs we only care about extracting signer certificates, and don't care
1522 // about verifying integrity.
1523 boolean signatureSchemeRollbackProtectionsEnforced =
Todd Kennedyd022ac22016-04-13 10:49:29 -07001524 (parseFlags & PARSE_IS_SYSTEM_DIR) == 0;
Alex Klyubine4157182016-01-05 13:27:05 -08001525 jarFile = new StrictJarFile(
1526 apkPath,
Alex Klyubin9b59bc42016-03-24 12:02:20 -07001527 !verified, // whether to verify JAR signature
1528 signatureSchemeRollbackProtectionsEnforced);
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001529 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530
Jeff Sharkey275e0852014-06-17 18:18:49 -07001531 // Always verify manifest, regardless of source
1532 final ZipEntry manifestEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
1533 if (manifestEntry == null) {
1534 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1535 "Package " + apkPath + " has no manifest");
1536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537
Alex Klyubine4157182016-01-05 13:27:05 -08001538 // Optimization: early termination when APK already verified
1539 if (verified) {
Alex Klyubine4157182016-01-05 13:27:05 -08001540 return;
1541 }
1542
1543 // APK's integrity needs to be verified using JAR signature scheme.
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001544 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV1");
Jeff Sharkey275e0852014-06-17 18:18:49 -07001545 final List<ZipEntry> toVerify = new ArrayList<>();
1546 toVerify.add(manifestEntry);
1547
1548 // If we're parsing an untrusted package, verify all contents
Todd Kennedyd022ac22016-04-13 10:49:29 -07001549 if ((parseFlags & PARSE_IS_SYSTEM_DIR) == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001550 final Iterator<ZipEntry> i = jarFile.iterator();
1551 while (i.hasNext()) {
1552 final ZipEntry entry = i.next();
1553
1554 if (entry.isDirectory()) continue;
Christopher Tatef3d939c2015-09-17 12:25:51 -07001555
1556 final String entryName = entry.getName();
1557 if (entryName.startsWith("META-INF/")) continue;
1558 if (entryName.equals(ANDROID_MANIFEST_FILENAME)) continue;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001559
1560 toVerify.add(entry);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001562 }
1563
1564 // Verify that entries are signed consistently with the first entry
1565 // we encountered. Note that for splits, certificates may have
1566 // already been populated during an earlier parse of a base APK.
1567 for (ZipEntry entry : toVerify) {
1568 final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
1569 if (ArrayUtils.isEmpty(entryCerts)) {
1570 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1571 "Package " + apkPath + " has no certificates at entry "
1572 + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 }
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001574 final Signature[] entrySignatures = convertToSignatures(entryCerts);
Kenny Rootd2d29252011-08-08 11:27:57 -07001575
Jeff Sharkey275e0852014-06-17 18:18:49 -07001576 if (pkg.mCertificates == null) {
1577 pkg.mCertificates = entryCerts;
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001578 pkg.mSignatures = entrySignatures;
dcashman55b10782014-04-09 14:20:38 -07001579 pkg.mSigningKeys = new ArraySet<PublicKey>();
1580 for (int i=0; i < entryCerts.length; i++) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001581 pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
Kenny Rootbcc954d2011-08-08 16:19:08 -07001582 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001583 } else {
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001584 if (!Signature.areExactMatch(pkg.mSignatures, entrySignatures)) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001585 throw new PackageParserException(
1586 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Package " + apkPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 + " has mismatched certificates at entry "
Jeff Sharkey275e0852014-06-17 18:18:49 -07001588 + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 }
1590 }
1591 }
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001592 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeybc097552014-09-09 14:57:26 -07001593 } catch (GeneralSecurityException e) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001594 throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING,
1595 "Failed to collect certificates from " + apkPath, e);
Jeff Sharkeybc097552014-09-09 14:57:26 -07001596 } catch (IOException | RuntimeException e) {
1597 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1598 "Failed to collect certificates from " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001599 } finally {
1600 closeQuietly(jarFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 }
1603
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001604 private static Signature[] convertToSignatures(Certificate[][] certs)
1605 throws CertificateEncodingException {
1606 final Signature[] res = new Signature[certs.length];
1607 for (int i = 0; i < certs.length; i++) {
1608 res[i] = new Signature(certs[i]);
1609 }
1610 return res;
1611 }
1612
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001613 private static AssetManager newConfiguredAssetManager() {
1614 AssetManager assetManager = new AssetManager();
Romain Guy408afbf2017-01-25 10:23:03 -08001615 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 -07001616 Build.VERSION.RESOURCES_SDK_INT);
1617 return assetManager;
1618 }
1619
Jeff Sharkey275e0852014-06-17 18:18:49 -07001620 /**
1621 * Utility method that retrieves lightweight details about a single APK
1622 * file, including package name, split name, and install location.
1623 *
1624 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001625 * @param flags optional parse flags, such as
1626 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001627 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001628 public static ApkLite parseApkLite(File apkFile, int flags)
1629 throws PackageParserException {
1630 final String apkPath = apkFile.getAbsolutePath();
1631
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001632 AssetManager assets = null;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001633 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 try {
Adam Lesinski4e862812016-11-21 16:02:24 -08001635 assets = newConfiguredAssetManager();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001636 int cookie = assets.addAssetPath(apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001637 if (cookie == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001638 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1639 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001640 }
1641
Kenny Root05ca4c92011-09-15 10:36:25 -07001642 final DisplayMetrics metrics = new DisplayMetrics();
1643 metrics.setToDefaults();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001644
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001645 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001646
Jeff Sharkey275e0852014-06-17 18:18:49 -07001647 final Signature[] signatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001648 final Certificate[][] certificates;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001649 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1650 // TODO: factor signature related items out of Package object
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001651 final Package tempPkg = new Package((String) null);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001652 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1653 try {
Alex Klyubinabbc2bad2017-01-04 11:28:47 -08001654 collectCertificates(tempPkg, apkFile, flags);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001655 } finally {
1656 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1657 }
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001658 signatures = tempPkg.mSignatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001659 certificates = tempPkg.mCertificates;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001660 } else {
1661 signatures = null;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001662 certificates = null;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001663 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001664
Jeff Sharkey275e0852014-06-17 18:18:49 -07001665 final AttributeSet attrs = parser;
Adam Lesinski4e862812016-11-21 16:02:24 -08001666 return parseApkLite(apkPath, parser, attrs, flags, signatures, certificates);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001667
1668 } catch (XmlPullParserException | IOException | RuntimeException e) {
Dianne Hackborn34041732017-01-31 15:27:13 -08001669 Slog.w(TAG, "Failed to parse " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001670 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1671 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001673 IoUtils.closeQuietly(parser);
Adam Lesinski4e862812016-11-21 16:02:24 -08001674 IoUtils.closeQuietly(assets);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 }
1677
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001678 private static String validateName(String name, boolean requireSeparator,
1679 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001680 final int N = name.length();
1681 boolean hasSep = false;
1682 boolean front = true;
1683 for (int i=0; i<N; i++) {
1684 final char c = name.charAt(i);
1685 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1686 front = false;
1687 continue;
1688 }
1689 if (!front) {
1690 if ((c >= '0' && c <= '9') || c == '_') {
1691 continue;
1692 }
1693 }
1694 if (c == '.') {
1695 hasSep = true;
1696 front = true;
1697 continue;
1698 }
1699 return "bad character '" + c + "'";
1700 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001701 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1702 return "Invalid filename";
1703 }
1704 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 ? null : "must have at least one '.' separator";
1706 }
1707
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001708 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
Svet Ganov354cd3c2015-12-17 11:35:04 -08001709 AttributeSet attrs) throws IOException, XmlPullParserException,
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001710 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711
1712 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001713 while ((type = parser.next()) != XmlPullParser.START_TAG
1714 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 }
1716
Kenny Rootd2d29252011-08-08 11:27:57 -07001717 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001718 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1719 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001721 if (!parser.getName().equals(TAG_MANIFEST)) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001722 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1723 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 }
1725
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001726 final String packageName = attrs.getAttributeValue(null, "package");
1727 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001728 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001729 if (error != null) {
1730 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1731 "Invalid manifest package: " + error);
1732 }
1733 }
1734
Jeff Sharkey275e0852014-06-17 18:18:49 -07001735 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001736 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001737 if (splitName.length() == 0) {
1738 splitName = null;
1739 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001740 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001741 if (error != null) {
1742 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1743 "Invalid manifest split: " + error);
1744 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001745 }
1746 }
1747
1748 return Pair.create(packageName.intern(),
1749 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001750 }
1751
Adam Lesinski4e862812016-11-21 16:02:24 -08001752 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
1753 int flags, Signature[] signatures, Certificate[][] certificates)
1754 throws IOException, XmlPullParserException, PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001755 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001756
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001757 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001758 int versionCode = 0;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001759 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001760 boolean coreApp = false;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001761 boolean debuggable = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001762 boolean multiArch = false;
Selim Gurun2d291d82016-02-05 17:50:53 -08001763 boolean use32bitAbi = false;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001764 boolean extractNativeLibs = true;
Adam Lesinski4e862812016-11-21 16:02:24 -08001765 boolean isolatedSplits = false;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001766 boolean isFeatureSplit = false;
1767 String configForSplit = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001768 String usesSplitName = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001769
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001770 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001771 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001772 if (attr.equals("installLocation")) {
1773 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001774 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001775 } else if (attr.equals("versionCode")) {
1776 versionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001777 } else if (attr.equals("revisionCode")) {
1778 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001779 } else if (attr.equals("coreApp")) {
1780 coreApp = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski4e862812016-11-21 16:02:24 -08001781 } else if (attr.equals("isolatedSplits")) {
1782 isolatedSplits = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001783 } else if (attr.equals("configForSplit")) {
1784 configForSplit = attrs.getAttributeValue(i);
1785 } else if (attr.equals("isFeatureSplit")) {
1786 isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001787 }
1788 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001789
1790 // Only search the tree when the tag is directly below <manifest>
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001791 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001792 final int searchDepth = parser.getDepth() + 1;
1793
1794 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1795 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1796 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1797 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1798 continue;
1799 }
1800
Adam Lesinski4e862812016-11-21 16:02:24 -08001801 if (parser.getDepth() != searchDepth) {
1802 continue;
1803 }
1804
1805 if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
1806 final VerifierInfo verifier = parseVerifier(attrs);
Kenny Root05ca4c92011-09-15 10:36:25 -07001807 if (verifier != null) {
1808 verifiers.add(verifier);
1809 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001810 } else if (TAG_APPLICATION.equals(parser.getName())) {
Narayan Kamatha8755a82014-07-15 12:26:35 +01001811 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1812 final String attr = attrs.getAttributeName(i);
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001813 if ("debuggable".equals(attr)) {
1814 debuggable = attrs.getAttributeBooleanValue(i, false);
1815 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001816 if ("multiArch".equals(attr)) {
1817 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001818 }
Selim Gurun2d291d82016-02-05 17:50:53 -08001819 if ("use32bitAbi".equals(attr)) {
1820 use32bitAbi = attrs.getAttributeBooleanValue(i, false);
Tao Baic9a02372016-01-12 15:02:24 -08001821 }
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001822 if ("extractNativeLibs".equals(attr)) {
1823 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001824 }
1825 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001826 } else if (TAG_USES_SPLIT.equals(parser.getName())) {
1827 if (usesSplitName != null) {
1828 Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
1829 continue;
1830 }
1831
1832 usesSplitName = attrs.getAttributeValue(ANDROID_RESOURCES, "name");
1833 if (usesSplitName == null) {
1834 throw new PackageParserException(
1835 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1836 "<uses-split> tag requires 'android:name' attribute");
1837 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001838 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001839 }
1840
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001841 return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
1842 configForSplit, usesSplitName, versionCode, revisionCode, installLocation,
1843 verifiers, signatures, certificates, coreApp, debuggable, multiArch, use32bitAbi,
1844 extractNativeLibs, isolatedSplits);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001845 }
1846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 /**
1848 * Temporary.
1849 */
1850 static public Signature stringToSignature(String str) {
1851 final int N = str.length();
1852 byte[] sig = new byte[N];
1853 for (int i=0; i<N; i++) {
1854 sig[i] = (byte)str.charAt(i);
1855 }
1856 return new Signature(sig);
1857 }
1858
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001859 /**
Svet Ganov354cd3c2015-12-17 11:35:04 -08001860 * Parses a child package and adds it to the parent if successful. If you add
1861 * new tags that need to be supported by child packages make sure to add them
1862 * to {@link #CHILD_PACKAGE_TAGS}.
1863 *
1864 * @param parentPkg The parent that contains the child
1865 * @param res Resources against which to resolve values
1866 * @param parser Parser of the manifest
1867 * @param flags Flags about how to parse
1868 * @param outError Human readable error if parsing fails
1869 * @return True of parsing succeeded.
1870 *
1871 * @throws XmlPullParserException
1872 * @throws IOException
1873 */
1874 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
1875 int flags, String[] outError) throws XmlPullParserException, IOException {
1876 // Let ppl not abuse this mechanism by limiting the packages per APK
1877 if (parentPkg.childPackages != null && parentPkg.childPackages.size() + 2
1878 > MAX_PACKAGES_PER_APK) {
1879 outError[0] = "Maximum number of packages per APK is: " + MAX_PACKAGES_PER_APK;
1880 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1881 return false;
1882 }
1883
1884 // Make sure we have a valid child package name
1885 String childPackageName = parser.getAttributeValue(null, "package");
1886 if (validateName(childPackageName, true, false) != null) {
1887 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1888 return false;
1889 }
1890
1891 // Child packages must be unique
1892 if (childPackageName.equals(parentPkg.packageName)) {
1893 String message = "Child package name cannot be equal to parent package name: "
1894 + parentPkg.packageName;
1895 Slog.w(TAG, message);
1896 outError[0] = message;
1897 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1898 return false;
1899 }
1900
1901 // Child packages must be unique
1902 if (parentPkg.hasChildPackage(childPackageName)) {
1903 String message = "Duplicate child package:" + childPackageName;
1904 Slog.w(TAG, message);
1905 outError[0] = message;
1906 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1907 return false;
1908 }
1909
1910 // Go ahead and parse the child
1911 Package childPkg = new Package(childPackageName);
1912
1913 // Child package inherits parent version code/name/target SDK
1914 childPkg.mVersionCode = parentPkg.mVersionCode;
1915 childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
1916 childPkg.mVersionName = parentPkg.mVersionName;
1917 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
Todd Kennedy89d60182016-03-11 11:18:32 -08001918 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001919
1920 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
1921 if (childPkg == null) {
1922 // If we got null then error was set during child parsing
1923 return false;
1924 }
1925
1926 // Set the parent-child relation
1927 if (parentPkg.childPackages == null) {
1928 parentPkg.childPackages = new ArrayList<>();
1929 }
1930 parentPkg.childPackages.add(childPkg);
1931 childPkg.parentPackage = parentPkg;
1932
1933 return true;
1934 }
1935
1936 /**
1937 * Parse the manifest of a <em>base APK</em>. When adding new features you
1938 * need to consider whether they should be supported by split APKs and child
1939 * packages.
1940 *
1941 * @param res The resources from which to resolve values
1942 * @param parser The manifest parser
1943 * @param flags Flags how to parse
1944 * @param outError Human readable error message
1945 * @return Parsed package or null on error.
1946 *
1947 * @throws XmlPullParserException
1948 * @throws IOException
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001949 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001950 private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001951 String[] outError) throws XmlPullParserException, IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001952 final String splitName;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001953 final String pkgName;
1954
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001955 try {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001956 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001957 pkgName = packageSplit.first;
1958 splitName = packageSplit.second;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001959
1960 if (!TextUtils.isEmpty(splitName)) {
1961 outError[0] = "Expected base APK, but found split " + splitName;
1962 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1963 return null;
1964 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001965 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001966 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1967 return null;
1968 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001969
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001970 final Package pkg = new Package(pkgName);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001971
Svet Ganov354cd3c2015-12-17 11:35:04 -08001972 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001973 com.android.internal.R.styleable.AndroidManifest);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001974
Dianne Hackborn8472e612014-01-23 17:57:20 -08001975 pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001976 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001977 pkg.baseRevisionCode = sa.getInteger(
1978 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001979 pkg.mVersionName = sa.getNonConfigurationString(
1980 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001981 if (pkg.mVersionName != null) {
1982 pkg.mVersionName = pkg.mVersionName.intern();
1983 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001984
1985 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
1986
1987 sa.recycle();
1988
1989 return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
1990 }
1991
1992 /**
1993 * This is the common parsing routing for handling parent and child
1994 * packages in a base APK. The difference between parent and child
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001995 * parsing is that some tags are not supported by child packages as
Svet Ganov354cd3c2015-12-17 11:35:04 -08001996 * well as some manifest attributes are ignored. The implementation
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001997 * assumes the calling code has already handled the manifest tag if needed
Svet Ganov354cd3c2015-12-17 11:35:04 -08001998 * (this applies to the parent only).
1999 *
2000 * @param pkg The package which to populate
2001 * @param acceptedTags Which tags to handle, null to handle all
2002 * @param res Resources against which to resolve values
2003 * @param parser Parser of the manifest
2004 * @param flags Flags about how to parse
2005 * @param outError Human readable error if parsing fails
2006 * @return The package if parsing succeeded or null.
2007 *
2008 * @throws XmlPullParserException
2009 * @throws IOException
2010 */
2011 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
2012 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
2013 IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002014 mParseInstrumentationArgs = null;
2015 mParseActivityArgs = null;
2016 mParseServiceArgs = null;
2017 mParseProviderArgs = null;
2018
2019 int type;
2020 boolean foundApp = false;
2021
2022 TypedArray sa = res.obtainAttributes(parser,
2023 com.android.internal.R.styleable.AndroidManifest);
2024
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002025 String str = sa.getNonConfigurationString(
2026 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
2027 if (str != null && str.length() > 0) {
Chad Brubaker32d07dc2016-12-01 15:30:01 -08002028 if ((flags & PARSE_IS_EPHEMERAL) != 0) {
2029 outError[0] = "sharedUserId not allowed in ephemeral application";
2030 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
2031 return null;
2032 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002033 String nameError = validateName(str, true, false);
Svet Ganov354cd3c2015-12-17 11:35:04 -08002034 if (nameError != null && !"android".equals(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002035 outError[0] = "<manifest> specifies bad sharedUserId name \""
2036 + str + "\": " + nameError;
2037 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
2038 return null;
2039 }
2040 pkg.mSharedUserId = str.intern();
2041 pkg.mSharedUserLabel = sa.getResourceId(
2042 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
2043 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08002044
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08002045 pkg.installLocation = sa.getInteger(
2046 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07002047 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002048 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07002049
Todd Kennedy11e45072017-01-25 13:24:21 -08002050 final int targetSandboxVersion = sa.getInteger(
2051 com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion,
2052 PARSE_DEFAULT_TARGET_SANDBOX);
2053 pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion;
Alan Viverettefd274a02014-03-27 15:39:15 -07002054
Kenny Root7cb9be22012-05-30 15:30:37 -07002055 /* Set the global "forward lock" flag */
2056 if ((flags & PARSE_FORWARD_LOCK) != 0) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002057 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
Kenny Root7cb9be22012-05-30 15:30:37 -07002058 }
2059
2060 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07002061 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07002062 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
2063 }
2064
Adam Lesinski4e862812016-11-21 16:02:24 -08002065 if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
2066 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
2067 }
2068
Dianne Hackborn723738c2009-06-25 19:48:04 -07002069 // Resource boolean are -1, so 1 means we don't know the value.
2070 int supportsSmallScreens = 1;
2071 int supportsNormalScreens = 1;
2072 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002073 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002074 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002075 int anyDensity = 1;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07002078 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2079 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2080 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002081 continue;
2082 }
2083
2084 String tagName = parser.getName();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002085
2086 if (acceptedTags != null && !acceptedTags.contains(tagName)) {
2087 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
2088 + tagName + " at " + mArchiveSourcePath + " "
2089 + parser.getPositionDescription());
2090 XmlUtils.skipCurrentTag(parser);
2091 continue;
2092 }
2093
2094 if (tagName.equals(TAG_APPLICATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002095 if (foundApp) {
2096 if (RIGID_PARSER) {
2097 outError[0] = "<manifest> has more than one <application>";
2098 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2099 return null;
2100 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002101 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002102 XmlUtils.skipCurrentTag(parser);
2103 continue;
2104 }
2105 }
2106
2107 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002108 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 return null;
2110 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002111 } else if (tagName.equals(TAG_OVERLAY)) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002112 sa = res.obtainAttributes(parser,
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002113 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
2114 pkg.mOverlayTarget = sa.getString(
2115 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002116 pkg.mOverlayPriority = sa.getInt(
2117 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
2118 0);
Jaekyun Seok04342892017-03-02 15:24:19 +09002119 pkg.mIsStaticOverlay = sa.getBoolean(
2120 com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
2121 false);
Todd Leeea2f3be2017-03-16 14:00:52 -07002122 final String propName = sa.getString(
2123 com.android.internal.R.styleable
2124 .AndroidManifestResourceOverlay_requiredSystemPropertyName);
2125 final String propValue = sa.getString(
2126 com.android.internal.R.styleable
2127 .AndroidManifestResourceOverlay_requiredSystemPropertyValue);
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002128 sa.recycle();
2129
2130 if (pkg.mOverlayTarget == null) {
2131 outError[0] = "<overlay> does not specify a target package";
2132 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2133 return null;
2134 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002135
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002136 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
2137 outError[0] = "<overlay> priority must be between 0 and 9999";
2138 mParseError =
2139 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2140 return null;
2141 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002142
2143 // check to see if overlay should be excluded based on system property condition
2144 if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
2145 Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
2146 + pkg.baseCodePath+ ": overlay ignored due to required system property: "
2147 + propName + " with value: " + propValue);
2148 return null;
Jaekyun Seok04342892017-03-02 15:24:19 +09002149 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002150
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002151 XmlUtils.skipCurrentTag(parser);
2152
Svet Ganov354cd3c2015-12-17 11:35:04 -08002153 } else if (tagName.equals(TAG_KEY_SETS)) {
2154 if (!parseKeySets(pkg, res, parser, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08002155 return null;
2156 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002157 } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002158 if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 return null;
2160 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002161 } else if (tagName.equals(TAG_PERMISSION)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002162 if (!parsePermission(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 return null;
2164 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002165 } else if (tagName.equals(TAG_PERMISSION_TREE)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002166 if (!parsePermissionTree(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002167 return null;
2168 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002169 } else if (tagName.equals(TAG_USES_PERMISSION)) {
2170 if (!parseUsesPermission(pkg, res, parser)) {
Svetoslav96a77162015-04-03 13:58:33 -07002171 return null;
2172 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002173 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
2174 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
2175 if (!parseUsesPermission(pkg, res, parser)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002176 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002178 } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179 ConfigurationInfo cPref = new ConfigurationInfo();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002180 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
2182 cPref.reqTouchScreen = sa.getInt(
2183 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
2184 Configuration.TOUCHSCREEN_UNDEFINED);
2185 cPref.reqKeyboardType = sa.getInt(
2186 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
2187 Configuration.KEYBOARD_UNDEFINED);
2188 if (sa.getBoolean(
2189 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
2190 false)) {
2191 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
2192 }
2193 cPref.reqNavigation = sa.getInt(
2194 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
2195 Configuration.NAVIGATION_UNDEFINED);
2196 if (sa.getBoolean(
2197 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
2198 false)) {
2199 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
2200 }
2201 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002202 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002203
2204 XmlUtils.skipCurrentTag(parser);
2205
Svet Ganov354cd3c2015-12-17 11:35:04 -08002206 } else if (tagName.equals(TAG_USES_FEATURE)) {
2207 FeatureInfo fi = parseUsesFeature(res, parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002208 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
2209
Dianne Hackborn49237342009-08-27 20:08:01 -07002210 if (fi.name == null) {
2211 ConfigurationInfo cPref = new ConfigurationInfo();
2212 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002213 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07002214 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07002215
2216 XmlUtils.skipCurrentTag(parser);
2217
Svet Ganov354cd3c2015-12-17 11:35:04 -08002218 } else if (tagName.equals(TAG_FEATURE_GROUP)) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002219 FeatureGroupInfo group = new FeatureGroupInfo();
2220 ArrayList<FeatureInfo> features = null;
2221 final int innerDepth = parser.getDepth();
2222 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2223 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2224 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2225 continue;
2226 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07002227
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002228 final String innerTagName = parser.getName();
2229 if (innerTagName.equals("uses-feature")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002230 FeatureInfo featureInfo = parseUsesFeature(res, parser);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002231 // FeatureGroups are stricter and mandate that
2232 // any <uses-feature> declared are mandatory.
2233 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
2234 features = ArrayUtils.add(features, featureInfo);
2235 } else {
2236 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
2237 " at " + mArchiveSourcePath + " " +
2238 parser.getPositionDescription());
2239 }
2240 XmlUtils.skipCurrentTag(parser);
2241 }
2242
2243 if (features != null) {
2244 group.features = new FeatureInfo[features.size()];
2245 group.features = features.toArray(group.features);
2246 }
2247 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07002248
Svet Ganov354cd3c2015-12-17 11:35:04 -08002249 } else if (tagName.equals(TAG_USES_SDK)) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07002250 if (SDK_VERSION > 0) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002251 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002252 com.android.internal.R.styleable.AndroidManifestUsesSdk);
2253
Todd Kennedy4f657082016-06-28 10:31:05 -07002254 int minVers = 1;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002255 String minCode = null;
2256 int targetVers = 0;
2257 String targetCode = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002258
Dianne Hackborn851a5412009-05-08 12:06:44 -07002259 TypedValue val = sa.peekValue(
2260 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
2261 if (val != null) {
2262 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
2263 targetCode = minCode = val.string.toString();
2264 } else {
2265 // If it's not a string, it's an integer.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002266 targetVers = minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002267 }
2268 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002269
Dianne Hackborn851a5412009-05-08 12:06:44 -07002270 val = sa.peekValue(
2271 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
2272 if (val != null) {
2273 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
Todd Kennedy89d60182016-03-11 11:18:32 -08002274 targetCode = val.string.toString();
2275 if (minCode == null) {
2276 minCode = targetCode;
2277 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002278 } else {
2279 // If it's not a string, it's an integer.
2280 targetVers = val.data;
2281 }
2282 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002284 sa.recycle();
2285
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002286 final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode,
2287 SDK_VERSION, SDK_CODENAMES, outError);
2288 if (minSdkVersion < 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002289 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2290 return null;
2291 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002292
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002293 final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers,
2294 targetCode, SDK_VERSION, SDK_CODENAMES, outError);
2295 if (targetSdkVersion < 0) {
2296 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2297 return null;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002298 }
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002299
2300 pkg.applicationInfo.minSdkVersion = minSdkVersion;
2301 pkg.applicationInfo.targetSdkVersion = targetSdkVersion;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002302 }
2303
2304 XmlUtils.skipCurrentTag(parser);
2305
Svet Ganov354cd3c2015-12-17 11:35:04 -08002306 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
2307 sa = res.obtainAttributes(parser,
Dianne Hackborn723738c2009-06-25 19:48:04 -07002308 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
2309
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002310 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
2311 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
2312 0);
2313 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
2314 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
2315 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07002316 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
2317 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
2318 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002319
Dianne Hackborn723738c2009-06-25 19:48:04 -07002320 // This is a trick to get a boolean and still able to detect
2321 // if a value was actually set.
2322 supportsSmallScreens = sa.getInteger(
2323 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
2324 supportsSmallScreens);
2325 supportsNormalScreens = sa.getInteger(
2326 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
2327 supportsNormalScreens);
2328 supportsLargeScreens = sa.getInteger(
2329 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
2330 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002331 supportsXLargeScreens = sa.getInteger(
2332 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
2333 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002334 resizeable = sa.getInteger(
2335 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002336 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002337 anyDensity = sa.getInteger(
2338 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
2339 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07002340
2341 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002342
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002343 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002344
Svet Ganov354cd3c2015-12-17 11:35:04 -08002345 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
2346 sa = res.obtainAttributes(parser,
Dianne Hackborn854060af2009-07-09 18:14:31 -07002347 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
2348
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002349 // Note: don't allow this value to be a reference to a resource
2350 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07002351 String name = sa.getNonResourceString(
2352 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
2353
2354 sa.recycle();
2355
2356 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
2357 if (pkg.protectedBroadcasts == null) {
2358 pkg.protectedBroadcasts = new ArrayList<String>();
2359 }
2360 if (!pkg.protectedBroadcasts.contains(name)) {
2361 pkg.protectedBroadcasts.add(name.intern());
2362 }
2363 }
2364
2365 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002366
Svet Ganov354cd3c2015-12-17 11:35:04 -08002367 } else if (tagName.equals(TAG_INSTRUMENTATION)) {
2368 if (parseInstrumentation(pkg, res, parser, outError) == null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002369 return null;
2370 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002371 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
2372 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002373 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2374
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002375 String orig =sa.getNonConfigurationString(
2376 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002377 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002378 if (pkg.mOriginalPackages == null) {
2379 pkg.mOriginalPackages = new ArrayList<String>();
2380 pkg.mRealPackage = pkg.packageName;
2381 }
2382 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002383 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002384
2385 sa.recycle();
2386
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002387 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002388
Svet Ganov354cd3c2015-12-17 11:35:04 -08002389 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
2390 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002391 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2392
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002393 String name = sa.getNonConfigurationString(
2394 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002395
2396 sa.recycle();
2397
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002398 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002399 if (pkg.mAdoptPermissions == null) {
2400 pkg.mAdoptPermissions = new ArrayList<String>();
2401 }
2402 pkg.mAdoptPermissions.add(name);
2403 }
2404
2405 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002406
Svet Ganov354cd3c2015-12-17 11:35:04 -08002407 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002408 // Just skip this tag
2409 XmlUtils.skipCurrentTag(parser);
2410 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002411
Svet Ganov354cd3c2015-12-17 11:35:04 -08002412 } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002413 // Just skip this tag
2414 XmlUtils.skipCurrentTag(parser);
2415 continue;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002416 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
Michael Wrighteaeb1902013-09-05 18:15:57 -07002417 XmlUtils.skipCurrentTag(parser);
2418 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002419
Svet Ganov354cd3c2015-12-17 11:35:04 -08002420 } else if (tagName.equals(TAG_EAT_COMMENT)) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002421 // Just skip this tag
2422 XmlUtils.skipCurrentTag(parser);
2423 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002424
Svet Ganov354cd3c2015-12-17 11:35:04 -08002425 } else if (tagName.equals(TAG_PACKAGE)) {
Svet Ganova7532cf2016-05-02 08:13:17 -07002426 if (!MULTI_PACKAGE_APK_ENABLED) {
2427 XmlUtils.skipCurrentTag(parser);
2428 continue;
2429 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002430 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
2431 // If parsing a child failed the error is already set
2432 return null;
2433 }
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002434
2435 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
2436 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
2437 sa = res.obtainAttributes(parser,
2438 com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
2439 final String hash = sa.getNonConfigurationString(
2440 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
2441 sa.recycle();
2442
2443 pkg.restrictUpdateHash = null;
2444 if (hash != null) {
2445 final int hashLength = hash.length();
2446 final byte[] hashBytes = new byte[hashLength / 2];
2447 for (int i = 0; i < hashLength; i += 2){
2448 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
2449 + Character.digit(hash.charAt(i + 1), 16));
2450 }
2451 pkg.restrictUpdateHash = hashBytes;
2452 }
2453 }
2454
2455 XmlUtils.skipCurrentTag(parser);
2456
Dianne Hackborn854060af2009-07-09 18:14:31 -07002457 } else if (RIGID_PARSER) {
2458 outError[0] = "Bad element under <manifest>: "
2459 + parser.getName();
2460 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2461 return null;
2462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002463 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002464 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002465 + " at " + mArchiveSourcePath + " "
2466 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 XmlUtils.skipCurrentTag(parser);
2468 continue;
2469 }
2470 }
2471
2472 if (!foundApp && pkg.instrumentation.size() == 0) {
2473 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
2474 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
2475 }
2476
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002477 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002478 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002479 for (int ip=0; ip<NP; ip++) {
2480 final PackageParser.NewPermissionInfo npi
2481 = PackageParser.NEW_PERMISSIONS[ip];
2482 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
2483 break;
2484 }
2485 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002486 if (implicitPerms == null) {
2487 implicitPerms = new StringBuilder(128);
2488 implicitPerms.append(pkg.packageName);
2489 implicitPerms.append(": compat added ");
2490 } else {
2491 implicitPerms.append(' ');
2492 }
2493 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002494 pkg.requestedPermissions.add(npi.name);
2495 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002496 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002497 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002498 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002499 }
Dianne Hackborn79245122012-03-12 10:51:26 -07002500
2501 final int NS = PackageParser.SPLIT_PERMISSIONS.length;
2502 for (int is=0; is<NS; is++) {
2503 final PackageParser.SplitPermissionInfo spi
2504 = PackageParser.SPLIT_PERMISSIONS[is];
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -07002505 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
2506 || !pkg.requestedPermissions.contains(spi.rootPerm)) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07002507 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07002508 }
2509 for (int in=0; in<spi.newPerms.length; in++) {
2510 final String perm = spi.newPerms[in];
2511 if (!pkg.requestedPermissions.contains(perm)) {
2512 pkg.requestedPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07002513 }
2514 }
2515 }
2516
Dianne Hackborn723738c2009-06-25 19:48:04 -07002517 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
2518 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002519 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002520 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
2521 }
2522 if (supportsNormalScreens != 0) {
2523 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
2524 }
2525 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
2526 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002527 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002528 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
2529 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002530 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
2531 && pkg.applicationInfo.targetSdkVersion
2532 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
2533 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
2534 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002535 if (resizeable < 0 || (resizeable > 0
2536 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002537 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002538 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
2539 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002540 if (anyDensity < 0 || (anyDensity > 0
2541 && pkg.applicationInfo.targetSdkVersion
2542 >= android.os.Build.VERSION_CODES.DONUT)) {
2543 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07002544 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07002545
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002546 // At this point we can check if an application is not supporting densities and hence
2547 // cannot be windowed / resized. Note that an SDK version of 0 is common for
2548 // pre-Doughnut applications.
2549 if (pkg.applicationInfo.usesCompatibilityMode()) {
Winson Chungd3395382016-12-13 11:49:09 -08002550 adjustPackageToBeUnresizeableAndUnpipable(pkg);
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 return pkg;
2553 }
2554
Todd Leeea2f3be2017-03-16 14:00:52 -07002555 private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
2556
2557 if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
2558 if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
2559 // malformed condition - incomplete
2560 Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
2561 + "=" + propValue + "' - require both requiredSystemPropertyName"
2562 + " AND requiredSystemPropertyValue to be specified.");
2563 return false;
2564 }
2565 // no valid condition set - so no exclusion criteria, overlay will be included.
2566 return true;
2567 }
2568
2569 // check property value - make sure it is both set and equal to expected value
2570 final String currValue = SystemProperties.get(propName);
2571 return (currValue != null && currValue.equals(propValue));
2572 }
2573
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002574 /**
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002575 * This is a pre-density application which will get scaled - instead of being pixel perfect.
2576 * This type of application is not resizable.
2577 *
2578 * @param pkg The package which needs to be marked as unresizable.
2579 */
Winson Chungd3395382016-12-13 11:49:09 -08002580 private void adjustPackageToBeUnresizeableAndUnpipable(Package pkg) {
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002581 for (Activity a : pkg.activities) {
2582 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -08002583 a.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE;
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002584 }
2585 }
2586
2587 /**
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002588 * Computes the targetSdkVersion to use at runtime. If the package is not
2589 * compatible with this platform, populates {@code outError[0]} with an
2590 * error message.
2591 * <p>
2592 * If {@code targetCode} is not specified, e.g. the value is {@code null},
2593 * then the {@code targetVers} will be returned unmodified.
2594 * <p>
2595 * Otherwise, the behavior varies based on whether the current platform
2596 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2597 * has length > 0:
2598 * <ul>
2599 * <li>If this is a pre-release platform and the value specified by
2600 * {@code targetCode} is contained within the array of allowed pre-release
2601 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2602 * <li>If this is a released platform, this method will return -1 to
2603 * indicate that the package is not compatible with this platform.
2604 * </ul>
2605 *
2606 * @param targetVers targetSdkVersion number, if specified in the
2607 * application manifest, or 0 otherwise
2608 * @param targetCode targetSdkVersion code, if specified in the application
2609 * manifest, or {@code null} otherwise
2610 * @param platformSdkVersion platform SDK version number, typically
2611 * Build.VERSION.SDK_INT
2612 * @param platformSdkCodenames array of allowed pre-release SDK codenames
2613 * for this platform
2614 * @param outError output array to populate with error, if applicable
2615 * @return the targetSdkVersion to use at runtime, or -1 if the package is
2616 * not compatible with this platform
2617 * @hide Exposed for unit testing only.
2618 */
2619 @TestApi
2620 public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
2621 @Nullable String targetCode, @IntRange(from = 1) int platformSdkVersion,
2622 @NonNull String[] platformSdkCodenames, @NonNull String[] outError) {
2623 // If it's a release SDK, return the version number unmodified.
2624 if (targetCode == null) {
2625 return targetVers;
2626 }
2627
2628 // If it's a pre-release SDK and the codename matches this platform, it
2629 // definitely targets this SDK.
2630 if (ArrayUtils.contains(platformSdkCodenames, targetCode)) {
2631 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2632 }
2633
2634 // Otherwise, we're looking at an incompatible pre-release SDK.
2635 if (platformSdkCodenames.length > 0) {
2636 outError[0] = "Requires development platform " + targetCode
2637 + " (current platform is any of "
2638 + Arrays.toString(platformSdkCodenames) + ")";
2639 } else {
2640 outError[0] = "Requires development platform " + targetCode
2641 + " but this is a release platform.";
2642 }
2643 return -1;
2644 }
2645
2646 /**
2647 * Computes the minSdkVersion to use at runtime. If the package is not
2648 * compatible with this platform, populates {@code outError[0]} with an
2649 * error message.
2650 * <p>
2651 * If {@code minCode} is not specified, e.g. the value is {@code null},
2652 * then behavior varies based on the {@code platformSdkVersion}:
2653 * <ul>
2654 * <li>If the platform SDK version is greater than or equal to the
2655 * {@code minVers}, returns the {@code mniVers} unmodified.
2656 * <li>Otherwise, returns -1 to indicate that the package is not
2657 * compatible with this platform.
2658 * </ul>
2659 * <p>
2660 * Otherwise, the behavior varies based on whether the current platform
2661 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2662 * has length > 0:
2663 * <ul>
2664 * <li>If this is a pre-release platform and the value specified by
2665 * {@code targetCode} is contained within the array of allowed pre-release
2666 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2667 * <li>If this is a released platform, this method will return -1 to
2668 * indicate that the package is not compatible with this platform.
2669 * </ul>
2670 *
2671 * @param minVers minSdkVersion number, if specified in the application
2672 * manifest, or 1 otherwise
2673 * @param minCode minSdkVersion code, if specified in the application
2674 * manifest, or {@code null} otherwise
2675 * @param platformSdkVersion platform SDK version number, typically
2676 * Build.VERSION.SDK_INT
2677 * @param platformSdkCodenames array of allowed prerelease SDK codenames
2678 * for this platform
2679 * @param outError output array to populate with error, if applicable
2680 * @return the minSdkVersion to use at runtime, or -1 if the package is not
2681 * compatible with this platform
2682 * @hide Exposed for unit testing only.
2683 */
2684 @TestApi
2685 public static int computeMinSdkVersion(@IntRange(from = 1) int minVers,
2686 @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion,
2687 @NonNull String[] platformSdkCodenames, @NonNull String[] outError) {
2688 // If it's a release SDK, make sure we meet the minimum SDK requirement.
2689 if (minCode == null) {
2690 if (minVers <= platformSdkVersion) {
2691 return minVers;
2692 }
2693
2694 // We don't meet the minimum SDK requirement.
2695 outError[0] = "Requires newer sdk version #" + minVers
2696 + " (current version is #" + platformSdkVersion + ")";
2697 return -1;
2698 }
2699
2700 // If it's a pre-release SDK and the codename matches this platform, we
2701 // definitely meet the minimum SDK requirement.
2702 if (ArrayUtils.contains(platformSdkCodenames, minCode)) {
2703 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2704 }
2705
2706 // Otherwise, we're looking at an incompatible pre-release SDK.
2707 if (platformSdkCodenames.length > 0) {
2708 outError[0] = "Requires development platform " + minCode
2709 + " (current platform is any of "
2710 + Arrays.toString(platformSdkCodenames) + ")";
2711 } else {
2712 outError[0] = "Requires development platform " + minCode
2713 + " but this is a release platform.";
2714 }
2715 return -1;
2716 }
2717
Todd Kennedy27c24fb2015-09-17 16:49:25 -07002718 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002719 FeatureInfo fi = new FeatureInfo();
2720 TypedArray sa = res.obtainAttributes(attrs,
2721 com.android.internal.R.styleable.AndroidManifestUsesFeature);
2722 // Note: don't allow this value to be a reference to a resource
2723 // that may change.
2724 fi.name = sa.getNonResourceString(
2725 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
Jeff Sharkey115d2c12016-02-15 17:25:57 -07002726 fi.version = sa.getInt(
2727 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002728 if (fi.name == null) {
2729 fi.reqGlEsVersion = sa.getInt(
2730 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
2731 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2732 }
2733 if (sa.getBoolean(
2734 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
2735 fi.flags |= FeatureInfo.FLAG_REQUIRED;
2736 }
2737 sa.recycle();
2738 return fi;
2739 }
2740
Svet Ganov67882122016-12-11 16:36:34 -08002741 private boolean parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser,
2742 String[] outError) throws XmlPullParserException, IOException {
2743 TypedArray sa = res.obtainAttributes(parser,
2744 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary);
2745
2746 // Note: don't allow this value to be a reference to a resource that may change.
2747 String lname = sa.getNonResourceString(
2748 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
2749 final int version = sa.getInt(
2750 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
2751 String certSha256 = sa.getNonResourceString(com.android.internal.R.styleable
2752 .AndroidManifestUsesStaticLibrary_certDigest);
2753 sa.recycle();
2754
2755 // Since an APK providing a static shared lib can only provide the lib - fail if malformed
2756 if (lname == null || version < 0 || certSha256 == null) {
2757 outError[0] = "Bad uses-static-library declaration name: " + lname + " version: "
2758 + version + " certDigest" + certSha256;
2759 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2760 XmlUtils.skipCurrentTag(parser);
2761 return false;
2762 }
2763
2764 // Can depend only on one version of the same library
2765 if (pkg.usesStaticLibraries != null && pkg.usesStaticLibraries.contains(lname)) {
2766 outError[0] = "Depending on multiple versions of static library " + lname;
2767 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2768 XmlUtils.skipCurrentTag(parser);
2769 return false;
2770 }
2771
2772 lname = lname.intern();
2773 // We allow ":" delimiters in the SHA declaration as this is the format
2774 // emitted by the certtool making it easy for developers to copy/paste.
2775 certSha256 = certSha256.replace(":", "").toLowerCase();
2776 pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname);
2777 pkg.usesStaticLibrariesVersions = ArrayUtils.appendInt(
Svet Ganov8a10ef52017-02-16 20:58:09 -08002778 pkg.usesStaticLibrariesVersions, version, true);
Svet Ganov67882122016-12-11 16:36:34 -08002779 pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String.class,
Svet Ganov8a10ef52017-02-16 20:58:09 -08002780 pkg.usesStaticLibrariesCertDigests, certSha256, true);
Svet Ganov67882122016-12-11 16:36:34 -08002781
2782 XmlUtils.skipCurrentTag(parser);
2783
2784 return true;
2785 }
2786
Svet Ganov354cd3c2015-12-17 11:35:04 -08002787 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
2788 throws XmlPullParserException, IOException {
2789 TypedArray sa = res.obtainAttributes(parser,
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002790 com.android.internal.R.styleable.AndroidManifestUsesPermission);
2791
2792 // Note: don't allow this value to be a reference to a resource
2793 // that may change.
2794 String name = sa.getNonResourceString(
2795 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002796
Christopher Tatefb0676a2013-09-16 16:34:52 -07002797 int maxSdkVersion = 0;
2798 TypedValue val = sa.peekValue(
2799 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
2800 if (val != null) {
2801 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
2802 maxSdkVersion = val.data;
2803 }
2804 }
2805
Dianne Hackborncd154e92017-02-28 17:37:35 -08002806 final String requiredFeature = sa.getNonConfigurationString(
2807 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
2808
2809 final String requiredNotfeature = sa.getNonConfigurationString(
2810 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
2811
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002812 sa.recycle();
2813
Dianne Hackborncd154e92017-02-28 17:37:35 -08002814 XmlUtils.skipCurrentTag(parser);
2815
2816 if (name == null) {
2817 return true;
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002818 }
2819
Dianne Hackborncd154e92017-02-28 17:37:35 -08002820 if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
2821 return true;
2822 }
2823
2824 // Only allow requesting this permission if the platform supports the given feature.
2825 if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
2826 return true;
2827 }
2828
2829 // Only allow requesting this permission if the platform doesn't support the given feature.
2830 if (requiredNotfeature != null && mCallback != null
2831 && mCallback.hasFeature(requiredNotfeature)) {
2832 return true;
2833 }
2834
2835 int index = pkg.requestedPermissions.indexOf(name);
2836 if (index == -1) {
2837 pkg.requestedPermissions.add(name.intern());
2838 } else {
2839 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
2840 + name + " in package: " + pkg.packageName + " at: "
2841 + parser.getPositionDescription());
2842 }
2843
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002844 return true;
2845 }
2846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002847 private static String buildClassName(String pkg, CharSequence clsSeq,
2848 String[] outError) {
2849 if (clsSeq == null || clsSeq.length() <= 0) {
2850 outError[0] = "Empty class name in package " + pkg;
2851 return null;
2852 }
2853 String cls = clsSeq.toString();
2854 char c = cls.charAt(0);
2855 if (c == '.') {
Narayan Kamath07ac1442017-02-10 15:08:07 +00002856 return pkg + cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002857 }
2858 if (cls.indexOf('.') < 0) {
2859 StringBuilder b = new StringBuilder(pkg);
2860 b.append('.');
2861 b.append(cls);
Narayan Kamath07ac1442017-02-10 15:08:07 +00002862 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002863 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002864 return cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002865 }
2866
2867 private static String buildCompoundName(String pkg,
2868 CharSequence procSeq, String type, String[] outError) {
2869 String proc = procSeq.toString();
2870 char c = proc.charAt(0);
2871 if (pkg != null && c == ':') {
2872 if (proc.length() < 2) {
2873 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
2874 + ": must be at least two characters";
2875 return null;
2876 }
2877 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002878 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002879 if (nameError != null) {
2880 outError[0] = "Invalid " + type + " name " + proc + " in package "
2881 + pkg + ": " + nameError;
2882 return null;
2883 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002884 return pkg + proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002885 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002886 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 if (nameError != null && !"system".equals(proc)) {
2888 outError[0] = "Invalid " + type + " name " + proc + " in package "
2889 + pkg + ": " + nameError;
2890 return null;
2891 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002892 return proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002893 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002895 private static String buildProcessName(String pkg, String defProc,
2896 CharSequence procSeq, int flags, String[] separateProcesses,
2897 String[] outError) {
2898 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
2899 return defProc != null ? defProc : pkg;
2900 }
2901 if (separateProcesses != null) {
2902 for (int i=separateProcesses.length-1; i>=0; i--) {
2903 String sp = separateProcesses[i];
2904 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
2905 return pkg;
2906 }
2907 }
2908 }
2909 if (procSeq == null || procSeq.length() <= 0) {
2910 return defProc;
2911 }
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002912 return buildCompoundName(pkg, procSeq, "process", outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002913 }
2914
2915 private static String buildTaskAffinityName(String pkg, String defProc,
2916 CharSequence procSeq, String[] outError) {
2917 if (procSeq == null) {
2918 return defProc;
2919 }
2920 if (procSeq.length() <= 0) {
2921 return null;
2922 }
2923 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
2924 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002925
dcashman989eb3712014-06-17 12:56:12 -07002926 private boolean parseKeySets(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002927 XmlResourceParser parser, String[] outError)
Geremy Condraf1bcca82013-01-07 22:35:24 -08002928 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07002929 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08002930 // all the keys and keysets that we want must be defined here
2931 // so we're going to iterate over the parser and pull out the things we want
2932 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07002933 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002934 int type;
dcashman989eb3712014-06-17 12:56:12 -07002935 String currentKeySet = null;
2936 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
2937 ArraySet<String> upgradeKeySets = new ArraySet<String>();
2938 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
2939 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08002940 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2941 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2942 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07002943 if (parser.getDepth() == currentKeySetDepth) {
2944 currentKeySet = null;
2945 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07002946 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002947 continue;
2948 }
dcashman989eb3712014-06-17 12:56:12 -07002949 String tagName = parser.getName();
2950 if (tagName.equals("key-set")) {
2951 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07002952 outError[0] = "Improperly nested 'key-set' tag at "
2953 + parser.getPositionDescription();
2954 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002955 return false;
2956 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002957 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002958 com.android.internal.R.styleable.AndroidManifestKeySet);
2959 final String keysetName = sa.getNonResourceString(
2960 com.android.internal.R.styleable.AndroidManifestKeySet_name);
2961 definedKeySets.put(keysetName, new ArraySet<String>());
2962 currentKeySet = keysetName;
2963 currentKeySetDepth = parser.getDepth();
2964 sa.recycle();
2965 } else if (tagName.equals("public-key")) {
2966 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002967 outError[0] = "Improperly nested 'key-set' tag at "
2968 + parser.getPositionDescription();
2969 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002970 return false;
2971 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002972 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002973 com.android.internal.R.styleable.AndroidManifestPublicKey);
2974 final String publicKeyName = sa.getNonResourceString(
2975 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002976 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07002977 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
2978 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002979 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
2980 + " on first use at " + parser.getPositionDescription();
2981 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07002982 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002983 return false;
2984 } else if (encodedKey != null) {
2985 PublicKey currentKey = parsePublicKey(encodedKey);
2986 if (currentKey == null) {
2987 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
2988 + parser.getPositionDescription() + " key-set " + currentKeySet
2989 + " will not be added to the package's defined key-sets.");
2990 sa.recycle();
2991 improperKeySets.add(currentKeySet);
2992 XmlUtils.skipCurrentTag(parser);
2993 continue;
2994 }
2995 if (publicKeys.get(publicKeyName) == null
2996 || publicKeys.get(publicKeyName).equals(currentKey)) {
2997
2998 /* public-key first definition, or matches old definition */
2999 publicKeys.put(publicKeyName, currentKey);
3000 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003001 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07003002 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07003003 + parser.getPositionDescription();
3004 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003005 sa.recycle();
3006 return false;
3007 }
Kenny Root37dca152013-07-10 14:01:49 -07003008 }
dcashman989eb3712014-06-17 12:56:12 -07003009 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003010 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003011 XmlUtils.skipCurrentTag(parser);
3012 } else if (tagName.equals("upgrade-key-set")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003013 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003014 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
3015 String name = sa.getNonResourceString(
3016 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
3017 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003018 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003019 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003020 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07003021 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003022 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07003023 + parser.getPositionDescription();
3024 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003025 return false;
3026 } else {
dcashman989eb3712014-06-17 12:56:12 -07003027 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003028 + " at " + mArchiveSourcePath + " "
3029 + parser.getPositionDescription());
3030 XmlUtils.skipCurrentTag(parser);
3031 continue;
3032 }
3033 }
dcashman989eb3712014-06-17 12:56:12 -07003034 Set<String> publicKeyNames = publicKeys.keySet();
3035 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07003036 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
3037 + "'key-set' and 'public-key' names must be distinct.";
3038 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003039 return false;
3040 }
3041 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
3042 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
3043 final String keySetName = e.getKey();
3044 if (e.getValue().size() == 0) {
3045 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3046 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
3047 + " Not including in package's defined key-sets.");
3048 continue;
3049 } else if (improperKeySets.contains(keySetName)) {
3050 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3051 + "'key-set' " + keySetName + " contained improper 'public-key'"
3052 + " tags. Not including in package's defined key-sets.");
3053 continue;
3054 }
3055 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
3056 for (String s : e.getValue()) {
3057 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08003058 }
3059 }
dcashman989eb3712014-06-17 12:56:12 -07003060 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
3061 owner.mUpgradeKeySets = upgradeKeySets;
3062 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003063 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
3064 + "does not define all 'upgrade-key-set's .";
3065 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003066 return false;
3067 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003068 return true;
3069 }
3070
Dianne Hackborncd154e92017-02-28 17:37:35 -08003071 private boolean parsePermissionGroup(Package owner, int flags, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003072 XmlResourceParser parser, String[] outError)
3073 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003074 PermissionGroup perm = new PermissionGroup(owner);
3075
Svet Ganov354cd3c2015-12-17 11:35:04 -08003076 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003077 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003078 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003079 "<permission-group>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003080 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
3081 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003082 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003083 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003084 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
3085 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 sa.recycle();
3087 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003088 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003089 }
3090
3091 perm.info.descriptionRes = sa.getResourceId(
3092 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
3093 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07003094 perm.info.flags = sa.getInt(
3095 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07003096 perm.info.priority = sa.getInt(
3097 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
Dianne Hackborn99222d22012-05-06 16:30:15 -07003098 if (perm.info.priority > 0 && (flags&PARSE_IS_SYSTEM) == 0) {
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07003099 perm.info.priority = 0;
3100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101
3102 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003103
Svet Ganov354cd3c2015-12-17 11:35:04 -08003104 if (!parseAllMetaData(res, parser, "<permission-group>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105 outError)) {
3106 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003107 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003108 }
3109
3110 owner.permissionGroups.add(perm);
3111
Dianne Hackborncd154e92017-02-28 17:37:35 -08003112 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003113 }
3114
Dianne Hackborncd154e92017-02-28 17:37:35 -08003115 private boolean parsePermission(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003116 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003117 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003118
Svet Ganov354cd3c2015-12-17 11:35:04 -08003119 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003120 com.android.internal.R.styleable.AndroidManifestPermission);
3121
Dianne Hackborncd154e92017-02-28 17:37:35 -08003122 Permission perm = new Permission(owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003123 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003124 "<permission>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003125 com.android.internal.R.styleable.AndroidManifestPermission_name,
3126 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003127 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003128 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003129 com.android.internal.R.styleable.AndroidManifestPermission_logo,
3130 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003131 sa.recycle();
3132 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003133 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003134 }
3135
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003136 // Note: don't allow this value to be a reference to a resource
3137 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003138 perm.info.group = sa.getNonResourceString(
3139 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
3140 if (perm.info.group != null) {
3141 perm.info.group = perm.info.group.intern();
3142 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003143
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003144 perm.info.descriptionRes = sa.getResourceId(
3145 com.android.internal.R.styleable.AndroidManifestPermission_description,
3146 0);
3147
3148 perm.info.protectionLevel = sa.getInt(
3149 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
3150 PermissionInfo.PROTECTION_NORMAL);
3151
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07003152 perm.info.flags = sa.getInt(
3153 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
3154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003155 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08003156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003157 if (perm.info.protectionLevel == -1) {
3158 outError[0] = "<permission> does not specify protectionLevel";
3159 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003160 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003161 }
Dianne Hackborne639da72012-02-21 15:11:13 -08003162
3163 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
3164
3165 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
Chad Brubakerc19706a2016-10-13 15:44:59 -07003166 if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_EPHEMERAL) == 0
Chad Brubakera5d70a12017-03-23 11:04:50 -07003167 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0
Chad Brubakerc19706a2016-10-13 15:44:59 -07003168 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
Dianne Hackborne639da72012-02-21 15:11:13 -08003169 PermissionInfo.PROTECTION_SIGNATURE) {
Chad Brubakerc19706a2016-10-13 15:44:59 -07003170 outError[0] = "<permission> protectionLevel specifies a non-ephemeral flag but is "
Dianne Hackborne639da72012-02-21 15:11:13 -08003171 + "not based on signature type";
3172 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003173 return false;
Dianne Hackborne639da72012-02-21 15:11:13 -08003174 }
3175 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003176
Svet Ganov354cd3c2015-12-17 11:35:04 -08003177 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003179 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180 }
3181
3182 owner.permissions.add(perm);
3183
Dianne Hackborncd154e92017-02-28 17:37:35 -08003184 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003185 }
3186
Dianne Hackborncd154e92017-02-28 17:37:35 -08003187 private boolean parsePermissionTree(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003188 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003189 throws XmlPullParserException, IOException {
3190 Permission perm = new Permission(owner);
3191
Svet Ganov354cd3c2015-12-17 11:35:04 -08003192 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003193 com.android.internal.R.styleable.AndroidManifestPermissionTree);
3194
3195 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003196 "<permission-tree>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003197 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
3198 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003199 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003200 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003201 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
3202 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003203 sa.recycle();
3204 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003205 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003206 }
3207
3208 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003210 int index = perm.info.name.indexOf('.');
3211 if (index > 0) {
3212 index = perm.info.name.indexOf('.', index+1);
3213 }
3214 if (index < 0) {
3215 outError[0] = "<permission-tree> name has less than three segments: "
3216 + perm.info.name;
3217 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003218 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003219 }
3220
3221 perm.info.descriptionRes = 0;
3222 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
3223 perm.tree = true;
3224
Svet Ganov354cd3c2015-12-17 11:35:04 -08003225 if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226 outError)) {
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 owner.permissions.add(perm);
3232
Dianne Hackborncd154e92017-02-28 17:37:35 -08003233 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003234 }
3235
3236 private Instrumentation parseInstrumentation(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003237 XmlResourceParser parser, String[] outError)
3238 throws XmlPullParserException, IOException {
3239 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003240 com.android.internal.R.styleable.AndroidManifestInstrumentation);
3241
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003242 if (mParseInstrumentationArgs == null) {
3243 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
3244 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
3245 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003246 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003247 com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003248 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
3249 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003250 mParseInstrumentationArgs.tag = "<instrumentation>";
3251 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003252
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003253 mParseInstrumentationArgs.sa = sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003254
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003255 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
3256 new InstrumentationInfo());
3257 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 sa.recycle();
3259 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3260 return null;
3261 }
3262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003263 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003264 // Note: don't allow this value to be a reference to a resource
3265 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003266 str = sa.getNonResourceString(
3267 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
3268 a.info.targetPackage = str != null ? str.intern() : null;
3269
Dianne Hackborn34041732017-01-31 15:27:13 -08003270 str = sa.getNonResourceString(
3271 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcess);
3272 a.info.targetProcess = str != null ? str.intern() : null;
3273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003274 a.info.handleProfiling = sa.getBoolean(
3275 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
3276 false);
3277
3278 a.info.functionalTest = sa.getBoolean(
3279 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
3280 false);
3281
3282 sa.recycle();
3283
3284 if (a.info.targetPackage == null) {
3285 outError[0] = "<instrumentation> does not specify targetPackage";
3286 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3287 return null;
3288 }
3289
Svet Ganov354cd3c2015-12-17 11:35:04 -08003290 if (!parseAllMetaData(res, parser, "<instrumentation>", a,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003291 outError)) {
3292 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3293 return null;
3294 }
3295
3296 owner.instrumentation.add(a);
3297
3298 return a;
3299 }
3300
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003301 /**
3302 * Parse the {@code application} XML tree at the current parse location in a
3303 * <em>base APK</em> manifest.
3304 * <p>
3305 * When adding new features, carefully consider if they should also be
3306 * supported by split APKs.
3307 */
3308 private boolean parseBaseApplication(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003309 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 throws XmlPullParserException, IOException {
3311 final ApplicationInfo ai = owner.applicationInfo;
3312 final String pkgName = owner.applicationInfo.packageName;
3313
Svet Ganov354cd3c2015-12-17 11:35:04 -08003314 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 com.android.internal.R.styleable.AndroidManifestApplication);
3316
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003317 if (!parsePackageItemInfo(owner, ai, outError,
3318 "<application>", sa, false /*nameRequired*/,
3319 com.android.internal.R.styleable.AndroidManifestApplication_name,
3320 com.android.internal.R.styleable.AndroidManifestApplication_label,
3321 com.android.internal.R.styleable.AndroidManifestApplication_icon,
3322 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
3323 com.android.internal.R.styleable.AndroidManifestApplication_logo,
3324 com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
3325 sa.recycle();
3326 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3327 return false;
3328 }
3329
3330 if (ai.name != null) {
Todd Kennedyafb52692016-08-22 15:44:00 -07003331 ai.className = ai.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003332 }
3333
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003334 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003335 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
3336 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003337 if (manageSpaceActivity != null) {
3338 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
3339 outError);
3340 }
3341
Christopher Tate181fafa2009-05-14 11:12:14 -07003342 boolean allowBackup = sa.getBoolean(
3343 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
3344 if (allowBackup) {
3345 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07003346
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003347 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
3348 // and restoreAnyVersion are only relevant if backup is possible for the
3349 // given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003350 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003351 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
3352 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07003353 if (backupAgent != null) {
3354 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07003355 if (DEBUG_BACKUP) {
3356 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003357 + " from " + pkgName + "+" + backupAgent);
3358 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003359
3360 if (sa.getBoolean(
3361 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
3362 true)) {
3363 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
3364 }
3365 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08003366 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
3367 false)) {
3368 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
3369 }
Christopher Tated1de2562014-06-17 17:12:35 -07003370 if (sa.getBoolean(
3371 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
3372 false)) {
3373 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
3374 }
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003375 if (sa.getBoolean(
3376 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
3377 false)) {
3378 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
3379 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003380 }
Matthew Williams303650c2015-04-17 18:22:51 -07003381
3382 TypedValue v = sa.peekValue(
3383 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
3384 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
3385 if (DEBUG_BACKUP) {
3386 Slog.v(TAG, "fullBackupContent specified as boolean=" +
3387 (v.data == 0 ? "false" : "true"));
3388 }
3389 // "false" => -1, "true" => 0
3390 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
3391 }
3392 if (DEBUG_BACKUP) {
3393 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
3394 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003395 }
Christopher Tate4a627c72011-04-01 14:43:32 -07003396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003397 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08003398 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003399 ai.descriptionRes = sa.getResourceId(
3400 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
3401
3402 if ((flags&PARSE_IS_SYSTEM) != 0) {
3403 if (sa.getBoolean(
3404 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
3405 false)) {
Martijn Coenen441d61b2017-04-12 13:52:40 -07003406 // Check if persistence is based on a feature being present
3407 final String requiredFeature = sa.getNonResourceString(
3408 com.android.internal.R.styleable.AndroidManifestApplication_persistentFeature);
3409 if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
3410 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
3411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003412 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07003413 }
3414
3415 if (sa.getBoolean(
3416 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
3417 false)) {
3418 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07003419 }
3420
3421 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
3422 .AndroidManifestApplication_restrictedAccountType);
3423 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
3424 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003425 }
3426
Amith Yamasaniccbe3892013-04-12 17:52:42 -07003427 String requiredAccountType = sa.getString(com.android.internal.R.styleable
3428 .AndroidManifestApplication_requiredAccountType);
3429 if (requiredAccountType != null && requiredAccountType.length() > 0) {
3430 owner.mRequiredAccountType = requiredAccountType;
3431 }
3432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003433 if (sa.getBoolean(
3434 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
3435 false)) {
3436 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
3437 }
3438
3439 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07003440 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08003441 false)) {
3442 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
3443 }
3444
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003445 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07003446 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07003447 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07003448 if (owner.baseHardwareAccelerated) {
3449 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
3450 }
Romain Guy812ccbe2010-06-01 14:07:24 -07003451
3452 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003453 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
3454 true)) {
3455 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
3456 }
3457
3458 if (sa.getBoolean(
3459 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
3460 false)) {
3461 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
3462 }
3463
3464 if (sa.getBoolean(
3465 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
3466 true)) {
3467 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
3468 }
3469
Svet Ganov354cd3c2015-12-17 11:35:04 -08003470 // The parent package controls installation, hence specify test only installs.
3471 if (owner.parentPackage == null) {
3472 if (sa.getBoolean(
3473 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
3474 false)) {
3475 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
3476 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003477 }
3478
Jason parksa3cdaa52011-01-13 14:15:43 -06003479 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003480 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06003481 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003482 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06003483 }
3484
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003485 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07003486 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
3487 true)) {
3488 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
3489 }
3490
3491 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003492 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
3493 false /* default is no RTL support*/)) {
3494 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
3495 }
3496
Narayan Kamath589a1bc2014-07-03 14:43:26 +01003497 if (sa.getBoolean(
3498 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
3499 false)) {
3500 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
3501 }
3502
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07003503 if (sa.getBoolean(
3504 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
3505 true)) {
3506 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
3507 }
3508
Todd Kennedyd022ac22016-04-13 10:49:29 -07003509 if (sa.getBoolean(
3510 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
3511 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003512 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003513 }
Todd Kennedyd022ac22016-04-13 10:49:29 -07003514 if (sa.getBoolean(
3515 R.styleable.AndroidManifestApplication_directBootAware,
3516 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003517 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003518 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003519
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003520 if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
3521 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003522 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
3523 } else {
3524 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003525 }
3526 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003527 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwale6afdf912016-01-30 13:01:33 -08003528 }
3529
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07003530 ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
3531
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003532 ai.networkSecurityConfigRes = sa.getResourceId(
3533 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
3534 0);
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07003535 ai.category = sa.getInt(
3536 com.android.internal.R.styleable.AndroidManifestApplication_appCategory,
3537 ApplicationInfo.CATEGORY_UNDEFINED);
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003539 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003540 str = sa.getNonConfigurationString(
3541 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003542 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
3543
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003544 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3545 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003546 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
3547 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003548 } else {
3549 // Some older apps have been seen to use a resource reference
3550 // here that on older builds was ignored (with a warning). We
3551 // need to continue to do this for them so they don't break.
3552 str = sa.getNonResourceString(
3553 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
3554 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003555 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
3556 str, outError);
3557
3558 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003559 CharSequence pname;
3560 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3561 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003562 com.android.internal.R.styleable.AndroidManifestApplication_process,
3563 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003564 } else {
3565 // Some older apps have been seen to use a resource reference
3566 // here that on older builds was ignored (with a warning). We
3567 // need to continue to do this for them so they don't break.
3568 pname = sa.getNonResourceString(
3569 com.android.internal.R.styleable.AndroidManifestApplication_process);
3570 }
3571 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572 flags, mSeparateProcesses, outError);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003573
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003574 ai.enabled = sa.getBoolean(
3575 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003576
Jose Lima12d0b4c2014-03-14 16:55:12 -07003577 if (sa.getBoolean(
3578 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
3579 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
3580 }
3581
Dianne Hackborn02486b12010-08-26 14:18:37 -07003582 if (false) {
3583 if (sa.getBoolean(
3584 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
3585 false)) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003586 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07003587
3588 // A heavy-weight application can not be in a custom process.
3589 // We can do direct compare because we intern all strings.
3590 if (ai.processName != null && ai.processName != ai.packageName) {
3591 outError[0] = "cantSaveState applications can not use custom processes";
3592 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003593 }
3594 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003595 }
3596
Adam Powell269248d2011-08-02 10:26:54 -07003597 ai.uiOptions = sa.getInt(
3598 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
3599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003600 sa.recycle();
3601
3602 if (outError[0] != null) {
3603 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3604 return false;
3605 }
3606
3607 final int innerDepth = parser.getDepth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003608 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07003609 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3610 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3611 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003612 continue;
3613 }
3614
3615 String tagName = parser.getName();
3616 if (tagName.equals("activity")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003617 Activity a = parseActivity(owner, res, parser, flags, outError, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003618 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003619 if (a == null) {
3620 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3621 return false;
3622 }
3623
3624 owner.activities.add(a);
3625
3626 } else if (tagName.equals("receiver")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003627 Activity a = parseActivity(owner, res, parser, flags, outError, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003628 if (a == null) {
3629 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3630 return false;
3631 }
3632
3633 owner.receivers.add(a);
3634
3635 } else if (tagName.equals("service")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003636 Service s = parseService(owner, res, parser, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003637 if (s == null) {
3638 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3639 return false;
3640 }
3641
3642 owner.services.add(s);
3643
3644 } else if (tagName.equals("provider")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003645 Provider p = parseProvider(owner, res, parser, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003646 if (p == null) {
3647 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3648 return false;
3649 }
3650
3651 owner.providers.add(p);
3652
3653 } else if (tagName.equals("activity-alias")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003654 Activity a = parseActivityAlias(owner, res, parser, flags, outError);
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
3660 owner.activities.add(a);
3661
3662 } else if (parser.getName().equals("meta-data")) {
3663 // note: application meta-data is stored off to the side, so it can
3664 // remain null in the primary copy (we like to avoid extra copies because
3665 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003666 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003667 outError)) == null) {
3668 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3669 return false;
3670 }
Svet Ganov67882122016-12-11 16:36:34 -08003671 } else if (tagName.equals("static-library")) {
3672 sa = res.obtainAttributes(parser,
3673 com.android.internal.R.styleable.AndroidManifestStaticLibrary);
3674
3675 // Note: don't allow this value to be a reference to a resource
3676 // that may change.
3677 final String lname = sa.getNonResourceString(
3678 com.android.internal.R.styleable.AndroidManifestStaticLibrary_name);
3679 final int version = sa.getInt(
3680 com.android.internal.R.styleable.AndroidManifestStaticLibrary_version, -1);
3681
3682 sa.recycle();
3683
3684 // Since the app canot run without a static lib - fail if malformed
3685 if (lname == null || version < 0) {
3686 outError[0] = "Bad static-library declaration name: " + lname
3687 + " version: " + version;
3688 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3689 XmlUtils.skipCurrentTag(parser);
3690 return false;
3691 }
3692
3693 if (owner.mSharedUserId != null) {
3694 outError[0] = "sharedUserId not allowed in static shared library";
3695 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
3696 XmlUtils.skipCurrentTag(parser);
3697 return false;
3698 }
3699
3700 if (owner.staticSharedLibName != null) {
3701 outError[0] = "Multiple static-shared libs for package " + pkgName;
3702 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3703 XmlUtils.skipCurrentTag(parser);
3704 return false;
3705 }
3706
3707 owner.staticSharedLibName = lname.intern();
3708 owner.staticSharedLibVersion = version;
3709 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
3710
3711 XmlUtils.skipCurrentTag(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003712
Dianne Hackbornc895be72013-03-11 17:48:43 -07003713 } else if (tagName.equals("library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003714 sa = res.obtainAttributes(parser,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003715 com.android.internal.R.styleable.AndroidManifestLibrary);
3716
3717 // Note: don't allow this value to be a reference to a resource
3718 // that may change.
3719 String lname = sa.getNonResourceString(
3720 com.android.internal.R.styleable.AndroidManifestLibrary_name);
3721
3722 sa.recycle();
3723
3724 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003725 lname = lname.intern();
3726 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
Svet Ganov67882122016-12-11 16:36:34 -08003727 owner.libraryNames = ArrayUtils.add(
3728 owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07003729 }
3730 }
3731
3732 XmlUtils.skipCurrentTag(parser);
3733
Svet Ganov67882122016-12-11 16:36:34 -08003734 } else if (tagName.equals("uses-static-library")) {
3735 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3736 return false;
3737 }
3738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003739 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003740 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003741 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3742
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003743 // Note: don't allow this value to be a reference to a resource
3744 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003745 String lname = sa.getNonResourceString(
3746 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07003747 boolean req = sa.getBoolean(
3748 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3749 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003750
3751 sa.recycle();
3752
Dianne Hackborn49237342009-08-27 20:08:01 -07003753 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003754 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07003755 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003756 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003757 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003758 owner.usesOptionalLibraries = ArrayUtils.add(
3759 owner.usesOptionalLibraries, lname);
3760 }
3761 }
3762
3763 XmlUtils.skipCurrentTag(parser);
3764
3765 } else if (tagName.equals("uses-package")) {
3766 // Dependencies for app installers; we don't currently try to
3767 // enforce this.
3768 XmlUtils.skipCurrentTag(parser);
3769
3770 } else {
3771 if (!RIGID_PARSER) {
3772 Slog.w(TAG, "Unknown element under <application>: " + tagName
3773 + " at " + mArchiveSourcePath + " "
3774 + parser.getPositionDescription());
3775 XmlUtils.skipCurrentTag(parser);
3776 continue;
3777 } else {
3778 outError[0] = "Bad element under <application>: " + tagName;
3779 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3780 return false;
3781 }
3782 }
3783 }
3784
Narayan Kamathb12dcfb2015-03-30 11:31:04 +01003785 modifySharedLibrariesForBackwardCompatibility(owner);
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003786
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003787 if (hasDomainURLs(owner)) {
3788 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3789 } else {
3790 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3791 }
3792
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003793 return true;
3794 }
3795
Narayan Kamathb12dcfb2015-03-30 11:31:04 +01003796 private static void modifySharedLibrariesForBackwardCompatibility(Package owner) {
3797 // "org.apache.http.legacy" is now a part of the boot classpath so it doesn't need
3798 // to be an explicit dependency.
3799 //
3800 // A future change will remove this library from the boot classpath, at which point
3801 // all apps that target SDK 21 and earlier will have it automatically added to their
3802 // dependency lists.
3803 owner.usesLibraries = ArrayUtils.remove(owner.usesLibraries, "org.apache.http.legacy");
3804 owner.usesOptionalLibraries = ArrayUtils.remove(owner.usesOptionalLibraries,
3805 "org.apache.http.legacy");
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003806 }
3807
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003808 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003809 * 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 -07003810 */
3811 private static boolean hasDomainURLs(Package pkg) {
3812 if (pkg == null || pkg.activities == null) return false;
3813 final ArrayList<Activity> activities = pkg.activities;
3814 final int countActivities = activities.size();
3815 for (int n=0; n<countActivities; n++) {
3816 Activity activity = activities.get(n);
3817 ArrayList<ActivityIntentInfo> filters = activity.intents;
3818 if (filters == null) continue;
3819 final int countFilters = filters.size();
3820 for (int m=0; m<countFilters; m++) {
3821 ActivityIntentInfo aii = filters.get(m);
3822 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003823 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003824 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
3825 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
3826 return true;
3827 }
3828 }
3829 }
3830 return false;
3831 }
3832
3833 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003834 * Parse the {@code application} XML tree at the current parse location in a
3835 * <em>split APK</em> manifest.
3836 * <p>
3837 * Note that split APKs have many more restrictions on what they're capable
3838 * of doing, so many valid features of a base APK have been carefully
3839 * omitted here.
3840 */
Svet Ganov354cd3c2015-12-17 11:35:04 -08003841 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
3842 int flags, int splitIndex, String[] outError)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003843 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003844 TypedArray sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003845 com.android.internal.R.styleable.AndroidManifestApplication);
3846
3847 if (sa.getBoolean(
3848 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
3849 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
3850 }
3851
3852 final int innerDepth = parser.getDepth();
3853 int type;
3854 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3855 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3856 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3857 continue;
3858 }
3859
Adam Lesinski4e862812016-11-21 16:02:24 -08003860 ComponentInfo parsedComponent = null;
3861
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003862 String tagName = parser.getName();
3863 if (tagName.equals("activity")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003864 Activity a = parseActivity(owner, res, parser, flags, outError, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003865 owner.baseHardwareAccelerated);
3866 if (a == null) {
3867 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3868 return false;
3869 }
3870
3871 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003872 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003873
3874 } else if (tagName.equals("receiver")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003875 Activity a = parseActivity(owner, res, parser, flags, outError, true, false);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003876 if (a == null) {
3877 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3878 return false;
3879 }
3880
3881 owner.receivers.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003882 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003883
3884 } else if (tagName.equals("service")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003885 Service s = parseService(owner, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003886 if (s == null) {
3887 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3888 return false;
3889 }
3890
3891 owner.services.add(s);
Adam Lesinski4e862812016-11-21 16:02:24 -08003892 parsedComponent = s.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003893
3894 } else if (tagName.equals("provider")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003895 Provider p = parseProvider(owner, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003896 if (p == null) {
3897 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3898 return false;
3899 }
3900
3901 owner.providers.add(p);
Adam Lesinski4e862812016-11-21 16:02:24 -08003902 parsedComponent = p.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003903
3904 } else if (tagName.equals("activity-alias")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003905 Activity a = parseActivityAlias(owner, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003906 if (a == null) {
3907 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3908 return false;
3909 }
3910
3911 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003912 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003913
3914 } else if (parser.getName().equals("meta-data")) {
3915 // note: application meta-data is stored off to the side, so it can
3916 // remain null in the primary copy (we like to avoid extra copies because
3917 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003918 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003919 outError)) == null) {
3920 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3921 return false;
3922 }
3923
Svet Ganov67882122016-12-11 16:36:34 -08003924 } else if (tagName.equals("uses-static-library")) {
3925 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3926 return false;
3927 }
3928
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003929 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003930 sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003931 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3932
3933 // Note: don't allow this value to be a reference to a resource
3934 // that may change.
3935 String lname = sa.getNonResourceString(
3936 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
3937 boolean req = sa.getBoolean(
3938 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3939 true);
3940
3941 sa.recycle();
3942
3943 if (lname != null) {
3944 lname = lname.intern();
3945 if (req) {
3946 // Upgrade to treat as stronger constraint
3947 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
3948 owner.usesOptionalLibraries = ArrayUtils.remove(
3949 owner.usesOptionalLibraries, lname);
3950 } else {
3951 // Ignore if someone already defined as required
3952 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
3953 owner.usesOptionalLibraries = ArrayUtils.add(
3954 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003955 }
3956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003957 }
3958
3959 XmlUtils.skipCurrentTag(parser);
3960
Dianne Hackborncef65ee2010-09-30 18:27:22 -07003961 } else if (tagName.equals("uses-package")) {
3962 // Dependencies for app installers; we don't currently try to
3963 // enforce this.
3964 XmlUtils.skipCurrentTag(parser);
3965
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003966 } else {
3967 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003968 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003969 + " at " + mArchiveSourcePath + " "
3970 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003971 XmlUtils.skipCurrentTag(parser);
3972 continue;
3973 } else {
3974 outError[0] = "Bad element under <application>: " + tagName;
3975 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3976 return false;
3977 }
3978 }
Adam Lesinski4e862812016-11-21 16:02:24 -08003979
3980 if (parsedComponent != null && parsedComponent.splitName == null) {
3981 // If the loaded component did not specify a split, inherit the split name
3982 // based on the split it is defined in.
3983 // This is used to later load the correct split when starting this
3984 // component.
3985 parsedComponent.splitName = owner.splitNames[splitIndex];
3986 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003987 }
3988
3989 return true;
3990 }
3991
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003992 private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
3993 String[] outError, String tag, TypedArray sa, boolean nameRequired,
3994 int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00003995 // This case can only happen in unit tests where we sometimes need to create fakes
3996 // of various package parser data structures.
3997 if (sa == null) {
3998 outError[0] = tag + " does not contain any attributes";
3999 return false;
4000 }
4001
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004002 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004003 if (name == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004004 if (nameRequired) {
4005 outError[0] = tag + " does not specify android:name";
4006 return false;
4007 }
4008 } else {
4009 outInfo.name
4010 = buildClassName(owner.applicationInfo.packageName, name, outError);
4011 if (outInfo.name == null) {
4012 return false;
4013 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004014 }
4015
Todd Kennedya83bfca2016-06-03 07:52:17 -07004016 final boolean useRoundIcon =
4017 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
4018 int roundIconVal = useRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004019 if (roundIconVal != 0) {
4020 outInfo.icon = roundIconVal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004021 outInfo.nonLocalizedLabel = null;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004022 } else {
4023 int iconVal = sa.getResourceId(iconRes, 0);
4024 if (iconVal != 0) {
4025 outInfo.icon = iconVal;
4026 outInfo.nonLocalizedLabel = null;
4027 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004028 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004029
Adam Powell81cd2e92010-04-21 16:35:18 -07004030 int logoVal = sa.getResourceId(logoRes, 0);
4031 if (logoVal != 0) {
4032 outInfo.logo = logoVal;
4033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004034
Jose Limaf78e3122014-03-06 12:13:15 -08004035 int bannerVal = sa.getResourceId(bannerRes, 0);
4036 if (bannerVal != 0) {
4037 outInfo.banner = bannerVal;
4038 }
4039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004040 TypedValue v = sa.peekValue(labelRes);
4041 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4042 outInfo.nonLocalizedLabel = v.coerceToString();
4043 }
4044
4045 outInfo.packageName = owner.packageName;
4046
4047 return true;
4048 }
4049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004050 private Activity parseActivity(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08004051 XmlResourceParser parser, int flags, String[] outError,
Romain Guy529b60a2010-08-03 18:05:47 -07004052 boolean receiver, boolean hardwareAccelerated)
4053 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004054 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004055
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004056 if (mParseActivityArgs == null) {
4057 mParseActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004058 R.styleable.AndroidManifestActivity_name,
4059 R.styleable.AndroidManifestActivity_label,
4060 R.styleable.AndroidManifestActivity_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004061 R.styleable.AndroidManifestActivity_roundIcon,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004062 R.styleable.AndroidManifestActivity_logo,
4063 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004064 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004065 R.styleable.AndroidManifestActivity_process,
4066 R.styleable.AndroidManifestActivity_description,
4067 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004068 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004069
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004070 mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
4071 mParseActivityArgs.sa = sa;
4072 mParseActivityArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004073
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004074 Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
4075 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004076 sa.recycle();
4077 return null;
4078 }
4079
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004080 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004081 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004082 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004083 }
4084
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004085 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004086
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004087 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07004088 a.info.applicationInfo.uiOptions);
4089
Adam Powelldd8fab22012-03-22 17:47:27 -07004090 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004091 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004092 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004093 if (parentName != null) {
4094 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4095 if (outError[0] == null) {
4096 a.info.parentActivityName = parentClassName;
4097 } else {
4098 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
4099 parentName);
4100 outError[0] = null;
4101 }
4102 }
4103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004105 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004106 if (str == null) {
4107 a.info.permission = owner.applicationInfo.permission;
4108 } else {
4109 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4110 }
4111
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004112 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004113 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004114 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004115 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
4116 owner.applicationInfo.taskAffinity, str, outError);
4117
Todd Kennedye9d0d272017-01-23 06:49:29 -08004118 a.info.splitName =
4119 sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0);
4120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004121 a.info.flags = 0;
4122 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004123 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004124 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
4125 }
4126
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004127 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
4129 }
4130
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004131 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
4133 }
4134
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004135 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004136 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
4137 }
4138
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004139 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004140 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
4141 }
4142
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004143 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004144 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
4145 }
4146
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004147 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004148 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
4149 }
4150
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004151 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004152 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
4153 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
4154 }
4155
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004156 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07004157 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
4158 }
4159
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07004160 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
4161 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
4162 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07004163 }
4164
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004165 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04004166 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
4167 }
Craig Mautner5962b122012-10-05 14:45:52 -07004168
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07004169 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
4170 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08004171 }
4172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004174 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07004175 hardwareAccelerated)) {
4176 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
4177 }
4178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004180 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07004181 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004182 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07004183 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07004184 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004185 R.styleable.AndroidManifestActivity_maxRecents,
Dianne Hackborn852975d2014-08-22 17:42:43 -07004186 ActivityManager.getDefaultAppRecentsLimitStatic());
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004187 a.info.configChanges = getActivityConfigChanges(
4188 sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
4189 sa.getInt(R.styleable.AndroidManifestActivity_restartOnConfigChanges, 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004191 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07004192
Craig Mautner43e52ed2014-06-16 17:18:52 -07004193 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004194 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07004195 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07004196
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004197 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004198 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
4199 }
4200
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004201 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004202 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
4203 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004204
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004205 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004206 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
4207 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004208
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004209 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004210 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
4211 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004212
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004213 a.info.screenOrientation = sa.getInt(
4214 R.styleable.AndroidManifestActivity_screenOrientation,
4215 SCREEN_ORIENTATION_UNSPECIFIED);
Wale Ogunwale6a591362015-10-05 20:18:27 -07004216
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004217 setActivityResizeMode(a.info, sa, owner);
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004218
Winson Chungd3395382016-12-13 11:49:09 -08004219 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
4220 false)) {
4221 a.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE;
4222 }
4223
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004224 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004225 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004226 }
Wale Ogunwaleb60692e2015-10-24 12:35:56 -07004227
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004228 setActivityMaxAspectRatio(a.info, sa, owner);
4229
Craig Mautner15df08a2015-04-01 12:17:18 -07004230 a.info.lockTaskLaunchMode =
4231 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004232
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004233 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4234 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004235 false);
Ruben Brunkf56c9f42016-04-22 18:20:55 -07004236
4237 a.info.requestedVrComponent =
4238 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
Robert Carr0f5d7532016-10-17 16:39:17 -07004239
4240 a.info.rotationAnimation =
4241 sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_ROTATE);
Romain Guy48327452017-01-23 17:03:35 -08004242
4243 a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
4244 ActivityInfo.COLOR_MODE_DEFAULT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004245 } else {
4246 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4247 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004248
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004249 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07004250 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07004251 if (a.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004252 Slog.w(TAG, "Activity exported request ignored due to singleUser: "
4253 + a.className + " at " + mArchiveSourcePath + " "
4254 + parser.getPositionDescription());
4255 a.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07004256 setExported = true;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004257 }
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004258 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004259
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004260 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4261 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004262 false);
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004263 }
4264
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004265 if (a.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004266 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004267 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004268 }
4269
Todd Kennedy752fb702017-03-21 16:28:10 -07004270 // can't make this final; we may set it later via meta-data
4271 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08004272 sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004273 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004274 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004275 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004276 }
4277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004278 sa.recycle();
4279
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004280 if (receiver && (owner.applicationInfo.privateFlags
4281 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004282 // A heavy-weight application can not have receives in its main process
4283 // We can do direct compare because we intern all strings.
4284 if (a.info.processName == owner.packageName) {
4285 outError[0] = "Heavy-weight applications can not have receivers in main process";
4286 }
4287 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004289 if (outError[0] != null) {
4290 return null;
4291 }
4292
4293 int outerDepth = parser.getDepth();
4294 int type;
4295 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4296 && (type != XmlPullParser.END_TAG
4297 || parser.getDepth() > outerDepth)) {
4298 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4299 continue;
4300 }
4301
4302 if (parser.getName().equals("intent-filter")) {
4303 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004304 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4305 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004306 return null;
4307 }
4308 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004309 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004310 + mArchiveSourcePath + " "
4311 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004312 } else {
4313 a.intents.add(intent);
4314 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004315 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004316 final int visibility = visibleToEphemeral
4317 ? IntentFilter.VISIBILITY_EXPLICIT
4318 : !receiver && isImplicitlyExposedIntent(intent)
4319 ? IntentFilter.VISIBILITY_IMPLICIT
4320 : IntentFilter.VISIBILITY_NONE;
4321 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004322 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004323 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4324 }
4325 if (intent.isImplicitlyVisibleToInstantApp()) {
4326 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004327 }
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -07004328 if (LOG_UNSAFE_BROADCASTS && receiver
4329 && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
4330 for (int i = 0; i < intent.countActions(); i++) {
4331 final String action = intent.getAction(i);
4332 if (action == null || !action.startsWith("android.")) continue;
4333 if (!SAFE_BROADCASTS.contains(action)) {
4334 Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
4335 + owner.packageName + " as requested at: "
4336 + parser.getPositionDescription());
4337 }
4338 }
4339 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004340 } else if (!receiver && parser.getName().equals("preferred")) {
4341 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004342 if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
4343 intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004344 return null;
4345 }
4346 if (intent.countActions() == 0) {
4347 Slog.w(TAG, "No actions in preferred at "
4348 + mArchiveSourcePath + " "
4349 + parser.getPositionDescription());
4350 } else {
4351 if (owner.preferredActivityFilters == null) {
4352 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
4353 }
4354 owner.preferredActivityFilters.add(intent);
4355 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004356 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004357 final int visibility = visibleToEphemeral
4358 ? IntentFilter.VISIBILITY_EXPLICIT
4359 : !receiver && isImplicitlyExposedIntent(intent)
4360 ? IntentFilter.VISIBILITY_IMPLICIT
4361 : IntentFilter.VISIBILITY_NONE;
4362 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004363 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004364 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4365 }
4366 if (intent.isImplicitlyVisibleToInstantApp()) {
4367 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004369 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004370 if ((a.metaData = parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004371 outError)) == null) {
4372 return null;
4373 }
Todd Kennedy752fb702017-03-21 16:28:10 -07004374 // we don't have an attribute [or it's false], but, we have meta-data
4375 if (!visibleToEphemeral && a.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
4376 visibleToEphemeral = true; // set in case there are more intent filters
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004377 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4378 a.info.flags &= ~ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy752fb702017-03-21 16:28:10 -07004379 owner.visibleToInstantApps = true;
4380 // cycle through any filters already seen
4381 for (int i = a.intents.size() - 1; i >= 0; --i) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004382 a.intents.get(i)
4383 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07004384 }
4385 if (owner.preferredActivityFilters != null) {
4386 for (int i = owner.preferredActivityFilters.size() - 1; i >= 0; --i) {
4387 owner.preferredActivityFilters.get(i)
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004388 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07004389 }
4390 }
4391 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004392 } else if (!receiver && parser.getName().equals("layout")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004393 parseLayout(res, parser, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004394 } else {
4395 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004396 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004398 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004399 + " at " + mArchiveSourcePath + " "
4400 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004401 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004402 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004403 + " at " + mArchiveSourcePath + " "
4404 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004405 }
4406 XmlUtils.skipCurrentTag(parser);
4407 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004408 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004409 if (receiver) {
4410 outError[0] = "Bad element under <receiver>: " + parser.getName();
4411 } else {
4412 outError[0] = "Bad element under <activity>: " + parser.getName();
4413 }
4414 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004416 }
4417 }
4418
4419 if (!setExported) {
4420 a.info.exported = a.intents.size() > 0;
4421 }
4422
4423 return a;
4424 }
4425
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004426 private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004427 final boolean appExplicitDefault = (owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004428 & (PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
4429 | PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004430
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004431 if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
4432 || appExplicitDefault) {
4433 // Activity or app explicitly set if it is resizeable or not;
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004434 final boolean appResizeable = (owner.applicationInfo.privateFlags
4435 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004436 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004437 appResizeable)) {
Winson Chungd3395382016-12-13 11:49:09 -08004438 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004439 } else {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004440 aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004441 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004442 return;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004443 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004444
4445 if ((owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004446 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) != 0) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004447 // The activity or app didn't explicitly set the resizing option, however we want to
4448 // make it resize due to the sdk version it is targeting.
4449 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4450 return;
4451 }
4452
4453 // resize preference isn't set and target sdk version doesn't support resizing apps by
4454 // default. For the app to be resizeable if it isn't fixed orientation or immersive.
skuhne@google.com322347b2016-12-02 12:54:03 -08004455 if (aInfo.isFixedOrientationPortrait()) {
4456 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
4457 } else if (aInfo.isFixedOrientationLandscape()) {
4458 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
4459 } else if (aInfo.isFixedOrientation()) {
4460 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
4461 } else {
4462 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4463 }
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004464 }
4465
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004466 private void setActivityMaxAspectRatio(ActivityInfo aInfo, TypedArray sa, Package owner) {
4467 if (aInfo.resizeMode == RESIZE_MODE_RESIZEABLE
4468 || aInfo.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
4469 // Resizeable activities can be put in any aspect ratio.
4470 aInfo.maxAspectRatio = 0;
4471 return;
4472 }
4473
4474 // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
4475 // NOTE: 16.7:9 was the max aspect ratio Android devices can support pre-O per the CDD.
4476 float defaultMaxAspectRatio = owner.applicationInfo.targetSdkVersion < O
4477 ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
4478 if (owner.applicationInfo.maxAspectRatio != 0 ) {
4479 // Use the application max aspect ration as default if set.
4480 defaultMaxAspectRatio = owner.applicationInfo.maxAspectRatio;
4481 }
4482
Wale Ogunwale0cb70ac2017-03-27 09:16:38 -07004483 aInfo.maxAspectRatio = sa.getFloat(
4484 R.styleable.AndroidManifestActivity_maxAspectRatio, defaultMaxAspectRatio);
4485 if (aInfo.maxAspectRatio < 1.0f && aInfo.maxAspectRatio != 0) {
4486 // Ignore any value lesser than 1.0.
4487 aInfo.maxAspectRatio = 0;
4488 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004489 }
4490
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004491 /**
4492 * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
4493 * @param restartOnConfigChanges The bit mask restartOnConfigChanges fetched from
4494 * AndroidManifest.xml.
4495 * @hide Exposed for unit testing only.
4496 */
4497 @TestApi
4498 public static int getActivityConfigChanges(int configChanges, int restartOnConfigChanges) {
4499 return configChanges | ((~restartOnConfigChanges) & RESTART_ON_CONFIG_CHANGES_MASK);
4500 }
4501
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004502 private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004503 TypedArray sw = res.obtainAttributes(attrs,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004504 com.android.internal.R.styleable.AndroidManifestLayout);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004505 int width = -1;
4506 float widthFraction = -1f;
4507 int height = -1;
4508 float heightFraction = -1f;
4509 final int widthType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004510 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004511 if (widthType == TypedValue.TYPE_FRACTION) {
4512 widthFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004513 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004514 1, 1, -1);
4515 } else if (widthType == TypedValue.TYPE_DIMENSION) {
4516 width = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004517 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004518 -1);
4519 }
4520 final int heightType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004521 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004522 if (heightType == TypedValue.TYPE_FRACTION) {
4523 heightFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004524 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004525 1, 1, -1);
4526 } else if (heightType == TypedValue.TYPE_DIMENSION) {
4527 height = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004528 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004529 -1);
4530 }
4531 int gravity = sw.getInt(
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004532 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004533 Gravity.CENTER);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004534 int minWidth = sw.getDimensionPixelSize(
4535 com.android.internal.R.styleable.AndroidManifestLayout_minWidth,
Andrii Kulian2e751b82016-03-16 16:59:32 -07004536 -1);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004537 int minHeight = sw.getDimensionPixelSize(
4538 com.android.internal.R.styleable.AndroidManifestLayout_minHeight,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004539 -1);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004540 sw.recycle();
Andrii Kulian2e751b82016-03-16 16:59:32 -07004541 a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction,
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004542 height, heightFraction, gravity, minWidth, minHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004543 }
4544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004545 private Activity parseActivityAlias(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08004546 XmlResourceParser parser, int flags, String[] outError)
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004547 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004548 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004549 com.android.internal.R.styleable.AndroidManifestActivityAlias);
4550
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004551 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004552 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
4553 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554 if (targetActivity == null) {
4555 outError[0] = "<activity-alias> does not specify android:targetActivity";
4556 sa.recycle();
4557 return null;
4558 }
4559
4560 targetActivity = buildClassName(owner.applicationInfo.packageName,
4561 targetActivity, outError);
4562 if (targetActivity == null) {
4563 sa.recycle();
4564 return null;
4565 }
4566
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004567 if (mParseActivityAliasArgs == null) {
4568 mParseActivityAliasArgs = new ParseComponentArgs(owner, outError,
4569 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
4570 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
4571 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004572 com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004573 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004574 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004575 mSeparateProcesses,
4576 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004577 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004578 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
4579 mParseActivityAliasArgs.tag = "<activity-alias>";
4580 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004581
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004582 mParseActivityAliasArgs.sa = sa;
4583 mParseActivityAliasArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004585 Activity target = null;
4586
4587 final int NA = owner.activities.size();
4588 for (int i=0; i<NA; i++) {
4589 Activity t = owner.activities.get(i);
4590 if (targetActivity.equals(t.info.name)) {
4591 target = t;
4592 break;
4593 }
4594 }
4595
4596 if (target == null) {
4597 outError[0] = "<activity-alias> target activity " + targetActivity
4598 + " not found in manifest";
4599 sa.recycle();
4600 return null;
4601 }
4602
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004603 ActivityInfo info = new ActivityInfo();
4604 info.targetActivity = targetActivity;
4605 info.configChanges = target.info.configChanges;
4606 info.flags = target.info.flags;
4607 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07004608 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08004609 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004610 info.labelRes = target.info.labelRes;
4611 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
4612 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07004613 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004614 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004615 if (info.descriptionRes == 0) {
4616 info.descriptionRes = target.info.descriptionRes;
4617 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004618 info.screenOrientation = target.info.screenOrientation;
4619 info.taskAffinity = target.info.taskAffinity;
4620 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07004621 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07004622 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07004623 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07004624 info.maxRecents = target.info.maxRecents;
Andrii Kulian2e751b82016-03-16 16:59:32 -07004625 info.windowLayout = target.info.windowLayout;
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004626 info.resizeMode = target.info.resizeMode;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004627 info.maxAspectRatio = target.info.maxAspectRatio;
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004628 info.encryptionAware = info.directBootAware = target.info.directBootAware;
Craig Mautner8307ea72014-09-11 15:03:53 -07004629
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004630 Activity a = new Activity(mParseActivityAliasArgs, info);
4631 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004632 sa.recycle();
4633 return null;
4634 }
4635
4636 final boolean setExported = sa.hasValue(
4637 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
4638 if (setExported) {
4639 a.info.exported = sa.getBoolean(
4640 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
4641 }
4642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004644 str = sa.getNonConfigurationString(
4645 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004646 if (str != null) {
4647 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4648 }
4649
Adam Powelldd8fab22012-03-22 17:47:27 -07004650 String parentName = sa.getNonConfigurationString(
4651 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004652 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004653 if (parentName != null) {
4654 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4655 if (outError[0] == null) {
4656 a.info.parentActivityName = parentClassName;
4657 } else {
4658 Log.e(TAG, "Activity alias " + a.info.name +
4659 " specified invalid parentActivityName " + parentName);
4660 outError[0] = null;
4661 }
4662 }
4663
Chad Brubaker699c7712017-01-20 13:53:42 -08004664 // TODO add visibleToInstantApps attribute to activity alias
Todd Kennedybe0b8892017-02-15 14:13:52 -08004665 final boolean visibleToEphemeral =
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004666 ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004668 sa.recycle();
4669
4670 if (outError[0] != null) {
4671 return null;
4672 }
4673
4674 int outerDepth = parser.getDepth();
4675 int type;
4676 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4677 && (type != XmlPullParser.END_TAG
4678 || parser.getDepth() > outerDepth)) {
4679 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4680 continue;
4681 }
4682
4683 if (parser.getName().equals("intent-filter")) {
4684 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004685 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4686 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004687 return null;
4688 }
4689 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004690 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004691 + mArchiveSourcePath + " "
4692 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004693 } else {
4694 a.intents.add(intent);
4695 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004696 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004697 final int visibility = visibleToEphemeral
4698 ? IntentFilter.VISIBILITY_EXPLICIT
4699 : isImplicitlyExposedIntent(intent)
4700 ? IntentFilter.VISIBILITY_IMPLICIT
4701 : IntentFilter.VISIBILITY_NONE;
4702 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004703 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004704 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4705 }
4706 if (intent.isImplicitlyVisibleToInstantApp()) {
4707 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004708 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004709 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004710 if ((a.metaData=parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004711 outError)) == null) {
4712 return null;
4713 }
4714 } else {
4715 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004716 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004717 + " at " + mArchiveSourcePath + " "
4718 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004719 XmlUtils.skipCurrentTag(parser);
4720 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004721 } else {
4722 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
4723 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004725 }
4726 }
4727
4728 if (!setExported) {
4729 a.info.exported = a.intents.size() > 0;
4730 }
4731
4732 return a;
4733 }
4734
4735 private Provider parseProvider(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08004736 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004737 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004738 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739 com.android.internal.R.styleable.AndroidManifestProvider);
4740
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004741 if (mParseProviderArgs == null) {
4742 mParseProviderArgs = new ParseComponentArgs(owner, outError,
4743 com.android.internal.R.styleable.AndroidManifestProvider_name,
4744 com.android.internal.R.styleable.AndroidManifestProvider_label,
4745 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004746 com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004747 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004748 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004749 mSeparateProcesses,
4750 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004751 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004752 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
4753 mParseProviderArgs.tag = "<provider>";
4754 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004755
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004756 mParseProviderArgs.sa = sa;
4757 mParseProviderArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004758
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004759 Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
4760 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004761 sa.recycle();
4762 return null;
4763 }
4764
Nick Kralevichf097b162012-07-28 12:43:48 -07004765 boolean providerExportedDefault = false;
4766
4767 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
4768 // For compatibility, applications targeting API level 16 or lower
4769 // should have their content providers exported by default, unless they
4770 // specify otherwise.
4771 providerExportedDefault = true;
4772 }
4773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004774 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07004775 com.android.internal.R.styleable.AndroidManifestProvider_exported,
4776 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004778 String cpname = sa.getNonConfigurationString(
4779 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780
4781 p.info.isSyncable = sa.getBoolean(
4782 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
4783 false);
4784
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004785 String permission = sa.getNonConfigurationString(
4786 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
4787 String str = sa.getNonConfigurationString(
4788 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004789 if (str == null) {
4790 str = permission;
4791 }
4792 if (str == null) {
4793 p.info.readPermission = owner.applicationInfo.permission;
4794 } else {
4795 p.info.readPermission =
4796 str.length() > 0 ? str.toString().intern() : null;
4797 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004798 str = sa.getNonConfigurationString(
4799 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004800 if (str == null) {
4801 str = permission;
4802 }
4803 if (str == null) {
4804 p.info.writePermission = owner.applicationInfo.permission;
4805 } else {
4806 p.info.writePermission =
4807 str.length() > 0 ? str.toString().intern() : null;
4808 }
4809
4810 p.info.grantUriPermissions = sa.getBoolean(
4811 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
4812 false);
4813
4814 p.info.multiprocess = sa.getBoolean(
4815 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
4816 false);
4817
4818 p.info.initOrder = sa.getInt(
4819 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
4820 0);
4821
Todd Kennedye9d0d272017-01-23 06:49:29 -08004822 p.info.splitName =
4823 sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0);
4824
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004825 p.info.flags = 0;
4826
4827 if (sa.getBoolean(
4828 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
4829 false)) {
4830 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07004831 if (p.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004832 Slog.w(TAG, "Provider exported request ignored due to singleUser: "
4833 + p.className + " at " + mArchiveSourcePath + " "
4834 + parser.getPositionDescription());
4835 p.info.exported = false;
4836 }
4837 }
4838
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004839 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
4840 R.styleable.AndroidManifestProvider_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004841 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004842 if (p.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004843 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004844 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004845 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004846
Todd Kennedybe0b8892017-02-15 14:13:52 -08004847 final boolean visibleToEphemeral =
4848 sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004849 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004850 p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004851 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004852 }
4853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004854 sa.recycle();
4855
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004856 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
4857 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004858 // A heavy-weight application can not have providers in its main process
4859 // We can do direct compare because we intern all strings.
4860 if (p.info.processName == owner.packageName) {
4861 outError[0] = "Heavy-weight applications can not have providers in main process";
4862 return null;
4863 }
4864 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004866 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07004867 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004868 return null;
4869 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08004870 if (cpname.length() <= 0) {
4871 outError[0] = "<provider> has empty authorities attribute";
4872 return null;
4873 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004874 p.info.authority = cpname.intern();
4875
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004876 if (!parseProviderTags(
Todd Kennedy752fb702017-03-21 16:28:10 -07004877 res, parser, visibleToEphemeral, owner, p, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004878 return null;
4879 }
4880
4881 return p;
4882 }
4883
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004884 private boolean parseProviderTags(Resources res, XmlResourceParser parser,
Todd Kennedy752fb702017-03-21 16:28:10 -07004885 boolean visibleToEphemeral, Package owner, Provider outInfo, String[] outError)
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004886 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004887 int outerDepth = parser.getDepth();
4888 int type;
4889 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4890 && (type != XmlPullParser.END_TAG
4891 || parser.getDepth() > outerDepth)) {
4892 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4893 continue;
4894 }
4895
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004896 if (parser.getName().equals("intent-filter")) {
4897 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004898 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
4899 intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004900 return false;
4901 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004902 if (visibleToEphemeral) {
4903 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
4904 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004905 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004906 outInfo.intents.add(intent);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004907
4908 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004909 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004910 outInfo.metaData, outError)) == null) {
4911 return false;
4912 }
Todd Kennedy752fb702017-03-21 16:28:10 -07004913 // we don't have an attribute [or it's false], but, we have meta-data
4914 if (!visibleToEphemeral && outInfo.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
4915 visibleToEphemeral = true; // set in case there are more intent filters
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004916 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy752fb702017-03-21 16:28:10 -07004917 owner.visibleToInstantApps = true;
4918 // cycle through any filters already seen
4919 for (int i = outInfo.intents.size() - 1; i >= 0; --i) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004920 outInfo.intents.get(i)
4921 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07004922 }
4923 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004925 } else if (parser.getName().equals("grant-uri-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004926 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004927 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
4928
4929 PatternMatcher pa = null;
4930
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004931 String str = sa.getNonConfigurationString(
4932 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 if (str != null) {
4934 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
4935 }
4936
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004937 str = sa.getNonConfigurationString(
4938 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 if (str != null) {
4940 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
4941 }
4942
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004943 str = sa.getNonConfigurationString(
4944 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 if (str != null) {
4946 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4947 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004949 sa.recycle();
4950
4951 if (pa != null) {
4952 if (outInfo.info.uriPermissionPatterns == null) {
4953 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
4954 outInfo.info.uriPermissionPatterns[0] = pa;
4955 } else {
4956 final int N = outInfo.info.uriPermissionPatterns.length;
4957 PatternMatcher[] newp = new PatternMatcher[N+1];
4958 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
4959 newp[N] = pa;
4960 outInfo.info.uriPermissionPatterns = newp;
4961 }
4962 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004963 } else {
4964 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004965 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004966 + parser.getName() + " at " + mArchiveSourcePath + " "
4967 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004968 XmlUtils.skipCurrentTag(parser);
4969 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004970 } else {
4971 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
4972 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004973 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004974 }
4975 XmlUtils.skipCurrentTag(parser);
4976
4977 } else if (parser.getName().equals("path-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004978 TypedArray sa = res.obtainAttributes(parser,
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004979 com.android.internal.R.styleable.AndroidManifestPathPermission);
4980
4981 PathPermission pa = null;
4982
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004983 String permission = sa.getNonConfigurationString(
4984 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
4985 String readPermission = sa.getNonConfigurationString(
4986 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004987 if (readPermission == null) {
4988 readPermission = permission;
4989 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004990 String writePermission = sa.getNonConfigurationString(
4991 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004992 if (writePermission == null) {
4993 writePermission = permission;
4994 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004995
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004996 boolean havePerm = false;
4997 if (readPermission != null) {
4998 readPermission = readPermission.intern();
4999 havePerm = true;
5000 }
5001 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00005002 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005003 havePerm = true;
5004 }
5005
5006 if (!havePerm) {
5007 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005008 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005009 + parser.getName() + " at " + mArchiveSourcePath + " "
5010 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005011 XmlUtils.skipCurrentTag(parser);
5012 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005013 } else {
5014 outError[0] = "No readPermission or writePermssion for <path-permission>";
5015 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005016 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005017 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005018
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005019 String path = sa.getNonConfigurationString(
5020 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005021 if (path != null) {
5022 pa = new PathPermission(path,
5023 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
5024 }
5025
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005026 path = sa.getNonConfigurationString(
5027 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005028 if (path != null) {
5029 pa = new PathPermission(path,
5030 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
5031 }
5032
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005033 path = sa.getNonConfigurationString(
5034 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005035 if (path != null) {
5036 pa = new PathPermission(path,
5037 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
5038 }
5039
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005040 path = sa.getNonConfigurationString(
5041 com.android.internal.R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
5042 if (path != null) {
5043 pa = new PathPermission(path,
5044 PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission);
5045 }
5046
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005047 sa.recycle();
5048
5049 if (pa != null) {
5050 if (outInfo.info.pathPermissions == null) {
5051 outInfo.info.pathPermissions = new PathPermission[1];
5052 outInfo.info.pathPermissions[0] = pa;
5053 } else {
5054 final int N = outInfo.info.pathPermissions.length;
5055 PathPermission[] newp = new PathPermission[N+1];
5056 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
5057 newp[N] = pa;
5058 outInfo.info.pathPermissions = newp;
5059 }
5060 } else {
5061 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005062 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005063 + parser.getName() + " at " + mArchiveSourcePath + " "
5064 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005065 XmlUtils.skipCurrentTag(parser);
5066 continue;
5067 }
5068 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5069 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005070 }
5071 XmlUtils.skipCurrentTag(parser);
5072
5073 } else {
5074 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005075 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005076 + parser.getName() + " at " + mArchiveSourcePath + " "
5077 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005078 XmlUtils.skipCurrentTag(parser);
5079 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005080 } else {
5081 outError[0] = "Bad element under <provider>: " + parser.getName();
5082 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005083 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005084 }
5085 }
5086 return true;
5087 }
5088
5089 private Service parseService(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08005090 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005091 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005092 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005093 com.android.internal.R.styleable.AndroidManifestService);
5094
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005095 if (mParseServiceArgs == null) {
5096 mParseServiceArgs = new ParseComponentArgs(owner, outError,
5097 com.android.internal.R.styleable.AndroidManifestService_name,
5098 com.android.internal.R.styleable.AndroidManifestService_label,
5099 com.android.internal.R.styleable.AndroidManifestService_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005100 com.android.internal.R.styleable.AndroidManifestService_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07005101 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08005102 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005103 mSeparateProcesses,
5104 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005105 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005106 com.android.internal.R.styleable.AndroidManifestService_enabled);
5107 mParseServiceArgs.tag = "<service>";
5108 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005109
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005110 mParseServiceArgs.sa = sa;
5111 mParseServiceArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005112
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005113 Service s = new Service(mParseServiceArgs, new ServiceInfo());
5114 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005115 sa.recycle();
5116 return null;
5117 }
5118
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005119 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005120 com.android.internal.R.styleable.AndroidManifestService_exported);
5121 if (setExported) {
5122 s.info.exported = sa.getBoolean(
5123 com.android.internal.R.styleable.AndroidManifestService_exported, false);
5124 }
5125
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005126 String str = sa.getNonConfigurationString(
5127 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005128 if (str == null) {
5129 s.info.permission = owner.applicationInfo.permission;
5130 } else {
5131 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
5132 }
5133
Todd Kennedye9d0d272017-01-23 06:49:29 -08005134 s.info.splitName =
5135 sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0);
5136
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005137 s.info.flags = 0;
5138 if (sa.getBoolean(
5139 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
5140 false)) {
5141 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
5142 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08005143 if (sa.getBoolean(
5144 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
5145 false)) {
5146 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
5147 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005148 if (sa.getBoolean(
Robert Sesekb9a86662015-12-09 16:22:45 -05005149 com.android.internal.R.styleable.AndroidManifestService_externalService,
5150 false)) {
5151 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
5152 }
5153 if (sa.getBoolean(
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005154 com.android.internal.R.styleable.AndroidManifestService_singleUser,
5155 false)) {
5156 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07005157 if (s.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005158 Slog.w(TAG, "Service exported request ignored due to singleUser: "
5159 + s.className + " at " + mArchiveSourcePath + " "
5160 + parser.getPositionDescription());
5161 s.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07005162 setExported = true;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005163 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005164 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005165
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005166 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
5167 R.styleable.AndroidManifestService_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005168 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005169 if (s.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005170 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005171 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005172 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005173
Todd Kennedy752fb702017-03-21 16:28:10 -07005174 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08005175 sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005176 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005177 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005178 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005179 }
5180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005181 sa.recycle();
5182
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005183 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5184 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005185 // A heavy-weight application can not have services in its main process
5186 // We can do direct compare because we intern all strings.
5187 if (s.info.processName == owner.packageName) {
5188 outError[0] = "Heavy-weight applications can not have services in main process";
5189 return null;
5190 }
5191 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005193 int outerDepth = parser.getDepth();
5194 int type;
5195 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5196 && (type != XmlPullParser.END_TAG
5197 || parser.getDepth() > outerDepth)) {
5198 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5199 continue;
5200 }
5201
5202 if (parser.getName().equals("intent-filter")) {
5203 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005204 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5205 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005206 return null;
5207 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005208 if (visibleToEphemeral) {
5209 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5210 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005211 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005212 s.intents.add(intent);
5213 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005214 if ((s.metaData=parseMetaData(res, parser, s.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005215 outError)) == null) {
5216 return null;
5217 }
Todd Kennedy752fb702017-03-21 16:28:10 -07005218 // we don't have an attribute [or it's false], but, we have meta-data
5219 if (!visibleToEphemeral && s.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
5220 visibleToEphemeral = true; // set in case there are more intent filters
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005221 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy752fb702017-03-21 16:28:10 -07005222 owner.visibleToInstantApps = true;
5223 // cycle through any filters already seen
5224 for (int i = s.intents.size() - 1; i >= 0; --i) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005225 s.intents.get(i)
5226 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07005227 }
5228 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005229 } else {
5230 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005231 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005232 + parser.getName() + " at " + mArchiveSourcePath + " "
5233 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005234 XmlUtils.skipCurrentTag(parser);
5235 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005236 } else {
5237 outError[0] = "Bad element under <service>: " + parser.getName();
5238 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005240 }
5241 }
5242
5243 if (!setExported) {
5244 s.info.exported = s.intents.size() > 0;
5245 }
5246
5247 return s;
5248 }
5249
Chad Brubaker49414832017-04-13 16:13:23 -07005250 private boolean isImplicitlyExposedIntent(IntentInfo intent) {
5251 return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
5252 || intent.hasAction(Intent.ACTION_SEND)
5253 || intent.hasAction(Intent.ACTION_SENDTO)
5254 || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005255 }
5256
Svet Ganov354cd3c2015-12-17 11:35:04 -08005257 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
5258 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005259 int outerDepth = parser.getDepth();
5260 int type;
5261 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5262 && (type != XmlPullParser.END_TAG
5263 || parser.getDepth() > outerDepth)) {
5264 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5265 continue;
5266 }
5267
5268 if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005269 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005270 outInfo.metaData, outError)) == null) {
5271 return false;
5272 }
5273 } else {
5274 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005275 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005276 + parser.getName() + " at " + mArchiveSourcePath + " "
5277 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005278 XmlUtils.skipCurrentTag(parser);
5279 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005280 } else {
5281 outError[0] = "Bad element under " + tag + ": " + parser.getName();
5282 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005283 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005284 }
5285 }
5286 return true;
5287 }
5288
5289 private Bundle parseMetaData(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08005290 XmlResourceParser parser, Bundle data, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005291 throws XmlPullParserException, IOException {
5292
Svet Ganov354cd3c2015-12-17 11:35:04 -08005293 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005294 com.android.internal.R.styleable.AndroidManifestMetaData);
5295
5296 if (data == null) {
5297 data = new Bundle();
5298 }
5299
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005300 String name = sa.getNonConfigurationString(
5301 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005302 if (name == null) {
5303 outError[0] = "<meta-data> requires an android:name attribute";
5304 sa.recycle();
5305 return null;
5306 }
5307
Dianne Hackborn854060af2009-07-09 18:14:31 -07005308 name = name.intern();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005310 TypedValue v = sa.peekValue(
5311 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
5312 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005313 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005314 data.putInt(name, v.resourceId);
5315 } else {
5316 v = sa.peekValue(
5317 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07005318 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005319 if (v != null) {
5320 if (v.type == TypedValue.TYPE_STRING) {
5321 CharSequence cs = v.coerceToString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00005322 data.putString(name, cs != null ? cs.toString() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
5324 data.putBoolean(name, v.data != 0);
5325 } else if (v.type >= TypedValue.TYPE_FIRST_INT
5326 && v.type <= TypedValue.TYPE_LAST_INT) {
5327 data.putInt(name, v.data);
5328 } else if (v.type == TypedValue.TYPE_FLOAT) {
5329 data.putFloat(name, v.getFloat());
5330 } else {
5331 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005332 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005333 + parser.getName() + " at " + mArchiveSourcePath + " "
5334 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 } else {
5336 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
5337 data = null;
5338 }
5339 }
5340 } else {
5341 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
5342 data = null;
5343 }
5344 }
5345
5346 sa.recycle();
5347
5348 XmlUtils.skipCurrentTag(parser);
5349
5350 return data;
5351 }
5352
Adam Lesinski4e862812016-11-21 16:02:24 -08005353 private static VerifierInfo parseVerifier(AttributeSet attrs) {
5354 String packageName = null;
5355 String encodedPublicKey = null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005356
Adam Lesinski4e862812016-11-21 16:02:24 -08005357 final int attrCount = attrs.getAttributeCount();
5358 for (int i = 0; i < attrCount; i++) {
5359 final int attrResId = attrs.getAttributeNameResource(i);
5360 switch (attrResId) {
5361 case com.android.internal.R.attr.name:
5362 packageName = attrs.getAttributeValue(i);
5363 break;
Kenny Root05ca4c92011-09-15 10:36:25 -07005364
Adam Lesinski4e862812016-11-21 16:02:24 -08005365 case com.android.internal.R.attr.publicKey:
5366 encodedPublicKey = attrs.getAttributeValue(i);
5367 break;
5368 }
5369 }
Kenny Root05ca4c92011-09-15 10:36:25 -07005370
5371 if (packageName == null || packageName.length() == 0) {
5372 Slog.i(TAG, "verifier package name was null; skipping");
5373 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005374 }
5375
Christopher Tate30147332014-04-15 12:57:47 -07005376 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
5377 if (publicKey == null) {
5378 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
5379 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08005380 }
5381
Christopher Tate30147332014-04-15 12:57:47 -07005382 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08005383 }
5384
Christopher Tate30147332014-04-15 12:57:47 -07005385 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
5386 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07005387 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07005388 return null;
5389 }
5390
Kenny Root05ca4c92011-09-15 10:36:25 -07005391 EncodedKeySpec keySpec;
5392 try {
5393 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
5394 keySpec = new X509EncodedKeySpec(encoded);
5395 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07005396 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07005397 return null;
5398 }
5399
5400 /* First try the key as an RSA key. */
5401 try {
5402 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005403 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005404 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005405 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005406 } catch (InvalidKeySpecException e) {
5407 // Not a RSA public key.
5408 }
5409
dcashman1616f302015-05-29 14:47:23 -07005410 /* Now try it as a ECDSA key. */
5411 try {
5412 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
5413 return keyFactory.generatePublic(keySpec);
5414 } catch (NoSuchAlgorithmException e) {
5415 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
5416 } catch (InvalidKeySpecException e) {
5417 // Not a ECDSA public key.
5418 }
5419
Kenny Root05ca4c92011-09-15 10:36:25 -07005420 /* Now try it as a DSA key. */
5421 try {
5422 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005423 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005424 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005425 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005426 } catch (InvalidKeySpecException e) {
5427 // Not a DSA public key.
5428 }
5429
dcashman1616f302015-05-29 14:47:23 -07005430 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07005431 return null;
5432 }
5433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005434 private static final String ANDROID_RESOURCES
5435 = "http://schemas.android.com/apk/res/android";
5436
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005437 private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs,
5438 boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
5439 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005440
Svet Ganov354cd3c2015-12-17 11:35:04 -08005441 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005442 com.android.internal.R.styleable.AndroidManifestIntentFilter);
5443
5444 int priority = sa.getInt(
5445 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005446 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08005447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005448 TypedValue v = sa.peekValue(
5449 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
5450 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
5451 outInfo.nonLocalizedLabel = v.coerceToString();
5452 }
5453
Todd Kennedya83bfca2016-06-03 07:52:17 -07005454 final boolean useRoundIcon =
5455 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
5456 int roundIconVal = useRoundIcon ? sa.getResourceId(
5457 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
5458 if (roundIconVal != 0) {
5459 outInfo.icon = roundIconVal;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005460 } else {
5461 outInfo.icon = sa.getResourceId(
5462 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
5463 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005464
Adam Powell81cd2e92010-04-21 16:35:18 -07005465 outInfo.logo = sa.getResourceId(
5466 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005467
Jose Limaf78e3122014-03-06 12:13:15 -08005468 outInfo.banner = sa.getResourceId(
5469 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
5470
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08005471 if (allowAutoVerify) {
5472 outInfo.setAutoVerify(sa.getBoolean(
5473 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
5474 false));
5475 }
5476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005477 sa.recycle();
5478
5479 int outerDepth = parser.getDepth();
5480 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07005481 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
5482 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
5483 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005484 continue;
5485 }
5486
5487 String nodeName = parser.getName();
5488 if (nodeName.equals("action")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005489 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005490 ANDROID_RESOURCES, "name");
5491 if (value == null || value == "") {
5492 outError[0] = "No value supplied for <android:name>";
5493 return false;
5494 }
5495 XmlUtils.skipCurrentTag(parser);
5496
5497 outInfo.addAction(value);
5498 } else if (nodeName.equals("category")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005499 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005500 ANDROID_RESOURCES, "name");
5501 if (value == null || value == "") {
5502 outError[0] = "No value supplied for <android:name>";
5503 return false;
5504 }
5505 XmlUtils.skipCurrentTag(parser);
5506
5507 outInfo.addCategory(value);
5508
5509 } else if (nodeName.equals("data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005510 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005511 com.android.internal.R.styleable.AndroidManifestData);
5512
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005513 String str = sa.getNonConfigurationString(
5514 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005515 if (str != null) {
5516 try {
5517 outInfo.addDataType(str);
5518 } catch (IntentFilter.MalformedMimeTypeException e) {
5519 outError[0] = e.toString();
5520 sa.recycle();
5521 return false;
5522 }
5523 }
5524
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005525 str = sa.getNonConfigurationString(
5526 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005527 if (str != null) {
5528 outInfo.addDataScheme(str);
5529 }
5530
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005531 str = sa.getNonConfigurationString(
5532 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
5533 if (str != null) {
5534 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
5535 }
5536
5537 str = sa.getNonConfigurationString(
5538 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
5539 if (str != null) {
5540 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
5541 }
5542
5543 str = sa.getNonConfigurationString(
5544 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
5545 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005546 if (!allowGlobs) {
5547 outError[0] = "sspPattern not allowed here; ssp must be literal";
5548 return false;
5549 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005550 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5551 }
5552
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005553 String host = sa.getNonConfigurationString(
5554 com.android.internal.R.styleable.AndroidManifestData_host, 0);
5555 String port = sa.getNonConfigurationString(
5556 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005557 if (host != null) {
5558 outInfo.addDataAuthority(host, port);
5559 }
5560
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005561 str = sa.getNonConfigurationString(
5562 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005563 if (str != null) {
5564 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
5565 }
5566
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005567 str = sa.getNonConfigurationString(
5568 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005569 if (str != null) {
5570 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
5571 }
5572
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005573 str = sa.getNonConfigurationString(
5574 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005575 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005576 if (!allowGlobs) {
5577 outError[0] = "pathPattern not allowed here; path must be literal";
5578 return false;
5579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005580 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5581 }
5582
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005583 str = sa.getNonConfigurationString(
5584 com.android.internal.R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
5585 if (str != null) {
5586 if (!allowGlobs) {
5587 outError[0] = "pathAdvancedPattern not allowed here; path must be literal";
5588 return false;
5589 }
5590 outInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
5591 }
5592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005593 sa.recycle();
5594 XmlUtils.skipCurrentTag(parser);
5595 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005596 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005597 + parser.getName() + " at " + mArchiveSourcePath + " "
5598 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005599 XmlUtils.skipCurrentTag(parser);
5600 } else {
5601 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
5602 return false;
5603 }
5604 }
5605
5606 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07005607
5608 if (DEBUG_PARSER) {
5609 final StringBuilder cats = new StringBuilder("Intent d=");
5610 cats.append(outInfo.hasDefault);
5611 cats.append(", cat=");
5612
5613 final Iterator<String> it = outInfo.categoriesIterator();
5614 if (it != null) {
5615 while (it.hasNext()) {
5616 cats.append(' ');
5617 cats.append(it.next());
5618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005619 }
Kenny Rootd2d29252011-08-08 11:27:57 -07005620 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005621 }
5622
5623 return true;
5624 }
5625
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005626 /**
5627 * Representation of a full package parsed from APK files on disk. A package
5628 * consists of a single base APK, and zero or more split APKs.
5629 */
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00005630 public final static class Package implements Parcelable {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07005631
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005632 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08005633
Svet Ganov67882122016-12-11 16:36:34 -08005634 // The package name declared in the manifest as the package can be
5635 // renamed, for example static shared libs use synthetic package names.
5636 public String manifestPackageName;
5637
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005638 /** Names of any split APKs, ordered by parsed splitName */
5639 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005640
5641 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07005642
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07005643 public String volumeUuid;
5644
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005645 /**
5646 * Path where this package was found on disk. For monolithic packages
5647 * this is path to single base APK file; for cluster packages this is
5648 * path to the cluster directory.
5649 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005650 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005651
5652 /** Path of base APK */
5653 public String baseCodePath;
5654 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005655 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005656
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08005657 /** Revision code of base APK */
5658 public int baseRevisionCode;
5659 /** Revision codes of any split APKs, ordered by parsed splitName */
5660 public int[] splitRevisionCodes;
5661
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005662 /** Flags of any split APKs; ordered by parsed splitName */
5663 public int[] splitFlags;
5664
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005665 /**
5666 * Private flags of any split APKs; ordered by parsed splitName.
5667 *
5668 * {@hide}
5669 */
5670 public int[] splitPrivateFlags;
5671
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005672 public boolean baseHardwareAccelerated;
5673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 // For now we only support one application per package.
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00005675 public ApplicationInfo applicationInfo = new ApplicationInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005676
5677 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
5678 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
5679 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
5680 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
5681 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
5682 public final ArrayList<Service> services = new ArrayList<Service>(0);
5683 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
5684
5685 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
5686
Dianne Hackborn854060af2009-07-09 18:14:31 -07005687 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07005688
Svet Ganov354cd3c2015-12-17 11:35:04 -08005689 public Package parentPackage;
5690 public ArrayList<Package> childPackages;
5691
Svet Ganov67882122016-12-11 16:36:34 -08005692 public String staticSharedLibName = null;
5693 public int staticSharedLibVersion = 0;
Dianne Hackbornc895be72013-03-11 17:48:43 -07005694 public ArrayList<String> libraryNames = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07005695 public ArrayList<String> usesLibraries = null;
Svet Ganov67882122016-12-11 16:36:34 -08005696 public ArrayList<String> usesStaticLibraries = null;
5697 public int[] usesStaticLibrariesVersions = null;
5698 public String[] usesStaticLibrariesCertDigests = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07005699 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005700 public String[] usesLibraryFiles = null;
5701
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005702 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
5703
Dianne Hackbornc1552392010-03-03 16:19:01 -08005704 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005705 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08005706 public ArrayList<String> mAdoptPermissions = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005708 // We store the application meta-data independently to avoid multiple unwanted references
5709 public Bundle mAppMetaData = null;
5710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005711 // The version code declared for this package.
5712 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08005713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005714 // The version name declared for this package.
5715 public String mVersionName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005717 // The shared user id that this package wants to use.
5718 public String mSharedUserId;
5719
5720 // The shared user label that this package wants to use.
5721 public int mSharedUserLabel;
5722
5723 // Signatures that were read from the package.
Jeff Sharkey275e0852014-06-17 18:18:49 -07005724 public Signature[] mSignatures;
5725 public Certificate[][] mCertificates;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005726
5727 // For use by package manager service for quick lookup of
5728 // preferred up order.
5729 public int mPreferredOrder = 0;
5730
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07005731 // For use by package manager to keep track of when a package was last used.
Brian Carlstromca82e612016-04-19 23:16:08 -07005732 public long[] mLastPackageUsageTimeInMills =
5733 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07005734
Amith Yamasani13593602012-03-22 16:16:17 -07005735 // // User set enabled state.
5736 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
5737 //
5738 // // Whether the package has been stopped.
5739 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005741 // Additional data supplied by callers.
5742 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07005743
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005744 // Applications hardware preferences
5745 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005746
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005747 // Applications requested features
Dianne Hackborn49237342009-08-27 20:08:01 -07005748 public ArrayList<FeatureInfo> reqFeatures = null;
5749
Adam Lesinskid3edfde2014-08-08 17:32:44 -07005750 // Applications requested feature groups
5751 public ArrayList<FeatureGroupInfo> featureGroups = null;
5752
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08005753 public int installLocation;
5754
Jeff Hao272bf3a2014-10-08 13:34:43 -07005755 public boolean coreApp;
5756
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08005757 /* An app that's required for all users and cannot be uninstalled for a user */
5758 public boolean mRequiredForAllUsers;
5759
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07005760 /* The restricted account authenticator type that is used by this application */
5761 public String mRestrictedAccountType;
5762
Amith Yamasaniccbe3892013-04-12 17:52:42 -07005763 /* The required account type without which this application will not function */
5764 public String mRequiredAccountType;
5765
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01005766 public String mOverlayTarget;
Jaekyun Seok42d53f62017-04-10 13:48:58 +09005767 public int mOverlayPriority;
Jaekyun Seok04342892017-03-02 15:24:19 +09005768 public boolean mIsStaticOverlay;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01005769 public boolean mTrustedOverlay;
5770
Geremy Condraf1bcca82013-01-07 22:35:24 -08005771 /**
dcashman989eb3712014-06-17 12:56:12 -07005772 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08005773 */
dcashman989eb3712014-06-17 12:56:12 -07005774 public ArraySet<PublicKey> mSigningKeys;
5775 public ArraySet<String> mUpgradeKeySets;
5776 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08005777
Narayan Kamath4903f642014-08-11 13:33:45 +01005778 /**
5779 * The install time abi override for this package, if any.
5780 *
5781 * TODO: This seems like a horrible place to put the abiOverride because
5782 * this isn't something the packageParser parsers. However, this fits in with
5783 * the rest of the PackageManager where package scanning randomly pushes
5784 * and prods fields out of {@code this.applicationInfo}.
5785 */
5786 public String cpuAbiOverride;
Selim Gurun2d291d82016-02-05 17:50:53 -08005787 /**
5788 * The install time abi override to choose 32bit abi's when multiple abi's
5789 * are present. This is only meaningfull for multiarch applications.
5790 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
5791 */
5792 public boolean use32bitAbi;
Narayan Kamath4903f642014-08-11 13:33:45 +01005793
Todd Kennedyfdd241a2016-04-28 12:26:53 -07005794 public byte[] restrictUpdateHash;
5795
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005796 /**
5797 * Set if the app or any of its components are visible to Instant Apps.
5798 */
5799 public boolean visibleToInstantApps;
5800
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005801 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005802 this.packageName = packageName;
Svet Ganov67882122016-12-11 16:36:34 -08005803 this.manifestPackageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005804 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005805 applicationInfo.uid = -1;
5806 }
5807
Svet Ganov354cd3c2015-12-17 11:35:04 -08005808 public void setApplicationVolumeUuid(String volumeUuid) {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06005809 final UUID storageUuid = StorageManager.convert(volumeUuid);
Svet Ganov354cd3c2015-12-17 11:35:04 -08005810 this.applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06005811 this.applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08005812 if (childPackages != null) {
5813 final int packageCount = childPackages.size();
5814 for (int i = 0; i < packageCount; i++) {
5815 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06005816 childPackages.get(i).applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08005817 }
5818 }
5819 }
5820
5821 public void setApplicationInfoCodePath(String codePath) {
5822 this.applicationInfo.setCodePath(codePath);
5823 if (childPackages != null) {
5824 final int packageCount = childPackages.size();
5825 for (int i = 0; i < packageCount; i++) {
5826 childPackages.get(i).applicationInfo.setCodePath(codePath);
5827 }
5828 }
5829 }
5830
5831 public void setApplicationInfoResourcePath(String resourcePath) {
5832 this.applicationInfo.setResourcePath(resourcePath);
5833 if (childPackages != null) {
5834 final int packageCount = childPackages.size();
5835 for (int i = 0; i < packageCount; i++) {
5836 childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
5837 }
5838 }
5839 }
5840
5841 public void setApplicationInfoBaseResourcePath(String resourcePath) {
5842 this.applicationInfo.setBaseResourcePath(resourcePath);
5843 if (childPackages != null) {
5844 final int packageCount = childPackages.size();
5845 for (int i = 0; i < packageCount; i++) {
5846 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
5847 }
5848 }
5849 }
5850
5851 public void setApplicationInfoBaseCodePath(String baseCodePath) {
5852 this.applicationInfo.setBaseCodePath(baseCodePath);
5853 if (childPackages != null) {
5854 final int packageCount = childPackages.size();
5855 for (int i = 0; i < packageCount; i++) {
5856 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
5857 }
5858 }
5859 }
5860
Todd Kennedy13715d52016-08-01 13:38:57 -07005861 public List<String> getChildPackageNames() {
5862 if (childPackages == null) {
5863 return null;
5864 }
5865 final int childCount = childPackages.size();
5866 final List<String> childPackageNames = new ArrayList<>(childCount);
5867 for (int i = 0; i < childCount; i++) {
5868 String childPackageName = childPackages.get(i).packageName;
5869 childPackageNames.add(childPackageName);
5870 }
5871 return childPackageNames;
5872 }
5873
Svet Ganov354cd3c2015-12-17 11:35:04 -08005874 public boolean hasChildPackage(String packageName) {
5875 final int childCount = (childPackages != null) ? childPackages.size() : 0;
5876 for (int i = 0; i < childCount; i++) {
5877 if (childPackages.get(i).packageName.equals(packageName)) {
5878 return true;
5879 }
5880 }
5881 return false;
5882 }
5883
5884 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
5885 this.applicationInfo.setSplitCodePaths(splitCodePaths);
5886 // Children have no splits
5887 }
5888
5889 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
5890 this.applicationInfo.setSplitResourcePaths(resroucePaths);
5891 // Children have no splits
5892 }
5893
5894 public void setSplitCodePaths(String[] codePaths) {
5895 this.splitCodePaths = codePaths;
5896 }
5897
5898 public void setCodePath(String codePath) {
5899 this.codePath = codePath;
5900 if (childPackages != null) {
5901 final int packageCount = childPackages.size();
5902 for (int i = 0; i < packageCount; i++) {
5903 childPackages.get(i).codePath = codePath;
5904 }
5905 }
5906 }
5907
5908 public void setBaseCodePath(String baseCodePath) {
5909 this.baseCodePath = baseCodePath;
5910 if (childPackages != null) {
5911 final int packageCount = childPackages.size();
5912 for (int i = 0; i < packageCount; i++) {
5913 childPackages.get(i).baseCodePath = baseCodePath;
5914 }
5915 }
5916 }
5917
5918 public void setSignatures(Signature[] signatures) {
5919 this.mSignatures = signatures;
5920 if (childPackages != null) {
5921 final int packageCount = childPackages.size();
5922 for (int i = 0; i < packageCount; i++) {
5923 childPackages.get(i).mSignatures = signatures;
5924 }
5925 }
5926 }
5927
5928 public void setVolumeUuid(String volumeUuid) {
5929 this.volumeUuid = volumeUuid;
5930 if (childPackages != null) {
5931 final int packageCount = childPackages.size();
5932 for (int i = 0; i < packageCount; i++) {
5933 childPackages.get(i).volumeUuid = volumeUuid;
5934 }
5935 }
5936 }
5937
5938 public void setApplicationInfoFlags(int mask, int flags) {
5939 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
5940 if (childPackages != null) {
5941 final int packageCount = childPackages.size();
5942 for (int i = 0; i < packageCount; i++) {
5943 childPackages.get(i).applicationInfo.flags =
5944 (applicationInfo.flags & ~mask) | (mask & flags);
5945 }
5946 }
5947 }
5948
Selim Gurun75827b22016-02-09 10:55:33 -08005949 public void setUse32bitAbi(boolean use32bitAbi) {
Selim Gurun2d291d82016-02-05 17:50:53 -08005950 this.use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08005951 if (childPackages != null) {
5952 final int packageCount = childPackages.size();
5953 for (int i = 0; i < packageCount; i++) {
Selim Gurun2d291d82016-02-05 17:50:53 -08005954 childPackages.get(i).use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08005955 }
5956 }
5957 }
5958
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005959 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07005960 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005961 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07005962 if (!ArrayUtils.isEmpty(splitCodePaths)) {
5963 Collections.addAll(paths, splitCodePaths);
5964 }
5965 return paths;
5966 }
5967
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005968 /**
5969 * Filtered set of {@link #getAllCodePaths()} that excludes
5970 * resource-only APKs.
5971 */
5972 public List<String> getAllCodePathsExcludingResourceOnly() {
5973 ArrayList<String> paths = new ArrayList<>();
5974 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
5975 paths.add(baseCodePath);
5976 }
5977 if (!ArrayUtils.isEmpty(splitCodePaths)) {
5978 for (int i = 0; i < splitCodePaths.length; i++) {
5979 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
5980 paths.add(splitCodePaths[i]);
5981 }
5982 }
5983 }
5984 return paths;
5985 }
5986
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005987 public void setPackageName(String newName) {
5988 packageName = newName;
5989 applicationInfo.packageName = newName;
5990 for (int i=permissions.size()-1; i>=0; i--) {
5991 permissions.get(i).setPackageName(newName);
5992 }
5993 for (int i=permissionGroups.size()-1; i>=0; i--) {
5994 permissionGroups.get(i).setPackageName(newName);
5995 }
5996 for (int i=activities.size()-1; i>=0; i--) {
5997 activities.get(i).setPackageName(newName);
5998 }
5999 for (int i=receivers.size()-1; i>=0; i--) {
6000 receivers.get(i).setPackageName(newName);
6001 }
6002 for (int i=providers.size()-1; i>=0; i--) {
6003 providers.get(i).setPackageName(newName);
6004 }
6005 for (int i=services.size()-1; i>=0; i--) {
6006 services.get(i).setPackageName(newName);
6007 }
6008 for (int i=instrumentation.size()-1; i>=0; i--) {
6009 instrumentation.get(i).setPackageName(newName);
6010 }
6011 }
Dianne Hackborn65696252012-03-05 18:49:21 -08006012
6013 public boolean hasComponentClassName(String name) {
6014 for (int i=activities.size()-1; i>=0; i--) {
6015 if (name.equals(activities.get(i).className)) {
6016 return true;
6017 }
6018 }
6019 for (int i=receivers.size()-1; i>=0; i--) {
6020 if (name.equals(receivers.get(i).className)) {
6021 return true;
6022 }
6023 }
6024 for (int i=providers.size()-1; i>=0; i--) {
6025 if (name.equals(providers.get(i).className)) {
6026 return true;
6027 }
6028 }
6029 for (int i=services.size()-1; i>=0; i--) {
6030 if (name.equals(services.get(i).className)) {
6031 return true;
6032 }
6033 }
6034 for (int i=instrumentation.size()-1; i>=0; i--) {
6035 if (name.equals(instrumentation.get(i).className)) {
6036 return true;
6037 }
6038 }
6039 return false;
6040 }
6041
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08006042 /**
6043 * @hide
6044 */
6045 public boolean isForwardLocked() {
6046 return applicationInfo.isForwardLocked();
6047 }
6048
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006049 /**
6050 * @hide
6051 */
6052 public boolean isSystemApp() {
6053 return applicationInfo.isSystemApp();
6054 }
6055
6056 /**
6057 * @hide
6058 */
Svet Ganovadc1cf42015-06-15 16:36:24 -07006059 public boolean isPrivilegedApp() {
6060 return applicationInfo.isPrivilegedApp();
6061 }
6062
6063 /**
6064 * @hide
6065 */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006066 public boolean isUpdatedSystemApp() {
6067 return applicationInfo.isUpdatedSystemApp();
6068 }
6069
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006070 /**
6071 * @hide
6072 */
6073 public boolean canHaveOatDir() {
6074 // The following app types CANNOT have oat directory
6075 // - non-updated system apps
6076 // - forward-locked apps or apps installed in ASEC containers
6077 return (!isSystemApp() || isUpdatedSystemApp())
6078 && !isForwardLocked() && !applicationInfo.isExternalAsec();
6079 }
6080
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006081 public boolean isMatch(int flags) {
6082 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
6083 return isSystemApp();
6084 }
6085 return true;
6086 }
6087
Brian Carlstromca82e612016-04-19 23:16:08 -07006088 public long getLatestPackageUseTimeInMills() {
6089 long latestUse = 0L;
6090 for (long use : mLastPackageUsageTimeInMills) {
6091 latestUse = Math.max(latestUse, use);
6092 }
6093 return latestUse;
6094 }
6095
David Brazdil90e26992016-04-18 14:08:52 +01006096 public long getLatestForegroundPackageUseTimeInMills() {
6097 int[] foregroundReasons = {
6098 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
6099 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
6100 };
6101
6102 long latestUse = 0L;
6103 for (int reason : foregroundReasons) {
6104 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
6105 }
6106 return latestUse;
6107 }
6108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006109 public String toString() {
6110 return "Package{"
6111 + Integer.toHexString(System.identityHashCode(this))
6112 + " " + packageName + "}";
6113 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006114
6115 @Override
6116 public int describeContents() {
6117 return 0;
6118 }
6119
6120 public Package(Parcel dest) {
6121 // We use the boot classloader for all classes that we load.
6122 final ClassLoader boot = Object.class.getClassLoader();
6123
Narayan Kamath07ac1442017-02-10 15:08:07 +00006124 packageName = dest.readString().intern();
Svet Ganov67882122016-12-11 16:36:34 -08006125 manifestPackageName = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006126 splitNames = dest.readStringArray();
6127 volumeUuid = dest.readString();
6128 codePath = dest.readString();
6129 baseCodePath = dest.readString();
6130 splitCodePaths = dest.readStringArray();
6131 baseRevisionCode = dest.readInt();
6132 splitRevisionCodes = dest.createIntArray();
6133 splitFlags = dest.createIntArray();
6134 splitPrivateFlags = dest.createIntArray();
6135 baseHardwareAccelerated = (dest.readInt() == 1);
6136 applicationInfo = dest.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006137 if (applicationInfo.permission != null) {
6138 applicationInfo.permission = applicationInfo.permission.intern();
6139 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006140
6141 // We don't serialize the "owner" package and the application info object for each of
6142 // these components, in order to save space and to avoid circular dependencies while
6143 // serialization. We need to fix them all up here.
6144 dest.readParcelableList(permissions, boot);
6145 fixupOwner(permissions);
6146 dest.readParcelableList(permissionGroups, boot);
6147 fixupOwner(permissionGroups);
6148 dest.readParcelableList(activities, boot);
6149 fixupOwner(activities);
6150 dest.readParcelableList(receivers, boot);
6151 fixupOwner(receivers);
6152 dest.readParcelableList(providers, boot);
6153 fixupOwner(providers);
6154 dest.readParcelableList(services, boot);
6155 fixupOwner(services);
6156 dest.readParcelableList(instrumentation, boot);
6157 fixupOwner(instrumentation);
6158
6159 dest.readStringList(requestedPermissions);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006160 internStringArrayList(requestedPermissions);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006161 protectedBroadcasts = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006162 internStringArrayList(protectedBroadcasts);
6163
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006164 parentPackage = dest.readParcelable(boot);
6165
6166 childPackages = new ArrayList<>();
6167 dest.readParcelableList(childPackages, boot);
6168 if (childPackages.size() == 0) {
6169 childPackages = null;
6170 }
6171
Svet Ganov67882122016-12-11 16:36:34 -08006172 staticSharedLibName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006173 if (staticSharedLibName != null) {
6174 staticSharedLibName = staticSharedLibName.intern();
6175 }
Svet Ganov67882122016-12-11 16:36:34 -08006176 staticSharedLibVersion = dest.readInt();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006177 libraryNames = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006178 internStringArrayList(libraryNames);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006179 usesLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006180 internStringArrayList(usesLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006181 usesOptionalLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006182 internStringArrayList(usesOptionalLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006183 usesLibraryFiles = dest.readStringArray();
6184
Svet Ganov67882122016-12-11 16:36:34 -08006185 final int libCount = dest.readInt();
6186 if (libCount > 0) {
6187 usesStaticLibraries = new ArrayList<>(libCount);
6188 dest.readStringList(usesStaticLibraries);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006189 internStringArrayList(usesStaticLibraries);
Svet Ganov67882122016-12-11 16:36:34 -08006190 usesStaticLibrariesVersions = new int[libCount];
6191 dest.readIntArray(usesStaticLibrariesVersions);
6192 usesStaticLibrariesCertDigests = new String[libCount];
6193 dest.readStringArray(usesStaticLibrariesCertDigests);
6194 }
6195
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006196 preferredActivityFilters = new ArrayList<>();
6197 dest.readParcelableList(preferredActivityFilters, boot);
6198 if (preferredActivityFilters.size() == 0) {
6199 preferredActivityFilters = null;
6200 }
6201
6202 mOriginalPackages = dest.createStringArrayList();
6203 mRealPackage = dest.readString();
6204 mAdoptPermissions = dest.createStringArrayList();
6205 mAppMetaData = dest.readBundle();
6206 mVersionCode = dest.readInt();
6207 mVersionName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006208 if (mVersionName != null) {
6209 mVersionName = mVersionName.intern();
6210 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006211 mSharedUserId = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006212 if (mSharedUserId != null) {
6213 mSharedUserId = mSharedUserId.intern();
6214 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006215 mSharedUserLabel = dest.readInt();
6216
6217 mSignatures = (Signature[]) dest.readParcelableArray(boot, Signature.class);
6218 mCertificates = (Certificate[][]) dest.readSerializable();
6219
6220 mPreferredOrder = dest.readInt();
6221
6222 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6223 // is parsed from the APK.
6224
6225 // Object mExtras is not persisted because it is not information that is read from
6226 // the APK, rather, it is supplied by callers.
6227
6228
6229 configPreferences = new ArrayList<>();
6230 dest.readParcelableList(configPreferences, boot);
6231 if (configPreferences.size() == 0) {
6232 configPreferences = null;
6233 }
6234
6235 reqFeatures = new ArrayList<>();
6236 dest.readParcelableList(reqFeatures, boot);
6237 if (reqFeatures.size() == 0) {
6238 reqFeatures = null;
6239 }
6240
6241 featureGroups = new ArrayList<>();
6242 dest.readParcelableList(featureGroups, boot);
6243 if (featureGroups.size() == 0) {
6244 featureGroups = null;
6245 }
6246
6247 installLocation = dest.readInt();
6248 coreApp = (dest.readInt() == 1);
6249 mRequiredForAllUsers = (dest.readInt() == 1);
6250 mRestrictedAccountType = dest.readString();
6251 mRequiredAccountType = dest.readString();
6252 mOverlayTarget = dest.readString();
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006253 mOverlayPriority = dest.readInt();
Jaekyun Seok04342892017-03-02 15:24:19 +09006254 mIsStaticOverlay = (dest.readInt() == 1);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006255 mTrustedOverlay = (dest.readInt() == 1);
6256 mSigningKeys = (ArraySet<PublicKey>) dest.readArraySet(boot);
6257 mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
6258
6259 mKeySetMapping = readKeySetMapping(dest);
6260
6261 cpuAbiOverride = dest.readString();
6262 use32bitAbi = (dest.readInt() == 1);
6263 restrictUpdateHash = dest.createByteArray();
Chad Brubaker49f24c62017-04-05 13:08:21 -07006264 visibleToInstantApps = dest.readInt() == 1;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006265 }
6266
Narayan Kamath07ac1442017-02-10 15:08:07 +00006267 private static void internStringArrayList(List<String> list) {
6268 if (list != null) {
6269 final int N = list.size();
6270 for (int i = 0; i < N; ++i) {
6271 list.set(i, list.get(i).intern());
6272 }
6273 }
6274 }
6275
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006276 /**
6277 * Sets the package owner and the the {@code applicationInfo} for every component
6278 * owner by this package.
6279 */
6280 private void fixupOwner(List<? extends Component<?>> list) {
6281 if (list != null) {
6282 for (Component<?> c : list) {
6283 c.owner = this;
6284 if (c instanceof Activity) {
6285 ((Activity) c).info.applicationInfo = this.applicationInfo;
6286 } else if (c instanceof Service) {
6287 ((Service) c).info.applicationInfo = this.applicationInfo;
6288 } else if (c instanceof Provider) {
6289 ((Provider) c).info.applicationInfo = this.applicationInfo;
6290 }
6291 }
6292 }
6293 }
6294
6295 @Override
6296 public void writeToParcel(Parcel dest, int flags) {
6297 dest.writeString(packageName);
Svet Ganov67882122016-12-11 16:36:34 -08006298 dest.writeString(manifestPackageName);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006299 dest.writeStringArray(splitNames);
6300 dest.writeString(volumeUuid);
6301 dest.writeString(codePath);
6302 dest.writeString(baseCodePath);
6303 dest.writeStringArray(splitCodePaths);
6304 dest.writeInt(baseRevisionCode);
6305 dest.writeIntArray(splitRevisionCodes);
6306 dest.writeIntArray(splitFlags);
6307 dest.writeIntArray(splitPrivateFlags);
6308 dest.writeInt(baseHardwareAccelerated ? 1 : 0);
6309 dest.writeParcelable(applicationInfo, flags);
6310
6311 dest.writeParcelableList(permissions, flags);
6312 dest.writeParcelableList(permissionGroups, flags);
6313 dest.writeParcelableList(activities, flags);
6314 dest.writeParcelableList(receivers, flags);
6315 dest.writeParcelableList(providers, flags);
6316 dest.writeParcelableList(services, flags);
6317 dest.writeParcelableList(instrumentation, flags);
6318
6319 dest.writeStringList(requestedPermissions);
6320 dest.writeStringList(protectedBroadcasts);
6321 dest.writeParcelable(parentPackage, flags);
6322 dest.writeParcelableList(childPackages, flags);
Svet Ganov67882122016-12-11 16:36:34 -08006323 dest.writeString(staticSharedLibName);
6324 dest.writeInt(staticSharedLibVersion);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006325 dest.writeStringList(libraryNames);
6326 dest.writeStringList(usesLibraries);
6327 dest.writeStringList(usesOptionalLibraries);
6328 dest.writeStringArray(usesLibraryFiles);
6329
Svet Ganov67882122016-12-11 16:36:34 -08006330 if (ArrayUtils.isEmpty(usesStaticLibraries)) {
6331 dest.writeInt(-1);
6332 } else {
6333 dest.writeInt(usesStaticLibraries.size());
6334 dest.writeStringList(usesStaticLibraries);
6335 dest.writeIntArray(usesStaticLibrariesVersions);
6336 dest.writeStringArray(usesStaticLibrariesCertDigests);
6337 }
6338
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006339 dest.writeParcelableList(preferredActivityFilters, flags);
6340
6341 dest.writeStringList(mOriginalPackages);
6342 dest.writeString(mRealPackage);
6343 dest.writeStringList(mAdoptPermissions);
6344 dest.writeBundle(mAppMetaData);
6345 dest.writeInt(mVersionCode);
6346 dest.writeString(mVersionName);
6347 dest.writeString(mSharedUserId);
6348 dest.writeInt(mSharedUserLabel);
6349
6350 dest.writeParcelableArray(mSignatures, flags);
6351 dest.writeSerializable(mCertificates);
6352
6353 dest.writeInt(mPreferredOrder);
6354
6355 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6356 // is parsed from the APK.
6357
6358 // Object mExtras is not persisted because it is not information that is read from
6359 // the APK, rather, it is supplied by callers.
6360
6361 dest.writeParcelableList(configPreferences, flags);
6362 dest.writeParcelableList(reqFeatures, flags);
6363 dest.writeParcelableList(featureGroups, flags);
6364
6365 dest.writeInt(installLocation);
6366 dest.writeInt(coreApp ? 1 : 0);
6367 dest.writeInt(mRequiredForAllUsers ? 1 : 0);
6368 dest.writeString(mRestrictedAccountType);
6369 dest.writeString(mRequiredAccountType);
6370 dest.writeString(mOverlayTarget);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006371 dest.writeInt(mOverlayPriority);
Jaekyun Seok04342892017-03-02 15:24:19 +09006372 dest.writeInt(mIsStaticOverlay ? 1 : 0);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006373 dest.writeInt(mTrustedOverlay ? 1 : 0);
6374 dest.writeArraySet(mSigningKeys);
6375 dest.writeArraySet(mUpgradeKeySets);
6376 writeKeySetMapping(dest, mKeySetMapping);
6377 dest.writeString(cpuAbiOverride);
6378 dest.writeInt(use32bitAbi ? 1 : 0);
6379 dest.writeByteArray(restrictUpdateHash);
Chad Brubaker49f24c62017-04-05 13:08:21 -07006380 dest.writeInt(visibleToInstantApps ? 1 : 0);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006381 }
6382
6383
6384 /**
6385 * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
6386 */
6387 private static void writeKeySetMapping(
6388 Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
6389 if (keySetMapping == null) {
6390 dest.writeInt(-1);
6391 return;
6392 }
6393
6394 final int N = keySetMapping.size();
6395 dest.writeInt(N);
6396
6397 for (int i = 0; i < N; i++) {
6398 dest.writeString(keySetMapping.keyAt(i));
6399 ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
6400 if (keys == null) {
6401 dest.writeInt(-1);
6402 continue;
6403 }
6404
6405 final int M = keys.size();
6406 dest.writeInt(M);
6407 for (int j = 0; j < M; j++) {
6408 dest.writeSerializable(keys.valueAt(j));
6409 }
6410 }
6411 }
6412
6413 /**
6414 * Reads a keyset mapping from the given parcel at the given data position. May return
6415 * {@code null} if the serialized mapping was {@code null}.
6416 */
6417 private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
6418 final int N = in.readInt();
6419 if (N == -1) {
6420 return null;
6421 }
6422
6423 ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
6424 for (int i = 0; i < N; ++i) {
6425 String key = in.readString();
6426 final int M = in.readInt();
6427 if (M == -1) {
6428 keySetMapping.put(key, null);
6429 continue;
6430 }
6431
6432 ArraySet<PublicKey> keys = new ArraySet<>(M);
6433 for (int j = 0; j < M; ++j) {
6434 PublicKey pk = (PublicKey) in.readSerializable();
6435 keys.add(pk);
6436 }
6437
6438 keySetMapping.put(key, keys);
6439 }
6440
6441 return keySetMapping;
6442 }
6443
6444 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
6445 public Package createFromParcel(Parcel in) {
6446 return new Package(in);
6447 }
6448
6449 public Package[] newArray(int size) {
6450 return new Package[size];
6451 }
6452 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006453 }
6454
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006455 public static abstract class Component<II extends IntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006456 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006457 public final String className;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006459 public Bundle metaData;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006460 public Package owner;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006461
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006462 ComponentName componentName;
6463 String componentShortName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006465 public Component(Package _owner) {
6466 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006467 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006468 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006469 }
6470
6471 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
6472 owner = args.owner;
6473 intents = new ArrayList<II>(0);
Todd Kennedybb8a42d2016-06-02 14:13:56 -07006474 if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
6475 true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
6476 args.roundIconRes, args.logoRes, args.bannerRes)) {
6477 className = outInfo.name;
6478 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006479 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006480 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006481 }
6482
6483 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
6484 this(args, (PackageItemInfo)outInfo);
6485 if (args.outError[0] != null) {
6486 return;
6487 }
6488
6489 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07006490 CharSequence pname;
6491 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07006492 pname = args.sa.getNonConfigurationString(args.processRes,
6493 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07006494 } else {
6495 // Some older apps have been seen to use a resource reference
6496 // here that on older builds was ignored (with a warning). We
6497 // need to continue to do this for them so they don't break.
6498 pname = args.sa.getNonResourceString(args.processRes);
6499 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006500 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07006501 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006502 args.flags, args.sepProcesses, args.outError);
6503 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006504
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08006505 if (args.descriptionRes != 0) {
6506 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
6507 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006508
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006509 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006510 }
6511
6512 public Component(Component<II> clone) {
6513 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006514 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006515 className = clone.className;
6516 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006517 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006518 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006519
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006520 public ComponentName getComponentName() {
6521 if (componentName != null) {
6522 return componentName;
6523 }
6524 if (className != null) {
6525 componentName = new ComponentName(owner.applicationInfo.packageName,
6526 className);
6527 }
6528 return componentName;
6529 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006530
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006531 protected Component(Parcel in) {
6532 className = in.readString();
6533 metaData = in.readBundle();
6534 intents = createIntentsList(in);
6535
6536 owner = null;
6537 }
6538
6539 protected void writeToParcel(Parcel dest, int flags) {
6540 dest.writeString(className);
6541 dest.writeBundle(metaData);
6542
6543 writeIntentsList(intents, dest, flags);
6544 }
6545
6546 /**
6547 * <p>
6548 * Implementation note: The serialized form for the intent list also contains the name
6549 * of the concrete class that's stored in the list, and assumes that every element of the
6550 * list is of the same type. This is very similar to the original parcelable mechanism.
6551 * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
6552 * and is public API. It also declares Parcelable related methods as final which means
6553 * we can't extend them. The approach of using composition instead of inheritance leads to
6554 * a large set of cascading changes in the PackageManagerService, which seem undesirable.
6555 *
6556 * <p>
6557 * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
6558 * to make sure their owner fields are consistent. See {@code fixupOwner}.
6559 */
6560 private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out,
6561 int flags) {
6562 if (list == null) {
6563 out.writeInt(-1);
6564 return;
6565 }
6566
6567 final int N = list.size();
6568 out.writeInt(N);
6569
6570 // Don't bother writing the component name if the list is empty.
6571 if (N > 0) {
6572 IntentInfo info = list.get(0);
6573 out.writeString(info.getClass().getName());
6574
6575 for (int i = 0; i < N;i++) {
6576 list.get(i).writeIntentInfoToParcel(out, flags);
6577 }
6578 }
6579 }
6580
6581 private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) {
6582 int N = in.readInt();
6583 if (N == -1) {
6584 return null;
6585 }
6586
6587 if (N == 0) {
6588 return new ArrayList<>(0);
6589 }
6590
6591 String componentName = in.readString();
6592 final ArrayList<T> intentsList;
6593 try {
6594 final Class<T> cls = (Class<T>) Class.forName(componentName);
6595 final Constructor<T> cons = cls.getConstructor(Parcel.class);
6596
6597 intentsList = new ArrayList<>(N);
6598 for (int i = 0; i < N; ++i) {
6599 intentsList.add(cons.newInstance(in));
6600 }
6601 } catch (ReflectiveOperationException ree) {
6602 throw new AssertionError("Unable to construct intent list for: " + componentName);
6603 }
6604
6605 return intentsList;
6606 }
6607
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006608 public void appendComponentShortName(StringBuilder sb) {
6609 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006610 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006611
6612 public void printComponentShortName(PrintWriter pw) {
6613 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
6614 }
6615
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006616 public void setPackageName(String packageName) {
6617 componentName = null;
6618 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006619 }
6620 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006621
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006622 public final static class Permission extends Component<IntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006623 public final PermissionInfo info;
6624 public boolean tree;
6625 public PermissionGroup group;
6626
6627 public Permission(Package _owner) {
6628 super(_owner);
6629 info = new PermissionInfo();
6630 }
6631
6632 public Permission(Package _owner, PermissionInfo _info) {
6633 super(_owner);
6634 info = _info;
6635 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006636
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006637 public void setPackageName(String packageName) {
6638 super.setPackageName(packageName);
6639 info.packageName = packageName;
6640 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006641
6642 public String toString() {
6643 return "Permission{"
6644 + Integer.toHexString(System.identityHashCode(this))
6645 + " " + info.name + "}";
6646 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006647
6648 @Override
6649 public int describeContents() {
6650 return 0;
6651 }
6652
6653 @Override
6654 public void writeToParcel(Parcel dest, int flags) {
6655 super.writeToParcel(dest, flags);
6656 dest.writeParcelable(info, flags);
6657 dest.writeInt(tree ? 1 : 0);
6658 dest.writeParcelable(group, flags);
6659 }
6660
6661 private Permission(Parcel in) {
6662 super(in);
6663 final ClassLoader boot = Object.class.getClassLoader();
6664 info = in.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006665 if (info.group != null) {
6666 info.group = info.group.intern();
6667 }
6668
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006669 tree = (in.readInt() == 1);
6670 group = in.readParcelable(boot);
6671 }
6672
6673 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
6674 public Permission createFromParcel(Parcel in) {
6675 return new Permission(in);
6676 }
6677
6678 public Permission[] newArray(int size) {
6679 return new Permission[size];
6680 }
6681 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006682 }
6683
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006684 public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006685 public final PermissionGroupInfo info;
6686
6687 public PermissionGroup(Package _owner) {
6688 super(_owner);
6689 info = new PermissionGroupInfo();
6690 }
6691
6692 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
6693 super(_owner);
6694 info = _info;
6695 }
6696
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006697 public void setPackageName(String packageName) {
6698 super.setPackageName(packageName);
6699 info.packageName = packageName;
6700 }
6701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006702 public String toString() {
6703 return "PermissionGroup{"
6704 + Integer.toHexString(System.identityHashCode(this))
6705 + " " + info.name + "}";
6706 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006707
6708 @Override
6709 public int describeContents() {
6710 return 0;
6711 }
6712
6713 @Override
6714 public void writeToParcel(Parcel dest, int flags) {
6715 super.writeToParcel(dest, flags);
6716 dest.writeParcelable(info, flags);
6717 }
6718
6719 private PermissionGroup(Parcel in) {
6720 super(in);
6721 info = in.readParcelable(Object.class.getClassLoader());
6722 }
6723
6724 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
6725 public PermissionGroup createFromParcel(Parcel in) {
6726 return new PermissionGroup(in);
6727 }
6728
6729 public PermissionGroup[] newArray(int size) {
6730 return new PermissionGroup[size];
6731 }
6732 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006733 }
6734
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006735 private static boolean copyNeeded(int flags, Package p,
6736 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07006737 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006738 // We always need to copy for other users, since we need
6739 // to fix up the uid.
6740 return true;
6741 }
6742 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
6743 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07006744 if (p.applicationInfo.enabled != enabled) {
6745 return true;
6746 }
6747 }
Rubin Xubf67c9c2016-04-20 17:09:38 +01006748 boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
6749 if (state.suspended != suspended) {
6750 return true;
6751 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07006752 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006753 return true;
6754 }
6755 if (state.stopped) {
6756 return true;
6757 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08006758 if (state.instantApp != p.applicationInfo.isInstantApp()) {
6759 return true;
6760 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006761 if ((flags & PackageManager.GET_META_DATA) != 0
6762 && (metaData != null || p.mAppMetaData != null)) {
6763 return true;
6764 }
6765 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
6766 && p.usesLibraryFiles != null) {
6767 return true;
6768 }
Svet Ganov67882122016-12-11 16:36:34 -08006769 if (p.staticSharedLibName != null) {
6770 return true;
6771 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006772 return false;
6773 }
6774
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006775 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
6776 PackageUserState state) {
6777 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07006778 }
6779
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08006780 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
6781 PackageUserState state) {
6782 // CompatibilityMode is global state.
6783 if (!sCompatibilityModeEnabled) {
6784 ai.disableCompatibilityMode();
6785 }
6786 if (state.installed) {
6787 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
6788 } else {
6789 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
6790 }
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00006791 if (state.suspended) {
6792 ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
6793 } else {
6794 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
6795 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08006796 if (state.instantApp) {
6797 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
6798 } else {
6799 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
6800 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07006801 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08006802 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07006803 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08006804 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07006805 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08006806 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
6807 ai.enabled = true;
6808 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
6809 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
6810 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
6811 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
6812 ai.enabled = false;
6813 }
6814 ai.enabledSetting = state.enabled;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07006815 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
6816 ai.category = state.categoryHint;
6817 }
Jeff Sharkey0078e1b2017-01-11 16:05:27 -07006818 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
6819 ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
6820 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08006821 ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
MÃ¥rten Kongstad2e0d0f32016-06-02 09:35:31 +02006822 ai.resourceDirs = state.resourceDirs;
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08006823 }
6824
Amith Yamasani13593602012-03-22 16:16:17 -07006825 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006826 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006827 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07006828 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006829 return null;
6830 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08006831 if (!copyNeeded(flags, p, state, null, userId)
6832 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
6833 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
6834 // In this case it is safe to directly modify the internal ApplicationInfo state:
6835 // - CompatibilityMode is global state, so will be the same for every call.
6836 // - We only come in to here if the app should reported as installed; this is the
6837 // default state, and we will do a copy otherwise.
6838 // - The enable state will always be reported the same for the application across
6839 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
6840 // be doing a copy.
6841 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006842 return p.applicationInfo;
6843 }
6844
6845 // Make shallow copy so we can store the metadata/libraries safely
6846 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Jeff Sharkey15447792015-11-05 16:18:51 -08006847 ai.initForUser(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006848 if ((flags & PackageManager.GET_META_DATA) != 0) {
6849 ai.metaData = p.mAppMetaData;
6850 }
6851 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
6852 ai.sharedLibraryFiles = p.usesLibraryFiles;
6853 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006854 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07006855 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08006856 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07006857 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08006858 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08006859 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006860 return ai;
6861 }
6862
Dianne Hackbornace27912014-09-18 18:38:30 -07006863 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
6864 PackageUserState state, int userId) {
6865 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07006866 if (!checkUseInstalledOrHidden(flags, state, ai)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07006867 return null;
6868 }
6869 // This is only used to return the ResolverActivity; we will just always
6870 // make a copy.
6871 ai = new ApplicationInfo(ai);
Jeff Sharkey15447792015-11-05 16:18:51 -08006872 ai.initForUser(userId);
Dianne Hackbornace27912014-09-18 18:38:30 -07006873 if (state.stopped) {
6874 ai.flags |= ApplicationInfo.FLAG_STOPPED;
6875 } else {
6876 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
6877 }
6878 updateApplicationInfo(ai, flags, state);
6879 return ai;
6880 }
6881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006882 public static final PermissionInfo generatePermissionInfo(
6883 Permission p, int flags) {
6884 if (p == null) return null;
6885 if ((flags&PackageManager.GET_META_DATA) == 0) {
6886 return p.info;
6887 }
6888 PermissionInfo pi = new PermissionInfo(p.info);
6889 pi.metaData = p.metaData;
6890 return pi;
6891 }
6892
6893 public static final PermissionGroupInfo generatePermissionGroupInfo(
6894 PermissionGroup pg, int flags) {
6895 if (pg == null) return null;
6896 if ((flags&PackageManager.GET_META_DATA) == 0) {
6897 return pg.info;
6898 }
6899 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
6900 pgi.metaData = pg.metaData;
6901 return pgi;
6902 }
6903
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006904 public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006905 public final ActivityInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006906
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006907 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
6908 super(args, _info);
6909 info = _info;
6910 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006911 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006912
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006913 public void setPackageName(String packageName) {
6914 super.setPackageName(packageName);
6915 info.packageName = packageName;
6916 }
6917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006918 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006919 StringBuilder sb = new StringBuilder(128);
6920 sb.append("Activity{");
6921 sb.append(Integer.toHexString(System.identityHashCode(this)));
6922 sb.append(' ');
6923 appendComponentShortName(sb);
6924 sb.append('}');
6925 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006926 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006927
6928 @Override
6929 public int describeContents() {
6930 return 0;
6931 }
6932
6933 @Override
6934 public void writeToParcel(Parcel dest, int flags) {
6935 super.writeToParcel(dest, flags);
6936 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
6937 }
6938
6939 private Activity(Parcel in) {
6940 super(in);
6941 info = in.readParcelable(Object.class.getClassLoader());
6942
6943 for (ActivityIntentInfo aii : intents) {
6944 aii.activity = this;
6945 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00006946
6947 if (info.permission != null) {
6948 info.permission = info.permission.intern();
6949 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006950 }
6951
6952 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
6953 public Activity createFromParcel(Parcel in) {
6954 return new Activity(in);
6955 }
6956
6957 public Activity[] newArray(int size) {
6958 return new Activity[size];
6959 }
6960 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006961 }
6962
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006963 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
6964 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006965 if (a == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07006966 if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006967 return null;
6968 }
6969 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006970 return a.info;
6971 }
6972 // Make shallow copies so we can store the metadata safely
6973 ActivityInfo ai = new ActivityInfo(a.info);
6974 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006975 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006976 return ai;
6977 }
6978
Dianne Hackbornace27912014-09-18 18:38:30 -07006979 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
6980 PackageUserState state, int userId) {
6981 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07006982 if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07006983 return null;
6984 }
6985 // This is only used to return the ResolverActivity; we will just always
6986 // make a copy.
6987 ai = new ActivityInfo(ai);
6988 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
6989 return ai;
6990 }
6991
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006992 public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006993 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006994
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006995 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
6996 super(args, _info);
6997 info = _info;
6998 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006999 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007000
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007001 public void setPackageName(String packageName) {
7002 super.setPackageName(packageName);
7003 info.packageName = packageName;
7004 }
7005
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007006 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007007 StringBuilder sb = new StringBuilder(128);
7008 sb.append("Service{");
7009 sb.append(Integer.toHexString(System.identityHashCode(this)));
7010 sb.append(' ');
7011 appendComponentShortName(sb);
7012 sb.append('}');
7013 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007015
7016 @Override
7017 public int describeContents() {
7018 return 0;
7019 }
7020
7021 @Override
7022 public void writeToParcel(Parcel dest, int flags) {
7023 super.writeToParcel(dest, flags);
7024 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7025 }
7026
7027 private Service(Parcel in) {
7028 super(in);
7029 info = in.readParcelable(Object.class.getClassLoader());
7030
7031 for (ServiceIntentInfo aii : intents) {
7032 aii.service = this;
7033 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007034
7035 if (info.permission != null) {
7036 info.permission = info.permission.intern();
7037 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007038 }
7039
7040 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
7041 public Service createFromParcel(Parcel in) {
7042 return new Service(in);
7043 }
7044
7045 public Service[] newArray(int size) {
7046 return new Service[size];
7047 }
7048 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007049 }
7050
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007051 public static final ServiceInfo generateServiceInfo(Service s, int flags,
7052 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007053 if (s == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007054 if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007055 return null;
7056 }
7057 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007058 return s.info;
7059 }
7060 // Make shallow copies so we can store the metadata safely
7061 ServiceInfo si = new ServiceInfo(s.info);
7062 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007063 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007064 return si;
7065 }
7066
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007067 public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007068 public final ProviderInfo info;
7069 public boolean syncable;
7070
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007071 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
7072 super(args, _info);
7073 info = _info;
7074 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007075 syncable = false;
7076 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007077
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007078 public Provider(Provider existingProvider) {
7079 super(existingProvider);
7080 this.info = existingProvider.info;
7081 this.syncable = existingProvider.syncable;
7082 }
7083
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007084 public void setPackageName(String packageName) {
7085 super.setPackageName(packageName);
7086 info.packageName = packageName;
7087 }
7088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007089 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007090 StringBuilder sb = new StringBuilder(128);
7091 sb.append("Provider{");
7092 sb.append(Integer.toHexString(System.identityHashCode(this)));
7093 sb.append(' ');
7094 appendComponentShortName(sb);
7095 sb.append('}');
7096 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007097 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007098
7099 @Override
7100 public int describeContents() {
7101 return 0;
7102 }
7103
7104 @Override
7105 public void writeToParcel(Parcel dest, int flags) {
7106 super.writeToParcel(dest, flags);
7107 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7108 dest.writeInt((syncable) ? 1 : 0);
7109 }
7110
7111 private Provider(Parcel in) {
7112 super(in);
7113 info = in.readParcelable(Object.class.getClassLoader());
7114 syncable = (in.readInt() == 1);
7115
7116 for (ProviderIntentInfo aii : intents) {
7117 aii.provider = this;
7118 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007119
7120 if (info.readPermission != null) {
7121 info.readPermission = info.readPermission.intern();
7122 }
7123
7124 if (info.writePermission != null) {
7125 info.writePermission = info.writePermission.intern();
7126 }
7127
7128 if (info.authority != null) {
7129 info.authority = info.authority.intern();
7130 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007131 }
7132
7133 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
7134 public Provider createFromParcel(Parcel in) {
7135 return new Provider(in);
7136 }
7137
7138 public Provider[] newArray(int size) {
7139 return new Provider[size];
7140 }
7141 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007142 }
7143
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007144 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
7145 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007146 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007147 if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007148 return null;
7149 }
7150 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007151 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007152 || p.info.uriPermissionPatterns == null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007153 return p.info;
7154 }
7155 // Make shallow copies so we can store the metadata safely
7156 ProviderInfo pi = new ProviderInfo(p.info);
7157 pi.metaData = p.metaData;
7158 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
7159 pi.uriPermissionPatterns = null;
7160 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007161 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007162 return pi;
7163 }
7164
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007165 public final static class Instrumentation extends Component<IntentInfo> implements
7166 Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007167 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007168
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007169 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
7170 super(args, _info);
7171 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007172 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007173
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007174 public void setPackageName(String packageName) {
7175 super.setPackageName(packageName);
7176 info.packageName = packageName;
7177 }
7178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007179 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007180 StringBuilder sb = new StringBuilder(128);
7181 sb.append("Instrumentation{");
7182 sb.append(Integer.toHexString(System.identityHashCode(this)));
7183 sb.append(' ');
7184 appendComponentShortName(sb);
7185 sb.append('}');
7186 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007187 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007188
7189 @Override
7190 public int describeContents() {
7191 return 0;
7192 }
7193
7194 @Override
7195 public void writeToParcel(Parcel dest, int flags) {
7196 super.writeToParcel(dest, flags);
7197 dest.writeParcelable(info, flags);
7198 }
7199
7200 private Instrumentation(Parcel in) {
7201 super(in);
7202 info = in.readParcelable(Object.class.getClassLoader());
Narayan Kamath07ac1442017-02-10 15:08:07 +00007203
7204 if (info.targetPackage != null) {
7205 info.targetPackage = info.targetPackage.intern();
7206 }
7207
7208 if (info.targetProcess != null) {
7209 info.targetProcess = info.targetProcess.intern();
7210 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007211 }
7212
7213 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
7214 public Instrumentation createFromParcel(Parcel in) {
7215 return new Instrumentation(in);
7216 }
7217
7218 public Instrumentation[] newArray(int size) {
7219 return new Instrumentation[size];
7220 }
7221 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007222 }
7223
7224 public static final InstrumentationInfo generateInstrumentationInfo(
7225 Instrumentation i, int flags) {
7226 if (i == null) return null;
7227 if ((flags&PackageManager.GET_META_DATA) == 0) {
7228 return i.info;
7229 }
7230 InstrumentationInfo ii = new InstrumentationInfo(i.info);
7231 ii.metaData = i.metaData;
7232 return ii;
7233 }
7234
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007235 public static abstract class IntentInfo extends IntentFilter {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007236 public boolean hasDefault;
7237 public int labelRes;
7238 public CharSequence nonLocalizedLabel;
7239 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07007240 public int logo;
Jose Limaf78e3122014-03-06 12:13:15 -08007241 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07007242 public int preferred;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007243
7244 protected IntentInfo() {
7245 }
7246
7247 protected IntentInfo(Parcel dest) {
7248 super(dest);
7249 hasDefault = (dest.readInt() == 1);
7250 labelRes = dest.readInt();
7251 nonLocalizedLabel = dest.readCharSequence();
7252 icon = dest.readInt();
7253 logo = dest.readInt();
7254 banner = dest.readInt();
7255 preferred = dest.readInt();
7256 }
7257
7258
7259 public void writeIntentInfoToParcel(Parcel dest, int flags) {
7260 super.writeToParcel(dest, flags);
7261 dest.writeInt(hasDefault ? 1 : 0);
7262 dest.writeInt(labelRes);
7263 dest.writeCharSequence(nonLocalizedLabel);
7264 dest.writeInt(icon);
7265 dest.writeInt(logo);
7266 dest.writeInt(banner);
7267 dest.writeInt(preferred);
7268 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007269 }
7270
7271 public final static class ActivityIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007272 public Activity activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007273
7274 public ActivityIntentInfo(Activity _activity) {
7275 activity = _activity;
7276 }
7277
7278 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007279 StringBuilder sb = new StringBuilder(128);
7280 sb.append("ActivityIntentInfo{");
7281 sb.append(Integer.toHexString(System.identityHashCode(this)));
7282 sb.append(' ');
7283 activity.appendComponentShortName(sb);
7284 sb.append('}');
7285 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007286 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007287
7288 public ActivityIntentInfo(Parcel in) {
7289 super(in);
7290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007291 }
7292
7293 public final static class ServiceIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007294 public Service service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007295
7296 public ServiceIntentInfo(Service _service) {
7297 service = _service;
7298 }
7299
7300 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007301 StringBuilder sb = new StringBuilder(128);
7302 sb.append("ServiceIntentInfo{");
7303 sb.append(Integer.toHexString(System.identityHashCode(this)));
7304 sb.append(' ');
7305 service.appendComponentShortName(sb);
7306 sb.append('}');
7307 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007309
7310 public ServiceIntentInfo(Parcel in) {
7311 super(in);
7312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007313 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007314
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007315 public static final class ProviderIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007316 public Provider provider;
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007317
7318 public ProviderIntentInfo(Provider provider) {
7319 this.provider = provider;
7320 }
7321
7322 public String toString() {
7323 StringBuilder sb = new StringBuilder(128);
7324 sb.append("ProviderIntentInfo{");
7325 sb.append(Integer.toHexString(System.identityHashCode(this)));
7326 sb.append(' ');
7327 provider.appendComponentShortName(sb);
7328 sb.append('}');
7329 return sb.toString();
7330 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007331
7332 public ProviderIntentInfo(Parcel in) {
7333 super(in);
7334 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007335 }
7336
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007337 /**
7338 * @hide
7339 */
7340 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
7341 sCompatibilityModeEnabled = compatibilityModeEnabled;
7342 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07007343
Jeff Sharkey275e0852014-06-17 18:18:49 -07007344 private static AtomicReference<byte[]> sBuffer = new AtomicReference<byte[]>();
7345
7346 public static long readFullyIgnoringContents(InputStream in) throws IOException {
7347 byte[] buffer = sBuffer.getAndSet(null);
7348 if (buffer == null) {
7349 buffer = new byte[4096];
7350 }
7351
7352 int n = 0;
7353 int count = 0;
7354 while ((n = in.read(buffer, 0, buffer.length)) != -1) {
7355 count += n;
7356 }
7357
7358 sBuffer.set(buffer);
7359 return count;
7360 }
7361
7362 public static void closeQuietly(StrictJarFile jarFile) {
7363 if (jarFile != null) {
7364 try {
7365 jarFile.close();
7366 } catch (Exception ignored) {
7367 }
7368 }
7369 }
7370
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07007371 public static class PackageParserException extends Exception {
7372 public final int error;
7373
7374 public PackageParserException(int error, String detailMessage) {
7375 super(detailMessage);
7376 this.error = error;
7377 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07007378
7379 public PackageParserException(int error, String detailMessage, Throwable throwable) {
7380 super(detailMessage, throwable);
7381 this.error = error;
7382 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07007383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007384}