blob: 383e60335b689d1c1e47a3daf61d52e4b89589e1 [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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019import android.content.ComponentName;
20import android.content.Intent;
21import android.content.IntentFilter;
22import android.content.res.AssetManager;
23import android.content.res.Configuration;
24import android.content.res.Resources;
25import android.content.res.TypedArray;
26import android.content.res.XmlResourceParser;
Amith Yamasani742a6712011-05-04 14:49:28 -070027import android.os.Binder;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070028import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.os.Bundle;
30import android.os.PatternMatcher;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070031import android.os.UserHandle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.util.AttributeSet;
Kenny Root05ca4c92011-09-15 10:36:25 -070033import android.util.Base64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070035import android.util.Log;
Kenny Rootd2d29252011-08-08 11:27:57 -070036import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.util.TypedValue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038
Kenny Rootd63f7db2010-09-27 08:07:48 -070039import java.io.BufferedInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import java.io.File;
41import java.io.IOException;
42import java.io.InputStream;
43import java.lang.ref.WeakReference;
Kenny Root05ca4c92011-09-15 10:36:25 -070044import java.security.KeyFactory;
45import java.security.NoSuchAlgorithmException;
46import java.security.PublicKey;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import java.security.cert.Certificate;
48import java.security.cert.CertificateEncodingException;
Geremy Condraf1bcca82013-01-07 22:35:24 -080049import java.security.cert.CertificateFactory;
50import java.security.cert.CertPath;
51import java.security.cert.X509Certificate;
Kenny Root05ca4c92011-09-15 10:36:25 -070052import java.security.spec.EncodedKeySpec;
53import java.security.spec.InvalidKeySpecException;
54import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import java.util.ArrayList;
56import java.util.Enumeration;
Geremy Condraf1bcca82013-01-07 22:35:24 -080057import java.util.HashMap;
Dianne Hackborne639da72012-02-21 15:11:13 -080058import java.util.HashSet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -070060import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -080061import java.util.Map;
62import java.util.Set;
Kenny Rootbcc954d2011-08-08 16:19:08 -070063import java.util.jar.Attributes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import java.util.jar.JarEntry;
65import java.util.jar.JarFile;
Kenny Rootd2d29252011-08-08 11:27:57 -070066import java.util.jar.Manifest;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067
Amith Yamasani742a6712011-05-04 14:49:28 -070068import com.android.internal.util.XmlUtils;
69
70import org.xmlpull.v1.XmlPullParser;
71import org.xmlpull.v1.XmlPullParserException;
72
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073/**
74 * Package archive parsing
75 *
76 * {@hide}
77 */
78public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -070079 private static final boolean DEBUG_JAR = false;
80 private static final boolean DEBUG_PARSER = false;
81 private static final boolean DEBUG_BACKUP = false;
82
Kenny Rootbcc954d2011-08-08 16:19:08 -070083 /** File name in an APK for the Android manifest. */
84 private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
85
Dianne Hackborna96cbb42009-05-13 15:06:13 -070086 /** @hide */
87 public static class NewPermissionInfo {
88 public final String name;
89 public final int sdkVersion;
90 public final int fileVersion;
91
92 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
93 this.name = name;
94 this.sdkVersion = sdkVersion;
95 this.fileVersion = fileVersion;
96 }
97 }
Dianne Hackborn79245122012-03-12 10:51:26 -070098
99 /** @hide */
100 public static class SplitPermissionInfo {
101 public final String rootPerm;
102 public final String[] newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700103 public final int targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700104
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700105 public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
Dianne Hackborn79245122012-03-12 10:51:26 -0700106 this.rootPerm = rootPerm;
107 this.newPerms = newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700108 this.targetSdk = targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700109 }
110 }
111
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700112 /**
113 * List of new permissions that have been added since 1.0.
114 * NOTE: These must be declared in SDK version order, with permissions
115 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700116 * If sdkVersion is 0, then this is not a permission that we want to
117 * automatically add to older apps, but we do want to allow it to be
118 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700119 * @hide
120 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700121 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
122 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700123 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700124 android.os.Build.VERSION_CODES.DONUT, 0),
125 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
126 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700127 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128
Dianne Hackborn79245122012-03-12 10:51:26 -0700129 /**
130 * List of permissions that have been split into more granular or dependent
131 * permissions.
132 * @hide
133 */
134 public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
135 new PackageParser.SplitPermissionInfo[] {
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700136 // READ_EXTERNAL_STORAGE is always required when an app requests
137 // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
138 // write access without read access. The hack here with the target
139 // target SDK version ensures that this grant is always done.
Dianne Hackborn79245122012-03-12 10:51:26 -0700140 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700141 new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700142 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700143 new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
144 new String[] { android.Manifest.permission.READ_CALL_LOG },
145 android.os.Build.VERSION_CODES.JELLY_BEAN),
146 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
147 new String[] { android.Manifest.permission.WRITE_CALL_LOG },
148 android.os.Build.VERSION_CODES.JELLY_BEAN)
Dianne Hackborn79245122012-03-12 10:51:26 -0700149 };
150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 private String mArchiveSourcePath;
152 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700153 private boolean mOnlyCoreApps;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700154 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
155 private static final String SDK_CODENAME = "REL".equals(Build.VERSION.CODENAME)
156 ? null : Build.VERSION.CODENAME;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157
158 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
159
160 private static final Object mSync = new Object();
161 private static WeakReference<byte[]> mReadBuffer;
162
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700163 private static boolean sCompatibilityModeEnabled = true;
164 private static final int PARSE_DEFAULT_INSTALL_LOCATION = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700165
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700166 static class ParsePackageItemArgs {
167 final Package owner;
168 final String[] outError;
169 final int nameRes;
170 final int labelRes;
171 final int iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700172 final int logoRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700173
174 String tag;
175 TypedArray sa;
176
177 ParsePackageItemArgs(Package _owner, String[] _outError,
Adam Powell81cd2e92010-04-21 16:35:18 -0700178 int _nameRes, int _labelRes, int _iconRes, int _logoRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700179 owner = _owner;
180 outError = _outError;
181 nameRes = _nameRes;
182 labelRes = _labelRes;
183 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700184 logoRes = _logoRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700185 }
186 }
187
188 static class ParseComponentArgs extends ParsePackageItemArgs {
189 final String[] sepProcesses;
190 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800191 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700192 final int enabledRes;
193 int flags;
194
195 ParseComponentArgs(Package _owner, String[] _outError,
Adam Powell81cd2e92010-04-21 16:35:18 -0700196 int _nameRes, int _labelRes, int _iconRes, int _logoRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800197 String[] _sepProcesses, int _processRes,
198 int _descriptionRes, int _enabledRes) {
Adam Powell81cd2e92010-04-21 16:35:18 -0700199 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _logoRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700200 sepProcesses = _sepProcesses;
201 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800202 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700203 enabledRes = _enabledRes;
204 }
205 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800206
207 /* Light weight package info.
208 * @hide
209 */
210 public static class PackageLite {
Kenny Root05ca4c92011-09-15 10:36:25 -0700211 public final String packageName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700212 public final int versionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700213 public final int installLocation;
214 public final VerifierInfo[] verifiers;
215
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700216 public PackageLite(String packageName, int versionCode,
217 int installLocation, List<VerifierInfo> verifiers) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800218 this.packageName = packageName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700219 this.versionCode = versionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800220 this.installLocation = installLocation;
Kenny Root05ca4c92011-09-15 10:36:25 -0700221 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800222 }
223 }
224
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700225 private ParsePackageItemArgs mParseInstrumentationArgs;
226 private ParseComponentArgs mParseActivityArgs;
227 private ParseComponentArgs mParseActivityAliasArgs;
228 private ParseComponentArgs mParseServiceArgs;
229 private ParseComponentArgs mParseProviderArgs;
230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 /** If set to true, we will only allow package files that exactly match
232 * the DTD. Otherwise, we try to get as much from the package as we
233 * can without failing. This should normally be set to false, to
234 * support extensions to the DTD in future versions. */
235 private static final boolean RIGID_PARSER = false;
236
237 private static final String TAG = "PackageParser";
238
239 public PackageParser(String archiveSourcePath) {
240 mArchiveSourcePath = archiveSourcePath;
241 }
242
243 public void setSeparateProcesses(String[] procs) {
244 mSeparateProcesses = procs;
245 }
246
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700247 public void setOnlyCoreApps(boolean onlyCoreApps) {
248 mOnlyCoreApps = onlyCoreApps;
249 }
250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 private static final boolean isPackageFilename(String name) {
252 return name.endsWith(".apk");
253 }
254
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700255 /*
Amith Yamasani13593602012-03-22 16:16:17 -0700256 public static PackageInfo generatePackageInfo(PackageParser.Package p,
257 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
258 HashSet<String> grantedPermissions) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700259 PackageUserState state = new PackageUserState();
Amith Yamasani13593602012-03-22 16:16:17 -0700260 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700261 grantedPermissions, state, UserHandle.getCallingUserId());
Amith Yamasani13593602012-03-22 16:16:17 -0700262 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700263 */
Amith Yamasani13593602012-03-22 16:16:17 -0700264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 /**
266 * Generate and return the {@link PackageInfo} for a parsed package.
267 *
268 * @param p the parsed package.
269 * @param flags indicating which optional information is included.
270 */
271 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800272 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700273 HashSet<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274
Amith Yamasani483f3b02012-03-13 16:08:00 -0700275 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700276 grantedPermissions, state, UserHandle.getCallingUserId());
277 }
278
279 private static boolean checkUseInstalled(int flags, PackageUserState state) {
280 return state.installed || ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0);
Amith Yamasani483f3b02012-03-13 16:08:00 -0700281 }
282
Amith Yamasani13593602012-03-22 16:16:17 -0700283 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700284 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700285 HashSet<String> grantedPermissions, PackageUserState state, int userId) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700286
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700287 if (!checkUseInstalled(flags, state)) {
288 return null;
289 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 PackageInfo pi = new PackageInfo();
291 pi.packageName = p.packageName;
292 pi.versionCode = p.mVersionCode;
293 pi.versionName = p.mVersionName;
294 pi.sharedUserId = p.mSharedUserId;
295 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700296 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800297 pi.installLocation = p.installLocation;
Dianne Hackborn78d68832010-10-07 01:12:46 -0700298 pi.firstInstallTime = firstInstallTime;
299 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 if ((flags&PackageManager.GET_GIDS) != 0) {
301 pi.gids = gids;
302 }
303 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
304 int N = p.configPreferences.size();
305 if (N > 0) {
306 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700307 p.configPreferences.toArray(pi.configPreferences);
308 }
309 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
310 if (N > 0) {
311 pi.reqFeatures = new FeatureInfo[N];
312 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 }
314 }
315 if ((flags&PackageManager.GET_ACTIVITIES) != 0) {
316 int N = p.activities.size();
317 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700318 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
319 pi.activities = new ActivityInfo[N];
320 } else {
321 int num = 0;
322 for (int i=0; i<N; i++) {
323 if (p.activities.get(i).info.enabled) num++;
324 }
325 pi.activities = new ActivityInfo[num];
326 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700327 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 final Activity activity = p.activities.get(i);
329 if (activity.info.enabled
330 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700331 pi.activities[j++] = generateActivityInfo(p.activities.get(i), flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700332 state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 }
334 }
335 }
336 }
337 if ((flags&PackageManager.GET_RECEIVERS) != 0) {
338 int N = p.receivers.size();
339 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700340 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
341 pi.receivers = new ActivityInfo[N];
342 } else {
343 int num = 0;
344 for (int i=0; i<N; i++) {
345 if (p.receivers.get(i).info.enabled) num++;
346 }
347 pi.receivers = new ActivityInfo[num];
348 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700349 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 final Activity activity = p.receivers.get(i);
351 if (activity.info.enabled
352 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Amith Yamasani13593602012-03-22 16:16:17 -0700353 pi.receivers[j++] = generateActivityInfo(p.receivers.get(i), flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700354 state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 }
356 }
357 }
358 }
359 if ((flags&PackageManager.GET_SERVICES) != 0) {
360 int N = p.services.size();
361 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700362 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
363 pi.services = new ServiceInfo[N];
364 } else {
365 int num = 0;
366 for (int i=0; i<N; i++) {
367 if (p.services.get(i).info.enabled) num++;
368 }
369 pi.services = new ServiceInfo[num];
370 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700371 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 final Service service = p.services.get(i);
373 if (service.info.enabled
374 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700375 pi.services[j++] = generateServiceInfo(p.services.get(i), flags,
376 state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 }
378 }
379 }
380 }
381 if ((flags&PackageManager.GET_PROVIDERS) != 0) {
382 int N = p.providers.size();
383 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700384 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
385 pi.providers = new ProviderInfo[N];
386 } else {
387 int num = 0;
388 for (int i=0; i<N; i++) {
389 if (p.providers.get(i).info.enabled) num++;
390 }
391 pi.providers = new ProviderInfo[num];
392 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700393 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 final Provider provider = p.providers.get(i);
395 if (provider.info.enabled
396 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700397 pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags,
398 state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800399 }
400 }
401 }
402 }
403 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
404 int N = p.instrumentation.size();
405 if (N > 0) {
406 pi.instrumentation = new InstrumentationInfo[N];
407 for (int i=0; i<N; i++) {
408 pi.instrumentation[i] = generateInstrumentationInfo(
409 p.instrumentation.get(i), flags);
410 }
411 }
412 }
413 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
414 int N = p.permissions.size();
415 if (N > 0) {
416 pi.permissions = new PermissionInfo[N];
417 for (int i=0; i<N; i++) {
418 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
419 }
420 }
421 N = p.requestedPermissions.size();
422 if (N > 0) {
423 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800424 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425 for (int i=0; i<N; i++) {
Dianne Hackborne639da72012-02-21 15:11:13 -0800426 final String perm = p.requestedPermissions.get(i);
427 pi.requestedPermissions[i] = perm;
428 if (p.requestedPermissionsRequired.get(i)) {
429 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
430 }
431 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
432 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
433 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 }
435 }
436 }
437 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700438 int N = (p.mSignatures != null) ? p.mSignatures.length : 0;
439 if (N > 0) {
440 pi.signatures = new Signature[N];
441 System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 }
443 }
444 return pi;
445 }
446
447 private Certificate[] loadCertificates(JarFile jarFile, JarEntry je,
448 byte[] readBuffer) {
449 try {
450 // We must read the stream for the JarEntry to retrieve
451 // its certificates.
Kenny Rootd63f7db2010-09-27 08:07:48 -0700452 InputStream is = new BufferedInputStream(jarFile.getInputStream(je));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 while (is.read(readBuffer, 0, readBuffer.length) != -1) {
454 // not using
455 }
456 is.close();
457 return je != null ? je.getCertificates() : null;
458 } catch (IOException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700459 Slog.w(TAG, "Exception reading " + je.getName() + " in "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 + jarFile.getName(), e);
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -0700461 } catch (RuntimeException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700462 Slog.w(TAG, "Exception reading " + je.getName() + " in "
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -0700463 + jarFile.getName(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 }
465 return null;
466 }
467
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800468 public final static int PARSE_IS_SYSTEM = 1<<0;
469 public final static int PARSE_CHATTY = 1<<1;
470 public final static int PARSE_MUST_BE_APK = 1<<2;
471 public final static int PARSE_IGNORE_PROCESSES = 1<<3;
472 public final static int PARSE_FORWARD_LOCK = 1<<4;
473 public final static int PARSE_ON_SDCARD = 1<<5;
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700474 public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475
476 public int getParseError() {
477 return mParseError;
478 }
479
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800480 public Package parsePackage(File sourceFile, String destCodePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 DisplayMetrics metrics, int flags) {
482 mParseError = PackageManager.INSTALL_SUCCEEDED;
483
484 mArchiveSourcePath = sourceFile.getPath();
485 if (!sourceFile.isFile()) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700486 Slog.w(TAG, "Skipping dir: " + mArchiveSourcePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487 mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
488 return null;
489 }
490 if (!isPackageFilename(sourceFile.getName())
491 && (flags&PARSE_MUST_BE_APK) != 0) {
492 if ((flags&PARSE_IS_SYSTEM) == 0) {
493 // We expect to have non-.apk files in the system dir,
494 // so don't warn about them.
Kenny Rootd2d29252011-08-08 11:27:57 -0700495 Slog.w(TAG, "Skipping non-package file: " + mArchiveSourcePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496 }
497 mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
498 return null;
499 }
500
Kenny Rootd2d29252011-08-08 11:27:57 -0700501 if (DEBUG_JAR)
502 Slog.d(TAG, "Scanning package: " + mArchiveSourcePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503
504 XmlResourceParser parser = null;
505 AssetManager assmgr = null;
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800506 Resources res = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 boolean assetError = true;
508 try {
509 assmgr = new AssetManager();
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700510 int cookie = assmgr.addAssetPath(mArchiveSourcePath);
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800511 if (cookie != 0) {
512 res = new Resources(assmgr, metrics, null);
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700513 assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800514 Build.VERSION.RESOURCES_SDK_INT);
Kenny Rootbcc954d2011-08-08 16:19:08 -0700515 parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800516 assetError = false;
517 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -0700518 Slog.w(TAG, "Failed adding asset path:"+mArchiveSourcePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 }
520 } catch (Exception e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700521 Slog.w(TAG, "Unable to read AndroidManifest.xml of "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522 + mArchiveSourcePath, e);
523 }
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800524 if (assetError) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 if (assmgr != null) assmgr.close();
526 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
527 return null;
528 }
529 String[] errorText = new String[1];
530 Package pkg = null;
531 Exception errorException = null;
532 try {
533 // XXXX todo: need to figure out correct configuration.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 pkg = parsePackage(res, parser, flags, errorText);
535 } catch (Exception e) {
536 errorException = e;
537 mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
538 }
539
540
541 if (pkg == null) {
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700542 // If we are only parsing core apps, then a null with INSTALL_SUCCEEDED
543 // just means to skip this app so don't make a fuss about it.
544 if (!mOnlyCoreApps || mParseError != PackageManager.INSTALL_SUCCEEDED) {
545 if (errorException != null) {
546 Slog.w(TAG, mArchiveSourcePath, errorException);
547 } else {
548 Slog.w(TAG, mArchiveSourcePath + " (at "
549 + parser.getPositionDescription()
550 + "): " + errorText[0]);
551 }
552 if (mParseError == PackageManager.INSTALL_SUCCEEDED) {
553 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
554 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 }
556 parser.close();
557 assmgr.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 return null;
559 }
560
561 parser.close();
562 assmgr.close();
563
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800564 // Set code and resource paths
565 pkg.mPath = destCodePath;
566 pkg.mScanPath = mArchiveSourcePath;
567 //pkg.applicationInfo.sourceDir = destCodePath;
568 //pkg.applicationInfo.publicSourceDir = destRes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800569 pkg.mSignatures = null;
570
571 return pkg;
572 }
573
574 public boolean collectCertificates(Package pkg, int flags) {
575 pkg.mSignatures = null;
576
577 WeakReference<byte[]> readBufferRef;
578 byte[] readBuffer = null;
579 synchronized (mSync) {
580 readBufferRef = mReadBuffer;
581 if (readBufferRef != null) {
582 mReadBuffer = null;
583 readBuffer = readBufferRef.get();
584 }
585 if (readBuffer == null) {
586 readBuffer = new byte[8192];
587 readBufferRef = new WeakReference<byte[]>(readBuffer);
588 }
589 }
590
591 try {
592 JarFile jarFile = new JarFile(mArchiveSourcePath);
593
594 Certificate[] certs = null;
595
596 if ((flags&PARSE_IS_SYSTEM) != 0) {
597 // If this package comes from the system image, then we
598 // can trust it... we'll just use the AndroidManifest.xml
599 // to retrieve its signatures, not validating all of the
600 // files.
Kenny Rootbcc954d2011-08-08 16:19:08 -0700601 JarEntry jarEntry = jarFile.getJarEntry(ANDROID_MANIFEST_FILENAME);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 certs = loadCertificates(jarFile, jarEntry, readBuffer);
603 if (certs == null) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700604 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605 + " has no certificates at entry "
606 + jarEntry.getName() + "; ignoring!");
607 jarFile.close();
608 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
609 return false;
610 }
Kenny Rootd2d29252011-08-08 11:27:57 -0700611 if (DEBUG_JAR) {
612 Slog.i(TAG, "File " + mArchiveSourcePath + ": entry=" + jarEntry
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 + " certs=" + (certs != null ? certs.length : 0));
614 if (certs != null) {
615 final int N = certs.length;
616 for (int i=0; i<N; i++) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700617 Slog.i(TAG, " Public key: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 + certs[i].getPublicKey().getEncoded()
619 + " " + certs[i].getPublicKey());
620 }
621 }
622 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -0700624 Enumeration<JarEntry> entries = jarFile.entries();
Kenny Rootbcc954d2011-08-08 16:19:08 -0700625 final Manifest manifest = jarFile.getManifest();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 while (entries.hasMoreElements()) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700627 final JarEntry je = entries.nextElement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628 if (je.isDirectory()) continue;
Kenny Rootd2d29252011-08-08 11:27:57 -0700629
Kenny Rootbcc954d2011-08-08 16:19:08 -0700630 final String name = je.getName();
631
632 if (name.startsWith("META-INF/"))
633 continue;
634
635 if (ANDROID_MANIFEST_FILENAME.equals(name)) {
636 final Attributes attributes = manifest.getAttributes(name);
637 pkg.manifestDigest = ManifestDigest.fromAttributes(attributes);
638 }
639
640 final Certificate[] localCerts = loadCertificates(jarFile, je, readBuffer);
Kenny Rootd2d29252011-08-08 11:27:57 -0700641 if (DEBUG_JAR) {
642 Slog.i(TAG, "File " + mArchiveSourcePath + " entry " + je.getName()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 + ": certs=" + certs + " ("
644 + (certs != null ? certs.length : 0) + ")");
645 }
Kenny Rootbcc954d2011-08-08 16:19:08 -0700646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647 if (localCerts == null) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700648 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 + " has no certificates at entry "
650 + je.getName() + "; ignoring!");
651 jarFile.close();
652 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
653 return false;
654 } else if (certs == null) {
655 certs = localCerts;
656 } else {
657 // Ensure all certificates match.
658 for (int i=0; i<certs.length; i++) {
659 boolean found = false;
660 for (int j=0; j<localCerts.length; j++) {
661 if (certs[i] != null &&
662 certs[i].equals(localCerts[j])) {
663 found = true;
664 break;
665 }
666 }
667 if (!found || certs.length != localCerts.length) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700668 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669 + " has mismatched certificates at entry "
670 + je.getName() + "; ignoring!");
671 jarFile.close();
672 mParseError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
673 return false;
674 }
675 }
676 }
677 }
678 }
679 jarFile.close();
680
681 synchronized (mSync) {
682 mReadBuffer = readBufferRef;
683 }
684
685 if (certs != null && certs.length > 0) {
686 final int N = certs.length;
687 pkg.mSignatures = new Signature[certs.length];
688 for (int i=0; i<N; i++) {
689 pkg.mSignatures[i] = new Signature(
690 certs[i].getEncoded());
691 }
692 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -0700693 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 + " has no certificates; ignoring!");
695 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
696 return false;
697 }
Geremy Condraf1bcca82013-01-07 22:35:24 -0800698
699 // Add the signing KeySet to the system
700 pkg.mSigningKeys = new HashSet<PublicKey>();
701 for (int i=0; i < certs.length; i++) {
702 pkg.mSigningKeys.add(certs[i].getPublicKey());
703 }
704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 } catch (CertificateEncodingException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700706 Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
708 return false;
709 } catch (IOException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700710 Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
712 return false;
713 } catch (RuntimeException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700714 Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715 mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
716 return false;
717 }
718
719 return true;
720 }
721
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800722 /*
723 * Utility method that retrieves just the package name and install
724 * location from the apk location at the given file path.
725 * @param packageFilePath file location of the apk
726 * @param flags Special parse flags
Kenny Root930d3af2010-07-30 16:52:29 -0700727 * @return PackageLite object with package information or null on failure.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800728 */
729 public static PackageLite parsePackageLite(String packageFilePath, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800730 AssetManager assmgr = null;
Kenny Root05ca4c92011-09-15 10:36:25 -0700731 final XmlResourceParser parser;
732 final Resources res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 try {
734 assmgr = new AssetManager();
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700735 assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800736 Build.VERSION.RESOURCES_SDK_INT);
Kenny Root1ebd74a2011-08-03 15:09:44 -0700737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 int cookie = assmgr.addAssetPath(packageFilePath);
Kenny Root1ebd74a2011-08-03 15:09:44 -0700739 if (cookie == 0) {
740 return null;
741 }
742
Kenny Root05ca4c92011-09-15 10:36:25 -0700743 final DisplayMetrics metrics = new DisplayMetrics();
744 metrics.setToDefaults();
745 res = new Resources(assmgr, metrics, null);
Kenny Rootbcc954d2011-08-08 16:19:08 -0700746 parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 } catch (Exception e) {
748 if (assmgr != null) assmgr.close();
Kenny Rootd2d29252011-08-08 11:27:57 -0700749 Slog.w(TAG, "Unable to read AndroidManifest.xml of "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 + packageFilePath, e);
751 return null;
752 }
Kenny Root05ca4c92011-09-15 10:36:25 -0700753
754 final AttributeSet attrs = parser;
755 final String errors[] = new String[1];
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800756 PackageLite packageLite = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800757 try {
Kenny Root05ca4c92011-09-15 10:36:25 -0700758 packageLite = parsePackageLite(res, parser, attrs, flags, errors);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 } catch (IOException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700760 Slog.w(TAG, packageFilePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 } catch (XmlPullParserException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700762 Slog.w(TAG, packageFilePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 } finally {
764 if (parser != null) parser.close();
765 if (assmgr != null) assmgr.close();
766 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800767 if (packageLite == null) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700768 Slog.e(TAG, "parsePackageLite error: " + errors[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 return null;
770 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800771 return packageLite;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 }
773
774 private static String validateName(String name, boolean requiresSeparator) {
775 final int N = name.length();
776 boolean hasSep = false;
777 boolean front = true;
778 for (int i=0; i<N; i++) {
779 final char c = name.charAt(i);
780 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
781 front = false;
782 continue;
783 }
784 if (!front) {
785 if ((c >= '0' && c <= '9') || c == '_') {
786 continue;
787 }
788 }
789 if (c == '.') {
790 hasSep = true;
791 front = true;
792 continue;
793 }
794 return "bad character '" + c + "'";
795 }
796 return hasSep || !requiresSeparator
797 ? null : "must have at least one '.' separator";
798 }
799
800 private static String parsePackageName(XmlPullParser parser,
801 AttributeSet attrs, int flags, String[] outError)
802 throws IOException, XmlPullParserException {
803
804 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -0700805 while ((type = parser.next()) != XmlPullParser.START_TAG
806 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 ;
808 }
809
Kenny Rootd2d29252011-08-08 11:27:57 -0700810 if (type != XmlPullParser.START_TAG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811 outError[0] = "No start tag found";
812 return null;
813 }
Kenny Rootd2d29252011-08-08 11:27:57 -0700814 if (DEBUG_PARSER)
815 Slog.v(TAG, "Root element name: '" + parser.getName() + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 if (!parser.getName().equals("manifest")) {
817 outError[0] = "No <manifest> tag";
818 return null;
819 }
820 String pkgName = attrs.getAttributeValue(null, "package");
821 if (pkgName == null || pkgName.length() == 0) {
822 outError[0] = "<manifest> does not specify package";
823 return null;
824 }
825 String nameError = validateName(pkgName, true);
826 if (nameError != null && !"android".equals(pkgName)) {
827 outError[0] = "<manifest> specifies bad package name \""
828 + pkgName + "\": " + nameError;
829 return null;
830 }
831
832 return pkgName.intern();
833 }
834
Kenny Root05ca4c92011-09-15 10:36:25 -0700835 private static PackageLite parsePackageLite(Resources res, XmlPullParser parser,
836 AttributeSet attrs, int flags, String[] outError) throws IOException,
837 XmlPullParserException {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800838
839 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -0700840 while ((type = parser.next()) != XmlPullParser.START_TAG
841 && type != XmlPullParser.END_DOCUMENT) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800842 ;
843 }
844
Kenny Rootd2d29252011-08-08 11:27:57 -0700845 if (type != XmlPullParser.START_TAG) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800846 outError[0] = "No start tag found";
847 return null;
848 }
Kenny Rootd2d29252011-08-08 11:27:57 -0700849 if (DEBUG_PARSER)
850 Slog.v(TAG, "Root element name: '" + parser.getName() + "'");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800851 if (!parser.getName().equals("manifest")) {
852 outError[0] = "No <manifest> tag";
853 return null;
854 }
855 String pkgName = attrs.getAttributeValue(null, "package");
856 if (pkgName == null || pkgName.length() == 0) {
857 outError[0] = "<manifest> does not specify package";
858 return null;
859 }
860 String nameError = validateName(pkgName, true);
861 if (nameError != null && !"android".equals(pkgName)) {
862 outError[0] = "<manifest> specifies bad package name \""
863 + pkgName + "\": " + nameError;
864 return null;
865 }
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700866 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700867 int versionCode = 0;
868 int numFound = 0;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800869 for (int i = 0; i < attrs.getAttributeCount(); i++) {
870 String attr = attrs.getAttributeName(i);
871 if (attr.equals("installLocation")) {
872 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700873 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700874 numFound++;
875 } else if (attr.equals("versionCode")) {
876 versionCode = attrs.getAttributeIntValue(i, 0);
877 numFound++;
878 }
879 if (numFound >= 2) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800880 break;
881 }
882 }
Kenny Root05ca4c92011-09-15 10:36:25 -0700883
884 // Only search the tree when the tag is directly below <manifest>
885 final int searchDepth = parser.getDepth() + 1;
886
887 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
888 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
889 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
890 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
891 continue;
892 }
893
894 if (parser.getDepth() == searchDepth && "package-verifier".equals(parser.getName())) {
895 final VerifierInfo verifier = parseVerifier(res, parser, attrs, flags, outError);
896 if (verifier != null) {
897 verifiers.add(verifier);
898 }
899 }
900 }
901
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700902 return new PackageLite(pkgName.intern(), versionCode, installLocation, verifiers);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800903 }
904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 /**
906 * Temporary.
907 */
908 static public Signature stringToSignature(String str) {
909 final int N = str.length();
910 byte[] sig = new byte[N];
911 for (int i=0; i<N; i++) {
912 sig[i] = (byte)str.charAt(i);
913 }
914 return new Signature(sig);
915 }
916
917 private Package parsePackage(
918 Resources res, XmlResourceParser parser, int flags, String[] outError)
919 throws XmlPullParserException, IOException {
920 AttributeSet attrs = parser;
921
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700922 mParseInstrumentationArgs = null;
923 mParseActivityArgs = null;
924 mParseServiceArgs = null;
925 mParseProviderArgs = null;
926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927 String pkgName = parsePackageName(parser, attrs, flags, outError);
928 if (pkgName == null) {
929 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
930 return null;
931 }
932 int type;
933
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700934 if (mOnlyCoreApps) {
935 boolean core = attrs.getAttributeBooleanValue(null, "coreApp", false);
936 if (!core) {
937 mParseError = PackageManager.INSTALL_SUCCEEDED;
938 return null;
939 }
940 }
941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 final Package pkg = new Package(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943 boolean foundApp = false;
Dianne Hackborn851a5412009-05-08 12:06:44 -0700944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 TypedArray sa = res.obtainAttributes(attrs,
946 com.android.internal.R.styleable.AndroidManifest);
947 pkg.mVersionCode = sa.getInteger(
948 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800949 pkg.mVersionName = sa.getNonConfigurationString(
950 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800951 if (pkg.mVersionName != null) {
952 pkg.mVersionName = pkg.mVersionName.intern();
953 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800954 String str = sa.getNonConfigurationString(
955 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
956 if (str != null && str.length() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 String nameError = validateName(str, true);
958 if (nameError != null && !"android".equals(pkgName)) {
959 outError[0] = "<manifest> specifies bad sharedUserId name \""
960 + str + "\": " + nameError;
961 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
962 return null;
963 }
964 pkg.mSharedUserId = str.intern();
965 pkg.mSharedUserLabel = sa.getResourceId(
966 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
967 }
968 sa.recycle();
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -0800969
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800970 pkg.installLocation = sa.getInteger(
971 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700972 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -0700973 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -0700974
975 /* Set the global "forward lock" flag */
976 if ((flags & PARSE_FORWARD_LOCK) != 0) {
977 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
978 }
979
980 /* Set the global "on SD card" flag */
981 if ((flags & PARSE_ON_SDCARD) != 0) {
982 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
983 }
984
Dianne Hackborn723738c2009-06-25 19:48:04 -0700985 // Resource boolean are -1, so 1 means we don't know the value.
986 int supportsSmallScreens = 1;
987 int supportsNormalScreens = 1;
988 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -0700989 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700990 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700991 int anyDensity = 1;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -0700994 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
995 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
996 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 continue;
998 }
999
1000 String tagName = parser.getName();
1001 if (tagName.equals("application")) {
1002 if (foundApp) {
1003 if (RIGID_PARSER) {
1004 outError[0] = "<manifest> has more than one <application>";
1005 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1006 return null;
1007 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07001008 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 XmlUtils.skipCurrentTag(parser);
1010 continue;
1011 }
1012 }
1013
1014 foundApp = true;
1015 if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
1016 return null;
1017 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08001018 } else if (tagName.equals("keys")) {
1019 if (!parseKeys(pkg, res, parser, attrs, outError)) {
1020 return null;
1021 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 } else if (tagName.equals("permission-group")) {
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07001023 if (parsePermissionGroup(pkg, flags, res, parser, attrs, outError) == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 return null;
1025 }
1026 } else if (tagName.equals("permission")) {
1027 if (parsePermission(pkg, res, parser, attrs, outError) == null) {
1028 return null;
1029 }
1030 } else if (tagName.equals("permission-tree")) {
1031 if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
1032 return null;
1033 }
1034 } else if (tagName.equals("uses-permission")) {
1035 sa = res.obtainAttributes(attrs,
1036 com.android.internal.R.styleable.AndroidManifestUsesPermission);
1037
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001038 // Note: don't allow this value to be a reference to a resource
1039 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 String name = sa.getNonResourceString(
1041 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Dianne Hackborne8241202012-04-06 13:39:09 -07001042 /* Not supporting optional permissions yet.
Dianne Hackborne639da72012-02-21 15:11:13 -08001043 boolean required = sa.getBoolean(
1044 com.android.internal.R.styleable.AndroidManifestUsesPermission_required, true);
Dianne Hackborne8241202012-04-06 13:39:09 -07001045 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001046
1047 sa.recycle();
1048
1049 if (name != null && !pkg.requestedPermissions.contains(name)) {
Dianne Hackborn854060a2009-07-09 18:14:31 -07001050 pkg.requestedPermissions.add(name.intern());
Dianne Hackborne8241202012-04-06 13:39:09 -07001051 pkg.requestedPermissionsRequired.add(Boolean.TRUE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001052 }
1053
1054 XmlUtils.skipCurrentTag(parser);
1055
1056 } else if (tagName.equals("uses-configuration")) {
1057 ConfigurationInfo cPref = new ConfigurationInfo();
1058 sa = res.obtainAttributes(attrs,
1059 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
1060 cPref.reqTouchScreen = sa.getInt(
1061 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
1062 Configuration.TOUCHSCREEN_UNDEFINED);
1063 cPref.reqKeyboardType = sa.getInt(
1064 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
1065 Configuration.KEYBOARD_UNDEFINED);
1066 if (sa.getBoolean(
1067 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
1068 false)) {
1069 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
1070 }
1071 cPref.reqNavigation = sa.getInt(
1072 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
1073 Configuration.NAVIGATION_UNDEFINED);
1074 if (sa.getBoolean(
1075 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
1076 false)) {
1077 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
1078 }
1079 sa.recycle();
1080 pkg.configPreferences.add(cPref);
1081
1082 XmlUtils.skipCurrentTag(parser);
1083
Suchi Amalapurapud299b812009-06-05 10:26:19 -07001084 } else if (tagName.equals("uses-feature")) {
Dianne Hackborn49237342009-08-27 20:08:01 -07001085 FeatureInfo fi = new FeatureInfo();
Suchi Amalapurapud299b812009-06-05 10:26:19 -07001086 sa = res.obtainAttributes(attrs,
1087 com.android.internal.R.styleable.AndroidManifestUsesFeature);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001088 // Note: don't allow this value to be a reference to a resource
1089 // that may change.
Dianne Hackborn49237342009-08-27 20:08:01 -07001090 fi.name = sa.getNonResourceString(
1091 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
1092 if (fi.name == null) {
1093 fi.reqGlEsVersion = sa.getInt(
1094 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
1095 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1096 }
1097 if (sa.getBoolean(
1098 com.android.internal.R.styleable.AndroidManifestUsesFeature_required,
1099 true)) {
1100 fi.flags |= FeatureInfo.FLAG_REQUIRED;
1101 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07001102 sa.recycle();
Dianne Hackborn49237342009-08-27 20:08:01 -07001103 if (pkg.reqFeatures == null) {
1104 pkg.reqFeatures = new ArrayList<FeatureInfo>();
1105 }
1106 pkg.reqFeatures.add(fi);
1107
1108 if (fi.name == null) {
1109 ConfigurationInfo cPref = new ConfigurationInfo();
1110 cPref.reqGlEsVersion = fi.reqGlEsVersion;
1111 pkg.configPreferences.add(cPref);
1112 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07001113
1114 XmlUtils.skipCurrentTag(parser);
1115
Dianne Hackborn851a5412009-05-08 12:06:44 -07001116 } else if (tagName.equals("uses-sdk")) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001117 if (SDK_VERSION > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 sa = res.obtainAttributes(attrs,
1119 com.android.internal.R.styleable.AndroidManifestUsesSdk);
1120
Dianne Hackborn851a5412009-05-08 12:06:44 -07001121 int minVers = 0;
1122 String minCode = null;
1123 int targetVers = 0;
1124 String targetCode = null;
1125
1126 TypedValue val = sa.peekValue(
1127 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
1128 if (val != null) {
1129 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1130 targetCode = minCode = val.string.toString();
1131 } else {
1132 // If it's not a string, it's an integer.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001133 targetVers = minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001134 }
1135 }
1136
1137 val = sa.peekValue(
1138 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
1139 if (val != null) {
1140 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1141 targetCode = minCode = val.string.toString();
1142 } else {
1143 // If it's not a string, it's an integer.
1144 targetVers = val.data;
1145 }
1146 }
1147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 sa.recycle();
1149
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001150 if (minCode != null) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001151 if (!minCode.equals(SDK_CODENAME)) {
1152 if (SDK_CODENAME != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001153 outError[0] = "Requires development platform " + minCode
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001154 + " (current platform is " + SDK_CODENAME + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001155 } else {
1156 outError[0] = "Requires development platform " + minCode
1157 + " but this is a release platform.";
1158 }
1159 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1160 return null;
1161 }
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001162 } else if (minVers > SDK_VERSION) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001163 outError[0] = "Requires newer sdk version #" + minVers
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001164 + " (current version is #" + SDK_VERSION + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001165 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1166 return null;
1167 }
1168
Dianne Hackborn851a5412009-05-08 12:06:44 -07001169 if (targetCode != null) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001170 if (!targetCode.equals(SDK_CODENAME)) {
1171 if (SDK_CODENAME != null) {
Dianne Hackborn851a5412009-05-08 12:06:44 -07001172 outError[0] = "Requires development platform " + targetCode
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001173 + " (current platform is " + SDK_CODENAME + ")";
Dianne Hackborn851a5412009-05-08 12:06:44 -07001174 } else {
1175 outError[0] = "Requires development platform " + targetCode
1176 + " but this is a release platform.";
1177 }
1178 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1179 return null;
1180 }
1181 // If the code matches, it definitely targets this SDK.
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001182 pkg.applicationInfo.targetSdkVersion
1183 = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
1184 } else {
1185 pkg.applicationInfo.targetSdkVersion = targetVers;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001186 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187 }
1188
1189 XmlUtils.skipCurrentTag(parser);
1190
Dianne Hackborn723738c2009-06-25 19:48:04 -07001191 } else if (tagName.equals("supports-screens")) {
1192 sa = res.obtainAttributes(attrs,
1193 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
1194
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001195 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
1196 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
1197 0);
1198 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
1199 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
1200 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07001201 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
1202 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
1203 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001204
Dianne Hackborn723738c2009-06-25 19:48:04 -07001205 // This is a trick to get a boolean and still able to detect
1206 // if a value was actually set.
1207 supportsSmallScreens = sa.getInteger(
1208 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
1209 supportsSmallScreens);
1210 supportsNormalScreens = sa.getInteger(
1211 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
1212 supportsNormalScreens);
1213 supportsLargeScreens = sa.getInteger(
1214 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
1215 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001216 supportsXLargeScreens = sa.getInteger(
1217 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
1218 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001219 resizeable = sa.getInteger(
1220 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001221 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001222 anyDensity = sa.getInteger(
1223 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
1224 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001225
1226 sa.recycle();
1227
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07001228 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn854060a2009-07-09 18:14:31 -07001229
1230 } else if (tagName.equals("protected-broadcast")) {
1231 sa = res.obtainAttributes(attrs,
1232 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
1233
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001234 // Note: don't allow this value to be a reference to a resource
1235 // that may change.
Dianne Hackborn854060a2009-07-09 18:14:31 -07001236 String name = sa.getNonResourceString(
1237 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
1238
1239 sa.recycle();
1240
1241 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
1242 if (pkg.protectedBroadcasts == null) {
1243 pkg.protectedBroadcasts = new ArrayList<String>();
1244 }
1245 if (!pkg.protectedBroadcasts.contains(name)) {
1246 pkg.protectedBroadcasts.add(name.intern());
1247 }
1248 }
1249
1250 XmlUtils.skipCurrentTag(parser);
1251
1252 } else if (tagName.equals("instrumentation")) {
1253 if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) {
1254 return null;
1255 }
1256
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001257 } else if (tagName.equals("original-package")) {
1258 sa = res.obtainAttributes(attrs,
1259 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1260
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001261 String orig =sa.getNonConfigurationString(
1262 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001263 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08001264 if (pkg.mOriginalPackages == null) {
1265 pkg.mOriginalPackages = new ArrayList<String>();
1266 pkg.mRealPackage = pkg.packageName;
1267 }
1268 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001269 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001270
1271 sa.recycle();
1272
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001273 XmlUtils.skipCurrentTag(parser);
1274
1275 } else if (tagName.equals("adopt-permissions")) {
1276 sa = res.obtainAttributes(attrs,
1277 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1278
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001279 String name = sa.getNonConfigurationString(
1280 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001281
1282 sa.recycle();
1283
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001284 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001285 if (pkg.mAdoptPermissions == null) {
1286 pkg.mAdoptPermissions = new ArrayList<String>();
1287 }
1288 pkg.mAdoptPermissions.add(name);
1289 }
1290
1291 XmlUtils.skipCurrentTag(parser);
1292
Dianne Hackborna0b46c92010-10-21 15:32:06 -07001293 } else if (tagName.equals("uses-gl-texture")) {
1294 // Just skip this tag
1295 XmlUtils.skipCurrentTag(parser);
1296 continue;
1297
1298 } else if (tagName.equals("compatible-screens")) {
1299 // Just skip this tag
1300 XmlUtils.skipCurrentTag(parser);
1301 continue;
1302
Dianne Hackborn854060a2009-07-09 18:14:31 -07001303 } else if (tagName.equals("eat-comment")) {
1304 // Just skip this tag
1305 XmlUtils.skipCurrentTag(parser);
1306 continue;
1307
1308 } else if (RIGID_PARSER) {
1309 outError[0] = "Bad element under <manifest>: "
1310 + parser.getName();
1311 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1312 return null;
1313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001314 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07001315 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07001316 + " at " + mArchiveSourcePath + " "
1317 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001318 XmlUtils.skipCurrentTag(parser);
1319 continue;
1320 }
1321 }
1322
1323 if (!foundApp && pkg.instrumentation.size() == 0) {
1324 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
1325 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1326 }
1327
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001328 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001329 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001330 for (int ip=0; ip<NP; ip++) {
1331 final PackageParser.NewPermissionInfo npi
1332 = PackageParser.NEW_PERMISSIONS[ip];
1333 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
1334 break;
1335 }
1336 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001337 if (implicitPerms == null) {
1338 implicitPerms = new StringBuilder(128);
1339 implicitPerms.append(pkg.packageName);
1340 implicitPerms.append(": compat added ");
1341 } else {
1342 implicitPerms.append(' ');
1343 }
1344 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001345 pkg.requestedPermissions.add(npi.name);
Dianne Hackborn65696252012-03-05 18:49:21 -08001346 pkg.requestedPermissionsRequired.add(Boolean.TRUE);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001347 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07001348 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001349 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07001350 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001351 }
Dianne Hackborn79245122012-03-12 10:51:26 -07001352
1353 final int NS = PackageParser.SPLIT_PERMISSIONS.length;
1354 for (int is=0; is<NS; is++) {
1355 final PackageParser.SplitPermissionInfo spi
1356 = PackageParser.SPLIT_PERMISSIONS[is];
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -07001357 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
1358 || !pkg.requestedPermissions.contains(spi.rootPerm)) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07001359 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07001360 }
1361 for (int in=0; in<spi.newPerms.length; in++) {
1362 final String perm = spi.newPerms[in];
1363 if (!pkg.requestedPermissions.contains(perm)) {
1364 pkg.requestedPermissions.add(perm);
1365 pkg.requestedPermissionsRequired.add(Boolean.TRUE);
1366 }
1367 }
1368 }
1369
Dianne Hackborn723738c2009-06-25 19:48:04 -07001370 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
1371 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001372 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001373 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
1374 }
1375 if (supportsNormalScreens != 0) {
1376 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
1377 }
1378 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
1379 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001380 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001381 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
1382 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001383 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
1384 && pkg.applicationInfo.targetSdkVersion
1385 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
1386 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
1387 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001388 if (resizeable < 0 || (resizeable > 0
1389 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001390 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001391 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
1392 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001393 if (anyDensity < 0 || (anyDensity > 0
1394 && pkg.applicationInfo.targetSdkVersion
1395 >= android.os.Build.VERSION_CODES.DONUT)) {
1396 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07001397 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07001398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 return pkg;
1400 }
1401
1402 private static String buildClassName(String pkg, CharSequence clsSeq,
1403 String[] outError) {
1404 if (clsSeq == null || clsSeq.length() <= 0) {
1405 outError[0] = "Empty class name in package " + pkg;
1406 return null;
1407 }
1408 String cls = clsSeq.toString();
1409 char c = cls.charAt(0);
1410 if (c == '.') {
1411 return (pkg + cls).intern();
1412 }
1413 if (cls.indexOf('.') < 0) {
1414 StringBuilder b = new StringBuilder(pkg);
1415 b.append('.');
1416 b.append(cls);
1417 return b.toString().intern();
1418 }
1419 if (c >= 'a' && c <= 'z') {
1420 return cls.intern();
1421 }
1422 outError[0] = "Bad class name " + cls + " in package " + pkg;
1423 return null;
1424 }
1425
1426 private static String buildCompoundName(String pkg,
1427 CharSequence procSeq, String type, String[] outError) {
1428 String proc = procSeq.toString();
1429 char c = proc.charAt(0);
1430 if (pkg != null && c == ':') {
1431 if (proc.length() < 2) {
1432 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
1433 + ": must be at least two characters";
1434 return null;
1435 }
1436 String subName = proc.substring(1);
1437 String nameError = validateName(subName, false);
1438 if (nameError != null) {
1439 outError[0] = "Invalid " + type + " name " + proc + " in package "
1440 + pkg + ": " + nameError;
1441 return null;
1442 }
1443 return (pkg + proc).intern();
1444 }
1445 String nameError = validateName(proc, true);
1446 if (nameError != null && !"system".equals(proc)) {
1447 outError[0] = "Invalid " + type + " name " + proc + " in package "
1448 + pkg + ": " + nameError;
1449 return null;
1450 }
1451 return proc.intern();
1452 }
1453
1454 private static String buildProcessName(String pkg, String defProc,
1455 CharSequence procSeq, int flags, String[] separateProcesses,
1456 String[] outError) {
1457 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
1458 return defProc != null ? defProc : pkg;
1459 }
1460 if (separateProcesses != null) {
1461 for (int i=separateProcesses.length-1; i>=0; i--) {
1462 String sp = separateProcesses[i];
1463 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
1464 return pkg;
1465 }
1466 }
1467 }
1468 if (procSeq == null || procSeq.length() <= 0) {
1469 return defProc;
1470 }
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07001471 return buildCompoundName(pkg, procSeq, "process", outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472 }
1473
1474 private static String buildTaskAffinityName(String pkg, String defProc,
1475 CharSequence procSeq, String[] outError) {
1476 if (procSeq == null) {
1477 return defProc;
1478 }
1479 if (procSeq.length() <= 0) {
1480 return null;
1481 }
1482 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
1483 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08001484
1485 private boolean parseKeys(Package owner, Resources res,
1486 XmlPullParser parser, AttributeSet attrs, String[] outError)
1487 throws XmlPullParserException, IOException {
1488 // we've encountered the 'keys' tag
1489 // all the keys and keysets that we want must be defined here
1490 // so we're going to iterate over the parser and pull out the things we want
1491 int outerDepth = parser.getDepth();
1492
1493 int type;
1494 PublicKey currentKey = null;
1495 Map<PublicKey, Set<String>> definedKeySets = new HashMap<PublicKey, Set<String>>();
1496 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1497 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1498 if (type == XmlPullParser.END_TAG) {
1499 continue;
1500 }
1501 String tagname = parser.getName();
1502 if (tagname.equals("publicKey")) {
1503 final TypedArray sa = res.obtainAttributes(attrs,
1504 com.android.internal.R.styleable.PublicKey);
1505 final String encodedKey = sa.getNonResourceString(
1506 com.android.internal.R.styleable.PublicKey_value);
1507 currentKey = parsePublicKey(encodedKey);
1508 definedKeySets.put(currentKey, new HashSet<String>());
1509 sa.recycle();
1510 } else if (tagname.equals("keyset")) {
1511 final TypedArray sa = res.obtainAttributes(attrs,
1512 com.android.internal.R.styleable.KeySet);
1513 final String name = sa.getNonResourceString(
1514 com.android.internal.R.styleable.KeySet_name);
1515 definedKeySets.get(currentKey).add(name);
1516 sa.recycle();
1517 } else if (RIGID_PARSER) {
1518 Slog.w(TAG, "Bad element under <keys>: " + parser.getName()
1519 + " at " + mArchiveSourcePath + " "
1520 + parser.getPositionDescription());
1521 return false;
1522 } else {
1523 Slog.w(TAG, "Unknown element under <keys>: " + parser.getName()
1524 + " at " + mArchiveSourcePath + " "
1525 + parser.getPositionDescription());
1526 XmlUtils.skipCurrentTag(parser);
1527 continue;
1528 }
1529 }
1530
1531 owner.mKeySetMapping = new HashMap<String, Set<PublicKey>>();
1532 for (Map.Entry<PublicKey, Set<String>> e : definedKeySets.entrySet()) {
1533 PublicKey key = e.getKey();
1534 Set<String> keySetNames = e.getValue();
1535 for (String alias : keySetNames) {
1536 if (owner.mKeySetMapping.containsKey(alias)) {
1537 owner.mKeySetMapping.get(alias).add(key);
1538 } else {
1539 Set<PublicKey> keys = new HashSet<PublicKey>();
1540 keys.add(key);
1541 owner.mKeySetMapping.put(alias, keys);
1542 }
1543 }
1544 }
1545
1546 return true;
1547 }
1548
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07001549 private PermissionGroup parsePermissionGroup(Package owner, int flags, Resources res,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 XmlPullParser parser, AttributeSet attrs, String[] outError)
1551 throws XmlPullParserException, IOException {
1552 PermissionGroup perm = new PermissionGroup(owner);
1553
1554 TypedArray sa = res.obtainAttributes(attrs,
1555 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
1556
1557 if (!parsePackageItemInfo(owner, perm.info, outError,
1558 "<permission-group>", sa,
1559 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
1560 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001561 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
1562 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 sa.recycle();
1564 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1565 return null;
1566 }
1567
1568 perm.info.descriptionRes = sa.getResourceId(
1569 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
1570 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07001571 perm.info.flags = sa.getInt(
1572 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07001573 perm.info.priority = sa.getInt(
1574 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
Dianne Hackborn99222d22012-05-06 16:30:15 -07001575 if (perm.info.priority > 0 && (flags&PARSE_IS_SYSTEM) == 0) {
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07001576 perm.info.priority = 0;
1577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001578
1579 sa.recycle();
1580
1581 if (!parseAllMetaData(res, parser, attrs, "<permission-group>", perm,
1582 outError)) {
1583 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1584 return null;
1585 }
1586
1587 owner.permissionGroups.add(perm);
1588
1589 return perm;
1590 }
1591
1592 private Permission parsePermission(Package owner, Resources res,
1593 XmlPullParser parser, AttributeSet attrs, String[] outError)
1594 throws XmlPullParserException, IOException {
1595 Permission perm = new Permission(owner);
1596
1597 TypedArray sa = res.obtainAttributes(attrs,
1598 com.android.internal.R.styleable.AndroidManifestPermission);
1599
1600 if (!parsePackageItemInfo(owner, perm.info, outError,
1601 "<permission>", sa,
1602 com.android.internal.R.styleable.AndroidManifestPermission_name,
1603 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001604 com.android.internal.R.styleable.AndroidManifestPermission_icon,
1605 com.android.internal.R.styleable.AndroidManifestPermission_logo)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 sa.recycle();
1607 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1608 return null;
1609 }
1610
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001611 // Note: don't allow this value to be a reference to a resource
1612 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 perm.info.group = sa.getNonResourceString(
1614 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
1615 if (perm.info.group != null) {
1616 perm.info.group = perm.info.group.intern();
1617 }
1618
1619 perm.info.descriptionRes = sa.getResourceId(
1620 com.android.internal.R.styleable.AndroidManifestPermission_description,
1621 0);
1622
1623 perm.info.protectionLevel = sa.getInt(
1624 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
1625 PermissionInfo.PROTECTION_NORMAL);
1626
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07001627 perm.info.flags = sa.getInt(
1628 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
1629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001630 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08001631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 if (perm.info.protectionLevel == -1) {
1633 outError[0] = "<permission> does not specify protectionLevel";
1634 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1635 return null;
1636 }
Dianne Hackborne639da72012-02-21 15:11:13 -08001637
1638 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
1639
1640 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
1641 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
1642 PermissionInfo.PROTECTION_SIGNATURE) {
1643 outError[0] = "<permission> protectionLevel specifies a flag but is "
1644 + "not based on signature type";
1645 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1646 return null;
1647 }
1648 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649
1650 if (!parseAllMetaData(res, parser, attrs, "<permission>", perm,
1651 outError)) {
1652 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1653 return null;
1654 }
1655
1656 owner.permissions.add(perm);
1657
1658 return perm;
1659 }
1660
1661 private Permission parsePermissionTree(Package owner, Resources res,
1662 XmlPullParser parser, AttributeSet attrs, String[] outError)
1663 throws XmlPullParserException, IOException {
1664 Permission perm = new Permission(owner);
1665
1666 TypedArray sa = res.obtainAttributes(attrs,
1667 com.android.internal.R.styleable.AndroidManifestPermissionTree);
1668
1669 if (!parsePackageItemInfo(owner, perm.info, outError,
1670 "<permission-tree>", sa,
1671 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
1672 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001673 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
1674 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 sa.recycle();
1676 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1677 return null;
1678 }
1679
1680 sa.recycle();
1681
1682 int index = perm.info.name.indexOf('.');
1683 if (index > 0) {
1684 index = perm.info.name.indexOf('.', index+1);
1685 }
1686 if (index < 0) {
1687 outError[0] = "<permission-tree> name has less than three segments: "
1688 + perm.info.name;
1689 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1690 return null;
1691 }
1692
1693 perm.info.descriptionRes = 0;
1694 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
1695 perm.tree = true;
1696
1697 if (!parseAllMetaData(res, parser, attrs, "<permission-tree>", perm,
1698 outError)) {
1699 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1700 return null;
1701 }
1702
1703 owner.permissions.add(perm);
1704
1705 return perm;
1706 }
1707
1708 private Instrumentation parseInstrumentation(Package owner, Resources res,
1709 XmlPullParser parser, AttributeSet attrs, String[] outError)
1710 throws XmlPullParserException, IOException {
1711 TypedArray sa = res.obtainAttributes(attrs,
1712 com.android.internal.R.styleable.AndroidManifestInstrumentation);
1713
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001714 if (mParseInstrumentationArgs == null) {
1715 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
1716 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
1717 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001718 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
1719 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001720 mParseInstrumentationArgs.tag = "<instrumentation>";
1721 }
1722
1723 mParseInstrumentationArgs.sa = sa;
1724
1725 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
1726 new InstrumentationInfo());
1727 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 sa.recycle();
1729 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1730 return null;
1731 }
1732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001734 // Note: don't allow this value to be a reference to a resource
1735 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 str = sa.getNonResourceString(
1737 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
1738 a.info.targetPackage = str != null ? str.intern() : null;
1739
1740 a.info.handleProfiling = sa.getBoolean(
1741 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
1742 false);
1743
1744 a.info.functionalTest = sa.getBoolean(
1745 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
1746 false);
1747
1748 sa.recycle();
1749
1750 if (a.info.targetPackage == null) {
1751 outError[0] = "<instrumentation> does not specify targetPackage";
1752 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1753 return null;
1754 }
1755
1756 if (!parseAllMetaData(res, parser, attrs, "<instrumentation>", a,
1757 outError)) {
1758 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1759 return null;
1760 }
1761
1762 owner.instrumentation.add(a);
1763
1764 return a;
1765 }
1766
1767 private boolean parseApplication(Package owner, Resources res,
1768 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
1769 throws XmlPullParserException, IOException {
1770 final ApplicationInfo ai = owner.applicationInfo;
1771 final String pkgName = owner.applicationInfo.packageName;
1772
1773 TypedArray sa = res.obtainAttributes(attrs,
1774 com.android.internal.R.styleable.AndroidManifestApplication);
1775
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001776 String name = sa.getNonConfigurationString(
1777 com.android.internal.R.styleable.AndroidManifestApplication_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001778 if (name != null) {
1779 ai.className = buildClassName(pkgName, name, outError);
1780 if (ai.className == null) {
1781 sa.recycle();
1782 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1783 return false;
1784 }
1785 }
1786
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001787 String manageSpaceActivity = sa.getNonConfigurationString(
1788 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789 if (manageSpaceActivity != null) {
1790 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
1791 outError);
1792 }
1793
Christopher Tate181fafa2009-05-14 11:12:14 -07001794 boolean allowBackup = sa.getBoolean(
1795 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
1796 if (allowBackup) {
1797 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07001798
Christopher Tate3de55bc2010-03-12 17:28:08 -08001799 // backupAgent, killAfterRestore, and restoreAnyVersion are only relevant
1800 // if backup is possible for the given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001801 String backupAgent = sa.getNonConfigurationString(
1802 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent, 0);
Christopher Tate181fafa2009-05-14 11:12:14 -07001803 if (backupAgent != null) {
1804 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07001805 if (DEBUG_BACKUP) {
1806 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001807 + " from " + pkgName + "+" + backupAgent);
1808 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07001809
1810 if (sa.getBoolean(
1811 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
1812 true)) {
1813 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
1814 }
1815 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08001816 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
1817 false)) {
1818 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
1819 }
Christopher Tate181fafa2009-05-14 11:12:14 -07001820 }
1821 }
Christopher Tate4a627c72011-04-01 14:43:32 -07001822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001823 TypedValue v = sa.peekValue(
1824 com.android.internal.R.styleable.AndroidManifestApplication_label);
1825 if (v != null && (ai.labelRes=v.resourceId) == 0) {
1826 ai.nonLocalizedLabel = v.coerceToString();
1827 }
1828
1829 ai.icon = sa.getResourceId(
1830 com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
Adam Powell81cd2e92010-04-21 16:35:18 -07001831 ai.logo = sa.getResourceId(
1832 com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001833 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08001834 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 ai.descriptionRes = sa.getResourceId(
1836 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
1837
1838 if ((flags&PARSE_IS_SYSTEM) != 0) {
1839 if (sa.getBoolean(
1840 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
1841 false)) {
1842 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
1843 }
1844 }
1845
1846 if (sa.getBoolean(
1847 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
1848 false)) {
1849 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
1850 }
1851
1852 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07001853 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08001854 false)) {
1855 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
1856 }
1857
Romain Guy529b60a2010-08-03 18:05:47 -07001858 boolean hardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07001859 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07001860 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Romain Guy812ccbe2010-06-01 14:07:24 -07001861
1862 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001863 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
1864 true)) {
1865 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
1866 }
1867
1868 if (sa.getBoolean(
1869 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
1870 false)) {
1871 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
1872 }
1873
1874 if (sa.getBoolean(
1875 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
1876 true)) {
1877 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
1878 }
1879
Dianne Hackbornade3eca2009-05-11 18:54:45 -07001880 if (sa.getBoolean(
1881 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
Dianne Hackborne7fe35b2009-05-13 10:53:41 -07001882 false)) {
Dianne Hackbornade3eca2009-05-11 18:54:45 -07001883 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
1884 }
1885
Jason parksa3cdaa52011-01-13 14:15:43 -06001886 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08001887 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06001888 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08001889 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06001890 }
1891
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07001892 if (sa.getBoolean(
1893 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
1894 false /* default is no RTL support*/)) {
1895 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
1896 }
1897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001898 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001899 str = sa.getNonConfigurationString(
1900 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001901 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
1902
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07001903 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
1904 str = sa.getNonConfigurationString(
1905 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity, 0);
1906 } else {
1907 // Some older apps have been seen to use a resource reference
1908 // here that on older builds was ignored (with a warning). We
1909 // need to continue to do this for them so they don't break.
1910 str = sa.getNonResourceString(
1911 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
1912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
1914 str, outError);
1915
1916 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07001917 CharSequence pname;
1918 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
1919 pname = sa.getNonConfigurationString(
1920 com.android.internal.R.styleable.AndroidManifestApplication_process, 0);
1921 } else {
1922 // Some older apps have been seen to use a resource reference
1923 // here that on older builds was ignored (with a warning). We
1924 // need to continue to do this for them so they don't break.
1925 pname = sa.getNonResourceString(
1926 com.android.internal.R.styleable.AndroidManifestApplication_process);
1927 }
1928 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001929 flags, mSeparateProcesses, outError);
1930
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001931 ai.enabled = sa.getBoolean(
1932 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001933
Dianne Hackborn02486b12010-08-26 14:18:37 -07001934 if (false) {
1935 if (sa.getBoolean(
1936 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
1937 false)) {
Dianne Hackborn54e570f2010-10-04 18:32:32 -07001938 ai.flags |= ApplicationInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07001939
1940 // A heavy-weight application can not be in a custom process.
1941 // We can do direct compare because we intern all strings.
1942 if (ai.processName != null && ai.processName != ai.packageName) {
1943 outError[0] = "cantSaveState applications can not use custom processes";
1944 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07001945 }
1946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001947 }
1948
Adam Powell269248d2011-08-02 10:26:54 -07001949 ai.uiOptions = sa.getInt(
1950 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
1951
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001952 sa.recycle();
1953
1954 if (outError[0] != null) {
1955 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1956 return false;
1957 }
1958
1959 final int innerDepth = parser.getDepth();
1960
1961 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001962 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1963 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
1964 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965 continue;
1966 }
1967
1968 String tagName = parser.getName();
1969 if (tagName.equals("activity")) {
Romain Guy529b60a2010-08-03 18:05:47 -07001970 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
1971 hardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001972 if (a == null) {
1973 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1974 return false;
1975 }
1976
1977 owner.activities.add(a);
1978
1979 } else if (tagName.equals("receiver")) {
Romain Guy529b60a2010-08-03 18:05:47 -07001980 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001981 if (a == null) {
1982 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1983 return false;
1984 }
1985
1986 owner.receivers.add(a);
1987
1988 } else if (tagName.equals("service")) {
1989 Service s = parseService(owner, res, parser, attrs, flags, outError);
1990 if (s == null) {
1991 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1992 return false;
1993 }
1994
1995 owner.services.add(s);
1996
1997 } else if (tagName.equals("provider")) {
1998 Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
1999 if (p == null) {
2000 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2001 return false;
2002 }
2003
2004 owner.providers.add(p);
2005
2006 } else if (tagName.equals("activity-alias")) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002007 Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002008 if (a == null) {
2009 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2010 return false;
2011 }
2012
2013 owner.activities.add(a);
2014
2015 } else if (parser.getName().equals("meta-data")) {
2016 // note: application meta-data is stored off to the side, so it can
2017 // remain null in the primary copy (we like to avoid extra copies because
2018 // it can be large)
2019 if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,
2020 outError)) == null) {
2021 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2022 return false;
2023 }
2024
2025 } else if (tagName.equals("uses-library")) {
2026 sa = res.obtainAttributes(attrs,
2027 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
2028
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002029 // Note: don't allow this value to be a reference to a resource
2030 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 String lname = sa.getNonResourceString(
2032 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07002033 boolean req = sa.getBoolean(
2034 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
2035 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002036
2037 sa.recycle();
2038
Dianne Hackborn49237342009-08-27 20:08:01 -07002039 if (lname != null) {
2040 if (req) {
2041 if (owner.usesLibraries == null) {
2042 owner.usesLibraries = new ArrayList<String>();
2043 }
2044 if (!owner.usesLibraries.contains(lname)) {
2045 owner.usesLibraries.add(lname.intern());
2046 }
2047 } else {
2048 if (owner.usesOptionalLibraries == null) {
2049 owner.usesOptionalLibraries = new ArrayList<String>();
2050 }
2051 if (!owner.usesOptionalLibraries.contains(lname)) {
2052 owner.usesOptionalLibraries.add(lname.intern());
2053 }
2054 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 }
2056
2057 XmlUtils.skipCurrentTag(parser);
2058
Dianne Hackborncef65ee2010-09-30 18:27:22 -07002059 } else if (tagName.equals("uses-package")) {
2060 // Dependencies for app installers; we don't currently try to
2061 // enforce this.
2062 XmlUtils.skipCurrentTag(parser);
2063
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 } else {
2065 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002066 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002067 + " at " + mArchiveSourcePath + " "
2068 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 XmlUtils.skipCurrentTag(parser);
2070 continue;
2071 } else {
2072 outError[0] = "Bad element under <application>: " + tagName;
2073 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2074 return false;
2075 }
2076 }
2077 }
2078
2079 return true;
2080 }
2081
2082 private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
2083 String[] outError, String tag, TypedArray sa,
Adam Powell81cd2e92010-04-21 16:35:18 -07002084 int nameRes, int labelRes, int iconRes, int logoRes) {
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002085 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002086 if (name == null) {
2087 outError[0] = tag + " does not specify android:name";
2088 return false;
2089 }
2090
2091 outInfo.name
2092 = buildClassName(owner.applicationInfo.packageName, name, outError);
2093 if (outInfo.name == null) {
2094 return false;
2095 }
2096
2097 int iconVal = sa.getResourceId(iconRes, 0);
2098 if (iconVal != 0) {
2099 outInfo.icon = iconVal;
2100 outInfo.nonLocalizedLabel = null;
2101 }
Adam Powell81cd2e92010-04-21 16:35:18 -07002102
2103 int logoVal = sa.getResourceId(logoRes, 0);
2104 if (logoVal != 0) {
2105 outInfo.logo = logoVal;
2106 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002107
2108 TypedValue v = sa.peekValue(labelRes);
2109 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
2110 outInfo.nonLocalizedLabel = v.coerceToString();
2111 }
2112
2113 outInfo.packageName = owner.packageName;
2114
2115 return true;
2116 }
2117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002118 private Activity parseActivity(Package owner, Resources res,
2119 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
Romain Guy529b60a2010-08-03 18:05:47 -07002120 boolean receiver, boolean hardwareAccelerated)
2121 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002122 TypedArray sa = res.obtainAttributes(attrs,
2123 com.android.internal.R.styleable.AndroidManifestActivity);
2124
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002125 if (mParseActivityArgs == null) {
2126 mParseActivityArgs = new ParseComponentArgs(owner, outError,
2127 com.android.internal.R.styleable.AndroidManifestActivity_name,
2128 com.android.internal.R.styleable.AndroidManifestActivity_label,
2129 com.android.internal.R.styleable.AndroidManifestActivity_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07002130 com.android.internal.R.styleable.AndroidManifestActivity_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002131 mSeparateProcesses,
2132 com.android.internal.R.styleable.AndroidManifestActivity_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002133 com.android.internal.R.styleable.AndroidManifestActivity_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002134 com.android.internal.R.styleable.AndroidManifestActivity_enabled);
2135 }
2136
2137 mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
2138 mParseActivityArgs.sa = sa;
2139 mParseActivityArgs.flags = flags;
2140
2141 Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
2142 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002143 sa.recycle();
2144 return null;
2145 }
2146
Dianne Hackborn7d19e022012-08-07 19:12:33 -07002147 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 com.android.internal.R.styleable.AndroidManifestActivity_exported);
2149 if (setExported) {
2150 a.info.exported = sa.getBoolean(
2151 com.android.internal.R.styleable.AndroidManifestActivity_exported, false);
2152 }
2153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002154 a.info.theme = sa.getResourceId(
2155 com.android.internal.R.styleable.AndroidManifestActivity_theme, 0);
2156
Adam Powell269248d2011-08-02 10:26:54 -07002157 a.info.uiOptions = sa.getInt(
2158 com.android.internal.R.styleable.AndroidManifestActivity_uiOptions,
2159 a.info.applicationInfo.uiOptions);
2160
Adam Powelldd8fab22012-03-22 17:47:27 -07002161 String parentName = sa.getNonConfigurationString(
2162 com.android.internal.R.styleable.AndroidManifestActivity_parentActivityName, 0);
2163 if (parentName != null) {
2164 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
2165 if (outError[0] == null) {
2166 a.info.parentActivityName = parentClassName;
2167 } else {
2168 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
2169 parentName);
2170 outError[0] = null;
2171 }
2172 }
2173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002174 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002175 str = sa.getNonConfigurationString(
2176 com.android.internal.R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 if (str == null) {
2178 a.info.permission = owner.applicationInfo.permission;
2179 } else {
2180 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
2181 }
2182
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002183 str = sa.getNonConfigurationString(
2184 com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002185 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
2186 owner.applicationInfo.taskAffinity, str, outError);
2187
2188 a.info.flags = 0;
2189 if (sa.getBoolean(
2190 com.android.internal.R.styleable.AndroidManifestActivity_multiprocess,
2191 false)) {
2192 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
2193 }
2194
2195 if (sa.getBoolean(
2196 com.android.internal.R.styleable.AndroidManifestActivity_finishOnTaskLaunch,
2197 false)) {
2198 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
2199 }
2200
2201 if (sa.getBoolean(
2202 com.android.internal.R.styleable.AndroidManifestActivity_clearTaskOnLaunch,
2203 false)) {
2204 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
2205 }
2206
2207 if (sa.getBoolean(
2208 com.android.internal.R.styleable.AndroidManifestActivity_noHistory,
2209 false)) {
2210 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
2211 }
2212
2213 if (sa.getBoolean(
2214 com.android.internal.R.styleable.AndroidManifestActivity_alwaysRetainTaskState,
2215 false)) {
2216 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
2217 }
2218
2219 if (sa.getBoolean(
2220 com.android.internal.R.styleable.AndroidManifestActivity_stateNotNeeded,
2221 false)) {
2222 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
2223 }
2224
2225 if (sa.getBoolean(
2226 com.android.internal.R.styleable.AndroidManifestActivity_excludeFromRecents,
2227 false)) {
2228 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2229 }
2230
2231 if (sa.getBoolean(
2232 com.android.internal.R.styleable.AndroidManifestActivity_allowTaskReparenting,
2233 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
2234 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
2235 }
2236
Dianne Hackbornffa42482009-09-23 22:20:11 -07002237 if (sa.getBoolean(
2238 com.android.internal.R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs,
2239 false)) {
2240 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
2241 }
2242
Daniel Sandler613dde42010-06-21 13:46:39 -04002243 if (sa.getBoolean(
Craig Mautner5962b122012-10-05 14:45:52 -07002244 com.android.internal.R.styleable.AndroidManifestActivity_showOnLockScreen,
2245 false)) {
2246 a.info.flags |= ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN;
2247 }
2248
2249 if (sa.getBoolean(
Daniel Sandler613dde42010-06-21 13:46:39 -04002250 com.android.internal.R.styleable.AndroidManifestActivity_immersive,
2251 false)) {
2252 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
2253 }
Craig Mautner5962b122012-10-05 14:45:52 -07002254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002255 if (!receiver) {
Romain Guy529b60a2010-08-03 18:05:47 -07002256 if (sa.getBoolean(
2257 com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated,
2258 hardwareAccelerated)) {
2259 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
2260 }
2261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002262 a.info.launchMode = sa.getInt(
2263 com.android.internal.R.styleable.AndroidManifestActivity_launchMode,
2264 ActivityInfo.LAUNCH_MULTIPLE);
2265 a.info.screenOrientation = sa.getInt(
2266 com.android.internal.R.styleable.AndroidManifestActivity_screenOrientation,
2267 ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
2268 a.info.configChanges = sa.getInt(
2269 com.android.internal.R.styleable.AndroidManifestActivity_configChanges,
2270 0);
2271 a.info.softInputMode = sa.getInt(
2272 com.android.internal.R.styleable.AndroidManifestActivity_windowSoftInputMode,
2273 0);
2274 } else {
2275 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2276 a.info.configChanges = 0;
2277 }
2278
Dianne Hackborn7d19e022012-08-07 19:12:33 -07002279 if (receiver) {
2280 if (sa.getBoolean(
2281 com.android.internal.R.styleable.AndroidManifestActivity_singleUser,
2282 false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002283 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07002284 if (a.info.exported) {
2285 Slog.w(TAG, "Activity exported request ignored due to singleUser: "
2286 + a.className + " at " + mArchiveSourcePath + " "
2287 + parser.getPositionDescription());
2288 a.info.exported = false;
2289 }
2290 setExported = true;
2291 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002292 if (sa.getBoolean(
2293 com.android.internal.R.styleable.AndroidManifestActivity_primaryUserOnly,
2294 false)) {
2295 a.info.flags |= ActivityInfo.FLAG_PRIMARY_USER_ONLY;
2296 }
Dianne Hackborn7d19e022012-08-07 19:12:33 -07002297 }
2298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002299 sa.recycle();
2300
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002301 if (receiver && (owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07002302 // A heavy-weight application can not have receives in its main process
2303 // We can do direct compare because we intern all strings.
2304 if (a.info.processName == owner.packageName) {
2305 outError[0] = "Heavy-weight applications can not have receivers in main process";
2306 }
2307 }
2308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 if (outError[0] != null) {
2310 return null;
2311 }
2312
2313 int outerDepth = parser.getDepth();
2314 int type;
2315 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2316 && (type != XmlPullParser.END_TAG
2317 || parser.getDepth() > outerDepth)) {
2318 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2319 continue;
2320 }
2321
2322 if (parser.getName().equals("intent-filter")) {
2323 ActivityIntentInfo intent = new ActivityIntentInfo(a);
2324 if (!parseIntent(res, parser, attrs, flags, intent, outError, !receiver)) {
2325 return null;
2326 }
2327 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002328 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002329 + mArchiveSourcePath + " "
2330 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002331 } else {
2332 a.intents.add(intent);
2333 }
2334 } else if (parser.getName().equals("meta-data")) {
2335 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
2336 outError)) == null) {
2337 return null;
2338 }
2339 } else {
2340 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002341 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002342 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002343 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002344 + " at " + mArchiveSourcePath + " "
2345 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002346 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002347 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002348 + " at " + mArchiveSourcePath + " "
2349 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002350 }
2351 XmlUtils.skipCurrentTag(parser);
2352 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002353 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002354 if (receiver) {
2355 outError[0] = "Bad element under <receiver>: " + parser.getName();
2356 } else {
2357 outError[0] = "Bad element under <activity>: " + parser.getName();
2358 }
2359 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002361 }
2362 }
2363
2364 if (!setExported) {
2365 a.info.exported = a.intents.size() > 0;
2366 }
2367
2368 return a;
2369 }
2370
2371 private Activity parseActivityAlias(Package owner, Resources res,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002372 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2373 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002374 TypedArray sa = res.obtainAttributes(attrs,
2375 com.android.internal.R.styleable.AndroidManifestActivityAlias);
2376
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002377 String targetActivity = sa.getNonConfigurationString(
2378 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379 if (targetActivity == null) {
2380 outError[0] = "<activity-alias> does not specify android:targetActivity";
2381 sa.recycle();
2382 return null;
2383 }
2384
2385 targetActivity = buildClassName(owner.applicationInfo.packageName,
2386 targetActivity, outError);
2387 if (targetActivity == null) {
2388 sa.recycle();
2389 return null;
2390 }
2391
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002392 if (mParseActivityAliasArgs == null) {
2393 mParseActivityAliasArgs = new ParseComponentArgs(owner, outError,
2394 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
2395 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
2396 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07002397 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002398 mSeparateProcesses,
2399 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002400 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002401 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
2402 mParseActivityAliasArgs.tag = "<activity-alias>";
2403 }
2404
2405 mParseActivityAliasArgs.sa = sa;
2406 mParseActivityAliasArgs.flags = flags;
2407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002408 Activity target = null;
2409
2410 final int NA = owner.activities.size();
2411 for (int i=0; i<NA; i++) {
2412 Activity t = owner.activities.get(i);
2413 if (targetActivity.equals(t.info.name)) {
2414 target = t;
2415 break;
2416 }
2417 }
2418
2419 if (target == null) {
2420 outError[0] = "<activity-alias> target activity " + targetActivity
2421 + " not found in manifest";
2422 sa.recycle();
2423 return null;
2424 }
2425
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002426 ActivityInfo info = new ActivityInfo();
2427 info.targetActivity = targetActivity;
2428 info.configChanges = target.info.configChanges;
2429 info.flags = target.info.flags;
2430 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07002431 info.logo = target.info.logo;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002432 info.labelRes = target.info.labelRes;
2433 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
2434 info.launchMode = target.info.launchMode;
2435 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002436 if (info.descriptionRes == 0) {
2437 info.descriptionRes = target.info.descriptionRes;
2438 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002439 info.screenOrientation = target.info.screenOrientation;
2440 info.taskAffinity = target.info.taskAffinity;
2441 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07002442 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07002443 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07002444 info.parentActivityName = target.info.parentActivityName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002445
2446 Activity a = new Activity(mParseActivityAliasArgs, info);
2447 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002448 sa.recycle();
2449 return null;
2450 }
2451
2452 final boolean setExported = sa.hasValue(
2453 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
2454 if (setExported) {
2455 a.info.exported = sa.getBoolean(
2456 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
2457 }
2458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002459 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002460 str = sa.getNonConfigurationString(
2461 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002462 if (str != null) {
2463 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
2464 }
2465
Adam Powelldd8fab22012-03-22 17:47:27 -07002466 String parentName = sa.getNonConfigurationString(
2467 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
2468 0);
2469 if (parentName != null) {
2470 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
2471 if (outError[0] == null) {
2472 a.info.parentActivityName = parentClassName;
2473 } else {
2474 Log.e(TAG, "Activity alias " + a.info.name +
2475 " specified invalid parentActivityName " + parentName);
2476 outError[0] = null;
2477 }
2478 }
2479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002480 sa.recycle();
2481
2482 if (outError[0] != null) {
2483 return null;
2484 }
2485
2486 int outerDepth = parser.getDepth();
2487 int type;
2488 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2489 && (type != XmlPullParser.END_TAG
2490 || parser.getDepth() > outerDepth)) {
2491 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2492 continue;
2493 }
2494
2495 if (parser.getName().equals("intent-filter")) {
2496 ActivityIntentInfo intent = new ActivityIntentInfo(a);
2497 if (!parseIntent(res, parser, attrs, flags, intent, outError, true)) {
2498 return null;
2499 }
2500 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002501 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002502 + mArchiveSourcePath + " "
2503 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002504 } else {
2505 a.intents.add(intent);
2506 }
2507 } else if (parser.getName().equals("meta-data")) {
2508 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
2509 outError)) == null) {
2510 return null;
2511 }
2512 } else {
2513 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002514 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002515 + " at " + mArchiveSourcePath + " "
2516 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 XmlUtils.skipCurrentTag(parser);
2518 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002519 } else {
2520 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
2521 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002523 }
2524 }
2525
2526 if (!setExported) {
2527 a.info.exported = a.intents.size() > 0;
2528 }
2529
2530 return a;
2531 }
2532
2533 private Provider parseProvider(Package owner, Resources res,
2534 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2535 throws XmlPullParserException, IOException {
2536 TypedArray sa = res.obtainAttributes(attrs,
2537 com.android.internal.R.styleable.AndroidManifestProvider);
2538
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002539 if (mParseProviderArgs == null) {
2540 mParseProviderArgs = new ParseComponentArgs(owner, outError,
2541 com.android.internal.R.styleable.AndroidManifestProvider_name,
2542 com.android.internal.R.styleable.AndroidManifestProvider_label,
2543 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07002544 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002545 mSeparateProcesses,
2546 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002547 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002548 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
2549 mParseProviderArgs.tag = "<provider>";
2550 }
2551
2552 mParseProviderArgs.sa = sa;
2553 mParseProviderArgs.flags = flags;
2554
2555 Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
2556 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 sa.recycle();
2558 return null;
2559 }
2560
Nick Kralevichf097b162012-07-28 12:43:48 -07002561 boolean providerExportedDefault = false;
2562
2563 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
2564 // For compatibility, applications targeting API level 16 or lower
2565 // should have their content providers exported by default, unless they
2566 // specify otherwise.
2567 providerExportedDefault = true;
2568 }
2569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07002571 com.android.internal.R.styleable.AndroidManifestProvider_exported,
2572 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002573
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002574 String cpname = sa.getNonConfigurationString(
2575 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576
2577 p.info.isSyncable = sa.getBoolean(
2578 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
2579 false);
2580
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002581 String permission = sa.getNonConfigurationString(
2582 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
2583 String str = sa.getNonConfigurationString(
2584 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002585 if (str == null) {
2586 str = permission;
2587 }
2588 if (str == null) {
2589 p.info.readPermission = owner.applicationInfo.permission;
2590 } else {
2591 p.info.readPermission =
2592 str.length() > 0 ? str.toString().intern() : null;
2593 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002594 str = sa.getNonConfigurationString(
2595 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596 if (str == null) {
2597 str = permission;
2598 }
2599 if (str == null) {
2600 p.info.writePermission = owner.applicationInfo.permission;
2601 } else {
2602 p.info.writePermission =
2603 str.length() > 0 ? str.toString().intern() : null;
2604 }
2605
2606 p.info.grantUriPermissions = sa.getBoolean(
2607 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
2608 false);
2609
2610 p.info.multiprocess = sa.getBoolean(
2611 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
2612 false);
2613
2614 p.info.initOrder = sa.getInt(
2615 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
2616 0);
2617
Dianne Hackborn7d19e022012-08-07 19:12:33 -07002618 p.info.flags = 0;
2619
2620 if (sa.getBoolean(
2621 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
2622 false)) {
2623 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
2624 if (p.info.exported) {
2625 Slog.w(TAG, "Provider exported request ignored due to singleUser: "
2626 + p.className + " at " + mArchiveSourcePath + " "
2627 + parser.getPositionDescription());
2628 p.info.exported = false;
2629 }
2630 }
2631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 sa.recycle();
2633
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002634 if ((owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07002635 // A heavy-weight application can not have providers in its main process
2636 // We can do direct compare because we intern all strings.
2637 if (p.info.processName == owner.packageName) {
2638 outError[0] = "Heavy-weight applications can not have providers in main process";
2639 return null;
2640 }
2641 }
2642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002643 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07002644 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002645 return null;
2646 }
2647 p.info.authority = cpname.intern();
2648
2649 if (!parseProviderTags(res, parser, attrs, p, outError)) {
2650 return null;
2651 }
2652
2653 return p;
2654 }
2655
2656 private boolean parseProviderTags(Resources res,
2657 XmlPullParser parser, AttributeSet attrs,
2658 Provider outInfo, String[] outError)
2659 throws XmlPullParserException, IOException {
2660 int outerDepth = parser.getDepth();
2661 int type;
2662 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2663 && (type != XmlPullParser.END_TAG
2664 || parser.getDepth() > outerDepth)) {
2665 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2666 continue;
2667 }
2668
2669 if (parser.getName().equals("meta-data")) {
2670 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
2671 outInfo.metaData, outError)) == null) {
2672 return false;
2673 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002675 } else if (parser.getName().equals("grant-uri-permission")) {
2676 TypedArray sa = res.obtainAttributes(attrs,
2677 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
2678
2679 PatternMatcher pa = null;
2680
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002681 String str = sa.getNonConfigurationString(
2682 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 if (str != null) {
2684 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
2685 }
2686
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002687 str = sa.getNonConfigurationString(
2688 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002689 if (str != null) {
2690 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
2691 }
2692
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002693 str = sa.getNonConfigurationString(
2694 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002695 if (str != null) {
2696 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
2697 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002699 sa.recycle();
2700
2701 if (pa != null) {
2702 if (outInfo.info.uriPermissionPatterns == null) {
2703 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
2704 outInfo.info.uriPermissionPatterns[0] = pa;
2705 } else {
2706 final int N = outInfo.info.uriPermissionPatterns.length;
2707 PatternMatcher[] newp = new PatternMatcher[N+1];
2708 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
2709 newp[N] = pa;
2710 outInfo.info.uriPermissionPatterns = newp;
2711 }
2712 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002713 } else {
2714 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002715 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002716 + parser.getName() + " at " + mArchiveSourcePath + " "
2717 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002718 XmlUtils.skipCurrentTag(parser);
2719 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002720 } else {
2721 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
2722 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002723 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002724 }
2725 XmlUtils.skipCurrentTag(parser);
2726
2727 } else if (parser.getName().equals("path-permission")) {
2728 TypedArray sa = res.obtainAttributes(attrs,
2729 com.android.internal.R.styleable.AndroidManifestPathPermission);
2730
2731 PathPermission pa = null;
2732
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002733 String permission = sa.getNonConfigurationString(
2734 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
2735 String readPermission = sa.getNonConfigurationString(
2736 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002737 if (readPermission == null) {
2738 readPermission = permission;
2739 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002740 String writePermission = sa.getNonConfigurationString(
2741 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002742 if (writePermission == null) {
2743 writePermission = permission;
2744 }
2745
2746 boolean havePerm = false;
2747 if (readPermission != null) {
2748 readPermission = readPermission.intern();
2749 havePerm = true;
2750 }
2751 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00002752 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002753 havePerm = true;
2754 }
2755
2756 if (!havePerm) {
2757 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002758 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002759 + parser.getName() + " at " + mArchiveSourcePath + " "
2760 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002761 XmlUtils.skipCurrentTag(parser);
2762 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002763 } else {
2764 outError[0] = "No readPermission or writePermssion for <path-permission>";
2765 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002766 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002767 }
2768
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002769 String path = sa.getNonConfigurationString(
2770 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002771 if (path != null) {
2772 pa = new PathPermission(path,
2773 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
2774 }
2775
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002776 path = sa.getNonConfigurationString(
2777 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002778 if (path != null) {
2779 pa = new PathPermission(path,
2780 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
2781 }
2782
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002783 path = sa.getNonConfigurationString(
2784 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002785 if (path != null) {
2786 pa = new PathPermission(path,
2787 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
2788 }
2789
2790 sa.recycle();
2791
2792 if (pa != null) {
2793 if (outInfo.info.pathPermissions == null) {
2794 outInfo.info.pathPermissions = new PathPermission[1];
2795 outInfo.info.pathPermissions[0] = pa;
2796 } else {
2797 final int N = outInfo.info.pathPermissions.length;
2798 PathPermission[] newp = new PathPermission[N+1];
2799 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
2800 newp[N] = pa;
2801 outInfo.info.pathPermissions = newp;
2802 }
2803 } else {
2804 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002805 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002806 + parser.getName() + " at " + mArchiveSourcePath + " "
2807 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002808 XmlUtils.skipCurrentTag(parser);
2809 continue;
2810 }
2811 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
2812 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002813 }
2814 XmlUtils.skipCurrentTag(parser);
2815
2816 } else {
2817 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002818 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002819 + parser.getName() + " at " + mArchiveSourcePath + " "
2820 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002821 XmlUtils.skipCurrentTag(parser);
2822 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002823 } else {
2824 outError[0] = "Bad element under <provider>: " + parser.getName();
2825 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002827 }
2828 }
2829 return true;
2830 }
2831
2832 private Service parseService(Package owner, Resources res,
2833 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2834 throws XmlPullParserException, IOException {
2835 TypedArray sa = res.obtainAttributes(attrs,
2836 com.android.internal.R.styleable.AndroidManifestService);
2837
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002838 if (mParseServiceArgs == null) {
2839 mParseServiceArgs = new ParseComponentArgs(owner, outError,
2840 com.android.internal.R.styleable.AndroidManifestService_name,
2841 com.android.internal.R.styleable.AndroidManifestService_label,
2842 com.android.internal.R.styleable.AndroidManifestService_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07002843 com.android.internal.R.styleable.AndroidManifestService_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002844 mSeparateProcesses,
2845 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002846 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002847 com.android.internal.R.styleable.AndroidManifestService_enabled);
2848 mParseServiceArgs.tag = "<service>";
2849 }
2850
2851 mParseServiceArgs.sa = sa;
2852 mParseServiceArgs.flags = flags;
2853
2854 Service s = new Service(mParseServiceArgs, new ServiceInfo());
2855 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856 sa.recycle();
2857 return null;
2858 }
2859
Dianne Hackbornb4163a62012-08-02 18:31:26 -07002860 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002861 com.android.internal.R.styleable.AndroidManifestService_exported);
2862 if (setExported) {
2863 s.info.exported = sa.getBoolean(
2864 com.android.internal.R.styleable.AndroidManifestService_exported, false);
2865 }
2866
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002867 String str = sa.getNonConfigurationString(
2868 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002869 if (str == null) {
2870 s.info.permission = owner.applicationInfo.permission;
2871 } else {
2872 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
2873 }
2874
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002875 s.info.flags = 0;
2876 if (sa.getBoolean(
2877 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
2878 false)) {
2879 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
2880 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08002881 if (sa.getBoolean(
2882 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
2883 false)) {
2884 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
2885 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07002886 if (sa.getBoolean(
2887 com.android.internal.R.styleable.AndroidManifestService_singleUser,
2888 false)) {
2889 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
2890 if (s.info.exported) {
2891 Slog.w(TAG, "Service exported request ignored due to singleUser: "
2892 + s.className + " at " + mArchiveSourcePath + " "
2893 + parser.getPositionDescription());
2894 s.info.exported = false;
2895 }
2896 setExported = true;
2897 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002899 sa.recycle();
2900
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002901 if ((owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07002902 // A heavy-weight application can not have services in its main process
2903 // We can do direct compare because we intern all strings.
2904 if (s.info.processName == owner.packageName) {
2905 outError[0] = "Heavy-weight applications can not have services in main process";
2906 return null;
2907 }
2908 }
2909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002910 int outerDepth = parser.getDepth();
2911 int type;
2912 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2913 && (type != XmlPullParser.END_TAG
2914 || parser.getDepth() > outerDepth)) {
2915 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2916 continue;
2917 }
2918
2919 if (parser.getName().equals("intent-filter")) {
2920 ServiceIntentInfo intent = new ServiceIntentInfo(s);
2921 if (!parseIntent(res, parser, attrs, flags, intent, outError, false)) {
2922 return null;
2923 }
2924
2925 s.intents.add(intent);
2926 } else if (parser.getName().equals("meta-data")) {
2927 if ((s.metaData=parseMetaData(res, parser, attrs, s.metaData,
2928 outError)) == null) {
2929 return null;
2930 }
2931 } else {
2932 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002933 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002934 + parser.getName() + " at " + mArchiveSourcePath + " "
2935 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 XmlUtils.skipCurrentTag(parser);
2937 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002938 } else {
2939 outError[0] = "Bad element under <service>: " + parser.getName();
2940 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002942 }
2943 }
2944
2945 if (!setExported) {
2946 s.info.exported = s.intents.size() > 0;
2947 }
2948
2949 return s;
2950 }
2951
2952 private boolean parseAllMetaData(Resources res,
2953 XmlPullParser parser, AttributeSet attrs, String tag,
2954 Component outInfo, String[] outError)
2955 throws XmlPullParserException, IOException {
2956 int outerDepth = parser.getDepth();
2957 int type;
2958 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2959 && (type != XmlPullParser.END_TAG
2960 || parser.getDepth() > outerDepth)) {
2961 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2962 continue;
2963 }
2964
2965 if (parser.getName().equals("meta-data")) {
2966 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
2967 outInfo.metaData, outError)) == null) {
2968 return false;
2969 }
2970 } else {
2971 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002972 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002973 + parser.getName() + " at " + mArchiveSourcePath + " "
2974 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002975 XmlUtils.skipCurrentTag(parser);
2976 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002977 } else {
2978 outError[0] = "Bad element under " + tag + ": " + parser.getName();
2979 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002981 }
2982 }
2983 return true;
2984 }
2985
2986 private Bundle parseMetaData(Resources res,
2987 XmlPullParser parser, AttributeSet attrs,
2988 Bundle data, String[] outError)
2989 throws XmlPullParserException, IOException {
2990
2991 TypedArray sa = res.obtainAttributes(attrs,
2992 com.android.internal.R.styleable.AndroidManifestMetaData);
2993
2994 if (data == null) {
2995 data = new Bundle();
2996 }
2997
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002998 String name = sa.getNonConfigurationString(
2999 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003000 if (name == null) {
3001 outError[0] = "<meta-data> requires an android:name attribute";
3002 sa.recycle();
3003 return null;
3004 }
3005
Dianne Hackborn854060a2009-07-09 18:14:31 -07003006 name = name.intern();
3007
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003008 TypedValue v = sa.peekValue(
3009 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
3010 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003011 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003012 data.putInt(name, v.resourceId);
3013 } else {
3014 v = sa.peekValue(
3015 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07003016 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003017 if (v != null) {
3018 if (v.type == TypedValue.TYPE_STRING) {
3019 CharSequence cs = v.coerceToString();
Dianne Hackborn854060a2009-07-09 18:14:31 -07003020 data.putString(name, cs != null ? cs.toString().intern() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
3022 data.putBoolean(name, v.data != 0);
3023 } else if (v.type >= TypedValue.TYPE_FIRST_INT
3024 && v.type <= TypedValue.TYPE_LAST_INT) {
3025 data.putInt(name, v.data);
3026 } else if (v.type == TypedValue.TYPE_FLOAT) {
3027 data.putFloat(name, v.getFloat());
3028 } else {
3029 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003030 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003031 + parser.getName() + " at " + mArchiveSourcePath + " "
3032 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003033 } else {
3034 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
3035 data = null;
3036 }
3037 }
3038 } else {
3039 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
3040 data = null;
3041 }
3042 }
3043
3044 sa.recycle();
3045
3046 XmlUtils.skipCurrentTag(parser);
3047
3048 return data;
3049 }
3050
Kenny Root05ca4c92011-09-15 10:36:25 -07003051 private static VerifierInfo parseVerifier(Resources res, XmlPullParser parser,
3052 AttributeSet attrs, int flags, String[] outError) throws XmlPullParserException,
3053 IOException {
3054 final TypedArray sa = res.obtainAttributes(attrs,
3055 com.android.internal.R.styleable.AndroidManifestPackageVerifier);
3056
3057 final String packageName = sa.getNonResourceString(
3058 com.android.internal.R.styleable.AndroidManifestPackageVerifier_name);
3059
3060 final String encodedPublicKey = sa.getNonResourceString(
3061 com.android.internal.R.styleable.AndroidManifestPackageVerifier_publicKey);
3062
3063 sa.recycle();
3064
3065 if (packageName == null || packageName.length() == 0) {
3066 Slog.i(TAG, "verifier package name was null; skipping");
3067 return null;
3068 } else if (encodedPublicKey == null) {
3069 Slog.i(TAG, "verifier " + packageName + " public key was null; skipping");
3070 }
3071
Geremy Condraf1bcca82013-01-07 22:35:24 -08003072 PublicKey publicKey = parsePublicKey(encodedPublicKey);
3073 if (publicKey != null) {
3074 return new VerifierInfo(packageName, publicKey);
3075 }
3076
3077 return null;
3078 }
3079
3080 public static final PublicKey parsePublicKey(String encodedPublicKey) {
Kenny Root05ca4c92011-09-15 10:36:25 -07003081 EncodedKeySpec keySpec;
3082 try {
3083 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
3084 keySpec = new X509EncodedKeySpec(encoded);
3085 } catch (IllegalArgumentException e) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08003086 Slog.i(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07003087 return null;
3088 }
3089
3090 /* First try the key as an RSA key. */
3091 try {
3092 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08003093 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07003094 } catch (NoSuchAlgorithmException e) {
3095 Log.wtf(TAG, "Could not parse public key because RSA isn't included in build");
3096 return null;
3097 } catch (InvalidKeySpecException e) {
3098 // Not a RSA public key.
3099 }
3100
3101 /* Now try it as a DSA key. */
3102 try {
3103 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08003104 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07003105 } catch (NoSuchAlgorithmException e) {
3106 Log.wtf(TAG, "Could not parse public key because DSA isn't included in build");
3107 return null;
3108 } catch (InvalidKeySpecException e) {
3109 // Not a DSA public key.
3110 }
3111
3112 return null;
3113 }
3114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003115 private static final String ANDROID_RESOURCES
3116 = "http://schemas.android.com/apk/res/android";
3117
3118 private boolean parseIntent(Resources res,
3119 XmlPullParser parser, AttributeSet attrs, int flags,
3120 IntentInfo outInfo, String[] outError, boolean isActivity)
3121 throws XmlPullParserException, IOException {
3122
3123 TypedArray sa = res.obtainAttributes(attrs,
3124 com.android.internal.R.styleable.AndroidManifestIntentFilter);
3125
3126 int priority = sa.getInt(
3127 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003128 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08003129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003130 TypedValue v = sa.peekValue(
3131 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
3132 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
3133 outInfo.nonLocalizedLabel = v.coerceToString();
3134 }
3135
3136 outInfo.icon = sa.getResourceId(
3137 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
Adam Powell81cd2e92010-04-21 16:35:18 -07003138
3139 outInfo.logo = sa.getResourceId(
3140 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003141
3142 sa.recycle();
3143
3144 int outerDepth = parser.getDepth();
3145 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07003146 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3147 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
3148 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003149 continue;
3150 }
3151
3152 String nodeName = parser.getName();
3153 if (nodeName.equals("action")) {
3154 String value = attrs.getAttributeValue(
3155 ANDROID_RESOURCES, "name");
3156 if (value == null || value == "") {
3157 outError[0] = "No value supplied for <android:name>";
3158 return false;
3159 }
3160 XmlUtils.skipCurrentTag(parser);
3161
3162 outInfo.addAction(value);
3163 } else if (nodeName.equals("category")) {
3164 String value = attrs.getAttributeValue(
3165 ANDROID_RESOURCES, "name");
3166 if (value == null || value == "") {
3167 outError[0] = "No value supplied for <android:name>";
3168 return false;
3169 }
3170 XmlUtils.skipCurrentTag(parser);
3171
3172 outInfo.addCategory(value);
3173
3174 } else if (nodeName.equals("data")) {
3175 sa = res.obtainAttributes(attrs,
3176 com.android.internal.R.styleable.AndroidManifestData);
3177
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003178 String str = sa.getNonConfigurationString(
3179 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180 if (str != null) {
3181 try {
3182 outInfo.addDataType(str);
3183 } catch (IntentFilter.MalformedMimeTypeException e) {
3184 outError[0] = e.toString();
3185 sa.recycle();
3186 return false;
3187 }
3188 }
3189
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003190 str = sa.getNonConfigurationString(
3191 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003192 if (str != null) {
3193 outInfo.addDataScheme(str);
3194 }
3195
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003196 String host = sa.getNonConfigurationString(
3197 com.android.internal.R.styleable.AndroidManifestData_host, 0);
3198 String port = sa.getNonConfigurationString(
3199 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003200 if (host != null) {
3201 outInfo.addDataAuthority(host, port);
3202 }
3203
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003204 str = sa.getNonConfigurationString(
3205 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003206 if (str != null) {
3207 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
3208 }
3209
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003210 str = sa.getNonConfigurationString(
3211 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003212 if (str != null) {
3213 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
3214 }
3215
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003216 str = sa.getNonConfigurationString(
3217 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003218 if (str != null) {
3219 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
3220 }
3221
3222 sa.recycle();
3223 XmlUtils.skipCurrentTag(parser);
3224 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003225 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003226 + parser.getName() + " at " + mArchiveSourcePath + " "
3227 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003228 XmlUtils.skipCurrentTag(parser);
3229 } else {
3230 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
3231 return false;
3232 }
3233 }
3234
3235 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07003236
3237 if (DEBUG_PARSER) {
3238 final StringBuilder cats = new StringBuilder("Intent d=");
3239 cats.append(outInfo.hasDefault);
3240 cats.append(", cat=");
3241
3242 final Iterator<String> it = outInfo.categoriesIterator();
3243 if (it != null) {
3244 while (it.hasNext()) {
3245 cats.append(' ');
3246 cats.append(it.next());
3247 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 }
Kenny Rootd2d29252011-08-08 11:27:57 -07003249 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003250 }
3251
3252 return true;
3253 }
3254
3255 public final static class Package {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003256 public String packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003257
3258 // For now we only support one application per package.
3259 public final ApplicationInfo applicationInfo = new ApplicationInfo();
3260
3261 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
3262 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
3263 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
3264 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
3265 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
3266 public final ArrayList<Service> services = new ArrayList<Service>(0);
3267 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
3268
3269 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
Dianne Hackborne639da72012-02-21 15:11:13 -08003270 public final ArrayList<Boolean> requestedPermissionsRequired = new ArrayList<Boolean>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003271
Dianne Hackborn854060a2009-07-09 18:14:31 -07003272 public ArrayList<String> protectedBroadcasts;
3273
Dianne Hackborn49237342009-08-27 20:08:01 -07003274 public ArrayList<String> usesLibraries = null;
3275 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003276 public String[] usesLibraryFiles = null;
3277
Dianne Hackbornc1552392010-03-03 16:19:01 -08003278 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003279 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003280 public ArrayList<String> mAdoptPermissions = null;
3281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003282 // We store the application meta-data independently to avoid multiple unwanted references
3283 public Bundle mAppMetaData = null;
3284
3285 // If this is a 3rd party app, this is the path of the zip file.
3286 public String mPath;
3287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003288 // The version code declared for this package.
3289 public int mVersionCode;
3290
3291 // The version name declared for this package.
3292 public String mVersionName;
3293
3294 // The shared user id that this package wants to use.
3295 public String mSharedUserId;
3296
3297 // The shared user label that this package wants to use.
3298 public int mSharedUserLabel;
3299
3300 // Signatures that were read from the package.
3301 public Signature mSignatures[];
3302
3303 // For use by package manager service for quick lookup of
3304 // preferred up order.
3305 public int mPreferredOrder = 0;
3306
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003307 // For use by the package manager to keep track of the path to the
3308 // file an app came from.
3309 public String mScanPath;
3310
3311 // For use by package manager to keep track of where it has done dexopt.
3312 public boolean mDidDexOpt;
3313
Amith Yamasani13593602012-03-22 16:16:17 -07003314 // // User set enabled state.
3315 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
3316 //
3317 // // Whether the package has been stopped.
3318 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08003319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003320 // Additional data supplied by callers.
3321 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07003322
3323 // Whether an operation is currently pending on this package
3324 public boolean mOperationPending;
3325
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003326 /*
3327 * Applications hardware preferences
3328 */
3329 public final ArrayList<ConfigurationInfo> configPreferences =
3330 new ArrayList<ConfigurationInfo>();
3331
Dianne Hackborn49237342009-08-27 20:08:01 -07003332 /*
3333 * Applications requested features
3334 */
3335 public ArrayList<FeatureInfo> reqFeatures = null;
3336
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08003337 public int installLocation;
3338
Kenny Rootbcc954d2011-08-08 16:19:08 -07003339 /**
3340 * Digest suitable for comparing whether this package's manifest is the
3341 * same as another.
3342 */
3343 public ManifestDigest manifestDigest;
3344
Geremy Condraf1bcca82013-01-07 22:35:24 -08003345 /**
3346 * Data used to feed the KeySetManager
3347 */
3348 public Set<PublicKey> mSigningKeys;
3349 public Map<String, Set<PublicKey>> mKeySetMapping;
3350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003351 public Package(String _name) {
3352 packageName = _name;
3353 applicationInfo.packageName = _name;
3354 applicationInfo.uid = -1;
3355 }
3356
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003357 public void setPackageName(String newName) {
3358 packageName = newName;
3359 applicationInfo.packageName = newName;
3360 for (int i=permissions.size()-1; i>=0; i--) {
3361 permissions.get(i).setPackageName(newName);
3362 }
3363 for (int i=permissionGroups.size()-1; i>=0; i--) {
3364 permissionGroups.get(i).setPackageName(newName);
3365 }
3366 for (int i=activities.size()-1; i>=0; i--) {
3367 activities.get(i).setPackageName(newName);
3368 }
3369 for (int i=receivers.size()-1; i>=0; i--) {
3370 receivers.get(i).setPackageName(newName);
3371 }
3372 for (int i=providers.size()-1; i>=0; i--) {
3373 providers.get(i).setPackageName(newName);
3374 }
3375 for (int i=services.size()-1; i>=0; i--) {
3376 services.get(i).setPackageName(newName);
3377 }
3378 for (int i=instrumentation.size()-1; i>=0; i--) {
3379 instrumentation.get(i).setPackageName(newName);
3380 }
3381 }
Dianne Hackborn65696252012-03-05 18:49:21 -08003382
3383 public boolean hasComponentClassName(String name) {
3384 for (int i=activities.size()-1; i>=0; i--) {
3385 if (name.equals(activities.get(i).className)) {
3386 return true;
3387 }
3388 }
3389 for (int i=receivers.size()-1; i>=0; i--) {
3390 if (name.equals(receivers.get(i).className)) {
3391 return true;
3392 }
3393 }
3394 for (int i=providers.size()-1; i>=0; i--) {
3395 if (name.equals(providers.get(i).className)) {
3396 return true;
3397 }
3398 }
3399 for (int i=services.size()-1; i>=0; i--) {
3400 if (name.equals(services.get(i).className)) {
3401 return true;
3402 }
3403 }
3404 for (int i=instrumentation.size()-1; i>=0; i--) {
3405 if (name.equals(instrumentation.get(i).className)) {
3406 return true;
3407 }
3408 }
3409 return false;
3410 }
3411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003412 public String toString() {
3413 return "Package{"
3414 + Integer.toHexString(System.identityHashCode(this))
3415 + " " + packageName + "}";
3416 }
3417 }
3418
3419 public static class Component<II extends IntentInfo> {
3420 public final Package owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003421 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003422 public final String className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003423 public Bundle metaData;
3424
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003425 ComponentName componentName;
3426 String componentShortName;
3427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003428 public Component(Package _owner) {
3429 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003430 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003431 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003432 }
3433
3434 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
3435 owner = args.owner;
3436 intents = new ArrayList<II>(0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003437 String name = args.sa.getNonConfigurationString(args.nameRes, 0);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003438 if (name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003439 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003440 args.outError[0] = args.tag + " does not specify android:name";
3441 return;
3442 }
3443
3444 outInfo.name
3445 = buildClassName(owner.applicationInfo.packageName, name, args.outError);
3446 if (outInfo.name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003447 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003448 args.outError[0] = args.tag + " does not have valid android:name";
3449 return;
3450 }
3451
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003452 className = outInfo.name;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003453
3454 int iconVal = args.sa.getResourceId(args.iconRes, 0);
3455 if (iconVal != 0) {
3456 outInfo.icon = iconVal;
3457 outInfo.nonLocalizedLabel = null;
3458 }
Adam Powell81cd2e92010-04-21 16:35:18 -07003459
3460 int logoVal = args.sa.getResourceId(args.logoRes, 0);
3461 if (logoVal != 0) {
3462 outInfo.logo = logoVal;
3463 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003464
3465 TypedValue v = args.sa.peekValue(args.labelRes);
3466 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
3467 outInfo.nonLocalizedLabel = v.coerceToString();
3468 }
3469
3470 outInfo.packageName = owner.packageName;
3471 }
3472
3473 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
3474 this(args, (PackageItemInfo)outInfo);
3475 if (args.outError[0] != null) {
3476 return;
3477 }
3478
3479 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003480 CharSequence pname;
3481 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3482 pname = args.sa.getNonConfigurationString(args.processRes, 0);
3483 } else {
3484 // Some older apps have been seen to use a resource reference
3485 // here that on older builds was ignored (with a warning). We
3486 // need to continue to do this for them so they don't break.
3487 pname = args.sa.getNonResourceString(args.processRes);
3488 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003489 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003490 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003491 args.flags, args.sepProcesses, args.outError);
3492 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003493
3494 if (args.descriptionRes != 0) {
3495 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
3496 }
3497
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003498 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003499 }
3500
3501 public Component(Component<II> clone) {
3502 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003503 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003504 className = clone.className;
3505 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003506 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003507 }
3508
3509 public ComponentName getComponentName() {
3510 if (componentName != null) {
3511 return componentName;
3512 }
3513 if (className != null) {
3514 componentName = new ComponentName(owner.applicationInfo.packageName,
3515 className);
3516 }
3517 return componentName;
3518 }
3519
3520 public String getComponentShortName() {
3521 if (componentShortName != null) {
3522 return componentShortName;
3523 }
3524 ComponentName component = getComponentName();
3525 if (component != null) {
3526 componentShortName = component.flattenToShortString();
3527 }
3528 return componentShortName;
3529 }
3530
3531 public void setPackageName(String packageName) {
3532 componentName = null;
3533 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003534 }
3535 }
3536
3537 public final static class Permission extends Component<IntentInfo> {
3538 public final PermissionInfo info;
3539 public boolean tree;
3540 public PermissionGroup group;
3541
3542 public Permission(Package _owner) {
3543 super(_owner);
3544 info = new PermissionInfo();
3545 }
3546
3547 public Permission(Package _owner, PermissionInfo _info) {
3548 super(_owner);
3549 info = _info;
3550 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003551
3552 public void setPackageName(String packageName) {
3553 super.setPackageName(packageName);
3554 info.packageName = packageName;
3555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556
3557 public String toString() {
3558 return "Permission{"
3559 + Integer.toHexString(System.identityHashCode(this))
3560 + " " + info.name + "}";
3561 }
3562 }
3563
3564 public final static class PermissionGroup extends Component<IntentInfo> {
3565 public final PermissionGroupInfo info;
3566
3567 public PermissionGroup(Package _owner) {
3568 super(_owner);
3569 info = new PermissionGroupInfo();
3570 }
3571
3572 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
3573 super(_owner);
3574 info = _info;
3575 }
3576
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003577 public void setPackageName(String packageName) {
3578 super.setPackageName(packageName);
3579 info.packageName = packageName;
3580 }
3581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003582 public String toString() {
3583 return "PermissionGroup{"
3584 + Integer.toHexString(System.identityHashCode(this))
3585 + " " + info.name + "}";
3586 }
3587 }
3588
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003589 private static boolean copyNeeded(int flags, Package p,
3590 PackageUserState state, Bundle metaData, int userId) {
3591 if (userId != 0) {
3592 // We always need to copy for other users, since we need
3593 // to fix up the uid.
3594 return true;
3595 }
3596 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
3597 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07003598 if (p.applicationInfo.enabled != enabled) {
3599 return true;
3600 }
3601 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003602 if (!state.installed) {
3603 return true;
3604 }
3605 if (state.stopped) {
3606 return true;
3607 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003608 if ((flags & PackageManager.GET_META_DATA) != 0
3609 && (metaData != null || p.mAppMetaData != null)) {
3610 return true;
3611 }
3612 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
3613 && p.usesLibraryFiles != null) {
3614 return true;
3615 }
3616 return false;
3617 }
3618
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003619 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
3620 PackageUserState state) {
3621 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07003622 }
3623
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08003624 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
3625 PackageUserState state) {
3626 // CompatibilityMode is global state.
3627 if (!sCompatibilityModeEnabled) {
3628 ai.disableCompatibilityMode();
3629 }
3630 if (state.installed) {
3631 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
3632 } else {
3633 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
3634 }
3635 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
3636 ai.enabled = true;
3637 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
3638 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
3639 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
3640 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
3641 ai.enabled = false;
3642 }
3643 ai.enabledSetting = state.enabled;
3644 }
3645
Amith Yamasani13593602012-03-22 16:16:17 -07003646 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003647 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003648 if (p == null) return null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003649 if (!checkUseInstalled(flags, state)) {
3650 return null;
3651 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08003652 if (!copyNeeded(flags, p, state, null, userId)
3653 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
3654 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
3655 // In this case it is safe to directly modify the internal ApplicationInfo state:
3656 // - CompatibilityMode is global state, so will be the same for every call.
3657 // - We only come in to here if the app should reported as installed; this is the
3658 // default state, and we will do a copy otherwise.
3659 // - The enable state will always be reported the same for the application across
3660 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
3661 // be doing a copy.
3662 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663 return p.applicationInfo;
3664 }
3665
3666 // Make shallow copy so we can store the metadata/libraries safely
3667 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Amith Yamasani742a6712011-05-04 14:49:28 -07003668 if (userId != 0) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07003669 ai.uid = UserHandle.getUid(userId, ai.uid);
Amith Yamasani742a6712011-05-04 14:49:28 -07003670 ai.dataDir = PackageManager.getDataDirForUser(userId, ai.packageName);
3671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 if ((flags & PackageManager.GET_META_DATA) != 0) {
3673 ai.metaData = p.mAppMetaData;
3674 }
3675 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
3676 ai.sharedLibraryFiles = p.usesLibraryFiles;
3677 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003678 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07003679 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08003680 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07003681 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08003682 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08003683 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003684 return ai;
3685 }
3686
3687 public static final PermissionInfo generatePermissionInfo(
3688 Permission p, int flags) {
3689 if (p == null) return null;
3690 if ((flags&PackageManager.GET_META_DATA) == 0) {
3691 return p.info;
3692 }
3693 PermissionInfo pi = new PermissionInfo(p.info);
3694 pi.metaData = p.metaData;
3695 return pi;
3696 }
3697
3698 public static final PermissionGroupInfo generatePermissionGroupInfo(
3699 PermissionGroup pg, int flags) {
3700 if (pg == null) return null;
3701 if ((flags&PackageManager.GET_META_DATA) == 0) {
3702 return pg.info;
3703 }
3704 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
3705 pgi.metaData = pg.metaData;
3706 return pgi;
3707 }
3708
3709 public final static class Activity extends Component<ActivityIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003710 public final ActivityInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003711
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003712 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
3713 super(args, _info);
3714 info = _info;
3715 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003716 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003717
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003718 public void setPackageName(String packageName) {
3719 super.setPackageName(packageName);
3720 info.packageName = packageName;
3721 }
3722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003723 public String toString() {
3724 return "Activity{"
3725 + Integer.toHexString(System.identityHashCode(this))
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003726 + " " + getComponentShortName() + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003727 }
3728 }
3729
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003730 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
3731 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003732 if (a == null) return null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003733 if (!checkUseInstalled(flags, state)) {
3734 return null;
3735 }
3736 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003737 return a.info;
3738 }
3739 // Make shallow copies so we can store the metadata safely
3740 ActivityInfo ai = new ActivityInfo(a.info);
3741 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003742 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003743 return ai;
3744 }
3745
3746 public final static class Service extends Component<ServiceIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003747 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003748
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003749 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
3750 super(args, _info);
3751 info = _info;
3752 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003753 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003754
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003755 public void setPackageName(String packageName) {
3756 super.setPackageName(packageName);
3757 info.packageName = packageName;
3758 }
3759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003760 public String toString() {
3761 return "Service{"
3762 + Integer.toHexString(System.identityHashCode(this))
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003763 + " " + getComponentShortName() + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 }
3765 }
3766
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003767 public static final ServiceInfo generateServiceInfo(Service s, int flags,
3768 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003769 if (s == null) return null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003770 if (!checkUseInstalled(flags, state)) {
3771 return null;
3772 }
3773 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003774 return s.info;
3775 }
3776 // Make shallow copies so we can store the metadata safely
3777 ServiceInfo si = new ServiceInfo(s.info);
3778 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003779 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003780 return si;
3781 }
3782
3783 public final static class Provider extends Component {
3784 public final ProviderInfo info;
3785 public boolean syncable;
3786
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003787 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
3788 super(args, _info);
3789 info = _info;
3790 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003791 syncable = false;
3792 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 public Provider(Provider existingProvider) {
3795 super(existingProvider);
3796 this.info = existingProvider.info;
3797 this.syncable = existingProvider.syncable;
3798 }
3799
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003800 public void setPackageName(String packageName) {
3801 super.setPackageName(packageName);
3802 info.packageName = packageName;
3803 }
3804
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 public String toString() {
3806 return "Provider{"
3807 + Integer.toHexString(System.identityHashCode(this))
3808 + " " + info.name + "}";
3809 }
3810 }
3811
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003812 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
3813 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 if (p == null) return null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003815 if (!checkUseInstalled(flags, state)) {
3816 return null;
3817 }
3818 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003820 || p.info.uriPermissionPatterns == null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 return p.info;
3822 }
3823 // Make shallow copies so we can store the metadata safely
3824 ProviderInfo pi = new ProviderInfo(p.info);
3825 pi.metaData = p.metaData;
3826 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
3827 pi.uriPermissionPatterns = null;
3828 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003829 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 return pi;
3831 }
3832
3833 public final static class Instrumentation extends Component {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003834 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003836 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
3837 super(args, _info);
3838 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003839 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003840
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003841 public void setPackageName(String packageName) {
3842 super.setPackageName(packageName);
3843 info.packageName = packageName;
3844 }
3845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003846 public String toString() {
3847 return "Instrumentation{"
3848 + Integer.toHexString(System.identityHashCode(this))
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003849 + " " + getComponentShortName() + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003850 }
3851 }
3852
3853 public static final InstrumentationInfo generateInstrumentationInfo(
3854 Instrumentation i, int flags) {
3855 if (i == null) return null;
3856 if ((flags&PackageManager.GET_META_DATA) == 0) {
3857 return i.info;
3858 }
3859 InstrumentationInfo ii = new InstrumentationInfo(i.info);
3860 ii.metaData = i.metaData;
3861 return ii;
3862 }
3863
3864 public static class IntentInfo extends IntentFilter {
3865 public boolean hasDefault;
3866 public int labelRes;
3867 public CharSequence nonLocalizedLabel;
3868 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07003869 public int logo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870 }
3871
3872 public final static class ActivityIntentInfo extends IntentInfo {
3873 public final Activity activity;
3874
3875 public ActivityIntentInfo(Activity _activity) {
3876 activity = _activity;
3877 }
3878
3879 public String toString() {
3880 return "ActivityIntentInfo{"
3881 + Integer.toHexString(System.identityHashCode(this))
3882 + " " + activity.info.name + "}";
3883 }
3884 }
3885
3886 public final static class ServiceIntentInfo extends IntentInfo {
3887 public final Service service;
3888
3889 public ServiceIntentInfo(Service _service) {
3890 service = _service;
3891 }
3892
3893 public String toString() {
3894 return "ServiceIntentInfo{"
3895 + Integer.toHexString(System.identityHashCode(this))
3896 + " " + service.info.name + "}";
3897 }
3898 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07003899
3900 /**
3901 * @hide
3902 */
3903 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
3904 sCompatibilityModeEnabled = compatibilityModeEnabled;
3905 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003906}