2 * Copyright (C) 2006 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package android.content.res;
19 import android.os.Trace;
20 import android.view.View;
21 import com.android.internal.util.XmlUtils;
23 import org.xmlpull.v1.XmlPullParser;
24 import org.xmlpull.v1.XmlPullParserException;
26 import android.content.pm.ActivityInfo;
27 import android.graphics.Movie;
28 import android.graphics.drawable.Drawable;
29 import android.graphics.drawable.ColorDrawable;
30 import android.graphics.drawable.Drawable.ConstantState;
31 import android.os.Build;
32 import android.os.Bundle;
33 import android.util.AttributeSet;
34 import android.util.DisplayMetrics;
35 import android.util.Log;
36 import android.util.Slog;
37 import android.util.TypedValue;
38 import android.util.LongSparseArray;
40 import java.io.IOException;
41 import java.io.InputStream;
42 import java.lang.ref.WeakReference;
43 import java.util.Locale;
45 import libcore.icu.NativePluralRules;
48 * Class for accessing an application's resources. This sits on top of the
49 * asset manager of the application (accessible through {@link #getAssets}) and
50 * provides a high-level API for getting typed data from the assets.
52 * <p>The Android resource system keeps track of all non-code assets associated with an
53 * application. You can use this class to access your application's resources. You can generally
54 * acquire the {@link android.content.res.Resources} instance associated with your application
55 * with {@link android.content.Context#getResources getResources()}.</p>
57 * <p>The Android SDK tools compile your application's resources into the application binary
58 * at build time. To use a resource, you must install it correctly in the source tree (inside
59 * your project's {@code res/} directory) and build your application. As part of the build
60 * process, the SDK tools generate symbols for each resource, which you can use in your application
61 * code to access the resources.</p>
63 * <p>Using application resources makes it easy to update various characteristics of your
64 * application without modifying code, and—by providing sets of alternative
65 * resources—enables you to optimize your application for a variety of device configurations
66 * (such as for different languages and screen sizes). This is an important aspect of developing
67 * Android applications that are compatible on different types of devices.</p>
69 * <p>For more information about using resources, see the documentation about <a
70 * href="{@docRoot}guide/topics/resources/index.html">Application Resources</a>.</p>
72 public class Resources {
73 static final String TAG = "Resources";
74 private static final boolean DEBUG_LOAD = false;
75 private static final boolean DEBUG_CONFIG = false;
76 private static final boolean DEBUG_ATTRIBUTES_CACHE = false;
77 private static final boolean TRACE_FOR_PRELOAD = false;
78 private static final boolean TRACE_FOR_MISS_PRELOAD = false;
80 private static final int ID_OTHER = 0x01000004;
82 private static final Object sSync = new Object();
83 /*package*/ static Resources mSystem = null;
85 // Information about preloaded resources. Note that they are not
86 // protected by a lock, because while preloading in zygote we are all
87 // single-threaded, and after that these are immutable.
88 private static final LongSparseArray<Drawable.ConstantState>[] sPreloadedDrawables;
89 private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
90 = new LongSparseArray<Drawable.ConstantState>();
91 private static final LongSparseArray<ColorStateList> sPreloadedColorStateLists
92 = new LongSparseArray<ColorStateList>();
94 private static boolean sPreloaded;
95 private static int sPreloadedDensity;
97 // These are protected by mAccessLock.
99 /*package*/ final Object mAccessLock = new Object();
100 /*package*/ final Configuration mTmpConfig = new Configuration();
101 /*package*/ TypedValue mTmpValue = new TypedValue();
102 /*package*/ final LongSparseArray<WeakReference<Drawable.ConstantState> > mDrawableCache
103 = new LongSparseArray<WeakReference<Drawable.ConstantState> >();
104 /*package*/ final LongSparseArray<WeakReference<ColorStateList> > mColorStateListCache
105 = new LongSparseArray<WeakReference<ColorStateList> >();
106 /*package*/ final LongSparseArray<WeakReference<Drawable.ConstantState> > mColorDrawableCache
107 = new LongSparseArray<WeakReference<Drawable.ConstantState> >();
108 /*package*/ boolean mPreloading;
110 /*package*/ TypedArray mCachedStyledAttributes = null;
111 RuntimeException mLastRetrievedAttrs = null;
113 private int mLastCachedXmlBlockIndex = -1;
114 private final int[] mCachedXmlBlockIds = { 0, 0, 0, 0 };
115 private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[4];
117 /*package*/ final AssetManager mAssets;
118 private final Configuration mConfiguration = new Configuration();
119 /*package*/ final DisplayMetrics mMetrics = new DisplayMetrics();
120 private NativePluralRules mPluralRule;
122 private CompatibilityInfo mCompatibilityInfo;
125 sPreloadedDrawables = new LongSparseArray[2];
126 sPreloadedDrawables[0] = new LongSparseArray<Drawable.ConstantState>();
127 sPreloadedDrawables[1] = new LongSparseArray<Drawable.ConstantState>();
131 public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
132 return selectSystemTheme(curTheme, targetSdkVersion,
133 com.android.internal.R.style.Theme,
134 com.android.internal.R.style.Theme_Holo,
135 com.android.internal.R.style.Theme_DeviceDefault);
139 public static int selectSystemTheme(int curTheme, int targetSdkVersion,
140 int orig, int holo, int deviceDefault) {
144 if (targetSdkVersion < Build.VERSION_CODES.HONEYCOMB) {
147 if (targetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
150 return deviceDefault;
154 * This exception is thrown by the resource APIs when a requested resource
157 public static class NotFoundException extends RuntimeException {
158 public NotFoundException() {
161 public NotFoundException(String name) {
167 * Create a new Resources object on top of an existing set of assets in an
170 * @param assets Previously created AssetManager.
171 * @param metrics Current display metrics to consider when
172 * selecting/computing resource values.
173 * @param config Desired device configuration to consider when
174 * selecting/computing resource values (optional).
176 public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
177 this(assets, metrics, config, null);
181 * Creates a new Resources object with CompatibilityInfo.
183 * @param assets Previously created AssetManager.
184 * @param metrics Current display metrics to consider when
185 * selecting/computing resource values.
186 * @param config Desired device configuration to consider when
187 * selecting/computing resource values (optional).
188 * @param compInfo this resource's compatibility info. It will use the default compatibility
189 * info when it's null.
192 public Resources(AssetManager assets, DisplayMetrics metrics,
193 Configuration config, CompatibilityInfo compInfo) {
195 mMetrics.setToDefaults();
196 mCompatibilityInfo = compInfo;
197 updateConfiguration(config, metrics);
198 assets.ensureStringBlocks();
202 * Return a global shared Resources object that provides access to only
203 * system resources (no application resources), and is not configured for
204 * the current screen (can not use dimension units, does not change based
205 * on orientation, etc).
207 public static Resources getSystem() {
208 synchronized (sSync) {
209 Resources ret = mSystem;
211 ret = new Resources();
220 * Return the string value associated with a particular resource ID. The
221 * returned object will be a String if this is a plain string; it will be
222 * some other type of CharSequence if it is styled.
225 * @param id The desired resource identifier, as generated by the aapt
226 * tool. This integer encodes the package, type, and resource
227 * entry. The value 0 is an invalid identifier.
229 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
231 * @return CharSequence The string data associated with the resource, plus
232 * possibly styled text information.
234 public CharSequence getText(int id) throws NotFoundException {
235 CharSequence res = mAssets.getResourceText(id);
239 throw new NotFoundException("String resource ID #0x"
240 + Integer.toHexString(id));
244 * Returns the character sequence necessary for grammatically correct pluralization
245 * of the given resource ID for the given quantity.
246 * Note that the character sequence is selected based solely on grammatical necessity,
247 * and that such rules differ between languages. Do not assume you know which string
248 * will be returned for a given quantity. See
249 * <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String Resources</a>
252 * @param id The desired resource identifier, as generated by the aapt
253 * tool. This integer encodes the package, type, and resource
254 * entry. The value 0 is an invalid identifier.
255 * @param quantity The number used to get the correct string for the current language's
258 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
260 * @return CharSequence The string data associated with the resource, plus
261 * possibly styled text information.
263 public CharSequence getQuantityText(int id, int quantity) throws NotFoundException {
264 NativePluralRules rule = getPluralRule();
265 CharSequence res = mAssets.getResourceBagText(id,
266 attrForQuantityCode(rule.quantityForInt(quantity)));
270 res = mAssets.getResourceBagText(id, ID_OTHER);
274 throw new NotFoundException("Plural resource ID #0x" + Integer.toHexString(id)
275 + " quantity=" + quantity
276 + " item=" + stringForQuantityCode(rule.quantityForInt(quantity)));
279 private NativePluralRules getPluralRule() {
280 synchronized (sSync) {
281 if (mPluralRule == null) {
282 mPluralRule = NativePluralRules.forLocale(mConfiguration.locale);
288 private static int attrForQuantityCode(int quantityCode) {
289 switch (quantityCode) {
290 case NativePluralRules.ZERO: return 0x01000005;
291 case NativePluralRules.ONE: return 0x01000006;
292 case NativePluralRules.TWO: return 0x01000007;
293 case NativePluralRules.FEW: return 0x01000008;
294 case NativePluralRules.MANY: return 0x01000009;
295 default: return ID_OTHER;
299 private static String stringForQuantityCode(int quantityCode) {
300 switch (quantityCode) {
301 case NativePluralRules.ZERO: return "zero";
302 case NativePluralRules.ONE: return "one";
303 case NativePluralRules.TWO: return "two";
304 case NativePluralRules.FEW: return "few";
305 case NativePluralRules.MANY: return "many";
306 default: return "other";
311 * Return the string value associated with a particular resource ID. It
312 * will be stripped of any styled text information.
315 * @param id The desired resource identifier, as generated by the aapt
316 * tool. This integer encodes the package, type, and resource
317 * entry. The value 0 is an invalid identifier.
319 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
321 * @return String The string data associated with the resource,
322 * stripped of styled text information.
324 public String getString(int id) throws NotFoundException {
325 CharSequence res = getText(id);
327 return res.toString();
329 throw new NotFoundException("String resource ID #0x"
330 + Integer.toHexString(id));
335 * Return the string value associated with a particular resource ID,
336 * substituting the format arguments as defined in {@link java.util.Formatter}
337 * and {@link java.lang.String#format}. It will be stripped of any styled text
341 * @param id The desired resource identifier, as generated by the aapt
342 * tool. This integer encodes the package, type, and resource
343 * entry. The value 0 is an invalid identifier.
345 * @param formatArgs The format arguments that will be used for substitution.
347 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
349 * @return String The string data associated with the resource,
350 * stripped of styled text information.
352 public String getString(int id, Object... formatArgs) throws NotFoundException {
353 String raw = getString(id);
354 return String.format(mConfiguration.locale, raw, formatArgs);
358 * Formats the string necessary for grammatically correct pluralization
359 * of the given resource ID for the given quantity, using the given arguments.
360 * Note that the string is selected based solely on grammatical necessity,
361 * and that such rules differ between languages. Do not assume you know which string
362 * will be returned for a given quantity. See
363 * <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String Resources</a>
366 * <p>Substitution of format arguments works as if using
367 * {@link java.util.Formatter} and {@link java.lang.String#format}.
368 * The resulting string will be stripped of any styled text information.
370 * @param id The desired resource identifier, as generated by the aapt
371 * tool. This integer encodes the package, type, and resource
372 * entry. The value 0 is an invalid identifier.
373 * @param quantity The number used to get the correct string for the current language's
375 * @param formatArgs The format arguments that will be used for substitution.
377 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
379 * @return String The string data associated with the resource,
380 * stripped of styled text information.
382 public String getQuantityString(int id, int quantity, Object... formatArgs)
383 throws NotFoundException {
384 String raw = getQuantityText(id, quantity).toString();
385 return String.format(mConfiguration.locale, raw, formatArgs);
389 * Returns the string necessary for grammatically correct pluralization
390 * of the given resource ID for the given quantity.
391 * Note that the string is selected based solely on grammatical necessity,
392 * and that such rules differ between languages. Do not assume you know which string
393 * will be returned for a given quantity. See
394 * <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String Resources</a>
397 * @param id The desired resource identifier, as generated by the aapt
398 * tool. This integer encodes the package, type, and resource
399 * entry. The value 0 is an invalid identifier.
400 * @param quantity The number used to get the correct string for the current language's
403 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
405 * @return String The string data associated with the resource,
406 * stripped of styled text information.
408 public String getQuantityString(int id, int quantity) throws NotFoundException {
409 return getQuantityText(id, quantity).toString();
413 * Return the string value associated with a particular resource ID. The
414 * returned object will be a String if this is a plain string; it will be
415 * some other type of CharSequence if it is styled.
417 * @param id The desired resource identifier, as generated by the aapt
418 * tool. This integer encodes the package, type, and resource
419 * entry. The value 0 is an invalid identifier.
421 * @param def The default CharSequence to return.
423 * @return CharSequence The string data associated with the resource, plus
424 * possibly styled text information, or def if id is 0 or not found.
426 public CharSequence getText(int id, CharSequence def) {
427 CharSequence res = id != 0 ? mAssets.getResourceText(id) : null;
428 return res != null ? res : def;
432 * Return the styled text array associated with a particular resource ID.
434 * @param id The desired resource identifier, as generated by the aapt
435 * tool. This integer encodes the package, type, and resource
436 * entry. The value 0 is an invalid identifier.
438 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
440 * @return The styled text array associated with the resource.
442 public CharSequence[] getTextArray(int id) throws NotFoundException {
443 CharSequence[] res = mAssets.getResourceTextArray(id);
447 throw new NotFoundException("Text array resource ID #0x"
448 + Integer.toHexString(id));
452 * Return the string array associated with a particular resource ID.
454 * @param id The desired resource identifier, as generated by the aapt
455 * tool. This integer encodes the package, type, and resource
456 * entry. The value 0 is an invalid identifier.
458 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
460 * @return The string array associated with the resource.
462 public String[] getStringArray(int id) throws NotFoundException {
463 String[] res = mAssets.getResourceStringArray(id);
467 throw new NotFoundException("String array resource ID #0x"
468 + Integer.toHexString(id));
472 * Return the int array associated with a particular resource ID.
474 * @param id The desired resource identifier, as generated by the aapt
475 * tool. This integer encodes the package, type, and resource
476 * entry. The value 0 is an invalid identifier.
478 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
480 * @return The int array associated with the resource.
482 public int[] getIntArray(int id) throws NotFoundException {
483 int[] res = mAssets.getArrayIntResource(id);
487 throw new NotFoundException("Int array resource ID #0x"
488 + Integer.toHexString(id));
492 * Return an array of heterogeneous values.
494 * @param id The desired resource identifier, as generated by the aapt
495 * tool. This integer encodes the package, type, and resource
496 * entry. The value 0 is an invalid identifier.
498 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
500 * @return Returns a TypedArray holding an array of the array values.
501 * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
504 public TypedArray obtainTypedArray(int id) throws NotFoundException {
505 int len = mAssets.getArraySize(id);
507 throw new NotFoundException("Array resource ID #0x"
508 + Integer.toHexString(id));
511 TypedArray array = getCachedStyledAttributes(len);
512 array.mLength = mAssets.retrieveArray(id, array.mData);
513 array.mIndices[0] = 0;
519 * Retrieve a dimensional for a particular resource ID. Unit
520 * conversions are based on the current {@link DisplayMetrics} associated
521 * with the resources.
523 * @param id The desired resource identifier, as generated by the aapt
524 * tool. This integer encodes the package, type, and resource
525 * entry. The value 0 is an invalid identifier.
527 * @return Resource dimension value multiplied by the appropriate
530 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
532 * @see #getDimensionPixelOffset
533 * @see #getDimensionPixelSize
535 public float getDimension(int id) throws NotFoundException {
536 synchronized (mAccessLock) {
537 TypedValue value = mTmpValue;
539 mTmpValue = value = new TypedValue();
541 getValue(id, value, true);
542 if (value.type == TypedValue.TYPE_DIMENSION) {
543 return TypedValue.complexToDimension(value.data, mMetrics);
545 throw new NotFoundException(
546 "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
547 + Integer.toHexString(value.type) + " is not valid");
552 * Retrieve a dimensional for a particular resource ID for use
553 * as an offset in raw pixels. This is the same as
554 * {@link #getDimension}, except the returned value is converted to
555 * integer pixels for you. An offset conversion involves simply
556 * truncating the base value to an integer.
558 * @param id The desired resource identifier, as generated by the aapt
559 * tool. This integer encodes the package, type, and resource
560 * entry. The value 0 is an invalid identifier.
562 * @return Resource dimension value multiplied by the appropriate
563 * metric and truncated to integer pixels.
565 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
568 * @see #getDimensionPixelSize
570 public int getDimensionPixelOffset(int id) throws NotFoundException {
571 synchronized (mAccessLock) {
572 TypedValue value = mTmpValue;
574 mTmpValue = value = new TypedValue();
576 getValue(id, value, true);
577 if (value.type == TypedValue.TYPE_DIMENSION) {
578 return TypedValue.complexToDimensionPixelOffset(
579 value.data, mMetrics);
581 throw new NotFoundException(
582 "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
583 + Integer.toHexString(value.type) + " is not valid");
588 * Retrieve a dimensional for a particular resource ID for use
589 * as a size in raw pixels. This is the same as
590 * {@link #getDimension}, except the returned value is converted to
591 * integer pixels for use as a size. A size conversion involves
592 * rounding the base value, and ensuring that a non-zero base value
593 * is at least one pixel in size.
595 * @param id The desired resource identifier, as generated by the aapt
596 * tool. This integer encodes the package, type, and resource
597 * entry. The value 0 is an invalid identifier.
599 * @return Resource dimension value multiplied by the appropriate
600 * metric and truncated to integer pixels.
602 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
605 * @see #getDimensionPixelOffset
607 public int getDimensionPixelSize(int id) throws NotFoundException {
608 synchronized (mAccessLock) {
609 TypedValue value = mTmpValue;
611 mTmpValue = value = new TypedValue();
613 getValue(id, value, true);
614 if (value.type == TypedValue.TYPE_DIMENSION) {
615 return TypedValue.complexToDimensionPixelSize(
616 value.data, mMetrics);
618 throw new NotFoundException(
619 "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
620 + Integer.toHexString(value.type) + " is not valid");
625 * Retrieve a fractional unit for a particular resource ID.
627 * @param id The desired resource identifier, as generated by the aapt
628 * tool. This integer encodes the package, type, and resource
629 * entry. The value 0 is an invalid identifier.
630 * @param base The base value of this fraction. In other words, a
631 * standard fraction is multiplied by this value.
632 * @param pbase The parent base value of this fraction. In other
633 * words, a parent fraction (nn%p) is multiplied by this
636 * @return Attribute fractional value multiplied by the appropriate
639 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
641 public float getFraction(int id, int base, int pbase) {
642 synchronized (mAccessLock) {
643 TypedValue value = mTmpValue;
645 mTmpValue = value = new TypedValue();
647 getValue(id, value, true);
648 if (value.type == TypedValue.TYPE_FRACTION) {
649 return TypedValue.complexToFraction(value.data, base, pbase);
651 throw new NotFoundException(
652 "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
653 + Integer.toHexString(value.type) + " is not valid");
658 * Return a drawable object associated with a particular resource ID.
659 * Various types of objects will be returned depending on the underlying
660 * resource -- for example, a solid color, PNG image, scalable image, etc.
661 * The Drawable API hides these implementation details.
663 * <p class="note"><strong>Note:</strong> Prior to
664 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN}, this function
665 * would not correctly retrieve the final configuration density when
666 * the resource ID passed here is an alias to another Drawable resource.
667 * This means that if the density configuration of the alias resource
668 * is different than the actual resource, the density of the returned
669 * Drawable would be incorrect, resulting in bad scaling. To work
670 * around this, you can instead retrieve the Drawable through
671 * {@link TypedArray#getDrawable TypedArray.getDrawable}. Use
672 * {@link android.content.Context#obtainStyledAttributes(int[])
673 * Context.obtainStyledAttributes} with
674 * an array containing the resource ID of interest to create the TypedArray.</p>
676 * @param id The desired resource identifier, as generated by the aapt
677 * tool. This integer encodes the package, type, and resource
678 * entry. The value 0 is an invalid identifier.
680 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
682 * @return Drawable An object that can be used to draw this resource.
684 public Drawable getDrawable(int id) throws NotFoundException {
686 synchronized (mAccessLock) {
689 value = new TypedValue();
693 getValue(id, value, true);
695 Drawable res = loadDrawable(value, id);
696 synchronized (mAccessLock) {
697 if (mTmpValue == null) {
705 * Return a drawable object associated with a particular resource ID for the
706 * given screen density in DPI. This will set the drawable's density to be
707 * the device's density multiplied by the ratio of actual drawable density
708 * to requested density. This allows the drawable to be scaled up to the
709 * correct size if needed. Various types of objects will be returned
710 * depending on the underlying resource -- for example, a solid color, PNG
711 * image, scalable image, etc. The Drawable API hides these implementation
714 * @param id The desired resource identifier, as generated by the aapt tool.
715 * This integer encodes the package, type, and resource entry.
716 * The value 0 is an invalid identifier.
717 * @param density the desired screen density indicated by the resource as
718 * found in {@link DisplayMetrics}.
719 * @throws NotFoundException Throws NotFoundException if the given ID does
721 * @return Drawable An object that can be used to draw this resource.
723 public Drawable getDrawableForDensity(int id, int density) throws NotFoundException {
725 synchronized (mAccessLock) {
728 value = new TypedValue();
732 getValueForDensity(id, density, value, true);
735 * Pretend the requested density is actually the display density. If
736 * the drawable returned is not the requested density, then force it
737 * to be scaled later by dividing its density by the ratio of
738 * requested density to actual device density. Drawables that have
739 * undefined density or no density don't need to be handled here.
741 if (value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
742 if (value.density == density) {
743 value.density = mMetrics.densityDpi;
745 value.density = (value.density * mMetrics.densityDpi) / density;
750 Drawable res = loadDrawable(value, id);
751 synchronized (mAccessLock) {
752 if (mTmpValue == null) {
760 * Return a movie object associated with the particular resource ID.
761 * @param id The desired resource identifier, as generated by the aapt
762 * tool. This integer encodes the package, type, and resource
763 * entry. The value 0 is an invalid identifier.
764 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
767 public Movie getMovie(int id) throws NotFoundException {
768 InputStream is = openRawResource(id);
769 Movie movie = Movie.decodeStream(is);
773 catch (java.io.IOException e) {
774 // don't care, since the return value is valid
780 * Return a color integer associated with a particular resource ID.
781 * If the resource holds a complex
782 * {@link android.content.res.ColorStateList}, then the default color from
783 * the set is returned.
785 * @param id The desired resource identifier, as generated by the aapt
786 * tool. This integer encodes the package, type, and resource
787 * entry. The value 0 is an invalid identifier.
789 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
791 * @return Returns a single color value in the form 0xAARRGGBB.
793 public int getColor(int id) throws NotFoundException {
795 synchronized (mAccessLock) {
798 value = new TypedValue();
800 getValue(id, value, true);
801 if (value.type >= TypedValue.TYPE_FIRST_INT
802 && value.type <= TypedValue.TYPE_LAST_INT) {
805 } else if (value.type != TypedValue.TYPE_STRING) {
806 throw new NotFoundException(
807 "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
808 + Integer.toHexString(value.type) + " is not valid");
812 ColorStateList csl = loadColorStateList(value, id);
813 synchronized (mAccessLock) {
814 if (mTmpValue == null) {
818 return csl.getDefaultColor();
822 * Return a color state list associated with a particular resource ID. The
823 * resource may contain either a single raw color value, or a complex
824 * {@link android.content.res.ColorStateList} holding multiple possible colors.
826 * @param id The desired resource identifier of a {@link ColorStateList},
827 * as generated by the aapt tool. This integer encodes the package, type, and resource
828 * entry. The value 0 is an invalid identifier.
830 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
832 * @return Returns a ColorStateList object containing either a single
833 * solid color or multiple colors that can be selected based on a state.
835 public ColorStateList getColorStateList(int id) throws NotFoundException {
837 synchronized (mAccessLock) {
840 value = new TypedValue();
844 getValue(id, value, true);
846 ColorStateList res = loadColorStateList(value, id);
847 synchronized (mAccessLock) {
848 if (mTmpValue == null) {
856 * Return a boolean associated with a particular resource ID. This can be
857 * used with any integral resource value, and will return true if it is
860 * @param id The desired resource identifier, as generated by the aapt
861 * tool. This integer encodes the package, type, and resource
862 * entry. The value 0 is an invalid identifier.
864 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
866 * @return Returns the boolean value contained in the resource.
868 public boolean getBoolean(int id) throws NotFoundException {
869 synchronized (mAccessLock) {
870 TypedValue value = mTmpValue;
872 mTmpValue = value = new TypedValue();
874 getValue(id, value, true);
875 if (value.type >= TypedValue.TYPE_FIRST_INT
876 && value.type <= TypedValue.TYPE_LAST_INT) {
877 return value.data != 0;
879 throw new NotFoundException(
880 "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
881 + Integer.toHexString(value.type) + " is not valid");
886 * Return an integer associated with a particular resource ID.
888 * @param id The desired resource identifier, as generated by the aapt
889 * tool. This integer encodes the package, type, and resource
890 * entry. The value 0 is an invalid identifier.
892 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
894 * @return Returns the integer value contained in the resource.
896 public int getInteger(int id) throws NotFoundException {
897 synchronized (mAccessLock) {
898 TypedValue value = mTmpValue;
900 mTmpValue = value = new TypedValue();
902 getValue(id, value, true);
903 if (value.type >= TypedValue.TYPE_FIRST_INT
904 && value.type <= TypedValue.TYPE_LAST_INT) {
907 throw new NotFoundException(
908 "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
909 + Integer.toHexString(value.type) + " is not valid");
914 * Return an XmlResourceParser through which you can read a view layout
915 * description for the given resource ID. This parser has limited
916 * functionality -- in particular, you can't change its input, and only
917 * the high-level events are available.
919 * <p>This function is really a simple wrapper for calling
920 * {@link #getXml} with a layout resource.
922 * @param id The desired resource identifier, as generated by the aapt
923 * tool. This integer encodes the package, type, and resource
924 * entry. The value 0 is an invalid identifier.
926 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
928 * @return A new parser object through which you can read
933 public XmlResourceParser getLayout(int id) throws NotFoundException {
934 return loadXmlResourceParser(id, "layout");
938 * Return an XmlResourceParser through which you can read an animation
939 * description for the given resource ID. This parser has limited
940 * functionality -- in particular, you can't change its input, and only
941 * the high-level events are available.
943 * <p>This function is really a simple wrapper for calling
944 * {@link #getXml} with an animation resource.
946 * @param id The desired resource identifier, as generated by the aapt
947 * tool. This integer encodes the package, type, and resource
948 * entry. The value 0 is an invalid identifier.
950 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
952 * @return A new parser object through which you can read
957 public XmlResourceParser getAnimation(int id) throws NotFoundException {
958 return loadXmlResourceParser(id, "anim");
962 * Return an XmlResourceParser through which you can read a generic XML
963 * resource for the given resource ID.
965 * <p>The XmlPullParser implementation returned here has some limited
966 * functionality. In particular, you can't change its input, and only
967 * high-level parsing events are available (since the document was
968 * pre-parsed for you at build time, which involved merging text and
969 * stripping comments).
971 * @param id The desired resource identifier, as generated by the aapt
972 * tool. This integer encodes the package, type, and resource
973 * entry. The value 0 is an invalid identifier.
975 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
977 * @return A new parser object through which you can read
980 * @see android.util.AttributeSet
982 public XmlResourceParser getXml(int id) throws NotFoundException {
983 return loadXmlResourceParser(id, "xml");
987 * Open a data stream for reading a raw resource. This can only be used
988 * with resources whose value is the name of an asset files -- that is, it can be
989 * used to open drawable, sound, and raw resources; it will fail on string
990 * and color resources.
992 * @param id The resource identifier to open, as generated by the appt
995 * @return InputStream Access to the resource data.
997 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1000 public InputStream openRawResource(int id) throws NotFoundException {
1002 synchronized (mAccessLock) {
1004 if (value == null) {
1005 value = new TypedValue();
1010 InputStream res = openRawResource(id, value);
1011 synchronized (mAccessLock) {
1012 if (mTmpValue == null) {
1020 * Open a data stream for reading a raw resource. This can only be used
1021 * with resources whose value is the name of an asset file -- that is, it can be
1022 * used to open drawable, sound, and raw resources; it will fail on string
1023 * and color resources.
1025 * @param id The resource identifier to open, as generated by the appt tool.
1026 * @param value The TypedValue object to hold the resource information.
1028 * @return InputStream Access to the resource data.
1030 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1032 public InputStream openRawResource(int id, TypedValue value) throws NotFoundException {
1033 getValue(id, value, true);
1036 return mAssets.openNonAsset(value.assetCookie, value.string.toString(),
1037 AssetManager.ACCESS_STREAMING);
1038 } catch (Exception e) {
1039 NotFoundException rnf = new NotFoundException("File " + value.string.toString() +
1040 " from drawable resource ID #0x" + Integer.toHexString(id));
1047 * Open a file descriptor for reading a raw resource. This can only be used
1048 * with resources whose value is the name of an asset files -- that is, it can be
1049 * used to open drawable, sound, and raw resources; it will fail on string
1050 * and color resources.
1052 * <p>This function only works for resources that are stored in the package
1053 * as uncompressed data, which typically includes things like mp3 files
1056 * @param id The resource identifier to open, as generated by the appt
1059 * @return AssetFileDescriptor A new file descriptor you can use to read
1060 * the resource. This includes the file descriptor itself, as well as the
1061 * offset and length of data where the resource appears in the file. A
1062 * null is returned if the file exists but is compressed.
1064 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1067 public AssetFileDescriptor openRawResourceFd(int id) throws NotFoundException {
1069 synchronized (mAccessLock) {
1071 if (value == null) {
1072 value = new TypedValue();
1076 getValue(id, value, true);
1079 return mAssets.openNonAssetFd(
1080 value.assetCookie, value.string.toString());
1081 } catch (Exception e) {
1082 NotFoundException rnf = new NotFoundException(
1083 "File " + value.string.toString()
1084 + " from drawable resource ID #0x"
1085 + Integer.toHexString(id));
1089 synchronized (mAccessLock) {
1090 if (mTmpValue == null) {
1098 * Return the raw data associated with a particular resource ID.
1100 * @param id The desired resource identifier, as generated by the aapt
1101 * tool. This integer encodes the package, type, and resource
1102 * entry. The value 0 is an invalid identifier.
1103 * @param outValue Object in which to place the resource data.
1104 * @param resolveRefs If true, a resource that is a reference to another
1105 * resource will be followed so that you receive the
1106 * actual final resource data. If false, the TypedValue
1107 * will be filled in with the reference itself.
1109 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1112 public void getValue(int id, TypedValue outValue, boolean resolveRefs)
1113 throws NotFoundException {
1114 boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
1118 throw new NotFoundException("Resource ID #0x"
1119 + Integer.toHexString(id));
1123 * Get the raw value associated with a resource with associated density.
1125 * @param id resource identifier
1126 * @param density density in DPI
1127 * @param resolveRefs If true, a resource that is a reference to another
1128 * resource will be followed so that you receive the actual final
1129 * resource data. If false, the TypedValue will be filled in with
1130 * the reference itself.
1131 * @throws NotFoundException Throws NotFoundException if the given ID does
1133 * @see #getValue(String, TypedValue, boolean)
1135 public void getValueForDensity(int id, int density, TypedValue outValue, boolean resolveRefs)
1136 throws NotFoundException {
1137 boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
1141 throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
1145 * Return the raw data associated with a particular resource ID.
1146 * See getIdentifier() for information on how names are mapped to resource
1147 * IDs, and getString(int) for information on how string resources are
1150 * <p>Note: use of this function is discouraged. It is much more
1151 * efficient to retrieve resources by identifier than by name.
1153 * @param name The name of the desired resource. This is passed to
1154 * getIdentifier() with a default type of "string".
1155 * @param outValue Object in which to place the resource data.
1156 * @param resolveRefs If true, a resource that is a reference to another
1157 * resource will be followed so that you receive the
1158 * actual final resource data. If false, the TypedValue
1159 * will be filled in with the reference itself.
1161 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1164 public void getValue(String name, TypedValue outValue, boolean resolveRefs)
1165 throws NotFoundException {
1166 int id = getIdentifier(name, "string", null);
1168 getValue(id, outValue, resolveRefs);
1171 throw new NotFoundException("String resource name " + name);
1175 * This class holds the current attribute values for a particular theme.
1176 * In other words, a Theme is a set of values for resource attributes;
1177 * these are used in conjunction with {@link TypedArray}
1178 * to resolve the final value for an attribute.
1180 * <p>The Theme's attributes come into play in two ways: (1) a styled
1181 * attribute can explicit reference a value in the theme through the
1182 * "?themeAttribute" syntax; (2) if no value has been defined for a
1183 * particular styled attribute, as a last resort we will try to find that
1184 * attribute's value in the Theme.
1186 * <p>You will normally use the {@link #obtainStyledAttributes} APIs to
1187 * retrieve XML attributes with style and theme information applied.
1189 public final class Theme {
1191 * Place new attribute values into the theme. The style resource
1192 * specified by <var>resid</var> will be retrieved from this Theme's
1193 * resources, its values placed into the Theme object.
1195 * <p>The semantics of this function depends on the <var>force</var>
1196 * argument: If false, only values that are not already defined in
1197 * the theme will be copied from the system resource; otherwise, if
1198 * any of the style's attributes are already defined in the theme, the
1199 * current values in the theme will be overwritten.
1201 * @param resid The resource ID of a style resource from which to
1202 * obtain attribute values.
1203 * @param force If true, values in the style resource will always be
1204 * used in the theme; otherwise, they will only be used
1205 * if not already defined in the theme.
1207 public void applyStyle(int resid, boolean force) {
1208 AssetManager.applyThemeStyle(mTheme, resid, force);
1212 * Set this theme to hold the same contents as the theme
1213 * <var>other</var>. If both of these themes are from the same
1214 * Resources object, they will be identical after this function
1215 * returns. If they are from different Resources, only the resources
1216 * they have in common will be set in this theme.
1218 * @param other The existing Theme to copy from.
1220 public void setTo(Theme other) {
1221 AssetManager.copyTheme(mTheme, other.mTheme);
1225 * Return a TypedArray holding the values defined by
1226 * <var>Theme</var> which are listed in <var>attrs</var>.
1228 * <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done
1231 * @param attrs The desired attributes.
1233 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1235 * @return Returns a TypedArray holding an array of the attribute values.
1236 * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
1237 * when done with it.
1239 * @see Resources#obtainAttributes
1240 * @see #obtainStyledAttributes(int, int[])
1241 * @see #obtainStyledAttributes(AttributeSet, int[], int, int)
1243 public TypedArray obtainStyledAttributes(int[] attrs) {
1244 int len = attrs.length;
1245 TypedArray array = getCachedStyledAttributes(len);
1246 array.mRsrcs = attrs;
1247 AssetManager.applyStyle(mTheme, 0, 0, 0, attrs,
1248 array.mData, array.mIndices);
1253 * Return a TypedArray holding the values defined by the style
1254 * resource <var>resid</var> which are listed in <var>attrs</var>.
1256 * <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done
1259 * @param resid The desired style resource.
1260 * @param attrs The desired attributes in the style.
1262 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1264 * @return Returns a TypedArray holding an array of the attribute values.
1265 * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
1266 * when done with it.
1268 * @see Resources#obtainAttributes
1269 * @see #obtainStyledAttributes(int[])
1270 * @see #obtainStyledAttributes(AttributeSet, int[], int, int)
1272 public TypedArray obtainStyledAttributes(int resid, int[] attrs)
1273 throws NotFoundException {
1274 int len = attrs.length;
1275 TypedArray array = getCachedStyledAttributes(len);
1276 array.mRsrcs = attrs;
1278 AssetManager.applyStyle(mTheme, 0, resid, 0, attrs,
1279 array.mData, array.mIndices);
1281 int[] data = array.mData;
1283 System.out.println("**********************************************************");
1284 System.out.println("**********************************************************");
1285 System.out.println("**********************************************************");
1286 System.out.println("Attributes:");
1287 String s = " Attrs:";
1289 for (i=0; i<attrs.length; i++) {
1290 s = s + " 0x" + Integer.toHexString(attrs[i]);
1292 System.out.println(s);
1294 TypedValue value = new TypedValue();
1295 for (i=0; i<attrs.length; i++) {
1296 int d = i*AssetManager.STYLE_NUM_ENTRIES;
1297 value.type = data[d+AssetManager.STYLE_TYPE];
1298 value.data = data[d+AssetManager.STYLE_DATA];
1299 value.assetCookie = data[d+AssetManager.STYLE_ASSET_COOKIE];
1300 value.resourceId = data[d+AssetManager.STYLE_RESOURCE_ID];
1301 s = s + " 0x" + Integer.toHexString(attrs[i])
1304 System.out.println(s);
1310 * Return a TypedArray holding the attribute values in
1312 * that are listed in <var>attrs</var>. In addition, if the given
1313 * AttributeSet specifies a style class (through the "style" attribute),
1314 * that style will be applied on top of the base attributes it defines.
1316 * <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done
1319 * <p>When determining the final value of a particular attribute, there
1320 * are four inputs that come into play:</p>
1323 * <li> Any attribute values in the given AttributeSet.
1324 * <li> The style resource specified in the AttributeSet (named
1326 * <li> The default style specified by <var>defStyleAttr</var> and
1327 * <var>defStyleRes</var>
1328 * <li> The base values in this theme.
1331 * <p>Each of these inputs is considered in-order, with the first listed
1332 * taking precedence over the following ones. In other words, if in the
1333 * AttributeSet you have supplied <code><Button
1334 * textColor="#ff000000"></code>, then the button's text will
1335 * <em>always</em> be black, regardless of what is specified in any of
1338 * @param set The base set of attribute values. May be null.
1339 * @param attrs The desired attributes to be retrieved.
1340 * @param defStyleAttr An attribute in the current theme that contains a
1341 * reference to a style resource that supplies
1342 * defaults values for the TypedArray. Can be
1343 * 0 to not look for defaults.
1344 * @param defStyleRes A resource identifier of a style resource that
1345 * supplies default values for the TypedArray,
1346 * used only if defStyleAttr is 0 or can not be found
1347 * in the theme. Can be 0 to not look for defaults.
1349 * @return Returns a TypedArray holding an array of the attribute values.
1350 * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
1351 * when done with it.
1353 * @see Resources#obtainAttributes
1354 * @see #obtainStyledAttributes(int[])
1355 * @see #obtainStyledAttributes(int, int[])
1357 public TypedArray obtainStyledAttributes(AttributeSet set,
1358 int[] attrs, int defStyleAttr, int defStyleRes) {
1359 int len = attrs.length;
1360 TypedArray array = getCachedStyledAttributes(len);
1362 // XXX note that for now we only work with compiled XML files.
1363 // To support generic XML files we will need to manually parse
1364 // out the attributes from the XML file (applying type information
1365 // contained in the resources and such).
1366 XmlBlock.Parser parser = (XmlBlock.Parser)set;
1367 AssetManager.applyStyle(
1368 mTheme, defStyleAttr, defStyleRes,
1369 parser != null ? parser.mParseState : 0, attrs,
1370 array.mData, array.mIndices);
1372 array.mRsrcs = attrs;
1373 array.mXml = parser;
1376 int[] data = array.mData;
1378 System.out.println("Attributes:");
1379 String s = " Attrs:";
1381 for (i=0; i<set.getAttributeCount(); i++) {
1382 s = s + " " + set.getAttributeName(i);
1383 int id = set.getAttributeNameResource(i);
1385 s = s + "(0x" + Integer.toHexString(id) + ")";
1387 s = s + "=" + set.getAttributeValue(i);
1389 System.out.println(s);
1391 TypedValue value = new TypedValue();
1392 for (i=0; i<attrs.length; i++) {
1393 int d = i*AssetManager.STYLE_NUM_ENTRIES;
1394 value.type = data[d+AssetManager.STYLE_TYPE];
1395 value.data = data[d+AssetManager.STYLE_DATA];
1396 value.assetCookie = data[d+AssetManager.STYLE_ASSET_COOKIE];
1397 value.resourceId = data[d+AssetManager.STYLE_RESOURCE_ID];
1398 s = s + " 0x" + Integer.toHexString(attrs[i])
1401 System.out.println(s);
1408 * Retrieve the value of an attribute in the Theme. The contents of
1409 * <var>outValue</var> are ultimately filled in by
1410 * {@link Resources#getValue}.
1412 * @param resid The resource identifier of the desired theme
1414 * @param outValue Filled in with the ultimate resource value supplied
1416 * @param resolveRefs If true, resource references will be walked; if
1417 * false, <var>outValue</var> may be a
1418 * TYPE_REFERENCE. In either case, it will never
1419 * be a TYPE_ATTRIBUTE.
1421 * @return boolean Returns true if the attribute was found and
1422 * <var>outValue</var> is valid, else false.
1424 public boolean resolveAttribute(int resid, TypedValue outValue,
1425 boolean resolveRefs) {
1426 boolean got = mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs);
1429 "resolveAttribute #" + Integer.toHexString(resid)
1430 + " got=" + got + ", type=0x" + Integer.toHexString(outValue.type)
1431 + ", data=0x" + Integer.toHexString(outValue.data));
1437 * Print contents of this theme out to the log. For debugging only.
1439 * @param priority The log priority to use.
1440 * @param tag The log tag to use.
1441 * @param prefix Text to prefix each line printed.
1443 public void dump(int priority, String tag, String prefix) {
1444 AssetManager.dumpTheme(mTheme, priority, tag, prefix);
1447 protected void finalize() throws Throwable {
1449 mAssets.releaseTheme(mTheme);
1452 /*package*/ Theme() {
1453 mAssets = Resources.this.mAssets;
1454 mTheme = mAssets.createTheme();
1457 private final AssetManager mAssets;
1458 private final int mTheme;
1462 * Generate a new Theme object for this set of Resources. It initially
1465 * @return Theme The newly created Theme container.
1467 public final Theme newTheme() {
1472 * Retrieve a set of basic attribute values from an AttributeSet, not
1473 * performing styling of them using a theme and/or style resources.
1475 * @param set The current attribute values to retrieve.
1476 * @param attrs The specific attributes to be retrieved.
1477 * @return Returns a TypedArray holding an array of the attribute values.
1478 * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
1479 * when done with it.
1481 * @see Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
1483 public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
1484 int len = attrs.length;
1485 TypedArray array = getCachedStyledAttributes(len);
1487 // XXX note that for now we only work with compiled XML files.
1488 // To support generic XML files we will need to manually parse
1489 // out the attributes from the XML file (applying type information
1490 // contained in the resources and such).
1491 XmlBlock.Parser parser = (XmlBlock.Parser)set;
1492 mAssets.retrieveAttributes(parser.mParseState, attrs,
1493 array.mData, array.mIndices);
1495 array.mRsrcs = attrs;
1496 array.mXml = parser;
1502 * Store the newly updated configuration.
1504 public void updateConfiguration(Configuration config,
1505 DisplayMetrics metrics) {
1506 updateConfiguration(config, metrics, null);
1512 public void updateConfiguration(Configuration config,
1513 DisplayMetrics metrics, CompatibilityInfo compat) {
1514 synchronized (mAccessLock) {
1516 Slog.i(TAG, "**** Updating config of " + this + ": old config is "
1517 + mConfiguration + " old compat is " + mCompatibilityInfo);
1518 Slog.i(TAG, "**** Updating config of " + this + ": new config is "
1519 + config + " new compat is " + compat);
1521 if (compat != null) {
1522 mCompatibilityInfo = compat;
1524 if (metrics != null) {
1525 mMetrics.setTo(metrics);
1527 // NOTE: We should re-arrange this code to create a Display
1528 // with the CompatibilityInfo that is used everywhere we deal
1529 // with the display in relation to this app, rather than
1530 // doing the conversion here. This impl should be okay because
1531 // we make sure to return a compatible display in the places
1532 // where there are public APIs to retrieve the display... but
1533 // it would be cleaner and more maintainble to just be
1534 // consistently dealing with a compatible display everywhere in
1536 if (mCompatibilityInfo != null) {
1537 mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
1539 int configChanges = 0xfffffff;
1540 if (config != null) {
1541 mTmpConfig.setTo(config);
1542 int density = config.densityDpi;
1543 if (density == Configuration.DENSITY_DPI_UNDEFINED) {
1544 density = mMetrics.noncompatDensityDpi;
1546 if (mCompatibilityInfo != null) {
1547 mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
1549 if (mTmpConfig.locale == null) {
1550 mTmpConfig.locale = Locale.getDefault();
1551 mTmpConfig.setLayoutDirection(mTmpConfig.locale);
1553 configChanges = mConfiguration.updateFrom(mTmpConfig);
1554 configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
1556 if (mConfiguration.locale == null) {
1557 mConfiguration.locale = Locale.getDefault();
1558 mConfiguration.setLayoutDirection(mConfiguration.locale);
1560 if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
1561 mMetrics.densityDpi = mConfiguration.densityDpi;
1562 mMetrics.density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
1564 mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
1566 String locale = null;
1567 if (mConfiguration.locale != null) {
1568 locale = mConfiguration.locale.getLanguage();
1569 if (mConfiguration.locale.getCountry() != null) {
1570 locale += "-" + mConfiguration.locale.getCountry();
1574 if (mMetrics.widthPixels >= mMetrics.heightPixels) {
1575 width = mMetrics.widthPixels;
1576 height = mMetrics.heightPixels;
1578 //noinspection SuspiciousNameCombination
1579 width = mMetrics.heightPixels;
1580 //noinspection SuspiciousNameCombination
1581 height = mMetrics.widthPixels;
1583 int keyboardHidden = mConfiguration.keyboardHidden;
1584 if (keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
1585 && mConfiguration.hardKeyboardHidden
1586 == Configuration.HARDKEYBOARDHIDDEN_YES) {
1587 keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT;
1589 mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
1590 locale, mConfiguration.orientation,
1591 mConfiguration.touchscreen,
1592 mConfiguration.densityDpi, mConfiguration.keyboard,
1593 keyboardHidden, mConfiguration.navigation, width, height,
1594 mConfiguration.smallestScreenWidthDp,
1595 mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
1596 mConfiguration.screenLayout, mConfiguration.uiMode,
1597 Build.VERSION.RESOURCES_SDK_INT);
1600 Slog.i(TAG, "**** Updating config of " + this + ": final config is " + mConfiguration
1601 + " final compat is " + mCompatibilityInfo);
1604 clearDrawableCacheLocked(mDrawableCache, configChanges);
1605 clearDrawableCacheLocked(mColorDrawableCache, configChanges);
1607 mColorStateListCache.clear();
1611 synchronized (sSync) {
1612 if (mPluralRule != null) {
1613 mPluralRule = NativePluralRules.forLocale(config.locale);
1618 private void clearDrawableCacheLocked(
1619 LongSparseArray<WeakReference<ConstantState>> cache,
1620 int configChanges) {
1621 int N = cache.size();
1623 Log.d(TAG, "Cleaning up drawables config changes: 0x"
1624 + Integer.toHexString(configChanges));
1626 for (int i=0; i<N; i++) {
1627 WeakReference<Drawable.ConstantState> ref = cache.valueAt(i);
1629 Drawable.ConstantState cs = ref.get();
1631 if (Configuration.needNewResources(
1632 configChanges, cs.getChangingConfigurations())) {
1634 Log.d(TAG, "FLUSHING #0x"
1635 + Long.toHexString(mDrawableCache.keyAt(i))
1636 + " / " + cs + " with changes: 0x"
1637 + Integer.toHexString(cs.getChangingConfigurations()));
1639 cache.setValueAt(i, null);
1640 } else if (DEBUG_CONFIG) {
1641 Log.d(TAG, "(Keeping #0x"
1642 + Long.toHexString(cache.keyAt(i))
1643 + " / " + cs + " with changes: 0x"
1644 + Integer.toHexString(cs.getChangingConfigurations())
1653 * Update the system resources configuration if they have previously
1658 public static void updateSystemConfiguration(Configuration config, DisplayMetrics metrics,
1659 CompatibilityInfo compat) {
1660 if (mSystem != null) {
1661 mSystem.updateConfiguration(config, metrics, compat);
1662 //Log.i(TAG, "Updated system resources " + mSystem
1663 // + ": " + mSystem.getConfiguration());
1670 public static void updateSystemConfiguration(Configuration config, DisplayMetrics metrics) {
1671 updateSystemConfiguration(config, metrics, null);
1675 * Return the current display metrics that are in effect for this resource
1676 * object. The returned object should be treated as read-only.
1678 * @return The resource's current display metrics.
1680 public DisplayMetrics getDisplayMetrics() {
1681 if (DEBUG_CONFIG) Slog.v(TAG, "Returning DisplayMetrics: " + mMetrics.widthPixels
1682 + "x" + mMetrics.heightPixels + " " + mMetrics.density);
1687 * Return the current configuration that is in effect for this resource
1688 * object. The returned object should be treated as read-only.
1690 * @return The resource's current configuration.
1692 public Configuration getConfiguration() {
1693 return mConfiguration;
1697 * Return the compatibility mode information for the application.
1698 * The returned object should be treated as read-only.
1700 * @return compatibility info.
1703 public CompatibilityInfo getCompatibilityInfo() {
1704 return mCompatibilityInfo != null ? mCompatibilityInfo
1705 : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
1709 * This is just for testing.
1712 public void setCompatibilityInfo(CompatibilityInfo ci) {
1713 mCompatibilityInfo = ci;
1714 updateConfiguration(mConfiguration, mMetrics);
1718 * Return a resource identifier for the given resource name. A fully
1719 * qualified resource name is of the form "package:type/entry". The first
1720 * two components (package and type) are optional if defType and
1721 * defPackage, respectively, are specified here.
1723 * <p>Note: use of this function is discouraged. It is much more
1724 * efficient to retrieve resources by identifier than by name.
1726 * @param name The name of the desired resource.
1727 * @param defType Optional default resource type to find, if "type/" is
1728 * not included in the name. Can be null to require an
1730 * @param defPackage Optional default package to find, if "package:" is
1731 * not included in the name. Can be null to require an
1734 * @return int The associated resource identifier. Returns 0 if no such
1735 * resource was found. (0 is not a valid resource ID.)
1737 public int getIdentifier(String name, String defType, String defPackage) {
1739 throw new NullPointerException("name is null");
1742 return Integer.parseInt(name);
1743 } catch (Exception e) {
1746 return mAssets.getResourceIdentifier(name, defType, defPackage);
1750 * Return true if given resource identifier includes a package.
1754 public static boolean resourceHasPackage(int resid) {
1755 return (resid >>> 24) != 0;
1759 * Return the full name for a given resource identifier. This name is
1760 * a single string of the form "package:type/entry".
1762 * @param resid The resource identifier whose name is to be retrieved.
1764 * @return A string holding the name of the resource.
1766 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1768 * @see #getResourcePackageName
1769 * @see #getResourceTypeName
1770 * @see #getResourceEntryName
1772 public String getResourceName(int resid) throws NotFoundException {
1773 String str = mAssets.getResourceName(resid);
1774 if (str != null) return str;
1775 throw new NotFoundException("Unable to find resource ID #0x"
1776 + Integer.toHexString(resid));
1780 * Return the package name for a given resource identifier.
1782 * @param resid The resource identifier whose package name is to be
1785 * @return A string holding the package name of the resource.
1787 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1789 * @see #getResourceName
1791 public String getResourcePackageName(int resid) throws NotFoundException {
1792 String str = mAssets.getResourcePackageName(resid);
1793 if (str != null) return str;
1794 throw new NotFoundException("Unable to find resource ID #0x"
1795 + Integer.toHexString(resid));
1799 * Return the type name for a given resource identifier.
1801 * @param resid The resource identifier whose type name is to be
1804 * @return A string holding the type name of the resource.
1806 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1808 * @see #getResourceName
1810 public String getResourceTypeName(int resid) throws NotFoundException {
1811 String str = mAssets.getResourceTypeName(resid);
1812 if (str != null) return str;
1813 throw new NotFoundException("Unable to find resource ID #0x"
1814 + Integer.toHexString(resid));
1818 * Return the entry name for a given resource identifier.
1820 * @param resid The resource identifier whose entry name is to be
1823 * @return A string holding the entry name of the resource.
1825 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1827 * @see #getResourceName
1829 public String getResourceEntryName(int resid) throws NotFoundException {
1830 String str = mAssets.getResourceEntryName(resid);
1831 if (str != null) return str;
1832 throw new NotFoundException("Unable to find resource ID #0x"
1833 + Integer.toHexString(resid));
1837 * Parse a series of {@link android.R.styleable#Extra <extra>} tags from
1838 * an XML file. You call this when you are at the parent tag of the
1839 * extra tags, and it will return once all of the child tags have been parsed.
1840 * This will call {@link #parseBundleExtra} for each extra tag encountered.
1842 * @param parser The parser from which to retrieve the extras.
1843 * @param outBundle A Bundle in which to place all parsed extras.
1844 * @throws XmlPullParserException
1845 * @throws IOException
1847 public void parseBundleExtras(XmlResourceParser parser, Bundle outBundle)
1848 throws XmlPullParserException, IOException {
1849 int outerDepth = parser.getDepth();
1851 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1852 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1853 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1857 String nodeName = parser.getName();
1858 if (nodeName.equals("extra")) {
1859 parseBundleExtra("extra", parser, outBundle);
1860 XmlUtils.skipCurrentTag(parser);
1863 XmlUtils.skipCurrentTag(parser);
1869 * Parse a name/value pair out of an XML tag holding that data. The
1870 * AttributeSet must be holding the data defined by
1871 * {@link android.R.styleable#Extra}. The following value types are supported:
1873 * <li> {@link TypedValue#TYPE_STRING}:
1874 * {@link Bundle#putCharSequence Bundle.putCharSequence()}
1875 * <li> {@link TypedValue#TYPE_INT_BOOLEAN}:
1876 * {@link Bundle#putCharSequence Bundle.putBoolean()}
1877 * <li> {@link TypedValue#TYPE_FIRST_INT}-{@link TypedValue#TYPE_LAST_INT}:
1878 * {@link Bundle#putCharSequence Bundle.putBoolean()}
1879 * <li> {@link TypedValue#TYPE_FLOAT}:
1880 * {@link Bundle#putCharSequence Bundle.putFloat()}
1883 * @param tagName The name of the tag these attributes come from; this is
1884 * only used for reporting error messages.
1885 * @param attrs The attributes from which to retrieve the name/value pair.
1886 * @param outBundle The Bundle in which to place the parsed value.
1887 * @throws XmlPullParserException If the attributes are not valid.
1889 public void parseBundleExtra(String tagName, AttributeSet attrs,
1890 Bundle outBundle) throws XmlPullParserException {
1891 TypedArray sa = obtainAttributes(attrs,
1892 com.android.internal.R.styleable.Extra);
1894 String name = sa.getString(
1895 com.android.internal.R.styleable.Extra_name);
1898 throw new XmlPullParserException("<" + tagName
1899 + "> requires an android:name attribute at "
1900 + attrs.getPositionDescription());
1903 TypedValue v = sa.peekValue(
1904 com.android.internal.R.styleable.Extra_value);
1906 if (v.type == TypedValue.TYPE_STRING) {
1907 CharSequence cs = v.coerceToString();
1908 outBundle.putCharSequence(name, cs);
1909 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
1910 outBundle.putBoolean(name, v.data != 0);
1911 } else if (v.type >= TypedValue.TYPE_FIRST_INT
1912 && v.type <= TypedValue.TYPE_LAST_INT) {
1913 outBundle.putInt(name, v.data);
1914 } else if (v.type == TypedValue.TYPE_FLOAT) {
1915 outBundle.putFloat(name, v.getFloat());
1918 throw new XmlPullParserException("<" + tagName
1919 + "> only supports string, integer, float, color, and boolean at "
1920 + attrs.getPositionDescription());
1924 throw new XmlPullParserException("<" + tagName
1925 + "> requires an android:value or android:resource attribute at "
1926 + attrs.getPositionDescription());
1933 * Retrieve underlying AssetManager storage for these resources.
1935 public final AssetManager getAssets() {
1940 * Call this to remove all cached loaded layout resources from the
1941 * Resources object. Only intended for use with performance testing
1944 public final void flushLayoutCache() {
1945 synchronized (mCachedXmlBlockIds) {
1946 // First see if this block is in our cache.
1947 final int num = mCachedXmlBlockIds.length;
1948 for (int i=0; i<num; i++) {
1949 mCachedXmlBlockIds[i] = -0;
1950 XmlBlock oldBlock = mCachedXmlBlocks[i];
1951 if (oldBlock != null) {
1954 mCachedXmlBlocks[i] = null;
1960 * Start preloading of resource data using this Resources object. Only
1961 * for use by the zygote process for loading common system resources.
1964 public final void startPreloading() {
1965 synchronized (sSync) {
1967 throw new IllegalStateException("Resources already preloaded");
1971 sPreloadedDensity = DisplayMetrics.DENSITY_DEVICE;
1972 mConfiguration.densityDpi = sPreloadedDensity;
1973 updateConfiguration(null, null);
1978 * Called by zygote when it is done preloading resources, to change back
1979 * to normal Resources operation.
1981 public final void finishPreloading() {
1983 mPreloading = false;
1988 static private final int VARYING_CONFIGS = ActivityInfo.activityInfoConfigToNative(
1989 ActivityInfo.CONFIG_LAYOUT_DIRECTION);
1991 private boolean verifyPreloadConfig(int changingConfigurations, int resourceId, String name) {
1992 // We dont want to preloadd a Drawable when there is both a LTR and RTL version of it
1993 if (((changingConfigurations&~(ActivityInfo.CONFIG_FONT_SCALE |
1994 ActivityInfo.CONFIG_DENSITY)) & VARYING_CONFIGS) != 0) {
1997 resName = getResourceName(resourceId);
1998 } catch (NotFoundException e) {
2001 Log.w(TAG, "Preloaded " + name + " resource #0x"
2002 + Integer.toHexString(resourceId)
2003 + " (" + resName + ") that varies with configuration!!");
2006 if (TRACE_FOR_PRELOAD) {
2009 resName = getResourceName(resourceId);
2010 } catch (NotFoundException e) {
2013 Log.w(TAG, "Preloading " + name + " resource #0x"
2014 + Integer.toHexString(resourceId)
2015 + " (" + resName + ")");
2020 /*package*/ Drawable loadDrawable(TypedValue value, int id)
2021 throws NotFoundException {
2023 if (TRACE_FOR_PRELOAD) {
2024 // Log only framework resources
2025 if ((id >>> 24) == 0x1) {
2026 final String name = getResourceName(id);
2027 if (name != null) android.util.Log.d("PreloadDrawable", name);
2031 boolean isColorDrawable = false;
2032 if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
2033 value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
2034 isColorDrawable = true;
2036 final long key = isColorDrawable ? value.data :
2037 (((long) value.assetCookie) << 32) | value.data;
2039 Drawable dr = getCachedDrawable(isColorDrawable ? mColorDrawableCache : mDrawableCache, key);
2044 final int layoutDirection = mConfiguration.getLayoutDirection();
2045 Drawable.ConstantState cs = isColorDrawable
2046 ? sPreloadedColorDrawables.get(key)
2047 : (sPreloadedDensity == mConfiguration.densityDpi
2048 ? sPreloadedDrawables[layoutDirection].get(key) : null);
2050 dr = cs.newDrawable(this);
2052 if (isColorDrawable) {
2053 dr = new ColorDrawable(value.data);
2057 if (value.string == null) {
2058 throw new NotFoundException(
2059 "Resource is not a Drawable (color or path): " + value);
2062 String file = value.string.toString();
2064 if (TRACE_FOR_MISS_PRELOAD) {
2065 // Log only framework resources
2066 if ((id >>> 24) == 0x1) {
2067 final String name = getResourceName(id);
2068 if (name != null) android.util.Log.d(TAG, "Loading framework drawable #"
2069 + Integer.toHexString(id) + ": " + name
2074 if (DEBUG_LOAD) Log.v(TAG, "Loading drawable for cookie "
2075 + value.assetCookie + ": " + file);
2077 if (file.endsWith(".xml")) {
2078 Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
2080 XmlResourceParser rp = loadXmlResourceParser(
2081 file, id, value.assetCookie, "drawable");
2082 dr = Drawable.createFromXml(this, rp);
2084 } catch (Exception e) {
2085 Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
2086 NotFoundException rnf = new NotFoundException(
2087 "File " + file + " from drawable resource ID #0x"
2088 + Integer.toHexString(id));
2092 Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
2095 Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
2097 InputStream is = mAssets.openNonAsset(
2098 value.assetCookie, file, AssetManager.ACCESS_STREAMING);
2099 // System.out.println("Opened file " + file + ": " + is);
2100 dr = Drawable.createFromResourceStream(this, value, is,
2103 // System.out.println("Created stream: " + dr);
2104 } catch (Exception e) {
2105 Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
2106 NotFoundException rnf = new NotFoundException(
2107 "File " + file + " from drawable resource ID #0x"
2108 + Integer.toHexString(id));
2112 Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
2118 dr.setChangingConfigurations(value.changingConfigurations);
2119 cs = dr.getConstantState();
2122 if (verifyPreloadConfig(cs.getChangingConfigurations(), value.resourceId,
2124 if (isColorDrawable) {
2125 sPreloadedColorDrawables.put(key, cs);
2127 sPreloadedDrawables[layoutDirection].put(key, cs);
2131 synchronized (mAccessLock) {
2132 //Log.i(TAG, "Saving cached drawable @ #" +
2133 // Integer.toHexString(key.intValue())
2134 // + " in " + this + ": " + cs);
2135 if (isColorDrawable) {
2136 mColorDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
2138 mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
2148 private Drawable getCachedDrawable(
2149 LongSparseArray<WeakReference<ConstantState>> drawableCache,
2151 synchronized (mAccessLock) {
2152 WeakReference<Drawable.ConstantState> wr = drawableCache.get(key);
2153 if (wr != null) { // we have the key
2154 Drawable.ConstantState entry = wr.get();
2155 if (entry != null) {
2156 //Log.i(TAG, "Returning cached drawable @ #" +
2157 // Integer.toHexString(((Integer)key).intValue())
2158 // + " in " + this + ": " + entry);
2159 return entry.newDrawable(this);
2161 else { // our entry has been purged
2162 drawableCache.delete(key);
2169 /*package*/ ColorStateList loadColorStateList(TypedValue value, int id)
2170 throws NotFoundException {
2171 if (TRACE_FOR_PRELOAD) {
2172 // Log only framework resources
2173 if ((id >>> 24) == 0x1) {
2174 final String name = getResourceName(id);
2175 if (name != null) android.util.Log.d("PreloadColorStateList", name);
2179 final long key = (((long) value.assetCookie) << 32) | value.data;
2183 if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
2184 value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
2186 csl = sPreloadedColorStateLists.get(key);
2191 csl = ColorStateList.valueOf(value.data);
2193 if (verifyPreloadConfig(value.changingConfigurations, value.resourceId, "color")) {
2194 sPreloadedColorStateLists.put(key, csl);
2201 csl = getCachedColorStateList(key);
2206 csl = sPreloadedColorStateLists.get(key);
2211 if (value.string == null) {
2212 throw new NotFoundException(
2213 "Resource is not a ColorStateList (color or path): " + value);
2216 String file = value.string.toString();
2218 if (file.endsWith(".xml")) {
2219 Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
2221 XmlResourceParser rp = loadXmlResourceParser(
2222 file, id, value.assetCookie, "colorstatelist");
2223 csl = ColorStateList.createFromXml(this, rp);
2225 } catch (Exception e) {
2226 Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
2227 NotFoundException rnf = new NotFoundException(
2228 "File " + file + " from color state list resource ID #0x"
2229 + Integer.toHexString(id));
2233 Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
2235 throw new NotFoundException(
2236 "File " + file + " from drawable resource ID #0x"
2237 + Integer.toHexString(id) + ": .xml extension required");
2242 if (verifyPreloadConfig(value.changingConfigurations, value.resourceId, "color")) {
2243 sPreloadedColorStateLists.put(key, csl);
2246 synchronized (mAccessLock) {
2247 //Log.i(TAG, "Saving cached color state list @ #" +
2248 // Integer.toHexString(key.intValue())
2249 // + " in " + this + ": " + csl);
2250 mColorStateListCache.put(key, new WeakReference<ColorStateList>(csl));
2258 private ColorStateList getCachedColorStateList(long key) {
2259 synchronized (mAccessLock) {
2260 WeakReference<ColorStateList> wr = mColorStateListCache.get(key);
2261 if (wr != null) { // we have the key
2262 ColorStateList entry = wr.get();
2263 if (entry != null) {
2264 //Log.i(TAG, "Returning cached color state list @ #" +
2265 // Integer.toHexString(((Integer)key).intValue())
2266 // + " in " + this + ": " + entry);
2268 } else { // our entry has been purged
2269 mColorStateListCache.delete(key);
2276 /*package*/ XmlResourceParser loadXmlResourceParser(int id, String type)
2277 throws NotFoundException {
2278 synchronized (mAccessLock) {
2279 TypedValue value = mTmpValue;
2280 if (value == null) {
2281 mTmpValue = value = new TypedValue();
2283 getValue(id, value, true);
2284 if (value.type == TypedValue.TYPE_STRING) {
2285 return loadXmlResourceParser(value.string.toString(), id,
2286 value.assetCookie, type);
2288 throw new NotFoundException(
2289 "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
2290 + Integer.toHexString(value.type) + " is not valid");
2294 /*package*/ XmlResourceParser loadXmlResourceParser(String file, int id,
2295 int assetCookie, String type) throws NotFoundException {
2298 // These may be compiled...
2299 synchronized (mCachedXmlBlockIds) {
2300 // First see if this block is in our cache.
2301 final int num = mCachedXmlBlockIds.length;
2302 for (int i=0; i<num; i++) {
2303 if (mCachedXmlBlockIds[i] == id) {
2304 //System.out.println("**** REUSING XML BLOCK! id="
2305 // + id + ", index=" + i);
2306 return mCachedXmlBlocks[i].newParser();
2310 // Not in the cache, create a new block and put it at
2311 // the next slot in the cache.
2312 XmlBlock block = mAssets.openXmlBlockAsset(
2314 if (block != null) {
2315 int pos = mLastCachedXmlBlockIndex+1;
2316 if (pos >= num) pos = 0;
2317 mLastCachedXmlBlockIndex = pos;
2318 XmlBlock oldBlock = mCachedXmlBlocks[pos];
2319 if (oldBlock != null) {
2322 mCachedXmlBlockIds[pos] = id;
2323 mCachedXmlBlocks[pos] = block;
2324 //System.out.println("**** CACHING NEW XML BLOCK! id="
2325 // + id + ", index=" + pos);
2326 return block.newParser();
2329 } catch (Exception e) {
2330 NotFoundException rnf = new NotFoundException(
2331 "File " + file + " from xml type " + type + " resource ID #0x"
2332 + Integer.toHexString(id));
2338 throw new NotFoundException(
2339 "File " + file + " from xml type " + type + " resource ID #0x"
2340 + Integer.toHexString(id));
2343 private TypedArray getCachedStyledAttributes(int len) {
2344 synchronized (mAccessLock) {
2345 TypedArray attrs = mCachedStyledAttributes;
2346 if (attrs != null) {
2347 mCachedStyledAttributes = null;
2348 if (DEBUG_ATTRIBUTES_CACHE) {
2349 mLastRetrievedAttrs = new RuntimeException("here");
2350 mLastRetrievedAttrs.fillInStackTrace();
2353 attrs.mLength = len;
2354 int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
2355 if (attrs.mData.length >= fullLen) {
2358 attrs.mData = new int[fullLen];
2359 attrs.mIndices = new int[1+len];
2362 if (DEBUG_ATTRIBUTES_CACHE) {
2363 RuntimeException here = new RuntimeException("here");
2364 here.fillInStackTrace();
2365 if (mLastRetrievedAttrs != null) {
2366 Log.i(TAG, "Allocated new TypedArray of " + len + " in " + this, here);
2367 Log.i(TAG, "Last retrieved attributes here", mLastRetrievedAttrs);
2369 mLastRetrievedAttrs = here;
2371 return new TypedArray(this,
2372 new int[len*AssetManager.STYLE_NUM_ENTRIES],
2373 new int[1+len], len);
2377 private Resources() {
2378 mAssets = AssetManager.getSystem();
2379 // NOTE: Intentionally leaving this uninitialized (all values set
2380 // to zero), so that anyone who tries to do something that requires
2381 // metrics will get a very wrong value.
2382 mConfiguration.setToDefaults();
2383 mMetrics.setToDefaults();
2384 updateConfiguration(null, null);
2385 mAssets.ensureStringBlocks();
2386 mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;