PackageParser.java revision d63f7dbf5d30320e8fd4dd8056d245f7b1e818ba
1/* 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 19import org.xmlpull.v1.XmlPullParser; 20import org.xmlpull.v1.XmlPullParserException; 21 22import android.content.ComponentName; 23import android.content.Intent; 24import android.content.IntentFilter; 25import android.content.res.AssetManager; 26import android.content.res.Configuration; 27import android.content.res.Resources; 28import android.content.res.TypedArray; 29import android.content.res.XmlResourceParser; 30import android.os.Build; 31import android.os.Bundle; 32import android.os.PatternMatcher; 33import android.provider.Settings; 34import android.util.AttributeSet; 35import android.util.Config; 36import android.util.DisplayMetrics; 37import android.util.Log; 38import android.util.TypedValue; 39 40import com.android.internal.util.XmlUtils; 41 42import java.io.BufferedInputStream; 43import java.io.File; 44import java.io.IOException; 45import java.io.InputStream; 46import java.lang.ref.WeakReference; 47import java.security.cert.Certificate; 48import java.security.cert.CertificateEncodingException; 49import java.util.ArrayList; 50import java.util.Enumeration; 51import java.util.Iterator; 52import java.util.List; 53import java.util.jar.JarEntry; 54import java.util.jar.JarFile; 55 56/** 57 * Package archive parsing 58 * 59 * {@hide} 60 */ 61public class PackageParser { 62 /** @hide */ 63 public static class NewPermissionInfo { 64 public final String name; 65 public final int sdkVersion; 66 public final int fileVersion; 67 68 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) { 69 this.name = name; 70 this.sdkVersion = sdkVersion; 71 this.fileVersion = fileVersion; 72 } 73 } 74 75 /** 76 * List of new permissions that have been added since 1.0. 77 * NOTE: These must be declared in SDK version order, with permissions 78 * added to older SDKs appearing before those added to newer SDKs. 79 * @hide 80 */ 81 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] = 82 new PackageParser.NewPermissionInfo[] { 83 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, 84 android.os.Build.VERSION_CODES.DONUT, 0), 85 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE, 86 android.os.Build.VERSION_CODES.DONUT, 0) 87 }; 88 89 private String mArchiveSourcePath; 90 private String[] mSeparateProcesses; 91 private static final int SDK_VERSION = Build.VERSION.SDK_INT; 92 private static final String SDK_CODENAME = "REL".equals(Build.VERSION.CODENAME) 93 ? null : Build.VERSION.CODENAME; 94 95 private int mParseError = PackageManager.INSTALL_SUCCEEDED; 96 97 private static final Object mSync = new Object(); 98 private static WeakReference<byte[]> mReadBuffer; 99 100 private static boolean sCompatibilityModeEnabled = true; 101 private static final int PARSE_DEFAULT_INSTALL_LOCATION = PackageInfo.INSTALL_LOCATION_UNSPECIFIED; 102 103 static class ParsePackageItemArgs { 104 final Package owner; 105 final String[] outError; 106 final int nameRes; 107 final int labelRes; 108 final int iconRes; 109 final int logoRes; 110 111 String tag; 112 TypedArray sa; 113 114 ParsePackageItemArgs(Package _owner, String[] _outError, 115 int _nameRes, int _labelRes, int _iconRes, int _logoRes) { 116 owner = _owner; 117 outError = _outError; 118 nameRes = _nameRes; 119 labelRes = _labelRes; 120 iconRes = _iconRes; 121 logoRes = _logoRes; 122 } 123 } 124 125 static class ParseComponentArgs extends ParsePackageItemArgs { 126 final String[] sepProcesses; 127 final int processRes; 128 final int descriptionRes; 129 final int enabledRes; 130 int flags; 131 132 ParseComponentArgs(Package _owner, String[] _outError, 133 int _nameRes, int _labelRes, int _iconRes, int _logoRes, 134 String[] _sepProcesses, int _processRes, 135 int _descriptionRes, int _enabledRes) { 136 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _logoRes); 137 sepProcesses = _sepProcesses; 138 processRes = _processRes; 139 descriptionRes = _descriptionRes; 140 enabledRes = _enabledRes; 141 } 142 } 143 144 /* Light weight package info. 145 * @hide 146 */ 147 public static class PackageLite { 148 public String packageName; 149 public int installLocation; 150 public String mScanPath; 151 public PackageLite(String packageName, int installLocation) { 152 this.packageName = packageName; 153 this.installLocation = installLocation; 154 } 155 } 156 157 private ParsePackageItemArgs mParseInstrumentationArgs; 158 private ParseComponentArgs mParseActivityArgs; 159 private ParseComponentArgs mParseActivityAliasArgs; 160 private ParseComponentArgs mParseServiceArgs; 161 private ParseComponentArgs mParseProviderArgs; 162 163 /** If set to true, we will only allow package files that exactly match 164 * the DTD. Otherwise, we try to get as much from the package as we 165 * can without failing. This should normally be set to false, to 166 * support extensions to the DTD in future versions. */ 167 private static final boolean RIGID_PARSER = false; 168 169 private static final String TAG = "PackageParser"; 170 171 public PackageParser(String archiveSourcePath) { 172 mArchiveSourcePath = archiveSourcePath; 173 } 174 175 public void setSeparateProcesses(String[] procs) { 176 mSeparateProcesses = procs; 177 } 178 179 private static final boolean isPackageFilename(String name) { 180 return name.endsWith(".apk"); 181 } 182 183 /** 184 * Generate and return the {@link PackageInfo} for a parsed package. 185 * 186 * @param p the parsed package. 187 * @param flags indicating which optional information is included. 188 */ 189 public static PackageInfo generatePackageInfo(PackageParser.Package p, 190 int gids[], int flags) { 191 192 PackageInfo pi = new PackageInfo(); 193 pi.packageName = p.packageName; 194 pi.versionCode = p.mVersionCode; 195 pi.versionName = p.mVersionName; 196 pi.sharedUserId = p.mSharedUserId; 197 pi.sharedUserLabel = p.mSharedUserLabel; 198 pi.applicationInfo = p.applicationInfo; 199 pi.installLocation = p.installLocation; 200 if ((flags&PackageManager.GET_GIDS) != 0) { 201 pi.gids = gids; 202 } 203 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) { 204 int N = p.configPreferences.size(); 205 if (N > 0) { 206 pi.configPreferences = new ConfigurationInfo[N]; 207 p.configPreferences.toArray(pi.configPreferences); 208 } 209 N = p.reqFeatures != null ? p.reqFeatures.size() : 0; 210 if (N > 0) { 211 pi.reqFeatures = new FeatureInfo[N]; 212 p.reqFeatures.toArray(pi.reqFeatures); 213 } 214 } 215 if ((flags&PackageManager.GET_ACTIVITIES) != 0) { 216 int N = p.activities.size(); 217 if (N > 0) { 218 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { 219 pi.activities = new ActivityInfo[N]; 220 } else { 221 int num = 0; 222 for (int i=0; i<N; i++) { 223 if (p.activities.get(i).info.enabled) num++; 224 } 225 pi.activities = new ActivityInfo[num]; 226 } 227 for (int i=0, j=0; i<N; i++) { 228 final Activity activity = p.activities.get(i); 229 if (activity.info.enabled 230 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { 231 pi.activities[j++] = generateActivityInfo(p.activities.get(i), flags); 232 } 233 } 234 } 235 } 236 if ((flags&PackageManager.GET_RECEIVERS) != 0) { 237 int N = p.receivers.size(); 238 if (N > 0) { 239 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { 240 pi.receivers = new ActivityInfo[N]; 241 } else { 242 int num = 0; 243 for (int i=0; i<N; i++) { 244 if (p.receivers.get(i).info.enabled) num++; 245 } 246 pi.receivers = new ActivityInfo[num]; 247 } 248 for (int i=0, j=0; i<N; i++) { 249 final Activity activity = p.receivers.get(i); 250 if (activity.info.enabled 251 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { 252 pi.receivers[j++] = generateActivityInfo(p.receivers.get(i), flags); 253 } 254 } 255 } 256 } 257 if ((flags&PackageManager.GET_SERVICES) != 0) { 258 int N = p.services.size(); 259 if (N > 0) { 260 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { 261 pi.services = new ServiceInfo[N]; 262 } else { 263 int num = 0; 264 for (int i=0; i<N; i++) { 265 if (p.services.get(i).info.enabled) num++; 266 } 267 pi.services = new ServiceInfo[num]; 268 } 269 for (int i=0, j=0; i<N; i++) { 270 final Service service = p.services.get(i); 271 if (service.info.enabled 272 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { 273 pi.services[j++] = generateServiceInfo(p.services.get(i), flags); 274 } 275 } 276 } 277 } 278 if ((flags&PackageManager.GET_PROVIDERS) != 0) { 279 int N = p.providers.size(); 280 if (N > 0) { 281 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { 282 pi.providers = new ProviderInfo[N]; 283 } else { 284 int num = 0; 285 for (int i=0; i<N; i++) { 286 if (p.providers.get(i).info.enabled) num++; 287 } 288 pi.providers = new ProviderInfo[num]; 289 } 290 for (int i=0, j=0; i<N; i++) { 291 final Provider provider = p.providers.get(i); 292 if (provider.info.enabled 293 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { 294 pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags); 295 } 296 } 297 } 298 } 299 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) { 300 int N = p.instrumentation.size(); 301 if (N > 0) { 302 pi.instrumentation = new InstrumentationInfo[N]; 303 for (int i=0; i<N; i++) { 304 pi.instrumentation[i] = generateInstrumentationInfo( 305 p.instrumentation.get(i), flags); 306 } 307 } 308 } 309 if ((flags&PackageManager.GET_PERMISSIONS) != 0) { 310 int N = p.permissions.size(); 311 if (N > 0) { 312 pi.permissions = new PermissionInfo[N]; 313 for (int i=0; i<N; i++) { 314 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags); 315 } 316 } 317 N = p.requestedPermissions.size(); 318 if (N > 0) { 319 pi.requestedPermissions = new String[N]; 320 for (int i=0; i<N; i++) { 321 pi.requestedPermissions[i] = p.requestedPermissions.get(i); 322 } 323 } 324 } 325 if ((flags&PackageManager.GET_SIGNATURES) != 0) { 326 int N = (p.mSignatures != null) ? p.mSignatures.length : 0; 327 if (N > 0) { 328 pi.signatures = new Signature[N]; 329 System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N); 330 } 331 } 332 return pi; 333 } 334 335 private Certificate[] loadCertificates(JarFile jarFile, JarEntry je, 336 byte[] readBuffer) { 337 try { 338 // We must read the stream for the JarEntry to retrieve 339 // its certificates. 340 InputStream is = new BufferedInputStream(jarFile.getInputStream(je)); 341 while (is.read(readBuffer, 0, readBuffer.length) != -1) { 342 // not using 343 } 344 is.close(); 345 return je != null ? je.getCertificates() : null; 346 } catch (IOException e) { 347 Log.w(TAG, "Exception reading " + je.getName() + " in " 348 + jarFile.getName(), e); 349 } catch (RuntimeException e) { 350 Log.w(TAG, "Exception reading " + je.getName() + " in " 351 + jarFile.getName(), e); 352 } 353 return null; 354 } 355 356 public final static int PARSE_IS_SYSTEM = 1<<0; 357 public final static int PARSE_CHATTY = 1<<1; 358 public final static int PARSE_MUST_BE_APK = 1<<2; 359 public final static int PARSE_IGNORE_PROCESSES = 1<<3; 360 public final static int PARSE_FORWARD_LOCK = 1<<4; 361 public final static int PARSE_ON_SDCARD = 1<<5; 362 public final static int PARSE_IS_SYSTEM_DIR = 1<<6; 363 364 public int getParseError() { 365 return mParseError; 366 } 367 368 public Package parsePackage(File sourceFile, String destCodePath, 369 DisplayMetrics metrics, int flags) { 370 mParseError = PackageManager.INSTALL_SUCCEEDED; 371 372 mArchiveSourcePath = sourceFile.getPath(); 373 if (!sourceFile.isFile()) { 374 Log.w(TAG, "Skipping dir: " + mArchiveSourcePath); 375 mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK; 376 return null; 377 } 378 if (!isPackageFilename(sourceFile.getName()) 379 && (flags&PARSE_MUST_BE_APK) != 0) { 380 if ((flags&PARSE_IS_SYSTEM) == 0) { 381 // We expect to have non-.apk files in the system dir, 382 // so don't warn about them. 383 Log.w(TAG, "Skipping non-package file: " + mArchiveSourcePath); 384 } 385 mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK; 386 return null; 387 } 388 389 if ((flags&PARSE_CHATTY) != 0 && Config.LOGD) Log.d( 390 TAG, "Scanning package: " + mArchiveSourcePath); 391 392 XmlResourceParser parser = null; 393 AssetManager assmgr = null; 394 boolean assetError = true; 395 try { 396 assmgr = new AssetManager(); 397 int cookie = assmgr.addAssetPath(mArchiveSourcePath); 398 if(cookie != 0) { 399 parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml"); 400 assetError = false; 401 } else { 402 Log.w(TAG, "Failed adding asset path:"+mArchiveSourcePath); 403 } 404 } catch (Exception e) { 405 Log.w(TAG, "Unable to read AndroidManifest.xml of " 406 + mArchiveSourcePath, e); 407 } 408 if(assetError) { 409 if (assmgr != null) assmgr.close(); 410 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST; 411 return null; 412 } 413 String[] errorText = new String[1]; 414 Package pkg = null; 415 Exception errorException = null; 416 try { 417 // XXXX todo: need to figure out correct configuration. 418 Resources res = new Resources(assmgr, metrics, null); 419 pkg = parsePackage(res, parser, flags, errorText); 420 } catch (Exception e) { 421 errorException = e; 422 mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; 423 } 424 425 426 if (pkg == null) { 427 if (errorException != null) { 428 Log.w(TAG, mArchiveSourcePath, errorException); 429 } else { 430 Log.w(TAG, mArchiveSourcePath + " (at " 431 + parser.getPositionDescription() 432 + "): " + errorText[0]); 433 } 434 parser.close(); 435 assmgr.close(); 436 if (mParseError == PackageManager.INSTALL_SUCCEEDED) { 437 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 438 } 439 return null; 440 } 441 442 parser.close(); 443 assmgr.close(); 444 445 // Set code and resource paths 446 pkg.mPath = destCodePath; 447 pkg.mScanPath = mArchiveSourcePath; 448 //pkg.applicationInfo.sourceDir = destCodePath; 449 //pkg.applicationInfo.publicSourceDir = destRes; 450 pkg.mSignatures = null; 451 452 return pkg; 453 } 454 455 public boolean collectCertificates(Package pkg, int flags) { 456 pkg.mSignatures = null; 457 458 WeakReference<byte[]> readBufferRef; 459 byte[] readBuffer = null; 460 synchronized (mSync) { 461 readBufferRef = mReadBuffer; 462 if (readBufferRef != null) { 463 mReadBuffer = null; 464 readBuffer = readBufferRef.get(); 465 } 466 if (readBuffer == null) { 467 readBuffer = new byte[8192]; 468 readBufferRef = new WeakReference<byte[]>(readBuffer); 469 } 470 } 471 472 try { 473 JarFile jarFile = new JarFile(mArchiveSourcePath); 474 475 Certificate[] certs = null; 476 477 if ((flags&PARSE_IS_SYSTEM) != 0) { 478 // If this package comes from the system image, then we 479 // can trust it... we'll just use the AndroidManifest.xml 480 // to retrieve its signatures, not validating all of the 481 // files. 482 JarEntry jarEntry = jarFile.getJarEntry("AndroidManifest.xml"); 483 certs = loadCertificates(jarFile, jarEntry, readBuffer); 484 if (certs == null) { 485 Log.e(TAG, "Package " + pkg.packageName 486 + " has no certificates at entry " 487 + jarEntry.getName() + "; ignoring!"); 488 jarFile.close(); 489 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; 490 return false; 491 } 492 if (false) { 493 Log.i(TAG, "File " + mArchiveSourcePath + ": entry=" + jarEntry 494 + " certs=" + (certs != null ? certs.length : 0)); 495 if (certs != null) { 496 final int N = certs.length; 497 for (int i=0; i<N; i++) { 498 Log.i(TAG, " Public key: " 499 + certs[i].getPublicKey().getEncoded() 500 + " " + certs[i].getPublicKey()); 501 } 502 } 503 } 504 505 } else { 506 Enumeration entries = jarFile.entries(); 507 while (entries.hasMoreElements()) { 508 JarEntry je = (JarEntry)entries.nextElement(); 509 if (je.isDirectory()) continue; 510 if (je.getName().startsWith("META-INF/")) continue; 511 Certificate[] localCerts = loadCertificates(jarFile, je, 512 readBuffer); 513 if (false) { 514 Log.i(TAG, "File " + mArchiveSourcePath + " entry " + je.getName() 515 + ": certs=" + certs + " (" 516 + (certs != null ? certs.length : 0) + ")"); 517 } 518 if (localCerts == null) { 519 Log.e(TAG, "Package " + pkg.packageName 520 + " has no certificates at entry " 521 + je.getName() + "; ignoring!"); 522 jarFile.close(); 523 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; 524 return false; 525 } else if (certs == null) { 526 certs = localCerts; 527 } else { 528 // Ensure all certificates match. 529 for (int i=0; i<certs.length; i++) { 530 boolean found = false; 531 for (int j=0; j<localCerts.length; j++) { 532 if (certs[i] != null && 533 certs[i].equals(localCerts[j])) { 534 found = true; 535 break; 536 } 537 } 538 if (!found || certs.length != localCerts.length) { 539 Log.e(TAG, "Package " + pkg.packageName 540 + " has mismatched certificates at entry " 541 + je.getName() + "; ignoring!"); 542 jarFile.close(); 543 mParseError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; 544 return false; 545 } 546 } 547 } 548 } 549 } 550 jarFile.close(); 551 552 synchronized (mSync) { 553 mReadBuffer = readBufferRef; 554 } 555 556 if (certs != null && certs.length > 0) { 557 final int N = certs.length; 558 pkg.mSignatures = new Signature[certs.length]; 559 for (int i=0; i<N; i++) { 560 pkg.mSignatures[i] = new Signature( 561 certs[i].getEncoded()); 562 } 563 } else { 564 Log.e(TAG, "Package " + pkg.packageName 565 + " has no certificates; ignoring!"); 566 mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; 567 return false; 568 } 569 } catch (CertificateEncodingException e) { 570 Log.w(TAG, "Exception reading " + mArchiveSourcePath, e); 571 mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; 572 return false; 573 } catch (IOException e) { 574 Log.w(TAG, "Exception reading " + mArchiveSourcePath, e); 575 mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; 576 return false; 577 } catch (RuntimeException e) { 578 Log.w(TAG, "Exception reading " + mArchiveSourcePath, e); 579 mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; 580 return false; 581 } 582 583 return true; 584 } 585 586 /* 587 * Utility method that retrieves just the package name and install 588 * location from the apk location at the given file path. 589 * @param packageFilePath file location of the apk 590 * @param flags Special parse flags 591 * @return PackageLite object with package information or null on failure. 592 */ 593 public static PackageLite parsePackageLite(String packageFilePath, int flags) { 594 XmlResourceParser parser = null; 595 AssetManager assmgr = null; 596 try { 597 assmgr = new AssetManager(); 598 int cookie = assmgr.addAssetPath(packageFilePath); 599 parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml"); 600 } catch (Exception e) { 601 if (assmgr != null) assmgr.close(); 602 Log.w(TAG, "Unable to read AndroidManifest.xml of " 603 + packageFilePath, e); 604 return null; 605 } 606 AttributeSet attrs = parser; 607 String errors[] = new String[1]; 608 PackageLite packageLite = null; 609 try { 610 packageLite = parsePackageLite(parser, attrs, flags, errors); 611 } catch (IOException e) { 612 Log.w(TAG, packageFilePath, e); 613 } catch (XmlPullParserException e) { 614 Log.w(TAG, packageFilePath, e); 615 } finally { 616 if (parser != null) parser.close(); 617 if (assmgr != null) assmgr.close(); 618 } 619 if (packageLite == null) { 620 Log.e(TAG, "parsePackageLite error: " + errors[0]); 621 return null; 622 } 623 return packageLite; 624 } 625 626 private static String validateName(String name, boolean requiresSeparator) { 627 final int N = name.length(); 628 boolean hasSep = false; 629 boolean front = true; 630 for (int i=0; i<N; i++) { 631 final char c = name.charAt(i); 632 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { 633 front = false; 634 continue; 635 } 636 if (!front) { 637 if ((c >= '0' && c <= '9') || c == '_') { 638 continue; 639 } 640 } 641 if (c == '.') { 642 hasSep = true; 643 front = true; 644 continue; 645 } 646 return "bad character '" + c + "'"; 647 } 648 return hasSep || !requiresSeparator 649 ? null : "must have at least one '.' separator"; 650 } 651 652 private static String parsePackageName(XmlPullParser parser, 653 AttributeSet attrs, int flags, String[] outError) 654 throws IOException, XmlPullParserException { 655 656 int type; 657 while ((type=parser.next()) != parser.START_TAG 658 && type != parser.END_DOCUMENT) { 659 ; 660 } 661 662 if (type != parser.START_TAG) { 663 outError[0] = "No start tag found"; 664 return null; 665 } 666 if ((flags&PARSE_CHATTY) != 0 && Config.LOGV) Log.v( 667 TAG, "Root element name: '" + parser.getName() + "'"); 668 if (!parser.getName().equals("manifest")) { 669 outError[0] = "No <manifest> tag"; 670 return null; 671 } 672 String pkgName = attrs.getAttributeValue(null, "package"); 673 if (pkgName == null || pkgName.length() == 0) { 674 outError[0] = "<manifest> does not specify package"; 675 return null; 676 } 677 String nameError = validateName(pkgName, true); 678 if (nameError != null && !"android".equals(pkgName)) { 679 outError[0] = "<manifest> specifies bad package name \"" 680 + pkgName + "\": " + nameError; 681 return null; 682 } 683 684 return pkgName.intern(); 685 } 686 687 private static PackageLite parsePackageLite(XmlPullParser parser, 688 AttributeSet attrs, int flags, String[] outError) 689 throws IOException, XmlPullParserException { 690 691 int type; 692 while ((type=parser.next()) != parser.START_TAG 693 && type != parser.END_DOCUMENT) { 694 ; 695 } 696 697 if (type != parser.START_TAG) { 698 outError[0] = "No start tag found"; 699 return null; 700 } 701 if ((flags&PARSE_CHATTY) != 0 && Config.LOGV) Log.v( 702 TAG, "Root element name: '" + parser.getName() + "'"); 703 if (!parser.getName().equals("manifest")) { 704 outError[0] = "No <manifest> tag"; 705 return null; 706 } 707 String pkgName = attrs.getAttributeValue(null, "package"); 708 if (pkgName == null || pkgName.length() == 0) { 709 outError[0] = "<manifest> does not specify package"; 710 return null; 711 } 712 String nameError = validateName(pkgName, true); 713 if (nameError != null && !"android".equals(pkgName)) { 714 outError[0] = "<manifest> specifies bad package name \"" 715 + pkgName + "\": " + nameError; 716 return null; 717 } 718 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION; 719 for (int i = 0; i < attrs.getAttributeCount(); i++) { 720 String attr = attrs.getAttributeName(i); 721 if (attr.equals("installLocation")) { 722 installLocation = attrs.getAttributeIntValue(i, 723 PARSE_DEFAULT_INSTALL_LOCATION); 724 break; 725 } 726 } 727 return new PackageLite(pkgName.intern(), installLocation); 728 } 729 730 /** 731 * Temporary. 732 */ 733 static public Signature stringToSignature(String str) { 734 final int N = str.length(); 735 byte[] sig = new byte[N]; 736 for (int i=0; i<N; i++) { 737 sig[i] = (byte)str.charAt(i); 738 } 739 return new Signature(sig); 740 } 741 742 private Package parsePackage( 743 Resources res, XmlResourceParser parser, int flags, String[] outError) 744 throws XmlPullParserException, IOException { 745 AttributeSet attrs = parser; 746 747 mParseInstrumentationArgs = null; 748 mParseActivityArgs = null; 749 mParseServiceArgs = null; 750 mParseProviderArgs = null; 751 752 String pkgName = parsePackageName(parser, attrs, flags, outError); 753 if (pkgName == null) { 754 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; 755 return null; 756 } 757 int type; 758 759 final Package pkg = new Package(pkgName); 760 boolean foundApp = false; 761 762 TypedArray sa = res.obtainAttributes(attrs, 763 com.android.internal.R.styleable.AndroidManifest); 764 pkg.mVersionCode = sa.getInteger( 765 com.android.internal.R.styleable.AndroidManifest_versionCode, 0); 766 pkg.mVersionName = sa.getNonConfigurationString( 767 com.android.internal.R.styleable.AndroidManifest_versionName, 0); 768 if (pkg.mVersionName != null) { 769 pkg.mVersionName = pkg.mVersionName.intern(); 770 } 771 String str = sa.getNonConfigurationString( 772 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0); 773 if (str != null && str.length() > 0) { 774 String nameError = validateName(str, true); 775 if (nameError != null && !"android".equals(pkgName)) { 776 outError[0] = "<manifest> specifies bad sharedUserId name \"" 777 + str + "\": " + nameError; 778 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID; 779 return null; 780 } 781 pkg.mSharedUserId = str.intern(); 782 pkg.mSharedUserLabel = sa.getResourceId( 783 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0); 784 } 785 sa.recycle(); 786 787 pkg.installLocation = sa.getInteger( 788 com.android.internal.R.styleable.AndroidManifest_installLocation, 789 PARSE_DEFAULT_INSTALL_LOCATION); 790 791 // Resource boolean are -1, so 1 means we don't know the value. 792 int supportsSmallScreens = 1; 793 int supportsNormalScreens = 1; 794 int supportsLargeScreens = 1; 795 int supportsXLargeScreens = 1; 796 int resizeable = 1; 797 int anyDensity = 1; 798 799 int outerDepth = parser.getDepth(); 800 while ((type=parser.next()) != parser.END_DOCUMENT 801 && (type != parser.END_TAG || parser.getDepth() > outerDepth)) { 802 if (type == parser.END_TAG || type == parser.TEXT) { 803 continue; 804 } 805 806 String tagName = parser.getName(); 807 if (tagName.equals("application")) { 808 if (foundApp) { 809 if (RIGID_PARSER) { 810 outError[0] = "<manifest> has more than one <application>"; 811 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 812 return null; 813 } else { 814 Log.w(TAG, "<manifest> has more than one <application>"); 815 XmlUtils.skipCurrentTag(parser); 816 continue; 817 } 818 } 819 820 foundApp = true; 821 if (!parseApplication(pkg, res, parser, attrs, flags, outError)) { 822 return null; 823 } 824 } else if (tagName.equals("permission-group")) { 825 if (parsePermissionGroup(pkg, res, parser, attrs, outError) == null) { 826 return null; 827 } 828 } else if (tagName.equals("permission")) { 829 if (parsePermission(pkg, res, parser, attrs, outError) == null) { 830 return null; 831 } 832 } else if (tagName.equals("permission-tree")) { 833 if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) { 834 return null; 835 } 836 } else if (tagName.equals("uses-permission")) { 837 sa = res.obtainAttributes(attrs, 838 com.android.internal.R.styleable.AndroidManifestUsesPermission); 839 840 // Note: don't allow this value to be a reference to a resource 841 // that may change. 842 String name = sa.getNonResourceString( 843 com.android.internal.R.styleable.AndroidManifestUsesPermission_name); 844 845 sa.recycle(); 846 847 if (name != null && !pkg.requestedPermissions.contains(name)) { 848 pkg.requestedPermissions.add(name.intern()); 849 } 850 851 XmlUtils.skipCurrentTag(parser); 852 853 } else if (tagName.equals("uses-configuration")) { 854 ConfigurationInfo cPref = new ConfigurationInfo(); 855 sa = res.obtainAttributes(attrs, 856 com.android.internal.R.styleable.AndroidManifestUsesConfiguration); 857 cPref.reqTouchScreen = sa.getInt( 858 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen, 859 Configuration.TOUCHSCREEN_UNDEFINED); 860 cPref.reqKeyboardType = sa.getInt( 861 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType, 862 Configuration.KEYBOARD_UNDEFINED); 863 if (sa.getBoolean( 864 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard, 865 false)) { 866 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD; 867 } 868 cPref.reqNavigation = sa.getInt( 869 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation, 870 Configuration.NAVIGATION_UNDEFINED); 871 if (sa.getBoolean( 872 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav, 873 false)) { 874 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV; 875 } 876 sa.recycle(); 877 pkg.configPreferences.add(cPref); 878 879 XmlUtils.skipCurrentTag(parser); 880 881 } else if (tagName.equals("uses-feature")) { 882 FeatureInfo fi = new FeatureInfo(); 883 sa = res.obtainAttributes(attrs, 884 com.android.internal.R.styleable.AndroidManifestUsesFeature); 885 // Note: don't allow this value to be a reference to a resource 886 // that may change. 887 fi.name = sa.getNonResourceString( 888 com.android.internal.R.styleable.AndroidManifestUsesFeature_name); 889 if (fi.name == null) { 890 fi.reqGlEsVersion = sa.getInt( 891 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion, 892 FeatureInfo.GL_ES_VERSION_UNDEFINED); 893 } 894 if (sa.getBoolean( 895 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, 896 true)) { 897 fi.flags |= FeatureInfo.FLAG_REQUIRED; 898 } 899 sa.recycle(); 900 if (pkg.reqFeatures == null) { 901 pkg.reqFeatures = new ArrayList<FeatureInfo>(); 902 } 903 pkg.reqFeatures.add(fi); 904 905 if (fi.name == null) { 906 ConfigurationInfo cPref = new ConfigurationInfo(); 907 cPref.reqGlEsVersion = fi.reqGlEsVersion; 908 pkg.configPreferences.add(cPref); 909 } 910 911 XmlUtils.skipCurrentTag(parser); 912 913 } else if (tagName.equals("uses-sdk")) { 914 if (SDK_VERSION > 0) { 915 sa = res.obtainAttributes(attrs, 916 com.android.internal.R.styleable.AndroidManifestUsesSdk); 917 918 int minVers = 0; 919 String minCode = null; 920 int targetVers = 0; 921 String targetCode = null; 922 923 TypedValue val = sa.peekValue( 924 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion); 925 if (val != null) { 926 if (val.type == TypedValue.TYPE_STRING && val.string != null) { 927 targetCode = minCode = val.string.toString(); 928 } else { 929 // If it's not a string, it's an integer. 930 targetVers = minVers = val.data; 931 } 932 } 933 934 val = sa.peekValue( 935 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion); 936 if (val != null) { 937 if (val.type == TypedValue.TYPE_STRING && val.string != null) { 938 targetCode = minCode = val.string.toString(); 939 } else { 940 // If it's not a string, it's an integer. 941 targetVers = val.data; 942 } 943 } 944 945 sa.recycle(); 946 947 if (minCode != null) { 948 if (!minCode.equals(SDK_CODENAME)) { 949 if (SDK_CODENAME != null) { 950 outError[0] = "Requires development platform " + minCode 951 + " (current platform is " + SDK_CODENAME + ")"; 952 } else { 953 outError[0] = "Requires development platform " + minCode 954 + " but this is a release platform."; 955 } 956 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; 957 return null; 958 } 959 } else if (minVers > SDK_VERSION) { 960 outError[0] = "Requires newer sdk version #" + minVers 961 + " (current version is #" + SDK_VERSION + ")"; 962 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; 963 return null; 964 } 965 966 if (targetCode != null) { 967 if (!targetCode.equals(SDK_CODENAME)) { 968 if (SDK_CODENAME != null) { 969 outError[0] = "Requires development platform " + targetCode 970 + " (current platform is " + SDK_CODENAME + ")"; 971 } else { 972 outError[0] = "Requires development platform " + targetCode 973 + " but this is a release platform."; 974 } 975 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; 976 return null; 977 } 978 // If the code matches, it definitely targets this SDK. 979 pkg.applicationInfo.targetSdkVersion 980 = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT; 981 } else { 982 pkg.applicationInfo.targetSdkVersion = targetVers; 983 } 984 } 985 986 XmlUtils.skipCurrentTag(parser); 987 988 } else if (tagName.equals("supports-screens")) { 989 sa = res.obtainAttributes(attrs, 990 com.android.internal.R.styleable.AndroidManifestSupportsScreens); 991 992 // This is a trick to get a boolean and still able to detect 993 // if a value was actually set. 994 supportsSmallScreens = sa.getInteger( 995 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens, 996 supportsSmallScreens); 997 supportsNormalScreens = sa.getInteger( 998 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens, 999 supportsNormalScreens); 1000 supportsLargeScreens = sa.getInteger( 1001 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens, 1002 supportsLargeScreens); 1003 supportsXLargeScreens = sa.getInteger( 1004 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens, 1005 supportsXLargeScreens); 1006 resizeable = sa.getInteger( 1007 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable, 1008 resizeable); 1009 anyDensity = sa.getInteger( 1010 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity, 1011 anyDensity); 1012 1013 sa.recycle(); 1014 1015 XmlUtils.skipCurrentTag(parser); 1016 1017 } else if (tagName.equals("protected-broadcast")) { 1018 sa = res.obtainAttributes(attrs, 1019 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast); 1020 1021 // Note: don't allow this value to be a reference to a resource 1022 // that may change. 1023 String name = sa.getNonResourceString( 1024 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name); 1025 1026 sa.recycle(); 1027 1028 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) { 1029 if (pkg.protectedBroadcasts == null) { 1030 pkg.protectedBroadcasts = new ArrayList<String>(); 1031 } 1032 if (!pkg.protectedBroadcasts.contains(name)) { 1033 pkg.protectedBroadcasts.add(name.intern()); 1034 } 1035 } 1036 1037 XmlUtils.skipCurrentTag(parser); 1038 1039 } else if (tagName.equals("instrumentation")) { 1040 if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) { 1041 return null; 1042 } 1043 1044 } else if (tagName.equals("original-package")) { 1045 sa = res.obtainAttributes(attrs, 1046 com.android.internal.R.styleable.AndroidManifestOriginalPackage); 1047 1048 String orig =sa.getNonConfigurationString( 1049 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0); 1050 if (!pkg.packageName.equals(orig)) { 1051 if (pkg.mOriginalPackages == null) { 1052 pkg.mOriginalPackages = new ArrayList<String>(); 1053 pkg.mRealPackage = pkg.packageName; 1054 } 1055 pkg.mOriginalPackages.add(orig); 1056 } 1057 1058 sa.recycle(); 1059 1060 XmlUtils.skipCurrentTag(parser); 1061 1062 } else if (tagName.equals("adopt-permissions")) { 1063 sa = res.obtainAttributes(attrs, 1064 com.android.internal.R.styleable.AndroidManifestOriginalPackage); 1065 1066 String name = sa.getNonConfigurationString( 1067 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0); 1068 1069 sa.recycle(); 1070 1071 if (name != null) { 1072 if (pkg.mAdoptPermissions == null) { 1073 pkg.mAdoptPermissions = new ArrayList<String>(); 1074 } 1075 pkg.mAdoptPermissions.add(name); 1076 } 1077 1078 XmlUtils.skipCurrentTag(parser); 1079 1080 } else if (tagName.equals("eat-comment")) { 1081 // Just skip this tag 1082 XmlUtils.skipCurrentTag(parser); 1083 continue; 1084 1085 } else if (RIGID_PARSER) { 1086 outError[0] = "Bad element under <manifest>: " 1087 + parser.getName(); 1088 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1089 return null; 1090 1091 } else { 1092 Log.w(TAG, "Unknown element under <manifest>: " + parser.getName() 1093 + " at " + mArchiveSourcePath + " " 1094 + parser.getPositionDescription()); 1095 XmlUtils.skipCurrentTag(parser); 1096 continue; 1097 } 1098 } 1099 1100 if (!foundApp && pkg.instrumentation.size() == 0) { 1101 outError[0] = "<manifest> does not contain an <application> or <instrumentation>"; 1102 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY; 1103 } 1104 1105 final int NP = PackageParser.NEW_PERMISSIONS.length; 1106 StringBuilder implicitPerms = null; 1107 for (int ip=0; ip<NP; ip++) { 1108 final PackageParser.NewPermissionInfo npi 1109 = PackageParser.NEW_PERMISSIONS[ip]; 1110 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) { 1111 break; 1112 } 1113 if (!pkg.requestedPermissions.contains(npi.name)) { 1114 if (implicitPerms == null) { 1115 implicitPerms = new StringBuilder(128); 1116 implicitPerms.append(pkg.packageName); 1117 implicitPerms.append(": compat added "); 1118 } else { 1119 implicitPerms.append(' '); 1120 } 1121 implicitPerms.append(npi.name); 1122 pkg.requestedPermissions.add(npi.name); 1123 } 1124 } 1125 if (implicitPerms != null) { 1126 Log.i(TAG, implicitPerms.toString()); 1127 } 1128 1129 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0 1130 && pkg.applicationInfo.targetSdkVersion 1131 >= android.os.Build.VERSION_CODES.DONUT)) { 1132 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS; 1133 } 1134 if (supportsNormalScreens != 0) { 1135 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS; 1136 } 1137 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0 1138 && pkg.applicationInfo.targetSdkVersion 1139 >= android.os.Build.VERSION_CODES.DONUT)) { 1140 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS; 1141 } 1142 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0 1143 && pkg.applicationInfo.targetSdkVersion 1144 >= android.os.Build.VERSION_CODES.GINGERBREAD)) { 1145 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS; 1146 } 1147 if (resizeable < 0 || (resizeable > 0 1148 && pkg.applicationInfo.targetSdkVersion 1149 >= android.os.Build.VERSION_CODES.DONUT)) { 1150 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS; 1151 } 1152 if (anyDensity < 0 || (anyDensity > 0 1153 && pkg.applicationInfo.targetSdkVersion 1154 >= android.os.Build.VERSION_CODES.DONUT)) { 1155 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES; 1156 } 1157 1158 return pkg; 1159 } 1160 1161 private static String buildClassName(String pkg, CharSequence clsSeq, 1162 String[] outError) { 1163 if (clsSeq == null || clsSeq.length() <= 0) { 1164 outError[0] = "Empty class name in package " + pkg; 1165 return null; 1166 } 1167 String cls = clsSeq.toString(); 1168 char c = cls.charAt(0); 1169 if (c == '.') { 1170 return (pkg + cls).intern(); 1171 } 1172 if (cls.indexOf('.') < 0) { 1173 StringBuilder b = new StringBuilder(pkg); 1174 b.append('.'); 1175 b.append(cls); 1176 return b.toString().intern(); 1177 } 1178 if (c >= 'a' && c <= 'z') { 1179 return cls.intern(); 1180 } 1181 outError[0] = "Bad class name " + cls + " in package " + pkg; 1182 return null; 1183 } 1184 1185 private static String buildCompoundName(String pkg, 1186 CharSequence procSeq, String type, String[] outError) { 1187 String proc = procSeq.toString(); 1188 char c = proc.charAt(0); 1189 if (pkg != null && c == ':') { 1190 if (proc.length() < 2) { 1191 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg 1192 + ": must be at least two characters"; 1193 return null; 1194 } 1195 String subName = proc.substring(1); 1196 String nameError = validateName(subName, false); 1197 if (nameError != null) { 1198 outError[0] = "Invalid " + type + " name " + proc + " in package " 1199 + pkg + ": " + nameError; 1200 return null; 1201 } 1202 return (pkg + proc).intern(); 1203 } 1204 String nameError = validateName(proc, true); 1205 if (nameError != null && !"system".equals(proc)) { 1206 outError[0] = "Invalid " + type + " name " + proc + " in package " 1207 + pkg + ": " + nameError; 1208 return null; 1209 } 1210 return proc.intern(); 1211 } 1212 1213 private static String buildProcessName(String pkg, String defProc, 1214 CharSequence procSeq, int flags, String[] separateProcesses, 1215 String[] outError) { 1216 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) { 1217 return defProc != null ? defProc : pkg; 1218 } 1219 if (separateProcesses != null) { 1220 for (int i=separateProcesses.length-1; i>=0; i--) { 1221 String sp = separateProcesses[i]; 1222 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) { 1223 return pkg; 1224 } 1225 } 1226 } 1227 if (procSeq == null || procSeq.length() <= 0) { 1228 return defProc; 1229 } 1230 return buildCompoundName(pkg, procSeq, "process", outError); 1231 } 1232 1233 private static String buildTaskAffinityName(String pkg, String defProc, 1234 CharSequence procSeq, String[] outError) { 1235 if (procSeq == null) { 1236 return defProc; 1237 } 1238 if (procSeq.length() <= 0) { 1239 return null; 1240 } 1241 return buildCompoundName(pkg, procSeq, "taskAffinity", outError); 1242 } 1243 1244 private PermissionGroup parsePermissionGroup(Package owner, Resources res, 1245 XmlPullParser parser, AttributeSet attrs, String[] outError) 1246 throws XmlPullParserException, IOException { 1247 PermissionGroup perm = new PermissionGroup(owner); 1248 1249 TypedArray sa = res.obtainAttributes(attrs, 1250 com.android.internal.R.styleable.AndroidManifestPermissionGroup); 1251 1252 if (!parsePackageItemInfo(owner, perm.info, outError, 1253 "<permission-group>", sa, 1254 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name, 1255 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label, 1256 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon, 0)) { 1257 sa.recycle(); 1258 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1259 return null; 1260 } 1261 1262 perm.info.descriptionRes = sa.getResourceId( 1263 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description, 1264 0); 1265 1266 sa.recycle(); 1267 1268 if (!parseAllMetaData(res, parser, attrs, "<permission-group>", perm, 1269 outError)) { 1270 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1271 return null; 1272 } 1273 1274 owner.permissionGroups.add(perm); 1275 1276 return perm; 1277 } 1278 1279 private Permission parsePermission(Package owner, Resources res, 1280 XmlPullParser parser, AttributeSet attrs, String[] outError) 1281 throws XmlPullParserException, IOException { 1282 Permission perm = new Permission(owner); 1283 1284 TypedArray sa = res.obtainAttributes(attrs, 1285 com.android.internal.R.styleable.AndroidManifestPermission); 1286 1287 if (!parsePackageItemInfo(owner, perm.info, outError, 1288 "<permission>", sa, 1289 com.android.internal.R.styleable.AndroidManifestPermission_name, 1290 com.android.internal.R.styleable.AndroidManifestPermission_label, 1291 com.android.internal.R.styleable.AndroidManifestPermission_icon, 0)) { 1292 sa.recycle(); 1293 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1294 return null; 1295 } 1296 1297 // Note: don't allow this value to be a reference to a resource 1298 // that may change. 1299 perm.info.group = sa.getNonResourceString( 1300 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup); 1301 if (perm.info.group != null) { 1302 perm.info.group = perm.info.group.intern(); 1303 } 1304 1305 perm.info.descriptionRes = sa.getResourceId( 1306 com.android.internal.R.styleable.AndroidManifestPermission_description, 1307 0); 1308 1309 perm.info.protectionLevel = sa.getInt( 1310 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel, 1311 PermissionInfo.PROTECTION_NORMAL); 1312 1313 sa.recycle(); 1314 1315 if (perm.info.protectionLevel == -1) { 1316 outError[0] = "<permission> does not specify protectionLevel"; 1317 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1318 return null; 1319 } 1320 1321 if (!parseAllMetaData(res, parser, attrs, "<permission>", perm, 1322 outError)) { 1323 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1324 return null; 1325 } 1326 1327 owner.permissions.add(perm); 1328 1329 return perm; 1330 } 1331 1332 private Permission parsePermissionTree(Package owner, Resources res, 1333 XmlPullParser parser, AttributeSet attrs, String[] outError) 1334 throws XmlPullParserException, IOException { 1335 Permission perm = new Permission(owner); 1336 1337 TypedArray sa = res.obtainAttributes(attrs, 1338 com.android.internal.R.styleable.AndroidManifestPermissionTree); 1339 1340 if (!parsePackageItemInfo(owner, perm.info, outError, 1341 "<permission-tree>", sa, 1342 com.android.internal.R.styleable.AndroidManifestPermissionTree_name, 1343 com.android.internal.R.styleable.AndroidManifestPermissionTree_label, 1344 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon, 0)) { 1345 sa.recycle(); 1346 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1347 return null; 1348 } 1349 1350 sa.recycle(); 1351 1352 int index = perm.info.name.indexOf('.'); 1353 if (index > 0) { 1354 index = perm.info.name.indexOf('.', index+1); 1355 } 1356 if (index < 0) { 1357 outError[0] = "<permission-tree> name has less than three segments: " 1358 + perm.info.name; 1359 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1360 return null; 1361 } 1362 1363 perm.info.descriptionRes = 0; 1364 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL; 1365 perm.tree = true; 1366 1367 if (!parseAllMetaData(res, parser, attrs, "<permission-tree>", perm, 1368 outError)) { 1369 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1370 return null; 1371 } 1372 1373 owner.permissions.add(perm); 1374 1375 return perm; 1376 } 1377 1378 private Instrumentation parseInstrumentation(Package owner, Resources res, 1379 XmlPullParser parser, AttributeSet attrs, String[] outError) 1380 throws XmlPullParserException, IOException { 1381 TypedArray sa = res.obtainAttributes(attrs, 1382 com.android.internal.R.styleable.AndroidManifestInstrumentation); 1383 1384 if (mParseInstrumentationArgs == null) { 1385 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError, 1386 com.android.internal.R.styleable.AndroidManifestInstrumentation_name, 1387 com.android.internal.R.styleable.AndroidManifestInstrumentation_label, 1388 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon, 0); 1389 mParseInstrumentationArgs.tag = "<instrumentation>"; 1390 } 1391 1392 mParseInstrumentationArgs.sa = sa; 1393 1394 Instrumentation a = new Instrumentation(mParseInstrumentationArgs, 1395 new InstrumentationInfo()); 1396 if (outError[0] != null) { 1397 sa.recycle(); 1398 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1399 return null; 1400 } 1401 1402 String str; 1403 // Note: don't allow this value to be a reference to a resource 1404 // that may change. 1405 str = sa.getNonResourceString( 1406 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage); 1407 a.info.targetPackage = str != null ? str.intern() : null; 1408 1409 a.info.handleProfiling = sa.getBoolean( 1410 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling, 1411 false); 1412 1413 a.info.functionalTest = sa.getBoolean( 1414 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest, 1415 false); 1416 1417 sa.recycle(); 1418 1419 if (a.info.targetPackage == null) { 1420 outError[0] = "<instrumentation> does not specify targetPackage"; 1421 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1422 return null; 1423 } 1424 1425 if (!parseAllMetaData(res, parser, attrs, "<instrumentation>", a, 1426 outError)) { 1427 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1428 return null; 1429 } 1430 1431 owner.instrumentation.add(a); 1432 1433 return a; 1434 } 1435 1436 private boolean parseApplication(Package owner, Resources res, 1437 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError) 1438 throws XmlPullParserException, IOException { 1439 final ApplicationInfo ai = owner.applicationInfo; 1440 final String pkgName = owner.applicationInfo.packageName; 1441 1442 TypedArray sa = res.obtainAttributes(attrs, 1443 com.android.internal.R.styleable.AndroidManifestApplication); 1444 1445 String name = sa.getNonConfigurationString( 1446 com.android.internal.R.styleable.AndroidManifestApplication_name, 0); 1447 if (name != null) { 1448 ai.className = buildClassName(pkgName, name, outError); 1449 if (ai.className == null) { 1450 sa.recycle(); 1451 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1452 return false; 1453 } 1454 } 1455 1456 String manageSpaceActivity = sa.getNonConfigurationString( 1457 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity, 0); 1458 if (manageSpaceActivity != null) { 1459 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity, 1460 outError); 1461 } 1462 1463 boolean allowBackup = sa.getBoolean( 1464 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true); 1465 if (allowBackup) { 1466 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP; 1467 1468 // backupAgent, killAfterRestore, and restoreAnyVersion are only relevant 1469 // if backup is possible for the given application. 1470 String backupAgent = sa.getNonConfigurationString( 1471 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent, 0); 1472 if (backupAgent != null) { 1473 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError); 1474 if (false) { 1475 Log.v(TAG, "android:backupAgent = " + ai.backupAgentName 1476 + " from " + pkgName + "+" + backupAgent); 1477 } 1478 1479 if (sa.getBoolean( 1480 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore, 1481 true)) { 1482 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE; 1483 } 1484 if (sa.getBoolean( 1485 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion, 1486 false)) { 1487 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION; 1488 } 1489 } 1490 } 1491 1492 TypedValue v = sa.peekValue( 1493 com.android.internal.R.styleable.AndroidManifestApplication_label); 1494 if (v != null && (ai.labelRes=v.resourceId) == 0) { 1495 ai.nonLocalizedLabel = v.coerceToString(); 1496 } 1497 1498 ai.icon = sa.getResourceId( 1499 com.android.internal.R.styleable.AndroidManifestApplication_icon, 0); 1500 ai.theme = sa.getResourceId( 1501 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0); 1502 ai.descriptionRes = sa.getResourceId( 1503 com.android.internal.R.styleable.AndroidManifestApplication_description, 0); 1504 1505 if ((flags&PARSE_IS_SYSTEM) != 0) { 1506 if (sa.getBoolean( 1507 com.android.internal.R.styleable.AndroidManifestApplication_persistent, 1508 false)) { 1509 ai.flags |= ApplicationInfo.FLAG_PERSISTENT; 1510 } 1511 } 1512 1513 if ((flags & PARSE_FORWARD_LOCK) != 0) { 1514 ai.flags |= ApplicationInfo.FLAG_FORWARD_LOCK; 1515 } 1516 1517 if ((flags & PARSE_ON_SDCARD) != 0) { 1518 ai.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE; 1519 } 1520 1521 if (sa.getBoolean( 1522 com.android.internal.R.styleable.AndroidManifestApplication_debuggable, 1523 false)) { 1524 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE; 1525 } 1526 1527 if (sa.getBoolean( 1528 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode, 1529 false)) { 1530 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE; 1531 } 1532 1533 if (sa.getBoolean( 1534 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, 1535 true)) { 1536 ai.flags |= ApplicationInfo.FLAG_HAS_CODE; 1537 } 1538 1539 if (sa.getBoolean( 1540 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting, 1541 false)) { 1542 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING; 1543 } 1544 1545 if (sa.getBoolean( 1546 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData, 1547 true)) { 1548 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA; 1549 } 1550 1551 if (sa.getBoolean( 1552 com.android.internal.R.styleable.AndroidManifestApplication_testOnly, 1553 false)) { 1554 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY; 1555 } 1556 1557 if (sa.getBoolean( 1558 com.android.internal.R.styleable.AndroidManifestApplication_neverEncrypt, 1559 false)) { 1560 ai.flags |= ApplicationInfo.FLAG_NEVER_ENCRYPT; 1561 } 1562 1563 String str; 1564 str = sa.getNonConfigurationString( 1565 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0); 1566 ai.permission = (str != null && str.length() > 0) ? str.intern() : null; 1567 1568 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) { 1569 str = sa.getNonConfigurationString( 1570 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity, 0); 1571 } else { 1572 // Some older apps have been seen to use a resource reference 1573 // here that on older builds was ignored (with a warning). We 1574 // need to continue to do this for them so they don't break. 1575 str = sa.getNonResourceString( 1576 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity); 1577 } 1578 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName, 1579 str, outError); 1580 1581 if (outError[0] == null) { 1582 CharSequence pname; 1583 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) { 1584 pname = sa.getNonConfigurationString( 1585 com.android.internal.R.styleable.AndroidManifestApplication_process, 0); 1586 } else { 1587 // Some older apps have been seen to use a resource reference 1588 // here that on older builds was ignored (with a warning). We 1589 // need to continue to do this for them so they don't break. 1590 pname = sa.getNonResourceString( 1591 com.android.internal.R.styleable.AndroidManifestApplication_process); 1592 } 1593 ai.processName = buildProcessName(ai.packageName, null, pname, 1594 flags, mSeparateProcesses, outError); 1595 1596 ai.enabled = sa.getBoolean( 1597 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true); 1598 1599 if (false) { 1600 if (sa.getBoolean( 1601 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState, 1602 false)) { 1603 ai.flags |= ApplicationInfo.CANT_SAVE_STATE; 1604 1605 // A heavy-weight application can not be in a custom process. 1606 // We can do direct compare because we intern all strings. 1607 if (ai.processName != null && ai.processName != ai.packageName) { 1608 outError[0] = "cantSaveState applications can not use custom processes"; 1609 } 1610 } 1611 } 1612 } 1613 1614 sa.recycle(); 1615 1616 if (outError[0] != null) { 1617 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1618 return false; 1619 } 1620 1621 final int innerDepth = parser.getDepth(); 1622 1623 int type; 1624 while ((type=parser.next()) != parser.END_DOCUMENT 1625 && (type != parser.END_TAG || parser.getDepth() > innerDepth)) { 1626 if (type == parser.END_TAG || type == parser.TEXT) { 1627 continue; 1628 } 1629 1630 String tagName = parser.getName(); 1631 if (tagName.equals("activity")) { 1632 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false); 1633 if (a == null) { 1634 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1635 return false; 1636 } 1637 1638 owner.activities.add(a); 1639 1640 } else if (tagName.equals("receiver")) { 1641 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true); 1642 if (a == null) { 1643 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1644 return false; 1645 } 1646 1647 owner.receivers.add(a); 1648 1649 } else if (tagName.equals("service")) { 1650 Service s = parseService(owner, res, parser, attrs, flags, outError); 1651 if (s == null) { 1652 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1653 return false; 1654 } 1655 1656 owner.services.add(s); 1657 1658 } else if (tagName.equals("provider")) { 1659 Provider p = parseProvider(owner, res, parser, attrs, flags, outError); 1660 if (p == null) { 1661 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1662 return false; 1663 } 1664 1665 owner.providers.add(p); 1666 1667 } else if (tagName.equals("activity-alias")) { 1668 Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError); 1669 if (a == null) { 1670 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1671 return false; 1672 } 1673 1674 owner.activities.add(a); 1675 1676 } else if (parser.getName().equals("meta-data")) { 1677 // note: application meta-data is stored off to the side, so it can 1678 // remain null in the primary copy (we like to avoid extra copies because 1679 // it can be large) 1680 if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData, 1681 outError)) == null) { 1682 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1683 return false; 1684 } 1685 1686 } else if (tagName.equals("uses-library")) { 1687 sa = res.obtainAttributes(attrs, 1688 com.android.internal.R.styleable.AndroidManifestUsesLibrary); 1689 1690 // Note: don't allow this value to be a reference to a resource 1691 // that may change. 1692 String lname = sa.getNonResourceString( 1693 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name); 1694 boolean req = sa.getBoolean( 1695 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required, 1696 true); 1697 1698 sa.recycle(); 1699 1700 if (lname != null) { 1701 if (req) { 1702 if (owner.usesLibraries == null) { 1703 owner.usesLibraries = new ArrayList<String>(); 1704 } 1705 if (!owner.usesLibraries.contains(lname)) { 1706 owner.usesLibraries.add(lname.intern()); 1707 } 1708 } else { 1709 if (owner.usesOptionalLibraries == null) { 1710 owner.usesOptionalLibraries = new ArrayList<String>(); 1711 } 1712 if (!owner.usesOptionalLibraries.contains(lname)) { 1713 owner.usesOptionalLibraries.add(lname.intern()); 1714 } 1715 } 1716 } 1717 1718 XmlUtils.skipCurrentTag(parser); 1719 1720 } else { 1721 if (!RIGID_PARSER) { 1722 Log.w(TAG, "Unknown element under <application>: " + tagName 1723 + " at " + mArchiveSourcePath + " " 1724 + parser.getPositionDescription()); 1725 XmlUtils.skipCurrentTag(parser); 1726 continue; 1727 } else { 1728 outError[0] = "Bad element under <application>: " + tagName; 1729 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 1730 return false; 1731 } 1732 } 1733 } 1734 1735 return true; 1736 } 1737 1738 private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo, 1739 String[] outError, String tag, TypedArray sa, 1740 int nameRes, int labelRes, int iconRes, int logoRes) { 1741 String name = sa.getNonConfigurationString(nameRes, 0); 1742 if (name == null) { 1743 outError[0] = tag + " does not specify android:name"; 1744 return false; 1745 } 1746 1747 outInfo.name 1748 = buildClassName(owner.applicationInfo.packageName, name, outError); 1749 if (outInfo.name == null) { 1750 return false; 1751 } 1752 1753 int iconVal = sa.getResourceId(iconRes, 0); 1754 if (iconVal != 0) { 1755 outInfo.icon = iconVal; 1756 outInfo.nonLocalizedLabel = null; 1757 } 1758 1759 TypedValue v = sa.peekValue(labelRes); 1760 if (v != null && (outInfo.labelRes=v.resourceId) == 0) { 1761 outInfo.nonLocalizedLabel = v.coerceToString(); 1762 } 1763 1764 outInfo.packageName = owner.packageName; 1765 1766 return true; 1767 } 1768 1769 private Activity parseActivity(Package owner, Resources res, 1770 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError, 1771 boolean receiver) throws XmlPullParserException, IOException { 1772 TypedArray sa = res.obtainAttributes(attrs, 1773 com.android.internal.R.styleable.AndroidManifestActivity); 1774 1775 if (mParseActivityArgs == null) { 1776 mParseActivityArgs = new ParseComponentArgs(owner, outError, 1777 com.android.internal.R.styleable.AndroidManifestActivity_name, 1778 com.android.internal.R.styleable.AndroidManifestActivity_label, 1779 com.android.internal.R.styleable.AndroidManifestActivity_icon, 0, 1780 mSeparateProcesses, 1781 com.android.internal.R.styleable.AndroidManifestActivity_process, 1782 com.android.internal.R.styleable.AndroidManifestActivity_description, 1783 com.android.internal.R.styleable.AndroidManifestActivity_enabled); 1784 } 1785 1786 mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>"; 1787 mParseActivityArgs.sa = sa; 1788 mParseActivityArgs.flags = flags; 1789 1790 Activity a = new Activity(mParseActivityArgs, new ActivityInfo()); 1791 if (outError[0] != null) { 1792 sa.recycle(); 1793 return null; 1794 } 1795 1796 final boolean setExported = sa.hasValue( 1797 com.android.internal.R.styleable.AndroidManifestActivity_exported); 1798 if (setExported) { 1799 a.info.exported = sa.getBoolean( 1800 com.android.internal.R.styleable.AndroidManifestActivity_exported, false); 1801 } 1802 1803 a.info.theme = sa.getResourceId( 1804 com.android.internal.R.styleable.AndroidManifestActivity_theme, 0); 1805 1806 String str; 1807 str = sa.getNonConfigurationString( 1808 com.android.internal.R.styleable.AndroidManifestActivity_permission, 0); 1809 if (str == null) { 1810 a.info.permission = owner.applicationInfo.permission; 1811 } else { 1812 a.info.permission = str.length() > 0 ? str.toString().intern() : null; 1813 } 1814 1815 str = sa.getNonConfigurationString( 1816 com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity, 0); 1817 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName, 1818 owner.applicationInfo.taskAffinity, str, outError); 1819 1820 a.info.flags = 0; 1821 if (sa.getBoolean( 1822 com.android.internal.R.styleable.AndroidManifestActivity_multiprocess, 1823 false)) { 1824 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS; 1825 } 1826 1827 if (sa.getBoolean( 1828 com.android.internal.R.styleable.AndroidManifestActivity_finishOnTaskLaunch, 1829 false)) { 1830 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH; 1831 } 1832 1833 if (sa.getBoolean( 1834 com.android.internal.R.styleable.AndroidManifestActivity_clearTaskOnLaunch, 1835 false)) { 1836 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH; 1837 } 1838 1839 if (sa.getBoolean( 1840 com.android.internal.R.styleable.AndroidManifestActivity_noHistory, 1841 false)) { 1842 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY; 1843 } 1844 1845 if (sa.getBoolean( 1846 com.android.internal.R.styleable.AndroidManifestActivity_alwaysRetainTaskState, 1847 false)) { 1848 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE; 1849 } 1850 1851 if (sa.getBoolean( 1852 com.android.internal.R.styleable.AndroidManifestActivity_stateNotNeeded, 1853 false)) { 1854 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED; 1855 } 1856 1857 if (sa.getBoolean( 1858 com.android.internal.R.styleable.AndroidManifestActivity_excludeFromRecents, 1859 false)) { 1860 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; 1861 } 1862 1863 if (sa.getBoolean( 1864 com.android.internal.R.styleable.AndroidManifestActivity_allowTaskReparenting, 1865 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) { 1866 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING; 1867 } 1868 1869 if (sa.getBoolean( 1870 com.android.internal.R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, 1871 false)) { 1872 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS; 1873 } 1874 1875 if (!receiver) { 1876 a.info.launchMode = sa.getInt( 1877 com.android.internal.R.styleable.AndroidManifestActivity_launchMode, 1878 ActivityInfo.LAUNCH_MULTIPLE); 1879 a.info.screenOrientation = sa.getInt( 1880 com.android.internal.R.styleable.AndroidManifestActivity_screenOrientation, 1881 ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 1882 a.info.configChanges = sa.getInt( 1883 com.android.internal.R.styleable.AndroidManifestActivity_configChanges, 1884 0); 1885 a.info.softInputMode = sa.getInt( 1886 com.android.internal.R.styleable.AndroidManifestActivity_windowSoftInputMode, 1887 0); 1888 } else { 1889 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE; 1890 a.info.configChanges = 0; 1891 } 1892 1893 sa.recycle(); 1894 1895 if (receiver && (owner.applicationInfo.flags&ApplicationInfo.CANT_SAVE_STATE) != 0) { 1896 // A heavy-weight application can not have receives in its main process 1897 // We can do direct compare because we intern all strings. 1898 if (a.info.processName == owner.packageName) { 1899 outError[0] = "Heavy-weight applications can not have receivers in main process"; 1900 } 1901 } 1902 1903 if (outError[0] != null) { 1904 return null; 1905 } 1906 1907 int outerDepth = parser.getDepth(); 1908 int type; 1909 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 1910 && (type != XmlPullParser.END_TAG 1911 || parser.getDepth() > outerDepth)) { 1912 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 1913 continue; 1914 } 1915 1916 if (parser.getName().equals("intent-filter")) { 1917 ActivityIntentInfo intent = new ActivityIntentInfo(a); 1918 if (!parseIntent(res, parser, attrs, flags, intent, outError, !receiver)) { 1919 return null; 1920 } 1921 if (intent.countActions() == 0) { 1922 Log.w(TAG, "No actions in intent filter at " 1923 + mArchiveSourcePath + " " 1924 + parser.getPositionDescription()); 1925 } else { 1926 a.intents.add(intent); 1927 } 1928 } else if (parser.getName().equals("meta-data")) { 1929 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData, 1930 outError)) == null) { 1931 return null; 1932 } 1933 } else { 1934 if (!RIGID_PARSER) { 1935 Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); 1936 if (receiver) { 1937 Log.w(TAG, "Unknown element under <receiver>: " + parser.getName() 1938 + " at " + mArchiveSourcePath + " " 1939 + parser.getPositionDescription()); 1940 } else { 1941 Log.w(TAG, "Unknown element under <activity>: " + parser.getName() 1942 + " at " + mArchiveSourcePath + " " 1943 + parser.getPositionDescription()); 1944 } 1945 XmlUtils.skipCurrentTag(parser); 1946 continue; 1947 } 1948 if (receiver) { 1949 outError[0] = "Bad element under <receiver>: " + parser.getName(); 1950 } else { 1951 outError[0] = "Bad element under <activity>: " + parser.getName(); 1952 } 1953 return null; 1954 } 1955 } 1956 1957 if (!setExported) { 1958 a.info.exported = a.intents.size() > 0; 1959 } 1960 1961 return a; 1962 } 1963 1964 private Activity parseActivityAlias(Package owner, Resources res, 1965 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError) 1966 throws XmlPullParserException, IOException { 1967 TypedArray sa = res.obtainAttributes(attrs, 1968 com.android.internal.R.styleable.AndroidManifestActivityAlias); 1969 1970 String targetActivity = sa.getNonConfigurationString( 1971 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity, 0); 1972 if (targetActivity == null) { 1973 outError[0] = "<activity-alias> does not specify android:targetActivity"; 1974 sa.recycle(); 1975 return null; 1976 } 1977 1978 targetActivity = buildClassName(owner.applicationInfo.packageName, 1979 targetActivity, outError); 1980 if (targetActivity == null) { 1981 sa.recycle(); 1982 return null; 1983 } 1984 1985 if (mParseActivityAliasArgs == null) { 1986 mParseActivityAliasArgs = new ParseComponentArgs(owner, outError, 1987 com.android.internal.R.styleable.AndroidManifestActivityAlias_name, 1988 com.android.internal.R.styleable.AndroidManifestActivityAlias_label, 1989 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon, 0, 1990 mSeparateProcesses, 1991 0, 1992 com.android.internal.R.styleable.AndroidManifestActivityAlias_description, 1993 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled); 1994 mParseActivityAliasArgs.tag = "<activity-alias>"; 1995 } 1996 1997 mParseActivityAliasArgs.sa = sa; 1998 mParseActivityAliasArgs.flags = flags; 1999 2000 Activity target = null; 2001 2002 final int NA = owner.activities.size(); 2003 for (int i=0; i<NA; i++) { 2004 Activity t = owner.activities.get(i); 2005 if (targetActivity.equals(t.info.name)) { 2006 target = t; 2007 break; 2008 } 2009 } 2010 2011 if (target == null) { 2012 outError[0] = "<activity-alias> target activity " + targetActivity 2013 + " not found in manifest"; 2014 sa.recycle(); 2015 return null; 2016 } 2017 2018 ActivityInfo info = new ActivityInfo(); 2019 info.targetActivity = targetActivity; 2020 info.configChanges = target.info.configChanges; 2021 info.flags = target.info.flags; 2022 info.icon = target.info.icon; 2023 info.logo = target.info.logo; 2024 info.labelRes = target.info.labelRes; 2025 info.nonLocalizedLabel = target.info.nonLocalizedLabel; 2026 info.launchMode = target.info.launchMode; 2027 info.processName = target.info.processName; 2028 if (info.descriptionRes == 0) { 2029 info.descriptionRes = target.info.descriptionRes; 2030 } 2031 info.screenOrientation = target.info.screenOrientation; 2032 info.taskAffinity = target.info.taskAffinity; 2033 info.theme = target.info.theme; 2034 2035 Activity a = new Activity(mParseActivityAliasArgs, info); 2036 if (outError[0] != null) { 2037 sa.recycle(); 2038 return null; 2039 } 2040 2041 final boolean setExported = sa.hasValue( 2042 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported); 2043 if (setExported) { 2044 a.info.exported = sa.getBoolean( 2045 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false); 2046 } 2047 2048 String str; 2049 str = sa.getNonConfigurationString( 2050 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0); 2051 if (str != null) { 2052 a.info.permission = str.length() > 0 ? str.toString().intern() : null; 2053 } 2054 2055 sa.recycle(); 2056 2057 if (outError[0] != null) { 2058 return null; 2059 } 2060 2061 int outerDepth = parser.getDepth(); 2062 int type; 2063 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 2064 && (type != XmlPullParser.END_TAG 2065 || parser.getDepth() > outerDepth)) { 2066 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2067 continue; 2068 } 2069 2070 if (parser.getName().equals("intent-filter")) { 2071 ActivityIntentInfo intent = new ActivityIntentInfo(a); 2072 if (!parseIntent(res, parser, attrs, flags, intent, outError, true)) { 2073 return null; 2074 } 2075 if (intent.countActions() == 0) { 2076 Log.w(TAG, "No actions in intent filter at " 2077 + mArchiveSourcePath + " " 2078 + parser.getPositionDescription()); 2079 } else { 2080 a.intents.add(intent); 2081 } 2082 } else if (parser.getName().equals("meta-data")) { 2083 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData, 2084 outError)) == null) { 2085 return null; 2086 } 2087 } else { 2088 if (!RIGID_PARSER) { 2089 Log.w(TAG, "Unknown element under <activity-alias>: " + parser.getName() 2090 + " at " + mArchiveSourcePath + " " 2091 + parser.getPositionDescription()); 2092 XmlUtils.skipCurrentTag(parser); 2093 continue; 2094 } 2095 outError[0] = "Bad element under <activity-alias>: " + parser.getName(); 2096 return null; 2097 } 2098 } 2099 2100 if (!setExported) { 2101 a.info.exported = a.intents.size() > 0; 2102 } 2103 2104 return a; 2105 } 2106 2107 private Provider parseProvider(Package owner, Resources res, 2108 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError) 2109 throws XmlPullParserException, IOException { 2110 TypedArray sa = res.obtainAttributes(attrs, 2111 com.android.internal.R.styleable.AndroidManifestProvider); 2112 2113 if (mParseProviderArgs == null) { 2114 mParseProviderArgs = new ParseComponentArgs(owner, outError, 2115 com.android.internal.R.styleable.AndroidManifestProvider_name, 2116 com.android.internal.R.styleable.AndroidManifestProvider_label, 2117 com.android.internal.R.styleable.AndroidManifestProvider_icon, 0, 2118 mSeparateProcesses, 2119 com.android.internal.R.styleable.AndroidManifestProvider_process, 2120 com.android.internal.R.styleable.AndroidManifestProvider_description, 2121 com.android.internal.R.styleable.AndroidManifestProvider_enabled); 2122 mParseProviderArgs.tag = "<provider>"; 2123 } 2124 2125 mParseProviderArgs.sa = sa; 2126 mParseProviderArgs.flags = flags; 2127 2128 Provider p = new Provider(mParseProviderArgs, new ProviderInfo()); 2129 if (outError[0] != null) { 2130 sa.recycle(); 2131 return null; 2132 } 2133 2134 p.info.exported = sa.getBoolean( 2135 com.android.internal.R.styleable.AndroidManifestProvider_exported, true); 2136 2137 String cpname = sa.getNonConfigurationString( 2138 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0); 2139 2140 p.info.isSyncable = sa.getBoolean( 2141 com.android.internal.R.styleable.AndroidManifestProvider_syncable, 2142 false); 2143 2144 String permission = sa.getNonConfigurationString( 2145 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0); 2146 String str = sa.getNonConfigurationString( 2147 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0); 2148 if (str == null) { 2149 str = permission; 2150 } 2151 if (str == null) { 2152 p.info.readPermission = owner.applicationInfo.permission; 2153 } else { 2154 p.info.readPermission = 2155 str.length() > 0 ? str.toString().intern() : null; 2156 } 2157 str = sa.getNonConfigurationString( 2158 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0); 2159 if (str == null) { 2160 str = permission; 2161 } 2162 if (str == null) { 2163 p.info.writePermission = owner.applicationInfo.permission; 2164 } else { 2165 p.info.writePermission = 2166 str.length() > 0 ? str.toString().intern() : null; 2167 } 2168 2169 p.info.grantUriPermissions = sa.getBoolean( 2170 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions, 2171 false); 2172 2173 p.info.multiprocess = sa.getBoolean( 2174 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess, 2175 false); 2176 2177 p.info.initOrder = sa.getInt( 2178 com.android.internal.R.styleable.AndroidManifestProvider_initOrder, 2179 0); 2180 2181 sa.recycle(); 2182 2183 if ((owner.applicationInfo.flags&ApplicationInfo.CANT_SAVE_STATE) != 0) { 2184 // A heavy-weight application can not have providers in its main process 2185 // We can do direct compare because we intern all strings. 2186 if (p.info.processName == owner.packageName) { 2187 outError[0] = "Heavy-weight applications can not have providers in main process"; 2188 return null; 2189 } 2190 } 2191 2192 if (cpname == null) { 2193 outError[0] = "<provider> does not incude authorities attribute"; 2194 return null; 2195 } 2196 p.info.authority = cpname.intern(); 2197 2198 if (!parseProviderTags(res, parser, attrs, p, outError)) { 2199 return null; 2200 } 2201 2202 return p; 2203 } 2204 2205 private boolean parseProviderTags(Resources res, 2206 XmlPullParser parser, AttributeSet attrs, 2207 Provider outInfo, String[] outError) 2208 throws XmlPullParserException, IOException { 2209 int outerDepth = parser.getDepth(); 2210 int type; 2211 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 2212 && (type != XmlPullParser.END_TAG 2213 || parser.getDepth() > outerDepth)) { 2214 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2215 continue; 2216 } 2217 2218 if (parser.getName().equals("meta-data")) { 2219 if ((outInfo.metaData=parseMetaData(res, parser, attrs, 2220 outInfo.metaData, outError)) == null) { 2221 return false; 2222 } 2223 2224 } else if (parser.getName().equals("grant-uri-permission")) { 2225 TypedArray sa = res.obtainAttributes(attrs, 2226 com.android.internal.R.styleable.AndroidManifestGrantUriPermission); 2227 2228 PatternMatcher pa = null; 2229 2230 String str = sa.getNonConfigurationString( 2231 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0); 2232 if (str != null) { 2233 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL); 2234 } 2235 2236 str = sa.getNonConfigurationString( 2237 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0); 2238 if (str != null) { 2239 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX); 2240 } 2241 2242 str = sa.getNonConfigurationString( 2243 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0); 2244 if (str != null) { 2245 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB); 2246 } 2247 2248 sa.recycle(); 2249 2250 if (pa != null) { 2251 if (outInfo.info.uriPermissionPatterns == null) { 2252 outInfo.info.uriPermissionPatterns = new PatternMatcher[1]; 2253 outInfo.info.uriPermissionPatterns[0] = pa; 2254 } else { 2255 final int N = outInfo.info.uriPermissionPatterns.length; 2256 PatternMatcher[] newp = new PatternMatcher[N+1]; 2257 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N); 2258 newp[N] = pa; 2259 outInfo.info.uriPermissionPatterns = newp; 2260 } 2261 outInfo.info.grantUriPermissions = true; 2262 } else { 2263 if (!RIGID_PARSER) { 2264 Log.w(TAG, "Unknown element under <path-permission>: " 2265 + parser.getName() + " at " + mArchiveSourcePath + " " 2266 + parser.getPositionDescription()); 2267 XmlUtils.skipCurrentTag(parser); 2268 continue; 2269 } 2270 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>"; 2271 return false; 2272 } 2273 XmlUtils.skipCurrentTag(parser); 2274 2275 } else if (parser.getName().equals("path-permission")) { 2276 TypedArray sa = res.obtainAttributes(attrs, 2277 com.android.internal.R.styleable.AndroidManifestPathPermission); 2278 2279 PathPermission pa = null; 2280 2281 String permission = sa.getNonConfigurationString( 2282 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0); 2283 String readPermission = sa.getNonConfigurationString( 2284 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0); 2285 if (readPermission == null) { 2286 readPermission = permission; 2287 } 2288 String writePermission = sa.getNonConfigurationString( 2289 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0); 2290 if (writePermission == null) { 2291 writePermission = permission; 2292 } 2293 2294 boolean havePerm = false; 2295 if (readPermission != null) { 2296 readPermission = readPermission.intern(); 2297 havePerm = true; 2298 } 2299 if (writePermission != null) { 2300 writePermission = writePermission.intern(); 2301 havePerm = true; 2302 } 2303 2304 if (!havePerm) { 2305 if (!RIGID_PARSER) { 2306 Log.w(TAG, "No readPermission or writePermssion for <path-permission>: " 2307 + parser.getName() + " at " + mArchiveSourcePath + " " 2308 + parser.getPositionDescription()); 2309 XmlUtils.skipCurrentTag(parser); 2310 continue; 2311 } 2312 outError[0] = "No readPermission or writePermssion for <path-permission>"; 2313 return false; 2314 } 2315 2316 String path = sa.getNonConfigurationString( 2317 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0); 2318 if (path != null) { 2319 pa = new PathPermission(path, 2320 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission); 2321 } 2322 2323 path = sa.getNonConfigurationString( 2324 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0); 2325 if (path != null) { 2326 pa = new PathPermission(path, 2327 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission); 2328 } 2329 2330 path = sa.getNonConfigurationString( 2331 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0); 2332 if (path != null) { 2333 pa = new PathPermission(path, 2334 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission); 2335 } 2336 2337 sa.recycle(); 2338 2339 if (pa != null) { 2340 if (outInfo.info.pathPermissions == null) { 2341 outInfo.info.pathPermissions = new PathPermission[1]; 2342 outInfo.info.pathPermissions[0] = pa; 2343 } else { 2344 final int N = outInfo.info.pathPermissions.length; 2345 PathPermission[] newp = new PathPermission[N+1]; 2346 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N); 2347 newp[N] = pa; 2348 outInfo.info.pathPermissions = newp; 2349 } 2350 } else { 2351 if (!RIGID_PARSER) { 2352 Log.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: " 2353 + parser.getName() + " at " + mArchiveSourcePath + " " 2354 + parser.getPositionDescription()); 2355 XmlUtils.skipCurrentTag(parser); 2356 continue; 2357 } 2358 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>"; 2359 return false; 2360 } 2361 XmlUtils.skipCurrentTag(parser); 2362 2363 } else { 2364 if (!RIGID_PARSER) { 2365 Log.w(TAG, "Unknown element under <provider>: " 2366 + parser.getName() + " at " + mArchiveSourcePath + " " 2367 + parser.getPositionDescription()); 2368 XmlUtils.skipCurrentTag(parser); 2369 continue; 2370 } 2371 outError[0] = "Bad element under <provider>: " 2372 + parser.getName(); 2373 return false; 2374 } 2375 } 2376 return true; 2377 } 2378 2379 private Service parseService(Package owner, Resources res, 2380 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError) 2381 throws XmlPullParserException, IOException { 2382 TypedArray sa = res.obtainAttributes(attrs, 2383 com.android.internal.R.styleable.AndroidManifestService); 2384 2385 if (mParseServiceArgs == null) { 2386 mParseServiceArgs = new ParseComponentArgs(owner, outError, 2387 com.android.internal.R.styleable.AndroidManifestService_name, 2388 com.android.internal.R.styleable.AndroidManifestService_label, 2389 com.android.internal.R.styleable.AndroidManifestService_icon, 0, 2390 mSeparateProcesses, 2391 com.android.internal.R.styleable.AndroidManifestService_process, 2392 com.android.internal.R.styleable.AndroidManifestService_description, 2393 com.android.internal.R.styleable.AndroidManifestService_enabled); 2394 mParseServiceArgs.tag = "<service>"; 2395 } 2396 2397 mParseServiceArgs.sa = sa; 2398 mParseServiceArgs.flags = flags; 2399 2400 Service s = new Service(mParseServiceArgs, new ServiceInfo()); 2401 if (outError[0] != null) { 2402 sa.recycle(); 2403 return null; 2404 } 2405 2406 final boolean setExported = sa.hasValue( 2407 com.android.internal.R.styleable.AndroidManifestService_exported); 2408 if (setExported) { 2409 s.info.exported = sa.getBoolean( 2410 com.android.internal.R.styleable.AndroidManifestService_exported, false); 2411 } 2412 2413 String str = sa.getNonConfigurationString( 2414 com.android.internal.R.styleable.AndroidManifestService_permission, 0); 2415 if (str == null) { 2416 s.info.permission = owner.applicationInfo.permission; 2417 } else { 2418 s.info.permission = str.length() > 0 ? str.toString().intern() : null; 2419 } 2420 2421 sa.recycle(); 2422 2423 if ((owner.applicationInfo.flags&ApplicationInfo.CANT_SAVE_STATE) != 0) { 2424 // A heavy-weight application can not have services in its main process 2425 // We can do direct compare because we intern all strings. 2426 if (s.info.processName == owner.packageName) { 2427 outError[0] = "Heavy-weight applications can not have services in main process"; 2428 return null; 2429 } 2430 } 2431 2432 int outerDepth = parser.getDepth(); 2433 int type; 2434 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 2435 && (type != XmlPullParser.END_TAG 2436 || parser.getDepth() > outerDepth)) { 2437 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2438 continue; 2439 } 2440 2441 if (parser.getName().equals("intent-filter")) { 2442 ServiceIntentInfo intent = new ServiceIntentInfo(s); 2443 if (!parseIntent(res, parser, attrs, flags, intent, outError, false)) { 2444 return null; 2445 } 2446 2447 s.intents.add(intent); 2448 } else if (parser.getName().equals("meta-data")) { 2449 if ((s.metaData=parseMetaData(res, parser, attrs, s.metaData, 2450 outError)) == null) { 2451 return null; 2452 } 2453 } else { 2454 if (!RIGID_PARSER) { 2455 Log.w(TAG, "Unknown element under <service>: " 2456 + parser.getName() + " at " + mArchiveSourcePath + " " 2457 + parser.getPositionDescription()); 2458 XmlUtils.skipCurrentTag(parser); 2459 continue; 2460 } 2461 outError[0] = "Bad element under <service>: " 2462 + parser.getName(); 2463 return null; 2464 } 2465 } 2466 2467 if (!setExported) { 2468 s.info.exported = s.intents.size() > 0; 2469 } 2470 2471 return s; 2472 } 2473 2474 private boolean parseAllMetaData(Resources res, 2475 XmlPullParser parser, AttributeSet attrs, String tag, 2476 Component outInfo, String[] outError) 2477 throws XmlPullParserException, IOException { 2478 int outerDepth = parser.getDepth(); 2479 int type; 2480 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 2481 && (type != XmlPullParser.END_TAG 2482 || parser.getDepth() > outerDepth)) { 2483 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2484 continue; 2485 } 2486 2487 if (parser.getName().equals("meta-data")) { 2488 if ((outInfo.metaData=parseMetaData(res, parser, attrs, 2489 outInfo.metaData, outError)) == null) { 2490 return false; 2491 } 2492 } else { 2493 if (!RIGID_PARSER) { 2494 Log.w(TAG, "Unknown element under " + tag + ": " 2495 + parser.getName() + " at " + mArchiveSourcePath + " " 2496 + parser.getPositionDescription()); 2497 XmlUtils.skipCurrentTag(parser); 2498 continue; 2499 } 2500 outError[0] = "Bad element under " + tag + ": " 2501 + parser.getName(); 2502 return false; 2503 } 2504 } 2505 return true; 2506 } 2507 2508 private Bundle parseMetaData(Resources res, 2509 XmlPullParser parser, AttributeSet attrs, 2510 Bundle data, String[] outError) 2511 throws XmlPullParserException, IOException { 2512 2513 TypedArray sa = res.obtainAttributes(attrs, 2514 com.android.internal.R.styleable.AndroidManifestMetaData); 2515 2516 if (data == null) { 2517 data = new Bundle(); 2518 } 2519 2520 String name = sa.getNonConfigurationString( 2521 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0); 2522 if (name == null) { 2523 outError[0] = "<meta-data> requires an android:name attribute"; 2524 sa.recycle(); 2525 return null; 2526 } 2527 2528 name = name.intern(); 2529 2530 TypedValue v = sa.peekValue( 2531 com.android.internal.R.styleable.AndroidManifestMetaData_resource); 2532 if (v != null && v.resourceId != 0) { 2533 //Log.i(TAG, "Meta data ref " + name + ": " + v); 2534 data.putInt(name, v.resourceId); 2535 } else { 2536 v = sa.peekValue( 2537 com.android.internal.R.styleable.AndroidManifestMetaData_value); 2538 //Log.i(TAG, "Meta data " + name + ": " + v); 2539 if (v != null) { 2540 if (v.type == TypedValue.TYPE_STRING) { 2541 CharSequence cs = v.coerceToString(); 2542 data.putString(name, cs != null ? cs.toString().intern() : null); 2543 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) { 2544 data.putBoolean(name, v.data != 0); 2545 } else if (v.type >= TypedValue.TYPE_FIRST_INT 2546 && v.type <= TypedValue.TYPE_LAST_INT) { 2547 data.putInt(name, v.data); 2548 } else if (v.type == TypedValue.TYPE_FLOAT) { 2549 data.putFloat(name, v.getFloat()); 2550 } else { 2551 if (!RIGID_PARSER) { 2552 Log.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: " 2553 + parser.getName() + " at " + mArchiveSourcePath + " " 2554 + parser.getPositionDescription()); 2555 } else { 2556 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types"; 2557 data = null; 2558 } 2559 } 2560 } else { 2561 outError[0] = "<meta-data> requires an android:value or android:resource attribute"; 2562 data = null; 2563 } 2564 } 2565 2566 sa.recycle(); 2567 2568 XmlUtils.skipCurrentTag(parser); 2569 2570 return data; 2571 } 2572 2573 private static final String ANDROID_RESOURCES 2574 = "http://schemas.android.com/apk/res/android"; 2575 2576 private boolean parseIntent(Resources res, 2577 XmlPullParser parser, AttributeSet attrs, int flags, 2578 IntentInfo outInfo, String[] outError, boolean isActivity) 2579 throws XmlPullParserException, IOException { 2580 2581 TypedArray sa = res.obtainAttributes(attrs, 2582 com.android.internal.R.styleable.AndroidManifestIntentFilter); 2583 2584 int priority = sa.getInt( 2585 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0); 2586 if (priority > 0 && isActivity && (flags&PARSE_IS_SYSTEM) == 0) { 2587 Log.w(TAG, "Activity with priority > 0, forcing to 0 at " 2588 + mArchiveSourcePath + " " 2589 + parser.getPositionDescription()); 2590 priority = 0; 2591 } 2592 outInfo.setPriority(priority); 2593 2594 TypedValue v = sa.peekValue( 2595 com.android.internal.R.styleable.AndroidManifestIntentFilter_label); 2596 if (v != null && (outInfo.labelRes=v.resourceId) == 0) { 2597 outInfo.nonLocalizedLabel = v.coerceToString(); 2598 } 2599 2600 outInfo.icon = sa.getResourceId( 2601 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0); 2602 2603 sa.recycle(); 2604 2605 int outerDepth = parser.getDepth(); 2606 int type; 2607 while ((type=parser.next()) != parser.END_DOCUMENT 2608 && (type != parser.END_TAG || parser.getDepth() > outerDepth)) { 2609 if (type == parser.END_TAG || type == parser.TEXT) { 2610 continue; 2611 } 2612 2613 String nodeName = parser.getName(); 2614 if (nodeName.equals("action")) { 2615 String value = attrs.getAttributeValue( 2616 ANDROID_RESOURCES, "name"); 2617 if (value == null || value == "") { 2618 outError[0] = "No value supplied for <android:name>"; 2619 return false; 2620 } 2621 XmlUtils.skipCurrentTag(parser); 2622 2623 outInfo.addAction(value); 2624 } else if (nodeName.equals("category")) { 2625 String value = attrs.getAttributeValue( 2626 ANDROID_RESOURCES, "name"); 2627 if (value == null || value == "") { 2628 outError[0] = "No value supplied for <android:name>"; 2629 return false; 2630 } 2631 XmlUtils.skipCurrentTag(parser); 2632 2633 outInfo.addCategory(value); 2634 2635 } else if (nodeName.equals("data")) { 2636 sa = res.obtainAttributes(attrs, 2637 com.android.internal.R.styleable.AndroidManifestData); 2638 2639 String str = sa.getNonConfigurationString( 2640 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0); 2641 if (str != null) { 2642 try { 2643 outInfo.addDataType(str); 2644 } catch (IntentFilter.MalformedMimeTypeException e) { 2645 outError[0] = e.toString(); 2646 sa.recycle(); 2647 return false; 2648 } 2649 } 2650 2651 str = sa.getNonConfigurationString( 2652 com.android.internal.R.styleable.AndroidManifestData_scheme, 0); 2653 if (str != null) { 2654 outInfo.addDataScheme(str); 2655 } 2656 2657 String host = sa.getNonConfigurationString( 2658 com.android.internal.R.styleable.AndroidManifestData_host, 0); 2659 String port = sa.getNonConfigurationString( 2660 com.android.internal.R.styleable.AndroidManifestData_port, 0); 2661 if (host != null) { 2662 outInfo.addDataAuthority(host, port); 2663 } 2664 2665 str = sa.getNonConfigurationString( 2666 com.android.internal.R.styleable.AndroidManifestData_path, 0); 2667 if (str != null) { 2668 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL); 2669 } 2670 2671 str = sa.getNonConfigurationString( 2672 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0); 2673 if (str != null) { 2674 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX); 2675 } 2676 2677 str = sa.getNonConfigurationString( 2678 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0); 2679 if (str != null) { 2680 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB); 2681 } 2682 2683 sa.recycle(); 2684 XmlUtils.skipCurrentTag(parser); 2685 } else if (!RIGID_PARSER) { 2686 Log.w(TAG, "Unknown element under <intent-filter>: " 2687 + parser.getName() + " at " + mArchiveSourcePath + " " 2688 + parser.getPositionDescription()); 2689 XmlUtils.skipCurrentTag(parser); 2690 } else { 2691 outError[0] = "Bad element under <intent-filter>: " + parser.getName(); 2692 return false; 2693 } 2694 } 2695 2696 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT); 2697 if (false) { 2698 String cats = ""; 2699 Iterator<String> it = outInfo.categoriesIterator(); 2700 while (it != null && it.hasNext()) { 2701 cats += " " + it.next(); 2702 } 2703 System.out.println("Intent d=" + 2704 outInfo.hasDefault + ", cat=" + cats); 2705 } 2706 2707 return true; 2708 } 2709 2710 public final static class Package { 2711 public String packageName; 2712 2713 // For now we only support one application per package. 2714 public final ApplicationInfo applicationInfo = new ApplicationInfo(); 2715 2716 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0); 2717 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0); 2718 public final ArrayList<Activity> activities = new ArrayList<Activity>(0); 2719 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0); 2720 public final ArrayList<Provider> providers = new ArrayList<Provider>(0); 2721 public final ArrayList<Service> services = new ArrayList<Service>(0); 2722 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0); 2723 2724 public final ArrayList<String> requestedPermissions = new ArrayList<String>(); 2725 2726 public ArrayList<String> protectedBroadcasts; 2727 2728 public ArrayList<String> usesLibraries = null; 2729 public ArrayList<String> usesOptionalLibraries = null; 2730 public String[] usesLibraryFiles = null; 2731 2732 public ArrayList<String> mOriginalPackages = null; 2733 public String mRealPackage = null; 2734 public ArrayList<String> mAdoptPermissions = null; 2735 2736 // We store the application meta-data independently to avoid multiple unwanted references 2737 public Bundle mAppMetaData = null; 2738 2739 // If this is a 3rd party app, this is the path of the zip file. 2740 public String mPath; 2741 2742 // The version code declared for this package. 2743 public int mVersionCode; 2744 2745 // The version name declared for this package. 2746 public String mVersionName; 2747 2748 // The shared user id that this package wants to use. 2749 public String mSharedUserId; 2750 2751 // The shared user label that this package wants to use. 2752 public int mSharedUserLabel; 2753 2754 // Signatures that were read from the package. 2755 public Signature mSignatures[]; 2756 2757 // For use by package manager service for quick lookup of 2758 // preferred up order. 2759 public int mPreferredOrder = 0; 2760 2761 // For use by the package manager to keep track of the path to the 2762 // file an app came from. 2763 public String mScanPath; 2764 2765 // For use by package manager to keep track of where it has done dexopt. 2766 public boolean mDidDexOpt; 2767 2768 // User set enabled state. 2769 public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 2770 2771 // Additional data supplied by callers. 2772 public Object mExtras; 2773 2774 // Whether an operation is currently pending on this package 2775 public boolean mOperationPending; 2776 2777 /* 2778 * Applications hardware preferences 2779 */ 2780 public final ArrayList<ConfigurationInfo> configPreferences = 2781 new ArrayList<ConfigurationInfo>(); 2782 2783 /* 2784 * Applications requested features 2785 */ 2786 public ArrayList<FeatureInfo> reqFeatures = null; 2787 2788 public int installLocation; 2789 2790 public Package(String _name) { 2791 packageName = _name; 2792 applicationInfo.packageName = _name; 2793 applicationInfo.uid = -1; 2794 } 2795 2796 public void setPackageName(String newName) { 2797 packageName = newName; 2798 applicationInfo.packageName = newName; 2799 for (int i=permissions.size()-1; i>=0; i--) { 2800 permissions.get(i).setPackageName(newName); 2801 } 2802 for (int i=permissionGroups.size()-1; i>=0; i--) { 2803 permissionGroups.get(i).setPackageName(newName); 2804 } 2805 for (int i=activities.size()-1; i>=0; i--) { 2806 activities.get(i).setPackageName(newName); 2807 } 2808 for (int i=receivers.size()-1; i>=0; i--) { 2809 receivers.get(i).setPackageName(newName); 2810 } 2811 for (int i=providers.size()-1; i>=0; i--) { 2812 providers.get(i).setPackageName(newName); 2813 } 2814 for (int i=services.size()-1; i>=0; i--) { 2815 services.get(i).setPackageName(newName); 2816 } 2817 for (int i=instrumentation.size()-1; i>=0; i--) { 2818 instrumentation.get(i).setPackageName(newName); 2819 } 2820 } 2821 2822 public String toString() { 2823 return "Package{" 2824 + Integer.toHexString(System.identityHashCode(this)) 2825 + " " + packageName + "}"; 2826 } 2827 } 2828 2829 public static class Component<II extends IntentInfo> { 2830 public final Package owner; 2831 public final ArrayList<II> intents; 2832 public final String className; 2833 public Bundle metaData; 2834 2835 ComponentName componentName; 2836 String componentShortName; 2837 2838 public Component(Package _owner) { 2839 owner = _owner; 2840 intents = null; 2841 className = null; 2842 } 2843 2844 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) { 2845 owner = args.owner; 2846 intents = new ArrayList<II>(0); 2847 String name = args.sa.getNonConfigurationString(args.nameRes, 0); 2848 if (name == null) { 2849 className = null; 2850 args.outError[0] = args.tag + " does not specify android:name"; 2851 return; 2852 } 2853 2854 outInfo.name 2855 = buildClassName(owner.applicationInfo.packageName, name, args.outError); 2856 if (outInfo.name == null) { 2857 className = null; 2858 args.outError[0] = args.tag + " does not have valid android:name"; 2859 return; 2860 } 2861 2862 className = outInfo.name; 2863 2864 int iconVal = args.sa.getResourceId(args.iconRes, 0); 2865 if (iconVal != 0) { 2866 outInfo.icon = iconVal; 2867 outInfo.nonLocalizedLabel = null; 2868 } 2869 2870 TypedValue v = args.sa.peekValue(args.labelRes); 2871 if (v != null && (outInfo.labelRes=v.resourceId) == 0) { 2872 outInfo.nonLocalizedLabel = v.coerceToString(); 2873 } 2874 2875 outInfo.packageName = owner.packageName; 2876 } 2877 2878 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) { 2879 this(args, (PackageItemInfo)outInfo); 2880 if (args.outError[0] != null) { 2881 return; 2882 } 2883 2884 if (args.processRes != 0) { 2885 CharSequence pname; 2886 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) { 2887 pname = args.sa.getNonConfigurationString(args.processRes, 0); 2888 } else { 2889 // Some older apps have been seen to use a resource reference 2890 // here that on older builds was ignored (with a warning). We 2891 // need to continue to do this for them so they don't break. 2892 pname = args.sa.getNonResourceString(args.processRes); 2893 } 2894 outInfo.processName = buildProcessName(owner.applicationInfo.packageName, 2895 owner.applicationInfo.processName, pname, 2896 args.flags, args.sepProcesses, args.outError); 2897 } 2898 2899 if (args.descriptionRes != 0) { 2900 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0); 2901 } 2902 2903 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true); 2904 } 2905 2906 public Component(Component<II> clone) { 2907 owner = clone.owner; 2908 intents = clone.intents; 2909 className = clone.className; 2910 componentName = clone.componentName; 2911 componentShortName = clone.componentShortName; 2912 } 2913 2914 public ComponentName getComponentName() { 2915 if (componentName != null) { 2916 return componentName; 2917 } 2918 if (className != null) { 2919 componentName = new ComponentName(owner.applicationInfo.packageName, 2920 className); 2921 } 2922 return componentName; 2923 } 2924 2925 public String getComponentShortName() { 2926 if (componentShortName != null) { 2927 return componentShortName; 2928 } 2929 ComponentName component = getComponentName(); 2930 if (component != null) { 2931 componentShortName = component.flattenToShortString(); 2932 } 2933 return componentShortName; 2934 } 2935 2936 public void setPackageName(String packageName) { 2937 componentName = null; 2938 componentShortName = null; 2939 } 2940 } 2941 2942 public final static class Permission extends Component<IntentInfo> { 2943 public final PermissionInfo info; 2944 public boolean tree; 2945 public PermissionGroup group; 2946 2947 public Permission(Package _owner) { 2948 super(_owner); 2949 info = new PermissionInfo(); 2950 } 2951 2952 public Permission(Package _owner, PermissionInfo _info) { 2953 super(_owner); 2954 info = _info; 2955 } 2956 2957 public void setPackageName(String packageName) { 2958 super.setPackageName(packageName); 2959 info.packageName = packageName; 2960 } 2961 2962 public String toString() { 2963 return "Permission{" 2964 + Integer.toHexString(System.identityHashCode(this)) 2965 + " " + info.name + "}"; 2966 } 2967 } 2968 2969 public final static class PermissionGroup extends Component<IntentInfo> { 2970 public final PermissionGroupInfo info; 2971 2972 public PermissionGroup(Package _owner) { 2973 super(_owner); 2974 info = new PermissionGroupInfo(); 2975 } 2976 2977 public PermissionGroup(Package _owner, PermissionGroupInfo _info) { 2978 super(_owner); 2979 info = _info; 2980 } 2981 2982 public void setPackageName(String packageName) { 2983 super.setPackageName(packageName); 2984 info.packageName = packageName; 2985 } 2986 2987 public String toString() { 2988 return "PermissionGroup{" 2989 + Integer.toHexString(System.identityHashCode(this)) 2990 + " " + info.name + "}"; 2991 } 2992 } 2993 2994 private static boolean copyNeeded(int flags, Package p, Bundle metaData) { 2995 if (p.mSetEnabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { 2996 boolean enabled = p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 2997 if (p.applicationInfo.enabled != enabled) { 2998 return true; 2999 } 3000 } 3001 if ((flags & PackageManager.GET_META_DATA) != 0 3002 && (metaData != null || p.mAppMetaData != null)) { 3003 return true; 3004 } 3005 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0 3006 && p.usesLibraryFiles != null) { 3007 return true; 3008 } 3009 return false; 3010 } 3011 3012 public static ApplicationInfo generateApplicationInfo(Package p, int flags) { 3013 if (p == null) return null; 3014 if (!copyNeeded(flags, p, null)) { 3015 // CompatibilityMode is global state. It's safe to modify the instance 3016 // of the package. 3017 if (!sCompatibilityModeEnabled) { 3018 p.applicationInfo.disableCompatibilityMode(); 3019 } 3020 return p.applicationInfo; 3021 } 3022 3023 // Make shallow copy so we can store the metadata/libraries safely 3024 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo); 3025 if ((flags & PackageManager.GET_META_DATA) != 0) { 3026 ai.metaData = p.mAppMetaData; 3027 } 3028 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) { 3029 ai.sharedLibraryFiles = p.usesLibraryFiles; 3030 } 3031 if (!sCompatibilityModeEnabled) { 3032 ai.disableCompatibilityMode(); 3033 } 3034 ai.enabled = p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 3035 return ai; 3036 } 3037 3038 public static final PermissionInfo generatePermissionInfo( 3039 Permission p, int flags) { 3040 if (p == null) return null; 3041 if ((flags&PackageManager.GET_META_DATA) == 0) { 3042 return p.info; 3043 } 3044 PermissionInfo pi = new PermissionInfo(p.info); 3045 pi.metaData = p.metaData; 3046 return pi; 3047 } 3048 3049 public static final PermissionGroupInfo generatePermissionGroupInfo( 3050 PermissionGroup pg, int flags) { 3051 if (pg == null) return null; 3052 if ((flags&PackageManager.GET_META_DATA) == 0) { 3053 return pg.info; 3054 } 3055 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info); 3056 pgi.metaData = pg.metaData; 3057 return pgi; 3058 } 3059 3060 public final static class Activity extends Component<ActivityIntentInfo> { 3061 public final ActivityInfo info; 3062 3063 public Activity(final ParseComponentArgs args, final ActivityInfo _info) { 3064 super(args, _info); 3065 info = _info; 3066 info.applicationInfo = args.owner.applicationInfo; 3067 } 3068 3069 public void setPackageName(String packageName) { 3070 super.setPackageName(packageName); 3071 info.packageName = packageName; 3072 } 3073 3074 public String toString() { 3075 return "Activity{" 3076 + Integer.toHexString(System.identityHashCode(this)) 3077 + " " + getComponentShortName() + "}"; 3078 } 3079 } 3080 3081 public static final ActivityInfo generateActivityInfo(Activity a, 3082 int flags) { 3083 if (a == null) return null; 3084 if (!copyNeeded(flags, a.owner, a.metaData)) { 3085 return a.info; 3086 } 3087 // Make shallow copies so we can store the metadata safely 3088 ActivityInfo ai = new ActivityInfo(a.info); 3089 ai.metaData = a.metaData; 3090 ai.applicationInfo = generateApplicationInfo(a.owner, flags); 3091 return ai; 3092 } 3093 3094 public final static class Service extends Component<ServiceIntentInfo> { 3095 public final ServiceInfo info; 3096 3097 public Service(final ParseComponentArgs args, final ServiceInfo _info) { 3098 super(args, _info); 3099 info = _info; 3100 info.applicationInfo = args.owner.applicationInfo; 3101 } 3102 3103 public void setPackageName(String packageName) { 3104 super.setPackageName(packageName); 3105 info.packageName = packageName; 3106 } 3107 3108 public String toString() { 3109 return "Service{" 3110 + Integer.toHexString(System.identityHashCode(this)) 3111 + " " + getComponentShortName() + "}"; 3112 } 3113 } 3114 3115 public static final ServiceInfo generateServiceInfo(Service s, int flags) { 3116 if (s == null) return null; 3117 if (!copyNeeded(flags, s.owner, s.metaData)) { 3118 return s.info; 3119 } 3120 // Make shallow copies so we can store the metadata safely 3121 ServiceInfo si = new ServiceInfo(s.info); 3122 si.metaData = s.metaData; 3123 si.applicationInfo = generateApplicationInfo(s.owner, flags); 3124 return si; 3125 } 3126 3127 public final static class Provider extends Component { 3128 public final ProviderInfo info; 3129 public boolean syncable; 3130 3131 public Provider(final ParseComponentArgs args, final ProviderInfo _info) { 3132 super(args, _info); 3133 info = _info; 3134 info.applicationInfo = args.owner.applicationInfo; 3135 syncable = false; 3136 } 3137 3138 public Provider(Provider existingProvider) { 3139 super(existingProvider); 3140 this.info = existingProvider.info; 3141 this.syncable = existingProvider.syncable; 3142 } 3143 3144 public void setPackageName(String packageName) { 3145 super.setPackageName(packageName); 3146 info.packageName = packageName; 3147 } 3148 3149 public String toString() { 3150 return "Provider{" 3151 + Integer.toHexString(System.identityHashCode(this)) 3152 + " " + info.name + "}"; 3153 } 3154 } 3155 3156 public static final ProviderInfo generateProviderInfo(Provider p, 3157 int flags) { 3158 if (p == null) return null; 3159 if (!copyNeeded(flags, p.owner, p.metaData) 3160 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0 3161 || p.info.uriPermissionPatterns == null)) { 3162 return p.info; 3163 } 3164 // Make shallow copies so we can store the metadata safely 3165 ProviderInfo pi = new ProviderInfo(p.info); 3166 pi.metaData = p.metaData; 3167 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) { 3168 pi.uriPermissionPatterns = null; 3169 } 3170 pi.applicationInfo = generateApplicationInfo(p.owner, flags); 3171 return pi; 3172 } 3173 3174 public final static class Instrumentation extends Component { 3175 public final InstrumentationInfo info; 3176 3177 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) { 3178 super(args, _info); 3179 info = _info; 3180 } 3181 3182 public void setPackageName(String packageName) { 3183 super.setPackageName(packageName); 3184 info.packageName = packageName; 3185 } 3186 3187 public String toString() { 3188 return "Instrumentation{" 3189 + Integer.toHexString(System.identityHashCode(this)) 3190 + " " + getComponentShortName() + "}"; 3191 } 3192 } 3193 3194 public static final InstrumentationInfo generateInstrumentationInfo( 3195 Instrumentation i, int flags) { 3196 if (i == null) return null; 3197 if ((flags&PackageManager.GET_META_DATA) == 0) { 3198 return i.info; 3199 } 3200 InstrumentationInfo ii = new InstrumentationInfo(i.info); 3201 ii.metaData = i.metaData; 3202 return ii; 3203 } 3204 3205 public static class IntentInfo extends IntentFilter { 3206 public boolean hasDefault; 3207 public int labelRes; 3208 public CharSequence nonLocalizedLabel; 3209 public int icon; 3210 public int logo; 3211 } 3212 3213 public final static class ActivityIntentInfo extends IntentInfo { 3214 public final Activity activity; 3215 3216 public ActivityIntentInfo(Activity _activity) { 3217 activity = _activity; 3218 } 3219 3220 public String toString() { 3221 return "ActivityIntentInfo{" 3222 + Integer.toHexString(System.identityHashCode(this)) 3223 + " " + activity.info.name + "}"; 3224 } 3225 } 3226 3227 public final static class ServiceIntentInfo extends IntentInfo { 3228 public final Service service; 3229 3230 public ServiceIntentInfo(Service _service) { 3231 service = _service; 3232 } 3233 3234 public String toString() { 3235 return "ServiceIntentInfo{" 3236 + Integer.toHexString(System.identityHashCode(this)) 3237 + " " + service.info.name + "}"; 3238 } 3239 } 3240 3241 /** 3242 * @hide 3243 */ 3244 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) { 3245 sCompatibilityModeEnabled = compatibilityModeEnabled; 3246 } 3247} 3248