OSDN Git Service

DO NOT MERGE. Grant MMS Uri permissions as the calling UID.
[android-x86/frameworks-base.git] / core / java / android / content / res / Resources.java
1 /*
2  * Copyright (C) 2006 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 android.content.res;
18
19 import android.animation.Animator;
20 import android.animation.StateListAnimator;
21 import android.annotation.AnimRes;
22 import android.annotation.AnyRes;
23 import android.annotation.ArrayRes;
24 import android.annotation.AttrRes;
25 import android.annotation.BoolRes;
26 import android.annotation.ColorInt;
27 import android.annotation.ColorRes;
28 import android.annotation.DimenRes;
29 import android.annotation.DrawableRes;
30 import android.annotation.FractionRes;
31 import android.annotation.IntegerRes;
32 import android.annotation.LayoutRes;
33 import android.annotation.NonNull;
34 import android.annotation.Nullable;
35 import android.annotation.PluralsRes;
36 import android.annotation.RawRes;
37 import android.annotation.StringRes;
38 import android.annotation.StyleRes;
39 import android.annotation.StyleableRes;
40 import android.annotation.XmlRes;
41 import android.content.pm.ActivityInfo;
42 import android.graphics.Movie;
43 import android.graphics.drawable.Drawable;
44 import android.graphics.drawable.Drawable.ConstantState;
45 import android.graphics.drawable.DrawableInflater;
46 import android.os.Build;
47 import android.os.Bundle;
48 import android.util.AttributeSet;
49 import android.util.DisplayMetrics;
50 import android.util.Log;
51 import android.util.LongSparseArray;
52 import android.util.Pools.SynchronizedPool;
53 import android.util.TypedValue;
54 import android.view.DisplayAdjustments;
55 import android.view.ViewDebug;
56 import android.view.ViewHierarchyEncoder;
57
58 import com.android.internal.annotations.VisibleForTesting;
59 import com.android.internal.util.GrowingArrayUtils;
60 import com.android.internal.util.XmlUtils;
61
62 import org.xmlpull.v1.XmlPullParser;
63 import org.xmlpull.v1.XmlPullParserException;
64
65 import java.io.IOException;
66 import java.io.InputStream;
67 import java.lang.ref.WeakReference;
68 import java.util.ArrayList;
69
70 /**
71  * Class for accessing an application's resources.  This sits on top of the
72  * asset manager of the application (accessible through {@link #getAssets}) and
73  * provides a high-level API for getting typed data from the assets.
74  *
75  * <p>The Android resource system keeps track of all non-code assets associated with an
76  * application. You can use this class to access your application's resources. You can generally
77  * acquire the {@link android.content.res.Resources} instance associated with your application
78  * with {@link android.content.Context#getResources getResources()}.</p>
79  *
80  * <p>The Android SDK tools compile your application's resources into the application binary
81  * at build time.  To use a resource, you must install it correctly in the source tree (inside
82  * your project's {@code res/} directory) and build your application.  As part of the build
83  * process, the SDK tools generate symbols for each resource, which you can use in your application
84  * code to access the resources.</p>
85  *
86  * <p>Using application resources makes it easy to update various characteristics of your
87  * application without modifying code, and&mdash;by providing sets of alternative
88  * resources&mdash;enables you to optimize your application for a variety of device configurations
89  * (such as for different languages and screen sizes). This is an important aspect of developing
90  * Android applications that are compatible on different types of devices.</p>
91  *
92  * <p>For more information about using resources, see the documentation about <a
93  * href="{@docRoot}guide/topics/resources/index.html">Application Resources</a>.</p>
94  */
95 public class Resources {
96     static final String TAG = "Resources";
97
98     private static final Object sSync = new Object();
99
100     // Used by BridgeResources in layoutlib
101     static Resources mSystem = null;
102
103     private ResourcesImpl mResourcesImpl;
104
105     // Pool of TypedArrays targeted to this Resources object.
106     final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5);
107
108     /** Used to inflate drawable objects from XML. */
109     private DrawableInflater mDrawableInflater;
110
111     /** Lock object used to protect access to {@link #mTmpValue}. */
112     private final Object mTmpValueLock = new Object();
113
114     /** Single-item pool used to minimize TypedValue allocations. */
115     private TypedValue mTmpValue = new TypedValue();
116
117     final ClassLoader mClassLoader;
118
119     /**
120      * WeakReferences to Themes that were constructed from this Resources object.
121      * We keep track of these in case our underlying implementation is changed, in which case
122      * the Themes must also get updated ThemeImpls.
123      */
124     private final ArrayList<WeakReference<Theme>> mThemeRefs = new ArrayList<>();
125
126     /**
127      * Returns the most appropriate default theme for the specified target SDK version.
128      * <ul>
129      * <li>Below API 11: Gingerbread
130      * <li>APIs 12 thru 14: Holo
131      * <li>APIs 15 thru 23: Device default dark
132      * <li>APIs 24 and above: Device default light with dark action bar
133      * </ul>
134      *
135      * @param curTheme The current theme, or 0 if not specified.
136      * @param targetSdkVersion The target SDK version.
137      * @return A theme resource identifier
138      * @hide
139      */
140     public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
141         return selectSystemTheme(curTheme, targetSdkVersion,
142                 com.android.internal.R.style.Theme,
143                 com.android.internal.R.style.Theme_Holo,
144                 com.android.internal.R.style.Theme_DeviceDefault,
145                 com.android.internal.R.style.Theme_DeviceDefault_Light_DarkActionBar);
146     }
147
148     /** @hide */
149     public static int selectSystemTheme(int curTheme, int targetSdkVersion, int orig, int holo,
150             int dark, int deviceDefault) {
151         if (curTheme != 0) {
152             return curTheme;
153         }
154         if (targetSdkVersion < Build.VERSION_CODES.HONEYCOMB) {
155             return orig;
156         }
157         if (targetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
158             return holo;
159         }
160         if (targetSdkVersion < Build.VERSION_CODES.N) {
161             return dark;
162         }
163         return deviceDefault;
164     }
165
166     /**
167      * Return a global shared Resources object that provides access to only
168      * system resources (no application resources), and is not configured for
169      * the current screen (can not use dimension units, does not change based
170      * on orientation, etc).
171      */
172     public static Resources getSystem() {
173         synchronized (sSync) {
174             Resources ret = mSystem;
175             if (ret == null) {
176                 ret = new Resources();
177                 mSystem = ret;
178             }
179             return ret;
180         }
181     }
182
183     /**
184      * This exception is thrown by the resource APIs when a requested resource
185      * can not be found.
186      */
187     public static class NotFoundException extends RuntimeException {
188         public NotFoundException() {
189         }
190
191         public NotFoundException(String name) {
192             super(name);
193         }
194
195         public NotFoundException(String name, Exception cause) {
196             super(name, cause);
197         }
198     }
199
200     /**
201      * Create a new Resources object on top of an existing set of assets in an
202      * AssetManager.
203      *
204      * @deprecated Resources should not be constructed by apps.
205      * See {@link android.content.Context#createConfigurationContext(Configuration)}.
206      *
207      * @param assets Previously created AssetManager.
208      * @param metrics Current display metrics to consider when
209      *                selecting/computing resource values.
210      * @param config Desired device configuration to consider when
211      *               selecting/computing resource values (optional).
212      */
213     @Deprecated
214     public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
215         this(null);
216         mResourcesImpl = new ResourcesImpl(assets, metrics, config, new DisplayAdjustments());
217     }
218
219     /**
220      * Creates a new Resources object with CompatibilityInfo.
221      *
222      * @param classLoader class loader for the package used to load custom
223      *                    resource classes, may be {@code null} to use system
224      *                    class loader
225      * @hide
226      */
227     public Resources(@Nullable ClassLoader classLoader) {
228         mClassLoader = classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader;
229     }
230
231     /**
232      * Only for creating the System resources.
233      */
234     private Resources() {
235         this(null);
236
237         final DisplayMetrics metrics = new DisplayMetrics();
238         metrics.setToDefaults();
239
240         final Configuration config = new Configuration();
241         config.setToDefaults();
242
243         mResourcesImpl = new ResourcesImpl(AssetManager.getSystem(), metrics, config,
244                 new DisplayAdjustments());
245     }
246
247     /**
248      * Set the underlying implementation (containing all the resources and caches)
249      * and updates all Theme references to new implementations as well.
250      * @hide
251      */
252     public void setImpl(ResourcesImpl impl) {
253         if (impl == mResourcesImpl) {
254             return;
255         }
256
257         mResourcesImpl = impl;
258
259         // Create new ThemeImpls that are identical to the ones we have.
260         synchronized (mThemeRefs) {
261             final int count = mThemeRefs.size();
262             for (int i = 0; i < count; i++) {
263                 WeakReference<Theme> weakThemeRef = mThemeRefs.get(i);
264                 Theme theme = weakThemeRef != null ? weakThemeRef.get() : null;
265                 if (theme != null) {
266                     theme.setImpl(mResourcesImpl.newThemeImpl(theme.getKey()));
267                 }
268             }
269         }
270     }
271
272     /**
273      * @hide
274      */
275     public ResourcesImpl getImpl() {
276         return mResourcesImpl;
277     }
278
279     /**
280      * @hide
281      */
282     public ClassLoader getClassLoader() {
283         return mClassLoader;
284     }
285
286     /**
287      * @return the inflater used to create drawable objects
288      * @hide Pending API finalization.
289      */
290     public final DrawableInflater getDrawableInflater() {
291         if (mDrawableInflater == null) {
292             mDrawableInflater = new DrawableInflater(this, mClassLoader);
293         }
294         return mDrawableInflater;
295     }
296
297     /**
298      * Used by AnimatorInflater.
299      *
300      * @hide
301      */
302     public ConfigurationBoundResourceCache<Animator> getAnimatorCache() {
303         return mResourcesImpl.getAnimatorCache();
304     }
305
306     /**
307      * Used by AnimatorInflater.
308      *
309      * @hide
310      */
311     public ConfigurationBoundResourceCache<StateListAnimator> getStateListAnimatorCache() {
312         return mResourcesImpl.getStateListAnimatorCache();
313     }
314
315     /**
316      * Return the string value associated with a particular resource ID.  The
317      * returned object will be a String if this is a plain string; it will be
318      * some other type of CharSequence if it is styled.
319      * {@more}
320      *
321      * @param id The desired resource identifier, as generated by the aapt
322      *           tool. This integer encodes the package, type, and resource
323      *           entry. The value 0 is an invalid identifier.
324      *
325      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
326      *
327      * @return CharSequence The string data associated with the resource, plus
328      *         possibly styled text information.
329      */
330     @NonNull public CharSequence getText(@StringRes int id) throws NotFoundException {
331         CharSequence res = mResourcesImpl.getAssets().getResourceText(id);
332         if (res != null) {
333             return res;
334         }
335         throw new NotFoundException("String resource ID #0x"
336                                     + Integer.toHexString(id));
337     }
338
339     /**
340      * Returns the character sequence necessary for grammatically correct pluralization
341      * of the given resource ID for the given quantity.
342      * Note that the character sequence is selected based solely on grammatical necessity,
343      * and that such rules differ between languages. Do not assume you know which string
344      * will be returned for a given quantity. See
345      * <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String Resources</a>
346      * for more detail.
347      *
348      * @param id The desired resource identifier, as generated by the aapt
349      *           tool. This integer encodes the package, type, and resource
350      *           entry. The value 0 is an invalid identifier.
351      * @param quantity The number used to get the correct string for the current language's
352      *           plural rules.
353      *
354      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
355      *
356      * @return CharSequence The string data associated with the resource, plus
357      *         possibly styled text information.
358      */
359     @NonNull
360     public CharSequence getQuantityText(@PluralsRes int id, int quantity)
361             throws NotFoundException {
362         return mResourcesImpl.getQuantityText(id, quantity);
363     }
364
365     /**
366      * Return the string value associated with a particular resource ID.  It
367      * will be stripped of any styled text information.
368      * {@more}
369      *
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      *
374      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
375      *
376      * @return String The string data associated with the resource,
377      *         stripped of styled text information.
378      */
379     @NonNull
380     public String getString(@StringRes int id) throws NotFoundException {
381         return getText(id).toString();
382     }
383
384
385     /**
386      * Return the string value associated with a particular resource ID,
387      * substituting the format arguments as defined in {@link java.util.Formatter}
388      * and {@link java.lang.String#format}. It will be stripped of any styled text
389      * information.
390      * {@more}
391      *
392      * @param id The desired resource identifier, as generated by the aapt
393      *           tool. This integer encodes the package, type, and resource
394      *           entry. The value 0 is an invalid identifier.
395      *           
396      * @param formatArgs The format arguments that will be used for substitution.
397      *
398      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
399      *
400      * @return String The string data associated with the resource,
401      *         stripped of styled text information.
402      */
403     @NonNull
404     public String getString(@StringRes int id, Object... formatArgs) throws NotFoundException {
405         final String raw = getString(id);
406         return String.format(mResourcesImpl.getConfiguration().getLocales().get(0), raw,
407                 formatArgs);
408     }
409
410     /**
411      * Formats the string necessary for grammatically correct pluralization
412      * of the given resource ID for the given quantity, using the given arguments.
413      * Note that the string is selected based solely on grammatical necessity,
414      * and that such rules differ between languages. Do not assume you know which string
415      * will be returned for a given quantity. See
416      * <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String Resources</a>
417      * for more detail.
418      *
419      * <p>Substitution of format arguments works as if using
420      * {@link java.util.Formatter} and {@link java.lang.String#format}.
421      * The resulting string will be stripped of any styled text information.
422      *
423      * @param id The desired resource identifier, as generated by the aapt
424      *           tool. This integer encodes the package, type, and resource
425      *           entry. The value 0 is an invalid identifier.
426      * @param quantity The number used to get the correct string for the current language's
427      *           plural rules.
428      * @param formatArgs The format arguments that will be used for substitution.
429      *
430      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
431      *
432      * @return String The string data associated with the resource,
433      * stripped of styled text information.
434      */
435     @NonNull
436     public String getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs)
437             throws NotFoundException {
438         String raw = getQuantityText(id, quantity).toString();
439         return String.format(mResourcesImpl.getConfiguration().getLocales().get(0), raw,
440                 formatArgs);
441     }
442
443     /**
444      * Returns the string necessary for grammatically correct pluralization
445      * of the given resource ID for the given quantity.
446      * Note that the string is selected based solely on grammatical necessity,
447      * and that such rules differ between languages. Do not assume you know which string
448      * will be returned for a given quantity. See
449      * <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String Resources</a>
450      * for more detail.
451      *
452      * @param id The desired resource identifier, as generated by the aapt
453      *           tool. This integer encodes the package, type, and resource
454      *           entry. The value 0 is an invalid identifier.
455      * @param quantity The number used to get the correct string for the current language's
456      *           plural rules.
457      *
458      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
459      *
460      * @return String The string data associated with the resource,
461      * stripped of styled text information.
462      */
463     @NonNull
464     public String getQuantityString(@PluralsRes int id, int quantity) throws NotFoundException {
465         return getQuantityText(id, quantity).toString();
466     }
467
468     /**
469      * Return the string value associated with a particular resource ID.  The
470      * returned object will be a String if this is a plain string; it will be
471      * some other type of CharSequence if it is styled.
472      * 
473      * @param id The desired resource identifier, as generated by the aapt
474      *           tool. This integer encodes the package, type, and resource
475      *           entry. The value 0 is an invalid identifier.
476      * 
477      * @param def The default CharSequence to return.
478      *
479      * @return CharSequence The string data associated with the resource, plus
480      *         possibly styled text information, or def if id is 0 or not found.
481      */
482     public CharSequence getText(@StringRes int id, CharSequence def) {
483         CharSequence res = id != 0 ? mResourcesImpl.getAssets().getResourceText(id) : null;
484         return res != null ? res : def;
485     }
486
487     /**
488      * Return the styled text array associated with a particular resource ID.
489      *
490      * @param id The desired resource identifier, as generated by the aapt
491      *           tool. This integer encodes the package, type, and resource
492      *           entry. The value 0 is an invalid identifier.
493      *
494      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
495      *
496      * @return The styled text array associated with the resource.
497      */
498     @NonNull
499     public CharSequence[] getTextArray(@ArrayRes int id) throws NotFoundException {
500         CharSequence[] res = mResourcesImpl.getAssets().getResourceTextArray(id);
501         if (res != null) {
502             return res;
503         }
504         throw new NotFoundException("Text array resource ID #0x" + Integer.toHexString(id));
505     }
506
507     /**
508      * Return the string array associated with a particular resource ID.
509      *
510      * @param id The desired resource identifier, as generated by the aapt
511      *           tool. This integer encodes the package, type, and resource
512      *           entry. The value 0 is an invalid identifier.
513      *
514      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
515      *
516      * @return The string array associated with the resource.
517      */
518     @NonNull
519     public String[] getStringArray(@ArrayRes int id)
520             throws NotFoundException {
521         String[] res = mResourcesImpl.getAssets().getResourceStringArray(id);
522         if (res != null) {
523             return res;
524         }
525         throw new NotFoundException("String array resource ID #0x" + Integer.toHexString(id));
526     }
527
528     /**
529      * Return the int array associated with a particular resource ID.
530      *
531      * @param id The desired resource identifier, as generated by the aapt
532      *           tool. This integer encodes the package, type, and resource
533      *           entry. The value 0 is an invalid identifier.
534      *
535      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
536      *
537      * @return The int array associated with the resource.
538      */
539     @NonNull
540     public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
541         int[] res = mResourcesImpl.getAssets().getArrayIntResource(id);
542         if (res != null) {
543             return res;
544         }
545         throw new NotFoundException("Int array resource ID #0x" + Integer.toHexString(id));
546     }
547
548     /**
549      * Return an array of heterogeneous values.
550      *
551      * @param id The desired resource identifier, as generated by the aapt
552      *           tool. This integer encodes the package, type, and resource
553      *           entry. The value 0 is an invalid identifier.
554      *
555      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
556      *
557      * @return Returns a TypedArray holding an array of the array values.
558      * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
559      * when done with it.
560      */
561     @NonNull
562     public TypedArray obtainTypedArray(@ArrayRes int id) throws NotFoundException {
563         final ResourcesImpl impl = mResourcesImpl;
564         int len = impl.getAssets().getArraySize(id);
565         if (len < 0) {
566             throw new NotFoundException("Array resource ID #0x" + Integer.toHexString(id));
567         }
568         
569         TypedArray array = TypedArray.obtain(this, len);
570         array.mLength = impl.getAssets().retrieveArray(id, array.mData);
571         array.mIndices[0] = 0;
572         
573         return array;
574     }
575
576     /**
577      * Retrieve a dimensional for a particular resource ID.  Unit 
578      * conversions are based on the current {@link DisplayMetrics} associated
579      * with the resources.
580      * 
581      * @param id The desired resource identifier, as generated by the aapt
582      *           tool. This integer encodes the package, type, and resource
583      *           entry. The value 0 is an invalid identifier.
584      * 
585      * @return Resource dimension value multiplied by the appropriate 
586      * metric.
587      * 
588      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
589      *
590      * @see #getDimensionPixelOffset
591      * @see #getDimensionPixelSize
592      */
593     public float getDimension(@DimenRes int id) throws NotFoundException {
594         final TypedValue value = obtainTempTypedValue();
595         try {
596             final ResourcesImpl impl = mResourcesImpl;
597             impl.getValue(id, value, true);
598             if (value.type == TypedValue.TYPE_DIMENSION) {
599                 return TypedValue.complexToDimension(value.data, impl.getDisplayMetrics());
600             }
601             throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
602                     + " type #0x" + Integer.toHexString(value.type) + " is not valid");
603         } finally {
604             releaseTempTypedValue(value);
605         }
606     }
607
608     /**
609      * Retrieve a dimensional for a particular resource ID for use
610      * as an offset in raw pixels.  This is the same as
611      * {@link #getDimension}, except the returned value is converted to
612      * integer pixels for you.  An offset conversion involves simply
613      * truncating the base value to an integer.
614      * 
615      * @param id The desired resource identifier, as generated by the aapt
616      *           tool. This integer encodes the package, type, and resource
617      *           entry. The value 0 is an invalid identifier.
618      * 
619      * @return Resource dimension value multiplied by the appropriate 
620      * metric and truncated to integer pixels.
621      * 
622      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
623      *
624      * @see #getDimension
625      * @see #getDimensionPixelSize
626      */
627     public int getDimensionPixelOffset(@DimenRes int id) throws NotFoundException {
628         final TypedValue value = obtainTempTypedValue();
629         try {
630             final ResourcesImpl impl = mResourcesImpl;
631             impl.getValue(id, value, true);
632             if (value.type == TypedValue.TYPE_DIMENSION) {
633                 return TypedValue.complexToDimensionPixelOffset(value.data,
634                         impl.getDisplayMetrics());
635             }
636             throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
637                     + " type #0x" + Integer.toHexString(value.type) + " is not valid");
638         } finally {
639             releaseTempTypedValue(value);
640         }
641     }
642
643     /**
644      * Retrieve a dimensional for a particular resource ID for use
645      * as a size in raw pixels.  This is the same as
646      * {@link #getDimension}, except the returned value is converted to
647      * integer pixels for use as a size.  A size conversion involves
648      * rounding the base value, and ensuring that a non-zero base value
649      * is at least one pixel in size.
650      * 
651      * @param id The desired resource identifier, as generated by the aapt
652      *           tool. This integer encodes the package, type, and resource
653      *           entry. The value 0 is an invalid identifier.
654      * 
655      * @return Resource dimension value multiplied by the appropriate 
656      * metric and truncated to integer pixels.
657      *  
658      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
659      *
660      * @see #getDimension
661      * @see #getDimensionPixelOffset
662      */
663     public int getDimensionPixelSize(@DimenRes int id) throws NotFoundException {
664         final TypedValue value = obtainTempTypedValue();
665         try {
666             final ResourcesImpl impl = mResourcesImpl;
667             impl.getValue(id, value, true);
668             if (value.type == TypedValue.TYPE_DIMENSION) {
669                 return TypedValue.complexToDimensionPixelSize(value.data, impl.getDisplayMetrics());
670             }
671             throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
672                     + " type #0x" + Integer.toHexString(value.type) + " is not valid");
673         } finally {
674             releaseTempTypedValue(value);
675         }
676     }
677
678     /**
679      * Retrieve a fractional unit for a particular resource ID.
680      * 
681      * @param id The desired resource identifier, as generated by the aapt
682      *           tool. This integer encodes the package, type, and resource
683      *           entry. The value 0 is an invalid identifier.
684      * @param base The base value of this fraction.  In other words, a 
685      *             standard fraction is multiplied by this value.
686      * @param pbase The parent base value of this fraction.  In other 
687      *             words, a parent fraction (nn%p) is multiplied by this
688      *             value.
689      * 
690      * @return Attribute fractional value multiplied by the appropriate 
691      * base value.
692      *  
693      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
694      */
695     public float getFraction(@FractionRes int id, int base, int pbase) {
696         final TypedValue value = obtainTempTypedValue();
697         try {
698             mResourcesImpl.getValue(id, value, true);
699             if (value.type == TypedValue.TYPE_FRACTION) {
700                 return TypedValue.complexToFraction(value.data, base, pbase);
701             }
702             throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
703                     + " type #0x" + Integer.toHexString(value.type) + " is not valid");
704         } finally {
705             releaseTempTypedValue(value);
706         }
707     }
708     
709     /**
710      * Return a drawable object associated with a particular resource ID.
711      * Various types of objects will be returned depending on the underlying
712      * resource -- for example, a solid color, PNG image, scalable image, etc.
713      * The Drawable API hides these implementation details.
714      *
715      * <p class="note"><strong>Note:</strong> Prior to
716      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN}, this function
717      * would not correctly retrieve the final configuration density when
718      * the resource ID passed here is an alias to another Drawable resource.
719      * This means that if the density configuration of the alias resource
720      * is different than the actual resource, the density of the returned
721      * Drawable would be incorrect, resulting in bad scaling. To work
722      * around this, you can instead manually resolve the aliased reference
723      * by using {@link #getValue(int, TypedValue, boolean)} and passing
724      * {@code true} for {@code resolveRefs}. The resulting
725      * {@link TypedValue#resourceId} value may be passed to this method.</p>
726      *
727      * <p class="note"><strong>Note:</strong> To obtain a themed drawable, use
728      * {@link android.content.Context#getDrawable(int) Context.getDrawable(int)}
729      * or {@link #getDrawable(int, Theme)} passing the desired theme.</p>
730      *
731      * @param id The desired resource identifier, as generated by the aapt
732      *           tool. This integer encodes the package, type, and resource
733      *           entry. The value 0 is an invalid identifier.
734      * @return Drawable An object that can be used to draw this resource.
735      * @throws NotFoundException Throws NotFoundException if the given ID does
736      *         not exist.
737      * @see #getDrawable(int, Theme)
738      * @deprecated Use {@link #getDrawable(int, Theme)} instead.
739      */
740     @Deprecated
741     public Drawable getDrawable(@DrawableRes int id) throws NotFoundException {
742         final Drawable d = getDrawable(id, null);
743         if (d != null && d.canApplyTheme()) {
744             Log.w(TAG, "Drawable " + getResourceName(id) + " has unresolved theme "
745                     + "attributes! Consider using Resources.getDrawable(int, Theme) or "
746                     + "Context.getDrawable(int).", new RuntimeException());
747         }
748         return d;
749     }
750
751     /**
752      * Return a drawable object associated with a particular resource ID and
753      * styled for the specified theme. Various types of objects will be
754      * returned depending on the underlying resource -- for example, a solid
755      * color, PNG image, scalable image, etc.
756      *
757      * @param id The desired resource identifier, as generated by the aapt
758      *           tool. This integer encodes the package, type, and resource
759      *           entry. The value 0 is an invalid identifier.
760      * @param theme The theme used to style the drawable attributes, may be {@code null}.
761      * @return Drawable An object that can be used to draw this resource.
762      * @throws NotFoundException Throws NotFoundException if the given ID does
763      *         not exist.
764      */
765     public Drawable getDrawable(@DrawableRes int id, @Nullable Theme theme)
766             throws NotFoundException {
767         final TypedValue value = obtainTempTypedValue();
768         try {
769             final ResourcesImpl impl = mResourcesImpl;
770             impl.getValue(id, value, true);
771             return impl.loadDrawable(this, value, id, theme, true);
772         } finally {
773             releaseTempTypedValue(value);
774         }
775     }
776
777     /**
778      * Return a drawable object associated with a particular resource ID for the
779      * given screen density in DPI. This will set the drawable's density to be
780      * the device's density multiplied by the ratio of actual drawable density
781      * to requested density. This allows the drawable to be scaled up to the
782      * correct size if needed. Various types of objects will be returned
783      * depending on the underlying resource -- for example, a solid color, PNG
784      * image, scalable image, etc. The Drawable API hides these implementation
785      * details.
786      *
787      * <p class="note"><strong>Note:</strong> To obtain a themed drawable, use
788      * {@link android.content.Context#getDrawable(int) Context.getDrawable(int)}
789      * or {@link #getDrawableForDensity(int, int, Theme)} passing the desired
790      * theme.</p>
791      *
792      * @param id The desired resource identifier, as generated by the aapt tool.
793      *            This integer encodes the package, type, and resource entry.
794      *            The value 0 is an invalid identifier.
795      * @param density the desired screen density indicated by the resource as
796      *            found in {@link DisplayMetrics}.
797      * @return Drawable An object that can be used to draw this resource.
798      * @throws NotFoundException Throws NotFoundException if the given ID does
799      *             not exist.
800      * @see #getDrawableForDensity(int, int, Theme)
801      * @deprecated Use {@link #getDrawableForDensity(int, int, Theme)} instead.
802      */
803     @Deprecated
804     public Drawable getDrawableForDensity(@DrawableRes int id, int density)
805             throws NotFoundException {
806         return getDrawableForDensity(id, density, null);
807     }
808
809     /**
810      * Return a drawable object associated with a particular resource ID for the
811      * given screen density in DPI and styled for the specified theme.
812      *
813      * @param id The desired resource identifier, as generated by the aapt tool.
814      *            This integer encodes the package, type, and resource entry.
815      *            The value 0 is an invalid identifier.
816      * @param density The desired screen density indicated by the resource as
817      *            found in {@link DisplayMetrics}.
818      * @param theme The theme used to style the drawable attributes, may be {@code null}.
819      * @return Drawable An object that can be used to draw this resource.
820      * @throws NotFoundException Throws NotFoundException if the given ID does
821      *             not exist.
822      */
823     public Drawable getDrawableForDensity(@DrawableRes int id, int density, @Nullable Theme theme) {
824         final TypedValue value = obtainTempTypedValue();
825         try {
826             final ResourcesImpl impl = mResourcesImpl;
827             impl.getValueForDensity(id, density, value, true);
828
829             // If the drawable's XML lives in our current density qualifier,
830             // it's okay to use a scaled version from the cache. Otherwise, we
831             // need to actually load the drawable from XML.
832             final DisplayMetrics metrics = impl.getDisplayMetrics();
833             final boolean useCache = value.density == metrics.densityDpi;
834
835             /*
836              * Pretend the requested density is actually the display density. If
837              * the drawable returned is not the requested density, then force it
838              * to be scaled later by dividing its density by the ratio of
839              * requested density to actual device density. Drawables that have
840              * undefined density or no density don't need to be handled here.
841              */
842             if (value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
843                 if (value.density == density) {
844                     value.density = metrics.densityDpi;
845                 } else {
846                     value.density = (value.density * metrics.densityDpi) / density;
847                 }
848             }
849             return impl.loadDrawable(this, value, id, theme, useCache);
850         } finally {
851             releaseTempTypedValue(value);
852         }
853     }
854
855     @NonNull
856     Drawable loadDrawable(@NonNull TypedValue value, int id, @Nullable Theme theme)
857             throws NotFoundException {
858         return mResourcesImpl.loadDrawable(this, value, id, theme, true);
859     }
860
861     /**
862      * Return a movie object associated with the particular resource ID.
863      * @param id The desired resource identifier, as generated by the aapt
864      *           tool. This integer encodes the package, type, and resource
865      *           entry. The value 0 is an invalid identifier.
866      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
867      * 
868      */
869     public Movie getMovie(@RawRes int id) throws NotFoundException {
870         final InputStream is = openRawResource(id);
871         final Movie movie = Movie.decodeStream(is);
872         try {
873             is.close();
874         } catch (IOException e) {
875             // No one cares.
876         }
877         return movie;
878     }
879
880     /**
881      * Returns a color integer associated with a particular resource ID. If the
882      * resource holds a complex {@link ColorStateList}, then the default color
883      * from the set is returned.
884      *
885      * @param id The desired resource identifier, as generated by the aapt
886      *           tool. This integer encodes the package, type, and resource
887      *           entry. The value 0 is an invalid identifier.
888      *
889      * @throws NotFoundException Throws NotFoundException if the given ID does
890      *         not exist.
891      *
892      * @return A single color value in the form 0xAARRGGBB.
893      * @deprecated Use {@link #getColor(int, Theme)} instead.
894      */
895     @ColorInt
896     @Deprecated
897     public int getColor(@ColorRes int id) throws NotFoundException {
898         return getColor(id, null);
899     }
900
901     /**
902      * Returns a themed color integer associated with a particular resource ID.
903      * If the resource holds a complex {@link ColorStateList}, then the default
904      * color from the set is returned.
905      *
906      * @param id The desired resource identifier, as generated by the aapt
907      *           tool. This integer encodes the package, type, and resource
908      *           entry. The value 0 is an invalid identifier.
909      * @param theme The theme used to style the color attributes, may be
910      *              {@code null}.
911      *
912      * @throws NotFoundException Throws NotFoundException if the given ID does
913      *         not exist.
914      *
915      * @return A single color value in the form 0xAARRGGBB.
916      */
917     @ColorInt
918     public int getColor(@ColorRes int id, @Nullable Theme theme) throws NotFoundException {
919         final TypedValue value = obtainTempTypedValue();
920         try {
921             final ResourcesImpl impl = mResourcesImpl;
922             impl.getValue(id, value, true);
923             if (value.type >= TypedValue.TYPE_FIRST_INT
924                     && value.type <= TypedValue.TYPE_LAST_INT) {
925                 return value.data;
926             } else if (value.type != TypedValue.TYPE_STRING) {
927                 throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
928                         + " type #0x" + Integer.toHexString(value.type) + " is not valid");
929             }
930
931             final ColorStateList csl = impl.loadColorStateList(this, value, id, theme);
932             return csl.getDefaultColor();
933         } finally {
934             releaseTempTypedValue(value);
935         }
936     }
937
938     /**
939      * Returns a color state list associated with a particular resource ID. The
940      * resource may contain either a single raw color value or a complex
941      * {@link ColorStateList} holding multiple possible colors.
942      *
943      * @param id The desired resource identifier of a {@link ColorStateList},
944      *           as generated by the aapt tool. This integer encodes the
945      *           package, type, and resource entry. The value 0 is an invalid
946      *           identifier.
947      *
948      * @throws NotFoundException Throws NotFoundException if the given ID does
949      *         not exist.
950      *
951      * @return A ColorStateList object containing either a single solid color
952      *         or multiple colors that can be selected based on a state.
953      * @deprecated Use {@link #getColorStateList(int, Theme)} instead.
954      */
955     @Nullable
956     @Deprecated
957     public ColorStateList getColorStateList(@ColorRes int id) throws NotFoundException {
958         final ColorStateList csl = getColorStateList(id, null);
959         if (csl != null && csl.canApplyTheme()) {
960             Log.w(TAG, "ColorStateList " + getResourceName(id) + " has "
961                     + "unresolved theme attributes! Consider using "
962                     + "Resources.getColorStateList(int, Theme) or "
963                     + "Context.getColorStateList(int).", new RuntimeException());
964         }
965         return csl;
966     }
967
968     /**
969      * Returns a themed color state list associated with a particular resource
970      * ID. The resource may contain either a single raw color value or a
971      * complex {@link ColorStateList} holding multiple possible colors.
972      *
973      * @param id The desired resource identifier of a {@link ColorStateList},
974      *           as generated by the aapt tool. This integer encodes the
975      *           package, type, and resource entry. The value 0 is an invalid
976      *           identifier.
977      * @param theme The theme used to style the color attributes, may be
978      *              {@code null}.
979      *
980      * @throws NotFoundException Throws NotFoundException if the given ID does
981      *         not exist.
982      *
983      * @return A themed ColorStateList object containing either a single solid
984      *         color or multiple colors that can be selected based on a state.
985      */
986     @Nullable
987     public ColorStateList getColorStateList(@ColorRes int id, @Nullable Theme theme)
988             throws NotFoundException {
989         final TypedValue value = obtainTempTypedValue();
990         try {
991             final ResourcesImpl impl = mResourcesImpl;
992             impl.getValue(id, value, true);
993             return impl.loadColorStateList(this, value, id, theme);
994         } finally {
995             releaseTempTypedValue(value);
996         }
997     }
998
999     @Nullable
1000     ColorStateList loadColorStateList(@NonNull TypedValue value, int id, @Nullable Theme theme)
1001             throws NotFoundException {
1002         return mResourcesImpl.loadColorStateList(this, value, id, theme);
1003     }
1004
1005     /**
1006      * @hide
1007      */
1008     @Nullable
1009     public ComplexColor loadComplexColor(@NonNull TypedValue value, int id, @Nullable Theme theme) {
1010         return mResourcesImpl.loadComplexColor(this, value, id, theme);
1011     }
1012
1013     /**
1014      * Return a boolean associated with a particular resource ID.  This can be
1015      * used with any integral resource value, and will return true if it is
1016      * non-zero.
1017      *
1018      * @param id The desired resource identifier, as generated by the aapt
1019      *           tool. This integer encodes the package, type, and resource
1020      *           entry. The value 0 is an invalid identifier.
1021      *
1022      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1023      *
1024      * @return Returns the boolean value contained in the resource.
1025      */
1026     public boolean getBoolean(@BoolRes int id) throws NotFoundException {
1027         final TypedValue value = obtainTempTypedValue();
1028         try {
1029             mResourcesImpl.getValue(id, value, true);
1030             if (value.type >= TypedValue.TYPE_FIRST_INT
1031                     && value.type <= TypedValue.TYPE_LAST_INT) {
1032                 return value.data != 0;
1033             }
1034             throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
1035                     + " type #0x" + Integer.toHexString(value.type) + " is not valid");
1036         } finally {
1037             releaseTempTypedValue(value);
1038         }
1039     }
1040
1041     /**
1042      * Return an integer associated with a particular resource ID.
1043      *
1044      * @param id The desired resource identifier, as generated by the aapt
1045      *           tool. This integer encodes the package, type, and resource
1046      *           entry. The value 0 is an invalid identifier.
1047      *
1048      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1049      *
1050      * @return Returns the integer value contained in the resource.
1051      */
1052     public int getInteger(@IntegerRes int id) throws NotFoundException {
1053         final TypedValue value = obtainTempTypedValue();
1054         try {
1055             mResourcesImpl.getValue(id, value, true);
1056             if (value.type >= TypedValue.TYPE_FIRST_INT
1057                     && value.type <= TypedValue.TYPE_LAST_INT) {
1058                 return value.data;
1059             }
1060             throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
1061                     + " type #0x" + Integer.toHexString(value.type) + " is not valid");
1062         } finally {
1063             releaseTempTypedValue(value);
1064         }
1065     }
1066
1067     /**
1068      * Retrieve a floating-point value for a particular resource ID.
1069      *
1070      * @param id The desired resource identifier, as generated by the aapt
1071      *           tool. This integer encodes the package, type, and resource
1072      *           entry. The value 0 is an invalid identifier.
1073      *
1074      * @return Returns the floating-point value contained in the resource.
1075      *
1076      * @throws NotFoundException Throws NotFoundException if the given ID does
1077      *         not exist or is not a floating-point value.
1078      * @hide Pending API council approval.
1079      */
1080     public float getFloat(int id) {
1081         final TypedValue value = obtainTempTypedValue();
1082         try {
1083             mResourcesImpl.getValue(id, value, true);
1084             if (value.type == TypedValue.TYPE_FLOAT) {
1085                 return value.getFloat();
1086             }
1087             throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
1088                     + " type #0x" + Integer.toHexString(value.type) + " is not valid");
1089         } finally {
1090             releaseTempTypedValue(value);
1091         }
1092     }
1093
1094     /**
1095      * Return an XmlResourceParser through which you can read a view layout
1096      * description for the given resource ID.  This parser has limited
1097      * functionality -- in particular, you can't change its input, and only
1098      * the high-level events are available.
1099      * 
1100      * <p>This function is really a simple wrapper for calling
1101      * {@link #getXml} with a layout resource.
1102      * 
1103      * @param id The desired resource identifier, as generated by the aapt
1104      *           tool. This integer encodes the package, type, and resource
1105      *           entry. The value 0 is an invalid identifier.
1106      *
1107      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1108      * 
1109      * @return A new parser object through which you can read
1110      *         the XML data.
1111      *         
1112      * @see #getXml
1113      */
1114     public XmlResourceParser getLayout(@LayoutRes int id) throws NotFoundException {
1115         return loadXmlResourceParser(id, "layout");
1116     }
1117
1118     /**
1119      * Return an XmlResourceParser through which you can read an animation
1120      * description for the given resource ID.  This parser has limited
1121      * functionality -- in particular, you can't change its input, and only
1122      * the high-level events are available.
1123      * 
1124      * <p>This function is really a simple wrapper for calling
1125      * {@link #getXml} with an animation resource.
1126      * 
1127      * @param id The desired resource identifier, as generated by the aapt
1128      *           tool. This integer encodes the package, type, and resource
1129      *           entry. The value 0 is an invalid identifier.
1130      *
1131      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1132      * 
1133      * @return A new parser object through which you can read
1134      *         the XML data.
1135      *         
1136      * @see #getXml
1137      */
1138     public XmlResourceParser getAnimation(@AnimRes int id) throws NotFoundException {
1139         return loadXmlResourceParser(id, "anim");
1140     }
1141
1142     /**
1143      * Return an XmlResourceParser through which you can read a generic XML
1144      * resource for the given resource ID.
1145      * 
1146      * <p>The XmlPullParser implementation returned here has some limited
1147      * functionality.  In particular, you can't change its input, and only
1148      * high-level parsing events are available (since the document was
1149      * pre-parsed for you at build time, which involved merging text and
1150      * stripping comments).
1151      * 
1152      * @param id The desired resource identifier, as generated by the aapt
1153      *           tool. This integer encodes the package, type, and resource
1154      *           entry. The value 0 is an invalid identifier.
1155      *
1156      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1157      * 
1158      * @return A new parser object through which you can read
1159      *         the XML data.
1160      *         
1161      * @see android.util.AttributeSet
1162      */
1163     public XmlResourceParser getXml(@XmlRes int id) throws NotFoundException {
1164         return loadXmlResourceParser(id, "xml");
1165     }
1166
1167     /**
1168      * Open a data stream for reading a raw resource.  This can only be used
1169      * with resources whose value is the name of an asset files -- that is, it can be
1170      * used to open drawable, sound, and raw resources; it will fail on string
1171      * and color resources.
1172      * 
1173      * @param id The resource identifier to open, as generated by the appt
1174      *           tool.
1175      * 
1176      * @return InputStream Access to the resource data.
1177      *
1178      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1179      * 
1180      */
1181     public InputStream openRawResource(@RawRes int id) throws NotFoundException {
1182         final TypedValue value = obtainTempTypedValue();
1183         try {
1184             return openRawResource(id, value);
1185         } finally {
1186             releaseTempTypedValue(value);
1187         }
1188     }
1189
1190     /**
1191      * Returns a TypedValue suitable for temporary use. The obtained TypedValue
1192      * should be released using {@link #releaseTempTypedValue(TypedValue)}.
1193      *
1194      * @return a typed value suitable for temporary use
1195      */
1196     private TypedValue obtainTempTypedValue() {
1197         TypedValue tmpValue = null;
1198         synchronized (mTmpValueLock) {
1199             if (mTmpValue != null) {
1200                 tmpValue = mTmpValue;
1201                 mTmpValue = null;
1202             }
1203         }
1204         if (tmpValue == null) {
1205             return new TypedValue();
1206         }
1207         return tmpValue;
1208     }
1209
1210     /**
1211      * Returns a TypedValue to the pool. After calling this method, the
1212      * specified TypedValue should no longer be accessed.
1213      *
1214      * @param value the typed value to return to the pool
1215      */
1216     private void releaseTempTypedValue(TypedValue value) {
1217         synchronized (mTmpValueLock) {
1218             if (mTmpValue == null) {
1219                 mTmpValue = value;
1220             }
1221         }
1222     }
1223
1224     /**
1225      * Open a data stream for reading a raw resource.  This can only be used
1226      * with resources whose value is the name of an asset file -- that is, it can be
1227      * used to open drawable, sound, and raw resources; it will fail on string
1228      * and color resources.
1229      *
1230      * @param id The resource identifier to open, as generated by the appt tool.
1231      * @param value The TypedValue object to hold the resource information.
1232      *
1233      * @return InputStream Access to the resource data.
1234      *
1235      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1236      */
1237     public InputStream openRawResource(@RawRes int id, TypedValue value)
1238             throws NotFoundException {
1239         return mResourcesImpl.openRawResource(id, value);
1240     }
1241
1242     /**
1243      * Open a file descriptor for reading a raw resource.  This can only be used
1244      * with resources whose value is the name of an asset files -- that is, it can be
1245      * used to open drawable, sound, and raw resources; it will fail on string
1246      * and color resources.
1247      * 
1248      * <p>This function only works for resources that are stored in the package
1249      * as uncompressed data, which typically includes things like mp3 files
1250      * and png images.
1251      * 
1252      * @param id The resource identifier to open, as generated by the appt
1253      *           tool.
1254      * 
1255      * @return AssetFileDescriptor A new file descriptor you can use to read
1256      * the resource.  This includes the file descriptor itself, as well as the
1257      * offset and length of data where the resource appears in the file.  A
1258      * null is returned if the file exists but is compressed.
1259      *
1260      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1261      * 
1262      */
1263     public AssetFileDescriptor openRawResourceFd(@RawRes int id)
1264             throws NotFoundException {
1265         final TypedValue value = obtainTempTypedValue();
1266         try {
1267             return mResourcesImpl.openRawResourceFd(id, value);
1268         } finally {
1269             releaseTempTypedValue(value);
1270         }
1271     }
1272
1273     /**
1274      * Return the raw data associated with a particular resource ID.
1275      * 
1276      * @param id The desired resource identifier, as generated by the aapt
1277      *           tool. This integer encodes the package, type, and resource
1278      *           entry. The value 0 is an invalid identifier.
1279      * @param outValue Object in which to place the resource data.
1280      * @param resolveRefs If true, a resource that is a reference to another
1281      *                    resource will be followed so that you receive the
1282      *                    actual final resource data.  If false, the TypedValue
1283      *                    will be filled in with the reference itself.
1284      *
1285      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1286      *
1287      */
1288     public void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs)
1289             throws NotFoundException {
1290         mResourcesImpl.getValue(id, outValue, resolveRefs);
1291     }
1292
1293     /**
1294      * Get the raw value associated with a resource with associated density.
1295      * 
1296      * @param id resource identifier
1297      * @param density density in DPI
1298      * @param resolveRefs If true, a resource that is a reference to another
1299      *            resource will be followed so that you receive the actual final
1300      *            resource data. If false, the TypedValue will be filled in with
1301      *            the reference itself.
1302      * @throws NotFoundException Throws NotFoundException if the given ID does
1303      *             not exist.
1304      * @see #getValue(String, TypedValue, boolean)
1305      */
1306     public void getValueForDensity(@AnyRes int id, int density, TypedValue outValue,
1307             boolean resolveRefs) throws NotFoundException {
1308         mResourcesImpl.getValueForDensity(id, density, outValue, resolveRefs);
1309     }
1310
1311     /**
1312      * Return the raw data associated with a particular resource ID.
1313      * See getIdentifier() for information on how names are mapped to resource
1314      * IDs, and getString(int) for information on how string resources are
1315      * retrieved.
1316      * 
1317      * <p>Note: use of this function is discouraged.  It is much more
1318      * efficient to retrieve resources by identifier than by name.
1319      * 
1320      * @param name The name of the desired resource.  This is passed to
1321      *             getIdentifier() with a default type of "string".
1322      * @param outValue Object in which to place the resource data.
1323      * @param resolveRefs If true, a resource that is a reference to another
1324      *                    resource will be followed so that you receive the
1325      *                    actual final resource data.  If false, the TypedValue
1326      *                    will be filled in with the reference itself.
1327      *
1328      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1329      *
1330      */
1331     public void getValue(String name, TypedValue outValue, boolean resolveRefs)
1332             throws NotFoundException {
1333         mResourcesImpl.getValue(name, outValue, resolveRefs);
1334     }
1335
1336     /**
1337      * This class holds the current attribute values for a particular theme.
1338      * In other words, a Theme is a set of values for resource attributes;
1339      * these are used in conjunction with {@link TypedArray}
1340      * to resolve the final value for an attribute.
1341      * 
1342      * <p>The Theme's attributes come into play in two ways: (1) a styled
1343      * attribute can explicit reference a value in the theme through the
1344      * "?themeAttribute" syntax; (2) if no value has been defined for a
1345      * particular styled attribute, as a last resort we will try to find that
1346      * attribute's value in the Theme.
1347      * 
1348      * <p>You will normally use the {@link #obtainStyledAttributes} APIs to
1349      * retrieve XML attributes with style and theme information applied.
1350      */
1351     public final class Theme {
1352         private ResourcesImpl.ThemeImpl mThemeImpl;
1353
1354         private Theme() {
1355         }
1356
1357         void setImpl(ResourcesImpl.ThemeImpl impl) {
1358             mThemeImpl = impl;
1359         }
1360
1361         /**
1362          * Place new attribute values into the theme.  The style resource
1363          * specified by <var>resid</var> will be retrieved from this Theme's
1364          * resources, its values placed into the Theme object.
1365          * 
1366          * <p>The semantics of this function depends on the <var>force</var>
1367          * argument:  If false, only values that are not already defined in
1368          * the theme will be copied from the system resource; otherwise, if
1369          * any of the style's attributes are already defined in the theme, the
1370          * current values in the theme will be overwritten.
1371          * 
1372          * @param resId The resource ID of a style resource from which to
1373          *              obtain attribute values.
1374          * @param force If true, values in the style resource will always be
1375          *              used in the theme; otherwise, they will only be used
1376          *              if not already defined in the theme.
1377          */
1378         public void applyStyle(int resId, boolean force) {
1379             mThemeImpl.applyStyle(resId, force);
1380         }
1381
1382         /**
1383          * Set this theme to hold the same contents as the theme
1384          * <var>other</var>.  If both of these themes are from the same
1385          * Resources object, they will be identical after this function
1386          * returns.  If they are from different Resources, only the resources
1387          * they have in common will be set in this theme.
1388          * 
1389          * @param other The existing Theme to copy from.
1390          */
1391         public void setTo(Theme other) {
1392             mThemeImpl.setTo(other.mThemeImpl);
1393         }
1394
1395         /**
1396          * Return a TypedArray holding the values defined by
1397          * <var>Theme</var> which are listed in <var>attrs</var>.
1398          * 
1399          * <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done
1400          * with the array.
1401          * 
1402          * @param attrs The desired attributes.
1403          *
1404          * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1405          * 
1406          * @return Returns a TypedArray holding an array of the attribute values.
1407          * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
1408          * when done with it.
1409          * 
1410          * @see Resources#obtainAttributes
1411          * @see #obtainStyledAttributes(int, int[])
1412          * @see #obtainStyledAttributes(AttributeSet, int[], int, int)
1413          */
1414         public TypedArray obtainStyledAttributes(@StyleableRes int[] attrs) {
1415             return mThemeImpl.obtainStyledAttributes(this, null, attrs, 0, 0);
1416         }
1417
1418         /**
1419          * Return a TypedArray holding the values defined by the style
1420          * resource <var>resid</var> which are listed in <var>attrs</var>.
1421          * 
1422          * <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done
1423          * with the array.
1424          * 
1425          * @param resId The desired style resource.
1426          * @param attrs The desired attributes in the style.
1427          * 
1428          * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1429          * 
1430          * @return Returns a TypedArray holding an array of the attribute values.
1431          * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
1432          * when done with it.
1433          * 
1434          * @see Resources#obtainAttributes
1435          * @see #obtainStyledAttributes(int[])
1436          * @see #obtainStyledAttributes(AttributeSet, int[], int, int)
1437          */
1438         public TypedArray obtainStyledAttributes(@StyleRes int resId, @StyleableRes int[] attrs)
1439                 throws NotFoundException {
1440             return mThemeImpl.obtainStyledAttributes(this, null, attrs, 0, resId);
1441         }
1442
1443         /**
1444          * Return a TypedArray holding the attribute values in
1445          * <var>set</var>
1446          * that are listed in <var>attrs</var>.  In addition, if the given
1447          * AttributeSet specifies a style class (through the "style" attribute),
1448          * that style will be applied on top of the base attributes it defines.
1449          * 
1450          * <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done
1451          * with the array.
1452          * 
1453          * <p>When determining the final value of a particular attribute, there
1454          * are four inputs that come into play:</p>
1455          * 
1456          * <ol>
1457          *     <li> Any attribute values in the given AttributeSet.
1458          *     <li> The style resource specified in the AttributeSet (named
1459          *     "style").
1460          *     <li> The default style specified by <var>defStyleAttr</var> and
1461          *     <var>defStyleRes</var>
1462          *     <li> The base values in this theme.
1463          * </ol>
1464          * 
1465          * <p>Each of these inputs is considered in-order, with the first listed
1466          * taking precedence over the following ones.  In other words, if in the
1467          * AttributeSet you have supplied <code>&lt;Button
1468          * textColor="#ff000000"&gt;</code>, then the button's text will
1469          * <em>always</em> be black, regardless of what is specified in any of
1470          * the styles.
1471          * 
1472          * @param set The base set of attribute values.  May be null.
1473          * @param attrs The desired attributes to be retrieved.
1474          * @param defStyleAttr An attribute in the current theme that contains a
1475          *                     reference to a style resource that supplies
1476          *                     defaults values for the TypedArray.  Can be
1477          *                     0 to not look for defaults.
1478          * @param defStyleRes A resource identifier of a style resource that
1479          *                    supplies default values for the TypedArray,
1480          *                    used only if defStyleAttr is 0 or can not be found
1481          *                    in the theme.  Can be 0 to not look for defaults.
1482          * 
1483          * @return Returns a TypedArray holding an array of the attribute values.
1484          * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
1485          * when done with it.
1486          * 
1487          * @see Resources#obtainAttributes
1488          * @see #obtainStyledAttributes(int[])
1489          * @see #obtainStyledAttributes(int, int[])
1490          */
1491         public TypedArray obtainStyledAttributes(AttributeSet set,
1492                 @StyleableRes int[] attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
1493             return mThemeImpl.obtainStyledAttributes(this, set, attrs, defStyleAttr, defStyleRes);
1494         }
1495
1496         /**
1497          * Retrieve the values for a set of attributes in the Theme. The
1498          * contents of the typed array are ultimately filled in by
1499          * {@link Resources#getValue}.
1500          *
1501          * @param values The base set of attribute values, must be equal in
1502          *               length to {@code attrs}. All values must be of type
1503          *               {@link TypedValue#TYPE_ATTRIBUTE}.
1504          * @param attrs The desired attributes to be retrieved.
1505          * @return Returns a TypedArray holding an array of the attribute
1506          *         values. Be sure to call {@link TypedArray#recycle()}
1507          *         when done with it.
1508          * @hide
1509          */
1510         @NonNull
1511         public TypedArray resolveAttributes(@NonNull int[] values, @NonNull int[] attrs) {
1512             return mThemeImpl.resolveAttributes(this, values, attrs);
1513         }
1514
1515         /**
1516          * Retrieve the value of an attribute in the Theme.  The contents of
1517          * <var>outValue</var> are ultimately filled in by
1518          * {@link Resources#getValue}.
1519          * 
1520          * @param resid The resource identifier of the desired theme
1521          *              attribute.
1522          * @param outValue Filled in with the ultimate resource value supplied
1523          *                 by the attribute.
1524          * @param resolveRefs If true, resource references will be walked; if
1525          *                    false, <var>outValue</var> may be a
1526          *                    TYPE_REFERENCE.  In either case, it will never
1527          *                    be a TYPE_ATTRIBUTE.
1528          * 
1529          * @return boolean Returns true if the attribute was found and
1530          *         <var>outValue</var> is valid, else false.
1531          */
1532         public boolean resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
1533             return mThemeImpl.resolveAttribute(resid, outValue, resolveRefs);
1534         }
1535
1536         /**
1537          * Gets all of the attribute ids associated with this {@link Theme}. For debugging only.
1538          *
1539          * @return The int array containing attribute ids associated with this {@link Theme}.
1540          * @hide
1541          */
1542         public int[] getAllAttributes() {
1543             return mThemeImpl.getAllAttributes();
1544         }
1545
1546         /**
1547          * Returns the resources to which this theme belongs.
1548          *
1549          * @return Resources to which this theme belongs.
1550          */
1551         public Resources getResources() {
1552             return Resources.this;
1553         }
1554
1555         /**
1556          * Return a drawable object associated with a particular resource ID
1557          * and styled for the Theme.
1558          *
1559          * @param id The desired resource identifier, as generated by the aapt
1560          *           tool. This integer encodes the package, type, and resource
1561          *           entry. The value 0 is an invalid identifier.
1562          * @return Drawable An object that can be used to draw this resource.
1563          * @throws NotFoundException Throws NotFoundException if the given ID
1564          *         does not exist.
1565          */
1566         public Drawable getDrawable(@DrawableRes int id) throws NotFoundException {
1567             return Resources.this.getDrawable(id, this);
1568         }
1569
1570         /**
1571          * Returns a bit mask of configuration changes that will impact this
1572          * theme (and thus require completely reloading it).
1573          *
1574          * @return a bit mask of configuration changes, as defined by
1575          *         {@link ActivityInfo}
1576          * @see ActivityInfo
1577          */
1578         public int getChangingConfigurations() {
1579             return mThemeImpl.getChangingConfigurations();
1580         }
1581
1582         /**
1583          * Print contents of this theme out to the log.  For debugging only.
1584          * 
1585          * @param priority The log priority to use.
1586          * @param tag The log tag to use.
1587          * @param prefix Text to prefix each line printed.
1588          */
1589         public void dump(int priority, String tag, String prefix) {
1590             mThemeImpl.dump(priority, tag, prefix);
1591         }
1592
1593         // Needed by layoutlib.
1594         /*package*/ long getNativeTheme() {
1595             return mThemeImpl.getNativeTheme();
1596         }
1597
1598         /*package*/ int getAppliedStyleResId() {
1599             return mThemeImpl.getAppliedStyleResId();
1600         }
1601
1602         /**
1603          * @hide
1604          */
1605         public ThemeKey getKey() {
1606             return mThemeImpl.getKey();
1607         }
1608
1609         private String getResourceNameFromHexString(String hexString) {
1610             return getResourceName(Integer.parseInt(hexString, 16));
1611         }
1612
1613         /**
1614          * Parses {@link #getKey()} and returns a String array that holds pairs of
1615          * adjacent Theme data: resource name followed by whether or not it was
1616          * forced, as specified by {@link #applyStyle(int, boolean)}.
1617          *
1618          * @hide
1619          */
1620         @ViewDebug.ExportedProperty(category = "theme", hasAdjacentMapping = true)
1621         public String[] getTheme() {
1622             return mThemeImpl.getTheme();
1623         }
1624
1625         /** @hide */
1626         public void encode(@NonNull ViewHierarchyEncoder encoder) {
1627             encoder.beginObject(this);
1628             final String[] properties = getTheme();
1629             for (int i = 0; i < properties.length; i += 2) {
1630                 encoder.addProperty(properties[i], properties[i+1]);
1631             }
1632             encoder.endObject();
1633         }
1634
1635         /**
1636          * Rebases the theme against the parent Resource object's current
1637          * configuration by re-applying the styles passed to
1638          * {@link #applyStyle(int, boolean)}.
1639          *
1640          * @hide
1641          */
1642         public void rebase() {
1643             mThemeImpl.rebase();
1644         }
1645     }
1646
1647     static class ThemeKey implements Cloneable {
1648         int[] mResId;
1649         boolean[] mForce;
1650         int mCount;
1651
1652         private int mHashCode = 0;
1653
1654         public void append(int resId, boolean force) {
1655             if (mResId == null) {
1656                 mResId = new int[4];
1657             }
1658
1659             if (mForce == null) {
1660                 mForce = new boolean[4];
1661             }
1662
1663             mResId = GrowingArrayUtils.append(mResId, mCount, resId);
1664             mForce = GrowingArrayUtils.append(mForce, mCount, force);
1665             mCount++;
1666
1667             mHashCode = 31 * (31 * mHashCode + resId) + (force ? 1 : 0);
1668         }
1669
1670         /**
1671          * Sets up this key as a deep copy of another key.
1672          *
1673          * @param other the key to deep copy into this key
1674          */
1675         public void setTo(ThemeKey other) {
1676             mResId = other.mResId == null ? null : other.mResId.clone();
1677             mForce = other.mForce == null ? null : other.mForce.clone();
1678             mCount = other.mCount;
1679         }
1680
1681         @Override
1682         public int hashCode() {
1683             return mHashCode;
1684         }
1685
1686         @Override
1687         public boolean equals(Object o) {
1688             if (this == o) {
1689                 return true;
1690             }
1691
1692             if (o == null || getClass() != o.getClass() || hashCode() != o.hashCode()) {
1693                 return false;
1694             }
1695
1696             final ThemeKey t = (ThemeKey) o;
1697             if (mCount != t.mCount) {
1698                 return false;
1699             }
1700
1701             final int N = mCount;
1702             for (int i = 0; i < N; i++) {
1703                 if (mResId[i] != t.mResId[i] || mForce[i] != t.mForce[i]) {
1704                     return false;
1705                 }
1706             }
1707
1708             return true;
1709         }
1710
1711         /**
1712          * @return a shallow copy of this key
1713          */
1714         @Override
1715         public ThemeKey clone() {
1716             final ThemeKey other = new ThemeKey();
1717             other.mResId = mResId;
1718             other.mForce = mForce;
1719             other.mCount = mCount;
1720             other.mHashCode = mHashCode;
1721             return other;
1722         }
1723     }
1724
1725     /**
1726      * Generate a new Theme object for this set of Resources.  It initially
1727      * starts out empty.
1728      *
1729      * @return Theme The newly created Theme container.
1730      */
1731     public final Theme newTheme() {
1732         Theme theme = new Theme();
1733         theme.setImpl(mResourcesImpl.newThemeImpl());
1734         mThemeRefs.add(new WeakReference<>(theme));
1735         return theme;
1736     }
1737
1738     /**
1739      * Retrieve a set of basic attribute values from an AttributeSet, not
1740      * performing styling of them using a theme and/or style resources.
1741      *
1742      * @param set The current attribute values to retrieve.
1743      * @param attrs The specific attributes to be retrieved.
1744      * @return Returns a TypedArray holding an array of the attribute values.
1745      * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
1746      * when done with it.
1747      * 
1748      * @see Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
1749      */
1750     public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
1751         int len = attrs.length;
1752         TypedArray array = TypedArray.obtain(this, len);
1753
1754         // XXX note that for now we only work with compiled XML files.
1755         // To support generic XML files we will need to manually parse
1756         // out the attributes from the XML file (applying type information
1757         // contained in the resources and such).
1758         XmlBlock.Parser parser = (XmlBlock.Parser)set;
1759         mResourcesImpl.getAssets().retrieveAttributes(parser.mParseState, attrs,
1760                 array.mData, array.mIndices);
1761
1762         array.mXml = parser;
1763
1764         return array;
1765     }
1766
1767     /**
1768      * Store the newly updated configuration.
1769      *
1770      * @deprecated See {@link android.content.Context#createConfigurationContext(Configuration)}.
1771      */
1772     @Deprecated
1773     public void updateConfiguration(Configuration config, DisplayMetrics metrics) {
1774         updateConfiguration(config, metrics, null);
1775     }
1776
1777     /**
1778      * @hide
1779      */
1780     public void updateConfiguration(Configuration config, DisplayMetrics metrics,
1781                                     CompatibilityInfo compat) {
1782         mResourcesImpl.updateConfiguration(config, metrics, compat);
1783     }
1784
1785     /**
1786      * Update the system resources configuration if they have previously
1787      * been initialized.
1788      *
1789      * @hide
1790      */
1791     public static void updateSystemConfiguration(Configuration config, DisplayMetrics metrics,
1792             CompatibilityInfo compat) {
1793         if (mSystem != null) {
1794             mSystem.updateConfiguration(config, metrics, compat);
1795             //Log.i(TAG, "Updated system resources " + mSystem
1796             //        + ": " + mSystem.getConfiguration());
1797         }
1798     }
1799
1800     /**
1801      * Return the current display metrics that are in effect for this resource 
1802      * object.  The returned object should be treated as read-only.
1803      * 
1804      * @return The resource's current display metrics. 
1805      */
1806     public DisplayMetrics getDisplayMetrics() {
1807         return mResourcesImpl.getDisplayMetrics();
1808     }
1809
1810     /** @hide */
1811     public DisplayAdjustments getDisplayAdjustments() {
1812         return mResourcesImpl.getDisplayAdjustments();
1813     }
1814
1815     /**
1816      * Return the current configuration that is in effect for this resource 
1817      * object.  The returned object should be treated as read-only.
1818      * 
1819      * @return The resource's current configuration. 
1820      */
1821     public Configuration getConfiguration() {
1822         return mResourcesImpl.getConfiguration();
1823     }
1824
1825     /** @hide */
1826     public Configuration[] getSizeConfigurations() {
1827         return mResourcesImpl.getSizeConfigurations();
1828     }
1829
1830     /**
1831      * Return the compatibility mode information for the application.
1832      * The returned object should be treated as read-only.
1833      * 
1834      * @return compatibility info.
1835      * @hide
1836      */
1837     public CompatibilityInfo getCompatibilityInfo() {
1838         return mResourcesImpl.getCompatibilityInfo();
1839     }
1840
1841     /**
1842      * This is just for testing.
1843      * @hide
1844      */
1845     @VisibleForTesting
1846     public void setCompatibilityInfo(CompatibilityInfo ci) {
1847         if (ci != null) {
1848             mResourcesImpl.updateConfiguration(null, null, ci);
1849         }
1850     }
1851     
1852     /**
1853      * Return a resource identifier for the given resource name.  A fully
1854      * qualified resource name is of the form "package:type/entry".  The first
1855      * two components (package and type) are optional if defType and
1856      * defPackage, respectively, are specified here.
1857      * 
1858      * <p>Note: use of this function is discouraged.  It is much more
1859      * efficient to retrieve resources by identifier than by name.
1860      * 
1861      * @param name The name of the desired resource.
1862      * @param defType Optional default resource type to find, if "type/" is
1863      *                not included in the name.  Can be null to require an
1864      *                explicit type.
1865      * @param defPackage Optional default package to find, if "package:" is
1866      *                   not included in the name.  Can be null to require an
1867      *                   explicit package.
1868      * 
1869      * @return int The associated resource identifier.  Returns 0 if no such
1870      *         resource was found.  (0 is not a valid resource ID.)
1871      */
1872     public int getIdentifier(String name, String defType, String defPackage) {
1873         return mResourcesImpl.getIdentifier(name, defType, defPackage);
1874     }
1875
1876     /**
1877      * Return true if given resource identifier includes a package.
1878      *
1879      * @hide
1880      */
1881     public static boolean resourceHasPackage(@AnyRes int resid) {
1882         return (resid >>> 24) != 0;
1883     }
1884
1885     /**
1886      * Return the full name for a given resource identifier.  This name is
1887      * a single string of the form "package:type/entry".
1888      * 
1889      * @param resid The resource identifier whose name is to be retrieved.
1890      * 
1891      * @return A string holding the name of the resource.
1892      * 
1893      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1894      * 
1895      * @see #getResourcePackageName
1896      * @see #getResourceTypeName
1897      * @see #getResourceEntryName
1898      */
1899     public String getResourceName(@AnyRes int resid) throws NotFoundException {
1900         return mResourcesImpl.getResourceName(resid);
1901     }
1902     
1903     /**
1904      * Return the package name for a given resource identifier.
1905      * 
1906      * @param resid The resource identifier whose package name is to be
1907      * retrieved.
1908      * 
1909      * @return A string holding the package name of the resource.
1910      * 
1911      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1912      * 
1913      * @see #getResourceName
1914      */
1915     public String getResourcePackageName(@AnyRes int resid) throws NotFoundException {
1916         return mResourcesImpl.getResourcePackageName(resid);
1917     }
1918     
1919     /**
1920      * Return the type name for a given resource identifier.
1921      * 
1922      * @param resid The resource identifier whose type name is to be
1923      * retrieved.
1924      * 
1925      * @return A string holding the type name of the resource.
1926      * 
1927      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1928      * 
1929      * @see #getResourceName
1930      */
1931     public String getResourceTypeName(@AnyRes int resid) throws NotFoundException {
1932         return mResourcesImpl.getResourceTypeName(resid);
1933     }
1934     
1935     /**
1936      * Return the entry name for a given resource identifier.
1937      * 
1938      * @param resid The resource identifier whose entry name is to be
1939      * retrieved.
1940      * 
1941      * @return A string holding the entry name of the resource.
1942      * 
1943      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1944      * 
1945      * @see #getResourceName
1946      */
1947     public String getResourceEntryName(@AnyRes int resid) throws NotFoundException {
1948         return mResourcesImpl.getResourceEntryName(resid);
1949     }
1950     
1951     /**
1952      * Parse a series of {@link android.R.styleable#Extra &lt;extra&gt;} tags from
1953      * an XML file.  You call this when you are at the parent tag of the
1954      * extra tags, and it will return once all of the child tags have been parsed.
1955      * This will call {@link #parseBundleExtra} for each extra tag encountered.
1956      * 
1957      * @param parser The parser from which to retrieve the extras.
1958      * @param outBundle A Bundle in which to place all parsed extras.
1959      * @throws XmlPullParserException
1960      * @throws IOException
1961      */
1962     public void parseBundleExtras(XmlResourceParser parser, Bundle outBundle)
1963             throws XmlPullParserException, IOException {
1964         int outerDepth = parser.getDepth();
1965         int type;
1966         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1967                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1968             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1969                 continue;
1970             }
1971             
1972             String nodeName = parser.getName();
1973             if (nodeName.equals("extra")) {
1974                 parseBundleExtra("extra", parser, outBundle);
1975                 XmlUtils.skipCurrentTag(parser);
1976
1977             } else {
1978                 XmlUtils.skipCurrentTag(parser);
1979             }
1980         }        
1981     }
1982     
1983     /**
1984      * Parse a name/value pair out of an XML tag holding that data.  The
1985      * AttributeSet must be holding the data defined by
1986      * {@link android.R.styleable#Extra}.  The following value types are supported:
1987      * <ul>
1988      * <li> {@link TypedValue#TYPE_STRING}:
1989      * {@link Bundle#putCharSequence Bundle.putCharSequence()}
1990      * <li> {@link TypedValue#TYPE_INT_BOOLEAN}:
1991      * {@link Bundle#putCharSequence Bundle.putBoolean()}
1992      * <li> {@link TypedValue#TYPE_FIRST_INT}-{@link TypedValue#TYPE_LAST_INT}:
1993      * {@link Bundle#putCharSequence Bundle.putBoolean()}
1994      * <li> {@link TypedValue#TYPE_FLOAT}:
1995      * {@link Bundle#putCharSequence Bundle.putFloat()}
1996      * </ul>
1997      * 
1998      * @param tagName The name of the tag these attributes come from; this is
1999      * only used for reporting error messages.
2000      * @param attrs The attributes from which to retrieve the name/value pair.
2001      * @param outBundle The Bundle in which to place the parsed value.
2002      * @throws XmlPullParserException If the attributes are not valid.
2003      */
2004     public void parseBundleExtra(String tagName, AttributeSet attrs,
2005             Bundle outBundle) throws XmlPullParserException {
2006         TypedArray sa = obtainAttributes(attrs,
2007                 com.android.internal.R.styleable.Extra);
2008
2009         String name = sa.getString(
2010                 com.android.internal.R.styleable.Extra_name);
2011         if (name == null) {
2012             sa.recycle();
2013             throw new XmlPullParserException("<" + tagName
2014                     + "> requires an android:name attribute at "
2015                     + attrs.getPositionDescription());
2016         }
2017
2018         TypedValue v = sa.peekValue(
2019                 com.android.internal.R.styleable.Extra_value);
2020         if (v != null) {
2021             if (v.type == TypedValue.TYPE_STRING) {
2022                 CharSequence cs = v.coerceToString();
2023                 outBundle.putCharSequence(name, cs);
2024             } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
2025                 outBundle.putBoolean(name, v.data != 0);
2026             } else if (v.type >= TypedValue.TYPE_FIRST_INT
2027                     && v.type <= TypedValue.TYPE_LAST_INT) {
2028                 outBundle.putInt(name, v.data);
2029             } else if (v.type == TypedValue.TYPE_FLOAT) {
2030                 outBundle.putFloat(name, v.getFloat());
2031             } else {
2032                 sa.recycle();
2033                 throw new XmlPullParserException("<" + tagName
2034                         + "> only supports string, integer, float, color, and boolean at "
2035                         + attrs.getPositionDescription());
2036             }
2037         } else {
2038             sa.recycle();
2039             throw new XmlPullParserException("<" + tagName
2040                     + "> requires an android:value or android:resource attribute at "
2041                     + attrs.getPositionDescription());
2042         }
2043
2044         sa.recycle();
2045     }
2046     
2047     /**
2048      * Retrieve underlying AssetManager storage for these resources.
2049      */
2050     public final AssetManager getAssets() {
2051         return mResourcesImpl.getAssets();
2052     }
2053
2054     /**
2055      * Call this to remove all cached loaded layout resources from the
2056      * Resources object.  Only intended for use with performance testing
2057      * tools.
2058      */
2059     public final void flushLayoutCache() {
2060         mResourcesImpl.flushLayoutCache();
2061     }
2062
2063     /**
2064      * Start preloading of resource data using this Resources object.  Only
2065      * for use by the zygote process for loading common system resources.
2066      * {@hide}
2067      */
2068     public final void startPreloading() {
2069         mResourcesImpl.startPreloading();
2070     }
2071     
2072     /**
2073      * Called by zygote when it is done preloading resources, to change back
2074      * to normal Resources operation.
2075      */
2076     public final void finishPreloading() {
2077         mResourcesImpl.finishPreloading();
2078     }
2079
2080     /**
2081      * @hide
2082      */
2083     public LongSparseArray<ConstantState> getPreloadedDrawables() {
2084         return mResourcesImpl.getPreloadedDrawables();
2085     }
2086
2087     /**
2088      * Loads an XML parser for the specified file.
2089      *
2090      * @param id the resource identifier for the file
2091      * @param type the type of resource (used for logging)
2092      * @return a parser for the specified XML file
2093      * @throws NotFoundException if the file could not be loaded
2094      */
2095     @NonNull
2096     XmlResourceParser loadXmlResourceParser(@AnyRes int id, @NonNull String type)
2097             throws NotFoundException {
2098         final TypedValue value = obtainTempTypedValue();
2099         try {
2100             final ResourcesImpl impl = mResourcesImpl;
2101             impl.getValue(id, value, true);
2102             if (value.type == TypedValue.TYPE_STRING) {
2103                 return impl.loadXmlResourceParser(value.string.toString(), id,
2104                         value.assetCookie, type);
2105             }
2106             throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
2107                     + " type #0x" + Integer.toHexString(value.type) + " is not valid");
2108         } finally {
2109             releaseTempTypedValue(value);
2110         }
2111     }
2112
2113     /**
2114      * Loads an XML parser for the specified file.
2115      *
2116      * @param file the path for the XML file to parse
2117      * @param id the resource identifier for the file
2118      * @param assetCookie the asset cookie for the file
2119      * @param type the type of resource (used for logging)
2120      * @return a parser for the specified XML file
2121      * @throws NotFoundException if the file could not be loaded
2122      */
2123     @NonNull
2124     XmlResourceParser loadXmlResourceParser(String file, int id, int assetCookie,
2125                                             String type) throws NotFoundException {
2126         return mResourcesImpl.loadXmlResourceParser(file, id, assetCookie, type);
2127     }
2128
2129     /**
2130      * Called by ConfigurationBoundResourceCacheTest.
2131      * @hide
2132      */
2133     @VisibleForTesting
2134     public int calcConfigChanges(Configuration config) {
2135         return mResourcesImpl.calcConfigChanges(config);
2136     }
2137
2138     /**
2139      * Obtains styled attributes from the theme, if available, or unstyled
2140      * resources if the theme is null.
2141      *
2142      * @hide
2143      */
2144     public static TypedArray obtainAttributes(
2145             Resources res, Theme theme, AttributeSet set, int[] attrs) {
2146         if (theme == null) {
2147             return res.obtainAttributes(set, attrs);
2148         }
2149         return theme.obtainStyledAttributes(set, attrs, 0, 0);
2150     }
2151 }