blob: faee873a5660856a5e44d10af7ff82b49c8b3490 [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;
Amith Yamasani742a6712011-05-04 14:49:28 -070031import android.os.UserId;
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;
Kenny Root05ca4c92011-09-15 10:36:25 -070049import java.security.spec.EncodedKeySpec;
50import java.security.spec.InvalidKeySpecException;
51import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import java.util.ArrayList;
53import java.util.Enumeration;
54import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -070055import java.util.List;
Kenny Rootbcc954d2011-08-08 16:19:08 -070056import java.util.jar.Attributes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import java.util.jar.JarEntry;
58import java.util.jar.JarFile;
Kenny Rootd2d29252011-08-08 11:27:57 -070059import java.util.jar.Manifest;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060
Amith Yamasani742a6712011-05-04 14:49:28 -070061import com.android.internal.util.XmlUtils;
62
63import org.xmlpull.v1.XmlPullParser;
64import org.xmlpull.v1.XmlPullParserException;
65
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066/**
67 * Package archive parsing
68 *
69 * {@hide}
70 */
71public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -070072 private static final boolean DEBUG_JAR = false;
73 private static final boolean DEBUG_PARSER = false;
74 private static final boolean DEBUG_BACKUP = false;
75
Kenny Rootbcc954d2011-08-08 16:19:08 -070076 /** File name in an APK for the Android manifest. */
77 private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
78
Dianne Hackborna96cbb42009-05-13 15:06:13 -070079 /** @hide */
80 public static class NewPermissionInfo {
81 public final String name;
82 public final int sdkVersion;
83 public final int fileVersion;
84
85 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
86 this.name = name;
87 this.sdkVersion = sdkVersion;
88 this.fileVersion = fileVersion;
89 }
90 }
91
92 /**
93 * List of new permissions that have been added since 1.0.
94 * NOTE: These must be declared in SDK version order, with permissions
95 * added to older SDKs appearing before those added to newer SDKs.
96 * @hide
97 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -070098 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
99 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700100 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700101 android.os.Build.VERSION_CODES.DONUT, 0),
102 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
103 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700104 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105
106 private String mArchiveSourcePath;
107 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700108 private boolean mOnlyCoreApps;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700109 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
110 private static final String SDK_CODENAME = "REL".equals(Build.VERSION.CODENAME)
111 ? null : Build.VERSION.CODENAME;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112
113 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
114
115 private static final Object mSync = new Object();
116 private static WeakReference<byte[]> mReadBuffer;
117
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700118 private static boolean sCompatibilityModeEnabled = true;
119 private static final int PARSE_DEFAULT_INSTALL_LOCATION = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700120
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700121 static class ParsePackageItemArgs {
122 final Package owner;
123 final String[] outError;
124 final int nameRes;
125 final int labelRes;
126 final int iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700127 final int logoRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700128
129 String tag;
130 TypedArray sa;
131
132 ParsePackageItemArgs(Package _owner, String[] _outError,
Adam Powell81cd2e92010-04-21 16:35:18 -0700133 int _nameRes, int _labelRes, int _iconRes, int _logoRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700134 owner = _owner;
135 outError = _outError;
136 nameRes = _nameRes;
137 labelRes = _labelRes;
138 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700139 logoRes = _logoRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700140 }
141 }
142
143 static class ParseComponentArgs extends ParsePackageItemArgs {
144 final String[] sepProcesses;
145 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800146 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700147 final int enabledRes;
148 int flags;
149
150 ParseComponentArgs(Package _owner, String[] _outError,
Adam Powell81cd2e92010-04-21 16:35:18 -0700151 int _nameRes, int _labelRes, int _iconRes, int _logoRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800152 String[] _sepProcesses, int _processRes,
153 int _descriptionRes, int _enabledRes) {
Adam Powell81cd2e92010-04-21 16:35:18 -0700154 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _logoRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700155 sepProcesses = _sepProcesses;
156 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800157 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700158 enabledRes = _enabledRes;
159 }
160 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800161
162 /* Light weight package info.
163 * @hide
164 */
165 public static class PackageLite {
Kenny Root05ca4c92011-09-15 10:36:25 -0700166 public final String packageName;
167 public final int installLocation;
168 public final VerifierInfo[] verifiers;
169
170 public PackageLite(String packageName, int installLocation, List<VerifierInfo> verifiers) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800171 this.packageName = packageName;
172 this.installLocation = installLocation;
Kenny Root05ca4c92011-09-15 10:36:25 -0700173 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800174 }
175 }
176
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700177 private ParsePackageItemArgs mParseInstrumentationArgs;
178 private ParseComponentArgs mParseActivityArgs;
179 private ParseComponentArgs mParseActivityAliasArgs;
180 private ParseComponentArgs mParseServiceArgs;
181 private ParseComponentArgs mParseProviderArgs;
182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 /** If set to true, we will only allow package files that exactly match
184 * the DTD. Otherwise, we try to get as much from the package as we
185 * can without failing. This should normally be set to false, to
186 * support extensions to the DTD in future versions. */
187 private static final boolean RIGID_PARSER = false;
188
189 private static final String TAG = "PackageParser";
190
191 public PackageParser(String archiveSourcePath) {
192 mArchiveSourcePath = archiveSourcePath;
193 }
194
195 public void setSeparateProcesses(String[] procs) {
196 mSeparateProcesses = procs;
197 }
198
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700199 public void setOnlyCoreApps(boolean onlyCoreApps) {
200 mOnlyCoreApps = onlyCoreApps;
201 }
202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 private static final boolean isPackageFilename(String name) {
204 return name.endsWith(".apk");
205 }
206
207 /**
208 * Generate and return the {@link PackageInfo} for a parsed package.
209 *
210 * @param p the parsed package.
211 * @param flags indicating which optional information is included.
212 */
213 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborn78d68832010-10-07 01:12:46 -0700214 int gids[], int flags, long firstInstallTime, long lastUpdateTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215
Amith Yamasani742a6712011-05-04 14:49:28 -0700216 final int userId = Binder.getOrigCallingUser();
217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 PackageInfo pi = new PackageInfo();
219 pi.packageName = p.packageName;
220 pi.versionCode = p.mVersionCode;
221 pi.versionName = p.mVersionName;
222 pi.sharedUserId = p.mSharedUserId;
223 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborne4a59512010-12-07 11:08:07 -0800224 pi.applicationInfo = generateApplicationInfo(p, flags);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800225 pi.installLocation = p.installLocation;
Dianne Hackborn78d68832010-10-07 01:12:46 -0700226 pi.firstInstallTime = firstInstallTime;
227 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 if ((flags&PackageManager.GET_GIDS) != 0) {
229 pi.gids = gids;
230 }
231 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
232 int N = p.configPreferences.size();
233 if (N > 0) {
234 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700235 p.configPreferences.toArray(pi.configPreferences);
236 }
237 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
238 if (N > 0) {
239 pi.reqFeatures = new FeatureInfo[N];
240 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 }
242 }
243 if ((flags&PackageManager.GET_ACTIVITIES) != 0) {
244 int N = p.activities.size();
245 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700246 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
247 pi.activities = new ActivityInfo[N];
248 } else {
249 int num = 0;
250 for (int i=0; i<N; i++) {
251 if (p.activities.get(i).info.enabled) num++;
252 }
253 pi.activities = new ActivityInfo[num];
254 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700255 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 final Activity activity = p.activities.get(i);
257 if (activity.info.enabled
258 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700259 pi.activities[j++] = generateActivityInfo(p.activities.get(i), flags,
260 userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 }
262 }
263 }
264 }
265 if ((flags&PackageManager.GET_RECEIVERS) != 0) {
266 int N = p.receivers.size();
267 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700268 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
269 pi.receivers = new ActivityInfo[N];
270 } else {
271 int num = 0;
272 for (int i=0; i<N; i++) {
273 if (p.receivers.get(i).info.enabled) num++;
274 }
275 pi.receivers = new ActivityInfo[num];
276 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700277 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 final Activity activity = p.receivers.get(i);
279 if (activity.info.enabled
280 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700281 pi.receivers[j++] = generateActivityInfo(p.receivers.get(i), flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 }
283 }
284 }
285 }
286 if ((flags&PackageManager.GET_SERVICES) != 0) {
287 int N = p.services.size();
288 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700289 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
290 pi.services = new ServiceInfo[N];
291 } else {
292 int num = 0;
293 for (int i=0; i<N; i++) {
294 if (p.services.get(i).info.enabled) num++;
295 }
296 pi.services = new ServiceInfo[num];
297 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700298 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 final Service service = p.services.get(i);
300 if (service.info.enabled
301 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700302 pi.services[j++] = generateServiceInfo(p.services.get(i), flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 }
304 }
305 }
306 }
307 if ((flags&PackageManager.GET_PROVIDERS) != 0) {
308 int N = p.providers.size();
309 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700310 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
311 pi.providers = new ProviderInfo[N];
312 } else {
313 int num = 0;
314 for (int i=0; i<N; i++) {
315 if (p.providers.get(i).info.enabled) num++;
316 }
317 pi.providers = new ProviderInfo[num];
318 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700319 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 final Provider provider = p.providers.get(i);
321 if (provider.info.enabled
322 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700323 pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324 }
325 }
326 }
327 }
328 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
329 int N = p.instrumentation.size();
330 if (N > 0) {
331 pi.instrumentation = new InstrumentationInfo[N];
332 for (int i=0; i<N; i++) {
333 pi.instrumentation[i] = generateInstrumentationInfo(
334 p.instrumentation.get(i), flags);
335 }
336 }
337 }
338 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
339 int N = p.permissions.size();
340 if (N > 0) {
341 pi.permissions = new PermissionInfo[N];
342 for (int i=0; i<N; i++) {
343 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
344 }
345 }
346 N = p.requestedPermissions.size();
347 if (N > 0) {
348 pi.requestedPermissions = new String[N];
349 for (int i=0; i<N; i++) {
350 pi.requestedPermissions[i] = p.requestedPermissions.get(i);
351 }
352 }
353 }
354 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700355 int N = (p.mSignatures != null) ? p.mSignatures.length : 0;
356 if (N > 0) {
357 pi.signatures = new Signature[N];
358 System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 }
360 }
361 return pi;
362 }
363
364 private Certificate[] loadCertificates(JarFile jarFile, JarEntry je,
365 byte[] readBuffer) {
366 try {
367 // We must read the stream for the JarEntry to retrieve
368 // its certificates.
Kenny Rootd63f7db2010-09-27 08:07:48 -0700369 InputStream is = new BufferedInputStream(jarFile.getInputStream(je));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 while (is.read(readBuffer, 0, readBuffer.length) != -1) {
371 // not using
372 }
373 is.close();
374 return je != null ? je.getCertificates() : null;
375 } catch (IOException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700376 Slog.w(TAG, "Exception reading " + je.getName() + " in "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 + jarFile.getName(), e);
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -0700378 } catch (RuntimeException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700379 Slog.w(TAG, "Exception reading " + je.getName() + " in "
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -0700380 + jarFile.getName(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 }
382 return null;
383 }
384
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800385 public final static int PARSE_IS_SYSTEM = 1<<0;
386 public final static int PARSE_CHATTY = 1<<1;
387 public final static int PARSE_MUST_BE_APK = 1<<2;
388 public final static int PARSE_IGNORE_PROCESSES = 1<<3;
389 public final static int PARSE_FORWARD_LOCK = 1<<4;
390 public final static int PARSE_ON_SDCARD = 1<<5;
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700391 public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392
393 public int getParseError() {
394 return mParseError;
395 }
396
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800397 public Package parsePackage(File sourceFile, String destCodePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 DisplayMetrics metrics, int flags) {
399 mParseError = PackageManager.INSTALL_SUCCEEDED;
400
401 mArchiveSourcePath = sourceFile.getPath();
402 if (!sourceFile.isFile()) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700403 Slog.w(TAG, "Skipping dir: " + mArchiveSourcePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
405 return null;
406 }
407 if (!isPackageFilename(sourceFile.getName())
408 && (flags&PARSE_MUST_BE_APK) != 0) {
409 if ((flags&PARSE_IS_SYSTEM) == 0) {
410 // We expect to have non-.apk files in the system dir,
411 // so don't warn about them.
Kenny Rootd2d29252011-08-08 11:27:57 -0700412 Slog.w(TAG, "Skipping non-package file: " + mArchiveSourcePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 }
414 mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
415 return null;
416 }
417
Kenny Rootd2d29252011-08-08 11:27:57 -0700418 if (DEBUG_JAR)
419 Slog.d(TAG, "Scanning package: " + mArchiveSourcePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420
421 XmlResourceParser parser = null;
422 AssetManager assmgr = null;
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800423 Resources res = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800424 boolean assetError = true;
425 try {
426 assmgr = new AssetManager();
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700427 int cookie = assmgr.addAssetPath(mArchiveSourcePath);
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800428 if (cookie != 0) {
429 res = new Resources(assmgr, metrics, null);
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700430 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 -0800431 Build.VERSION.RESOURCES_SDK_INT);
Kenny Rootbcc954d2011-08-08 16:19:08 -0700432 parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 assetError = false;
434 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -0700435 Slog.w(TAG, "Failed adding asset path:"+mArchiveSourcePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 }
437 } catch (Exception e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700438 Slog.w(TAG, "Unable to read AndroidManifest.xml of "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 + mArchiveSourcePath, e);
440 }
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800441 if (assetError) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 if (assmgr != null) assmgr.close();
443 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
444 return null;
445 }
446 String[] errorText = new String[1];
447 Package pkg = null;
448 Exception errorException = null;
449 try {
450 // XXXX todo: need to figure out correct configuration.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451 pkg = parsePackage(res, parser, flags, errorText);
452 } catch (Exception e) {
453 errorException = e;
454 mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
455 }
456
457
458 if (pkg == null) {
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700459 // If we are only parsing core apps, then a null with INSTALL_SUCCEEDED
460 // just means to skip this app so don't make a fuss about it.
461 if (!mOnlyCoreApps || mParseError != PackageManager.INSTALL_SUCCEEDED) {
462 if (errorException != null) {
463 Slog.w(TAG, mArchiveSourcePath, errorException);
464 } else {
465 Slog.w(TAG, mArchiveSourcePath + " (at "
466 + parser.getPositionDescription()
467 + "): " + errorText[0]);
468 }
469 if (mParseError == PackageManager.INSTALL_SUCCEEDED) {
470 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
471 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800472 }
473 parser.close();
474 assmgr.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 return null;
476 }
477
478 parser.close();
479 assmgr.close();
480
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800481 // Set code and resource paths
482 pkg.mPath = destCodePath;
483 pkg.mScanPath = mArchiveSourcePath;
484 //pkg.applicationInfo.sourceDir = destCodePath;
485 //pkg.applicationInfo.publicSourceDir = destRes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 pkg.mSignatures = null;
487
488 return pkg;
489 }
490
491 public boolean collectCertificates(Package pkg, int flags) {
492 pkg.mSignatures = null;
493
494 WeakReference<byte[]> readBufferRef;
495 byte[] readBuffer = null;
496 synchronized (mSync) {
497 readBufferRef = mReadBuffer;
498 if (readBufferRef != null) {
499 mReadBuffer = null;
500 readBuffer = readBufferRef.get();
501 }
502 if (readBuffer == null) {
503 readBuffer = new byte[8192];
504 readBufferRef = new WeakReference<byte[]>(readBuffer);
505 }
506 }
507
508 try {
509 JarFile jarFile = new JarFile(mArchiveSourcePath);
510
511 Certificate[] certs = null;
512
513 if ((flags&PARSE_IS_SYSTEM) != 0) {
514 // If this package comes from the system image, then we
515 // can trust it... we'll just use the AndroidManifest.xml
516 // to retrieve its signatures, not validating all of the
517 // files.
Kenny Rootbcc954d2011-08-08 16:19:08 -0700518 JarEntry jarEntry = jarFile.getJarEntry(ANDROID_MANIFEST_FILENAME);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 certs = loadCertificates(jarFile, jarEntry, readBuffer);
520 if (certs == null) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700521 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522 + " has no certificates at entry "
523 + jarEntry.getName() + "; ignoring!");
524 jarFile.close();
525 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
526 return false;
527 }
Kenny Rootd2d29252011-08-08 11:27:57 -0700528 if (DEBUG_JAR) {
529 Slog.i(TAG, "File " + mArchiveSourcePath + ": entry=" + jarEntry
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 + " certs=" + (certs != null ? certs.length : 0));
531 if (certs != null) {
532 final int N = certs.length;
533 for (int i=0; i<N; i++) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700534 Slog.i(TAG, " Public key: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 + certs[i].getPublicKey().getEncoded()
536 + " " + certs[i].getPublicKey());
537 }
538 }
539 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -0700541 Enumeration<JarEntry> entries = jarFile.entries();
Kenny Rootbcc954d2011-08-08 16:19:08 -0700542 final Manifest manifest = jarFile.getManifest();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 while (entries.hasMoreElements()) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700544 final JarEntry je = entries.nextElement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 if (je.isDirectory()) continue;
Kenny Rootd2d29252011-08-08 11:27:57 -0700546
Kenny Rootbcc954d2011-08-08 16:19:08 -0700547 final String name = je.getName();
548
549 if (name.startsWith("META-INF/"))
550 continue;
551
552 if (ANDROID_MANIFEST_FILENAME.equals(name)) {
553 final Attributes attributes = manifest.getAttributes(name);
554 pkg.manifestDigest = ManifestDigest.fromAttributes(attributes);
555 }
556
557 final Certificate[] localCerts = loadCertificates(jarFile, je, readBuffer);
Kenny Rootd2d29252011-08-08 11:27:57 -0700558 if (DEBUG_JAR) {
559 Slog.i(TAG, "File " + mArchiveSourcePath + " entry " + je.getName()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560 + ": certs=" + certs + " ("
561 + (certs != null ? certs.length : 0) + ")");
562 }
Kenny Rootbcc954d2011-08-08 16:19:08 -0700563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564 if (localCerts == null) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700565 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 + " has no certificates at entry "
567 + je.getName() + "; ignoring!");
568 jarFile.close();
569 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
570 return false;
571 } else if (certs == null) {
572 certs = localCerts;
573 } else {
574 // Ensure all certificates match.
575 for (int i=0; i<certs.length; i++) {
576 boolean found = false;
577 for (int j=0; j<localCerts.length; j++) {
578 if (certs[i] != null &&
579 certs[i].equals(localCerts[j])) {
580 found = true;
581 break;
582 }
583 }
584 if (!found || certs.length != localCerts.length) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700585 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800586 + " has mismatched certificates at entry "
587 + je.getName() + "; ignoring!");
588 jarFile.close();
589 mParseError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
590 return false;
591 }
592 }
593 }
594 }
595 }
596 jarFile.close();
597
598 synchronized (mSync) {
599 mReadBuffer = readBufferRef;
600 }
601
602 if (certs != null && certs.length > 0) {
603 final int N = certs.length;
604 pkg.mSignatures = new Signature[certs.length];
605 for (int i=0; i<N; i++) {
606 pkg.mSignatures[i] = new Signature(
607 certs[i].getEncoded());
608 }
609 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -0700610 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800611 + " has no certificates; ignoring!");
612 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
613 return false;
614 }
615 } catch (CertificateEncodingException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700616 Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800617 mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
618 return false;
619 } catch (IOException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700620 Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
622 return false;
623 } catch (RuntimeException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700624 Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
626 return false;
627 }
628
629 return true;
630 }
631
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800632 /*
633 * Utility method that retrieves just the package name and install
634 * location from the apk location at the given file path.
635 * @param packageFilePath file location of the apk
636 * @param flags Special parse flags
Kenny Root930d3af2010-07-30 16:52:29 -0700637 * @return PackageLite object with package information or null on failure.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800638 */
639 public static PackageLite parsePackageLite(String packageFilePath, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640 AssetManager assmgr = null;
Kenny Root05ca4c92011-09-15 10:36:25 -0700641 final XmlResourceParser parser;
642 final Resources res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 try {
644 assmgr = new AssetManager();
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700645 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 -0800646 Build.VERSION.RESOURCES_SDK_INT);
Kenny Root1ebd74a2011-08-03 15:09:44 -0700647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648 int cookie = assmgr.addAssetPath(packageFilePath);
Kenny Root1ebd74a2011-08-03 15:09:44 -0700649 if (cookie == 0) {
650 return null;
651 }
652
Kenny Root05ca4c92011-09-15 10:36:25 -0700653 final DisplayMetrics metrics = new DisplayMetrics();
654 metrics.setToDefaults();
655 res = new Resources(assmgr, metrics, null);
Kenny Rootbcc954d2011-08-08 16:19:08 -0700656 parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800657 } catch (Exception e) {
658 if (assmgr != null) assmgr.close();
Kenny Rootd2d29252011-08-08 11:27:57 -0700659 Slog.w(TAG, "Unable to read AndroidManifest.xml of "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660 + packageFilePath, e);
661 return null;
662 }
Kenny Root05ca4c92011-09-15 10:36:25 -0700663
664 final AttributeSet attrs = parser;
665 final String errors[] = new String[1];
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800666 PackageLite packageLite = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 try {
Kenny Root05ca4c92011-09-15 10:36:25 -0700668 packageLite = parsePackageLite(res, parser, attrs, flags, errors);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669 } catch (IOException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700670 Slog.w(TAG, packageFilePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671 } catch (XmlPullParserException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700672 Slog.w(TAG, packageFilePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800673 } finally {
674 if (parser != null) parser.close();
675 if (assmgr != null) assmgr.close();
676 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800677 if (packageLite == null) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700678 Slog.e(TAG, "parsePackageLite error: " + errors[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679 return null;
680 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800681 return packageLite;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682 }
683
684 private static String validateName(String name, boolean requiresSeparator) {
685 final int N = name.length();
686 boolean hasSep = false;
687 boolean front = true;
688 for (int i=0; i<N; i++) {
689 final char c = name.charAt(i);
690 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
691 front = false;
692 continue;
693 }
694 if (!front) {
695 if ((c >= '0' && c <= '9') || c == '_') {
696 continue;
697 }
698 }
699 if (c == '.') {
700 hasSep = true;
701 front = true;
702 continue;
703 }
704 return "bad character '" + c + "'";
705 }
706 return hasSep || !requiresSeparator
707 ? null : "must have at least one '.' separator";
708 }
709
710 private static String parsePackageName(XmlPullParser parser,
711 AttributeSet attrs, int flags, String[] outError)
712 throws IOException, XmlPullParserException {
713
714 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -0700715 while ((type = parser.next()) != XmlPullParser.START_TAG
716 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 ;
718 }
719
Kenny Rootd2d29252011-08-08 11:27:57 -0700720 if (type != XmlPullParser.START_TAG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 outError[0] = "No start tag found";
722 return null;
723 }
Kenny Rootd2d29252011-08-08 11:27:57 -0700724 if (DEBUG_PARSER)
725 Slog.v(TAG, "Root element name: '" + parser.getName() + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 if (!parser.getName().equals("manifest")) {
727 outError[0] = "No <manifest> tag";
728 return null;
729 }
730 String pkgName = attrs.getAttributeValue(null, "package");
731 if (pkgName == null || pkgName.length() == 0) {
732 outError[0] = "<manifest> does not specify package";
733 return null;
734 }
735 String nameError = validateName(pkgName, true);
736 if (nameError != null && !"android".equals(pkgName)) {
737 outError[0] = "<manifest> specifies bad package name \""
738 + pkgName + "\": " + nameError;
739 return null;
740 }
741
742 return pkgName.intern();
743 }
744
Kenny Root05ca4c92011-09-15 10:36:25 -0700745 private static PackageLite parsePackageLite(Resources res, XmlPullParser parser,
746 AttributeSet attrs, int flags, String[] outError) throws IOException,
747 XmlPullParserException {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800748
749 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -0700750 while ((type = parser.next()) != XmlPullParser.START_TAG
751 && type != XmlPullParser.END_DOCUMENT) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800752 ;
753 }
754
Kenny Rootd2d29252011-08-08 11:27:57 -0700755 if (type != XmlPullParser.START_TAG) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800756 outError[0] = "No start tag found";
757 return null;
758 }
Kenny Rootd2d29252011-08-08 11:27:57 -0700759 if (DEBUG_PARSER)
760 Slog.v(TAG, "Root element name: '" + parser.getName() + "'");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800761 if (!parser.getName().equals("manifest")) {
762 outError[0] = "No <manifest> tag";
763 return null;
764 }
765 String pkgName = attrs.getAttributeValue(null, "package");
766 if (pkgName == null || pkgName.length() == 0) {
767 outError[0] = "<manifest> does not specify package";
768 return null;
769 }
770 String nameError = validateName(pkgName, true);
771 if (nameError != null && !"android".equals(pkgName)) {
772 outError[0] = "<manifest> specifies bad package name \""
773 + pkgName + "\": " + nameError;
774 return null;
775 }
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700776 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800777 for (int i = 0; i < attrs.getAttributeCount(); i++) {
778 String attr = attrs.getAttributeName(i);
779 if (attr.equals("installLocation")) {
780 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700781 PARSE_DEFAULT_INSTALL_LOCATION);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800782 break;
783 }
784 }
Kenny Root05ca4c92011-09-15 10:36:25 -0700785
786 // Only search the tree when the tag is directly below <manifest>
787 final int searchDepth = parser.getDepth() + 1;
788
789 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
790 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
791 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
792 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
793 continue;
794 }
795
796 if (parser.getDepth() == searchDepth && "package-verifier".equals(parser.getName())) {
797 final VerifierInfo verifier = parseVerifier(res, parser, attrs, flags, outError);
798 if (verifier != null) {
799 verifiers.add(verifier);
800 }
801 }
802 }
803
804 return new PackageLite(pkgName.intern(), installLocation, verifiers);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800805 }
806
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 /**
808 * Temporary.
809 */
810 static public Signature stringToSignature(String str) {
811 final int N = str.length();
812 byte[] sig = new byte[N];
813 for (int i=0; i<N; i++) {
814 sig[i] = (byte)str.charAt(i);
815 }
816 return new Signature(sig);
817 }
818
819 private Package parsePackage(
820 Resources res, XmlResourceParser parser, int flags, String[] outError)
821 throws XmlPullParserException, IOException {
822 AttributeSet attrs = parser;
823
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700824 mParseInstrumentationArgs = null;
825 mParseActivityArgs = null;
826 mParseServiceArgs = null;
827 mParseProviderArgs = null;
828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 String pkgName = parsePackageName(parser, attrs, flags, outError);
830 if (pkgName == null) {
831 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
832 return null;
833 }
834 int type;
835
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700836 if (mOnlyCoreApps) {
837 boolean core = attrs.getAttributeBooleanValue(null, "coreApp", false);
838 if (!core) {
839 mParseError = PackageManager.INSTALL_SUCCEEDED;
840 return null;
841 }
842 }
843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 final Package pkg = new Package(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845 boolean foundApp = false;
Dianne Hackborn851a5412009-05-08 12:06:44 -0700846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800847 TypedArray sa = res.obtainAttributes(attrs,
848 com.android.internal.R.styleable.AndroidManifest);
849 pkg.mVersionCode = sa.getInteger(
850 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800851 pkg.mVersionName = sa.getNonConfigurationString(
852 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 if (pkg.mVersionName != null) {
854 pkg.mVersionName = pkg.mVersionName.intern();
855 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800856 String str = sa.getNonConfigurationString(
857 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
858 if (str != null && str.length() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859 String nameError = validateName(str, true);
860 if (nameError != null && !"android".equals(pkgName)) {
861 outError[0] = "<manifest> specifies bad sharedUserId name \""
862 + str + "\": " + nameError;
863 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
864 return null;
865 }
866 pkg.mSharedUserId = str.intern();
867 pkg.mSharedUserLabel = sa.getResourceId(
868 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
869 }
870 sa.recycle();
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -0800871
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800872 pkg.installLocation = sa.getInteger(
873 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700874 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -0700875 pkg.applicationInfo.installLocation = pkg.installLocation;
876
Dianne Hackborn723738c2009-06-25 19:48:04 -0700877 // Resource boolean are -1, so 1 means we don't know the value.
878 int supportsSmallScreens = 1;
879 int supportsNormalScreens = 1;
880 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -0700881 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700882 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700883 int anyDensity = 1;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800885 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -0700886 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
887 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
888 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800889 continue;
890 }
891
892 String tagName = parser.getName();
893 if (tagName.equals("application")) {
894 if (foundApp) {
895 if (RIGID_PARSER) {
896 outError[0] = "<manifest> has more than one <application>";
897 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
898 return null;
899 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -0700900 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800901 XmlUtils.skipCurrentTag(parser);
902 continue;
903 }
904 }
905
906 foundApp = true;
907 if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
908 return null;
909 }
910 } else if (tagName.equals("permission-group")) {
911 if (parsePermissionGroup(pkg, res, parser, attrs, outError) == null) {
912 return null;
913 }
914 } else if (tagName.equals("permission")) {
915 if (parsePermission(pkg, res, parser, attrs, outError) == null) {
916 return null;
917 }
918 } else if (tagName.equals("permission-tree")) {
919 if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
920 return null;
921 }
922 } else if (tagName.equals("uses-permission")) {
923 sa = res.obtainAttributes(attrs,
924 com.android.internal.R.styleable.AndroidManifestUsesPermission);
925
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800926 // Note: don't allow this value to be a reference to a resource
927 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 String name = sa.getNonResourceString(
929 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
930
931 sa.recycle();
932
933 if (name != null && !pkg.requestedPermissions.contains(name)) {
Dianne Hackborn854060a2009-07-09 18:14:31 -0700934 pkg.requestedPermissions.add(name.intern());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 }
936
937 XmlUtils.skipCurrentTag(parser);
938
939 } else if (tagName.equals("uses-configuration")) {
940 ConfigurationInfo cPref = new ConfigurationInfo();
941 sa = res.obtainAttributes(attrs,
942 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
943 cPref.reqTouchScreen = sa.getInt(
944 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
945 Configuration.TOUCHSCREEN_UNDEFINED);
946 cPref.reqKeyboardType = sa.getInt(
947 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
948 Configuration.KEYBOARD_UNDEFINED);
949 if (sa.getBoolean(
950 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
951 false)) {
952 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
953 }
954 cPref.reqNavigation = sa.getInt(
955 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
956 Configuration.NAVIGATION_UNDEFINED);
957 if (sa.getBoolean(
958 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
959 false)) {
960 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
961 }
962 sa.recycle();
963 pkg.configPreferences.add(cPref);
964
965 XmlUtils.skipCurrentTag(parser);
966
Suchi Amalapurapud299b812009-06-05 10:26:19 -0700967 } else if (tagName.equals("uses-feature")) {
Dianne Hackborn49237342009-08-27 20:08:01 -0700968 FeatureInfo fi = new FeatureInfo();
Suchi Amalapurapud299b812009-06-05 10:26:19 -0700969 sa = res.obtainAttributes(attrs,
970 com.android.internal.R.styleable.AndroidManifestUsesFeature);
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800971 // Note: don't allow this value to be a reference to a resource
972 // that may change.
Dianne Hackborn49237342009-08-27 20:08:01 -0700973 fi.name = sa.getNonResourceString(
974 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
975 if (fi.name == null) {
976 fi.reqGlEsVersion = sa.getInt(
977 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
978 FeatureInfo.GL_ES_VERSION_UNDEFINED);
979 }
980 if (sa.getBoolean(
981 com.android.internal.R.styleable.AndroidManifestUsesFeature_required,
982 true)) {
983 fi.flags |= FeatureInfo.FLAG_REQUIRED;
984 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -0700985 sa.recycle();
Dianne Hackborn49237342009-08-27 20:08:01 -0700986 if (pkg.reqFeatures == null) {
987 pkg.reqFeatures = new ArrayList<FeatureInfo>();
988 }
989 pkg.reqFeatures.add(fi);
990
991 if (fi.name == null) {
992 ConfigurationInfo cPref = new ConfigurationInfo();
993 cPref.reqGlEsVersion = fi.reqGlEsVersion;
994 pkg.configPreferences.add(cPref);
995 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -0700996
997 XmlUtils.skipCurrentTag(parser);
998
Dianne Hackborn851a5412009-05-08 12:06:44 -0700999 } else if (tagName.equals("uses-sdk")) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001000 if (SDK_VERSION > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 sa = res.obtainAttributes(attrs,
1002 com.android.internal.R.styleable.AndroidManifestUsesSdk);
1003
Dianne Hackborn851a5412009-05-08 12:06:44 -07001004 int minVers = 0;
1005 String minCode = null;
1006 int targetVers = 0;
1007 String targetCode = null;
1008
1009 TypedValue val = sa.peekValue(
1010 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
1011 if (val != null) {
1012 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1013 targetCode = minCode = val.string.toString();
1014 } else {
1015 // If it's not a string, it's an integer.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001016 targetVers = minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001017 }
1018 }
1019
1020 val = sa.peekValue(
1021 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
1022 if (val != null) {
1023 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1024 targetCode = minCode = val.string.toString();
1025 } else {
1026 // If it's not a string, it's an integer.
1027 targetVers = val.data;
1028 }
1029 }
1030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 sa.recycle();
1032
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001033 if (minCode != null) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001034 if (!minCode.equals(SDK_CODENAME)) {
1035 if (SDK_CODENAME != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001036 outError[0] = "Requires development platform " + minCode
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001037 + " (current platform is " + SDK_CODENAME + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001038 } else {
1039 outError[0] = "Requires development platform " + minCode
1040 + " but this is a release platform.";
1041 }
1042 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1043 return null;
1044 }
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001045 } else if (minVers > SDK_VERSION) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001046 outError[0] = "Requires newer sdk version #" + minVers
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001047 + " (current version is #" + SDK_VERSION + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001048 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1049 return null;
1050 }
1051
Dianne Hackborn851a5412009-05-08 12:06:44 -07001052 if (targetCode != null) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001053 if (!targetCode.equals(SDK_CODENAME)) {
1054 if (SDK_CODENAME != null) {
Dianne Hackborn851a5412009-05-08 12:06:44 -07001055 outError[0] = "Requires development platform " + targetCode
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001056 + " (current platform is " + SDK_CODENAME + ")";
Dianne Hackborn851a5412009-05-08 12:06:44 -07001057 } else {
1058 outError[0] = "Requires development platform " + targetCode
1059 + " but this is a release platform.";
1060 }
1061 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1062 return null;
1063 }
1064 // If the code matches, it definitely targets this SDK.
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001065 pkg.applicationInfo.targetSdkVersion
1066 = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
1067 } else {
1068 pkg.applicationInfo.targetSdkVersion = targetVers;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001069 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070 }
1071
1072 XmlUtils.skipCurrentTag(parser);
1073
Dianne Hackborn723738c2009-06-25 19:48:04 -07001074 } else if (tagName.equals("supports-screens")) {
1075 sa = res.obtainAttributes(attrs,
1076 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
1077
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001078 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
1079 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
1080 0);
1081 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
1082 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
1083 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07001084 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
1085 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
1086 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001087
Dianne Hackborn723738c2009-06-25 19:48:04 -07001088 // This is a trick to get a boolean and still able to detect
1089 // if a value was actually set.
1090 supportsSmallScreens = sa.getInteger(
1091 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
1092 supportsSmallScreens);
1093 supportsNormalScreens = sa.getInteger(
1094 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
1095 supportsNormalScreens);
1096 supportsLargeScreens = sa.getInteger(
1097 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
1098 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001099 supportsXLargeScreens = sa.getInteger(
1100 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
1101 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001102 resizeable = sa.getInteger(
1103 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001104 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001105 anyDensity = sa.getInteger(
1106 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
1107 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001108
1109 sa.recycle();
1110
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07001111 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn854060a2009-07-09 18:14:31 -07001112
1113 } else if (tagName.equals("protected-broadcast")) {
1114 sa = res.obtainAttributes(attrs,
1115 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
1116
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001117 // Note: don't allow this value to be a reference to a resource
1118 // that may change.
Dianne Hackborn854060a2009-07-09 18:14:31 -07001119 String name = sa.getNonResourceString(
1120 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
1121
1122 sa.recycle();
1123
1124 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
1125 if (pkg.protectedBroadcasts == null) {
1126 pkg.protectedBroadcasts = new ArrayList<String>();
1127 }
1128 if (!pkg.protectedBroadcasts.contains(name)) {
1129 pkg.protectedBroadcasts.add(name.intern());
1130 }
1131 }
1132
1133 XmlUtils.skipCurrentTag(parser);
1134
1135 } else if (tagName.equals("instrumentation")) {
1136 if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) {
1137 return null;
1138 }
1139
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001140 } else if (tagName.equals("original-package")) {
1141 sa = res.obtainAttributes(attrs,
1142 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1143
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001144 String orig =sa.getNonConfigurationString(
1145 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001146 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08001147 if (pkg.mOriginalPackages == null) {
1148 pkg.mOriginalPackages = new ArrayList<String>();
1149 pkg.mRealPackage = pkg.packageName;
1150 }
1151 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001152 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001153
1154 sa.recycle();
1155
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001156 XmlUtils.skipCurrentTag(parser);
1157
1158 } else if (tagName.equals("adopt-permissions")) {
1159 sa = res.obtainAttributes(attrs,
1160 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1161
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001162 String name = sa.getNonConfigurationString(
1163 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001164
1165 sa.recycle();
1166
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001167 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001168 if (pkg.mAdoptPermissions == null) {
1169 pkg.mAdoptPermissions = new ArrayList<String>();
1170 }
1171 pkg.mAdoptPermissions.add(name);
1172 }
1173
1174 XmlUtils.skipCurrentTag(parser);
1175
Dianne Hackborna0b46c92010-10-21 15:32:06 -07001176 } else if (tagName.equals("uses-gl-texture")) {
1177 // Just skip this tag
1178 XmlUtils.skipCurrentTag(parser);
1179 continue;
1180
1181 } else if (tagName.equals("compatible-screens")) {
1182 // Just skip this tag
1183 XmlUtils.skipCurrentTag(parser);
1184 continue;
1185
Dianne Hackborn854060a2009-07-09 18:14:31 -07001186 } else if (tagName.equals("eat-comment")) {
1187 // Just skip this tag
1188 XmlUtils.skipCurrentTag(parser);
1189 continue;
1190
1191 } else if (RIGID_PARSER) {
1192 outError[0] = "Bad element under <manifest>: "
1193 + parser.getName();
1194 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1195 return null;
1196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07001198 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07001199 + " at " + mArchiveSourcePath + " "
1200 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 XmlUtils.skipCurrentTag(parser);
1202 continue;
1203 }
1204 }
1205
1206 if (!foundApp && pkg.instrumentation.size() == 0) {
1207 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
1208 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1209 }
1210
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001211 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001212 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001213 for (int ip=0; ip<NP; ip++) {
1214 final PackageParser.NewPermissionInfo npi
1215 = PackageParser.NEW_PERMISSIONS[ip];
1216 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
1217 break;
1218 }
1219 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001220 if (implicitPerms == null) {
1221 implicitPerms = new StringBuilder(128);
1222 implicitPerms.append(pkg.packageName);
1223 implicitPerms.append(": compat added ");
1224 } else {
1225 implicitPerms.append(' ');
1226 }
1227 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001228 pkg.requestedPermissions.add(npi.name);
1229 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07001230 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001231 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07001232 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001233 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07001234
Dianne Hackborn723738c2009-06-25 19:48:04 -07001235 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
1236 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001237 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001238 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
1239 }
1240 if (supportsNormalScreens != 0) {
1241 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
1242 }
1243 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
1244 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001245 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001246 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
1247 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001248 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
1249 && pkg.applicationInfo.targetSdkVersion
1250 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
1251 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
1252 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001253 if (resizeable < 0 || (resizeable > 0
1254 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001255 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001256 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
1257 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001258 if (anyDensity < 0 || (anyDensity > 0
1259 && pkg.applicationInfo.targetSdkVersion
1260 >= android.os.Build.VERSION_CODES.DONUT)) {
1261 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07001262 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07001263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264 return pkg;
1265 }
1266
1267 private static String buildClassName(String pkg, CharSequence clsSeq,
1268 String[] outError) {
1269 if (clsSeq == null || clsSeq.length() <= 0) {
1270 outError[0] = "Empty class name in package " + pkg;
1271 return null;
1272 }
1273 String cls = clsSeq.toString();
1274 char c = cls.charAt(0);
1275 if (c == '.') {
1276 return (pkg + cls).intern();
1277 }
1278 if (cls.indexOf('.') < 0) {
1279 StringBuilder b = new StringBuilder(pkg);
1280 b.append('.');
1281 b.append(cls);
1282 return b.toString().intern();
1283 }
1284 if (c >= 'a' && c <= 'z') {
1285 return cls.intern();
1286 }
1287 outError[0] = "Bad class name " + cls + " in package " + pkg;
1288 return null;
1289 }
1290
1291 private static String buildCompoundName(String pkg,
1292 CharSequence procSeq, String type, String[] outError) {
1293 String proc = procSeq.toString();
1294 char c = proc.charAt(0);
1295 if (pkg != null && c == ':') {
1296 if (proc.length() < 2) {
1297 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
1298 + ": must be at least two characters";
1299 return null;
1300 }
1301 String subName = proc.substring(1);
1302 String nameError = validateName(subName, false);
1303 if (nameError != null) {
1304 outError[0] = "Invalid " + type + " name " + proc + " in package "
1305 + pkg + ": " + nameError;
1306 return null;
1307 }
1308 return (pkg + proc).intern();
1309 }
1310 String nameError = validateName(proc, true);
1311 if (nameError != null && !"system".equals(proc)) {
1312 outError[0] = "Invalid " + type + " name " + proc + " in package "
1313 + pkg + ": " + nameError;
1314 return null;
1315 }
1316 return proc.intern();
1317 }
1318
1319 private static String buildProcessName(String pkg, String defProc,
1320 CharSequence procSeq, int flags, String[] separateProcesses,
1321 String[] outError) {
1322 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
1323 return defProc != null ? defProc : pkg;
1324 }
1325 if (separateProcesses != null) {
1326 for (int i=separateProcesses.length-1; i>=0; i--) {
1327 String sp = separateProcesses[i];
1328 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
1329 return pkg;
1330 }
1331 }
1332 }
1333 if (procSeq == null || procSeq.length() <= 0) {
1334 return defProc;
1335 }
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07001336 return buildCompoundName(pkg, procSeq, "process", outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 }
1338
1339 private static String buildTaskAffinityName(String pkg, String defProc,
1340 CharSequence procSeq, String[] outError) {
1341 if (procSeq == null) {
1342 return defProc;
1343 }
1344 if (procSeq.length() <= 0) {
1345 return null;
1346 }
1347 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
1348 }
1349
1350 private PermissionGroup parsePermissionGroup(Package owner, Resources res,
1351 XmlPullParser parser, AttributeSet attrs, String[] outError)
1352 throws XmlPullParserException, IOException {
1353 PermissionGroup perm = new PermissionGroup(owner);
1354
1355 TypedArray sa = res.obtainAttributes(attrs,
1356 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
1357
1358 if (!parsePackageItemInfo(owner, perm.info, outError,
1359 "<permission-group>", sa,
1360 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
1361 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001362 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
1363 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 sa.recycle();
1365 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1366 return null;
1367 }
1368
1369 perm.info.descriptionRes = sa.getResourceId(
1370 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
1371 0);
1372
1373 sa.recycle();
1374
1375 if (!parseAllMetaData(res, parser, attrs, "<permission-group>", perm,
1376 outError)) {
1377 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1378 return null;
1379 }
1380
1381 owner.permissionGroups.add(perm);
1382
1383 return perm;
1384 }
1385
1386 private Permission parsePermission(Package owner, Resources res,
1387 XmlPullParser parser, AttributeSet attrs, String[] outError)
1388 throws XmlPullParserException, IOException {
1389 Permission perm = new Permission(owner);
1390
1391 TypedArray sa = res.obtainAttributes(attrs,
1392 com.android.internal.R.styleable.AndroidManifestPermission);
1393
1394 if (!parsePackageItemInfo(owner, perm.info, outError,
1395 "<permission>", sa,
1396 com.android.internal.R.styleable.AndroidManifestPermission_name,
1397 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001398 com.android.internal.R.styleable.AndroidManifestPermission_icon,
1399 com.android.internal.R.styleable.AndroidManifestPermission_logo)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400 sa.recycle();
1401 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1402 return null;
1403 }
1404
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001405 // Note: don't allow this value to be a reference to a resource
1406 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407 perm.info.group = sa.getNonResourceString(
1408 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
1409 if (perm.info.group != null) {
1410 perm.info.group = perm.info.group.intern();
1411 }
1412
1413 perm.info.descriptionRes = sa.getResourceId(
1414 com.android.internal.R.styleable.AndroidManifestPermission_description,
1415 0);
1416
1417 perm.info.protectionLevel = sa.getInt(
1418 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
1419 PermissionInfo.PROTECTION_NORMAL);
1420
1421 sa.recycle();
1422
1423 if (perm.info.protectionLevel == -1) {
1424 outError[0] = "<permission> does not specify protectionLevel";
1425 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1426 return null;
1427 }
1428
1429 if (!parseAllMetaData(res, parser, attrs, "<permission>", perm,
1430 outError)) {
1431 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1432 return null;
1433 }
1434
1435 owner.permissions.add(perm);
1436
1437 return perm;
1438 }
1439
1440 private Permission parsePermissionTree(Package owner, Resources res,
1441 XmlPullParser parser, AttributeSet attrs, String[] outError)
1442 throws XmlPullParserException, IOException {
1443 Permission perm = new Permission(owner);
1444
1445 TypedArray sa = res.obtainAttributes(attrs,
1446 com.android.internal.R.styleable.AndroidManifestPermissionTree);
1447
1448 if (!parsePackageItemInfo(owner, perm.info, outError,
1449 "<permission-tree>", sa,
1450 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
1451 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001452 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
1453 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 sa.recycle();
1455 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1456 return null;
1457 }
1458
1459 sa.recycle();
1460
1461 int index = perm.info.name.indexOf('.');
1462 if (index > 0) {
1463 index = perm.info.name.indexOf('.', index+1);
1464 }
1465 if (index < 0) {
1466 outError[0] = "<permission-tree> name has less than three segments: "
1467 + perm.info.name;
1468 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1469 return null;
1470 }
1471
1472 perm.info.descriptionRes = 0;
1473 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
1474 perm.tree = true;
1475
1476 if (!parseAllMetaData(res, parser, attrs, "<permission-tree>", perm,
1477 outError)) {
1478 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1479 return null;
1480 }
1481
1482 owner.permissions.add(perm);
1483
1484 return perm;
1485 }
1486
1487 private Instrumentation parseInstrumentation(Package owner, Resources res,
1488 XmlPullParser parser, AttributeSet attrs, String[] outError)
1489 throws XmlPullParserException, IOException {
1490 TypedArray sa = res.obtainAttributes(attrs,
1491 com.android.internal.R.styleable.AndroidManifestInstrumentation);
1492
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001493 if (mParseInstrumentationArgs == null) {
1494 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
1495 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
1496 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001497 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
1498 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001499 mParseInstrumentationArgs.tag = "<instrumentation>";
1500 }
1501
1502 mParseInstrumentationArgs.sa = sa;
1503
1504 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
1505 new InstrumentationInfo());
1506 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 sa.recycle();
1508 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1509 return null;
1510 }
1511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001513 // Note: don't allow this value to be a reference to a resource
1514 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 str = sa.getNonResourceString(
1516 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
1517 a.info.targetPackage = str != null ? str.intern() : null;
1518
1519 a.info.handleProfiling = sa.getBoolean(
1520 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
1521 false);
1522
1523 a.info.functionalTest = sa.getBoolean(
1524 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
1525 false);
1526
1527 sa.recycle();
1528
1529 if (a.info.targetPackage == null) {
1530 outError[0] = "<instrumentation> does not specify targetPackage";
1531 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1532 return null;
1533 }
1534
1535 if (!parseAllMetaData(res, parser, attrs, "<instrumentation>", a,
1536 outError)) {
1537 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1538 return null;
1539 }
1540
1541 owner.instrumentation.add(a);
1542
1543 return a;
1544 }
1545
1546 private boolean parseApplication(Package owner, Resources res,
1547 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
1548 throws XmlPullParserException, IOException {
1549 final ApplicationInfo ai = owner.applicationInfo;
1550 final String pkgName = owner.applicationInfo.packageName;
1551
1552 TypedArray sa = res.obtainAttributes(attrs,
1553 com.android.internal.R.styleable.AndroidManifestApplication);
1554
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001555 String name = sa.getNonConfigurationString(
1556 com.android.internal.R.styleable.AndroidManifestApplication_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001557 if (name != null) {
1558 ai.className = buildClassName(pkgName, name, outError);
1559 if (ai.className == null) {
1560 sa.recycle();
1561 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1562 return false;
1563 }
1564 }
1565
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001566 String manageSpaceActivity = sa.getNonConfigurationString(
1567 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 if (manageSpaceActivity != null) {
1569 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
1570 outError);
1571 }
1572
Christopher Tate181fafa2009-05-14 11:12:14 -07001573 boolean allowBackup = sa.getBoolean(
1574 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
1575 if (allowBackup) {
1576 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07001577
Christopher Tate3de55bc2010-03-12 17:28:08 -08001578 // backupAgent, killAfterRestore, and restoreAnyVersion are only relevant
1579 // if backup is possible for the given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001580 String backupAgent = sa.getNonConfigurationString(
1581 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent, 0);
Christopher Tate181fafa2009-05-14 11:12:14 -07001582 if (backupAgent != null) {
1583 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07001584 if (DEBUG_BACKUP) {
1585 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001586 + " from " + pkgName + "+" + backupAgent);
1587 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07001588
1589 if (sa.getBoolean(
1590 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
1591 true)) {
1592 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
1593 }
1594 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08001595 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
1596 false)) {
1597 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
1598 }
Christopher Tate181fafa2009-05-14 11:12:14 -07001599 }
1600 }
Christopher Tate4a627c72011-04-01 14:43:32 -07001601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 TypedValue v = sa.peekValue(
1603 com.android.internal.R.styleable.AndroidManifestApplication_label);
1604 if (v != null && (ai.labelRes=v.resourceId) == 0) {
1605 ai.nonLocalizedLabel = v.coerceToString();
1606 }
1607
1608 ai.icon = sa.getResourceId(
1609 com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
Adam Powell81cd2e92010-04-21 16:35:18 -07001610 ai.logo = sa.getResourceId(
1611 com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001612 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08001613 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 ai.descriptionRes = sa.getResourceId(
1615 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
1616
1617 if ((flags&PARSE_IS_SYSTEM) != 0) {
1618 if (sa.getBoolean(
1619 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
1620 false)) {
1621 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
1622 }
1623 }
1624
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08001625 if ((flags & PARSE_FORWARD_LOCK) != 0) {
1626 ai.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
1627 }
1628
1629 if ((flags & PARSE_ON_SDCARD) != 0) {
Suchi Amalapurapu6069beb2010-03-10 09:46:49 -08001630 ai.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08001631 }
1632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001633 if (sa.getBoolean(
1634 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
1635 false)) {
1636 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
1637 }
1638
1639 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07001640 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08001641 false)) {
1642 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
1643 }
1644
Romain Guy529b60a2010-08-03 18:05:47 -07001645 boolean hardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07001646 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07001647 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Romain Guy812ccbe2010-06-01 14:07:24 -07001648
1649 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
1651 true)) {
1652 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
1653 }
1654
1655 if (sa.getBoolean(
1656 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
1657 false)) {
1658 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
1659 }
1660
1661 if (sa.getBoolean(
1662 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
1663 true)) {
1664 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
1665 }
1666
Dianne Hackbornade3eca2009-05-11 18:54:45 -07001667 if (sa.getBoolean(
1668 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
Dianne Hackborne7fe35b2009-05-13 10:53:41 -07001669 false)) {
Dianne Hackbornade3eca2009-05-11 18:54:45 -07001670 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
1671 }
1672
Jason parksa3cdaa52011-01-13 14:15:43 -06001673 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08001674 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06001675 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08001676 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06001677 }
1678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001680 str = sa.getNonConfigurationString(
1681 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
1683
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07001684 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
1685 str = sa.getNonConfigurationString(
1686 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity, 0);
1687 } else {
1688 // Some older apps have been seen to use a resource reference
1689 // here that on older builds was ignored (with a warning). We
1690 // need to continue to do this for them so they don't break.
1691 str = sa.getNonResourceString(
1692 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
1693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
1695 str, outError);
1696
1697 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07001698 CharSequence pname;
1699 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
1700 pname = sa.getNonConfigurationString(
1701 com.android.internal.R.styleable.AndroidManifestApplication_process, 0);
1702 } else {
1703 // Some older apps have been seen to use a resource reference
1704 // here that on older builds was ignored (with a warning). We
1705 // need to continue to do this for them so they don't break.
1706 pname = sa.getNonResourceString(
1707 com.android.internal.R.styleable.AndroidManifestApplication_process);
1708 }
1709 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001710 flags, mSeparateProcesses, outError);
1711
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001712 ai.enabled = sa.getBoolean(
1713 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001714
Dianne Hackborn02486b12010-08-26 14:18:37 -07001715 if (false) {
1716 if (sa.getBoolean(
1717 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
1718 false)) {
Dianne Hackborn54e570f2010-10-04 18:32:32 -07001719 ai.flags |= ApplicationInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07001720
1721 // A heavy-weight application can not be in a custom process.
1722 // We can do direct compare because we intern all strings.
1723 if (ai.processName != null && ai.processName != ai.packageName) {
1724 outError[0] = "cantSaveState applications can not use custom processes";
1725 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07001726 }
1727 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 }
1729
Adam Powell269248d2011-08-02 10:26:54 -07001730 ai.uiOptions = sa.getInt(
1731 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
1732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 sa.recycle();
1734
1735 if (outError[0] != null) {
1736 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1737 return false;
1738 }
1739
1740 final int innerDepth = parser.getDepth();
1741
1742 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001743 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1744 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
1745 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 continue;
1747 }
1748
1749 String tagName = parser.getName();
1750 if (tagName.equals("activity")) {
Romain Guy529b60a2010-08-03 18:05:47 -07001751 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
1752 hardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 if (a == null) {
1754 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1755 return false;
1756 }
1757
1758 owner.activities.add(a);
1759
1760 } else if (tagName.equals("receiver")) {
Romain Guy529b60a2010-08-03 18:05:47 -07001761 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 if (a == null) {
1763 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1764 return false;
1765 }
1766
1767 owner.receivers.add(a);
1768
1769 } else if (tagName.equals("service")) {
1770 Service s = parseService(owner, res, parser, attrs, flags, outError);
1771 if (s == null) {
1772 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1773 return false;
1774 }
1775
1776 owner.services.add(s);
1777
1778 } else if (tagName.equals("provider")) {
1779 Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
1780 if (p == null) {
1781 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1782 return false;
1783 }
1784
1785 owner.providers.add(p);
1786
1787 } else if (tagName.equals("activity-alias")) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001788 Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789 if (a == null) {
1790 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1791 return false;
1792 }
1793
1794 owner.activities.add(a);
1795
1796 } else if (parser.getName().equals("meta-data")) {
1797 // note: application meta-data is stored off to the side, so it can
1798 // remain null in the primary copy (we like to avoid extra copies because
1799 // it can be large)
1800 if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,
1801 outError)) == null) {
1802 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1803 return false;
1804 }
1805
1806 } else if (tagName.equals("uses-library")) {
1807 sa = res.obtainAttributes(attrs,
1808 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
1809
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001810 // Note: don't allow this value to be a reference to a resource
1811 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 String lname = sa.getNonResourceString(
1813 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07001814 boolean req = sa.getBoolean(
1815 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
1816 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001817
1818 sa.recycle();
1819
Dianne Hackborn49237342009-08-27 20:08:01 -07001820 if (lname != null) {
1821 if (req) {
1822 if (owner.usesLibraries == null) {
1823 owner.usesLibraries = new ArrayList<String>();
1824 }
1825 if (!owner.usesLibraries.contains(lname)) {
1826 owner.usesLibraries.add(lname.intern());
1827 }
1828 } else {
1829 if (owner.usesOptionalLibraries == null) {
1830 owner.usesOptionalLibraries = new ArrayList<String>();
1831 }
1832 if (!owner.usesOptionalLibraries.contains(lname)) {
1833 owner.usesOptionalLibraries.add(lname.intern());
1834 }
1835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001836 }
1837
1838 XmlUtils.skipCurrentTag(parser);
1839
Dianne Hackborncef65ee2010-09-30 18:27:22 -07001840 } else if (tagName.equals("uses-package")) {
1841 // Dependencies for app installers; we don't currently try to
1842 // enforce this.
1843 XmlUtils.skipCurrentTag(parser);
1844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001845 } else {
1846 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07001847 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001848 + " at " + mArchiveSourcePath + " "
1849 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001850 XmlUtils.skipCurrentTag(parser);
1851 continue;
1852 } else {
1853 outError[0] = "Bad element under <application>: " + tagName;
1854 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1855 return false;
1856 }
1857 }
1858 }
1859
1860 return true;
1861 }
1862
1863 private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
1864 String[] outError, String tag, TypedArray sa,
Adam Powell81cd2e92010-04-21 16:35:18 -07001865 int nameRes, int labelRes, int iconRes, int logoRes) {
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001866 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 if (name == null) {
1868 outError[0] = tag + " does not specify android:name";
1869 return false;
1870 }
1871
1872 outInfo.name
1873 = buildClassName(owner.applicationInfo.packageName, name, outError);
1874 if (outInfo.name == null) {
1875 return false;
1876 }
1877
1878 int iconVal = sa.getResourceId(iconRes, 0);
1879 if (iconVal != 0) {
1880 outInfo.icon = iconVal;
1881 outInfo.nonLocalizedLabel = null;
1882 }
Adam Powell81cd2e92010-04-21 16:35:18 -07001883
1884 int logoVal = sa.getResourceId(logoRes, 0);
1885 if (logoVal != 0) {
1886 outInfo.logo = logoVal;
1887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001888
1889 TypedValue v = sa.peekValue(labelRes);
1890 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
1891 outInfo.nonLocalizedLabel = v.coerceToString();
1892 }
1893
1894 outInfo.packageName = owner.packageName;
1895
1896 return true;
1897 }
1898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001899 private Activity parseActivity(Package owner, Resources res,
1900 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
Romain Guy529b60a2010-08-03 18:05:47 -07001901 boolean receiver, boolean hardwareAccelerated)
1902 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001903 TypedArray sa = res.obtainAttributes(attrs,
1904 com.android.internal.R.styleable.AndroidManifestActivity);
1905
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001906 if (mParseActivityArgs == null) {
1907 mParseActivityArgs = new ParseComponentArgs(owner, outError,
1908 com.android.internal.R.styleable.AndroidManifestActivity_name,
1909 com.android.internal.R.styleable.AndroidManifestActivity_label,
1910 com.android.internal.R.styleable.AndroidManifestActivity_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07001911 com.android.internal.R.styleable.AndroidManifestActivity_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001912 mSeparateProcesses,
1913 com.android.internal.R.styleable.AndroidManifestActivity_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08001914 com.android.internal.R.styleable.AndroidManifestActivity_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001915 com.android.internal.R.styleable.AndroidManifestActivity_enabled);
1916 }
1917
1918 mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
1919 mParseActivityArgs.sa = sa;
1920 mParseActivityArgs.flags = flags;
1921
1922 Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
1923 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 sa.recycle();
1925 return null;
1926 }
1927
1928 final boolean setExported = sa.hasValue(
1929 com.android.internal.R.styleable.AndroidManifestActivity_exported);
1930 if (setExported) {
1931 a.info.exported = sa.getBoolean(
1932 com.android.internal.R.styleable.AndroidManifestActivity_exported, false);
1933 }
1934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001935 a.info.theme = sa.getResourceId(
1936 com.android.internal.R.styleable.AndroidManifestActivity_theme, 0);
1937
Adam Powell269248d2011-08-02 10:26:54 -07001938 a.info.uiOptions = sa.getInt(
1939 com.android.internal.R.styleable.AndroidManifestActivity_uiOptions,
1940 a.info.applicationInfo.uiOptions);
1941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001943 str = sa.getNonConfigurationString(
1944 com.android.internal.R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001945 if (str == null) {
1946 a.info.permission = owner.applicationInfo.permission;
1947 } else {
1948 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
1949 }
1950
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001951 str = sa.getNonConfigurationString(
1952 com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001953 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
1954 owner.applicationInfo.taskAffinity, str, outError);
1955
1956 a.info.flags = 0;
1957 if (sa.getBoolean(
1958 com.android.internal.R.styleable.AndroidManifestActivity_multiprocess,
1959 false)) {
1960 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
1961 }
1962
1963 if (sa.getBoolean(
1964 com.android.internal.R.styleable.AndroidManifestActivity_finishOnTaskLaunch,
1965 false)) {
1966 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
1967 }
1968
1969 if (sa.getBoolean(
1970 com.android.internal.R.styleable.AndroidManifestActivity_clearTaskOnLaunch,
1971 false)) {
1972 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
1973 }
1974
1975 if (sa.getBoolean(
1976 com.android.internal.R.styleable.AndroidManifestActivity_noHistory,
1977 false)) {
1978 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
1979 }
1980
1981 if (sa.getBoolean(
1982 com.android.internal.R.styleable.AndroidManifestActivity_alwaysRetainTaskState,
1983 false)) {
1984 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
1985 }
1986
1987 if (sa.getBoolean(
1988 com.android.internal.R.styleable.AndroidManifestActivity_stateNotNeeded,
1989 false)) {
1990 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
1991 }
1992
1993 if (sa.getBoolean(
1994 com.android.internal.R.styleable.AndroidManifestActivity_excludeFromRecents,
1995 false)) {
1996 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
1997 }
1998
1999 if (sa.getBoolean(
2000 com.android.internal.R.styleable.AndroidManifestActivity_allowTaskReparenting,
2001 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
2002 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
2003 }
2004
Dianne Hackbornffa42482009-09-23 22:20:11 -07002005 if (sa.getBoolean(
2006 com.android.internal.R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs,
2007 false)) {
2008 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
2009 }
2010
Daniel Sandler613dde42010-06-21 13:46:39 -04002011 if (sa.getBoolean(
2012 com.android.internal.R.styleable.AndroidManifestActivity_immersive,
2013 false)) {
2014 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
2015 }
Romain Guy529b60a2010-08-03 18:05:47 -07002016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017 if (!receiver) {
Romain Guy529b60a2010-08-03 18:05:47 -07002018 if (sa.getBoolean(
2019 com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated,
2020 hardwareAccelerated)) {
2021 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
2022 }
2023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002024 a.info.launchMode = sa.getInt(
2025 com.android.internal.R.styleable.AndroidManifestActivity_launchMode,
2026 ActivityInfo.LAUNCH_MULTIPLE);
2027 a.info.screenOrientation = sa.getInt(
2028 com.android.internal.R.styleable.AndroidManifestActivity_screenOrientation,
2029 ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
2030 a.info.configChanges = sa.getInt(
2031 com.android.internal.R.styleable.AndroidManifestActivity_configChanges,
2032 0);
2033 a.info.softInputMode = sa.getInt(
2034 com.android.internal.R.styleable.AndroidManifestActivity_windowSoftInputMode,
2035 0);
2036 } else {
2037 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2038 a.info.configChanges = 0;
2039 }
2040
2041 sa.recycle();
2042
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002043 if (receiver && (owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07002044 // A heavy-weight application can not have receives in its main process
2045 // We can do direct compare because we intern all strings.
2046 if (a.info.processName == owner.packageName) {
2047 outError[0] = "Heavy-weight applications can not have receivers in main process";
2048 }
2049 }
2050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002051 if (outError[0] != null) {
2052 return null;
2053 }
2054
2055 int outerDepth = parser.getDepth();
2056 int type;
2057 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2058 && (type != XmlPullParser.END_TAG
2059 || parser.getDepth() > outerDepth)) {
2060 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2061 continue;
2062 }
2063
2064 if (parser.getName().equals("intent-filter")) {
2065 ActivityIntentInfo intent = new ActivityIntentInfo(a);
2066 if (!parseIntent(res, parser, attrs, flags, intent, outError, !receiver)) {
2067 return null;
2068 }
2069 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002070 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002071 + mArchiveSourcePath + " "
2072 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002073 } else {
2074 a.intents.add(intent);
2075 }
2076 } else if (parser.getName().equals("meta-data")) {
2077 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
2078 outError)) == null) {
2079 return null;
2080 }
2081 } else {
2082 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002083 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002084 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002085 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002086 + " at " + mArchiveSourcePath + " "
2087 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002088 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002089 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002090 + " at " + mArchiveSourcePath + " "
2091 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002092 }
2093 XmlUtils.skipCurrentTag(parser);
2094 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002095 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002096 if (receiver) {
2097 outError[0] = "Bad element under <receiver>: " + parser.getName();
2098 } else {
2099 outError[0] = "Bad element under <activity>: " + parser.getName();
2100 }
2101 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002102 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002103 }
2104 }
2105
2106 if (!setExported) {
2107 a.info.exported = a.intents.size() > 0;
2108 }
2109
2110 return a;
2111 }
2112
2113 private Activity parseActivityAlias(Package owner, Resources res,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002114 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2115 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002116 TypedArray sa = res.obtainAttributes(attrs,
2117 com.android.internal.R.styleable.AndroidManifestActivityAlias);
2118
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002119 String targetActivity = sa.getNonConfigurationString(
2120 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002121 if (targetActivity == null) {
2122 outError[0] = "<activity-alias> does not specify android:targetActivity";
2123 sa.recycle();
2124 return null;
2125 }
2126
2127 targetActivity = buildClassName(owner.applicationInfo.packageName,
2128 targetActivity, outError);
2129 if (targetActivity == null) {
2130 sa.recycle();
2131 return null;
2132 }
2133
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002134 if (mParseActivityAliasArgs == null) {
2135 mParseActivityAliasArgs = new ParseComponentArgs(owner, outError,
2136 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
2137 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
2138 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07002139 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002140 mSeparateProcesses,
2141 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002142 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002143 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
2144 mParseActivityAliasArgs.tag = "<activity-alias>";
2145 }
2146
2147 mParseActivityAliasArgs.sa = sa;
2148 mParseActivityAliasArgs.flags = flags;
2149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002150 Activity target = null;
2151
2152 final int NA = owner.activities.size();
2153 for (int i=0; i<NA; i++) {
2154 Activity t = owner.activities.get(i);
2155 if (targetActivity.equals(t.info.name)) {
2156 target = t;
2157 break;
2158 }
2159 }
2160
2161 if (target == null) {
2162 outError[0] = "<activity-alias> target activity " + targetActivity
2163 + " not found in manifest";
2164 sa.recycle();
2165 return null;
2166 }
2167
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002168 ActivityInfo info = new ActivityInfo();
2169 info.targetActivity = targetActivity;
2170 info.configChanges = target.info.configChanges;
2171 info.flags = target.info.flags;
2172 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07002173 info.logo = target.info.logo;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002174 info.labelRes = target.info.labelRes;
2175 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
2176 info.launchMode = target.info.launchMode;
2177 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002178 if (info.descriptionRes == 0) {
2179 info.descriptionRes = target.info.descriptionRes;
2180 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002181 info.screenOrientation = target.info.screenOrientation;
2182 info.taskAffinity = target.info.taskAffinity;
2183 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07002184 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07002185 info.uiOptions = target.info.uiOptions;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002186
2187 Activity a = new Activity(mParseActivityAliasArgs, info);
2188 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002189 sa.recycle();
2190 return null;
2191 }
2192
2193 final boolean setExported = sa.hasValue(
2194 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
2195 if (setExported) {
2196 a.info.exported = sa.getBoolean(
2197 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
2198 }
2199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002201 str = sa.getNonConfigurationString(
2202 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002203 if (str != null) {
2204 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
2205 }
2206
2207 sa.recycle();
2208
2209 if (outError[0] != null) {
2210 return null;
2211 }
2212
2213 int outerDepth = parser.getDepth();
2214 int type;
2215 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2216 && (type != XmlPullParser.END_TAG
2217 || parser.getDepth() > outerDepth)) {
2218 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2219 continue;
2220 }
2221
2222 if (parser.getName().equals("intent-filter")) {
2223 ActivityIntentInfo intent = new ActivityIntentInfo(a);
2224 if (!parseIntent(res, parser, attrs, flags, intent, outError, true)) {
2225 return null;
2226 }
2227 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002228 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002229 + mArchiveSourcePath + " "
2230 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002231 } else {
2232 a.intents.add(intent);
2233 }
2234 } else if (parser.getName().equals("meta-data")) {
2235 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
2236 outError)) == null) {
2237 return null;
2238 }
2239 } else {
2240 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002241 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002242 + " at " + mArchiveSourcePath + " "
2243 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002244 XmlUtils.skipCurrentTag(parser);
2245 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002246 } else {
2247 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
2248 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002249 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250 }
2251 }
2252
2253 if (!setExported) {
2254 a.info.exported = a.intents.size() > 0;
2255 }
2256
2257 return a;
2258 }
2259
2260 private Provider parseProvider(Package owner, Resources res,
2261 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2262 throws XmlPullParserException, IOException {
2263 TypedArray sa = res.obtainAttributes(attrs,
2264 com.android.internal.R.styleable.AndroidManifestProvider);
2265
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002266 if (mParseProviderArgs == null) {
2267 mParseProviderArgs = new ParseComponentArgs(owner, outError,
2268 com.android.internal.R.styleable.AndroidManifestProvider_name,
2269 com.android.internal.R.styleable.AndroidManifestProvider_label,
2270 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07002271 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002272 mSeparateProcesses,
2273 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002274 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002275 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
2276 mParseProviderArgs.tag = "<provider>";
2277 }
2278
2279 mParseProviderArgs.sa = sa;
2280 mParseProviderArgs.flags = flags;
2281
2282 Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
2283 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002284 sa.recycle();
2285 return null;
2286 }
2287
2288 p.info.exported = sa.getBoolean(
2289 com.android.internal.R.styleable.AndroidManifestProvider_exported, true);
2290
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002291 String cpname = sa.getNonConfigurationString(
2292 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293
2294 p.info.isSyncable = sa.getBoolean(
2295 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
2296 false);
2297
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002298 String permission = sa.getNonConfigurationString(
2299 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
2300 String str = sa.getNonConfigurationString(
2301 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002302 if (str == null) {
2303 str = permission;
2304 }
2305 if (str == null) {
2306 p.info.readPermission = owner.applicationInfo.permission;
2307 } else {
2308 p.info.readPermission =
2309 str.length() > 0 ? str.toString().intern() : null;
2310 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002311 str = sa.getNonConfigurationString(
2312 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002313 if (str == null) {
2314 str = permission;
2315 }
2316 if (str == null) {
2317 p.info.writePermission = owner.applicationInfo.permission;
2318 } else {
2319 p.info.writePermission =
2320 str.length() > 0 ? str.toString().intern() : null;
2321 }
2322
2323 p.info.grantUriPermissions = sa.getBoolean(
2324 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
2325 false);
2326
2327 p.info.multiprocess = sa.getBoolean(
2328 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
2329 false);
2330
2331 p.info.initOrder = sa.getInt(
2332 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
2333 0);
2334
2335 sa.recycle();
2336
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002337 if ((owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07002338 // A heavy-weight application can not have providers in its main process
2339 // We can do direct compare because we intern all strings.
2340 if (p.info.processName == owner.packageName) {
2341 outError[0] = "Heavy-weight applications can not have providers in main process";
2342 return null;
2343 }
2344 }
2345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002346 if (cpname == null) {
2347 outError[0] = "<provider> does not incude authorities attribute";
2348 return null;
2349 }
2350 p.info.authority = cpname.intern();
2351
2352 if (!parseProviderTags(res, parser, attrs, p, outError)) {
2353 return null;
2354 }
2355
2356 return p;
2357 }
2358
2359 private boolean parseProviderTags(Resources res,
2360 XmlPullParser parser, AttributeSet attrs,
2361 Provider outInfo, String[] outError)
2362 throws XmlPullParserException, IOException {
2363 int outerDepth = parser.getDepth();
2364 int type;
2365 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2366 && (type != XmlPullParser.END_TAG
2367 || parser.getDepth() > outerDepth)) {
2368 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2369 continue;
2370 }
2371
2372 if (parser.getName().equals("meta-data")) {
2373 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
2374 outInfo.metaData, outError)) == null) {
2375 return false;
2376 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002378 } else if (parser.getName().equals("grant-uri-permission")) {
2379 TypedArray sa = res.obtainAttributes(attrs,
2380 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
2381
2382 PatternMatcher pa = null;
2383
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002384 String str = sa.getNonConfigurationString(
2385 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002386 if (str != null) {
2387 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
2388 }
2389
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002390 str = sa.getNonConfigurationString(
2391 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002392 if (str != null) {
2393 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
2394 }
2395
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002396 str = sa.getNonConfigurationString(
2397 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002398 if (str != null) {
2399 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
2400 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 sa.recycle();
2403
2404 if (pa != null) {
2405 if (outInfo.info.uriPermissionPatterns == null) {
2406 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
2407 outInfo.info.uriPermissionPatterns[0] = pa;
2408 } else {
2409 final int N = outInfo.info.uriPermissionPatterns.length;
2410 PatternMatcher[] newp = new PatternMatcher[N+1];
2411 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
2412 newp[N] = pa;
2413 outInfo.info.uriPermissionPatterns = newp;
2414 }
2415 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002416 } else {
2417 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002418 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002419 + parser.getName() + " at " + mArchiveSourcePath + " "
2420 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002421 XmlUtils.skipCurrentTag(parser);
2422 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002423 } else {
2424 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
2425 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002426 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002427 }
2428 XmlUtils.skipCurrentTag(parser);
2429
2430 } else if (parser.getName().equals("path-permission")) {
2431 TypedArray sa = res.obtainAttributes(attrs,
2432 com.android.internal.R.styleable.AndroidManifestPathPermission);
2433
2434 PathPermission pa = null;
2435
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002436 String permission = sa.getNonConfigurationString(
2437 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
2438 String readPermission = sa.getNonConfigurationString(
2439 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002440 if (readPermission == null) {
2441 readPermission = permission;
2442 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002443 String writePermission = sa.getNonConfigurationString(
2444 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002445 if (writePermission == null) {
2446 writePermission = permission;
2447 }
2448
2449 boolean havePerm = false;
2450 if (readPermission != null) {
2451 readPermission = readPermission.intern();
2452 havePerm = true;
2453 }
2454 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00002455 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002456 havePerm = true;
2457 }
2458
2459 if (!havePerm) {
2460 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002461 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002462 + parser.getName() + " at " + mArchiveSourcePath + " "
2463 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002464 XmlUtils.skipCurrentTag(parser);
2465 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002466 } else {
2467 outError[0] = "No readPermission or writePermssion for <path-permission>";
2468 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002469 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002470 }
2471
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002472 String path = sa.getNonConfigurationString(
2473 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002474 if (path != null) {
2475 pa = new PathPermission(path,
2476 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
2477 }
2478
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002479 path = sa.getNonConfigurationString(
2480 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002481 if (path != null) {
2482 pa = new PathPermission(path,
2483 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
2484 }
2485
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002486 path = sa.getNonConfigurationString(
2487 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002488 if (path != null) {
2489 pa = new PathPermission(path,
2490 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
2491 }
2492
2493 sa.recycle();
2494
2495 if (pa != null) {
2496 if (outInfo.info.pathPermissions == null) {
2497 outInfo.info.pathPermissions = new PathPermission[1];
2498 outInfo.info.pathPermissions[0] = pa;
2499 } else {
2500 final int N = outInfo.info.pathPermissions.length;
2501 PathPermission[] newp = new PathPermission[N+1];
2502 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
2503 newp[N] = pa;
2504 outInfo.info.pathPermissions = newp;
2505 }
2506 } else {
2507 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002508 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002509 + parser.getName() + " at " + mArchiveSourcePath + " "
2510 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002511 XmlUtils.skipCurrentTag(parser);
2512 continue;
2513 }
2514 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
2515 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516 }
2517 XmlUtils.skipCurrentTag(parser);
2518
2519 } else {
2520 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002521 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002522 + parser.getName() + " at " + mArchiveSourcePath + " "
2523 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 XmlUtils.skipCurrentTag(parser);
2525 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002526 } else {
2527 outError[0] = "Bad element under <provider>: " + parser.getName();
2528 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002529 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002530 }
2531 }
2532 return true;
2533 }
2534
2535 private Service parseService(Package owner, Resources res,
2536 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2537 throws XmlPullParserException, IOException {
2538 TypedArray sa = res.obtainAttributes(attrs,
2539 com.android.internal.R.styleable.AndroidManifestService);
2540
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002541 if (mParseServiceArgs == null) {
2542 mParseServiceArgs = new ParseComponentArgs(owner, outError,
2543 com.android.internal.R.styleable.AndroidManifestService_name,
2544 com.android.internal.R.styleable.AndroidManifestService_label,
2545 com.android.internal.R.styleable.AndroidManifestService_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07002546 com.android.internal.R.styleable.AndroidManifestService_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002547 mSeparateProcesses,
2548 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002549 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002550 com.android.internal.R.styleable.AndroidManifestService_enabled);
2551 mParseServiceArgs.tag = "<service>";
2552 }
2553
2554 mParseServiceArgs.sa = sa;
2555 mParseServiceArgs.flags = flags;
2556
2557 Service s = new Service(mParseServiceArgs, new ServiceInfo());
2558 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002559 sa.recycle();
2560 return null;
2561 }
2562
2563 final boolean setExported = sa.hasValue(
2564 com.android.internal.R.styleable.AndroidManifestService_exported);
2565 if (setExported) {
2566 s.info.exported = sa.getBoolean(
2567 com.android.internal.R.styleable.AndroidManifestService_exported, false);
2568 }
2569
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002570 String str = sa.getNonConfigurationString(
2571 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002572 if (str == null) {
2573 s.info.permission = owner.applicationInfo.permission;
2574 } else {
2575 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
2576 }
2577
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002578 s.info.flags = 0;
2579 if (sa.getBoolean(
2580 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
2581 false)) {
2582 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
2583 }
2584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002585 sa.recycle();
2586
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002587 if ((owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07002588 // A heavy-weight application can not have services in its main process
2589 // We can do direct compare because we intern all strings.
2590 if (s.info.processName == owner.packageName) {
2591 outError[0] = "Heavy-weight applications can not have services in main process";
2592 return null;
2593 }
2594 }
2595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596 int outerDepth = parser.getDepth();
2597 int type;
2598 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2599 && (type != XmlPullParser.END_TAG
2600 || parser.getDepth() > outerDepth)) {
2601 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2602 continue;
2603 }
2604
2605 if (parser.getName().equals("intent-filter")) {
2606 ServiceIntentInfo intent = new ServiceIntentInfo(s);
2607 if (!parseIntent(res, parser, attrs, flags, intent, outError, false)) {
2608 return null;
2609 }
2610
2611 s.intents.add(intent);
2612 } else if (parser.getName().equals("meta-data")) {
2613 if ((s.metaData=parseMetaData(res, parser, attrs, s.metaData,
2614 outError)) == null) {
2615 return null;
2616 }
2617 } else {
2618 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002619 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002620 + parser.getName() + " at " + mArchiveSourcePath + " "
2621 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 XmlUtils.skipCurrentTag(parser);
2623 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002624 } else {
2625 outError[0] = "Bad element under <service>: " + parser.getName();
2626 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002627 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002628 }
2629 }
2630
2631 if (!setExported) {
2632 s.info.exported = s.intents.size() > 0;
2633 }
2634
2635 return s;
2636 }
2637
2638 private boolean parseAllMetaData(Resources res,
2639 XmlPullParser parser, AttributeSet attrs, String tag,
2640 Component outInfo, String[] outError)
2641 throws XmlPullParserException, IOException {
2642 int outerDepth = parser.getDepth();
2643 int type;
2644 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2645 && (type != XmlPullParser.END_TAG
2646 || parser.getDepth() > outerDepth)) {
2647 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2648 continue;
2649 }
2650
2651 if (parser.getName().equals("meta-data")) {
2652 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
2653 outInfo.metaData, outError)) == null) {
2654 return false;
2655 }
2656 } else {
2657 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002658 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002659 + parser.getName() + " at " + mArchiveSourcePath + " "
2660 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 XmlUtils.skipCurrentTag(parser);
2662 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002663 } else {
2664 outError[0] = "Bad element under " + tag + ": " + parser.getName();
2665 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002667 }
2668 }
2669 return true;
2670 }
2671
2672 private Bundle parseMetaData(Resources res,
2673 XmlPullParser parser, AttributeSet attrs,
2674 Bundle data, String[] outError)
2675 throws XmlPullParserException, IOException {
2676
2677 TypedArray sa = res.obtainAttributes(attrs,
2678 com.android.internal.R.styleable.AndroidManifestMetaData);
2679
2680 if (data == null) {
2681 data = new Bundle();
2682 }
2683
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002684 String name = sa.getNonConfigurationString(
2685 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002686 if (name == null) {
2687 outError[0] = "<meta-data> requires an android:name attribute";
2688 sa.recycle();
2689 return null;
2690 }
2691
Dianne Hackborn854060a2009-07-09 18:14:31 -07002692 name = name.intern();
2693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694 TypedValue v = sa.peekValue(
2695 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
2696 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002697 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002698 data.putInt(name, v.resourceId);
2699 } else {
2700 v = sa.peekValue(
2701 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07002702 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002703 if (v != null) {
2704 if (v.type == TypedValue.TYPE_STRING) {
2705 CharSequence cs = v.coerceToString();
Dianne Hackborn854060a2009-07-09 18:14:31 -07002706 data.putString(name, cs != null ? cs.toString().intern() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002707 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
2708 data.putBoolean(name, v.data != 0);
2709 } else if (v.type >= TypedValue.TYPE_FIRST_INT
2710 && v.type <= TypedValue.TYPE_LAST_INT) {
2711 data.putInt(name, v.data);
2712 } else if (v.type == TypedValue.TYPE_FLOAT) {
2713 data.putFloat(name, v.getFloat());
2714 } else {
2715 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002716 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002717 + parser.getName() + " at " + mArchiveSourcePath + " "
2718 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 } else {
2720 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
2721 data = null;
2722 }
2723 }
2724 } else {
2725 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
2726 data = null;
2727 }
2728 }
2729
2730 sa.recycle();
2731
2732 XmlUtils.skipCurrentTag(parser);
2733
2734 return data;
2735 }
2736
Kenny Root05ca4c92011-09-15 10:36:25 -07002737 private static VerifierInfo parseVerifier(Resources res, XmlPullParser parser,
2738 AttributeSet attrs, int flags, String[] outError) throws XmlPullParserException,
2739 IOException {
2740 final TypedArray sa = res.obtainAttributes(attrs,
2741 com.android.internal.R.styleable.AndroidManifestPackageVerifier);
2742
2743 final String packageName = sa.getNonResourceString(
2744 com.android.internal.R.styleable.AndroidManifestPackageVerifier_name);
2745
2746 final String encodedPublicKey = sa.getNonResourceString(
2747 com.android.internal.R.styleable.AndroidManifestPackageVerifier_publicKey);
2748
2749 sa.recycle();
2750
2751 if (packageName == null || packageName.length() == 0) {
2752 Slog.i(TAG, "verifier package name was null; skipping");
2753 return null;
2754 } else if (encodedPublicKey == null) {
2755 Slog.i(TAG, "verifier " + packageName + " public key was null; skipping");
2756 }
2757
2758 EncodedKeySpec keySpec;
2759 try {
2760 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
2761 keySpec = new X509EncodedKeySpec(encoded);
2762 } catch (IllegalArgumentException e) {
2763 Slog.i(TAG, "Could not parse verifier " + packageName + " public key; invalid Base64");
2764 return null;
2765 }
2766
2767 /* First try the key as an RSA key. */
2768 try {
2769 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
2770 final PublicKey publicKey = keyFactory.generatePublic(keySpec);
2771 return new VerifierInfo(packageName, publicKey);
2772 } catch (NoSuchAlgorithmException e) {
2773 Log.wtf(TAG, "Could not parse public key because RSA isn't included in build");
2774 return null;
2775 } catch (InvalidKeySpecException e) {
2776 // Not a RSA public key.
2777 }
2778
2779 /* Now try it as a DSA key. */
2780 try {
2781 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
2782 final PublicKey publicKey = keyFactory.generatePublic(keySpec);
2783 return new VerifierInfo(packageName, publicKey);
2784 } catch (NoSuchAlgorithmException e) {
2785 Log.wtf(TAG, "Could not parse public key because DSA isn't included in build");
2786 return null;
2787 } catch (InvalidKeySpecException e) {
2788 // Not a DSA public key.
2789 }
2790
2791 return null;
2792 }
2793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002794 private static final String ANDROID_RESOURCES
2795 = "http://schemas.android.com/apk/res/android";
2796
2797 private boolean parseIntent(Resources res,
2798 XmlPullParser parser, AttributeSet attrs, int flags,
2799 IntentInfo outInfo, String[] outError, boolean isActivity)
2800 throws XmlPullParserException, IOException {
2801
2802 TypedArray sa = res.obtainAttributes(attrs,
2803 com.android.internal.R.styleable.AndroidManifestIntentFilter);
2804
2805 int priority = sa.getInt(
2806 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002807 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08002808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002809 TypedValue v = sa.peekValue(
2810 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
2811 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
2812 outInfo.nonLocalizedLabel = v.coerceToString();
2813 }
2814
2815 outInfo.icon = sa.getResourceId(
2816 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
Adam Powell81cd2e92010-04-21 16:35:18 -07002817
2818 outInfo.logo = sa.getResourceId(
2819 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820
2821 sa.recycle();
2822
2823 int outerDepth = parser.getDepth();
2824 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07002825 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2826 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2827 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002828 continue;
2829 }
2830
2831 String nodeName = parser.getName();
2832 if (nodeName.equals("action")) {
2833 String value = attrs.getAttributeValue(
2834 ANDROID_RESOURCES, "name");
2835 if (value == null || value == "") {
2836 outError[0] = "No value supplied for <android:name>";
2837 return false;
2838 }
2839 XmlUtils.skipCurrentTag(parser);
2840
2841 outInfo.addAction(value);
2842 } else if (nodeName.equals("category")) {
2843 String value = attrs.getAttributeValue(
2844 ANDROID_RESOURCES, "name");
2845 if (value == null || value == "") {
2846 outError[0] = "No value supplied for <android:name>";
2847 return false;
2848 }
2849 XmlUtils.skipCurrentTag(parser);
2850
2851 outInfo.addCategory(value);
2852
2853 } else if (nodeName.equals("data")) {
2854 sa = res.obtainAttributes(attrs,
2855 com.android.internal.R.styleable.AndroidManifestData);
2856
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002857 String str = sa.getNonConfigurationString(
2858 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002859 if (str != null) {
2860 try {
2861 outInfo.addDataType(str);
2862 } catch (IntentFilter.MalformedMimeTypeException e) {
2863 outError[0] = e.toString();
2864 sa.recycle();
2865 return false;
2866 }
2867 }
2868
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002869 str = sa.getNonConfigurationString(
2870 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002871 if (str != null) {
2872 outInfo.addDataScheme(str);
2873 }
2874
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002875 String host = sa.getNonConfigurationString(
2876 com.android.internal.R.styleable.AndroidManifestData_host, 0);
2877 String port = sa.getNonConfigurationString(
2878 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002879 if (host != null) {
2880 outInfo.addDataAuthority(host, port);
2881 }
2882
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002883 str = sa.getNonConfigurationString(
2884 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002885 if (str != null) {
2886 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
2887 }
2888
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002889 str = sa.getNonConfigurationString(
2890 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002891 if (str != null) {
2892 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
2893 }
2894
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002895 str = sa.getNonConfigurationString(
2896 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002897 if (str != null) {
2898 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
2899 }
2900
2901 sa.recycle();
2902 XmlUtils.skipCurrentTag(parser);
2903 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002904 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002905 + parser.getName() + " at " + mArchiveSourcePath + " "
2906 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002907 XmlUtils.skipCurrentTag(parser);
2908 } else {
2909 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
2910 return false;
2911 }
2912 }
2913
2914 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07002915
2916 if (DEBUG_PARSER) {
2917 final StringBuilder cats = new StringBuilder("Intent d=");
2918 cats.append(outInfo.hasDefault);
2919 cats.append(", cat=");
2920
2921 final Iterator<String> it = outInfo.categoriesIterator();
2922 if (it != null) {
2923 while (it.hasNext()) {
2924 cats.append(' ');
2925 cats.append(it.next());
2926 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002927 }
Kenny Rootd2d29252011-08-08 11:27:57 -07002928 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929 }
2930
2931 return true;
2932 }
2933
2934 public final static class Package {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002935 public String packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936
2937 // For now we only support one application per package.
2938 public final ApplicationInfo applicationInfo = new ApplicationInfo();
2939
2940 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
2941 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
2942 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
2943 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
2944 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
2945 public final ArrayList<Service> services = new ArrayList<Service>(0);
2946 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
2947
2948 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
2949
Dianne Hackborn854060a2009-07-09 18:14:31 -07002950 public ArrayList<String> protectedBroadcasts;
2951
Dianne Hackborn49237342009-08-27 20:08:01 -07002952 public ArrayList<String> usesLibraries = null;
2953 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 public String[] usesLibraryFiles = null;
2955
Dianne Hackbornc1552392010-03-03 16:19:01 -08002956 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002957 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002958 public ArrayList<String> mAdoptPermissions = null;
2959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002960 // We store the application meta-data independently to avoid multiple unwanted references
2961 public Bundle mAppMetaData = null;
2962
2963 // If this is a 3rd party app, this is the path of the zip file.
2964 public String mPath;
2965
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002966 // The version code declared for this package.
2967 public int mVersionCode;
2968
2969 // The version name declared for this package.
2970 public String mVersionName;
2971
2972 // The shared user id that this package wants to use.
2973 public String mSharedUserId;
2974
2975 // The shared user label that this package wants to use.
2976 public int mSharedUserLabel;
2977
2978 // Signatures that were read from the package.
2979 public Signature mSignatures[];
2980
2981 // For use by package manager service for quick lookup of
2982 // preferred up order.
2983 public int mPreferredOrder = 0;
2984
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002985 // For use by the package manager to keep track of the path to the
2986 // file an app came from.
2987 public String mScanPath;
2988
2989 // For use by package manager to keep track of where it has done dexopt.
2990 public boolean mDidDexOpt;
2991
Dianne Hackborn46730fc2010-07-24 16:32:42 -07002992 // User set enabled state.
2993 public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2994
Dianne Hackborne7f97212011-02-24 14:40:20 -08002995 // Whether the package has been stopped.
2996 public boolean mSetStopped = false;
2997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002998 // Additional data supplied by callers.
2999 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07003000
3001 // Whether an operation is currently pending on this package
3002 public boolean mOperationPending;
3003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003004 /*
3005 * Applications hardware preferences
3006 */
3007 public final ArrayList<ConfigurationInfo> configPreferences =
3008 new ArrayList<ConfigurationInfo>();
3009
Dianne Hackborn49237342009-08-27 20:08:01 -07003010 /*
3011 * Applications requested features
3012 */
3013 public ArrayList<FeatureInfo> reqFeatures = null;
3014
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08003015 public int installLocation;
3016
Kenny Rootbcc954d2011-08-08 16:19:08 -07003017 /**
3018 * Digest suitable for comparing whether this package's manifest is the
3019 * same as another.
3020 */
3021 public ManifestDigest manifestDigest;
3022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003023 public Package(String _name) {
3024 packageName = _name;
3025 applicationInfo.packageName = _name;
3026 applicationInfo.uid = -1;
3027 }
3028
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003029 public void setPackageName(String newName) {
3030 packageName = newName;
3031 applicationInfo.packageName = newName;
3032 for (int i=permissions.size()-1; i>=0; i--) {
3033 permissions.get(i).setPackageName(newName);
3034 }
3035 for (int i=permissionGroups.size()-1; i>=0; i--) {
3036 permissionGroups.get(i).setPackageName(newName);
3037 }
3038 for (int i=activities.size()-1; i>=0; i--) {
3039 activities.get(i).setPackageName(newName);
3040 }
3041 for (int i=receivers.size()-1; i>=0; i--) {
3042 receivers.get(i).setPackageName(newName);
3043 }
3044 for (int i=providers.size()-1; i>=0; i--) {
3045 providers.get(i).setPackageName(newName);
3046 }
3047 for (int i=services.size()-1; i>=0; i--) {
3048 services.get(i).setPackageName(newName);
3049 }
3050 for (int i=instrumentation.size()-1; i>=0; i--) {
3051 instrumentation.get(i).setPackageName(newName);
3052 }
3053 }
3054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055 public String toString() {
3056 return "Package{"
3057 + Integer.toHexString(System.identityHashCode(this))
3058 + " " + packageName + "}";
3059 }
3060 }
3061
3062 public static class Component<II extends IntentInfo> {
3063 public final Package owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003064 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003065 public final String className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 public Bundle metaData;
3067
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003068 ComponentName componentName;
3069 String componentShortName;
3070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003071 public Component(Package _owner) {
3072 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003073 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003074 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003075 }
3076
3077 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
3078 owner = args.owner;
3079 intents = new ArrayList<II>(0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003080 String name = args.sa.getNonConfigurationString(args.nameRes, 0);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003081 if (name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003082 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003083 args.outError[0] = args.tag + " does not specify android:name";
3084 return;
3085 }
3086
3087 outInfo.name
3088 = buildClassName(owner.applicationInfo.packageName, name, args.outError);
3089 if (outInfo.name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003090 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003091 args.outError[0] = args.tag + " does not have valid android:name";
3092 return;
3093 }
3094
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003095 className = outInfo.name;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003096
3097 int iconVal = args.sa.getResourceId(args.iconRes, 0);
3098 if (iconVal != 0) {
3099 outInfo.icon = iconVal;
3100 outInfo.nonLocalizedLabel = null;
3101 }
Adam Powell81cd2e92010-04-21 16:35:18 -07003102
3103 int logoVal = args.sa.getResourceId(args.logoRes, 0);
3104 if (logoVal != 0) {
3105 outInfo.logo = logoVal;
3106 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003107
3108 TypedValue v = args.sa.peekValue(args.labelRes);
3109 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
3110 outInfo.nonLocalizedLabel = v.coerceToString();
3111 }
3112
3113 outInfo.packageName = owner.packageName;
3114 }
3115
3116 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
3117 this(args, (PackageItemInfo)outInfo);
3118 if (args.outError[0] != null) {
3119 return;
3120 }
3121
3122 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003123 CharSequence pname;
3124 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3125 pname = args.sa.getNonConfigurationString(args.processRes, 0);
3126 } else {
3127 // Some older apps have been seen to use a resource reference
3128 // here that on older builds was ignored (with a warning). We
3129 // need to continue to do this for them so they don't break.
3130 pname = args.sa.getNonResourceString(args.processRes);
3131 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003132 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003133 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003134 args.flags, args.sepProcesses, args.outError);
3135 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003136
3137 if (args.descriptionRes != 0) {
3138 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
3139 }
3140
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003141 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003142 }
3143
3144 public Component(Component<II> clone) {
3145 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003146 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003147 className = clone.className;
3148 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003149 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003150 }
3151
3152 public ComponentName getComponentName() {
3153 if (componentName != null) {
3154 return componentName;
3155 }
3156 if (className != null) {
3157 componentName = new ComponentName(owner.applicationInfo.packageName,
3158 className);
3159 }
3160 return componentName;
3161 }
3162
3163 public String getComponentShortName() {
3164 if (componentShortName != null) {
3165 return componentShortName;
3166 }
3167 ComponentName component = getComponentName();
3168 if (component != null) {
3169 componentShortName = component.flattenToShortString();
3170 }
3171 return componentShortName;
3172 }
3173
3174 public void setPackageName(String packageName) {
3175 componentName = null;
3176 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003177 }
3178 }
3179
3180 public final static class Permission extends Component<IntentInfo> {
3181 public final PermissionInfo info;
3182 public boolean tree;
3183 public PermissionGroup group;
3184
3185 public Permission(Package _owner) {
3186 super(_owner);
3187 info = new PermissionInfo();
3188 }
3189
3190 public Permission(Package _owner, PermissionInfo _info) {
3191 super(_owner);
3192 info = _info;
3193 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003194
3195 public void setPackageName(String packageName) {
3196 super.setPackageName(packageName);
3197 info.packageName = packageName;
3198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003199
3200 public String toString() {
3201 return "Permission{"
3202 + Integer.toHexString(System.identityHashCode(this))
3203 + " " + info.name + "}";
3204 }
3205 }
3206
3207 public final static class PermissionGroup extends Component<IntentInfo> {
3208 public final PermissionGroupInfo info;
3209
3210 public PermissionGroup(Package _owner) {
3211 super(_owner);
3212 info = new PermissionGroupInfo();
3213 }
3214
3215 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
3216 super(_owner);
3217 info = _info;
3218 }
3219
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003220 public void setPackageName(String packageName) {
3221 super.setPackageName(packageName);
3222 info.packageName = packageName;
3223 }
3224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003225 public String toString() {
3226 return "PermissionGroup{"
3227 + Integer.toHexString(System.identityHashCode(this))
3228 + " " + info.name + "}";
3229 }
3230 }
3231
3232 private static boolean copyNeeded(int flags, Package p, Bundle metaData) {
Dianne Hackborn46730fc2010-07-24 16:32:42 -07003233 if (p.mSetEnabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
3234 boolean enabled = p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
3235 if (p.applicationInfo.enabled != enabled) {
3236 return true;
3237 }
3238 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003239 if ((flags & PackageManager.GET_META_DATA) != 0
3240 && (metaData != null || p.mAppMetaData != null)) {
3241 return true;
3242 }
3243 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
3244 && p.usesLibraryFiles != null) {
3245 return true;
3246 }
3247 return false;
3248 }
3249
3250 public static ApplicationInfo generateApplicationInfo(Package p, int flags) {
Amith Yamasani742a6712011-05-04 14:49:28 -07003251 return generateApplicationInfo(p, flags, UserId.getUserId(Binder.getCallingUid()));
3252 }
3253
3254 public static ApplicationInfo generateApplicationInfo(Package p, int flags, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 if (p == null) return null;
Amith Yamasani742a6712011-05-04 14:49:28 -07003256 if (!copyNeeded(flags, p, null) && userId == 0) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07003257 // CompatibilityMode is global state. It's safe to modify the instance
3258 // of the package.
3259 if (!sCompatibilityModeEnabled) {
3260 p.applicationInfo.disableCompatibilityMode();
3261 }
Dianne Hackborne7f97212011-02-24 14:40:20 -08003262 if (p.mSetStopped) {
3263 p.applicationInfo.flags |= ApplicationInfo.FLAG_STOPPED;
3264 } else {
3265 p.applicationInfo.flags &= ~ApplicationInfo.FLAG_STOPPED;
3266 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 return p.applicationInfo;
3268 }
3269
3270 // Make shallow copy so we can store the metadata/libraries safely
3271 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Amith Yamasani742a6712011-05-04 14:49:28 -07003272 if (userId != 0) {
3273 ai.uid = UserId.getUid(userId, ai.uid);
3274 ai.dataDir = PackageManager.getDataDirForUser(userId, ai.packageName);
3275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003276 if ((flags & PackageManager.GET_META_DATA) != 0) {
3277 ai.metaData = p.mAppMetaData;
3278 }
3279 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
3280 ai.sharedLibraryFiles = p.usesLibraryFiles;
3281 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07003282 if (!sCompatibilityModeEnabled) {
3283 ai.disableCompatibilityMode();
3284 }
Dianne Hackborne7f97212011-02-24 14:40:20 -08003285 if (p.mSetStopped) {
3286 p.applicationInfo.flags |= ApplicationInfo.FLAG_STOPPED;
3287 } else {
3288 p.applicationInfo.flags &= ~ApplicationInfo.FLAG_STOPPED;
3289 }
John Reck4b7b7cc2011-02-02 11:57:44 -08003290 if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
3291 ai.enabled = true;
Dianne Hackborn0ac30312011-06-17 14:49:23 -07003292 } else if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
3293 || p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
John Reck4b7b7cc2011-02-02 11:57:44 -08003294 ai.enabled = false;
3295 }
Dianne Hackborn0ac30312011-06-17 14:49:23 -07003296 ai.enabledSetting = p.mSetEnabled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003297 return ai;
3298 }
3299
3300 public static final PermissionInfo generatePermissionInfo(
3301 Permission p, int flags) {
3302 if (p == null) return null;
3303 if ((flags&PackageManager.GET_META_DATA) == 0) {
3304 return p.info;
3305 }
3306 PermissionInfo pi = new PermissionInfo(p.info);
3307 pi.metaData = p.metaData;
3308 return pi;
3309 }
3310
3311 public static final PermissionGroupInfo generatePermissionGroupInfo(
3312 PermissionGroup pg, int flags) {
3313 if (pg == null) return null;
3314 if ((flags&PackageManager.GET_META_DATA) == 0) {
3315 return pg.info;
3316 }
3317 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
3318 pgi.metaData = pg.metaData;
3319 return pgi;
3320 }
3321
3322 public final static class Activity extends Component<ActivityIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003323 public final ActivityInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003325 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
3326 super(args, _info);
3327 info = _info;
3328 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003329 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003330
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003331 public void setPackageName(String packageName) {
3332 super.setPackageName(packageName);
3333 info.packageName = packageName;
3334 }
3335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003336 public String toString() {
3337 return "Activity{"
3338 + Integer.toHexString(System.identityHashCode(this))
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003339 + " " + getComponentShortName() + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 }
3341 }
3342
Amith Yamasani742a6712011-05-04 14:49:28 -07003343 public static final ActivityInfo generateActivityInfo(Activity a, int flags, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 if (a == null) return null;
Amith Yamasani742a6712011-05-04 14:49:28 -07003345 if (!copyNeeded(flags, a.owner, a.metaData) && userId == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346 return a.info;
3347 }
3348 // Make shallow copies so we can store the metadata safely
3349 ActivityInfo ai = new ActivityInfo(a.info);
3350 ai.metaData = a.metaData;
Amith Yamasani742a6712011-05-04 14:49:28 -07003351 ai.applicationInfo = generateApplicationInfo(a.owner, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003352 return ai;
3353 }
3354
3355 public final static class Service extends Component<ServiceIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003356 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003357
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003358 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
3359 super(args, _info);
3360 info = _info;
3361 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003363
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003364 public void setPackageName(String packageName) {
3365 super.setPackageName(packageName);
3366 info.packageName = packageName;
3367 }
3368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003369 public String toString() {
3370 return "Service{"
3371 + Integer.toHexString(System.identityHashCode(this))
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003372 + " " + getComponentShortName() + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003373 }
3374 }
3375
Amith Yamasani742a6712011-05-04 14:49:28 -07003376 public static final ServiceInfo generateServiceInfo(Service s, int flags, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377 if (s == null) return null;
Amith Yamasani742a6712011-05-04 14:49:28 -07003378 if (!copyNeeded(flags, s.owner, s.metaData) && userId == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003379 return s.info;
3380 }
3381 // Make shallow copies so we can store the metadata safely
3382 ServiceInfo si = new ServiceInfo(s.info);
3383 si.metaData = s.metaData;
Amith Yamasani742a6712011-05-04 14:49:28 -07003384 si.applicationInfo = generateApplicationInfo(s.owner, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003385 return si;
3386 }
3387
3388 public final static class Provider extends Component {
3389 public final ProviderInfo info;
3390 public boolean syncable;
3391
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003392 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
3393 super(args, _info);
3394 info = _info;
3395 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003396 syncable = false;
3397 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003399 public Provider(Provider existingProvider) {
3400 super(existingProvider);
3401 this.info = existingProvider.info;
3402 this.syncable = existingProvider.syncable;
3403 }
3404
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003405 public void setPackageName(String packageName) {
3406 super.setPackageName(packageName);
3407 info.packageName = packageName;
3408 }
3409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410 public String toString() {
3411 return "Provider{"
3412 + Integer.toHexString(System.identityHashCode(this))
3413 + " " + info.name + "}";
3414 }
3415 }
3416
Amith Yamasani742a6712011-05-04 14:49:28 -07003417 public static final ProviderInfo generateProviderInfo(Provider p, int flags, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003418 if (p == null) return null;
3419 if (!copyNeeded(flags, p.owner, p.metaData)
3420 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Amith Yamasani742a6712011-05-04 14:49:28 -07003421 || p.info.uriPermissionPatterns == null)
3422 && userId == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003423 return p.info;
3424 }
3425 // Make shallow copies so we can store the metadata safely
3426 ProviderInfo pi = new ProviderInfo(p.info);
3427 pi.metaData = p.metaData;
3428 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
3429 pi.uriPermissionPatterns = null;
3430 }
Amith Yamasani742a6712011-05-04 14:49:28 -07003431 pi.applicationInfo = generateApplicationInfo(p.owner, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003432 return pi;
3433 }
3434
3435 public final static class Instrumentation extends Component {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003436 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003438 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
3439 super(args, _info);
3440 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003441 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003442
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003443 public void setPackageName(String packageName) {
3444 super.setPackageName(packageName);
3445 info.packageName = packageName;
3446 }
3447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 public String toString() {
3449 return "Instrumentation{"
3450 + Integer.toHexString(System.identityHashCode(this))
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003451 + " " + getComponentShortName() + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003452 }
3453 }
3454
3455 public static final InstrumentationInfo generateInstrumentationInfo(
3456 Instrumentation i, int flags) {
3457 if (i == null) return null;
3458 if ((flags&PackageManager.GET_META_DATA) == 0) {
3459 return i.info;
3460 }
3461 InstrumentationInfo ii = new InstrumentationInfo(i.info);
3462 ii.metaData = i.metaData;
3463 return ii;
3464 }
3465
3466 public static class IntentInfo extends IntentFilter {
3467 public boolean hasDefault;
3468 public int labelRes;
3469 public CharSequence nonLocalizedLabel;
3470 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07003471 public int logo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003472 }
3473
3474 public final static class ActivityIntentInfo extends IntentInfo {
3475 public final Activity activity;
3476
3477 public ActivityIntentInfo(Activity _activity) {
3478 activity = _activity;
3479 }
3480
3481 public String toString() {
3482 return "ActivityIntentInfo{"
3483 + Integer.toHexString(System.identityHashCode(this))
3484 + " " + activity.info.name + "}";
3485 }
3486 }
3487
3488 public final static class ServiceIntentInfo extends IntentInfo {
3489 public final Service service;
3490
3491 public ServiceIntentInfo(Service _service) {
3492 service = _service;
3493 }
3494
3495 public String toString() {
3496 return "ServiceIntentInfo{"
3497 + Integer.toHexString(System.identityHashCode(this))
3498 + " " + service.info.name + "}";
3499 }
3500 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07003501
3502 /**
3503 * @hide
3504 */
3505 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
3506 sCompatibilityModeEnabled = compatibilityModeEnabled;
3507 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003508}