blob: e593d5bac8d13053c65bb1ab6ca5a4e9a958e558 [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;
Kenny Root05ca4c92011-09-15 10:36:25 -070031import android.util.Base64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070033import android.util.Log;
Kenny Rootd2d29252011-08-08 11:27:57 -070034import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.util.TypedValue;
Jason parksa3cdaa52011-01-13 14:15:43 -060036import com.android.internal.util.XmlUtils;
37import org.xmlpull.v1.XmlPullParser;
38import org.xmlpull.v1.XmlPullParserException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039
Kenny Rootd63f7db2010-09-27 08:07:48 -070040import java.io.BufferedInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import java.io.File;
42import java.io.IOException;
43import java.io.InputStream;
44import java.lang.ref.WeakReference;
Kenny Root05ca4c92011-09-15 10:36:25 -070045import java.security.KeyFactory;
46import java.security.NoSuchAlgorithmException;
47import java.security.PublicKey;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import java.security.cert.Certificate;
49import java.security.cert.CertificateEncodingException;
Kenny Root05ca4c92011-09-15 10:36:25 -070050import java.security.spec.EncodedKeySpec;
51import java.security.spec.InvalidKeySpecException;
52import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053import java.util.ArrayList;
54import java.util.Enumeration;
55import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -070056import java.util.List;
Kenny Rootbcc954d2011-08-08 16:19:08 -070057import java.util.jar.Attributes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import java.util.jar.JarEntry;
59import java.util.jar.JarFile;
Kenny Rootd2d29252011-08-08 11:27:57 -070060import java.util.jar.Manifest;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061
62/**
63 * Package archive parsing
64 *
65 * {@hide}
66 */
67public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -070068 private static final boolean DEBUG_JAR = false;
69 private static final boolean DEBUG_PARSER = false;
70 private static final boolean DEBUG_BACKUP = false;
71
Kenny Rootbcc954d2011-08-08 16:19:08 -070072 /** File name in an APK for the Android manifest. */
73 private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
74
Dianne Hackborna96cbb42009-05-13 15:06:13 -070075 /** @hide */
76 public static class NewPermissionInfo {
77 public final String name;
78 public final int sdkVersion;
79 public final int fileVersion;
80
81 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
82 this.name = name;
83 this.sdkVersion = sdkVersion;
84 this.fileVersion = fileVersion;
85 }
86 }
87
88 /**
89 * List of new permissions that have been added since 1.0.
90 * NOTE: These must be declared in SDK version order, with permissions
91 * added to older SDKs appearing before those added to newer SDKs.
92 * @hide
93 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -070094 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
95 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -070096 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -070097 android.os.Build.VERSION_CODES.DONUT, 0),
98 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
99 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700100 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101
102 private String mArchiveSourcePath;
103 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700104 private boolean mOnlyCoreApps;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700105 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
106 private static final String SDK_CODENAME = "REL".equals(Build.VERSION.CODENAME)
107 ? null : Build.VERSION.CODENAME;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108
109 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
110
111 private static final Object mSync = new Object();
112 private static WeakReference<byte[]> mReadBuffer;
113
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700114 private static boolean sCompatibilityModeEnabled = true;
115 private static final int PARSE_DEFAULT_INSTALL_LOCATION = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700116
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700117 static class ParsePackageItemArgs {
118 final Package owner;
119 final String[] outError;
120 final int nameRes;
121 final int labelRes;
122 final int iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700123 final int logoRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700124
125 String tag;
126 TypedArray sa;
127
128 ParsePackageItemArgs(Package _owner, String[] _outError,
Adam Powell81cd2e92010-04-21 16:35:18 -0700129 int _nameRes, int _labelRes, int _iconRes, int _logoRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700130 owner = _owner;
131 outError = _outError;
132 nameRes = _nameRes;
133 labelRes = _labelRes;
134 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700135 logoRes = _logoRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700136 }
137 }
138
139 static class ParseComponentArgs extends ParsePackageItemArgs {
140 final String[] sepProcesses;
141 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800142 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700143 final int enabledRes;
144 int flags;
145
146 ParseComponentArgs(Package _owner, String[] _outError,
Adam Powell81cd2e92010-04-21 16:35:18 -0700147 int _nameRes, int _labelRes, int _iconRes, int _logoRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800148 String[] _sepProcesses, int _processRes,
149 int _descriptionRes, int _enabledRes) {
Adam Powell81cd2e92010-04-21 16:35:18 -0700150 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _logoRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700151 sepProcesses = _sepProcesses;
152 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800153 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700154 enabledRes = _enabledRes;
155 }
156 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800157
158 /* Light weight package info.
159 * @hide
160 */
161 public static class PackageLite {
Kenny Root05ca4c92011-09-15 10:36:25 -0700162 public final String packageName;
163 public final int installLocation;
164 public final VerifierInfo[] verifiers;
165
166 public PackageLite(String packageName, int installLocation, List<VerifierInfo> verifiers) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800167 this.packageName = packageName;
168 this.installLocation = installLocation;
Kenny Root05ca4c92011-09-15 10:36:25 -0700169 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800170 }
171 }
172
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700173 private ParsePackageItemArgs mParseInstrumentationArgs;
174 private ParseComponentArgs mParseActivityArgs;
175 private ParseComponentArgs mParseActivityAliasArgs;
176 private ParseComponentArgs mParseServiceArgs;
177 private ParseComponentArgs mParseProviderArgs;
178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 /** If set to true, we will only allow package files that exactly match
180 * the DTD. Otherwise, we try to get as much from the package as we
181 * can without failing. This should normally be set to false, to
182 * support extensions to the DTD in future versions. */
183 private static final boolean RIGID_PARSER = false;
184
185 private static final String TAG = "PackageParser";
186
187 public PackageParser(String archiveSourcePath) {
188 mArchiveSourcePath = archiveSourcePath;
189 }
190
191 public void setSeparateProcesses(String[] procs) {
192 mSeparateProcesses = procs;
193 }
194
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700195 public void setOnlyCoreApps(boolean onlyCoreApps) {
196 mOnlyCoreApps = onlyCoreApps;
197 }
198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 private static final boolean isPackageFilename(String name) {
200 return name.endsWith(".apk");
201 }
202
203 /**
204 * Generate and return the {@link PackageInfo} for a parsed package.
205 *
206 * @param p the parsed package.
207 * @param flags indicating which optional information is included.
208 */
209 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborn78d68832010-10-07 01:12:46 -0700210 int gids[], int flags, long firstInstallTime, long lastUpdateTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211
212 PackageInfo pi = new PackageInfo();
213 pi.packageName = p.packageName;
214 pi.versionCode = p.mVersionCode;
215 pi.versionName = p.mVersionName;
216 pi.sharedUserId = p.mSharedUserId;
217 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborne4a59512010-12-07 11:08:07 -0800218 pi.applicationInfo = generateApplicationInfo(p, flags);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800219 pi.installLocation = p.installLocation;
Dianne Hackborn78d68832010-10-07 01:12:46 -0700220 pi.firstInstallTime = firstInstallTime;
221 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 if ((flags&PackageManager.GET_GIDS) != 0) {
223 pi.gids = gids;
224 }
225 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
226 int N = p.configPreferences.size();
227 if (N > 0) {
228 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700229 p.configPreferences.toArray(pi.configPreferences);
230 }
231 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
232 if (N > 0) {
233 pi.reqFeatures = new FeatureInfo[N];
234 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 }
236 }
237 if ((flags&PackageManager.GET_ACTIVITIES) != 0) {
238 int N = p.activities.size();
239 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700240 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
241 pi.activities = new ActivityInfo[N];
242 } else {
243 int num = 0;
244 for (int i=0; i<N; i++) {
245 if (p.activities.get(i).info.enabled) num++;
246 }
247 pi.activities = new ActivityInfo[num];
248 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700249 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 final Activity activity = p.activities.get(i);
251 if (activity.info.enabled
252 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700253 pi.activities[j++] = generateActivityInfo(p.activities.get(i), flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 }
255 }
256 }
257 }
258 if ((flags&PackageManager.GET_RECEIVERS) != 0) {
259 int N = p.receivers.size();
260 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700261 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
262 pi.receivers = new ActivityInfo[N];
263 } else {
264 int num = 0;
265 for (int i=0; i<N; i++) {
266 if (p.receivers.get(i).info.enabled) num++;
267 }
268 pi.receivers = new ActivityInfo[num];
269 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700270 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 final Activity activity = p.receivers.get(i);
272 if (activity.info.enabled
273 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700274 pi.receivers[j++] = generateActivityInfo(p.receivers.get(i), flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 }
276 }
277 }
278 }
279 if ((flags&PackageManager.GET_SERVICES) != 0) {
280 int N = p.services.size();
281 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700282 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
283 pi.services = new ServiceInfo[N];
284 } else {
285 int num = 0;
286 for (int i=0; i<N; i++) {
287 if (p.services.get(i).info.enabled) num++;
288 }
289 pi.services = new ServiceInfo[num];
290 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700291 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 final Service service = p.services.get(i);
293 if (service.info.enabled
294 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700295 pi.services[j++] = generateServiceInfo(p.services.get(i), flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296 }
297 }
298 }
299 }
300 if ((flags&PackageManager.GET_PROVIDERS) != 0) {
301 int N = p.providers.size();
302 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700303 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
304 pi.providers = new ProviderInfo[N];
305 } else {
306 int num = 0;
307 for (int i=0; i<N; i++) {
308 if (p.providers.get(i).info.enabled) num++;
309 }
310 pi.providers = new ProviderInfo[num];
311 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700312 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 final Provider provider = p.providers.get(i);
314 if (provider.info.enabled
315 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700316 pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 }
318 }
319 }
320 }
321 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
322 int N = p.instrumentation.size();
323 if (N > 0) {
324 pi.instrumentation = new InstrumentationInfo[N];
325 for (int i=0; i<N; i++) {
326 pi.instrumentation[i] = generateInstrumentationInfo(
327 p.instrumentation.get(i), flags);
328 }
329 }
330 }
331 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
332 int N = p.permissions.size();
333 if (N > 0) {
334 pi.permissions = new PermissionInfo[N];
335 for (int i=0; i<N; i++) {
336 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
337 }
338 }
339 N = p.requestedPermissions.size();
340 if (N > 0) {
341 pi.requestedPermissions = new String[N];
342 for (int i=0; i<N; i++) {
343 pi.requestedPermissions[i] = p.requestedPermissions.get(i);
344 }
345 }
346 }
347 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700348 int N = (p.mSignatures != null) ? p.mSignatures.length : 0;
349 if (N > 0) {
350 pi.signatures = new Signature[N];
351 System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352 }
353 }
354 return pi;
355 }
356
357 private Certificate[] loadCertificates(JarFile jarFile, JarEntry je,
358 byte[] readBuffer) {
359 try {
360 // We must read the stream for the JarEntry to retrieve
361 // its certificates.
Kenny Rootd63f7db2010-09-27 08:07:48 -0700362 InputStream is = new BufferedInputStream(jarFile.getInputStream(je));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 while (is.read(readBuffer, 0, readBuffer.length) != -1) {
364 // not using
365 }
366 is.close();
367 return je != null ? je.getCertificates() : null;
368 } catch (IOException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700369 Slog.w(TAG, "Exception reading " + je.getName() + " in "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 + jarFile.getName(), e);
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -0700371 } catch (RuntimeException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700372 Slog.w(TAG, "Exception reading " + je.getName() + " in "
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -0700373 + jarFile.getName(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 }
375 return null;
376 }
377
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800378 public final static int PARSE_IS_SYSTEM = 1<<0;
379 public final static int PARSE_CHATTY = 1<<1;
380 public final static int PARSE_MUST_BE_APK = 1<<2;
381 public final static int PARSE_IGNORE_PROCESSES = 1<<3;
382 public final static int PARSE_FORWARD_LOCK = 1<<4;
383 public final static int PARSE_ON_SDCARD = 1<<5;
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700384 public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385
386 public int getParseError() {
387 return mParseError;
388 }
389
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800390 public Package parsePackage(File sourceFile, String destCodePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 DisplayMetrics metrics, int flags) {
392 mParseError = PackageManager.INSTALL_SUCCEEDED;
393
394 mArchiveSourcePath = sourceFile.getPath();
395 if (!sourceFile.isFile()) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700396 Slog.w(TAG, "Skipping dir: " + mArchiveSourcePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
398 return null;
399 }
400 if (!isPackageFilename(sourceFile.getName())
401 && (flags&PARSE_MUST_BE_APK) != 0) {
402 if ((flags&PARSE_IS_SYSTEM) == 0) {
403 // We expect to have non-.apk files in the system dir,
404 // so don't warn about them.
Kenny Rootd2d29252011-08-08 11:27:57 -0700405 Slog.w(TAG, "Skipping non-package file: " + mArchiveSourcePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 }
407 mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
408 return null;
409 }
410
Kenny Rootd2d29252011-08-08 11:27:57 -0700411 if (DEBUG_JAR)
412 Slog.d(TAG, "Scanning package: " + mArchiveSourcePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413
414 XmlResourceParser parser = null;
415 AssetManager assmgr = null;
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800416 Resources res = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 boolean assetError = true;
418 try {
419 assmgr = new AssetManager();
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700420 int cookie = assmgr.addAssetPath(mArchiveSourcePath);
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800421 if (cookie != 0) {
422 res = new Resources(assmgr, metrics, null);
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700423 assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800424 Build.VERSION.RESOURCES_SDK_INT);
Kenny Rootbcc954d2011-08-08 16:19:08 -0700425 parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 assetError = false;
427 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -0700428 Slog.w(TAG, "Failed adding asset path:"+mArchiveSourcePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 }
430 } catch (Exception e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700431 Slog.w(TAG, "Unable to read AndroidManifest.xml of "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 + mArchiveSourcePath, e);
433 }
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800434 if (assetError) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 if (assmgr != null) assmgr.close();
436 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
437 return null;
438 }
439 String[] errorText = new String[1];
440 Package pkg = null;
441 Exception errorException = null;
442 try {
443 // XXXX todo: need to figure out correct configuration.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 pkg = parsePackage(res, parser, flags, errorText);
445 } catch (Exception e) {
446 errorException = e;
447 mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
448 }
449
450
451 if (pkg == null) {
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700452 // If we are only parsing core apps, then a null with INSTALL_SUCCEEDED
453 // just means to skip this app so don't make a fuss about it.
454 if (!mOnlyCoreApps || mParseError != PackageManager.INSTALL_SUCCEEDED) {
455 if (errorException != null) {
456 Slog.w(TAG, mArchiveSourcePath, errorException);
457 } else {
458 Slog.w(TAG, mArchiveSourcePath + " (at "
459 + parser.getPositionDescription()
460 + "): " + errorText[0]);
461 }
462 if (mParseError == PackageManager.INSTALL_SUCCEEDED) {
463 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
464 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465 }
466 parser.close();
467 assmgr.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 return null;
469 }
470
471 parser.close();
472 assmgr.close();
473
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800474 // Set code and resource paths
475 pkg.mPath = destCodePath;
476 pkg.mScanPath = mArchiveSourcePath;
477 //pkg.applicationInfo.sourceDir = destCodePath;
478 //pkg.applicationInfo.publicSourceDir = destRes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 pkg.mSignatures = null;
480
481 return pkg;
482 }
483
484 public boolean collectCertificates(Package pkg, int flags) {
485 pkg.mSignatures = null;
486
487 WeakReference<byte[]> readBufferRef;
488 byte[] readBuffer = null;
489 synchronized (mSync) {
490 readBufferRef = mReadBuffer;
491 if (readBufferRef != null) {
492 mReadBuffer = null;
493 readBuffer = readBufferRef.get();
494 }
495 if (readBuffer == null) {
496 readBuffer = new byte[8192];
497 readBufferRef = new WeakReference<byte[]>(readBuffer);
498 }
499 }
500
501 try {
502 JarFile jarFile = new JarFile(mArchiveSourcePath);
503
504 Certificate[] certs = null;
505
506 if ((flags&PARSE_IS_SYSTEM) != 0) {
507 // If this package comes from the system image, then we
508 // can trust it... we'll just use the AndroidManifest.xml
509 // to retrieve its signatures, not validating all of the
510 // files.
Kenny Rootbcc954d2011-08-08 16:19:08 -0700511 JarEntry jarEntry = jarFile.getJarEntry(ANDROID_MANIFEST_FILENAME);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 certs = loadCertificates(jarFile, jarEntry, readBuffer);
513 if (certs == null) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700514 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 + " has no certificates at entry "
516 + jarEntry.getName() + "; ignoring!");
517 jarFile.close();
518 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
519 return false;
520 }
Kenny Rootd2d29252011-08-08 11:27:57 -0700521 if (DEBUG_JAR) {
522 Slog.i(TAG, "File " + mArchiveSourcePath + ": entry=" + jarEntry
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 + " certs=" + (certs != null ? certs.length : 0));
524 if (certs != null) {
525 final int N = certs.length;
526 for (int i=0; i<N; i++) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700527 Slog.i(TAG, " Public key: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 + certs[i].getPublicKey().getEncoded()
529 + " " + certs[i].getPublicKey());
530 }
531 }
532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800533 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -0700534 Enumeration<JarEntry> entries = jarFile.entries();
Kenny Rootbcc954d2011-08-08 16:19:08 -0700535 final Manifest manifest = jarFile.getManifest();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 while (entries.hasMoreElements()) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700537 final JarEntry je = entries.nextElement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 if (je.isDirectory()) continue;
Kenny Rootd2d29252011-08-08 11:27:57 -0700539
Kenny Rootbcc954d2011-08-08 16:19:08 -0700540 final String name = je.getName();
541
542 if (name.startsWith("META-INF/"))
543 continue;
544
545 if (ANDROID_MANIFEST_FILENAME.equals(name)) {
546 final Attributes attributes = manifest.getAttributes(name);
547 pkg.manifestDigest = ManifestDigest.fromAttributes(attributes);
548 }
549
550 final Certificate[] localCerts = loadCertificates(jarFile, je, readBuffer);
Kenny Rootd2d29252011-08-08 11:27:57 -0700551 if (DEBUG_JAR) {
552 Slog.i(TAG, "File " + mArchiveSourcePath + " entry " + je.getName()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 + ": certs=" + certs + " ("
554 + (certs != null ? certs.length : 0) + ")");
555 }
Kenny Rootbcc954d2011-08-08 16:19:08 -0700556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 if (localCerts == null) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700558 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559 + " has no certificates at entry "
560 + je.getName() + "; ignoring!");
561 jarFile.close();
562 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
563 return false;
564 } else if (certs == null) {
565 certs = localCerts;
566 } else {
567 // Ensure all certificates match.
568 for (int i=0; i<certs.length; i++) {
569 boolean found = false;
570 for (int j=0; j<localCerts.length; j++) {
571 if (certs[i] != null &&
572 certs[i].equals(localCerts[j])) {
573 found = true;
574 break;
575 }
576 }
577 if (!found || certs.length != localCerts.length) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700578 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800579 + " has mismatched certificates at entry "
580 + je.getName() + "; ignoring!");
581 jarFile.close();
582 mParseError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
583 return false;
584 }
585 }
586 }
587 }
588 }
589 jarFile.close();
590
591 synchronized (mSync) {
592 mReadBuffer = readBufferRef;
593 }
594
595 if (certs != null && certs.length > 0) {
596 final int N = certs.length;
597 pkg.mSignatures = new Signature[certs.length];
598 for (int i=0; i<N; i++) {
599 pkg.mSignatures[i] = new Signature(
600 certs[i].getEncoded());
601 }
602 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -0700603 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 + " has no certificates; ignoring!");
605 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
606 return false;
607 }
608 } catch (CertificateEncodingException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700609 Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
611 return false;
612 } catch (IOException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700613 Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614 mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
615 return false;
616 } catch (RuntimeException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700617 Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
619 return false;
620 }
621
622 return true;
623 }
624
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800625 /*
626 * Utility method that retrieves just the package name and install
627 * location from the apk location at the given file path.
628 * @param packageFilePath file location of the apk
629 * @param flags Special parse flags
Kenny Root930d3af2010-07-30 16:52:29 -0700630 * @return PackageLite object with package information or null on failure.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800631 */
632 public static PackageLite parsePackageLite(String packageFilePath, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 AssetManager assmgr = null;
Kenny Root05ca4c92011-09-15 10:36:25 -0700634 final XmlResourceParser parser;
635 final Resources res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 try {
637 assmgr = new AssetManager();
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700638 assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800639 Build.VERSION.RESOURCES_SDK_INT);
Kenny Root1ebd74a2011-08-03 15:09:44 -0700640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800641 int cookie = assmgr.addAssetPath(packageFilePath);
Kenny Root1ebd74a2011-08-03 15:09:44 -0700642 if (cookie == 0) {
643 return null;
644 }
645
Kenny Root05ca4c92011-09-15 10:36:25 -0700646 final DisplayMetrics metrics = new DisplayMetrics();
647 metrics.setToDefaults();
648 res = new Resources(assmgr, metrics, null);
Kenny Rootbcc954d2011-08-08 16:19:08 -0700649 parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800650 } catch (Exception e) {
651 if (assmgr != null) assmgr.close();
Kenny Rootd2d29252011-08-08 11:27:57 -0700652 Slog.w(TAG, "Unable to read AndroidManifest.xml of "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653 + packageFilePath, e);
654 return null;
655 }
Kenny Root05ca4c92011-09-15 10:36:25 -0700656
657 final AttributeSet attrs = parser;
658 final String errors[] = new String[1];
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800659 PackageLite packageLite = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660 try {
Kenny Root05ca4c92011-09-15 10:36:25 -0700661 packageLite = parsePackageLite(res, parser, attrs, flags, errors);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662 } catch (IOException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700663 Slog.w(TAG, packageFilePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664 } catch (XmlPullParserException e) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700665 Slog.w(TAG, packageFilePath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666 } finally {
667 if (parser != null) parser.close();
668 if (assmgr != null) assmgr.close();
669 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800670 if (packageLite == null) {
Kenny Rootd2d29252011-08-08 11:27:57 -0700671 Slog.e(TAG, "parsePackageLite error: " + errors[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672 return null;
673 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800674 return packageLite;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675 }
676
677 private static String validateName(String name, boolean requiresSeparator) {
678 final int N = name.length();
679 boolean hasSep = false;
680 boolean front = true;
681 for (int i=0; i<N; i++) {
682 final char c = name.charAt(i);
683 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
684 front = false;
685 continue;
686 }
687 if (!front) {
688 if ((c >= '0' && c <= '9') || c == '_') {
689 continue;
690 }
691 }
692 if (c == '.') {
693 hasSep = true;
694 front = true;
695 continue;
696 }
697 return "bad character '" + c + "'";
698 }
699 return hasSep || !requiresSeparator
700 ? null : "must have at least one '.' separator";
701 }
702
703 private static String parsePackageName(XmlPullParser parser,
704 AttributeSet attrs, int flags, String[] outError)
705 throws IOException, XmlPullParserException {
706
707 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -0700708 while ((type = parser.next()) != XmlPullParser.START_TAG
709 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710 ;
711 }
712
Kenny Rootd2d29252011-08-08 11:27:57 -0700713 if (type != XmlPullParser.START_TAG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 outError[0] = "No start tag found";
715 return null;
716 }
Kenny Rootd2d29252011-08-08 11:27:57 -0700717 if (DEBUG_PARSER)
718 Slog.v(TAG, "Root element name: '" + parser.getName() + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 if (!parser.getName().equals("manifest")) {
720 outError[0] = "No <manifest> tag";
721 return null;
722 }
723 String pkgName = attrs.getAttributeValue(null, "package");
724 if (pkgName == null || pkgName.length() == 0) {
725 outError[0] = "<manifest> does not specify package";
726 return null;
727 }
728 String nameError = validateName(pkgName, true);
729 if (nameError != null && !"android".equals(pkgName)) {
730 outError[0] = "<manifest> specifies bad package name \""
731 + pkgName + "\": " + nameError;
732 return null;
733 }
734
735 return pkgName.intern();
736 }
737
Kenny Root05ca4c92011-09-15 10:36:25 -0700738 private static PackageLite parsePackageLite(Resources res, XmlPullParser parser,
739 AttributeSet attrs, int flags, String[] outError) throws IOException,
740 XmlPullParserException {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800741
742 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -0700743 while ((type = parser.next()) != XmlPullParser.START_TAG
744 && type != XmlPullParser.END_DOCUMENT) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800745 ;
746 }
747
Kenny Rootd2d29252011-08-08 11:27:57 -0700748 if (type != XmlPullParser.START_TAG) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800749 outError[0] = "No start tag found";
750 return null;
751 }
Kenny Rootd2d29252011-08-08 11:27:57 -0700752 if (DEBUG_PARSER)
753 Slog.v(TAG, "Root element name: '" + parser.getName() + "'");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800754 if (!parser.getName().equals("manifest")) {
755 outError[0] = "No <manifest> tag";
756 return null;
757 }
758 String pkgName = attrs.getAttributeValue(null, "package");
759 if (pkgName == null || pkgName.length() == 0) {
760 outError[0] = "<manifest> does not specify package";
761 return null;
762 }
763 String nameError = validateName(pkgName, true);
764 if (nameError != null && !"android".equals(pkgName)) {
765 outError[0] = "<manifest> specifies bad package name \""
766 + pkgName + "\": " + nameError;
767 return null;
768 }
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700769 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800770 for (int i = 0; i < attrs.getAttributeCount(); i++) {
771 String attr = attrs.getAttributeName(i);
772 if (attr.equals("installLocation")) {
773 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700774 PARSE_DEFAULT_INSTALL_LOCATION);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800775 break;
776 }
777 }
Kenny Root05ca4c92011-09-15 10:36:25 -0700778
779 // Only search the tree when the tag is directly below <manifest>
780 final int searchDepth = parser.getDepth() + 1;
781
782 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
783 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
784 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
785 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
786 continue;
787 }
788
789 if (parser.getDepth() == searchDepth && "package-verifier".equals(parser.getName())) {
790 final VerifierInfo verifier = parseVerifier(res, parser, attrs, flags, outError);
791 if (verifier != null) {
792 verifiers.add(verifier);
793 }
794 }
795 }
796
797 return new PackageLite(pkgName.intern(), installLocation, verifiers);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800798 }
799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800800 /**
801 * Temporary.
802 */
803 static public Signature stringToSignature(String str) {
804 final int N = str.length();
805 byte[] sig = new byte[N];
806 for (int i=0; i<N; i++) {
807 sig[i] = (byte)str.charAt(i);
808 }
809 return new Signature(sig);
810 }
811
812 private Package parsePackage(
813 Resources res, XmlResourceParser parser, int flags, String[] outError)
814 throws XmlPullParserException, IOException {
815 AttributeSet attrs = parser;
816
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700817 mParseInstrumentationArgs = null;
818 mParseActivityArgs = null;
819 mParseServiceArgs = null;
820 mParseProviderArgs = null;
821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 String pkgName = parsePackageName(parser, attrs, flags, outError);
823 if (pkgName == null) {
824 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
825 return null;
826 }
827 int type;
828
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700829 if (mOnlyCoreApps) {
830 boolean core = attrs.getAttributeBooleanValue(null, "coreApp", false);
831 if (!core) {
832 mParseError = PackageManager.INSTALL_SUCCEEDED;
833 return null;
834 }
835 }
836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837 final Package pkg = new Package(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838 boolean foundApp = false;
Dianne Hackborn851a5412009-05-08 12:06:44 -0700839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 TypedArray sa = res.obtainAttributes(attrs,
841 com.android.internal.R.styleable.AndroidManifest);
842 pkg.mVersionCode = sa.getInteger(
843 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800844 pkg.mVersionName = sa.getNonConfigurationString(
845 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 if (pkg.mVersionName != null) {
847 pkg.mVersionName = pkg.mVersionName.intern();
848 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800849 String str = sa.getNonConfigurationString(
850 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
851 if (str != null && str.length() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800852 String nameError = validateName(str, true);
853 if (nameError != null && !"android".equals(pkgName)) {
854 outError[0] = "<manifest> specifies bad sharedUserId name \""
855 + str + "\": " + nameError;
856 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
857 return null;
858 }
859 pkg.mSharedUserId = str.intern();
860 pkg.mSharedUserLabel = sa.getResourceId(
861 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
862 }
863 sa.recycle();
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -0800864
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800865 pkg.installLocation = sa.getInteger(
866 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700867 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -0700868 pkg.applicationInfo.installLocation = pkg.installLocation;
869
Dianne Hackborn723738c2009-06-25 19:48:04 -0700870 // Resource boolean are -1, so 1 means we don't know the value.
871 int supportsSmallScreens = 1;
872 int supportsNormalScreens = 1;
873 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -0700874 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700875 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700876 int anyDensity = 1;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -0700879 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
880 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
881 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800882 continue;
883 }
884
885 String tagName = parser.getName();
886 if (tagName.equals("application")) {
887 if (foundApp) {
888 if (RIGID_PARSER) {
889 outError[0] = "<manifest> has more than one <application>";
890 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
891 return null;
892 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -0700893 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800894 XmlUtils.skipCurrentTag(parser);
895 continue;
896 }
897 }
898
899 foundApp = true;
900 if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
901 return null;
902 }
903 } else if (tagName.equals("permission-group")) {
904 if (parsePermissionGroup(pkg, res, parser, attrs, outError) == null) {
905 return null;
906 }
907 } else if (tagName.equals("permission")) {
908 if (parsePermission(pkg, res, parser, attrs, outError) == null) {
909 return null;
910 }
911 } else if (tagName.equals("permission-tree")) {
912 if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
913 return null;
914 }
915 } else if (tagName.equals("uses-permission")) {
916 sa = res.obtainAttributes(attrs,
917 com.android.internal.R.styleable.AndroidManifestUsesPermission);
918
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800919 // Note: don't allow this value to be a reference to a resource
920 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 String name = sa.getNonResourceString(
922 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
923
924 sa.recycle();
925
926 if (name != null && !pkg.requestedPermissions.contains(name)) {
Dianne Hackborn854060a2009-07-09 18:14:31 -0700927 pkg.requestedPermissions.add(name.intern());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 }
929
930 XmlUtils.skipCurrentTag(parser);
931
932 } else if (tagName.equals("uses-configuration")) {
933 ConfigurationInfo cPref = new ConfigurationInfo();
934 sa = res.obtainAttributes(attrs,
935 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
936 cPref.reqTouchScreen = sa.getInt(
937 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
938 Configuration.TOUCHSCREEN_UNDEFINED);
939 cPref.reqKeyboardType = sa.getInt(
940 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
941 Configuration.KEYBOARD_UNDEFINED);
942 if (sa.getBoolean(
943 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
944 false)) {
945 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
946 }
947 cPref.reqNavigation = sa.getInt(
948 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
949 Configuration.NAVIGATION_UNDEFINED);
950 if (sa.getBoolean(
951 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
952 false)) {
953 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
954 }
955 sa.recycle();
956 pkg.configPreferences.add(cPref);
957
958 XmlUtils.skipCurrentTag(parser);
959
Suchi Amalapurapud299b812009-06-05 10:26:19 -0700960 } else if (tagName.equals("uses-feature")) {
Dianne Hackborn49237342009-08-27 20:08:01 -0700961 FeatureInfo fi = new FeatureInfo();
Suchi Amalapurapud299b812009-06-05 10:26:19 -0700962 sa = res.obtainAttributes(attrs,
963 com.android.internal.R.styleable.AndroidManifestUsesFeature);
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800964 // Note: don't allow this value to be a reference to a resource
965 // that may change.
Dianne Hackborn49237342009-08-27 20:08:01 -0700966 fi.name = sa.getNonResourceString(
967 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
968 if (fi.name == null) {
969 fi.reqGlEsVersion = sa.getInt(
970 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
971 FeatureInfo.GL_ES_VERSION_UNDEFINED);
972 }
973 if (sa.getBoolean(
974 com.android.internal.R.styleable.AndroidManifestUsesFeature_required,
975 true)) {
976 fi.flags |= FeatureInfo.FLAG_REQUIRED;
977 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -0700978 sa.recycle();
Dianne Hackborn49237342009-08-27 20:08:01 -0700979 if (pkg.reqFeatures == null) {
980 pkg.reqFeatures = new ArrayList<FeatureInfo>();
981 }
982 pkg.reqFeatures.add(fi);
983
984 if (fi.name == null) {
985 ConfigurationInfo cPref = new ConfigurationInfo();
986 cPref.reqGlEsVersion = fi.reqGlEsVersion;
987 pkg.configPreferences.add(cPref);
988 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -0700989
990 XmlUtils.skipCurrentTag(parser);
991
Dianne Hackborn851a5412009-05-08 12:06:44 -0700992 } else if (tagName.equals("uses-sdk")) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700993 if (SDK_VERSION > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 sa = res.obtainAttributes(attrs,
995 com.android.internal.R.styleable.AndroidManifestUsesSdk);
996
Dianne Hackborn851a5412009-05-08 12:06:44 -0700997 int minVers = 0;
998 String minCode = null;
999 int targetVers = 0;
1000 String targetCode = null;
1001
1002 TypedValue val = sa.peekValue(
1003 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
1004 if (val != null) {
1005 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1006 targetCode = minCode = val.string.toString();
1007 } else {
1008 // If it's not a string, it's an integer.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001009 targetVers = minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001010 }
1011 }
1012
1013 val = sa.peekValue(
1014 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
1015 if (val != null) {
1016 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1017 targetCode = minCode = val.string.toString();
1018 } else {
1019 // If it's not a string, it's an integer.
1020 targetVers = val.data;
1021 }
1022 }
1023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 sa.recycle();
1025
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001026 if (minCode != null) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001027 if (!minCode.equals(SDK_CODENAME)) {
1028 if (SDK_CODENAME != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001029 outError[0] = "Requires development platform " + minCode
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001030 + " (current platform is " + SDK_CODENAME + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001031 } else {
1032 outError[0] = "Requires development platform " + minCode
1033 + " but this is a release platform.";
1034 }
1035 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1036 return null;
1037 }
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001038 } else if (minVers > SDK_VERSION) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001039 outError[0] = "Requires newer sdk version #" + minVers
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001040 + " (current version is #" + SDK_VERSION + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001041 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1042 return null;
1043 }
1044
Dianne Hackborn851a5412009-05-08 12:06:44 -07001045 if (targetCode != null) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001046 if (!targetCode.equals(SDK_CODENAME)) {
1047 if (SDK_CODENAME != null) {
Dianne Hackborn851a5412009-05-08 12:06:44 -07001048 outError[0] = "Requires development platform " + targetCode
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001049 + " (current platform is " + SDK_CODENAME + ")";
Dianne Hackborn851a5412009-05-08 12:06:44 -07001050 } else {
1051 outError[0] = "Requires development platform " + targetCode
1052 + " but this is a release platform.";
1053 }
1054 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1055 return null;
1056 }
1057 // If the code matches, it definitely targets this SDK.
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001058 pkg.applicationInfo.targetSdkVersion
1059 = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
1060 } else {
1061 pkg.applicationInfo.targetSdkVersion = targetVers;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 }
1064
1065 XmlUtils.skipCurrentTag(parser);
1066
Dianne Hackborn723738c2009-06-25 19:48:04 -07001067 } else if (tagName.equals("supports-screens")) {
1068 sa = res.obtainAttributes(attrs,
1069 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
1070
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001071 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
1072 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
1073 0);
1074 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
1075 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
1076 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07001077 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
1078 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
1079 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001080
Dianne Hackborn723738c2009-06-25 19:48:04 -07001081 // This is a trick to get a boolean and still able to detect
1082 // if a value was actually set.
1083 supportsSmallScreens = sa.getInteger(
1084 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
1085 supportsSmallScreens);
1086 supportsNormalScreens = sa.getInteger(
1087 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
1088 supportsNormalScreens);
1089 supportsLargeScreens = sa.getInteger(
1090 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
1091 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001092 supportsXLargeScreens = sa.getInteger(
1093 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
1094 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001095 resizeable = sa.getInteger(
1096 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001097 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001098 anyDensity = sa.getInteger(
1099 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
1100 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001101
1102 sa.recycle();
1103
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07001104 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn854060a2009-07-09 18:14:31 -07001105
1106 } else if (tagName.equals("protected-broadcast")) {
1107 sa = res.obtainAttributes(attrs,
1108 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
1109
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001110 // Note: don't allow this value to be a reference to a resource
1111 // that may change.
Dianne Hackborn854060a2009-07-09 18:14:31 -07001112 String name = sa.getNonResourceString(
1113 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
1114
1115 sa.recycle();
1116
1117 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
1118 if (pkg.protectedBroadcasts == null) {
1119 pkg.protectedBroadcasts = new ArrayList<String>();
1120 }
1121 if (!pkg.protectedBroadcasts.contains(name)) {
1122 pkg.protectedBroadcasts.add(name.intern());
1123 }
1124 }
1125
1126 XmlUtils.skipCurrentTag(parser);
1127
1128 } else if (tagName.equals("instrumentation")) {
1129 if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) {
1130 return null;
1131 }
1132
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001133 } else if (tagName.equals("original-package")) {
1134 sa = res.obtainAttributes(attrs,
1135 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1136
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001137 String orig =sa.getNonConfigurationString(
1138 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001139 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08001140 if (pkg.mOriginalPackages == null) {
1141 pkg.mOriginalPackages = new ArrayList<String>();
1142 pkg.mRealPackage = pkg.packageName;
1143 }
1144 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001145 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001146
1147 sa.recycle();
1148
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001149 XmlUtils.skipCurrentTag(parser);
1150
1151 } else if (tagName.equals("adopt-permissions")) {
1152 sa = res.obtainAttributes(attrs,
1153 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1154
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001155 String name = sa.getNonConfigurationString(
1156 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001157
1158 sa.recycle();
1159
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001160 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001161 if (pkg.mAdoptPermissions == null) {
1162 pkg.mAdoptPermissions = new ArrayList<String>();
1163 }
1164 pkg.mAdoptPermissions.add(name);
1165 }
1166
1167 XmlUtils.skipCurrentTag(parser);
1168
Dianne Hackborna0b46c92010-10-21 15:32:06 -07001169 } else if (tagName.equals("uses-gl-texture")) {
1170 // Just skip this tag
1171 XmlUtils.skipCurrentTag(parser);
1172 continue;
1173
1174 } else if (tagName.equals("compatible-screens")) {
1175 // Just skip this tag
1176 XmlUtils.skipCurrentTag(parser);
1177 continue;
1178
Dianne Hackborn854060a2009-07-09 18:14:31 -07001179 } else if (tagName.equals("eat-comment")) {
1180 // Just skip this tag
1181 XmlUtils.skipCurrentTag(parser);
1182 continue;
1183
1184 } else if (RIGID_PARSER) {
1185 outError[0] = "Bad element under <manifest>: "
1186 + parser.getName();
1187 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1188 return null;
1189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07001191 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07001192 + " at " + mArchiveSourcePath + " "
1193 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001194 XmlUtils.skipCurrentTag(parser);
1195 continue;
1196 }
1197 }
1198
1199 if (!foundApp && pkg.instrumentation.size() == 0) {
1200 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
1201 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1202 }
1203
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001204 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001205 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001206 for (int ip=0; ip<NP; ip++) {
1207 final PackageParser.NewPermissionInfo npi
1208 = PackageParser.NEW_PERMISSIONS[ip];
1209 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
1210 break;
1211 }
1212 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001213 if (implicitPerms == null) {
1214 implicitPerms = new StringBuilder(128);
1215 implicitPerms.append(pkg.packageName);
1216 implicitPerms.append(": compat added ");
1217 } else {
1218 implicitPerms.append(' ');
1219 }
1220 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001221 pkg.requestedPermissions.add(npi.name);
1222 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07001223 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001224 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07001225 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001226 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07001227
Dianne Hackborn723738c2009-06-25 19:48:04 -07001228 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
1229 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001230 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001231 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
1232 }
1233 if (supportsNormalScreens != 0) {
1234 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
1235 }
1236 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
1237 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001238 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001239 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
1240 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001241 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
1242 && pkg.applicationInfo.targetSdkVersion
1243 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
1244 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
1245 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001246 if (resizeable < 0 || (resizeable > 0
1247 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001248 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001249 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
1250 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001251 if (anyDensity < 0 || (anyDensity > 0
1252 && pkg.applicationInfo.targetSdkVersion
1253 >= android.os.Build.VERSION_CODES.DONUT)) {
1254 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07001255 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07001256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001257 return pkg;
1258 }
1259
1260 private static String buildClassName(String pkg, CharSequence clsSeq,
1261 String[] outError) {
1262 if (clsSeq == null || clsSeq.length() <= 0) {
1263 outError[0] = "Empty class name in package " + pkg;
1264 return null;
1265 }
1266 String cls = clsSeq.toString();
1267 char c = cls.charAt(0);
1268 if (c == '.') {
1269 return (pkg + cls).intern();
1270 }
1271 if (cls.indexOf('.') < 0) {
1272 StringBuilder b = new StringBuilder(pkg);
1273 b.append('.');
1274 b.append(cls);
1275 return b.toString().intern();
1276 }
1277 if (c >= 'a' && c <= 'z') {
1278 return cls.intern();
1279 }
1280 outError[0] = "Bad class name " + cls + " in package " + pkg;
1281 return null;
1282 }
1283
1284 private static String buildCompoundName(String pkg,
1285 CharSequence procSeq, String type, String[] outError) {
1286 String proc = procSeq.toString();
1287 char c = proc.charAt(0);
1288 if (pkg != null && c == ':') {
1289 if (proc.length() < 2) {
1290 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
1291 + ": must be at least two characters";
1292 return null;
1293 }
1294 String subName = proc.substring(1);
1295 String nameError = validateName(subName, false);
1296 if (nameError != null) {
1297 outError[0] = "Invalid " + type + " name " + proc + " in package "
1298 + pkg + ": " + nameError;
1299 return null;
1300 }
1301 return (pkg + proc).intern();
1302 }
1303 String nameError = validateName(proc, true);
1304 if (nameError != null && !"system".equals(proc)) {
1305 outError[0] = "Invalid " + type + " name " + proc + " in package "
1306 + pkg + ": " + nameError;
1307 return null;
1308 }
1309 return proc.intern();
1310 }
1311
1312 private static String buildProcessName(String pkg, String defProc,
1313 CharSequence procSeq, int flags, String[] separateProcesses,
1314 String[] outError) {
1315 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
1316 return defProc != null ? defProc : pkg;
1317 }
1318 if (separateProcesses != null) {
1319 for (int i=separateProcesses.length-1; i>=0; i--) {
1320 String sp = separateProcesses[i];
1321 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
1322 return pkg;
1323 }
1324 }
1325 }
1326 if (procSeq == null || procSeq.length() <= 0) {
1327 return defProc;
1328 }
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07001329 return buildCompoundName(pkg, procSeq, "process", outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 }
1331
1332 private static String buildTaskAffinityName(String pkg, String defProc,
1333 CharSequence procSeq, String[] outError) {
1334 if (procSeq == null) {
1335 return defProc;
1336 }
1337 if (procSeq.length() <= 0) {
1338 return null;
1339 }
1340 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
1341 }
1342
1343 private PermissionGroup parsePermissionGroup(Package owner, Resources res,
1344 XmlPullParser parser, AttributeSet attrs, String[] outError)
1345 throws XmlPullParserException, IOException {
1346 PermissionGroup perm = new PermissionGroup(owner);
1347
1348 TypedArray sa = res.obtainAttributes(attrs,
1349 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
1350
1351 if (!parsePackageItemInfo(owner, perm.info, outError,
1352 "<permission-group>", sa,
1353 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
1354 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001355 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
1356 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 sa.recycle();
1358 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1359 return null;
1360 }
1361
1362 perm.info.descriptionRes = sa.getResourceId(
1363 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
1364 0);
1365
1366 sa.recycle();
1367
1368 if (!parseAllMetaData(res, parser, attrs, "<permission-group>", perm,
1369 outError)) {
1370 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1371 return null;
1372 }
1373
1374 owner.permissionGroups.add(perm);
1375
1376 return perm;
1377 }
1378
1379 private Permission parsePermission(Package owner, Resources res,
1380 XmlPullParser parser, AttributeSet attrs, String[] outError)
1381 throws XmlPullParserException, IOException {
1382 Permission perm = new Permission(owner);
1383
1384 TypedArray sa = res.obtainAttributes(attrs,
1385 com.android.internal.R.styleable.AndroidManifestPermission);
1386
1387 if (!parsePackageItemInfo(owner, perm.info, outError,
1388 "<permission>", sa,
1389 com.android.internal.R.styleable.AndroidManifestPermission_name,
1390 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001391 com.android.internal.R.styleable.AndroidManifestPermission_icon,
1392 com.android.internal.R.styleable.AndroidManifestPermission_logo)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 sa.recycle();
1394 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1395 return null;
1396 }
1397
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001398 // Note: don't allow this value to be a reference to a resource
1399 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400 perm.info.group = sa.getNonResourceString(
1401 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
1402 if (perm.info.group != null) {
1403 perm.info.group = perm.info.group.intern();
1404 }
1405
1406 perm.info.descriptionRes = sa.getResourceId(
1407 com.android.internal.R.styleable.AndroidManifestPermission_description,
1408 0);
1409
1410 perm.info.protectionLevel = sa.getInt(
1411 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
1412 PermissionInfo.PROTECTION_NORMAL);
1413
1414 sa.recycle();
1415
1416 if (perm.info.protectionLevel == -1) {
1417 outError[0] = "<permission> does not specify protectionLevel";
1418 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1419 return null;
1420 }
1421
1422 if (!parseAllMetaData(res, parser, attrs, "<permission>", perm,
1423 outError)) {
1424 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1425 return null;
1426 }
1427
1428 owner.permissions.add(perm);
1429
1430 return perm;
1431 }
1432
1433 private Permission parsePermissionTree(Package owner, Resources res,
1434 XmlPullParser parser, AttributeSet attrs, String[] outError)
1435 throws XmlPullParserException, IOException {
1436 Permission perm = new Permission(owner);
1437
1438 TypedArray sa = res.obtainAttributes(attrs,
1439 com.android.internal.R.styleable.AndroidManifestPermissionTree);
1440
1441 if (!parsePackageItemInfo(owner, perm.info, outError,
1442 "<permission-tree>", sa,
1443 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
1444 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001445 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
1446 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 sa.recycle();
1448 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1449 return null;
1450 }
1451
1452 sa.recycle();
1453
1454 int index = perm.info.name.indexOf('.');
1455 if (index > 0) {
1456 index = perm.info.name.indexOf('.', index+1);
1457 }
1458 if (index < 0) {
1459 outError[0] = "<permission-tree> name has less than three segments: "
1460 + perm.info.name;
1461 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1462 return null;
1463 }
1464
1465 perm.info.descriptionRes = 0;
1466 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
1467 perm.tree = true;
1468
1469 if (!parseAllMetaData(res, parser, attrs, "<permission-tree>", perm,
1470 outError)) {
1471 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1472 return null;
1473 }
1474
1475 owner.permissions.add(perm);
1476
1477 return perm;
1478 }
1479
1480 private Instrumentation parseInstrumentation(Package owner, Resources res,
1481 XmlPullParser parser, AttributeSet attrs, String[] outError)
1482 throws XmlPullParserException, IOException {
1483 TypedArray sa = res.obtainAttributes(attrs,
1484 com.android.internal.R.styleable.AndroidManifestInstrumentation);
1485
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001486 if (mParseInstrumentationArgs == null) {
1487 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
1488 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
1489 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07001490 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
1491 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001492 mParseInstrumentationArgs.tag = "<instrumentation>";
1493 }
1494
1495 mParseInstrumentationArgs.sa = sa;
1496
1497 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
1498 new InstrumentationInfo());
1499 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 sa.recycle();
1501 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1502 return null;
1503 }
1504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001506 // Note: don't allow this value to be a reference to a resource
1507 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 str = sa.getNonResourceString(
1509 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
1510 a.info.targetPackage = str != null ? str.intern() : null;
1511
1512 a.info.handleProfiling = sa.getBoolean(
1513 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
1514 false);
1515
1516 a.info.functionalTest = sa.getBoolean(
1517 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
1518 false);
1519
1520 sa.recycle();
1521
1522 if (a.info.targetPackage == null) {
1523 outError[0] = "<instrumentation> does not specify targetPackage";
1524 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1525 return null;
1526 }
1527
1528 if (!parseAllMetaData(res, parser, attrs, "<instrumentation>", a,
1529 outError)) {
1530 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1531 return null;
1532 }
1533
1534 owner.instrumentation.add(a);
1535
1536 return a;
1537 }
1538
1539 private boolean parseApplication(Package owner, Resources res,
1540 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
1541 throws XmlPullParserException, IOException {
1542 final ApplicationInfo ai = owner.applicationInfo;
1543 final String pkgName = owner.applicationInfo.packageName;
1544
1545 TypedArray sa = res.obtainAttributes(attrs,
1546 com.android.internal.R.styleable.AndroidManifestApplication);
1547
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001548 String name = sa.getNonConfigurationString(
1549 com.android.internal.R.styleable.AndroidManifestApplication_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 if (name != null) {
1551 ai.className = buildClassName(pkgName, name, outError);
1552 if (ai.className == null) {
1553 sa.recycle();
1554 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1555 return false;
1556 }
1557 }
1558
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001559 String manageSpaceActivity = sa.getNonConfigurationString(
1560 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 if (manageSpaceActivity != null) {
1562 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
1563 outError);
1564 }
1565
Christopher Tate181fafa2009-05-14 11:12:14 -07001566 boolean allowBackup = sa.getBoolean(
1567 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
1568 if (allowBackup) {
1569 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07001570
Christopher Tate3de55bc2010-03-12 17:28:08 -08001571 // backupAgent, killAfterRestore, and restoreAnyVersion are only relevant
1572 // if backup is possible for the given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001573 String backupAgent = sa.getNonConfigurationString(
1574 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent, 0);
Christopher Tate181fafa2009-05-14 11:12:14 -07001575 if (backupAgent != null) {
1576 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07001577 if (DEBUG_BACKUP) {
1578 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001579 + " from " + pkgName + "+" + backupAgent);
1580 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07001581
1582 if (sa.getBoolean(
1583 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
1584 true)) {
1585 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
1586 }
1587 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08001588 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
1589 false)) {
1590 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
1591 }
Christopher Tate181fafa2009-05-14 11:12:14 -07001592 }
1593 }
Christopher Tate4a627c72011-04-01 14:43:32 -07001594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 TypedValue v = sa.peekValue(
1596 com.android.internal.R.styleable.AndroidManifestApplication_label);
1597 if (v != null && (ai.labelRes=v.resourceId) == 0) {
1598 ai.nonLocalizedLabel = v.coerceToString();
1599 }
1600
1601 ai.icon = sa.getResourceId(
1602 com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
Adam Powell81cd2e92010-04-21 16:35:18 -07001603 ai.logo = sa.getResourceId(
1604 com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08001606 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 ai.descriptionRes = sa.getResourceId(
1608 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
1609
1610 if ((flags&PARSE_IS_SYSTEM) != 0) {
1611 if (sa.getBoolean(
1612 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
1613 false)) {
1614 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
1615 }
1616 }
1617
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08001618 if ((flags & PARSE_FORWARD_LOCK) != 0) {
1619 ai.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
1620 }
1621
1622 if ((flags & PARSE_ON_SDCARD) != 0) {
Suchi Amalapurapu6069beb2010-03-10 09:46:49 -08001623 ai.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08001624 }
1625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626 if (sa.getBoolean(
1627 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
1628 false)) {
1629 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
1630 }
1631
1632 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07001633 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08001634 false)) {
1635 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
1636 }
1637
Romain Guy529b60a2010-08-03 18:05:47 -07001638 boolean hardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07001639 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07001640 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Romain Guy812ccbe2010-06-01 14:07:24 -07001641
1642 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
1644 true)) {
1645 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
1646 }
1647
1648 if (sa.getBoolean(
1649 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
1650 false)) {
1651 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
1652 }
1653
1654 if (sa.getBoolean(
1655 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
1656 true)) {
1657 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
1658 }
1659
Dianne Hackbornade3eca2009-05-11 18:54:45 -07001660 if (sa.getBoolean(
1661 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
Dianne Hackborne7fe35b2009-05-13 10:53:41 -07001662 false)) {
Dianne Hackbornade3eca2009-05-11 18:54:45 -07001663 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
1664 }
1665
Jason parksa3cdaa52011-01-13 14:15:43 -06001666 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08001667 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06001668 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08001669 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06001670 }
1671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001673 str = sa.getNonConfigurationString(
1674 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
1676
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07001677 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
1678 str = sa.getNonConfigurationString(
1679 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity, 0);
1680 } else {
1681 // Some older apps have been seen to use a resource reference
1682 // here that on older builds was ignored (with a warning). We
1683 // need to continue to do this for them so they don't break.
1684 str = sa.getNonResourceString(
1685 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
1686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
1688 str, outError);
1689
1690 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07001691 CharSequence pname;
1692 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
1693 pname = sa.getNonConfigurationString(
1694 com.android.internal.R.styleable.AndroidManifestApplication_process, 0);
1695 } else {
1696 // Some older apps have been seen to use a resource reference
1697 // here that on older builds was ignored (with a warning). We
1698 // need to continue to do this for them so they don't break.
1699 pname = sa.getNonResourceString(
1700 com.android.internal.R.styleable.AndroidManifestApplication_process);
1701 }
1702 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001703 flags, mSeparateProcesses, outError);
1704
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001705 ai.enabled = sa.getBoolean(
1706 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001707
Dianne Hackborn02486b12010-08-26 14:18:37 -07001708 if (false) {
1709 if (sa.getBoolean(
1710 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
1711 false)) {
Dianne Hackborn54e570f2010-10-04 18:32:32 -07001712 ai.flags |= ApplicationInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07001713
1714 // A heavy-weight application can not be in a custom process.
1715 // We can do direct compare because we intern all strings.
1716 if (ai.processName != null && ai.processName != ai.packageName) {
1717 outError[0] = "cantSaveState applications can not use custom processes";
1718 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07001719 }
1720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001721 }
1722
Adam Powell269248d2011-08-02 10:26:54 -07001723 ai.uiOptions = sa.getInt(
1724 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
1725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726 sa.recycle();
1727
1728 if (outError[0] != null) {
1729 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1730 return false;
1731 }
1732
1733 final int innerDepth = parser.getDepth();
1734
1735 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001736 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1737 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
1738 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 continue;
1740 }
1741
1742 String tagName = parser.getName();
1743 if (tagName.equals("activity")) {
Romain Guy529b60a2010-08-03 18:05:47 -07001744 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
1745 hardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 if (a == null) {
1747 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1748 return false;
1749 }
1750
1751 owner.activities.add(a);
1752
1753 } else if (tagName.equals("receiver")) {
Romain Guy529b60a2010-08-03 18:05:47 -07001754 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 if (a == null) {
1756 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1757 return false;
1758 }
1759
1760 owner.receivers.add(a);
1761
1762 } else if (tagName.equals("service")) {
1763 Service s = parseService(owner, res, parser, attrs, flags, outError);
1764 if (s == null) {
1765 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1766 return false;
1767 }
1768
1769 owner.services.add(s);
1770
1771 } else if (tagName.equals("provider")) {
1772 Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
1773 if (p == null) {
1774 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1775 return false;
1776 }
1777
1778 owner.providers.add(p);
1779
1780 } else if (tagName.equals("activity-alias")) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001781 Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 if (a == null) {
1783 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1784 return false;
1785 }
1786
1787 owner.activities.add(a);
1788
1789 } else if (parser.getName().equals("meta-data")) {
1790 // note: application meta-data is stored off to the side, so it can
1791 // remain null in the primary copy (we like to avoid extra copies because
1792 // it can be large)
1793 if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,
1794 outError)) == null) {
1795 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1796 return false;
1797 }
1798
1799 } else if (tagName.equals("uses-library")) {
1800 sa = res.obtainAttributes(attrs,
1801 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
1802
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001803 // Note: don't allow this value to be a reference to a resource
1804 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 String lname = sa.getNonResourceString(
1806 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07001807 boolean req = sa.getBoolean(
1808 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
1809 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001810
1811 sa.recycle();
1812
Dianne Hackborn49237342009-08-27 20:08:01 -07001813 if (lname != null) {
1814 if (req) {
1815 if (owner.usesLibraries == null) {
1816 owner.usesLibraries = new ArrayList<String>();
1817 }
1818 if (!owner.usesLibraries.contains(lname)) {
1819 owner.usesLibraries.add(lname.intern());
1820 }
1821 } else {
1822 if (owner.usesOptionalLibraries == null) {
1823 owner.usesOptionalLibraries = new ArrayList<String>();
1824 }
1825 if (!owner.usesOptionalLibraries.contains(lname)) {
1826 owner.usesOptionalLibraries.add(lname.intern());
1827 }
1828 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 }
1830
1831 XmlUtils.skipCurrentTag(parser);
1832
Dianne Hackborncef65ee2010-09-30 18:27:22 -07001833 } else if (tagName.equals("uses-package")) {
1834 // Dependencies for app installers; we don't currently try to
1835 // enforce this.
1836 XmlUtils.skipCurrentTag(parser);
1837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001838 } else {
1839 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07001840 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001841 + " at " + mArchiveSourcePath + " "
1842 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 XmlUtils.skipCurrentTag(parser);
1844 continue;
1845 } else {
1846 outError[0] = "Bad element under <application>: " + tagName;
1847 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1848 return false;
1849 }
1850 }
1851 }
1852
1853 return true;
1854 }
1855
1856 private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
1857 String[] outError, String tag, TypedArray sa,
Adam Powell81cd2e92010-04-21 16:35:18 -07001858 int nameRes, int labelRes, int iconRes, int logoRes) {
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001859 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 if (name == null) {
1861 outError[0] = tag + " does not specify android:name";
1862 return false;
1863 }
1864
1865 outInfo.name
1866 = buildClassName(owner.applicationInfo.packageName, name, outError);
1867 if (outInfo.name == null) {
1868 return false;
1869 }
1870
1871 int iconVal = sa.getResourceId(iconRes, 0);
1872 if (iconVal != 0) {
1873 outInfo.icon = iconVal;
1874 outInfo.nonLocalizedLabel = null;
1875 }
Adam Powell81cd2e92010-04-21 16:35:18 -07001876
1877 int logoVal = sa.getResourceId(logoRes, 0);
1878 if (logoVal != 0) {
1879 outInfo.logo = logoVal;
1880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001881
1882 TypedValue v = sa.peekValue(labelRes);
1883 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
1884 outInfo.nonLocalizedLabel = v.coerceToString();
1885 }
1886
1887 outInfo.packageName = owner.packageName;
1888
1889 return true;
1890 }
1891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 private Activity parseActivity(Package owner, Resources res,
1893 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
Romain Guy529b60a2010-08-03 18:05:47 -07001894 boolean receiver, boolean hardwareAccelerated)
1895 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001896 TypedArray sa = res.obtainAttributes(attrs,
1897 com.android.internal.R.styleable.AndroidManifestActivity);
1898
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001899 if (mParseActivityArgs == null) {
1900 mParseActivityArgs = new ParseComponentArgs(owner, outError,
1901 com.android.internal.R.styleable.AndroidManifestActivity_name,
1902 com.android.internal.R.styleable.AndroidManifestActivity_label,
1903 com.android.internal.R.styleable.AndroidManifestActivity_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07001904 com.android.internal.R.styleable.AndroidManifestActivity_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001905 mSeparateProcesses,
1906 com.android.internal.R.styleable.AndroidManifestActivity_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08001907 com.android.internal.R.styleable.AndroidManifestActivity_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001908 com.android.internal.R.styleable.AndroidManifestActivity_enabled);
1909 }
1910
1911 mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
1912 mParseActivityArgs.sa = sa;
1913 mParseActivityArgs.flags = flags;
1914
1915 Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
1916 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 sa.recycle();
1918 return null;
1919 }
1920
1921 final boolean setExported = sa.hasValue(
1922 com.android.internal.R.styleable.AndroidManifestActivity_exported);
1923 if (setExported) {
1924 a.info.exported = sa.getBoolean(
1925 com.android.internal.R.styleable.AndroidManifestActivity_exported, false);
1926 }
1927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001928 a.info.theme = sa.getResourceId(
1929 com.android.internal.R.styleable.AndroidManifestActivity_theme, 0);
1930
Adam Powell269248d2011-08-02 10:26:54 -07001931 a.info.uiOptions = sa.getInt(
1932 com.android.internal.R.styleable.AndroidManifestActivity_uiOptions,
1933 a.info.applicationInfo.uiOptions);
1934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001935 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001936 str = sa.getNonConfigurationString(
1937 com.android.internal.R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 if (str == null) {
1939 a.info.permission = owner.applicationInfo.permission;
1940 } else {
1941 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
1942 }
1943
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001944 str = sa.getNonConfigurationString(
1945 com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
1947 owner.applicationInfo.taskAffinity, str, outError);
1948
1949 a.info.flags = 0;
1950 if (sa.getBoolean(
1951 com.android.internal.R.styleable.AndroidManifestActivity_multiprocess,
1952 false)) {
1953 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
1954 }
1955
1956 if (sa.getBoolean(
1957 com.android.internal.R.styleable.AndroidManifestActivity_finishOnTaskLaunch,
1958 false)) {
1959 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
1960 }
1961
1962 if (sa.getBoolean(
1963 com.android.internal.R.styleable.AndroidManifestActivity_clearTaskOnLaunch,
1964 false)) {
1965 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
1966 }
1967
1968 if (sa.getBoolean(
1969 com.android.internal.R.styleable.AndroidManifestActivity_noHistory,
1970 false)) {
1971 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
1972 }
1973
1974 if (sa.getBoolean(
1975 com.android.internal.R.styleable.AndroidManifestActivity_alwaysRetainTaskState,
1976 false)) {
1977 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
1978 }
1979
1980 if (sa.getBoolean(
1981 com.android.internal.R.styleable.AndroidManifestActivity_stateNotNeeded,
1982 false)) {
1983 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
1984 }
1985
1986 if (sa.getBoolean(
1987 com.android.internal.R.styleable.AndroidManifestActivity_excludeFromRecents,
1988 false)) {
1989 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
1990 }
1991
1992 if (sa.getBoolean(
1993 com.android.internal.R.styleable.AndroidManifestActivity_allowTaskReparenting,
1994 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
1995 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
1996 }
1997
Dianne Hackbornffa42482009-09-23 22:20:11 -07001998 if (sa.getBoolean(
1999 com.android.internal.R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs,
2000 false)) {
2001 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
2002 }
2003
Daniel Sandler613dde42010-06-21 13:46:39 -04002004 if (sa.getBoolean(
2005 com.android.internal.R.styleable.AndroidManifestActivity_immersive,
2006 false)) {
2007 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
2008 }
Romain Guy529b60a2010-08-03 18:05:47 -07002009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010 if (!receiver) {
Romain Guy529b60a2010-08-03 18:05:47 -07002011 if (sa.getBoolean(
2012 com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated,
2013 hardwareAccelerated)) {
2014 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
2015 }
2016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017 a.info.launchMode = sa.getInt(
2018 com.android.internal.R.styleable.AndroidManifestActivity_launchMode,
2019 ActivityInfo.LAUNCH_MULTIPLE);
2020 a.info.screenOrientation = sa.getInt(
2021 com.android.internal.R.styleable.AndroidManifestActivity_screenOrientation,
2022 ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
2023 a.info.configChanges = sa.getInt(
2024 com.android.internal.R.styleable.AndroidManifestActivity_configChanges,
2025 0);
2026 a.info.softInputMode = sa.getInt(
2027 com.android.internal.R.styleable.AndroidManifestActivity_windowSoftInputMode,
2028 0);
2029 } else {
2030 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2031 a.info.configChanges = 0;
2032 }
2033
2034 sa.recycle();
2035
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002036 if (receiver && (owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07002037 // A heavy-weight application can not have receives in its main process
2038 // We can do direct compare because we intern all strings.
2039 if (a.info.processName == owner.packageName) {
2040 outError[0] = "Heavy-weight applications can not have receivers in main process";
2041 }
2042 }
2043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002044 if (outError[0] != null) {
2045 return null;
2046 }
2047
2048 int outerDepth = parser.getDepth();
2049 int type;
2050 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2051 && (type != XmlPullParser.END_TAG
2052 || parser.getDepth() > outerDepth)) {
2053 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2054 continue;
2055 }
2056
2057 if (parser.getName().equals("intent-filter")) {
2058 ActivityIntentInfo intent = new ActivityIntentInfo(a);
2059 if (!parseIntent(res, parser, attrs, flags, intent, outError, !receiver)) {
2060 return null;
2061 }
2062 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002063 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002064 + mArchiveSourcePath + " "
2065 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066 } else {
2067 a.intents.add(intent);
2068 }
2069 } else if (parser.getName().equals("meta-data")) {
2070 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
2071 outError)) == null) {
2072 return null;
2073 }
2074 } else {
2075 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002076 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002078 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002079 + " at " + mArchiveSourcePath + " "
2080 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002081 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002082 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002083 + " at " + mArchiveSourcePath + " "
2084 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002085 }
2086 XmlUtils.skipCurrentTag(parser);
2087 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002088 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002089 if (receiver) {
2090 outError[0] = "Bad element under <receiver>: " + parser.getName();
2091 } else {
2092 outError[0] = "Bad element under <activity>: " + parser.getName();
2093 }
2094 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002095 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002096 }
2097 }
2098
2099 if (!setExported) {
2100 a.info.exported = a.intents.size() > 0;
2101 }
2102
2103 return a;
2104 }
2105
2106 private Activity parseActivityAlias(Package owner, Resources res,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002107 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2108 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 TypedArray sa = res.obtainAttributes(attrs,
2110 com.android.internal.R.styleable.AndroidManifestActivityAlias);
2111
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002112 String targetActivity = sa.getNonConfigurationString(
2113 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002114 if (targetActivity == null) {
2115 outError[0] = "<activity-alias> does not specify android:targetActivity";
2116 sa.recycle();
2117 return null;
2118 }
2119
2120 targetActivity = buildClassName(owner.applicationInfo.packageName,
2121 targetActivity, outError);
2122 if (targetActivity == null) {
2123 sa.recycle();
2124 return null;
2125 }
2126
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002127 if (mParseActivityAliasArgs == null) {
2128 mParseActivityAliasArgs = new ParseComponentArgs(owner, outError,
2129 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
2130 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
2131 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07002132 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002133 mSeparateProcesses,
2134 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002135 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002136 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
2137 mParseActivityAliasArgs.tag = "<activity-alias>";
2138 }
2139
2140 mParseActivityAliasArgs.sa = sa;
2141 mParseActivityAliasArgs.flags = flags;
2142
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002143 Activity target = null;
2144
2145 final int NA = owner.activities.size();
2146 for (int i=0; i<NA; i++) {
2147 Activity t = owner.activities.get(i);
2148 if (targetActivity.equals(t.info.name)) {
2149 target = t;
2150 break;
2151 }
2152 }
2153
2154 if (target == null) {
2155 outError[0] = "<activity-alias> target activity " + targetActivity
2156 + " not found in manifest";
2157 sa.recycle();
2158 return null;
2159 }
2160
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002161 ActivityInfo info = new ActivityInfo();
2162 info.targetActivity = targetActivity;
2163 info.configChanges = target.info.configChanges;
2164 info.flags = target.info.flags;
2165 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07002166 info.logo = target.info.logo;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002167 info.labelRes = target.info.labelRes;
2168 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
2169 info.launchMode = target.info.launchMode;
2170 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002171 if (info.descriptionRes == 0) {
2172 info.descriptionRes = target.info.descriptionRes;
2173 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002174 info.screenOrientation = target.info.screenOrientation;
2175 info.taskAffinity = target.info.taskAffinity;
2176 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07002177 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07002178 info.uiOptions = target.info.uiOptions;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002179
2180 Activity a = new Activity(mParseActivityAliasArgs, info);
2181 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002182 sa.recycle();
2183 return null;
2184 }
2185
2186 final boolean setExported = sa.hasValue(
2187 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
2188 if (setExported) {
2189 a.info.exported = sa.getBoolean(
2190 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
2191 }
2192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002193 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002194 str = sa.getNonConfigurationString(
2195 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 if (str != null) {
2197 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
2198 }
2199
2200 sa.recycle();
2201
2202 if (outError[0] != null) {
2203 return null;
2204 }
2205
2206 int outerDepth = parser.getDepth();
2207 int type;
2208 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2209 && (type != XmlPullParser.END_TAG
2210 || parser.getDepth() > outerDepth)) {
2211 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2212 continue;
2213 }
2214
2215 if (parser.getName().equals("intent-filter")) {
2216 ActivityIntentInfo intent = new ActivityIntentInfo(a);
2217 if (!parseIntent(res, parser, attrs, flags, intent, outError, true)) {
2218 return null;
2219 }
2220 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002221 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002222 + mArchiveSourcePath + " "
2223 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002224 } else {
2225 a.intents.add(intent);
2226 }
2227 } else if (parser.getName().equals("meta-data")) {
2228 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
2229 outError)) == null) {
2230 return null;
2231 }
2232 } else {
2233 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002234 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002235 + " at " + mArchiveSourcePath + " "
2236 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002237 XmlUtils.skipCurrentTag(parser);
2238 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002239 } else {
2240 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
2241 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002242 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002243 }
2244 }
2245
2246 if (!setExported) {
2247 a.info.exported = a.intents.size() > 0;
2248 }
2249
2250 return a;
2251 }
2252
2253 private Provider parseProvider(Package owner, Resources res,
2254 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2255 throws XmlPullParserException, IOException {
2256 TypedArray sa = res.obtainAttributes(attrs,
2257 com.android.internal.R.styleable.AndroidManifestProvider);
2258
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002259 if (mParseProviderArgs == null) {
2260 mParseProviderArgs = new ParseComponentArgs(owner, outError,
2261 com.android.internal.R.styleable.AndroidManifestProvider_name,
2262 com.android.internal.R.styleable.AndroidManifestProvider_label,
2263 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07002264 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002265 mSeparateProcesses,
2266 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002267 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002268 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
2269 mParseProviderArgs.tag = "<provider>";
2270 }
2271
2272 mParseProviderArgs.sa = sa;
2273 mParseProviderArgs.flags = flags;
2274
2275 Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
2276 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002277 sa.recycle();
2278 return null;
2279 }
2280
2281 p.info.exported = sa.getBoolean(
2282 com.android.internal.R.styleable.AndroidManifestProvider_exported, true);
2283
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002284 String cpname = sa.getNonConfigurationString(
2285 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002286
2287 p.info.isSyncable = sa.getBoolean(
2288 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
2289 false);
2290
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002291 String permission = sa.getNonConfigurationString(
2292 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
2293 String str = sa.getNonConfigurationString(
2294 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295 if (str == null) {
2296 str = permission;
2297 }
2298 if (str == null) {
2299 p.info.readPermission = owner.applicationInfo.permission;
2300 } else {
2301 p.info.readPermission =
2302 str.length() > 0 ? str.toString().intern() : null;
2303 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002304 str = sa.getNonConfigurationString(
2305 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002306 if (str == null) {
2307 str = permission;
2308 }
2309 if (str == null) {
2310 p.info.writePermission = owner.applicationInfo.permission;
2311 } else {
2312 p.info.writePermission =
2313 str.length() > 0 ? str.toString().intern() : null;
2314 }
2315
2316 p.info.grantUriPermissions = sa.getBoolean(
2317 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
2318 false);
2319
2320 p.info.multiprocess = sa.getBoolean(
2321 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
2322 false);
2323
2324 p.info.initOrder = sa.getInt(
2325 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
2326 0);
2327
2328 sa.recycle();
2329
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002330 if ((owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07002331 // A heavy-weight application can not have providers in its main process
2332 // We can do direct compare because we intern all strings.
2333 if (p.info.processName == owner.packageName) {
2334 outError[0] = "Heavy-weight applications can not have providers in main process";
2335 return null;
2336 }
2337 }
2338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002339 if (cpname == null) {
2340 outError[0] = "<provider> does not incude authorities attribute";
2341 return null;
2342 }
2343 p.info.authority = cpname.intern();
2344
2345 if (!parseProviderTags(res, parser, attrs, p, outError)) {
2346 return null;
2347 }
2348
2349 return p;
2350 }
2351
2352 private boolean parseProviderTags(Resources res,
2353 XmlPullParser parser, AttributeSet attrs,
2354 Provider outInfo, String[] outError)
2355 throws XmlPullParserException, IOException {
2356 int outerDepth = parser.getDepth();
2357 int type;
2358 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2359 && (type != XmlPullParser.END_TAG
2360 || parser.getDepth() > outerDepth)) {
2361 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2362 continue;
2363 }
2364
2365 if (parser.getName().equals("meta-data")) {
2366 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
2367 outInfo.metaData, outError)) == null) {
2368 return false;
2369 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002371 } else if (parser.getName().equals("grant-uri-permission")) {
2372 TypedArray sa = res.obtainAttributes(attrs,
2373 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
2374
2375 PatternMatcher pa = null;
2376
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002377 String str = sa.getNonConfigurationString(
2378 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379 if (str != null) {
2380 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
2381 }
2382
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002383 str = sa.getNonConfigurationString(
2384 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002385 if (str != null) {
2386 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
2387 }
2388
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002389 str = sa.getNonConfigurationString(
2390 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002391 if (str != null) {
2392 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
2393 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002395 sa.recycle();
2396
2397 if (pa != null) {
2398 if (outInfo.info.uriPermissionPatterns == null) {
2399 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
2400 outInfo.info.uriPermissionPatterns[0] = pa;
2401 } else {
2402 final int N = outInfo.info.uriPermissionPatterns.length;
2403 PatternMatcher[] newp = new PatternMatcher[N+1];
2404 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
2405 newp[N] = pa;
2406 outInfo.info.uriPermissionPatterns = newp;
2407 }
2408 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002409 } else {
2410 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002411 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002412 + parser.getName() + " at " + mArchiveSourcePath + " "
2413 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002414 XmlUtils.skipCurrentTag(parser);
2415 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002416 } else {
2417 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
2418 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002419 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002420 }
2421 XmlUtils.skipCurrentTag(parser);
2422
2423 } else if (parser.getName().equals("path-permission")) {
2424 TypedArray sa = res.obtainAttributes(attrs,
2425 com.android.internal.R.styleable.AndroidManifestPathPermission);
2426
2427 PathPermission pa = null;
2428
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002429 String permission = sa.getNonConfigurationString(
2430 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
2431 String readPermission = sa.getNonConfigurationString(
2432 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002433 if (readPermission == null) {
2434 readPermission = permission;
2435 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002436 String writePermission = sa.getNonConfigurationString(
2437 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002438 if (writePermission == null) {
2439 writePermission = permission;
2440 }
2441
2442 boolean havePerm = false;
2443 if (readPermission != null) {
2444 readPermission = readPermission.intern();
2445 havePerm = true;
2446 }
2447 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00002448 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002449 havePerm = true;
2450 }
2451
2452 if (!havePerm) {
2453 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002454 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002455 + parser.getName() + " at " + mArchiveSourcePath + " "
2456 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002457 XmlUtils.skipCurrentTag(parser);
2458 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002459 } else {
2460 outError[0] = "No readPermission or writePermssion for <path-permission>";
2461 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002462 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002463 }
2464
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002465 String path = sa.getNonConfigurationString(
2466 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002467 if (path != null) {
2468 pa = new PathPermission(path,
2469 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
2470 }
2471
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002472 path = sa.getNonConfigurationString(
2473 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002474 if (path != null) {
2475 pa = new PathPermission(path,
2476 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
2477 }
2478
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002479 path = sa.getNonConfigurationString(
2480 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002481 if (path != null) {
2482 pa = new PathPermission(path,
2483 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
2484 }
2485
2486 sa.recycle();
2487
2488 if (pa != null) {
2489 if (outInfo.info.pathPermissions == null) {
2490 outInfo.info.pathPermissions = new PathPermission[1];
2491 outInfo.info.pathPermissions[0] = pa;
2492 } else {
2493 final int N = outInfo.info.pathPermissions.length;
2494 PathPermission[] newp = new PathPermission[N+1];
2495 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
2496 newp[N] = pa;
2497 outInfo.info.pathPermissions = newp;
2498 }
2499 } else {
2500 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002501 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002502 + parser.getName() + " at " + mArchiveSourcePath + " "
2503 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07002504 XmlUtils.skipCurrentTag(parser);
2505 continue;
2506 }
2507 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
2508 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509 }
2510 XmlUtils.skipCurrentTag(parser);
2511
2512 } else {
2513 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002514 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002515 + parser.getName() + " at " + mArchiveSourcePath + " "
2516 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 XmlUtils.skipCurrentTag(parser);
2518 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002519 } else {
2520 outError[0] = "Bad element under <provider>: " + parser.getName();
2521 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002523 }
2524 }
2525 return true;
2526 }
2527
2528 private Service parseService(Package owner, Resources res,
2529 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2530 throws XmlPullParserException, IOException {
2531 TypedArray sa = res.obtainAttributes(attrs,
2532 com.android.internal.R.styleable.AndroidManifestService);
2533
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002534 if (mParseServiceArgs == null) {
2535 mParseServiceArgs = new ParseComponentArgs(owner, outError,
2536 com.android.internal.R.styleable.AndroidManifestService_name,
2537 com.android.internal.R.styleable.AndroidManifestService_label,
2538 com.android.internal.R.styleable.AndroidManifestService_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07002539 com.android.internal.R.styleable.AndroidManifestService_logo,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002540 mSeparateProcesses,
2541 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002542 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002543 com.android.internal.R.styleable.AndroidManifestService_enabled);
2544 mParseServiceArgs.tag = "<service>";
2545 }
2546
2547 mParseServiceArgs.sa = sa;
2548 mParseServiceArgs.flags = flags;
2549
2550 Service s = new Service(mParseServiceArgs, new ServiceInfo());
2551 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 sa.recycle();
2553 return null;
2554 }
2555
2556 final boolean setExported = sa.hasValue(
2557 com.android.internal.R.styleable.AndroidManifestService_exported);
2558 if (setExported) {
2559 s.info.exported = sa.getBoolean(
2560 com.android.internal.R.styleable.AndroidManifestService_exported, false);
2561 }
2562
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002563 String str = sa.getNonConfigurationString(
2564 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002565 if (str == null) {
2566 s.info.permission = owner.applicationInfo.permission;
2567 } else {
2568 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
2569 }
2570
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002571 s.info.flags = 0;
2572 if (sa.getBoolean(
2573 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
2574 false)) {
2575 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
2576 }
2577
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002578 sa.recycle();
2579
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002580 if ((owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07002581 // A heavy-weight application can not have services in its main process
2582 // We can do direct compare because we intern all strings.
2583 if (s.info.processName == owner.packageName) {
2584 outError[0] = "Heavy-weight applications can not have services in main process";
2585 return null;
2586 }
2587 }
2588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002589 int outerDepth = parser.getDepth();
2590 int type;
2591 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2592 && (type != XmlPullParser.END_TAG
2593 || parser.getDepth() > outerDepth)) {
2594 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2595 continue;
2596 }
2597
2598 if (parser.getName().equals("intent-filter")) {
2599 ServiceIntentInfo intent = new ServiceIntentInfo(s);
2600 if (!parseIntent(res, parser, attrs, flags, intent, outError, false)) {
2601 return null;
2602 }
2603
2604 s.intents.add(intent);
2605 } else if (parser.getName().equals("meta-data")) {
2606 if ((s.metaData=parseMetaData(res, parser, attrs, s.metaData,
2607 outError)) == null) {
2608 return null;
2609 }
2610 } else {
2611 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002612 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002613 + parser.getName() + " at " + mArchiveSourcePath + " "
2614 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 XmlUtils.skipCurrentTag(parser);
2616 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002617 } else {
2618 outError[0] = "Bad element under <service>: " + parser.getName();
2619 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 }
2622 }
2623
2624 if (!setExported) {
2625 s.info.exported = s.intents.size() > 0;
2626 }
2627
2628 return s;
2629 }
2630
2631 private boolean parseAllMetaData(Resources res,
2632 XmlPullParser parser, AttributeSet attrs, String tag,
2633 Component outInfo, String[] outError)
2634 throws XmlPullParserException, IOException {
2635 int outerDepth = parser.getDepth();
2636 int type;
2637 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2638 && (type != XmlPullParser.END_TAG
2639 || parser.getDepth() > outerDepth)) {
2640 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2641 continue;
2642 }
2643
2644 if (parser.getName().equals("meta-data")) {
2645 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
2646 outInfo.metaData, outError)) == null) {
2647 return false;
2648 }
2649 } else {
2650 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002651 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002652 + parser.getName() + " at " + mArchiveSourcePath + " "
2653 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002654 XmlUtils.skipCurrentTag(parser);
2655 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07002656 } else {
2657 outError[0] = "Bad element under " + tag + ": " + parser.getName();
2658 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002659 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002660 }
2661 }
2662 return true;
2663 }
2664
2665 private Bundle parseMetaData(Resources res,
2666 XmlPullParser parser, AttributeSet attrs,
2667 Bundle data, String[] outError)
2668 throws XmlPullParserException, IOException {
2669
2670 TypedArray sa = res.obtainAttributes(attrs,
2671 com.android.internal.R.styleable.AndroidManifestMetaData);
2672
2673 if (data == null) {
2674 data = new Bundle();
2675 }
2676
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002677 String name = sa.getNonConfigurationString(
2678 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 if (name == null) {
2680 outError[0] = "<meta-data> requires an android:name attribute";
2681 sa.recycle();
2682 return null;
2683 }
2684
Dianne Hackborn854060a2009-07-09 18:14:31 -07002685 name = name.intern();
2686
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002687 TypedValue v = sa.peekValue(
2688 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
2689 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002690 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002691 data.putInt(name, v.resourceId);
2692 } else {
2693 v = sa.peekValue(
2694 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07002695 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002696 if (v != null) {
2697 if (v.type == TypedValue.TYPE_STRING) {
2698 CharSequence cs = v.coerceToString();
Dianne Hackborn854060a2009-07-09 18:14:31 -07002699 data.putString(name, cs != null ? cs.toString().intern() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002700 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
2701 data.putBoolean(name, v.data != 0);
2702 } else if (v.type >= TypedValue.TYPE_FIRST_INT
2703 && v.type <= TypedValue.TYPE_LAST_INT) {
2704 data.putInt(name, v.data);
2705 } else if (v.type == TypedValue.TYPE_FLOAT) {
2706 data.putFloat(name, v.getFloat());
2707 } else {
2708 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002709 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002710 + parser.getName() + " at " + mArchiveSourcePath + " "
2711 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002712 } else {
2713 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
2714 data = null;
2715 }
2716 }
2717 } else {
2718 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
2719 data = null;
2720 }
2721 }
2722
2723 sa.recycle();
2724
2725 XmlUtils.skipCurrentTag(parser);
2726
2727 return data;
2728 }
2729
Kenny Root05ca4c92011-09-15 10:36:25 -07002730 private static VerifierInfo parseVerifier(Resources res, XmlPullParser parser,
2731 AttributeSet attrs, int flags, String[] outError) throws XmlPullParserException,
2732 IOException {
2733 final TypedArray sa = res.obtainAttributes(attrs,
2734 com.android.internal.R.styleable.AndroidManifestPackageVerifier);
2735
2736 final String packageName = sa.getNonResourceString(
2737 com.android.internal.R.styleable.AndroidManifestPackageVerifier_name);
2738
2739 final String encodedPublicKey = sa.getNonResourceString(
2740 com.android.internal.R.styleable.AndroidManifestPackageVerifier_publicKey);
2741
2742 sa.recycle();
2743
2744 if (packageName == null || packageName.length() == 0) {
2745 Slog.i(TAG, "verifier package name was null; skipping");
2746 return null;
2747 } else if (encodedPublicKey == null) {
2748 Slog.i(TAG, "verifier " + packageName + " public key was null; skipping");
2749 }
2750
2751 EncodedKeySpec keySpec;
2752 try {
2753 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
2754 keySpec = new X509EncodedKeySpec(encoded);
2755 } catch (IllegalArgumentException e) {
2756 Slog.i(TAG, "Could not parse verifier " + packageName + " public key; invalid Base64");
2757 return null;
2758 }
2759
2760 /* First try the key as an RSA key. */
2761 try {
2762 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
2763 final PublicKey publicKey = keyFactory.generatePublic(keySpec);
2764 return new VerifierInfo(packageName, publicKey);
2765 } catch (NoSuchAlgorithmException e) {
2766 Log.wtf(TAG, "Could not parse public key because RSA isn't included in build");
2767 return null;
2768 } catch (InvalidKeySpecException e) {
2769 // Not a RSA public key.
2770 }
2771
2772 /* Now try it as a DSA key. */
2773 try {
2774 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
2775 final PublicKey publicKey = keyFactory.generatePublic(keySpec);
2776 return new VerifierInfo(packageName, publicKey);
2777 } catch (NoSuchAlgorithmException e) {
2778 Log.wtf(TAG, "Could not parse public key because DSA isn't included in build");
2779 return null;
2780 } catch (InvalidKeySpecException e) {
2781 // Not a DSA public key.
2782 }
2783
2784 return null;
2785 }
2786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002787 private static final String ANDROID_RESOURCES
2788 = "http://schemas.android.com/apk/res/android";
2789
2790 private boolean parseIntent(Resources res,
2791 XmlPullParser parser, AttributeSet attrs, int flags,
2792 IntentInfo outInfo, String[] outError, boolean isActivity)
2793 throws XmlPullParserException, IOException {
2794
2795 TypedArray sa = res.obtainAttributes(attrs,
2796 com.android.internal.R.styleable.AndroidManifestIntentFilter);
2797
2798 int priority = sa.getInt(
2799 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002800 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08002801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002802 TypedValue v = sa.peekValue(
2803 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
2804 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
2805 outInfo.nonLocalizedLabel = v.coerceToString();
2806 }
2807
2808 outInfo.icon = sa.getResourceId(
2809 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
Adam Powell81cd2e92010-04-21 16:35:18 -07002810
2811 outInfo.logo = sa.getResourceId(
2812 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002813
2814 sa.recycle();
2815
2816 int outerDepth = parser.getDepth();
2817 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07002818 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2819 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2820 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002821 continue;
2822 }
2823
2824 String nodeName = parser.getName();
2825 if (nodeName.equals("action")) {
2826 String value = attrs.getAttributeValue(
2827 ANDROID_RESOURCES, "name");
2828 if (value == null || value == "") {
2829 outError[0] = "No value supplied for <android:name>";
2830 return false;
2831 }
2832 XmlUtils.skipCurrentTag(parser);
2833
2834 outInfo.addAction(value);
2835 } else if (nodeName.equals("category")) {
2836 String value = attrs.getAttributeValue(
2837 ANDROID_RESOURCES, "name");
2838 if (value == null || value == "") {
2839 outError[0] = "No value supplied for <android:name>";
2840 return false;
2841 }
2842 XmlUtils.skipCurrentTag(parser);
2843
2844 outInfo.addCategory(value);
2845
2846 } else if (nodeName.equals("data")) {
2847 sa = res.obtainAttributes(attrs,
2848 com.android.internal.R.styleable.AndroidManifestData);
2849
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002850 String str = sa.getNonConfigurationString(
2851 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002852 if (str != null) {
2853 try {
2854 outInfo.addDataType(str);
2855 } catch (IntentFilter.MalformedMimeTypeException e) {
2856 outError[0] = e.toString();
2857 sa.recycle();
2858 return false;
2859 }
2860 }
2861
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002862 str = sa.getNonConfigurationString(
2863 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002864 if (str != null) {
2865 outInfo.addDataScheme(str);
2866 }
2867
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002868 String host = sa.getNonConfigurationString(
2869 com.android.internal.R.styleable.AndroidManifestData_host, 0);
2870 String port = sa.getNonConfigurationString(
2871 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002872 if (host != null) {
2873 outInfo.addDataAuthority(host, port);
2874 }
2875
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002876 str = sa.getNonConfigurationString(
2877 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002878 if (str != null) {
2879 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
2880 }
2881
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002882 str = sa.getNonConfigurationString(
2883 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002884 if (str != null) {
2885 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
2886 }
2887
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002888 str = sa.getNonConfigurationString(
2889 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002890 if (str != null) {
2891 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
2892 }
2893
2894 sa.recycle();
2895 XmlUtils.skipCurrentTag(parser);
2896 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002897 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002898 + parser.getName() + " at " + mArchiveSourcePath + " "
2899 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002900 XmlUtils.skipCurrentTag(parser);
2901 } else {
2902 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
2903 return false;
2904 }
2905 }
2906
2907 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07002908
2909 if (DEBUG_PARSER) {
2910 final StringBuilder cats = new StringBuilder("Intent d=");
2911 cats.append(outInfo.hasDefault);
2912 cats.append(", cat=");
2913
2914 final Iterator<String> it = outInfo.categoriesIterator();
2915 if (it != null) {
2916 while (it.hasNext()) {
2917 cats.append(' ');
2918 cats.append(it.next());
2919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002920 }
Kenny Rootd2d29252011-08-08 11:27:57 -07002921 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002922 }
2923
2924 return true;
2925 }
2926
2927 public final static class Package {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002928 public String packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929
2930 // For now we only support one application per package.
2931 public final ApplicationInfo applicationInfo = new ApplicationInfo();
2932
2933 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
2934 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
2935 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
2936 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
2937 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
2938 public final ArrayList<Service> services = new ArrayList<Service>(0);
2939 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
2940
2941 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
2942
Dianne Hackborn854060a2009-07-09 18:14:31 -07002943 public ArrayList<String> protectedBroadcasts;
2944
Dianne Hackborn49237342009-08-27 20:08:01 -07002945 public ArrayList<String> usesLibraries = null;
2946 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002947 public String[] usesLibraryFiles = null;
2948
Dianne Hackbornc1552392010-03-03 16:19:01 -08002949 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002950 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002951 public ArrayList<String> mAdoptPermissions = null;
2952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 // We store the application meta-data independently to avoid multiple unwanted references
2954 public Bundle mAppMetaData = null;
2955
2956 // If this is a 3rd party app, this is the path of the zip file.
2957 public String mPath;
2958
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959 // The version code declared for this package.
2960 public int mVersionCode;
2961
2962 // The version name declared for this package.
2963 public String mVersionName;
2964
2965 // The shared user id that this package wants to use.
2966 public String mSharedUserId;
2967
2968 // The shared user label that this package wants to use.
2969 public int mSharedUserLabel;
2970
2971 // Signatures that were read from the package.
2972 public Signature mSignatures[];
2973
2974 // For use by package manager service for quick lookup of
2975 // preferred up order.
2976 public int mPreferredOrder = 0;
2977
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002978 // For use by the package manager to keep track of the path to the
2979 // file an app came from.
2980 public String mScanPath;
2981
2982 // For use by package manager to keep track of where it has done dexopt.
2983 public boolean mDidDexOpt;
2984
Dianne Hackborn46730fc2010-07-24 16:32:42 -07002985 // User set enabled state.
2986 public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2987
Dianne Hackborne7f97212011-02-24 14:40:20 -08002988 // Whether the package has been stopped.
2989 public boolean mSetStopped = false;
2990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 // Additional data supplied by callers.
2992 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07002993
2994 // Whether an operation is currently pending on this package
2995 public boolean mOperationPending;
2996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002997 /*
2998 * Applications hardware preferences
2999 */
3000 public final ArrayList<ConfigurationInfo> configPreferences =
3001 new ArrayList<ConfigurationInfo>();
3002
Dianne Hackborn49237342009-08-27 20:08:01 -07003003 /*
3004 * Applications requested features
3005 */
3006 public ArrayList<FeatureInfo> reqFeatures = null;
3007
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08003008 public int installLocation;
3009
Kenny Rootbcc954d2011-08-08 16:19:08 -07003010 /**
3011 * Digest suitable for comparing whether this package's manifest is the
3012 * same as another.
3013 */
3014 public ManifestDigest manifestDigest;
3015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003016 public Package(String _name) {
3017 packageName = _name;
3018 applicationInfo.packageName = _name;
3019 applicationInfo.uid = -1;
3020 }
3021
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003022 public void setPackageName(String newName) {
3023 packageName = newName;
3024 applicationInfo.packageName = newName;
3025 for (int i=permissions.size()-1; i>=0; i--) {
3026 permissions.get(i).setPackageName(newName);
3027 }
3028 for (int i=permissionGroups.size()-1; i>=0; i--) {
3029 permissionGroups.get(i).setPackageName(newName);
3030 }
3031 for (int i=activities.size()-1; i>=0; i--) {
3032 activities.get(i).setPackageName(newName);
3033 }
3034 for (int i=receivers.size()-1; i>=0; i--) {
3035 receivers.get(i).setPackageName(newName);
3036 }
3037 for (int i=providers.size()-1; i>=0; i--) {
3038 providers.get(i).setPackageName(newName);
3039 }
3040 for (int i=services.size()-1; i>=0; i--) {
3041 services.get(i).setPackageName(newName);
3042 }
3043 for (int i=instrumentation.size()-1; i>=0; i--) {
3044 instrumentation.get(i).setPackageName(newName);
3045 }
3046 }
3047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003048 public String toString() {
3049 return "Package{"
3050 + Integer.toHexString(System.identityHashCode(this))
3051 + " " + packageName + "}";
3052 }
3053 }
3054
3055 public static class Component<II extends IntentInfo> {
3056 public final Package owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003057 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003058 public final String className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003059 public Bundle metaData;
3060
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003061 ComponentName componentName;
3062 String componentShortName;
3063
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003064 public Component(Package _owner) {
3065 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003066 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003067 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003068 }
3069
3070 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
3071 owner = args.owner;
3072 intents = new ArrayList<II>(0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003073 String name = args.sa.getNonConfigurationString(args.nameRes, 0);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003074 if (name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003075 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003076 args.outError[0] = args.tag + " does not specify android:name";
3077 return;
3078 }
3079
3080 outInfo.name
3081 = buildClassName(owner.applicationInfo.packageName, name, args.outError);
3082 if (outInfo.name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003083 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003084 args.outError[0] = args.tag + " does not have valid android:name";
3085 return;
3086 }
3087
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003088 className = outInfo.name;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003089
3090 int iconVal = args.sa.getResourceId(args.iconRes, 0);
3091 if (iconVal != 0) {
3092 outInfo.icon = iconVal;
3093 outInfo.nonLocalizedLabel = null;
3094 }
Adam Powell81cd2e92010-04-21 16:35:18 -07003095
3096 int logoVal = args.sa.getResourceId(args.logoRes, 0);
3097 if (logoVal != 0) {
3098 outInfo.logo = logoVal;
3099 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003100
3101 TypedValue v = args.sa.peekValue(args.labelRes);
3102 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
3103 outInfo.nonLocalizedLabel = v.coerceToString();
3104 }
3105
3106 outInfo.packageName = owner.packageName;
3107 }
3108
3109 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
3110 this(args, (PackageItemInfo)outInfo);
3111 if (args.outError[0] != null) {
3112 return;
3113 }
3114
3115 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003116 CharSequence pname;
3117 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3118 pname = args.sa.getNonConfigurationString(args.processRes, 0);
3119 } else {
3120 // Some older apps have been seen to use a resource reference
3121 // here that on older builds was ignored (with a warning). We
3122 // need to continue to do this for them so they don't break.
3123 pname = args.sa.getNonResourceString(args.processRes);
3124 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003125 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003126 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003127 args.flags, args.sepProcesses, args.outError);
3128 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003129
3130 if (args.descriptionRes != 0) {
3131 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
3132 }
3133
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003134 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003135 }
3136
3137 public Component(Component<II> clone) {
3138 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003139 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003140 className = clone.className;
3141 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003142 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003143 }
3144
3145 public ComponentName getComponentName() {
3146 if (componentName != null) {
3147 return componentName;
3148 }
3149 if (className != null) {
3150 componentName = new ComponentName(owner.applicationInfo.packageName,
3151 className);
3152 }
3153 return componentName;
3154 }
3155
3156 public String getComponentShortName() {
3157 if (componentShortName != null) {
3158 return componentShortName;
3159 }
3160 ComponentName component = getComponentName();
3161 if (component != null) {
3162 componentShortName = component.flattenToShortString();
3163 }
3164 return componentShortName;
3165 }
3166
3167 public void setPackageName(String packageName) {
3168 componentName = null;
3169 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003170 }
3171 }
3172
3173 public final static class Permission extends Component<IntentInfo> {
3174 public final PermissionInfo info;
3175 public boolean tree;
3176 public PermissionGroup group;
3177
3178 public Permission(Package _owner) {
3179 super(_owner);
3180 info = new PermissionInfo();
3181 }
3182
3183 public Permission(Package _owner, PermissionInfo _info) {
3184 super(_owner);
3185 info = _info;
3186 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003187
3188 public void setPackageName(String packageName) {
3189 super.setPackageName(packageName);
3190 info.packageName = packageName;
3191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003192
3193 public String toString() {
3194 return "Permission{"
3195 + Integer.toHexString(System.identityHashCode(this))
3196 + " " + info.name + "}";
3197 }
3198 }
3199
3200 public final static class PermissionGroup extends Component<IntentInfo> {
3201 public final PermissionGroupInfo info;
3202
3203 public PermissionGroup(Package _owner) {
3204 super(_owner);
3205 info = new PermissionGroupInfo();
3206 }
3207
3208 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
3209 super(_owner);
3210 info = _info;
3211 }
3212
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 "PermissionGroup{"
3220 + Integer.toHexString(System.identityHashCode(this))
3221 + " " + info.name + "}";
3222 }
3223 }
3224
3225 private static boolean copyNeeded(int flags, Package p, Bundle metaData) {
Dianne Hackborn46730fc2010-07-24 16:32:42 -07003226 if (p.mSetEnabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
3227 boolean enabled = p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
3228 if (p.applicationInfo.enabled != enabled) {
3229 return true;
3230 }
3231 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003232 if ((flags & PackageManager.GET_META_DATA) != 0
3233 && (metaData != null || p.mAppMetaData != null)) {
3234 return true;
3235 }
3236 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
3237 && p.usesLibraryFiles != null) {
3238 return true;
3239 }
3240 return false;
3241 }
3242
3243 public static ApplicationInfo generateApplicationInfo(Package p, int flags) {
3244 if (p == null) return null;
3245 if (!copyNeeded(flags, p, null)) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07003246 // CompatibilityMode is global state. It's safe to modify the instance
3247 // of the package.
3248 if (!sCompatibilityModeEnabled) {
3249 p.applicationInfo.disableCompatibilityMode();
3250 }
Dianne Hackborne7f97212011-02-24 14:40:20 -08003251 if (p.mSetStopped) {
3252 p.applicationInfo.flags |= ApplicationInfo.FLAG_STOPPED;
3253 } else {
3254 p.applicationInfo.flags &= ~ApplicationInfo.FLAG_STOPPED;
3255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003256 return p.applicationInfo;
3257 }
3258
3259 // Make shallow copy so we can store the metadata/libraries safely
3260 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
3261 if ((flags & PackageManager.GET_META_DATA) != 0) {
3262 ai.metaData = p.mAppMetaData;
3263 }
3264 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
3265 ai.sharedLibraryFiles = p.usesLibraryFiles;
3266 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07003267 if (!sCompatibilityModeEnabled) {
3268 ai.disableCompatibilityMode();
3269 }
Dianne Hackborne7f97212011-02-24 14:40:20 -08003270 if (p.mSetStopped) {
3271 p.applicationInfo.flags |= ApplicationInfo.FLAG_STOPPED;
3272 } else {
3273 p.applicationInfo.flags &= ~ApplicationInfo.FLAG_STOPPED;
3274 }
John Reck4b7b7cc2011-02-02 11:57:44 -08003275 if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
3276 ai.enabled = true;
Dianne Hackborn0ac30312011-06-17 14:49:23 -07003277 } else if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
3278 || p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
John Reck4b7b7cc2011-02-02 11:57:44 -08003279 ai.enabled = false;
3280 }
Dianne Hackborn0ac30312011-06-17 14:49:23 -07003281 ai.enabledSetting = p.mSetEnabled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003282 return ai;
3283 }
3284
3285 public static final PermissionInfo generatePermissionInfo(
3286 Permission p, int flags) {
3287 if (p == null) return null;
3288 if ((flags&PackageManager.GET_META_DATA) == 0) {
3289 return p.info;
3290 }
3291 PermissionInfo pi = new PermissionInfo(p.info);
3292 pi.metaData = p.metaData;
3293 return pi;
3294 }
3295
3296 public static final PermissionGroupInfo generatePermissionGroupInfo(
3297 PermissionGroup pg, int flags) {
3298 if (pg == null) return null;
3299 if ((flags&PackageManager.GET_META_DATA) == 0) {
3300 return pg.info;
3301 }
3302 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
3303 pgi.metaData = pg.metaData;
3304 return pgi;
3305 }
3306
3307 public final static class Activity extends Component<ActivityIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003308 public final ActivityInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003309
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003310 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
3311 super(args, _info);
3312 info = _info;
3313 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003315
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003316 public void setPackageName(String packageName) {
3317 super.setPackageName(packageName);
3318 info.packageName = packageName;
3319 }
3320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003321 public String toString() {
3322 return "Activity{"
3323 + Integer.toHexString(System.identityHashCode(this))
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003324 + " " + getComponentShortName() + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003325 }
3326 }
3327
3328 public static final ActivityInfo generateActivityInfo(Activity a,
3329 int flags) {
3330 if (a == null) return null;
3331 if (!copyNeeded(flags, a.owner, a.metaData)) {
3332 return a.info;
3333 }
3334 // Make shallow copies so we can store the metadata safely
3335 ActivityInfo ai = new ActivityInfo(a.info);
3336 ai.metaData = a.metaData;
3337 ai.applicationInfo = generateApplicationInfo(a.owner, flags);
3338 return ai;
3339 }
3340
3341 public final static class Service extends Component<ServiceIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003342 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003343
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003344 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
3345 super(args, _info);
3346 info = _info;
3347 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003348 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003349
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003350 public void setPackageName(String packageName) {
3351 super.setPackageName(packageName);
3352 info.packageName = packageName;
3353 }
3354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003355 public String toString() {
3356 return "Service{"
3357 + Integer.toHexString(System.identityHashCode(this))
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003358 + " " + getComponentShortName() + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 }
3360 }
3361
3362 public static final ServiceInfo generateServiceInfo(Service s, int flags) {
3363 if (s == null) return null;
3364 if (!copyNeeded(flags, s.owner, s.metaData)) {
3365 return s.info;
3366 }
3367 // Make shallow copies so we can store the metadata safely
3368 ServiceInfo si = new ServiceInfo(s.info);
3369 si.metaData = s.metaData;
3370 si.applicationInfo = generateApplicationInfo(s.owner, flags);
3371 return si;
3372 }
3373
3374 public final static class Provider extends Component {
3375 public final ProviderInfo info;
3376 public boolean syncable;
3377
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003378 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
3379 super(args, _info);
3380 info = _info;
3381 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003382 syncable = false;
3383 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003385 public Provider(Provider existingProvider) {
3386 super(existingProvider);
3387 this.info = existingProvider.info;
3388 this.syncable = existingProvider.syncable;
3389 }
3390
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003391 public void setPackageName(String packageName) {
3392 super.setPackageName(packageName);
3393 info.packageName = packageName;
3394 }
3395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003396 public String toString() {
3397 return "Provider{"
3398 + Integer.toHexString(System.identityHashCode(this))
3399 + " " + info.name + "}";
3400 }
3401 }
3402
3403 public static final ProviderInfo generateProviderInfo(Provider p,
3404 int flags) {
3405 if (p == null) return null;
3406 if (!copyNeeded(flags, p.owner, p.metaData)
3407 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
3408 || p.info.uriPermissionPatterns == null)) {
3409 return p.info;
3410 }
3411 // Make shallow copies so we can store the metadata safely
3412 ProviderInfo pi = new ProviderInfo(p.info);
3413 pi.metaData = p.metaData;
3414 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
3415 pi.uriPermissionPatterns = null;
3416 }
3417 pi.applicationInfo = generateApplicationInfo(p.owner, flags);
3418 return pi;
3419 }
3420
3421 public final static class Instrumentation extends Component {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003422 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003423
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003424 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
3425 super(args, _info);
3426 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003428
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003429 public void setPackageName(String packageName) {
3430 super.setPackageName(packageName);
3431 info.packageName = packageName;
3432 }
3433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003434 public String toString() {
3435 return "Instrumentation{"
3436 + Integer.toHexString(System.identityHashCode(this))
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003437 + " " + getComponentShortName() + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003438 }
3439 }
3440
3441 public static final InstrumentationInfo generateInstrumentationInfo(
3442 Instrumentation i, int flags) {
3443 if (i == null) return null;
3444 if ((flags&PackageManager.GET_META_DATA) == 0) {
3445 return i.info;
3446 }
3447 InstrumentationInfo ii = new InstrumentationInfo(i.info);
3448 ii.metaData = i.metaData;
3449 return ii;
3450 }
3451
3452 public static class IntentInfo extends IntentFilter {
3453 public boolean hasDefault;
3454 public int labelRes;
3455 public CharSequence nonLocalizedLabel;
3456 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07003457 public int logo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003458 }
3459
3460 public final static class ActivityIntentInfo extends IntentInfo {
3461 public final Activity activity;
3462
3463 public ActivityIntentInfo(Activity _activity) {
3464 activity = _activity;
3465 }
3466
3467 public String toString() {
3468 return "ActivityIntentInfo{"
3469 + Integer.toHexString(System.identityHashCode(this))
3470 + " " + activity.info.name + "}";
3471 }
3472 }
3473
3474 public final static class ServiceIntentInfo extends IntentInfo {
3475 public final Service service;
3476
3477 public ServiceIntentInfo(Service _service) {
3478 service = _service;
3479 }
3480
3481 public String toString() {
3482 return "ServiceIntentInfo{"
3483 + Integer.toHexString(System.identityHashCode(this))
3484 + " " + service.info.name + "}";
3485 }
3486 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07003487
3488 /**
3489 * @hide
3490 */
3491 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
3492 sCompatibilityModeEnabled = compatibilityModeEnabled;
3493 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003494}