1 /* 2 * Copyright (C) 2010 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 17 package com.android.ide.common.xml; 18 19 import com.android.resources.Keyboard; 20 import com.android.resources.Navigation; 21 import com.android.resources.TouchScreen; 22 23 import java.util.ArrayList; 24 import java.util.Set; 25 import java.util.TreeSet; 26 27 /** 28 * Class containing the manifest info obtained during the parsing. 29 */ 30 public final class ManifestData { 31 32 /** 33 * Value returned by {@link #getMinSdkVersion()} when the value of the minSdkVersion attribute 34 * in the manifest is a codename and not an integer value. 35 */ 36 public final static int MIN_SDK_CODENAME = 0; 37 38 /** 39 * Value returned by {@link #getGlEsVersion()} when there are no <uses-feature> node with the 40 * attribute glEsVersion set. 41 */ 42 public final static int GL_ES_VERSION_NOT_SET = -1; 43 44 /** Application package */ 45 String mPackage; 46 /** Application version Code, null if the attribute is not present. */ 47 Integer mVersionCode = null; 48 /** List of all activities */ 49 final ArrayList<Activity> mActivities = new ArrayList<Activity>(); 50 /** Launcher activity */ 51 Activity mLauncherActivity = null; 52 /** list of process names declared by the manifest */ 53 Set<String> mProcesses = null; 54 /** debuggable attribute value. If null, the attribute is not present. */ 55 Boolean mDebuggable = null; 56 /** API level requirement. if null the attribute was not present. */ 57 private String mMinSdkVersionString = null; 58 /** API level requirement. Default is 1 even if missing. If value is a codename, then it'll be 59 * 0 instead. */ 60 private int mMinSdkVersion = 1; 61 private int mTargetSdkVersion = 0; 62 /** List of all instrumentations declared by the manifest */ 63 final ArrayList<Instrumentation> mInstrumentations = 64 new ArrayList<Instrumentation>(); 65 /** List of all libraries in use declared by the manifest */ 66 final ArrayList<UsesLibrary> mLibraries = new ArrayList<UsesLibrary>(); 67 /** List of all feature in use declared by the manifest */ 68 final ArrayList<UsesFeature> mFeatures = new ArrayList<UsesFeature>(); 69 70 SupportsScreens mSupportsScreensFromManifest; 71 SupportsScreens mSupportsScreensValues; 72 UsesConfiguration mUsesConfiguration; 73 74 /** 75 * Instrumentation info obtained from manifest 76 */ 77 public final static class Instrumentation { 78 private final String mName; 79 private final String mTargetPackage; 80 Instrumentation(String name, String targetPackage)81 Instrumentation(String name, String targetPackage) { 82 mName = name; 83 mTargetPackage = targetPackage; 84 } 85 86 /** 87 * Returns the fully qualified instrumentation class name 88 */ getName()89 public String getName() { 90 return mName; 91 } 92 93 /** 94 * Returns the Android app package that is the target of this instrumentation 95 */ getTargetPackage()96 public String getTargetPackage() { 97 return mTargetPackage; 98 } 99 } 100 101 /** 102 * Activity info obtained from the manifest. 103 */ 104 public final static class Activity { 105 private final String mName; 106 private final boolean mIsExported; 107 private boolean mHasAction = false; 108 private boolean mHasMainAction = false; 109 private boolean mHasLauncherCategory = false; 110 Activity(String name, boolean exported)111 public Activity(String name, boolean exported) { 112 mName = name; 113 mIsExported = exported; 114 } 115 getName()116 public String getName() { 117 return mName; 118 } 119 isExported()120 public boolean isExported() { 121 return mIsExported; 122 } 123 hasAction()124 public boolean hasAction() { 125 return mHasAction; 126 } 127 isHomeActivity()128 public boolean isHomeActivity() { 129 return mHasMainAction && mHasLauncherCategory; 130 } 131 setHasAction(boolean hasAction)132 void setHasAction(boolean hasAction) { 133 mHasAction = hasAction; 134 } 135 136 /** If the activity doesn't yet have a filter set for the launcher, this resets both 137 * flags. This is to handle multiple intent-filters where one could have the valid 138 * action, and another one of the valid category. 139 */ resetIntentFilter()140 void resetIntentFilter() { 141 if (isHomeActivity() == false) { 142 mHasMainAction = mHasLauncherCategory = false; 143 } 144 } 145 setHasMainAction(boolean hasMainAction)146 void setHasMainAction(boolean hasMainAction) { 147 mHasMainAction = hasMainAction; 148 } 149 setHasLauncherCategory(boolean hasLauncherCategory)150 void setHasLauncherCategory(boolean hasLauncherCategory) { 151 mHasLauncherCategory = hasLauncherCategory; 152 } 153 } 154 155 /** 156 * Class representing the <code>supports-screens</code> node in the manifest. 157 * By default, all the getters will return null if there was no value defined in the manifest. 158 * 159 * To get an instance with all the actual values, use {@link #resolveSupportsScreensValues(int)} 160 */ 161 public final static class SupportsScreens { 162 private Boolean mResizeable; 163 private Boolean mAnyDensity; 164 private Boolean mSmallScreens; 165 private Boolean mNormalScreens; 166 private Boolean mLargeScreens; 167 SupportsScreens()168 public SupportsScreens() { 169 } 170 171 /** 172 * Instantiate an instance from a string. The string must have been created with 173 * {@link #getEncodedValues()}. 174 * @param value the string. 175 */ SupportsScreens(String value)176 public SupportsScreens(String value) { 177 String[] values = value.split("\\|"); 178 179 mAnyDensity = Boolean.valueOf(values[0]); 180 mResizeable = Boolean.valueOf(values[1]); 181 mSmallScreens = Boolean.valueOf(values[2]); 182 mNormalScreens = Boolean.valueOf(values[3]); 183 mLargeScreens = Boolean.valueOf(values[4]); 184 } 185 186 /** 187 * Returns an instance of {@link SupportsScreens} initialized with the default values 188 * based on the given targetSdkVersion. 189 * @param targetSdkVersion 190 */ getDefaultValues(int targetSdkVersion)191 public static SupportsScreens getDefaultValues(int targetSdkVersion) { 192 SupportsScreens result = new SupportsScreens(); 193 194 result.mNormalScreens = Boolean.TRUE; 195 // Screen size and density became available in Android 1.5/API3, so before that 196 // non normal screens were not supported by default. After they are considered 197 // supported. 198 result.mResizeable = result.mAnyDensity = result.mSmallScreens = result.mLargeScreens = 199 targetSdkVersion <= 3 ? Boolean.FALSE : Boolean.TRUE; 200 201 return result; 202 } 203 204 /** 205 * Returns a version of the receiver for which all values have been set, even if they 206 * were not present in the manifest. 207 * @param targetSdkVersion the target api level of the app, since this has an effect 208 * on default values. 209 */ resolveSupportsScreensValues(int targetSdkVersion)210 public SupportsScreens resolveSupportsScreensValues(int targetSdkVersion) { 211 SupportsScreens result = getDefaultValues(targetSdkVersion); 212 213 // Override the default with the existing values: 214 if (mResizeable != null) result.mResizeable = mResizeable; 215 if (mAnyDensity != null) result.mAnyDensity = mAnyDensity; 216 if (mSmallScreens != null) result.mSmallScreens = mSmallScreens; 217 if (mNormalScreens != null) result.mNormalScreens = mNormalScreens; 218 if (mLargeScreens != null) result.mLargeScreens = mLargeScreens; 219 220 return result; 221 } 222 223 /** 224 * returns the value of the <code>resizeable</code> attribute or null if not present. 225 */ getResizeable()226 public Boolean getResizeable() { 227 return mResizeable; 228 } 229 setResizeable(Boolean resizeable)230 void setResizeable(Boolean resizeable) { 231 mResizeable = getConstantBoolean(resizeable); 232 } 233 234 /** 235 * returns the value of the <code>anyDensity</code> attribute or null if not present. 236 */ getAnyDensity()237 public Boolean getAnyDensity() { 238 return mAnyDensity; 239 } 240 setAnyDensity(Boolean anyDensity)241 void setAnyDensity(Boolean anyDensity) { 242 mAnyDensity = getConstantBoolean(anyDensity); 243 } 244 245 /** 246 * returns the value of the <code>smallScreens</code> attribute or null if not present. 247 */ getSmallScreens()248 public Boolean getSmallScreens() { 249 return mSmallScreens; 250 } 251 setSmallScreens(Boolean smallScreens)252 void setSmallScreens(Boolean smallScreens) { 253 mSmallScreens = getConstantBoolean(smallScreens); 254 } 255 256 /** 257 * returns the value of the <code>normalScreens</code> attribute or null if not present. 258 */ getNormalScreens()259 public Boolean getNormalScreens() { 260 return mNormalScreens; 261 } 262 setNormalScreens(Boolean normalScreens)263 void setNormalScreens(Boolean normalScreens) { 264 mNormalScreens = getConstantBoolean(normalScreens); 265 } 266 267 /** 268 * returns the value of the <code>largeScreens</code> attribute or null if not present. 269 */ getLargeScreens()270 public Boolean getLargeScreens() { 271 return mLargeScreens; 272 } 273 setLargeScreens(Boolean largeScreens)274 void setLargeScreens(Boolean largeScreens) { 275 mLargeScreens = getConstantBoolean(largeScreens); 276 } 277 278 /** 279 * Returns either {@link Boolean#TRUE} or {@link Boolean#FALSE} based on the value of 280 * the given Boolean object. 281 */ getConstantBoolean(Boolean v)282 private Boolean getConstantBoolean(Boolean v) { 283 if (v != null) { 284 if (v.equals(Boolean.TRUE)) { 285 return Boolean.TRUE; 286 } else { 287 return Boolean.FALSE; 288 } 289 } 290 291 return null; 292 } 293 294 @Override equals(Object obj)295 public boolean equals(Object obj) { 296 if (obj instanceof SupportsScreens) { 297 SupportsScreens support = (SupportsScreens) obj; 298 // since all the fields are guaranteed to be either Boolean.TRUE or Boolean.FALSE 299 // (or null), we can simply check they are identical and not bother with 300 // calling equals (which would require to check != null. 301 // see #getConstanntBoolean(Boolean) 302 return mResizeable == support.mResizeable && 303 mAnyDensity == support.mAnyDensity && 304 mSmallScreens == support.mSmallScreens && 305 mNormalScreens == support.mNormalScreens && 306 mLargeScreens == support.mLargeScreens; 307 } 308 309 return false; 310 } 311 312 /* Override hashCode, mostly to make Eclipse happy and not warn about it. 313 * And if you ever put this in a Map or Set, it will avoid surprises. */ 314 @Override hashCode()315 public int hashCode() { 316 final int prime = 31; 317 int result = 1; 318 result = prime * result + ((mAnyDensity == null) ? 0 : mAnyDensity.hashCode()); 319 result = prime * result + ((mLargeScreens == null) ? 0 : mLargeScreens.hashCode()); 320 result = prime * result + ((mNormalScreens == null) ? 0 : mNormalScreens.hashCode()); 321 result = prime * result + ((mResizeable == null) ? 0 : mResizeable.hashCode()); 322 result = prime * result + ((mSmallScreens == null) ? 0 : mSmallScreens.hashCode()); 323 return result; 324 } 325 326 /** 327 * Returns true if the two instances support the same screen sizes. 328 * This is similar to {@link #equals(Object)} except that it ignores the values of 329 * {@link #getAnyDensity()} and {@link #getResizeable()}. 330 * @param support the other instance to compare to. 331 * @return true if the two instances support the same screen sizes. 332 */ hasSameScreenSupportAs(SupportsScreens support)333 public boolean hasSameScreenSupportAs(SupportsScreens support) { 334 // since all the fields are guaranteed to be either Boolean.TRUE or Boolean.FALSE 335 // (or null), we can simply check they are identical and not bother with 336 // calling equals (which would require to check != null. 337 // see #getConstanntBoolean(Boolean) 338 339 // This only checks that matter here are the screen sizes. resizeable and anyDensity 340 // are not checked. 341 return mSmallScreens == support.mSmallScreens && 342 mNormalScreens == support.mNormalScreens && 343 mLargeScreens == support.mLargeScreens; 344 } 345 346 /** 347 * Returns true if the two instances have strictly different screen size support. 348 * This means that there is no screen size that they both support. 349 * @param support the other instance to compare to. 350 * @return true if they are stricly different. 351 */ hasStrictlyDifferentScreenSupportAs(SupportsScreens support)352 public boolean hasStrictlyDifferentScreenSupportAs(SupportsScreens support) { 353 // since all the fields are guaranteed to be either Boolean.TRUE or Boolean.FALSE 354 // (or null), we can simply check they are identical and not bother with 355 // calling equals (which would require to check != null. 356 // see #getConstanntBoolean(Boolean) 357 358 // This only checks that matter here are the screen sizes. resizeable and anyDensity 359 // are not checked. 360 return (mSmallScreens != Boolean.TRUE || support.mSmallScreens != Boolean.TRUE) && 361 (mNormalScreens != Boolean.TRUE || support.mNormalScreens != Boolean.TRUE) && 362 (mLargeScreens != Boolean.TRUE || support.mLargeScreens != Boolean.TRUE); 363 } 364 365 /** 366 * Comparison of 2 Supports-screens. This only uses screen sizes (ignores resizeable and 367 * anyDensity), and considers that 368 * {@link #hasStrictlyDifferentScreenSupportAs(SupportsScreens)} returns true and 369 * {@link #overlapWith(SupportsScreens)} returns false. 370 * @throws IllegalArgumentException if the two instanced are not strictly different or 371 * overlap each other 372 * @see #hasStrictlyDifferentScreenSupportAs(SupportsScreens) 373 * @see #overlapWith(SupportsScreens) 374 */ compareScreenSizesWith(SupportsScreens o)375 public int compareScreenSizesWith(SupportsScreens o) { 376 if (hasStrictlyDifferentScreenSupportAs(o) == false) { 377 throw new IllegalArgumentException("The two instances are not strictly different."); 378 } 379 if (overlapWith(o)) { 380 throw new IllegalArgumentException("The two instances overlap each other."); 381 } 382 383 int comp = mLargeScreens.compareTo(o.mLargeScreens); 384 if (comp != 0) return comp; 385 386 comp = mNormalScreens.compareTo(o.mNormalScreens); 387 if (comp != 0) return comp; 388 389 comp = mSmallScreens.compareTo(o.mSmallScreens); 390 if (comp != 0) return comp; 391 392 return 0; 393 } 394 395 /** 396 * Returns a string encoding of the content of the instance. This string can be used to 397 * instantiate a {@link SupportsScreens} object through 398 * {@link #SupportsScreens(String)}. 399 */ getEncodedValues()400 public String getEncodedValues() { 401 return String.format("%1$s|%2$s|%3$s|%4$s|%5$s", 402 mAnyDensity, mResizeable, mSmallScreens, mNormalScreens, mLargeScreens); 403 } 404 405 @Override toString()406 public String toString() { 407 StringBuilder sb = new StringBuilder(); 408 409 boolean alreadyOutputSomething = false; 410 411 if (Boolean.TRUE.equals(mSmallScreens)) { 412 alreadyOutputSomething = true; 413 sb.append("small"); 414 } 415 416 if (Boolean.TRUE.equals(mNormalScreens)) { 417 if (alreadyOutputSomething) { 418 sb.append(", "); 419 } 420 alreadyOutputSomething = true; 421 sb.append("normal"); 422 } 423 424 if (Boolean.TRUE.equals(mLargeScreens)) { 425 if (alreadyOutputSomething) { 426 sb.append(", "); 427 } 428 alreadyOutputSomething = true; 429 sb.append("large"); 430 } 431 432 if (alreadyOutputSomething == false) { 433 sb.append("<none>"); 434 } 435 436 return sb.toString(); 437 } 438 439 /** 440 * Returns true if the two instance overlap with each other. 441 * This can happen if one instances supports a size, when the other instance doesn't while 442 * supporting a size above and a size below. 443 * @param otherSS the other supports-screens to compare to. 444 */ overlapWith(SupportsScreens otherSS)445 public boolean overlapWith(SupportsScreens otherSS) { 446 if (mSmallScreens == null || mNormalScreens == null || mLargeScreens == null || 447 otherSS.mSmallScreens == null || otherSS.mNormalScreens == null || 448 otherSS.mLargeScreens == null) { 449 throw new IllegalArgumentException("Some screen sizes Boolean are not initialized"); 450 } 451 452 if (mSmallScreens == Boolean.TRUE && mNormalScreens == Boolean.FALSE && 453 mLargeScreens == Boolean.TRUE) { 454 return otherSS.mNormalScreens == Boolean.TRUE; 455 } 456 457 if (otherSS.mSmallScreens == Boolean.TRUE && otherSS.mNormalScreens == Boolean.FALSE && 458 otherSS.mLargeScreens == Boolean.TRUE) { 459 return mNormalScreens == Boolean.TRUE; 460 } 461 462 return false; 463 } 464 } 465 466 /** 467 * Class representing a <code>uses-library</code> node in the manifest. 468 */ 469 public final static class UsesLibrary { 470 String mName; 471 Boolean mRequired = Boolean.TRUE; // default is true even if missing 472 getName()473 public String getName() { 474 return mName; 475 } 476 getRequired()477 public Boolean getRequired() { 478 return mRequired; 479 } 480 } 481 482 /** 483 * Class representing a <code>uses-feature</code> node in the manifest. 484 */ 485 public final static class UsesFeature { 486 String mName; 487 int mGlEsVersion = 0; 488 Boolean mRequired = Boolean.TRUE; // default is true even if missing 489 getName()490 public String getName() { 491 return mName; 492 } 493 494 /** 495 * Returns the value of the glEsVersion attribute, or 0 if the attribute was not present. 496 */ getGlEsVersion()497 public int getGlEsVersion() { 498 return mGlEsVersion; 499 } 500 getRequired()501 public Boolean getRequired() { 502 return mRequired; 503 } 504 } 505 506 /** 507 * Class representing the <code>uses-configuration</code> node in the manifest. 508 */ 509 public final static class UsesConfiguration { 510 Boolean mReqFiveWayNav; 511 Boolean mReqHardKeyboard; 512 Keyboard mReqKeyboardType; 513 TouchScreen mReqTouchScreen; 514 Navigation mReqNavigation; 515 516 /** 517 * returns the value of the <code>reqFiveWayNav</code> attribute or null if not present. 518 */ getReqFiveWayNav()519 public Boolean getReqFiveWayNav() { 520 return mReqFiveWayNav; 521 } 522 523 /** 524 * returns the value of the <code>reqNavigation</code> attribute or null if not present. 525 */ getReqNavigation()526 public Navigation getReqNavigation() { 527 return mReqNavigation; 528 } 529 530 /** 531 * returns the value of the <code>reqHardKeyboard</code> attribute or null if not present. 532 */ getReqHardKeyboard()533 public Boolean getReqHardKeyboard() { 534 return mReqHardKeyboard; 535 } 536 537 /** 538 * returns the value of the <code>reqKeyboardType</code> attribute or null if not present. 539 */ getReqKeyboardType()540 public Keyboard getReqKeyboardType() { 541 return mReqKeyboardType; 542 } 543 544 /** 545 * returns the value of the <code>reqTouchScreen</code> attribute or null if not present. 546 */ getReqTouchScreen()547 public TouchScreen getReqTouchScreen() { 548 return mReqTouchScreen; 549 } 550 } 551 552 /** 553 * Returns the package defined in the manifest, if found. 554 * @return The package name or null if not found. 555 */ getPackage()556 public String getPackage() { 557 return mPackage; 558 } 559 560 /** 561 * Returns the versionCode value defined in the manifest, if found, null otherwise. 562 * @return the versionCode or null if not found. 563 */ getVersionCode()564 public Integer getVersionCode() { 565 return mVersionCode; 566 } 567 568 /** 569 * Returns the list of activities found in the manifest. 570 * @return An array of fully qualified class names, or empty if no activity were found. 571 */ getActivities()572 public Activity[] getActivities() { 573 return mActivities.toArray(new Activity[mActivities.size()]); 574 } 575 576 /** 577 * Returns the name of one activity found in the manifest, that is configured to show 578 * up in the HOME screen. 579 * @return the fully qualified name of a HOME activity or null if none were found. 580 */ getLauncherActivity()581 public Activity getLauncherActivity() { 582 return mLauncherActivity; 583 } 584 585 /** 586 * Returns the list of process names declared by the manifest. 587 */ getProcesses()588 public String[] getProcesses() { 589 if (mProcesses != null) { 590 return mProcesses.toArray(new String[mProcesses.size()]); 591 } 592 593 return new String[0]; 594 } 595 596 /** 597 * Returns the <code>debuggable</code> attribute value or null if it is not set. 598 */ getDebuggable()599 public Boolean getDebuggable() { 600 return mDebuggable; 601 } 602 603 /** 604 * Returns the <code>minSdkVersion</code> attribute, or null if it's not set. 605 */ getMinSdkVersionString()606 public String getMinSdkVersionString() { 607 return mMinSdkVersionString; 608 } 609 610 /** 611 * Sets the value of the <code>minSdkVersion</code> attribute. 612 * @param minSdkVersion the string value of the attribute in the manifest. 613 */ setMinSdkVersionString(String minSdkVersion)614 public void setMinSdkVersionString(String minSdkVersion) { 615 mMinSdkVersionString = minSdkVersion; 616 if (mMinSdkVersionString != null) { 617 try { 618 mMinSdkVersion = Integer.parseInt(mMinSdkVersionString); 619 } catch (NumberFormatException e) { 620 mMinSdkVersion = MIN_SDK_CODENAME; 621 } 622 } 623 } 624 625 /** 626 * Returns the <code>minSdkVersion</code> attribute, or 0 if it's not set or is a codename. 627 * @see #getMinSdkVersionString() 628 */ getMinSdkVersion()629 public int getMinSdkVersion() { 630 return mMinSdkVersion; 631 } 632 633 634 /** 635 * Sets the value of the <code>minSdkVersion</code> attribute. 636 * @param targetSdkVersion the string value of the attribute in the manifest. 637 */ setTargetSdkVersionString(String targetSdkVersion)638 public void setTargetSdkVersionString(String targetSdkVersion) { 639 if (targetSdkVersion != null) { 640 try { 641 mTargetSdkVersion = Integer.parseInt(targetSdkVersion); 642 } catch (NumberFormatException e) { 643 // keep the value at 0. 644 } 645 } 646 } 647 648 /** 649 * Returns the <code>targetSdkVersion</code> attribute, or the same value as 650 * {@link #getMinSdkVersion()} if it was not set in the manifest. 651 */ getTargetSdkVersion()652 public int getTargetSdkVersion() { 653 if (mTargetSdkVersion == 0) { 654 return getMinSdkVersion(); 655 } 656 657 return mTargetSdkVersion; 658 } 659 660 /** 661 * Returns the list of instrumentations found in the manifest. 662 * @return An array of {@link Instrumentation}, or empty if no instrumentations were 663 * found. 664 */ getInstrumentations()665 public Instrumentation[] getInstrumentations() { 666 return mInstrumentations.toArray(new Instrumentation[mInstrumentations.size()]); 667 } 668 669 /** 670 * Returns the list of libraries in use found in the manifest. 671 * @return An array of {@link UsesLibrary} objects, or empty if no libraries were found. 672 */ getUsesLibraries()673 public UsesLibrary[] getUsesLibraries() { 674 return mLibraries.toArray(new UsesLibrary[mLibraries.size()]); 675 } 676 677 /** 678 * Returns the list of features in use found in the manifest. 679 * @return An array of {@link UsesFeature} objects, or empty if no libraries were found. 680 */ getUsesFeatures()681 public UsesFeature[] getUsesFeatures() { 682 return mFeatures.toArray(new UsesFeature[mFeatures.size()]); 683 } 684 685 /** 686 * Returns the glEsVersion from a <uses-feature> or {@link #GL_ES_VERSION_NOT_SET} if not set. 687 */ getGlEsVersion()688 public int getGlEsVersion() { 689 for (UsesFeature feature : mFeatures) { 690 if (feature.mGlEsVersion > 0) { 691 return feature.mGlEsVersion; 692 } 693 } 694 return GL_ES_VERSION_NOT_SET; 695 } 696 697 /** 698 * Returns the {@link SupportsScreens} object representing the <code>supports-screens</code> 699 * node, or null if the node doesn't exist at all. 700 * Some values in the {@link SupportsScreens} instance maybe null, indicating that they 701 * were not present in the manifest. To get an instance that contains the values, as seen 702 * by the Android platform when the app is running, use {@link #getSupportsScreensValues()}. 703 */ getSupportsScreensFromManifest()704 public SupportsScreens getSupportsScreensFromManifest() { 705 return mSupportsScreensFromManifest; 706 } 707 708 /** 709 * Returns an always non-null instance of {@link SupportsScreens} that's been initialized with 710 * the default values, and the values from the manifest. 711 * The default values depends on the manifest values for minSdkVersion and targetSdkVersion. 712 */ getSupportsScreensValues()713 public synchronized SupportsScreens getSupportsScreensValues() { 714 if (mSupportsScreensValues == null) { 715 if (mSupportsScreensFromManifest == null) { 716 mSupportsScreensValues = SupportsScreens.getDefaultValues(getTargetSdkVersion()); 717 } else { 718 // get a SupportsScreen that replace the missing values with default values. 719 mSupportsScreensValues = mSupportsScreensFromManifest.resolveSupportsScreensValues( 720 getTargetSdkVersion()); 721 } 722 } 723 724 return mSupportsScreensValues; 725 } 726 727 /** 728 * Returns the {@link UsesConfiguration} object representing the <code>uses-configuration</code> 729 * node, or null if the node doesn't exist at all. 730 */ getUsesConfiguration()731 public UsesConfiguration getUsesConfiguration() { 732 return mUsesConfiguration; 733 } 734 addProcessName(String processName)735 void addProcessName(String processName) { 736 if (mProcesses == null) { 737 mProcesses = new TreeSet<String>(); 738 } 739 740 if (processName.startsWith(":")) { 741 mProcesses.add(mPackage + processName); 742 } else { 743 mProcesses.add(processName); 744 } 745 } 746 747 } 748