blob: 8c9cc4e41eef3c6564ef2d4953ca0afbbc44aced [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;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070027import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.os.Bundle;
29import android.os.PatternMatcher;
30import android.util.AttributeSet;
31import android.util.Config;
32import android.util.DisplayMetrics;
33import android.util.Log;
34import android.util.TypedValue;
Dianne Hackborn2269d152010-02-24 19:54:22 -080035import com.android.internal.util.XmlUtils;
Romain Guy529b60a2010-08-03 18:05:47 -070036import org.xmlpull.v1.XmlPullParser;
37import org.xmlpull.v1.XmlPullParserException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038
39import java.io.File;
40import java.io.IOException;
41import java.io.InputStream;
42import java.lang.ref.WeakReference;
43import java.security.cert.Certificate;
44import java.security.cert.CertificateEncodingException;
45import java.util.ArrayList;
46import java.util.Enumeration;
47import java.util.Iterator;
48import java.util.jar.JarEntry;
49import java.util.jar.JarFile;
50
51/**
52 * Package archive parsing
53 *
54 * {@hide}
55 */
56public class PackageParser {
Dianne Hackborna96cbb42009-05-13 15:06:13 -070057 /** @hide */
58 public static class NewPermissionInfo {
59 public final String name;
60 public final int sdkVersion;
61 public final int fileVersion;
62
63 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
64 this.name = name;
65 this.sdkVersion = sdkVersion;
66 this.fileVersion = fileVersion;
67 }
68 }
69
70 /**
71 * List of new permissions that have been added since 1.0.
72 * NOTE: These must be declared in SDK version order, with permissions
73 * added to older SDKs appearing before those added to newer SDKs.
74 * @hide
75 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -070076 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
77 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -070078 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -070079 android.os.Build.VERSION_CODES.DONUT, 0),
80 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
81 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -070082 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083
84 private String mArchiveSourcePath;
85 private String[] mSeparateProcesses;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070086 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
87 private static final String SDK_CODENAME = "REL".equals(Build.VERSION.CODENAME)
88 ? null : Build.VERSION.CODENAME;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089
90 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
91
92 private static final Object mSync = new Object();
93 private static WeakReference<byte[]> mReadBuffer;
94
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -070095 private static boolean sCompatibilityModeEnabled = true;
96 private static final int PARSE_DEFAULT_INSTALL_LOCATION = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -070097
Dianne Hackborn1d442e02009-04-20 18:14:05 -070098 static class ParsePackageItemArgs {
99 final Package owner;
100 final String[] outError;
101 final int nameRes;
102 final int labelRes;
103 final int iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700104 final int logoRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700105
106 String tag;
107 TypedArray sa;
108
109 ParsePackageItemArgs(Package _owner, String[] _outError,
Adam Powell81cd2e92010-04-21 16:35:18 -0700110 int _nameRes, int _labelRes, int _iconRes, int _logoRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700111 owner = _owner;
112 outError = _outError;
113 nameRes = _nameRes;
114 labelRes = _labelRes;
115 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700116 logoRes = _logoRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700117 }
118 }
119
120 static class ParseComponentArgs extends ParsePackageItemArgs {
121 final String[] sepProcesses;
122 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800123 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700124 final int enabledRes;
125 int flags;
126
127 ParseComponentArgs(Package _owner, String[] _outError,
Adam Powell81cd2e92010-04-21 16:35:18 -0700128 int _nameRes, int _labelRes, int _iconRes, int _logoRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800129 String[] _sepProcesses, int _processRes,
130 int _descriptionRes, int _enabledRes) {
Adam Powell81cd2e92010-04-21 16:35:18 -0700131 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _logoRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700132 sepProcesses = _sepProcesses;
133 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800134 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700135 enabledRes = _enabledRes;
136 }
137 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800138
139 /* Light weight package info.
140 * @hide
141 */
142 public static class PackageLite {
143 public String packageName;
144 public int installLocation;
145 public String mScanPath;
146 public PackageLite(String packageName, int installLocation) {
147 this.packageName = packageName;
148 this.installLocation = installLocation;
149 }
150 }
151
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700152 private ParsePackageItemArgs mParseInstrumentationArgs;
153 private ParseComponentArgs mParseActivityArgs;
154 private ParseComponentArgs mParseActivityAliasArgs;
155 private ParseComponentArgs mParseServiceArgs;
156 private ParseComponentArgs mParseProviderArgs;
157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 /** If set to true, we will only allow package files that exactly match
159 * the DTD. Otherwise, we try to get as much from the package as we
160 * can without failing. This should normally be set to false, to
161 * support extensions to the DTD in future versions. */
162 private static final boolean RIGID_PARSER = false;
163
164 private static final String TAG = "PackageParser";
165
166 public PackageParser(String archiveSourcePath) {
167 mArchiveSourcePath = archiveSourcePath;
168 }
169
170 public void setSeparateProcesses(String[] procs) {
171 mSeparateProcesses = procs;
172 }
173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 private static final boolean isPackageFilename(String name) {
175 return name.endsWith(".apk");
176 }
177
178 /**
179 * Generate and return the {@link PackageInfo} for a parsed package.
180 *
181 * @param p the parsed package.
182 * @param flags indicating which optional information is included.
183 */
184 public static PackageInfo generatePackageInfo(PackageParser.Package p,
185 int gids[], int flags) {
186
187 PackageInfo pi = new PackageInfo();
188 pi.packageName = p.packageName;
189 pi.versionCode = p.mVersionCode;
190 pi.versionName = p.mVersionName;
191 pi.sharedUserId = p.mSharedUserId;
192 pi.sharedUserLabel = p.mSharedUserLabel;
193 pi.applicationInfo = p.applicationInfo;
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800194 pi.installLocation = p.installLocation;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 if ((flags&PackageManager.GET_GIDS) != 0) {
196 pi.gids = gids;
197 }
198 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
199 int N = p.configPreferences.size();
200 if (N > 0) {
201 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700202 p.configPreferences.toArray(pi.configPreferences);
203 }
204 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
205 if (N > 0) {
206 pi.reqFeatures = new FeatureInfo[N];
207 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 }
209 }
210 if ((flags&PackageManager.GET_ACTIVITIES) != 0) {
211 int N = p.activities.size();
212 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700213 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
214 pi.activities = new ActivityInfo[N];
215 } else {
216 int num = 0;
217 for (int i=0; i<N; i++) {
218 if (p.activities.get(i).info.enabled) num++;
219 }
220 pi.activities = new ActivityInfo[num];
221 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700222 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 final Activity activity = p.activities.get(i);
224 if (activity.info.enabled
225 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700226 pi.activities[j++] = generateActivityInfo(p.activities.get(i), flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 }
228 }
229 }
230 }
231 if ((flags&PackageManager.GET_RECEIVERS) != 0) {
232 int N = p.receivers.size();
233 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700234 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
235 pi.receivers = new ActivityInfo[N];
236 } else {
237 int num = 0;
238 for (int i=0; i<N; i++) {
239 if (p.receivers.get(i).info.enabled) num++;
240 }
241 pi.receivers = new ActivityInfo[num];
242 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700243 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 final Activity activity = p.receivers.get(i);
245 if (activity.info.enabled
246 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700247 pi.receivers[j++] = generateActivityInfo(p.receivers.get(i), flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 }
249 }
250 }
251 }
252 if ((flags&PackageManager.GET_SERVICES) != 0) {
253 int N = p.services.size();
254 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700255 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
256 pi.services = new ServiceInfo[N];
257 } else {
258 int num = 0;
259 for (int i=0; i<N; i++) {
260 if (p.services.get(i).info.enabled) num++;
261 }
262 pi.services = new ServiceInfo[num];
263 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700264 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 final Service service = p.services.get(i);
266 if (service.info.enabled
267 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700268 pi.services[j++] = generateServiceInfo(p.services.get(i), flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 }
270 }
271 }
272 }
273 if ((flags&PackageManager.GET_PROVIDERS) != 0) {
274 int N = p.providers.size();
275 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700276 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
277 pi.providers = new ProviderInfo[N];
278 } else {
279 int num = 0;
280 for (int i=0; i<N; i++) {
281 if (p.providers.get(i).info.enabled) num++;
282 }
283 pi.providers = new ProviderInfo[num];
284 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700285 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 final Provider provider = p.providers.get(i);
287 if (provider.info.enabled
288 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700289 pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 }
291 }
292 }
293 }
294 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
295 int N = p.instrumentation.size();
296 if (N > 0) {
297 pi.instrumentation = new InstrumentationInfo[N];
298 for (int i=0; i<N; i++) {
299 pi.instrumentation[i] = generateInstrumentationInfo(
300 p.instrumentation.get(i), flags);
301 }
302 }
303 }
304 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
305 int N = p.permissions.size();
306 if (N > 0) {
307 pi.permissions = new PermissionInfo[N];
308 for (int i=0; i<N; i++) {
309 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
310 }
311 }
312 N = p.requestedPermissions.size();
313 if (N > 0) {
314 pi.requestedPermissions = new String[N];
315 for (int i=0; i<N; i++) {
316 pi.requestedPermissions[i] = p.requestedPermissions.get(i);
317 }
318 }
319 }
320 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700321 int N = (p.mSignatures != null) ? p.mSignatures.length : 0;
322 if (N > 0) {
323 pi.signatures = new Signature[N];
324 System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325 }
326 }
327 return pi;
328 }
329
330 private Certificate[] loadCertificates(JarFile jarFile, JarEntry je,
331 byte[] readBuffer) {
332 try {
333 // We must read the stream for the JarEntry to retrieve
334 // its certificates.
335 InputStream is = jarFile.getInputStream(je);
336 while (is.read(readBuffer, 0, readBuffer.length) != -1) {
337 // not using
338 }
339 is.close();
340 return je != null ? je.getCertificates() : null;
341 } catch (IOException e) {
342 Log.w(TAG, "Exception reading " + je.getName() + " in "
343 + jarFile.getName(), e);
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -0700344 } catch (RuntimeException e) {
345 Log.w(TAG, "Exception reading " + je.getName() + " in "
346 + jarFile.getName(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 }
348 return null;
349 }
350
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800351 public final static int PARSE_IS_SYSTEM = 1<<0;
352 public final static int PARSE_CHATTY = 1<<1;
353 public final static int PARSE_MUST_BE_APK = 1<<2;
354 public final static int PARSE_IGNORE_PROCESSES = 1<<3;
355 public final static int PARSE_FORWARD_LOCK = 1<<4;
356 public final static int PARSE_ON_SDCARD = 1<<5;
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700357 public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358
359 public int getParseError() {
360 return mParseError;
361 }
362
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800363 public Package parsePackage(File sourceFile, String destCodePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 DisplayMetrics metrics, int flags) {
365 mParseError = PackageManager.INSTALL_SUCCEEDED;
366
367 mArchiveSourcePath = sourceFile.getPath();
368 if (!sourceFile.isFile()) {
369 Log.w(TAG, "Skipping dir: " + mArchiveSourcePath);
370 mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
371 return null;
372 }
373 if (!isPackageFilename(sourceFile.getName())
374 && (flags&PARSE_MUST_BE_APK) != 0) {
375 if ((flags&PARSE_IS_SYSTEM) == 0) {
376 // We expect to have non-.apk files in the system dir,
377 // so don't warn about them.
378 Log.w(TAG, "Skipping non-package file: " + mArchiveSourcePath);
379 }
380 mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
381 return null;
382 }
383
384 if ((flags&PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
385 TAG, "Scanning package: " + mArchiveSourcePath);
386
387 XmlResourceParser parser = null;
388 AssetManager assmgr = null;
389 boolean assetError = true;
390 try {
391 assmgr = new AssetManager();
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700392 int cookie = assmgr.addAssetPath(mArchiveSourcePath);
393 if(cookie != 0) {
394 parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395 assetError = false;
396 } else {
397 Log.w(TAG, "Failed adding asset path:"+mArchiveSourcePath);
398 }
399 } catch (Exception e) {
400 Log.w(TAG, "Unable to read AndroidManifest.xml of "
401 + mArchiveSourcePath, e);
402 }
403 if(assetError) {
404 if (assmgr != null) assmgr.close();
405 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
406 return null;
407 }
408 String[] errorText = new String[1];
409 Package pkg = null;
410 Exception errorException = null;
411 try {
412 // XXXX todo: need to figure out correct configuration.
413 Resources res = new Resources(assmgr, metrics, null);
414 pkg = parsePackage(res, parser, flags, errorText);
415 } catch (Exception e) {
416 errorException = e;
417 mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
418 }
419
420
421 if (pkg == null) {
422 if (errorException != null) {
423 Log.w(TAG, mArchiveSourcePath, errorException);
424 } else {
425 Log.w(TAG, mArchiveSourcePath + " (at "
426 + parser.getPositionDescription()
427 + "): " + errorText[0]);
428 }
429 parser.close();
430 assmgr.close();
431 if (mParseError == PackageManager.INSTALL_SUCCEEDED) {
432 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
433 }
434 return null;
435 }
436
437 parser.close();
438 assmgr.close();
439
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800440 // Set code and resource paths
441 pkg.mPath = destCodePath;
442 pkg.mScanPath = mArchiveSourcePath;
443 //pkg.applicationInfo.sourceDir = destCodePath;
444 //pkg.applicationInfo.publicSourceDir = destRes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 pkg.mSignatures = null;
446
447 return pkg;
448 }
449
450 public boolean collectCertificates(Package pkg, int flags) {
451 pkg.mSignatures = null;
452
453 WeakReference<byte[]> readBufferRef;
454 byte[] readBuffer = null;
455 synchronized (mSync) {
456 readBufferRef = mReadBuffer;
457 if (readBufferRef != null) {
458 mReadBuffer = null;
459 readBuffer = readBufferRef.get();
460 }
461 if (readBuffer == null) {
462 readBuffer = new byte[8192];
463 readBufferRef = new WeakReference<byte[]>(readBuffer);
464 }
465 }
466
467 try {
468 JarFile jarFile = new JarFile(mArchiveSourcePath);
469
470 Certificate[] certs = null;
471
472 if ((flags&PARSE_IS_SYSTEM) != 0) {
473 // If this package comes from the system image, then we
474 // can trust it... we'll just use the AndroidManifest.xml
475 // to retrieve its signatures, not validating all of the
476 // files.
477 JarEntry jarEntry = jarFile.getJarEntry("AndroidManifest.xml");
478 certs = loadCertificates(jarFile, jarEntry, readBuffer);
479 if (certs == null) {
480 Log.e(TAG, "Package " + pkg.packageName
481 + " has no certificates at entry "
482 + jarEntry.getName() + "; ignoring!");
483 jarFile.close();
484 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
485 return false;
486 }
487 if (false) {
488 Log.i(TAG, "File " + mArchiveSourcePath + ": entry=" + jarEntry
489 + " certs=" + (certs != null ? certs.length : 0));
490 if (certs != null) {
491 final int N = certs.length;
492 for (int i=0; i<N; i++) {
493 Log.i(TAG, " Public key: "
494 + certs[i].getPublicKey().getEncoded()
495 + " " + certs[i].getPublicKey());
496 }
497 }
498 }
499
500 } else {
501 Enumeration entries = jarFile.entries();
502 while (entries.hasMoreElements()) {
503 JarEntry je = (JarEntry)entries.nextElement();
504 if (je.isDirectory()) continue;
505 if (je.getName().startsWith("META-INF/")) continue;
506 Certificate[] localCerts = loadCertificates(jarFile, je,
507 readBuffer);
508 if (false) {
509 Log.i(TAG, "File " + mArchiveSourcePath + " entry " + je.getName()
510 + ": certs=" + certs + " ("
511 + (certs != null ? certs.length : 0) + ")");
512 }
513 if (localCerts == null) {
514 Log.e(TAG, "Package " + pkg.packageName
515 + " has no certificates at entry "
516 + je.getName() + "; ignoring!");
517 jarFile.close();
518 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
519 return false;
520 } else if (certs == null) {
521 certs = localCerts;
522 } else {
523 // Ensure all certificates match.
524 for (int i=0; i<certs.length; i++) {
525 boolean found = false;
526 for (int j=0; j<localCerts.length; j++) {
527 if (certs[i] != null &&
528 certs[i].equals(localCerts[j])) {
529 found = true;
530 break;
531 }
532 }
533 if (!found || certs.length != localCerts.length) {
534 Log.e(TAG, "Package " + pkg.packageName
535 + " has mismatched certificates at entry "
536 + je.getName() + "; ignoring!");
537 jarFile.close();
538 mParseError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
539 return false;
540 }
541 }
542 }
543 }
544 }
545 jarFile.close();
546
547 synchronized (mSync) {
548 mReadBuffer = readBufferRef;
549 }
550
551 if (certs != null && certs.length > 0) {
552 final int N = certs.length;
553 pkg.mSignatures = new Signature[certs.length];
554 for (int i=0; i<N; i++) {
555 pkg.mSignatures[i] = new Signature(
556 certs[i].getEncoded());
557 }
558 } else {
559 Log.e(TAG, "Package " + pkg.packageName
560 + " has no certificates; ignoring!");
561 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
562 return false;
563 }
564 } catch (CertificateEncodingException e) {
565 Log.w(TAG, "Exception reading " + mArchiveSourcePath, e);
566 mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
567 return false;
568 } catch (IOException e) {
569 Log.w(TAG, "Exception reading " + mArchiveSourcePath, e);
570 mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
571 return false;
572 } catch (RuntimeException e) {
573 Log.w(TAG, "Exception reading " + mArchiveSourcePath, e);
574 mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
575 return false;
576 }
577
578 return true;
579 }
580
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800581 /*
582 * Utility method that retrieves just the package name and install
583 * location from the apk location at the given file path.
584 * @param packageFilePath file location of the apk
585 * @param flags Special parse flags
Kenny Root930d3af2010-07-30 16:52:29 -0700586 * @return PackageLite object with package information or null on failure.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800587 */
588 public static PackageLite parsePackageLite(String packageFilePath, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 XmlResourceParser parser = null;
590 AssetManager assmgr = null;
591 try {
592 assmgr = new AssetManager();
593 int cookie = assmgr.addAssetPath(packageFilePath);
594 parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");
595 } catch (Exception e) {
596 if (assmgr != null) assmgr.close();
597 Log.w(TAG, "Unable to read AndroidManifest.xml of "
598 + packageFilePath, e);
599 return null;
600 }
601 AttributeSet attrs = parser;
602 String errors[] = new String[1];
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800603 PackageLite packageLite = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 try {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800605 packageLite = parsePackageLite(parser, attrs, flags, errors);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606 } catch (IOException e) {
607 Log.w(TAG, packageFilePath, e);
608 } catch (XmlPullParserException e) {
609 Log.w(TAG, packageFilePath, e);
610 } finally {
611 if (parser != null) parser.close();
612 if (assmgr != null) assmgr.close();
613 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800614 if (packageLite == null) {
615 Log.e(TAG, "parsePackageLite error: " + errors[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 return null;
617 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800618 return packageLite;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 }
620
621 private static String validateName(String name, boolean requiresSeparator) {
622 final int N = name.length();
623 boolean hasSep = false;
624 boolean front = true;
625 for (int i=0; i<N; i++) {
626 final char c = name.charAt(i);
627 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
628 front = false;
629 continue;
630 }
631 if (!front) {
632 if ((c >= '0' && c <= '9') || c == '_') {
633 continue;
634 }
635 }
636 if (c == '.') {
637 hasSep = true;
638 front = true;
639 continue;
640 }
641 return "bad character '" + c + "'";
642 }
643 return hasSep || !requiresSeparator
644 ? null : "must have at least one '.' separator";
645 }
646
647 private static String parsePackageName(XmlPullParser parser,
648 AttributeSet attrs, int flags, String[] outError)
649 throws IOException, XmlPullParserException {
650
651 int type;
652 while ((type=parser.next()) != parser.START_TAG
653 && type != parser.END_DOCUMENT) {
654 ;
655 }
656
657 if (type != parser.START_TAG) {
658 outError[0] = "No start tag found";
659 return null;
660 }
661 if ((flags&PARSE_CHATTY) != 0 && Config.LOGV) Log.v(
662 TAG, "Root element name: '" + parser.getName() + "'");
663 if (!parser.getName().equals("manifest")) {
664 outError[0] = "No <manifest> tag";
665 return null;
666 }
667 String pkgName = attrs.getAttributeValue(null, "package");
668 if (pkgName == null || pkgName.length() == 0) {
669 outError[0] = "<manifest> does not specify package";
670 return null;
671 }
672 String nameError = validateName(pkgName, true);
673 if (nameError != null && !"android".equals(pkgName)) {
674 outError[0] = "<manifest> specifies bad package name \""
675 + pkgName + "\": " + nameError;
676 return null;
677 }
678
679 return pkgName.intern();
680 }
681
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800682 private static PackageLite parsePackageLite(XmlPullParser parser,
683 AttributeSet attrs, int flags, String[] outError)
684 throws IOException, XmlPullParserException {
685
686 int type;
687 while ((type=parser.next()) != parser.START_TAG
688 && type != parser.END_DOCUMENT) {
689 ;
690 }
691
692 if (type != parser.START_TAG) {
693 outError[0] = "No start tag found";
694 return null;
695 }
696 if ((flags&PARSE_CHATTY) != 0 && Config.LOGV) Log.v(
697 TAG, "Root element name: '" + parser.getName() + "'");
698 if (!parser.getName().equals("manifest")) {
699 outError[0] = "No <manifest> tag";
700 return null;
701 }
702 String pkgName = attrs.getAttributeValue(null, "package");
703 if (pkgName == null || pkgName.length() == 0) {
704 outError[0] = "<manifest> does not specify package";
705 return null;
706 }
707 String nameError = validateName(pkgName, true);
708 if (nameError != null && !"android".equals(pkgName)) {
709 outError[0] = "<manifest> specifies bad package name \""
710 + pkgName + "\": " + nameError;
711 return null;
712 }
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700713 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800714 for (int i = 0; i < attrs.getAttributeCount(); i++) {
715 String attr = attrs.getAttributeName(i);
716 if (attr.equals("installLocation")) {
717 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700718 PARSE_DEFAULT_INSTALL_LOCATION);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800719 break;
720 }
721 }
722 return new PackageLite(pkgName.intern(), installLocation);
723 }
724
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800725 /**
726 * Temporary.
727 */
728 static public Signature stringToSignature(String str) {
729 final int N = str.length();
730 byte[] sig = new byte[N];
731 for (int i=0; i<N; i++) {
732 sig[i] = (byte)str.charAt(i);
733 }
734 return new Signature(sig);
735 }
736
737 private Package parsePackage(
738 Resources res, XmlResourceParser parser, int flags, String[] outError)
739 throws XmlPullParserException, IOException {
740 AttributeSet attrs = parser;
741
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700742 mParseInstrumentationArgs = null;
743 mParseActivityArgs = null;
744 mParseServiceArgs = null;
745 mParseProviderArgs = null;
746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 String pkgName = parsePackageName(parser, attrs, flags, outError);
748 if (pkgName == null) {
749 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
750 return null;
751 }
752 int type;
753
754 final Package pkg = new Package(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 boolean foundApp = false;
Dianne Hackborn851a5412009-05-08 12:06:44 -0700756
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800757 TypedArray sa = res.obtainAttributes(attrs,
758 com.android.internal.R.styleable.AndroidManifest);
759 pkg.mVersionCode = sa.getInteger(
760 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800761 pkg.mVersionName = sa.getNonConfigurationString(
762 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 if (pkg.mVersionName != null) {
764 pkg.mVersionName = pkg.mVersionName.intern();
765 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800766 String str = sa.getNonConfigurationString(
767 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
768 if (str != null && str.length() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 String nameError = validateName(str, true);
770 if (nameError != null && !"android".equals(pkgName)) {
771 outError[0] = "<manifest> specifies bad sharedUserId name \""
772 + str + "\": " + nameError;
773 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
774 return null;
775 }
776 pkg.mSharedUserId = str.intern();
777 pkg.mSharedUserLabel = sa.getResourceId(
778 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
779 }
780 sa.recycle();
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -0800781
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800782 pkg.installLocation = sa.getInteger(
783 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700784 PARSE_DEFAULT_INSTALL_LOCATION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785
Dianne Hackborn723738c2009-06-25 19:48:04 -0700786 // Resource boolean are -1, so 1 means we don't know the value.
787 int supportsSmallScreens = 1;
788 int supportsNormalScreens = 1;
789 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -0700790 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700791 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700792 int anyDensity = 1;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 int outerDepth = parser.getDepth();
795 while ((type=parser.next()) != parser.END_DOCUMENT
796 && (type != parser.END_TAG || parser.getDepth() > outerDepth)) {
797 if (type == parser.END_TAG || type == parser.TEXT) {
798 continue;
799 }
800
801 String tagName = parser.getName();
802 if (tagName.equals("application")) {
803 if (foundApp) {
804 if (RIGID_PARSER) {
805 outError[0] = "<manifest> has more than one <application>";
806 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
807 return null;
808 } else {
809 Log.w(TAG, "<manifest> has more than one <application>");
810 XmlUtils.skipCurrentTag(parser);
811 continue;
812 }
813 }
814
815 foundApp = true;
816 if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
817 return null;
818 }
819 } else if (tagName.equals("permission-group")) {
820 if (parsePermissionGroup(pkg, res, parser, attrs, outError) == null) {
821 return null;
822 }
823 } else if (tagName.equals("permission")) {
824 if (parsePermission(pkg, res, parser, attrs, outError) == null) {
825 return null;
826 }
827 } else if (tagName.equals("permission-tree")) {
828 if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
829 return null;
830 }
831 } else if (tagName.equals("uses-permission")) {
832 sa = res.obtainAttributes(attrs,
833 com.android.internal.R.styleable.AndroidManifestUsesPermission);
834
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800835 // Note: don't allow this value to be a reference to a resource
836 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837 String name = sa.getNonResourceString(
838 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
839
840 sa.recycle();
841
842 if (name != null && !pkg.requestedPermissions.contains(name)) {
Dianne Hackborn854060a2009-07-09 18:14:31 -0700843 pkg.requestedPermissions.add(name.intern());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 }
845
846 XmlUtils.skipCurrentTag(parser);
847
848 } else if (tagName.equals("uses-configuration")) {
849 ConfigurationInfo cPref = new ConfigurationInfo();
850 sa = res.obtainAttributes(attrs,
851 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
852 cPref.reqTouchScreen = sa.getInt(
853 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
854 Configuration.TOUCHSCREEN_UNDEFINED);
855 cPref.reqKeyboardType = sa.getInt(
856 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
857 Configuration.KEYBOARD_UNDEFINED);
858 if (sa.getBoolean(
859 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
860 false)) {
861 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
862 }
863 cPref.reqNavigation = sa.getInt(
864 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
865 Configuration.NAVIGATION_UNDEFINED);
866 if (sa.getBoolean(
867 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
868 false)) {
869 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
870 }
871 sa.recycle();
872 pkg.configPreferences.add(cPref);
873
874 XmlUtils.skipCurrentTag(parser);
875
Suchi Amalapurapud299b812009-06-05 10:26:19 -0700876 } else if (tagName.equals("uses-feature")) {
Dianne Hackborn49237342009-08-27 20:08:01 -0700877 FeatureInfo fi = new FeatureInfo();
Suchi Amalapurapud299b812009-06-05 10:26:19 -0700878 sa = res.obtainAttributes(attrs,
879 com.android.internal.R.styleable.AndroidManifestUsesFeature);
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800880 // Note: don't allow this value to be a reference to a resource
881 // that may change.
Dianne Hackborn49237342009-08-27 20:08:01 -0700882 fi.name = sa.getNonResourceString(
883 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
884 if (fi.name == null) {
885 fi.reqGlEsVersion = sa.getInt(
886 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
887 FeatureInfo.GL_ES_VERSION_UNDEFINED);
888 }
889 if (sa.getBoolean(
890 com.android.internal.R.styleable.AndroidManifestUsesFeature_required,
891 true)) {
892 fi.flags |= FeatureInfo.FLAG_REQUIRED;
893 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -0700894 sa.recycle();
Dianne Hackborn49237342009-08-27 20:08:01 -0700895 if (pkg.reqFeatures == null) {
896 pkg.reqFeatures = new ArrayList<FeatureInfo>();
897 }
898 pkg.reqFeatures.add(fi);
899
900 if (fi.name == null) {
901 ConfigurationInfo cPref = new ConfigurationInfo();
902 cPref.reqGlEsVersion = fi.reqGlEsVersion;
903 pkg.configPreferences.add(cPref);
904 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -0700905
906 XmlUtils.skipCurrentTag(parser);
907
Dianne Hackborn851a5412009-05-08 12:06:44 -0700908 } else if (tagName.equals("uses-sdk")) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700909 if (SDK_VERSION > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 sa = res.obtainAttributes(attrs,
911 com.android.internal.R.styleable.AndroidManifestUsesSdk);
912
Dianne Hackborn851a5412009-05-08 12:06:44 -0700913 int minVers = 0;
914 String minCode = null;
915 int targetVers = 0;
916 String targetCode = null;
917
918 TypedValue val = sa.peekValue(
919 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
920 if (val != null) {
921 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
922 targetCode = minCode = val.string.toString();
923 } else {
924 // If it's not a string, it's an integer.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700925 targetVers = minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -0700926 }
927 }
928
929 val = sa.peekValue(
930 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
931 if (val != null) {
932 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
933 targetCode = minCode = val.string.toString();
934 } else {
935 // If it's not a string, it's an integer.
936 targetVers = val.data;
937 }
938 }
939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800940 sa.recycle();
941
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700942 if (minCode != null) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700943 if (!minCode.equals(SDK_CODENAME)) {
944 if (SDK_CODENAME != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700945 outError[0] = "Requires development platform " + minCode
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700946 + " (current platform is " + SDK_CODENAME + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700947 } else {
948 outError[0] = "Requires development platform " + minCode
949 + " but this is a release platform.";
950 }
951 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
952 return null;
953 }
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700954 } else if (minVers > SDK_VERSION) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700955 outError[0] = "Requires newer sdk version #" + minVers
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700956 + " (current version is #" + SDK_VERSION + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700957 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
958 return null;
959 }
960
Dianne Hackborn851a5412009-05-08 12:06:44 -0700961 if (targetCode != null) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700962 if (!targetCode.equals(SDK_CODENAME)) {
963 if (SDK_CODENAME != null) {
Dianne Hackborn851a5412009-05-08 12:06:44 -0700964 outError[0] = "Requires development platform " + targetCode
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700965 + " (current platform is " + SDK_CODENAME + ")";
Dianne Hackborn851a5412009-05-08 12:06:44 -0700966 } else {
967 outError[0] = "Requires development platform " + targetCode
968 + " but this is a release platform.";
969 }
970 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
971 return null;
972 }
973 // If the code matches, it definitely targets this SDK.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700974 pkg.applicationInfo.targetSdkVersion
975 = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
976 } else {
977 pkg.applicationInfo.targetSdkVersion = targetVers;
Dianne Hackborn851a5412009-05-08 12:06:44 -0700978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 }
980
981 XmlUtils.skipCurrentTag(parser);
982
Dianne Hackborn723738c2009-06-25 19:48:04 -0700983 } else if (tagName.equals("supports-screens")) {
984 sa = res.obtainAttributes(attrs,
985 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
986
987 // This is a trick to get a boolean and still able to detect
988 // if a value was actually set.
989 supportsSmallScreens = sa.getInteger(
990 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
991 supportsSmallScreens);
992 supportsNormalScreens = sa.getInteger(
993 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
994 supportsNormalScreens);
995 supportsLargeScreens = sa.getInteger(
996 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
997 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -0700998 supportsXLargeScreens = sa.getInteger(
999 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
1000 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001001 resizeable = sa.getInteger(
1002 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001003 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001004 anyDensity = sa.getInteger(
1005 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
1006 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001007
1008 sa.recycle();
1009
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07001010 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn854060a2009-07-09 18:14:31 -07001011
1012 } else if (tagName.equals("protected-broadcast")) {
1013 sa = res.obtainAttributes(attrs,
1014 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
1015
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001016 // Note: don't allow this value to be a reference to a resource
1017 // that may change.
Dianne Hackborn854060a2009-07-09 18:14:31 -07001018 String name = sa.getNonResourceString(
1019 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
1020
1021 sa.recycle();
1022
1023 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
1024 if (pkg.protectedBroadcasts == null) {
1025 pkg.protectedBroadcasts = new ArrayList<String>();
1026 }
1027 if (!pkg.protectedBroadcasts.contains(name)) {
1028 pkg.protectedBroadcasts.add(name.intern());
1029 }
1030 }
1031
1032 XmlUtils.skipCurrentTag(parser);
1033
1034 } else if (tagName.equals("instrumentation")) {
1035 if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) {
1036 return null;
1037 }
1038
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001039 } else if (tagName.equals("original-package")) {
1040 sa = res.obtainAttributes(attrs,
1041 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1042
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001043 String orig =sa.getNonConfigurationString(
1044 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001045 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08001046 if (pkg.mOriginalPackages == null) {
1047 pkg.mOriginalPackages = new ArrayList<String>();
1048 pkg.mRealPackage = pkg.packageName;
1049 }
1050 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001051 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001052
1053 sa.recycle();
1054
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001055 XmlUtils.skipCurrentTag(parser);
1056
1057 } else if (tagName.equals("adopt-permissions")) {
1058 sa = res.obtainAttributes(attrs,
1059 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1060
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001061 String name = sa.getNonConfigurationString(
1062 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001063
1064 sa.recycle();
1065
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001066 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001067 if (pkg.mAdoptPermissions == null) {
1068 pkg.mAdoptPermissions = new ArrayList<String>();
1069 }
1070 pkg.mAdoptPermissions.add(name);
1071 }
1072
1073 XmlUtils.skipCurrentTag(parser);
1074
Dianne Hackborn854060a2009-07-09 18:14:31 -07001075 } else if (tagName.equals("eat-comment")) {
1076 // Just skip this tag
1077 XmlUtils.skipCurrentTag(parser);
1078 continue;
1079
1080 } else if (RIGID_PARSER) {
1081 outError[0] = "Bad element under <manifest>: "
1082 + parser.getName();
1083 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1084 return null;
1085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 } else {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07001087 Log.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1088 + " at " + mArchiveSourcePath + " "
1089 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 XmlUtils.skipCurrentTag(parser);
1091 continue;
1092 }
1093 }
1094
1095 if (!foundApp && pkg.instrumentation.size() == 0) {
1096 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
1097 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1098 }
1099
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001100 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001101 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001102 for (int ip=0; ip<NP; ip++) {
1103 final PackageParser.NewPermissionInfo npi
1104 = PackageParser.NEW_PERMISSIONS[ip];
1105 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
1106 break;
1107 }
1108 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001109 if (implicitPerms == null) {
1110 implicitPerms = new StringBuilder(128);
1111 implicitPerms.append(pkg.packageName);
1112 implicitPerms.append(": compat added ");
1113 } else {
1114 implicitPerms.append(' ');
1115 }
1116 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001117 pkg.requestedPermissions.add(npi.name);
1118 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07001119 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001120 if (implicitPerms != null) {
1121 Log.i(TAG, implicitPerms.toString());
1122 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07001123
Dianne Hackborn723738c2009-06-25 19:48:04 -07001124 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
1125 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001126 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001127 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
1128 }
1129 if (supportsNormalScreens != 0) {
1130 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
1131 }
1132 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
1133 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001134 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001135 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
1136 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001137 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
1138 && pkg.applicationInfo.targetSdkVersion
1139 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
1140 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
1141 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001142 if (resizeable < 0 || (resizeable > 0
1143 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001144 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001145 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
1146 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001147 if (anyDensity < 0 || (anyDensity > 0
1148 && pkg.applicationInfo.targetSdkVersion
1149 >= android.os.Build.VERSION_CODES.DONUT)) {
1150 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07001151 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07001152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 return pkg;
1154 }
1155
1156 private static String buildClassName(String pkg, CharSequence clsSeq,
1157 String[] outError) {
1158 if (clsSeq == null || clsSeq.length() <= 0) {
1159 outError[0] = "Empty class name in package " + pkg;
1160 return null;
1161 }
1162 String cls = clsSeq.toString();
1163 char c = cls.charAt(0);
1164 if (c == '.') {
1165 return (pkg + cls).intern();
1166 }
1167 if (cls.indexOf('.') < 0) {
1168 StringBuilder b = new StringBuilder(pkg);
1169 b.append('.');
1170 b.append(cls);
1171 return b.toString().intern();
1172 }
1173 if (c >= 'a' && c <= 'z') {
1174 return cls.intern();
1175 }
1176 outError[0] = "Bad class name " + cls + " in package " + pkg;
1177 return null;
1178 }
1179
1180 private static String buildCompoundName(String pkg,
1181 CharSequence procSeq, String type, String[] outError) {
1182 String proc = procSeq.toString();
1183 char c = proc.charAt(0);
1184 if (pkg != null && c == ':') {
1185 if (proc.length() < 2) {
1186 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
1187 + ": must be at least two characters";
1188 return null;
1189 }
1190 String subName = proc.substring(1);
1191 String nameError = validateName(subName, false);
1192 if (nameError != null) {
1193 outError[0] = "Invalid " + type + " name " + proc + " in package "
1194 + pkg + ": " + nameError;
1195 return null;
1196 }
1197 return (pkg + proc).intern();
1198 }
1199 String nameError = validateName(proc, true);
1200 if (nameError != null && !"system".equals(proc)) {
1201 outError[0] = "Invalid " + type + " name " + proc + " in package "
1202 + pkg + ": " + nameError;
1203 return null;
1204 }
1205 return proc.intern();
1206 }
1207
1208 private static String buildProcessName(String pkg, String defProc,
1209 CharSequence procSeq, int flags, String[] separateProcesses,
1210 String[] outError) {
1211 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
1212 return defProc != null ? defProc : pkg;
1213 }
1214 if (separateProcesses != null) {
1215 for (int i=separateProcesses.length-1; i>=0; i--) {
1216 String sp = separateProcesses[i];
1217 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
1218 return pkg;
1219 }
1220 }
1221 }
1222 if (procSeq == null || procSeq.length() <= 0) {
1223 return defProc;
1224 }
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07001225 return buildCompoundName(pkg, procSeq, "process", outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 }
1227
1228 private static String buildTaskAffinityName(String pkg, String defProc,
1229 CharSequence procSeq, String[] outError) {
1230 if (procSeq == null) {
1231 return defProc;
1232 }
1233 if (procSeq.length() <= 0) {
1234 return null;
1235 }
1236 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
1237 }
1238
1239 private PermissionGroup parsePermissionGroup(Package owner, Resources res,
1240 XmlPullParser parser, AttributeSet attrs, String[] outError)
1241 throws XmlPullParserException, IOException {
1242 PermissionGroup perm = new PermissionGroup(owner);
1243
1244 TypedArray sa = res.obtainAttributes(attrs,
1245 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
1246
1247 if (!parsePackageItemInfo(owner, perm.info, outError,
1248 "<permission-group>", sa,
1249 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
1250 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001251 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
1252 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 sa.recycle();
1254 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1255 return null;
1256 }
1257
1258 perm.info.descriptionRes = sa.getResourceId(
1259 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
1260 0);
1261
1262 sa.recycle();
1263
1264 if (!parseAllMetaData(res, parser, attrs, "<permission-group>", perm,
1265 outError)) {
1266 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1267 return null;
1268 }
1269
1270 owner.permissionGroups.add(perm);
1271
1272 return perm;
1273 }
1274
1275 private Permission parsePermission(Package owner, Resources res,
1276 XmlPullParser parser, AttributeSet attrs, String[] outError)
1277 throws XmlPullParserException, IOException {
1278 Permission perm = new Permission(owner);
1279
1280 TypedArray sa = res.obtainAttributes(attrs,
1281 com.android.internal.R.styleable.AndroidManifestPermission);
1282
1283 if (!parsePackageItemInfo(owner, perm.info, outError,
1284 "<permission>", sa,
1285 com.android.internal.R.styleable.AndroidManifestPermission_name,
1286 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001287 com.android.internal.R.styleable.AndroidManifestPermission_icon,
1288 com.android.internal.R.styleable.AndroidManifestPermission_logo)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001289 sa.recycle();
1290 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1291 return null;
1292 }
1293
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001294 // Note: don't allow this value to be a reference to a resource
1295 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001296 perm.info.group = sa.getNonResourceString(
1297 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
1298 if (perm.info.group != null) {
1299 perm.info.group = perm.info.group.intern();
1300 }
1301
1302 perm.info.descriptionRes = sa.getResourceId(
1303 com.android.internal.R.styleable.AndroidManifestPermission_description,
1304 0);
1305
1306 perm.info.protectionLevel = sa.getInt(
1307 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
1308 PermissionInfo.PROTECTION_NORMAL);
1309
1310 sa.recycle();
1311
1312 if (perm.info.protectionLevel == -1) {
1313 outError[0] = "<permission> does not specify protectionLevel";
1314 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1315 return null;
1316 }
1317
1318 if (!parseAllMetaData(res, parser, attrs, "<permission>", perm,
1319 outError)) {
1320 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1321 return null;
1322 }
1323
1324 owner.permissions.add(perm);
1325
1326 return perm;
1327 }
1328
1329 private Permission parsePermissionTree(Package owner, Resources res,
1330 XmlPullParser parser, AttributeSet attrs, String[] outError)
1331 throws XmlPullParserException, IOException {
1332 Permission perm = new Permission(owner);
1333
1334 TypedArray sa = res.obtainAttributes(attrs,
1335 com.android.internal.R.styleable.AndroidManifestPermissionTree);
1336
1337 if (!parsePackageItemInfo(owner, perm.info, outError,
1338 "<permission-tree>", sa,
1339 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
1340 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001341 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
1342 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343 sa.recycle();
1344 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1345 return null;
1346 }
1347
1348 sa.recycle();
1349
1350 int index = perm.info.name.indexOf('.');
1351 if (index > 0) {
1352 index = perm.info.name.indexOf('.', index+1);
1353 }
1354 if (index < 0) {
1355 outError[0] = "<permission-tree> name has less than three segments: "
1356 + perm.info.name;
1357 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1358 return null;
1359 }
1360
1361 perm.info.descriptionRes = 0;
1362 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
1363 perm.tree = true;
1364
1365 if (!parseAllMetaData(res, parser, attrs, "<permission-tree>", perm,
1366 outError)) {
1367 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1368 return null;
1369 }
1370
1371 owner.permissions.add(perm);
1372
1373 return perm;
1374 }
1375
1376 private Instrumentation parseInstrumentation(Package owner, Resources res,
1377 XmlPullParser parser, AttributeSet attrs, String[] outError)
1378 throws XmlPullParserException, IOException {
1379 TypedArray sa = res.obtainAttributes(attrs,
1380 com.android.internal.R.styleable.AndroidManifestInstrumentation);
1381
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001382 if (mParseInstrumentationArgs == null) {
1383 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
1384 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
1385 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001386 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
1387 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001388 mParseInstrumentationArgs.tag = "<instrumentation>";
1389 }
1390
1391 mParseInstrumentationArgs.sa = sa;
1392
1393 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
1394 new InstrumentationInfo());
1395 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 sa.recycle();
1397 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1398 return null;
1399 }
1400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001402 // Note: don't allow this value to be a reference to a resource
1403 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 str = sa.getNonResourceString(
1405 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
1406 a.info.targetPackage = str != null ? str.intern() : null;
1407
1408 a.info.handleProfiling = sa.getBoolean(
1409 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
1410 false);
1411
1412 a.info.functionalTest = sa.getBoolean(
1413 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
1414 false);
1415
1416 sa.recycle();
1417
1418 if (a.info.targetPackage == null) {
1419 outError[0] = "<instrumentation> does not specify targetPackage";
1420 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1421 return null;
1422 }
1423
1424 if (!parseAllMetaData(res, parser, attrs, "<instrumentation>", a,
1425 outError)) {
1426 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1427 return null;
1428 }
1429
1430 owner.instrumentation.add(a);
1431
1432 return a;
1433 }
1434
1435 private boolean parseApplication(Package owner, Resources res,
1436 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
1437 throws XmlPullParserException, IOException {
1438 final ApplicationInfo ai = owner.applicationInfo;
1439 final String pkgName = owner.applicationInfo.packageName;
1440
1441 TypedArray sa = res.obtainAttributes(attrs,
1442 com.android.internal.R.styleable.AndroidManifestApplication);
1443
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001444 String name = sa.getNonConfigurationString(
1445 com.android.internal.R.styleable.AndroidManifestApplication_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 if (name != null) {
1447 ai.className = buildClassName(pkgName, name, outError);
1448 if (ai.className == null) {
1449 sa.recycle();
1450 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1451 return false;
1452 }
1453 }
1454
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001455 String manageSpaceActivity = sa.getNonConfigurationString(
1456 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 if (manageSpaceActivity != null) {
1458 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
1459 outError);
1460 }
1461
Christopher Tate181fafa2009-05-14 11:12:14 -07001462 boolean allowBackup = sa.getBoolean(
1463 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
1464 if (allowBackup) {
1465 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07001466
Christopher Tate3de55bc2010-03-12 17:28:08 -08001467 // backupAgent, killAfterRestore, and restoreAnyVersion are only relevant
1468 // if backup is possible for the given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001469 String backupAgent = sa.getNonConfigurationString(
1470 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent, 0);
Christopher Tate181fafa2009-05-14 11:12:14 -07001471 if (backupAgent != null) {
1472 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001473 if (false) {
1474 Log.v(TAG, "android:backupAgent = " + ai.backupAgentName
1475 + " from " + pkgName + "+" + backupAgent);
1476 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07001477
1478 if (sa.getBoolean(
1479 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
1480 true)) {
1481 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
1482 }
1483 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08001484 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
1485 false)) {
1486 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
1487 }
Christopher Tate181fafa2009-05-14 11:12:14 -07001488 }
1489 }
1490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 TypedValue v = sa.peekValue(
1492 com.android.internal.R.styleable.AndroidManifestApplication_label);
1493 if (v != null && (ai.labelRes=v.resourceId) == 0) {
1494 ai.nonLocalizedLabel = v.coerceToString();
1495 }
1496
1497 ai.icon = sa.getResourceId(
1498 com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
Adam Powell81cd2e92010-04-21 16:35:18 -07001499 ai.logo = sa.getResourceId(
1500 com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 ai.theme = sa.getResourceId(
1502 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
1503 ai.descriptionRes = sa.getResourceId(
1504 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
1505
1506 if ((flags&PARSE_IS_SYSTEM) != 0) {
1507 if (sa.getBoolean(
1508 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
1509 false)) {
1510 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
1511 }
1512 }
1513
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08001514 if ((flags & PARSE_FORWARD_LOCK) != 0) {
1515 ai.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
1516 }
1517
1518 if ((flags & PARSE_ON_SDCARD) != 0) {
Suchi Amalapurapu6069beb2010-03-10 09:46:49 -08001519 ai.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08001520 }
1521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 if (sa.getBoolean(
1523 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
1524 false)) {
1525 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
1526 }
1527
1528 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07001529 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08001530 false)) {
1531 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
1532 }
1533
Romain Guy529b60a2010-08-03 18:05:47 -07001534 boolean hardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07001535 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07001536 false);
Romain Guy812ccbe2010-06-01 14:07:24 -07001537
1538 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
1540 true)) {
1541 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
1542 }
1543
1544 if (sa.getBoolean(
1545 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
1546 false)) {
1547 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
1548 }
1549
1550 if (sa.getBoolean(
1551 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
1552 true)) {
1553 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
1554 }
1555
Dianne Hackbornade3eca2009-05-11 18:54:45 -07001556 if (sa.getBoolean(
1557 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
Dianne Hackborne7fe35b2009-05-13 10:53:41 -07001558 false)) {
Dianne Hackbornade3eca2009-05-11 18:54:45 -07001559 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
1560 }
1561
Oscar Montemayor1874aa42009-11-10 18:35:33 -08001562 if (sa.getBoolean(
1563 com.android.internal.R.styleable.AndroidManifestApplication_neverEncrypt,
1564 false)) {
1565 ai.flags |= ApplicationInfo.FLAG_NEVER_ENCRYPT;
1566 }
1567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001569 str = sa.getNonConfigurationString(
1570 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
1572
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07001573 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
1574 str = sa.getNonConfigurationString(
1575 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity, 0);
1576 } else {
1577 // Some older apps have been seen to use a resource reference
1578 // here that on older builds was ignored (with a warning). We
1579 // need to continue to do this for them so they don't break.
1580 str = sa.getNonResourceString(
1581 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
1582 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001583 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
1584 str, outError);
1585
1586 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07001587 CharSequence pname;
1588 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
1589 pname = sa.getNonConfigurationString(
1590 com.android.internal.R.styleable.AndroidManifestApplication_process, 0);
1591 } else {
1592 // Some older apps have been seen to use a resource reference
1593 // here that on older builds was ignored (with a warning). We
1594 // need to continue to do this for them so they don't break.
1595 pname = sa.getNonResourceString(
1596 com.android.internal.R.styleable.AndroidManifestApplication_process);
1597 }
1598 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 flags, mSeparateProcesses, outError);
1600
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001601 ai.enabled = sa.getBoolean(
1602 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001603
1604 if (sa.getBoolean(
1605 com.android.internal.R.styleable.AndroidManifestApplication_heavyWeight,
1606 false)) {
1607 ai.flags |= ApplicationInfo.FLAG_HEAVY_WEIGHT;
1608
1609 // A heavy-weight application can not be in a custom process.
1610 // We can do direct compare because we intern all strings.
1611 if (ai.processName != null && ai.processName != ai.packageName) {
1612 outError[0] = "Heavy-weight applications can not use custom processes";
1613 }
1614 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 }
1616
1617 sa.recycle();
1618
1619 if (outError[0] != null) {
1620 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1621 return false;
1622 }
1623
1624 final int innerDepth = parser.getDepth();
1625
1626 int type;
1627 while ((type=parser.next()) != parser.END_DOCUMENT
1628 && (type != parser.END_TAG || parser.getDepth() > innerDepth)) {
1629 if (type == parser.END_TAG || type == parser.TEXT) {
1630 continue;
1631 }
1632
1633 String tagName = parser.getName();
1634 if (tagName.equals("activity")) {
Romain Guy529b60a2010-08-03 18:05:47 -07001635 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
1636 hardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 if (a == null) {
1638 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1639 return false;
1640 }
1641
1642 owner.activities.add(a);
1643
1644 } else if (tagName.equals("receiver")) {
Romain Guy529b60a2010-08-03 18:05:47 -07001645 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 if (a == null) {
1647 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1648 return false;
1649 }
1650
1651 owner.receivers.add(a);
1652
1653 } else if (tagName.equals("service")) {
1654 Service s = parseService(owner, res, parser, attrs, flags, outError);
1655 if (s == null) {
1656 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1657 return false;
1658 }
1659
1660 owner.services.add(s);
1661
1662 } else if (tagName.equals("provider")) {
1663 Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
1664 if (p == null) {
1665 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1666 return false;
1667 }
1668
1669 owner.providers.add(p);
1670
1671 } else if (tagName.equals("activity-alias")) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001672 Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 if (a == null) {
1674 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1675 return false;
1676 }
1677
1678 owner.activities.add(a);
1679
1680 } else if (parser.getName().equals("meta-data")) {
1681 // note: application meta-data is stored off to the side, so it can
1682 // remain null in the primary copy (we like to avoid extra copies because
1683 // it can be large)
1684 if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,
1685 outError)) == null) {
1686 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1687 return false;
1688 }
1689
1690 } else if (tagName.equals("uses-library")) {
1691 sa = res.obtainAttributes(attrs,
1692 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
1693
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001694 // Note: don't allow this value to be a reference to a resource
1695 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001696 String lname = sa.getNonResourceString(
1697 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07001698 boolean req = sa.getBoolean(
1699 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
1700 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701
1702 sa.recycle();
1703
Dianne Hackborn49237342009-08-27 20:08:01 -07001704 if (lname != null) {
1705 if (req) {
1706 if (owner.usesLibraries == null) {
1707 owner.usesLibraries = new ArrayList<String>();
1708 }
1709 if (!owner.usesLibraries.contains(lname)) {
1710 owner.usesLibraries.add(lname.intern());
1711 }
1712 } else {
1713 if (owner.usesOptionalLibraries == null) {
1714 owner.usesOptionalLibraries = new ArrayList<String>();
1715 }
1716 if (!owner.usesOptionalLibraries.contains(lname)) {
1717 owner.usesOptionalLibraries.add(lname.intern());
1718 }
1719 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 }
1721
1722 XmlUtils.skipCurrentTag(parser);
1723
1724 } else {
1725 if (!RIGID_PARSER) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001726 Log.w(TAG, "Unknown element under <application>: " + tagName
1727 + " at " + mArchiveSourcePath + " "
1728 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 XmlUtils.skipCurrentTag(parser);
1730 continue;
1731 } else {
1732 outError[0] = "Bad element under <application>: " + tagName;
1733 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1734 return false;
1735 }
1736 }
1737 }
1738
1739 return true;
1740 }
1741
1742 private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
1743 String[] outError, String tag, TypedArray sa,
Adam Powell81cd2e92010-04-21 16:35:18 -07001744 int nameRes, int labelRes, int iconRes, int logoRes) {
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001745 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 if (name == null) {
1747 outError[0] = tag + " does not specify android:name";
1748 return false;
1749 }
1750
1751 outInfo.name
1752 = buildClassName(owner.applicationInfo.packageName, name, outError);
1753 if (outInfo.name == null) {
1754 return false;
1755 }
1756
1757 int iconVal = sa.getResourceId(iconRes, 0);
1758 if (iconVal != 0) {
1759 outInfo.icon = iconVal;
1760 outInfo.nonLocalizedLabel = null;
1761 }
Adam Powell81cd2e92010-04-21 16:35:18 -07001762
1763 int logoVal = sa.getResourceId(logoRes, 0);
1764 if (logoVal != 0) {
1765 outInfo.logo = logoVal;
1766 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767
1768 TypedValue v = sa.peekValue(labelRes);
1769 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
1770 outInfo.nonLocalizedLabel = v.coerceToString();
1771 }
1772
1773 outInfo.packageName = owner.packageName;
1774
1775 return true;
1776 }
1777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001778 private Activity parseActivity(Package owner, Resources res,
1779 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
Romain Guy529b60a2010-08-03 18:05:47 -07001780 boolean receiver, boolean hardwareAccelerated)
1781 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 TypedArray sa = res.obtainAttributes(attrs,
1783 com.android.internal.R.styleable.AndroidManifestActivity);
1784
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001785 if (mParseActivityArgs == null) {
1786 mParseActivityArgs = new ParseComponentArgs(owner, outError,
1787 com.android.internal.R.styleable.AndroidManifestActivity_name,
1788 com.android.internal.R.styleable.AndroidManifestActivity_label,
1789 com.android.internal.R.styleable.AndroidManifestActivity_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07001790 com.android.internal.R.styleable.AndroidManifestActivity_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001791 mSeparateProcesses,
1792 com.android.internal.R.styleable.AndroidManifestActivity_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08001793 com.android.internal.R.styleable.AndroidManifestActivity_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001794 com.android.internal.R.styleable.AndroidManifestActivity_enabled);
1795 }
1796
1797 mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
1798 mParseActivityArgs.sa = sa;
1799 mParseActivityArgs.flags = flags;
1800
1801 Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
1802 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 sa.recycle();
1804 return null;
1805 }
1806
1807 final boolean setExported = sa.hasValue(
1808 com.android.internal.R.styleable.AndroidManifestActivity_exported);
1809 if (setExported) {
1810 a.info.exported = sa.getBoolean(
1811 com.android.internal.R.styleable.AndroidManifestActivity_exported, false);
1812 }
1813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 a.info.theme = sa.getResourceId(
1815 com.android.internal.R.styleable.AndroidManifestActivity_theme, 0);
1816
1817 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001818 str = sa.getNonConfigurationString(
1819 com.android.internal.R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 if (str == null) {
1821 a.info.permission = owner.applicationInfo.permission;
1822 } else {
1823 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
1824 }
1825
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001826 str = sa.getNonConfigurationString(
1827 com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001828 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
1829 owner.applicationInfo.taskAffinity, str, outError);
1830
1831 a.info.flags = 0;
1832 if (sa.getBoolean(
1833 com.android.internal.R.styleable.AndroidManifestActivity_multiprocess,
1834 false)) {
1835 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
1836 }
1837
1838 if (sa.getBoolean(
1839 com.android.internal.R.styleable.AndroidManifestActivity_finishOnTaskLaunch,
1840 false)) {
1841 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
1842 }
1843
1844 if (sa.getBoolean(
1845 com.android.internal.R.styleable.AndroidManifestActivity_clearTaskOnLaunch,
1846 false)) {
1847 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
1848 }
1849
1850 if (sa.getBoolean(
1851 com.android.internal.R.styleable.AndroidManifestActivity_noHistory,
1852 false)) {
1853 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
1854 }
1855
1856 if (sa.getBoolean(
1857 com.android.internal.R.styleable.AndroidManifestActivity_alwaysRetainTaskState,
1858 false)) {
1859 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
1860 }
1861
1862 if (sa.getBoolean(
1863 com.android.internal.R.styleable.AndroidManifestActivity_stateNotNeeded,
1864 false)) {
1865 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
1866 }
1867
1868 if (sa.getBoolean(
1869 com.android.internal.R.styleable.AndroidManifestActivity_excludeFromRecents,
1870 false)) {
1871 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
1872 }
1873
1874 if (sa.getBoolean(
1875 com.android.internal.R.styleable.AndroidManifestActivity_allowTaskReparenting,
1876 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
1877 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
1878 }
1879
Dianne Hackbornffa42482009-09-23 22:20:11 -07001880 if (sa.getBoolean(
1881 com.android.internal.R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs,
1882 false)) {
1883 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
1884 }
1885
Daniel Sandler613dde42010-06-21 13:46:39 -04001886 if (sa.getBoolean(
1887 com.android.internal.R.styleable.AndroidManifestActivity_immersive,
1888 false)) {
1889 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
1890 }
Romain Guy529b60a2010-08-03 18:05:47 -07001891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 if (!receiver) {
Romain Guy529b60a2010-08-03 18:05:47 -07001893 if (sa.getBoolean(
1894 com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated,
1895 hardwareAccelerated)) {
1896 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
1897 }
1898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001899 a.info.launchMode = sa.getInt(
1900 com.android.internal.R.styleable.AndroidManifestActivity_launchMode,
1901 ActivityInfo.LAUNCH_MULTIPLE);
1902 a.info.screenOrientation = sa.getInt(
1903 com.android.internal.R.styleable.AndroidManifestActivity_screenOrientation,
1904 ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
1905 a.info.configChanges = sa.getInt(
1906 com.android.internal.R.styleable.AndroidManifestActivity_configChanges,
1907 0);
1908 a.info.softInputMode = sa.getInt(
1909 com.android.internal.R.styleable.AndroidManifestActivity_windowSoftInputMode,
1910 0);
1911 } else {
1912 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
1913 a.info.configChanges = 0;
1914 }
1915
1916 sa.recycle();
1917
Dianne Hackborn860755f2010-06-03 18:47:52 -07001918 if (receiver && (owner.applicationInfo.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
1919 // A heavy-weight application can not have receives in its main process
1920 // We can do direct compare because we intern all strings.
1921 if (a.info.processName == owner.packageName) {
1922 outError[0] = "Heavy-weight applications can not have receivers in main process";
1923 }
1924 }
1925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001926 if (outError[0] != null) {
1927 return null;
1928 }
1929
1930 int outerDepth = parser.getDepth();
1931 int type;
1932 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1933 && (type != XmlPullParser.END_TAG
1934 || parser.getDepth() > outerDepth)) {
1935 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1936 continue;
1937 }
1938
1939 if (parser.getName().equals("intent-filter")) {
1940 ActivityIntentInfo intent = new ActivityIntentInfo(a);
1941 if (!parseIntent(res, parser, attrs, flags, intent, outError, !receiver)) {
1942 return null;
1943 }
1944 if (intent.countActions() == 0) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07001945 Log.w(TAG, "No actions in intent filter at "
1946 + mArchiveSourcePath + " "
1947 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001948 } else {
1949 a.intents.add(intent);
1950 }
1951 } else if (parser.getName().equals("meta-data")) {
1952 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
1953 outError)) == null) {
1954 return null;
1955 }
1956 } else {
1957 if (!RIGID_PARSER) {
1958 Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
1959 if (receiver) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001960 Log.w(TAG, "Unknown element under <receiver>: " + parser.getName()
1961 + " at " + mArchiveSourcePath + " "
1962 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001963 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001964 Log.w(TAG, "Unknown element under <activity>: " + parser.getName()
1965 + " at " + mArchiveSourcePath + " "
1966 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001967 }
1968 XmlUtils.skipCurrentTag(parser);
1969 continue;
1970 }
1971 if (receiver) {
1972 outError[0] = "Bad element under <receiver>: " + parser.getName();
1973 } else {
1974 outError[0] = "Bad element under <activity>: " + parser.getName();
1975 }
1976 return null;
1977 }
1978 }
1979
1980 if (!setExported) {
1981 a.info.exported = a.intents.size() > 0;
1982 }
1983
1984 return a;
1985 }
1986
1987 private Activity parseActivityAlias(Package owner, Resources res,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001988 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
1989 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 TypedArray sa = res.obtainAttributes(attrs,
1991 com.android.internal.R.styleable.AndroidManifestActivityAlias);
1992
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001993 String targetActivity = sa.getNonConfigurationString(
1994 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001995 if (targetActivity == null) {
1996 outError[0] = "<activity-alias> does not specify android:targetActivity";
1997 sa.recycle();
1998 return null;
1999 }
2000
2001 targetActivity = buildClassName(owner.applicationInfo.packageName,
2002 targetActivity, outError);
2003 if (targetActivity == null) {
2004 sa.recycle();
2005 return null;
2006 }
2007
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002008 if (mParseActivityAliasArgs == null) {
2009 mParseActivityAliasArgs = new ParseComponentArgs(owner, outError,
2010 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
2011 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
2012 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07002013 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002014 mSeparateProcesses,
2015 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002016 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002017 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
2018 mParseActivityAliasArgs.tag = "<activity-alias>";
2019 }
2020
2021 mParseActivityAliasArgs.sa = sa;
2022 mParseActivityAliasArgs.flags = flags;
2023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002024 Activity target = null;
2025
2026 final int NA = owner.activities.size();
2027 for (int i=0; i<NA; i++) {
2028 Activity t = owner.activities.get(i);
2029 if (targetActivity.equals(t.info.name)) {
2030 target = t;
2031 break;
2032 }
2033 }
2034
2035 if (target == null) {
2036 outError[0] = "<activity-alias> target activity " + targetActivity
2037 + " not found in manifest";
2038 sa.recycle();
2039 return null;
2040 }
2041
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002042 ActivityInfo info = new ActivityInfo();
2043 info.targetActivity = targetActivity;
2044 info.configChanges = target.info.configChanges;
2045 info.flags = target.info.flags;
2046 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07002047 info.logo = target.info.logo;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002048 info.labelRes = target.info.labelRes;
2049 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
2050 info.launchMode = target.info.launchMode;
2051 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002052 if (info.descriptionRes == 0) {
2053 info.descriptionRes = target.info.descriptionRes;
2054 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002055 info.screenOrientation = target.info.screenOrientation;
2056 info.taskAffinity = target.info.taskAffinity;
2057 info.theme = target.info.theme;
2058
2059 Activity a = new Activity(mParseActivityAliasArgs, info);
2060 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061 sa.recycle();
2062 return null;
2063 }
2064
2065 final boolean setExported = sa.hasValue(
2066 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
2067 if (setExported) {
2068 a.info.exported = sa.getBoolean(
2069 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
2070 }
2071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002073 str = sa.getNonConfigurationString(
2074 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 if (str != null) {
2076 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
2077 }
2078
2079 sa.recycle();
2080
2081 if (outError[0] != null) {
2082 return null;
2083 }
2084
2085 int outerDepth = parser.getDepth();
2086 int type;
2087 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2088 && (type != XmlPullParser.END_TAG
2089 || parser.getDepth() > outerDepth)) {
2090 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2091 continue;
2092 }
2093
2094 if (parser.getName().equals("intent-filter")) {
2095 ActivityIntentInfo intent = new ActivityIntentInfo(a);
2096 if (!parseIntent(res, parser, attrs, flags, intent, outError, true)) {
2097 return null;
2098 }
2099 if (intent.countActions() == 0) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002100 Log.w(TAG, "No actions in intent filter at "
2101 + mArchiveSourcePath + " "
2102 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002103 } else {
2104 a.intents.add(intent);
2105 }
2106 } else if (parser.getName().equals("meta-data")) {
2107 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
2108 outError)) == null) {
2109 return null;
2110 }
2111 } else {
2112 if (!RIGID_PARSER) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002113 Log.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
2114 + " at " + mArchiveSourcePath + " "
2115 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002116 XmlUtils.skipCurrentTag(parser);
2117 continue;
2118 }
2119 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
2120 return null;
2121 }
2122 }
2123
2124 if (!setExported) {
2125 a.info.exported = a.intents.size() > 0;
2126 }
2127
2128 return a;
2129 }
2130
2131 private Provider parseProvider(Package owner, Resources res,
2132 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2133 throws XmlPullParserException, IOException {
2134 TypedArray sa = res.obtainAttributes(attrs,
2135 com.android.internal.R.styleable.AndroidManifestProvider);
2136
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002137 if (mParseProviderArgs == null) {
2138 mParseProviderArgs = new ParseComponentArgs(owner, outError,
2139 com.android.internal.R.styleable.AndroidManifestProvider_name,
2140 com.android.internal.R.styleable.AndroidManifestProvider_label,
2141 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07002142 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002143 mSeparateProcesses,
2144 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002145 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002146 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
2147 mParseProviderArgs.tag = "<provider>";
2148 }
2149
2150 mParseProviderArgs.sa = sa;
2151 mParseProviderArgs.flags = flags;
2152
2153 Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
2154 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002155 sa.recycle();
2156 return null;
2157 }
2158
2159 p.info.exported = sa.getBoolean(
2160 com.android.internal.R.styleable.AndroidManifestProvider_exported, true);
2161
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002162 String cpname = sa.getNonConfigurationString(
2163 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002164
2165 p.info.isSyncable = sa.getBoolean(
2166 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
2167 false);
2168
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002169 String permission = sa.getNonConfigurationString(
2170 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
2171 String str = sa.getNonConfigurationString(
2172 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002173 if (str == null) {
2174 str = permission;
2175 }
2176 if (str == null) {
2177 p.info.readPermission = owner.applicationInfo.permission;
2178 } else {
2179 p.info.readPermission =
2180 str.length() > 0 ? str.toString().intern() : null;
2181 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002182 str = sa.getNonConfigurationString(
2183 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002184 if (str == null) {
2185 str = permission;
2186 }
2187 if (str == null) {
2188 p.info.writePermission = owner.applicationInfo.permission;
2189 } else {
2190 p.info.writePermission =
2191 str.length() > 0 ? str.toString().intern() : null;
2192 }
2193
2194 p.info.grantUriPermissions = sa.getBoolean(
2195 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
2196 false);
2197
2198 p.info.multiprocess = sa.getBoolean(
2199 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
2200 false);
2201
2202 p.info.initOrder = sa.getInt(
2203 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
2204 0);
2205
2206 sa.recycle();
2207
Dianne Hackborn860755f2010-06-03 18:47:52 -07002208 if ((owner.applicationInfo.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
2209 // A heavy-weight application can not have providers in its main process
2210 // We can do direct compare because we intern all strings.
2211 if (p.info.processName == owner.packageName) {
2212 outError[0] = "Heavy-weight applications can not have providers in main process";
2213 return null;
2214 }
2215 }
2216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002217 if (cpname == null) {
2218 outError[0] = "<provider> does not incude authorities attribute";
2219 return null;
2220 }
2221 p.info.authority = cpname.intern();
2222
2223 if (!parseProviderTags(res, parser, attrs, p, outError)) {
2224 return null;
2225 }
2226
2227 return p;
2228 }
2229
2230 private boolean parseProviderTags(Resources res,
2231 XmlPullParser parser, AttributeSet attrs,
2232 Provider outInfo, String[] outError)
2233 throws XmlPullParserException, IOException {
2234 int outerDepth = parser.getDepth();
2235 int type;
2236 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2237 && (type != XmlPullParser.END_TAG
2238 || parser.getDepth() > outerDepth)) {
2239 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2240 continue;
2241 }
2242
2243 if (parser.getName().equals("meta-data")) {
2244 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
2245 outInfo.metaData, outError)) == null) {
2246 return false;
2247 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002249 } else if (parser.getName().equals("grant-uri-permission")) {
2250 TypedArray sa = res.obtainAttributes(attrs,
2251 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
2252
2253 PatternMatcher pa = null;
2254
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002255 String str = sa.getNonConfigurationString(
2256 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 if (str != null) {
2258 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
2259 }
2260
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002261 str = sa.getNonConfigurationString(
2262 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002263 if (str != null) {
2264 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
2265 }
2266
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002267 str = sa.getNonConfigurationString(
2268 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 if (str != null) {
2270 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
2271 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002273 sa.recycle();
2274
2275 if (pa != null) {
2276 if (outInfo.info.uriPermissionPatterns == null) {
2277 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
2278 outInfo.info.uriPermissionPatterns[0] = pa;
2279 } else {
2280 final int N = outInfo.info.uriPermissionPatterns.length;
2281 PatternMatcher[] newp = new PatternMatcher[N+1];
2282 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
2283 newp[N] = pa;
2284 outInfo.info.uriPermissionPatterns = newp;
2285 }
2286 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002287 } else {
2288 if (!RIGID_PARSER) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002289 Log.w(TAG, "Unknown element under <path-permission>: "
2290 + parser.getName() + " at " + mArchiveSourcePath + " "
2291 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002292 XmlUtils.skipCurrentTag(parser);
2293 continue;
2294 }
2295 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
2296 return false;
2297 }
2298 XmlUtils.skipCurrentTag(parser);
2299
2300 } else if (parser.getName().equals("path-permission")) {
2301 TypedArray sa = res.obtainAttributes(attrs,
2302 com.android.internal.R.styleable.AndroidManifestPathPermission);
2303
2304 PathPermission pa = null;
2305
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002306 String permission = sa.getNonConfigurationString(
2307 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
2308 String readPermission = sa.getNonConfigurationString(
2309 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002310 if (readPermission == null) {
2311 readPermission = permission;
2312 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002313 String writePermission = sa.getNonConfigurationString(
2314 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002315 if (writePermission == null) {
2316 writePermission = permission;
2317 }
2318
2319 boolean havePerm = false;
2320 if (readPermission != null) {
2321 readPermission = readPermission.intern();
2322 havePerm = true;
2323 }
2324 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00002325 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002326 havePerm = true;
2327 }
2328
2329 if (!havePerm) {
2330 if (!RIGID_PARSER) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002331 Log.w(TAG, "No readPermission or writePermssion for <path-permission>: "
2332 + parser.getName() + " at " + mArchiveSourcePath + " "
2333 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002334 XmlUtils.skipCurrentTag(parser);
2335 continue;
2336 }
2337 outError[0] = "No readPermission or writePermssion for <path-permission>";
2338 return false;
2339 }
2340
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002341 String path = sa.getNonConfigurationString(
2342 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002343 if (path != null) {
2344 pa = new PathPermission(path,
2345 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
2346 }
2347
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002348 path = sa.getNonConfigurationString(
2349 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002350 if (path != null) {
2351 pa = new PathPermission(path,
2352 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
2353 }
2354
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002355 path = sa.getNonConfigurationString(
2356 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002357 if (path != null) {
2358 pa = new PathPermission(path,
2359 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
2360 }
2361
2362 sa.recycle();
2363
2364 if (pa != null) {
2365 if (outInfo.info.pathPermissions == null) {
2366 outInfo.info.pathPermissions = new PathPermission[1];
2367 outInfo.info.pathPermissions[0] = pa;
2368 } else {
2369 final int N = outInfo.info.pathPermissions.length;
2370 PathPermission[] newp = new PathPermission[N+1];
2371 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
2372 newp[N] = pa;
2373 outInfo.info.pathPermissions = newp;
2374 }
2375 } else {
2376 if (!RIGID_PARSER) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002377 Log.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
2378 + parser.getName() + " at " + mArchiveSourcePath + " "
2379 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002380 XmlUtils.skipCurrentTag(parser);
2381 continue;
2382 }
2383 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
2384 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002385 }
2386 XmlUtils.skipCurrentTag(parser);
2387
2388 } else {
2389 if (!RIGID_PARSER) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 Log.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002391 + parser.getName() + " at " + mArchiveSourcePath + " "
2392 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002393 XmlUtils.skipCurrentTag(parser);
2394 continue;
2395 }
2396 outError[0] = "Bad element under <provider>: "
2397 + parser.getName();
2398 return false;
2399 }
2400 }
2401 return true;
2402 }
2403
2404 private Service parseService(Package owner, Resources res,
2405 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2406 throws XmlPullParserException, IOException {
2407 TypedArray sa = res.obtainAttributes(attrs,
2408 com.android.internal.R.styleable.AndroidManifestService);
2409
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002410 if (mParseServiceArgs == null) {
2411 mParseServiceArgs = new ParseComponentArgs(owner, outError,
2412 com.android.internal.R.styleable.AndroidManifestService_name,
2413 com.android.internal.R.styleable.AndroidManifestService_label,
2414 com.android.internal.R.styleable.AndroidManifestService_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07002415 com.android.internal.R.styleable.AndroidManifestService_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002416 mSeparateProcesses,
2417 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002418 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002419 com.android.internal.R.styleable.AndroidManifestService_enabled);
2420 mParseServiceArgs.tag = "<service>";
2421 }
2422
2423 mParseServiceArgs.sa = sa;
2424 mParseServiceArgs.flags = flags;
2425
2426 Service s = new Service(mParseServiceArgs, new ServiceInfo());
2427 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002428 sa.recycle();
2429 return null;
2430 }
2431
2432 final boolean setExported = sa.hasValue(
2433 com.android.internal.R.styleable.AndroidManifestService_exported);
2434 if (setExported) {
2435 s.info.exported = sa.getBoolean(
2436 com.android.internal.R.styleable.AndroidManifestService_exported, false);
2437 }
2438
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002439 String str = sa.getNonConfigurationString(
2440 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002441 if (str == null) {
2442 s.info.permission = owner.applicationInfo.permission;
2443 } else {
2444 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
2445 }
2446
2447 sa.recycle();
2448
Dianne Hackborn860755f2010-06-03 18:47:52 -07002449 if ((owner.applicationInfo.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
2450 // A heavy-weight application can not have services in its main process
2451 // We can do direct compare because we intern all strings.
2452 if (s.info.processName == owner.packageName) {
2453 outError[0] = "Heavy-weight applications can not have services in main process";
2454 return null;
2455 }
2456 }
2457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002458 int outerDepth = parser.getDepth();
2459 int type;
2460 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2461 && (type != XmlPullParser.END_TAG
2462 || parser.getDepth() > outerDepth)) {
2463 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2464 continue;
2465 }
2466
2467 if (parser.getName().equals("intent-filter")) {
2468 ServiceIntentInfo intent = new ServiceIntentInfo(s);
2469 if (!parseIntent(res, parser, attrs, flags, intent, outError, false)) {
2470 return null;
2471 }
2472
2473 s.intents.add(intent);
2474 } else if (parser.getName().equals("meta-data")) {
2475 if ((s.metaData=parseMetaData(res, parser, attrs, s.metaData,
2476 outError)) == null) {
2477 return null;
2478 }
2479 } else {
2480 if (!RIGID_PARSER) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002481 Log.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002482 + parser.getName() + " at " + mArchiveSourcePath + " "
2483 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002484 XmlUtils.skipCurrentTag(parser);
2485 continue;
2486 }
2487 outError[0] = "Bad element under <service>: "
2488 + parser.getName();
2489 return null;
2490 }
2491 }
2492
2493 if (!setExported) {
2494 s.info.exported = s.intents.size() > 0;
2495 }
2496
2497 return s;
2498 }
2499
2500 private boolean parseAllMetaData(Resources res,
2501 XmlPullParser parser, AttributeSet attrs, String tag,
2502 Component outInfo, String[] outError)
2503 throws XmlPullParserException, IOException {
2504 int outerDepth = parser.getDepth();
2505 int type;
2506 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2507 && (type != XmlPullParser.END_TAG
2508 || parser.getDepth() > outerDepth)) {
2509 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2510 continue;
2511 }
2512
2513 if (parser.getName().equals("meta-data")) {
2514 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
2515 outInfo.metaData, outError)) == null) {
2516 return false;
2517 }
2518 } else {
2519 if (!RIGID_PARSER) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002520 Log.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002521 + parser.getName() + " at " + mArchiveSourcePath + " "
2522 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002523 XmlUtils.skipCurrentTag(parser);
2524 continue;
2525 }
2526 outError[0] = "Bad element under " + tag + ": "
2527 + parser.getName();
2528 return false;
2529 }
2530 }
2531 return true;
2532 }
2533
2534 private Bundle parseMetaData(Resources res,
2535 XmlPullParser parser, AttributeSet attrs,
2536 Bundle data, String[] outError)
2537 throws XmlPullParserException, IOException {
2538
2539 TypedArray sa = res.obtainAttributes(attrs,
2540 com.android.internal.R.styleable.AndroidManifestMetaData);
2541
2542 if (data == null) {
2543 data = new Bundle();
2544 }
2545
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002546 String name = sa.getNonConfigurationString(
2547 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002548 if (name == null) {
2549 outError[0] = "<meta-data> requires an android:name attribute";
2550 sa.recycle();
2551 return null;
2552 }
2553
Dianne Hackborn854060a2009-07-09 18:14:31 -07002554 name = name.intern();
2555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002556 TypedValue v = sa.peekValue(
2557 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
2558 if (v != null && v.resourceId != 0) {
2559 //Log.i(TAG, "Meta data ref " + name + ": " + v);
2560 data.putInt(name, v.resourceId);
2561 } else {
2562 v = sa.peekValue(
2563 com.android.internal.R.styleable.AndroidManifestMetaData_value);
2564 //Log.i(TAG, "Meta data " + name + ": " + v);
2565 if (v != null) {
2566 if (v.type == TypedValue.TYPE_STRING) {
2567 CharSequence cs = v.coerceToString();
Dianne Hackborn854060a2009-07-09 18:14:31 -07002568 data.putString(name, cs != null ? cs.toString().intern() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
2570 data.putBoolean(name, v.data != 0);
2571 } else if (v.type >= TypedValue.TYPE_FIRST_INT
2572 && v.type <= TypedValue.TYPE_LAST_INT) {
2573 data.putInt(name, v.data);
2574 } else if (v.type == TypedValue.TYPE_FLOAT) {
2575 data.putFloat(name, v.getFloat());
2576 } else {
2577 if (!RIGID_PARSER) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002578 Log.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
2579 + parser.getName() + " at " + mArchiveSourcePath + " "
2580 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002581 } else {
2582 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
2583 data = null;
2584 }
2585 }
2586 } else {
2587 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
2588 data = null;
2589 }
2590 }
2591
2592 sa.recycle();
2593
2594 XmlUtils.skipCurrentTag(parser);
2595
2596 return data;
2597 }
2598
2599 private static final String ANDROID_RESOURCES
2600 = "http://schemas.android.com/apk/res/android";
2601
2602 private boolean parseIntent(Resources res,
2603 XmlPullParser parser, AttributeSet attrs, int flags,
2604 IntentInfo outInfo, String[] outError, boolean isActivity)
2605 throws XmlPullParserException, IOException {
2606
2607 TypedArray sa = res.obtainAttributes(attrs,
2608 com.android.internal.R.styleable.AndroidManifestIntentFilter);
2609
2610 int priority = sa.getInt(
2611 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
2612 if (priority > 0 && isActivity && (flags&PARSE_IS_SYSTEM) == 0) {
2613 Log.w(TAG, "Activity with priority > 0, forcing to 0 at "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002614 + mArchiveSourcePath + " "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 + parser.getPositionDescription());
2616 priority = 0;
2617 }
2618 outInfo.setPriority(priority);
2619
2620 TypedValue v = sa.peekValue(
2621 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
2622 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
2623 outInfo.nonLocalizedLabel = v.coerceToString();
2624 }
2625
2626 outInfo.icon = sa.getResourceId(
2627 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
Adam Powell81cd2e92010-04-21 16:35:18 -07002628
2629 outInfo.logo = sa.getResourceId(
2630 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002631
2632 sa.recycle();
2633
2634 int outerDepth = parser.getDepth();
2635 int type;
2636 while ((type=parser.next()) != parser.END_DOCUMENT
2637 && (type != parser.END_TAG || parser.getDepth() > outerDepth)) {
2638 if (type == parser.END_TAG || type == parser.TEXT) {
2639 continue;
2640 }
2641
2642 String nodeName = parser.getName();
2643 if (nodeName.equals("action")) {
2644 String value = attrs.getAttributeValue(
2645 ANDROID_RESOURCES, "name");
2646 if (value == null || value == "") {
2647 outError[0] = "No value supplied for <android:name>";
2648 return false;
2649 }
2650 XmlUtils.skipCurrentTag(parser);
2651
2652 outInfo.addAction(value);
2653 } else if (nodeName.equals("category")) {
2654 String value = attrs.getAttributeValue(
2655 ANDROID_RESOURCES, "name");
2656 if (value == null || value == "") {
2657 outError[0] = "No value supplied for <android:name>";
2658 return false;
2659 }
2660 XmlUtils.skipCurrentTag(parser);
2661
2662 outInfo.addCategory(value);
2663
2664 } else if (nodeName.equals("data")) {
2665 sa = res.obtainAttributes(attrs,
2666 com.android.internal.R.styleable.AndroidManifestData);
2667
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002668 String str = sa.getNonConfigurationString(
2669 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002670 if (str != null) {
2671 try {
2672 outInfo.addDataType(str);
2673 } catch (IntentFilter.MalformedMimeTypeException e) {
2674 outError[0] = e.toString();
2675 sa.recycle();
2676 return false;
2677 }
2678 }
2679
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002680 str = sa.getNonConfigurationString(
2681 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002682 if (str != null) {
2683 outInfo.addDataScheme(str);
2684 }
2685
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002686 String host = sa.getNonConfigurationString(
2687 com.android.internal.R.styleable.AndroidManifestData_host, 0);
2688 String port = sa.getNonConfigurationString(
2689 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002690 if (host != null) {
2691 outInfo.addDataAuthority(host, port);
2692 }
2693
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002694 str = sa.getNonConfigurationString(
2695 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002696 if (str != null) {
2697 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
2698 }
2699
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002700 str = sa.getNonConfigurationString(
2701 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 if (str != null) {
2703 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
2704 }
2705
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002706 str = sa.getNonConfigurationString(
2707 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002708 if (str != null) {
2709 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
2710 }
2711
2712 sa.recycle();
2713 XmlUtils.skipCurrentTag(parser);
2714 } else if (!RIGID_PARSER) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002715 Log.w(TAG, "Unknown element under <intent-filter>: "
2716 + parser.getName() + " at " + mArchiveSourcePath + " "
2717 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002718 XmlUtils.skipCurrentTag(parser);
2719 } else {
2720 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
2721 return false;
2722 }
2723 }
2724
2725 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
2726 if (false) {
2727 String cats = "";
2728 Iterator<String> it = outInfo.categoriesIterator();
2729 while (it != null && it.hasNext()) {
2730 cats += " " + it.next();
2731 }
2732 System.out.println("Intent d=" +
2733 outInfo.hasDefault + ", cat=" + cats);
2734 }
2735
2736 return true;
2737 }
2738
2739 public final static class Package {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002740 public String packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002741
2742 // For now we only support one application per package.
2743 public final ApplicationInfo applicationInfo = new ApplicationInfo();
2744
2745 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
2746 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
2747 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
2748 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
2749 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
2750 public final ArrayList<Service> services = new ArrayList<Service>(0);
2751 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
2752
2753 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
2754
Dianne Hackborn854060a2009-07-09 18:14:31 -07002755 public ArrayList<String> protectedBroadcasts;
2756
Dianne Hackborn49237342009-08-27 20:08:01 -07002757 public ArrayList<String> usesLibraries = null;
2758 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002759 public String[] usesLibraryFiles = null;
2760
Dianne Hackbornc1552392010-03-03 16:19:01 -08002761 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002762 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002763 public ArrayList<String> mAdoptPermissions = null;
2764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765 // We store the application meta-data independently to avoid multiple unwanted references
2766 public Bundle mAppMetaData = null;
2767
2768 // If this is a 3rd party app, this is the path of the zip file.
2769 public String mPath;
2770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002771 // The version code declared for this package.
2772 public int mVersionCode;
2773
2774 // The version name declared for this package.
2775 public String mVersionName;
2776
2777 // The shared user id that this package wants to use.
2778 public String mSharedUserId;
2779
2780 // The shared user label that this package wants to use.
2781 public int mSharedUserLabel;
2782
2783 // Signatures that were read from the package.
2784 public Signature mSignatures[];
2785
2786 // For use by package manager service for quick lookup of
2787 // preferred up order.
2788 public int mPreferredOrder = 0;
2789
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002790 // For use by the package manager to keep track of the path to the
2791 // file an app came from.
2792 public String mScanPath;
2793
2794 // For use by package manager to keep track of where it has done dexopt.
2795 public boolean mDidDexOpt;
2796
Dianne Hackborn46730fc2010-07-24 16:32:42 -07002797 // User set enabled state.
2798 public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002800 // Additional data supplied by callers.
2801 public Object mExtras;
2802
2803 /*
2804 * Applications hardware preferences
2805 */
2806 public final ArrayList<ConfigurationInfo> configPreferences =
2807 new ArrayList<ConfigurationInfo>();
2808
Dianne Hackborn49237342009-08-27 20:08:01 -07002809 /*
2810 * Applications requested features
2811 */
2812 public ArrayList<FeatureInfo> reqFeatures = null;
2813
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08002814 public int installLocation;
2815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002816 public Package(String _name) {
2817 packageName = _name;
2818 applicationInfo.packageName = _name;
2819 applicationInfo.uid = -1;
2820 }
2821
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002822 public void setPackageName(String newName) {
2823 packageName = newName;
2824 applicationInfo.packageName = newName;
2825 for (int i=permissions.size()-1; i>=0; i--) {
2826 permissions.get(i).setPackageName(newName);
2827 }
2828 for (int i=permissionGroups.size()-1; i>=0; i--) {
2829 permissionGroups.get(i).setPackageName(newName);
2830 }
2831 for (int i=activities.size()-1; i>=0; i--) {
2832 activities.get(i).setPackageName(newName);
2833 }
2834 for (int i=receivers.size()-1; i>=0; i--) {
2835 receivers.get(i).setPackageName(newName);
2836 }
2837 for (int i=providers.size()-1; i>=0; i--) {
2838 providers.get(i).setPackageName(newName);
2839 }
2840 for (int i=services.size()-1; i>=0; i--) {
2841 services.get(i).setPackageName(newName);
2842 }
2843 for (int i=instrumentation.size()-1; i>=0; i--) {
2844 instrumentation.get(i).setPackageName(newName);
2845 }
2846 }
2847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002848 public String toString() {
2849 return "Package{"
2850 + Integer.toHexString(System.identityHashCode(this))
2851 + " " + packageName + "}";
2852 }
2853 }
2854
2855 public static class Component<II extends IntentInfo> {
2856 public final Package owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002857 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002858 public final String className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002859 public Bundle metaData;
2860
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002861 ComponentName componentName;
2862 String componentShortName;
2863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002864 public Component(Package _owner) {
2865 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002866 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002867 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002868 }
2869
2870 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
2871 owner = args.owner;
2872 intents = new ArrayList<II>(0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002873 String name = args.sa.getNonConfigurationString(args.nameRes, 0);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002874 if (name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002875 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002876 args.outError[0] = args.tag + " does not specify android:name";
2877 return;
2878 }
2879
2880 outInfo.name
2881 = buildClassName(owner.applicationInfo.packageName, name, args.outError);
2882 if (outInfo.name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002883 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002884 args.outError[0] = args.tag + " does not have valid android:name";
2885 return;
2886 }
2887
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002888 className = outInfo.name;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002889
2890 int iconVal = args.sa.getResourceId(args.iconRes, 0);
2891 if (iconVal != 0) {
2892 outInfo.icon = iconVal;
2893 outInfo.nonLocalizedLabel = null;
2894 }
Adam Powell81cd2e92010-04-21 16:35:18 -07002895
2896 int logoVal = args.sa.getResourceId(args.logoRes, 0);
2897 if (logoVal != 0) {
2898 outInfo.logo = logoVal;
2899 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002900
2901 TypedValue v = args.sa.peekValue(args.labelRes);
2902 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
2903 outInfo.nonLocalizedLabel = v.coerceToString();
2904 }
2905
2906 outInfo.packageName = owner.packageName;
2907 }
2908
2909 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
2910 this(args, (PackageItemInfo)outInfo);
2911 if (args.outError[0] != null) {
2912 return;
2913 }
2914
2915 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002916 CharSequence pname;
2917 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
2918 pname = args.sa.getNonConfigurationString(args.processRes, 0);
2919 } else {
2920 // Some older apps have been seen to use a resource reference
2921 // here that on older builds was ignored (with a warning). We
2922 // need to continue to do this for them so they don't break.
2923 pname = args.sa.getNonResourceString(args.processRes);
2924 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002925 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002926 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002927 args.flags, args.sepProcesses, args.outError);
2928 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002929
2930 if (args.descriptionRes != 0) {
2931 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
2932 }
2933
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002934 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935 }
2936
2937 public Component(Component<II> clone) {
2938 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002939 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002940 className = clone.className;
2941 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002942 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002943 }
2944
2945 public ComponentName getComponentName() {
2946 if (componentName != null) {
2947 return componentName;
2948 }
2949 if (className != null) {
2950 componentName = new ComponentName(owner.applicationInfo.packageName,
2951 className);
2952 }
2953 return componentName;
2954 }
2955
2956 public String getComponentShortName() {
2957 if (componentShortName != null) {
2958 return componentShortName;
2959 }
2960 ComponentName component = getComponentName();
2961 if (component != null) {
2962 componentShortName = component.flattenToShortString();
2963 }
2964 return componentShortName;
2965 }
2966
2967 public void setPackageName(String packageName) {
2968 componentName = null;
2969 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002970 }
2971 }
2972
2973 public final static class Permission extends Component<IntentInfo> {
2974 public final PermissionInfo info;
2975 public boolean tree;
2976 public PermissionGroup group;
2977
2978 public Permission(Package _owner) {
2979 super(_owner);
2980 info = new PermissionInfo();
2981 }
2982
2983 public Permission(Package _owner, PermissionInfo _info) {
2984 super(_owner);
2985 info = _info;
2986 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002987
2988 public void setPackageName(String packageName) {
2989 super.setPackageName(packageName);
2990 info.packageName = packageName;
2991 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002992
2993 public String toString() {
2994 return "Permission{"
2995 + Integer.toHexString(System.identityHashCode(this))
2996 + " " + info.name + "}";
2997 }
2998 }
2999
3000 public final static class PermissionGroup extends Component<IntentInfo> {
3001 public final PermissionGroupInfo info;
3002
3003 public PermissionGroup(Package _owner) {
3004 super(_owner);
3005 info = new PermissionGroupInfo();
3006 }
3007
3008 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
3009 super(_owner);
3010 info = _info;
3011 }
3012
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003013 public void setPackageName(String packageName) {
3014 super.setPackageName(packageName);
3015 info.packageName = packageName;
3016 }
3017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003018 public String toString() {
3019 return "PermissionGroup{"
3020 + Integer.toHexString(System.identityHashCode(this))
3021 + " " + info.name + "}";
3022 }
3023 }
3024
3025 private static boolean copyNeeded(int flags, Package p, Bundle metaData) {
Dianne Hackborn46730fc2010-07-24 16:32:42 -07003026 if (p.mSetEnabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
3027 boolean enabled = p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
3028 if (p.applicationInfo.enabled != enabled) {
3029 return true;
3030 }
3031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003032 if ((flags & PackageManager.GET_META_DATA) != 0
3033 && (metaData != null || p.mAppMetaData != null)) {
3034 return true;
3035 }
3036 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
3037 && p.usesLibraryFiles != null) {
3038 return true;
3039 }
3040 return false;
3041 }
3042
3043 public static ApplicationInfo generateApplicationInfo(Package p, int flags) {
3044 if (p == null) return null;
3045 if (!copyNeeded(flags, p, null)) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07003046 // CompatibilityMode is global state. It's safe to modify the instance
3047 // of the package.
3048 if (!sCompatibilityModeEnabled) {
3049 p.applicationInfo.disableCompatibilityMode();
3050 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 return p.applicationInfo;
3052 }
3053
3054 // Make shallow copy so we can store the metadata/libraries safely
3055 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
3056 if ((flags & PackageManager.GET_META_DATA) != 0) {
3057 ai.metaData = p.mAppMetaData;
3058 }
3059 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
3060 ai.sharedLibraryFiles = p.usesLibraryFiles;
3061 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07003062 if (!sCompatibilityModeEnabled) {
3063 ai.disableCompatibilityMode();
3064 }
Dianne Hackborn46730fc2010-07-24 16:32:42 -07003065 ai.enabled = p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 return ai;
3067 }
3068
3069 public static final PermissionInfo generatePermissionInfo(
3070 Permission p, int flags) {
3071 if (p == null) return null;
3072 if ((flags&PackageManager.GET_META_DATA) == 0) {
3073 return p.info;
3074 }
3075 PermissionInfo pi = new PermissionInfo(p.info);
3076 pi.metaData = p.metaData;
3077 return pi;
3078 }
3079
3080 public static final PermissionGroupInfo generatePermissionGroupInfo(
3081 PermissionGroup pg, int flags) {
3082 if (pg == null) return null;
3083 if ((flags&PackageManager.GET_META_DATA) == 0) {
3084 return pg.info;
3085 }
3086 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
3087 pgi.metaData = pg.metaData;
3088 return pgi;
3089 }
3090
3091 public final static class Activity extends Component<ActivityIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003092 public final ActivityInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003093
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003094 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
3095 super(args, _info);
3096 info = _info;
3097 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003098 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003099
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003100 public void setPackageName(String packageName) {
3101 super.setPackageName(packageName);
3102 info.packageName = packageName;
3103 }
3104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105 public String toString() {
3106 return "Activity{"
3107 + Integer.toHexString(System.identityHashCode(this))
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003108 + " " + getComponentShortName() + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003109 }
3110 }
3111
3112 public static final ActivityInfo generateActivityInfo(Activity a,
3113 int flags) {
3114 if (a == null) return null;
3115 if (!copyNeeded(flags, a.owner, a.metaData)) {
3116 return a.info;
3117 }
3118 // Make shallow copies so we can store the metadata safely
3119 ActivityInfo ai = new ActivityInfo(a.info);
3120 ai.metaData = a.metaData;
3121 ai.applicationInfo = generateApplicationInfo(a.owner, flags);
3122 return ai;
3123 }
3124
3125 public final static class Service extends Component<ServiceIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003126 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003127
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003128 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
3129 super(args, _info);
3130 info = _info;
3131 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003132 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003133
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003134 public void setPackageName(String packageName) {
3135 super.setPackageName(packageName);
3136 info.packageName = packageName;
3137 }
3138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003139 public String toString() {
3140 return "Service{"
3141 + Integer.toHexString(System.identityHashCode(this))
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003142 + " " + getComponentShortName() + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003143 }
3144 }
3145
3146 public static final ServiceInfo generateServiceInfo(Service s, int flags) {
3147 if (s == null) return null;
3148 if (!copyNeeded(flags, s.owner, s.metaData)) {
3149 return s.info;
3150 }
3151 // Make shallow copies so we can store the metadata safely
3152 ServiceInfo si = new ServiceInfo(s.info);
3153 si.metaData = s.metaData;
3154 si.applicationInfo = generateApplicationInfo(s.owner, flags);
3155 return si;
3156 }
3157
3158 public final static class Provider extends Component {
3159 public final ProviderInfo info;
3160 public boolean syncable;
3161
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003162 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
3163 super(args, _info);
3164 info = _info;
3165 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003166 syncable = false;
3167 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003169 public Provider(Provider existingProvider) {
3170 super(existingProvider);
3171 this.info = existingProvider.info;
3172 this.syncable = existingProvider.syncable;
3173 }
3174
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003175 public void setPackageName(String packageName) {
3176 super.setPackageName(packageName);
3177 info.packageName = packageName;
3178 }
3179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180 public String toString() {
3181 return "Provider{"
3182 + Integer.toHexString(System.identityHashCode(this))
3183 + " " + info.name + "}";
3184 }
3185 }
3186
3187 public static final ProviderInfo generateProviderInfo(Provider p,
3188 int flags) {
3189 if (p == null) return null;
3190 if (!copyNeeded(flags, p.owner, p.metaData)
3191 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
3192 || p.info.uriPermissionPatterns == null)) {
3193 return p.info;
3194 }
3195 // Make shallow copies so we can store the metadata safely
3196 ProviderInfo pi = new ProviderInfo(p.info);
3197 pi.metaData = p.metaData;
3198 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
3199 pi.uriPermissionPatterns = null;
3200 }
3201 pi.applicationInfo = generateApplicationInfo(p.owner, flags);
3202 return pi;
3203 }
3204
3205 public final static class Instrumentation extends Component {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003206 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003207
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003208 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
3209 super(args, _info);
3210 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003211 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003212
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003213 public void setPackageName(String packageName) {
3214 super.setPackageName(packageName);
3215 info.packageName = packageName;
3216 }
3217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003218 public String toString() {
3219 return "Instrumentation{"
3220 + Integer.toHexString(System.identityHashCode(this))
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003221 + " " + getComponentShortName() + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222 }
3223 }
3224
3225 public static final InstrumentationInfo generateInstrumentationInfo(
3226 Instrumentation i, int flags) {
3227 if (i == null) return null;
3228 if ((flags&PackageManager.GET_META_DATA) == 0) {
3229 return i.info;
3230 }
3231 InstrumentationInfo ii = new InstrumentationInfo(i.info);
3232 ii.metaData = i.metaData;
3233 return ii;
3234 }
3235
3236 public static class IntentInfo extends IntentFilter {
3237 public boolean hasDefault;
3238 public int labelRes;
3239 public CharSequence nonLocalizedLabel;
3240 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07003241 public int logo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003242 }
3243
3244 public final static class ActivityIntentInfo extends IntentInfo {
3245 public final Activity activity;
3246
3247 public ActivityIntentInfo(Activity _activity) {
3248 activity = _activity;
3249 }
3250
3251 public String toString() {
3252 return "ActivityIntentInfo{"
3253 + Integer.toHexString(System.identityHashCode(this))
3254 + " " + activity.info.name + "}";
3255 }
3256 }
3257
3258 public final static class ServiceIntentInfo extends IntentInfo {
3259 public final Service service;
3260
3261 public ServiceIntentInfo(Service _service) {
3262 service = _service;
3263 }
3264
3265 public String toString() {
3266 return "ServiceIntentInfo{"
3267 + Integer.toHexString(System.identityHashCode(this))
3268 + " " + service.info.name + "}";
3269 }
3270 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07003271
3272 /**
3273 * @hide
3274 */
3275 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
3276 sCompatibilityModeEnabled = compatibilityModeEnabled;
3277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003278}