Resources.java revision e5b50a65ad26a32f6e58588ffdcbc0389eac9257
1ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa/*
2ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * Copyright (C) 2006 The Android Open Source Project
3ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa *
4ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * Licensed under the Apache License, Version 2.0 (the "License");
5ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * you may not use this file except in compliance with the License.
6ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * You may obtain a copy of the License at
7ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa *
8ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa *      http://www.apache.org/licenses/LICENSE-2.0
9ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa *
10ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * Unless required by applicable law or agreed to in writing, software
11ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * distributed under the License is distributed on an "AS IS" BASIS,
12ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * See the License for the specific language governing permissions and
14ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * limitations under the License.
15ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa */
16ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
17ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaapackage android.content.res;
18ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
19a62050d42c7d76d57ae555ffcb6d8efc5cf79de1destradaaimport com.android.internal.util.XmlUtils;
20ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
21ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport org.xmlpull.v1.XmlPullParser;
22ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport org.xmlpull.v1.XmlPullParserException;
23ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
24ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.content.pm.ActivityInfo;
25ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.graphics.Movie;
26ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.graphics.drawable.Drawable;
27ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.graphics.drawable.ColorDrawable;
28ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.graphics.drawable.Drawable.ConstantState;
29a62050d42c7d76d57ae555ffcb6d8efc5cf79de1destradaaimport android.os.Build;
30ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.os.Bundle;
31ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.util.AttributeSet;
32ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.util.DisplayMetrics;
332102dd725540bcf51bf324a2775fbcffe45dd32fdestradaaimport android.util.Log;
34ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.util.Slog;
352102dd725540bcf51bf324a2775fbcffe45dd32fdestradaaimport android.util.TypedValue;
362102dd725540bcf51bf324a2775fbcffe45dd32fdestradaaimport android.util.LongSparseArray;
37ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
3881cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaaimport java.io.IOException;
39ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport java.io.InputStream;
40ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport java.lang.ref.WeakReference;
41ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport java.util.Locale;
422102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
43ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport libcore.icu.NativePluralRules;
44ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
45ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa/**
46ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * Class for accessing an application's resources.  This sits on top of the
47ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * asset manager of the application (accessible through {@link #getAssets}) and
48ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * provides a high-level API for getting typed data from the assets.
49ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa *
50ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * <p>The Android resource system keeps track of all non-code assets associated with an
51ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * application. You can use this class to access your application's resources. You can generally
52ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * acquire the {@link android.content.res.Resources} instance associated with your application
532102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa * with {@link android.content.Context#getResources getResources()}.</p>
5452617bbff8607cdc208ba107ec111bd1471433cbTsuwei Chen *
552102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa * <p>The Android SDK tools compile your application's resources into the application binary
56ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * at build time.  To use a resource, you must install it correctly in the source tree (inside
57ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * your project's {@code res/} directory) and build your application.  As part of the build
582102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa * process, the SDK tools generate symbols for each resource, which you can use in your application
59ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * code to access the resources.</p>
60ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa *
61ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * <p>Using application resources makes it easy to update various characteristics of your
62ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * application without modifying code, and&mdash;by providing sets of alternative
63ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * resources&mdash;enables you to optimize your application for a variety of device configurations
64ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * (such as for different languages and screen sizes). This is an important aspect of developing
65ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * Android applications that are compatible on different types of devices.</p>
66ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa *
67ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * <p>For more information about using resources, see the documentation about <a
682102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa * href="{@docRoot}guide/topics/resources/index.html">Application Resources</a>.</p>
692102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa */
702102dd725540bcf51bf324a2775fbcffe45dd32fdestradaapublic class Resources {
712102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    static final String TAG = "Resources";
722102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private static final boolean DEBUG_LOAD = false;
732102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private static final boolean DEBUG_CONFIG = false;
742102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private static final boolean DEBUG_ATTRIBUTES_CACHE = false;
752102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private static final boolean TRACE_FOR_PRELOAD = false;
762102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private static final boolean TRACE_FOR_MISS_PRELOAD = false;
772102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
782102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private static final int ID_OTHER = 0x01000004;
792102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
802102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private static final Object sSync = new Object();
812102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /*package*/ static Resources mSystem = null;
822102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
832102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    // Information about preloaded resources.  Note that they are not
842102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    // protected by a lock, because while preloading in zygote we are all
852102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    // single-threaded, and after that these are immutable.
862102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private static final LongSparseArray<Drawable.ConstantState> sPreloadedDrawables
87ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            = new LongSparseArray<Drawable.ConstantState>();
88ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    private static final LongSparseArray<ColorStateList> sPreloadedColorStateLists
89ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            = new LongSparseArray<ColorStateList>();
902102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
91ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            = new LongSparseArray<Drawable.ConstantState>();
92ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    private static boolean sPreloaded;
93ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    private static int sPreloadedDensity;
94ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
952102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    // These are protected by mAccessLock.
96ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
97ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /*package*/ final Object mAccessLock = new Object();
98ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /*package*/ final Configuration mTmpConfig = new Configuration();
99ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /*package*/ TypedValue mTmpValue = new TypedValue();
1002102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /*package*/ final LongSparseArray<WeakReference<Drawable.ConstantState> > mDrawableCache
101ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            = new LongSparseArray<WeakReference<Drawable.ConstantState> >();
102ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /*package*/ final LongSparseArray<WeakReference<ColorStateList> > mColorStateListCache
103ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            = new LongSparseArray<WeakReference<ColorStateList> >();
104ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /*package*/ final LongSparseArray<WeakReference<Drawable.ConstantState> > mColorDrawableCache
1052102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            = new LongSparseArray<WeakReference<Drawable.ConstantState> >();
106ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /*package*/ boolean mPreloading;
107ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
108ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /*package*/ TypedArray mCachedStyledAttributes = null;
109ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    RuntimeException mLastRetrievedAttrs = null;
1102102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
111ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    private int mLastCachedXmlBlockIndex = -1;
112ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    private final int[] mCachedXmlBlockIds = { 0, 0, 0, 0 };
113ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[4];
114ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
1152102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /*package*/ final AssetManager mAssets;
1162102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private final Configuration mConfiguration = new Configuration();
1172102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /*package*/ final DisplayMetrics mMetrics = new DisplayMetrics();
1182102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private NativePluralRules mPluralRule;
1192102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
1202102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private CompatibilityInfo mCompatibilityInfo;
1212102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
1222102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /** @hide */
1232102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
1242102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        return selectSystemTheme(curTheme, targetSdkVersion,
1252102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                com.android.internal.R.style.Theme,
1262102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                com.android.internal.R.style.Theme_Holo,
1272102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                com.android.internal.R.style.Theme_DeviceDefault);
1282102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    }
1292102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
1302102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /** @hide */
1312102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    public static int selectSystemTheme(int curTheme, int targetSdkVersion,
1322102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            int orig, int holo, int deviceDefault) {
1332102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        if (curTheme != 0) {
1342102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            return curTheme;
1352102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        }
1362102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        if (targetSdkVersion < Build.VERSION_CODES.HONEYCOMB) {
1372102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            return orig;
1382102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        }
1392102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        if (targetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
1402102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            return holo;
1412102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        }
1422102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        return deviceDefault;
1432102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    }
1442102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
1452102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /**
1462102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * This exception is thrown by the resource APIs when a requested resource
1472102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * can not be found.
1482102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     */
1492102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    public static class NotFoundException extends RuntimeException {
1502102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        public NotFoundException() {
1512102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        }
1522102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
1532102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        public NotFoundException(String name) {
1542102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            super(name);
1552102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        }
1562102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    }
1572102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
1582102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /**
1592102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * Create a new Resources object on top of an existing set of assets in an
1602102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * AssetManager.
161ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
162ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param assets Previously created AssetManager.
163ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param metrics Current display metrics to consider when
164ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *                selecting/computing resource values.
1652102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param config Desired device configuration to consider when
166ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *               selecting/computing resource values (optional).
167ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
168ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
169ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        this(assets, metrics, config, null);
170ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
171ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
1722102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /**
173ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Creates a new Resources object with CompatibilityInfo.
1742102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
1752102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param assets Previously created AssetManager.
176ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param metrics Current display metrics to consider when
17781cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     *                selecting/computing resource values.
178ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param config Desired device configuration to consider when
179ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *               selecting/computing resource values (optional).
180ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param compInfo this resource's compatibility info. It will use the default compatibility
181ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *  info when it's null.
1822102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @hide
183ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
184ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public Resources(AssetManager assets, DisplayMetrics metrics,
185ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            Configuration config, CompatibilityInfo compInfo) {
186ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        mAssets = assets;
187ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        mMetrics.setToDefaults();
188ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        mCompatibilityInfo = compInfo;
189ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        updateConfiguration(config, metrics);
190ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        assets.ensureStringBlocks();
191ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
192ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
193ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
194ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return a global shared Resources object that provides access to only
195ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * system resources (no application resources), and is not configured for
1962102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * the current screen (can not use dimension units, does not change based
197ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * on orientation, etc).
198ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
199ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public static Resources getSystem() {
200ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (sSync) {
201ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            Resources ret = mSystem;
202ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (ret == null) {
203ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                ret = new Resources();
204ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mSystem = ret;
205ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
206ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
207ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            return ret;
208ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
209ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
210ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
211ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
2122102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * Return the string value associated with a particular resource ID.  The
213ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * returned object will be a String if this is a plain string; it will be
214ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * some other type of CharSequence if it is styled.
215ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * {@more}
216ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
217ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
218ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
219ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
220ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
221ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
222ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
223ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return CharSequence The string data associated with the resource, plus
224ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *         possibly styled text information.
225ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
226ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public CharSequence getText(int id) throws NotFoundException {
227ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        CharSequence res = mAssets.getResourceText(id);
228ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        if (res != null) {
229ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            return res;
230ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
2312102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        throw new NotFoundException("String resource ID #0x"
2322102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                                    + Integer.toHexString(id));
2332102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    }
2342102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
2352102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /**
2362102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * Return the character sequence associated with a particular resource ID for a particular
2372102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * numerical quantity.
2382102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
2392102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * <p>See <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String
2402102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * Resources</a> for more on quantity strings.
2412102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
2422102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param id The desired resource identifier, as generated by the aapt
2432102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *           tool. This integer encodes the package, type, and resource
2442102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *           entry. The value 0 is an invalid identifier.
2452102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param quantity The number used to get the correct string for the current language's
2462102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *           plural rules.
2472102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
2482102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
2492102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
2502102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @return CharSequence The string data associated with the resource, plus
2512102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *         possibly styled text information.
2522102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     */
2532102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    public CharSequence getQuantityText(int id, int quantity) throws NotFoundException {
2542102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        NativePluralRules rule = getPluralRule();
2552102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        CharSequence res = mAssets.getResourceBagText(id,
2562102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                attrForQuantityCode(rule.quantityForInt(quantity)));
257ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        if (res != null) {
2582102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            return res;
2592102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        }
260ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        res = mAssets.getResourceBagText(id, ID_OTHER);
261ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        if (res != null) {
262ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            return res;
2632102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        }
264ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        throw new NotFoundException("Plural resource ID #0x" + Integer.toHexString(id)
2652102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                + " quantity=" + quantity
2662102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                + " item=" + stringForQuantityCode(rule.quantityForInt(quantity)));
2672102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    }
2682102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
2692102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private NativePluralRules getPluralRule() {
2702102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        synchronized (sSync) {
2712102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            if (mPluralRule == null) {
2722102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                mPluralRule = NativePluralRules.forLocale(mConfiguration.locale);
2732102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            }
2742102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            return mPluralRule;
2752102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        }
2762102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    }
2772102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
2782102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private static int attrForQuantityCode(int quantityCode) {
279ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        switch (quantityCode) {
280ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            case NativePluralRules.ZERO: return 0x01000005;
281ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            case NativePluralRules.ONE:  return 0x01000006;
2822102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            case NativePluralRules.TWO:  return 0x01000007;
2832102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            case NativePluralRules.FEW:  return 0x01000008;
2842102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            case NativePluralRules.MANY: return 0x01000009;
2852102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            default:                     return ID_OTHER;
2862102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        }
2872102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    }
2882102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
2892102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    private static String stringForQuantityCode(int quantityCode) {
2902102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        switch (quantityCode) {
2912102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            case NativePluralRules.ZERO: return "zero";
2922102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            case NativePluralRules.ONE:  return "one";
2932102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            case NativePluralRules.TWO:  return "two";
2942102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            case NativePluralRules.FEW:  return "few";
2952102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            case NativePluralRules.MANY: return "many";
2962102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            default:                     return "other";
2972102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        }
2982102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    }
2992102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
3002102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /**
3012102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * Return the string value associated with a particular resource ID.  It
3022102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * will be stripped of any styled text information.
3032102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * {@more}
304ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
3052102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param id The desired resource identifier, as generated by the aapt
3062102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *           tool. This integer encodes the package, type, and resource
3072102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *           entry. The value 0 is an invalid identifier.
3082102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
3092102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
3102102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
3112102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @return String The string data associated with the resource,
312ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * stripped of styled text information.
313ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
314ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public String getString(int id) throws NotFoundException {
315ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        CharSequence res = getText(id);
316ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        if (res != null) {
317ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            return res.toString();
318ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
319ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        throw new NotFoundException("String resource ID #0x"
320ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                                    + Integer.toHexString(id));
321ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
322ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
323ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
324ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
32581cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     * Return the string value associated with a particular resource ID,
32681cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     * substituting the format arguments as defined in {@link java.util.Formatter}
32781cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     * and {@link java.lang.String#format}. It will be stripped of any styled text
32881cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     * information.
32981cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     * {@more}
33081cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     *
33181cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     * @param id The desired resource identifier, as generated by the aapt
33281cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     *           tool. This integer encodes the package, type, and resource
33381cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     *           entry. The value 0 is an invalid identifier.
33481cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     *
33581cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     * @param formatArgs The format arguments that will be used for substitution.
33681cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     *
33781cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
33881cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa     *
339ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return String The string data associated with the resource,
340ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * stripped of styled text information.
341ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
342ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public String getString(int id, Object... formatArgs) throws NotFoundException {
343ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        String raw = getString(id);
344ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        return String.format(mConfiguration.locale, raw, formatArgs);
345ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
346ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
347ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
348ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return the string value associated with a particular resource ID for a particular
349ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * numerical quantity, substituting the format arguments as defined in
350ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * {@link java.util.Formatter} and {@link java.lang.String#format}. It will be
351ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * stripped of any styled text information.
352ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * {@more}
353ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
354ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * <p>See <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String
355ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Resources</a> for more on quantity strings.
356ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
357ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
358ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
359ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
360ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param quantity The number used to get the correct string for the current language's
361ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           plural rules.
362ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param formatArgs The format arguments that will be used for substitution.
363ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
364ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
365ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
366ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return String The string data associated with the resource,
367ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * stripped of styled text information.
368ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
369ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public String getQuantityString(int id, int quantity, Object... formatArgs)
370ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            throws NotFoundException {
371ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        String raw = getQuantityText(id, quantity).toString();
372ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        return String.format(mConfiguration.locale, raw, formatArgs);
373ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
374ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
375ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
376ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return the string value associated with a particular resource ID for a particular
377ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * numerical quantity.
378ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
379ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * <p>See <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String
380ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Resources</a> for more on quantity strings.
381ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
382ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
383ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
384ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
385ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param quantity The number used to get the correct string for the current language's
3862102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *           plural rules.
3872102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
3882102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
3892102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
3902102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @return String The string data associated with the resource,
3912102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * stripped of styled text information.
3922102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     */
3932102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    public String getQuantityString(int id, int quantity) throws NotFoundException {
3942102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        return getQuantityText(id, quantity).toString();
3952102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    }
3962102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
3972102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /**
3982102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * Return the string value associated with a particular resource ID.  The
3992102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * returned object will be a String if this is a plain string; it will be
4002102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * some other type of CharSequence if it is styled.
4012102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
4022102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param id The desired resource identifier, as generated by the aapt
4032102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *           tool. This integer encodes the package, type, and resource
4042102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *           entry. The value 0 is an invalid identifier.
4052102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
4062102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param def The default CharSequence to return.
4072102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
4082102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @return CharSequence The string data associated with the resource, plus
4092102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *         possibly styled text information, or def if id is 0 or not found.
4102102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     */
4112102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    public CharSequence getText(int id, CharSequence def) {
4122102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        CharSequence res = id != 0 ? mAssets.getResourceText(id) : null;
4132102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        return res != null ? res : def;
4142102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    }
4152102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
4162102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /**
4172102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * Return the styled text array associated with a particular resource ID.
4182102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
4192102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param id The desired resource identifier, as generated by the aapt
4202102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *           tool. This integer encodes the package, type, and resource
4212102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *           entry. The value 0 is an invalid identifier.
4222102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
4232102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
4242102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
4252102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @return The styled text array associated with the resource.
4262102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     */
4272102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    public CharSequence[] getTextArray(int id) throws NotFoundException {
4282102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        CharSequence[] res = mAssets.getResourceTextArray(id);
4292102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        if (res != null) {
4302102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            return res;
4312102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        }
432ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        throw new NotFoundException("Text array resource ID #0x"
433ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                                    + Integer.toHexString(id));
4342102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    }
4352102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
436ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
437ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return the string array associated with a particular resource ID.
438ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
439ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
440ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
441ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
442ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
443ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
444ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
445ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return The string array associated with the resource.
446ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
447ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public String[] getStringArray(int id) throws NotFoundException {
448ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        String[] res = mAssets.getResourceStringArray(id);
449ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        if (res != null) {
450ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            return res;
451ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
452ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        throw new NotFoundException("String array resource ID #0x"
453ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                                    + Integer.toHexString(id));
454ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
455ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
456ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
457ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return the int array associated with a particular resource ID.
4582102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
4592102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param id The desired resource identifier, as generated by the aapt
460ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
461ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
462ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
463ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
464ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
465ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return The int array associated with the resource.
466ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
467ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public int[] getIntArray(int id) throws NotFoundException {
468ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        int[] res = mAssets.getArrayIntResource(id);
4692102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        if (res != null) {
470ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            return res;
471ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
472ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        throw new NotFoundException("Int array resource ID #0x"
473ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                                    + Integer.toHexString(id));
474ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
475ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
476ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
477ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return an array of heterogeneous values.
478ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
479ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
480ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
481ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
482ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
483ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
484ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
485ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return Returns a TypedArray holding an array of the array values.
4862102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
487ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * when done with it.
488ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
489ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public TypedArray obtainTypedArray(int id) throws NotFoundException {
490ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        int len = mAssets.getArraySize(id);
491ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        if (len < 0) {
492ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            throw new NotFoundException("Array resource ID #0x"
493ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                                        + Integer.toHexString(id));
4942102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        }
495ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
496ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        TypedArray array = getCachedStyledAttributes(len);
497ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        array.mLength = mAssets.retrieveArray(id, array.mData);
498ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        array.mIndices[0] = 0;
499ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
500ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        return array;
501ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
5022102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
503ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
504ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Retrieve a dimensional for a particular resource ID.  Unit
505ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * conversions are based on the current {@link DisplayMetrics} associated
506ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * with the resources.
507ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
508ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
509ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
510ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
511ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
512ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return Resource dimension value multiplied by the appropriate
513ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * metric.
514ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
515ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
516ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
517ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @see #getDimensionPixelOffset
518ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @see #getDimensionPixelSize
519ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
5202102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    public float getDimension(int id) throws NotFoundException {
521ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
522ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            TypedValue value = mTmpValue;
523ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value == null) {
524ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = value = new TypedValue();
525ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
526ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            getValue(id, value, true);
527ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value.type == TypedValue.TYPE_DIMENSION) {
5282102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                return TypedValue.complexToDimension(value.data, mMetrics);
529ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
530ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            throw new NotFoundException(
531ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
532ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    + Integer.toHexString(value.type) + " is not valid");
533ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
534ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
535ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
5362102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /**
537ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Retrieve a dimensional for a particular resource ID for use
538ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * as an offset in raw pixels.  This is the same as
539ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * {@link #getDimension}, except the returned value is converted to
540ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * integer pixels for you.  An offset conversion involves simply
541ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * truncating the base value to an integer.
542ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
543ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
544ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
545ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
546ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
547ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return Resource dimension value multiplied by the appropriate
548ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * metric and truncated to integer pixels.
549ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
550ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
551ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
552ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @see #getDimension
553ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @see #getDimensionPixelSize
554ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
5552102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    public int getDimensionPixelOffset(int id) throws NotFoundException {
556ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
557ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            TypedValue value = mTmpValue;
558ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value == null) {
559ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = value = new TypedValue();
560ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
561ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            getValue(id, value, true);
562ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value.type == TypedValue.TYPE_DIMENSION) {
5632102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                return TypedValue.complexToDimensionPixelOffset(
564ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                        value.data, mMetrics);
565ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
566ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            throw new NotFoundException(
567ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
568ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    + Integer.toHexString(value.type) + " is not valid");
569ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
570ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
5712102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
572ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
573ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Retrieve a dimensional for a particular resource ID for use
574ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * as a size in raw pixels.  This is the same as
575ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * {@link #getDimension}, except the returned value is converted to
576ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * integer pixels for use as a size.  A size conversion involves
577ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * rounding the base value, and ensuring that a non-zero base value
578ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * is at least one pixel in size.
579ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
580ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
581ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
582ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
583ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
584ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return Resource dimension value multiplied by the appropriate
585ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * metric and truncated to integer pixels.
586ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
587ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
5882102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
589ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @see #getDimension
590ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @see #getDimensionPixelOffset
591ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
592ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public int getDimensionPixelSize(int id) throws NotFoundException {
593ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
594ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            TypedValue value = mTmpValue;
595ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value == null) {
5962102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                mTmpValue = value = new TypedValue();
597ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
598ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            getValue(id, value, true);
599ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value.type == TypedValue.TYPE_DIMENSION) {
600ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                return TypedValue.complexToDimensionPixelSize(
601ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                        value.data, mMetrics);
602ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
603ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            throw new NotFoundException(
6042102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
605ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    + Integer.toHexString(value.type) + " is not valid");
606ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
607ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
608ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
609ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
610ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Retrieve a fractional unit for a particular resource ID.
611ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
612ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
613ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
614ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
615ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param base The base value of this fraction.  In other words, a
616ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *             standard fraction is multiplied by this value.
617ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param pbase The parent base value of this fraction.  In other
618ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *             words, a parent fraction (nn%p) is multiplied by this
619ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *             value.
620ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
6212102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @return Attribute fractional value multiplied by the appropriate
622ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * base value.
623ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
624ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
625ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
626ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public float getFraction(int id, int base, int pbase) {
627ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
628ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            TypedValue value = mTmpValue;
6292102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            if (value == null) {
630ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = value = new TypedValue();
631ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
632ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            getValue(id, value, true);
633ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value.type == TypedValue.TYPE_FRACTION) {
634ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                return TypedValue.complexToFraction(value.data, base, pbase);
635ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
636ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            throw new NotFoundException(
6372102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
638ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    + Integer.toHexString(value.type) + " is not valid");
639ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
640ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
641ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
642ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
643ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return a drawable object associated with a particular resource ID.
644ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Various types of objects will be returned depending on the underlying
645ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * resource -- for example, a solid color, PNG image, scalable image, etc.
646ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * The Drawable API hides these implementation details.
647ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
648ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * <p class="note"><strong>Note:</strong> Prior to
649ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN}, this function
650ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * would not correctly retrieve the final configuration density when
651ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * the resource ID passed here is an alias to another Drawable resource.
652ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * This means that if the density configuration of the alias resource
653ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * is different than the actual resource, the density of the returned
6542102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * Drawable would be incorrect, resulting in bad scaling.  To work
655ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * around this, you can instead retrieve the Drawable through
656ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * {@link TypedArray#getDrawable TypedArray.getDrawable}.  Use
657ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * {@link android.content.Context#obtainStyledAttributes(int[])
658ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Context.obtainStyledAttributes} with
659ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * an array containing the resource ID of interest to create the TypedArray.</p>
660ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
661ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
6622102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *           tool. This integer encodes the package, type, and resource
663ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
664ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
665ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
666ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
667ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return Drawable An object that can be used to draw this resource.
668ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
669ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public Drawable getDrawable(int id) throws NotFoundException {
6702102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        TypedValue value;
671ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
672ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            value = mTmpValue;
673ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value == null) {
674ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                value = new TypedValue();
675ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            } else {
676ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = null;
677ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
678ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            getValue(id, value, true);
679ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
680ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        Drawable res = loadDrawable(value, id);
681ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
682ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (mTmpValue == null) {
683ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = value;
684ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
685ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
686ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        return res;
687ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
688ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
689ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
690ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return a drawable object associated with a particular resource ID for the
6912102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * given screen density in DPI. This will set the drawable's density to be
692ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * the device's density multiplied by the ratio of actual drawable density
693ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * to requested density. This allows the drawable to be scaled up to the
694ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * correct size if needed. Various types of objects will be returned
695ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * depending on the underlying resource -- for example, a solid color, PNG
696ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * image, scalable image, etc. The Drawable API hides these implementation
697ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * details.
698ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
6992102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param id The desired resource identifier, as generated by the aapt tool.
700ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *            This integer encodes the package, type, and resource entry.
701ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *            The value 0 is an invalid identifier.
702ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param density the desired screen density indicated by the resource as
703ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *            found in {@link DisplayMetrics}.
704ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does
705ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *             not exist.
706ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return Drawable An object that can be used to draw this resource.
7072102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     */
708ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public Drawable getDrawableForDensity(int id, int density) throws NotFoundException {
709ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        TypedValue value;
710ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
711ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            value = mTmpValue;
712ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value == null) {
713ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                value = new TypedValue();
714ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            } else {
715ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = null;
716ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
717ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            getValueForDensity(id, density, value, true);
718ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
719ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            /*
720ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa             * Pretend the requested density is actually the display density. If
721ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa             * the drawable returned is not the requested density, then force it
722ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa             * to be scaled later by dividing its density by the ratio of
723ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa             * requested density to actual device density. Drawables that have
7242102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa             * undefined density or no density don't need to be handled here.
725ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa             */
726ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
727ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                if (value.density == density) {
728ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    value.density = mMetrics.densityDpi;
729ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                } else {
730ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    value.density = (value.density * mMetrics.densityDpi) / density;
731ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                }
7322102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            }
733ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
734ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
735ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        Drawable res = loadDrawable(value, id);
736ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
737ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (mTmpValue == null) {
738ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = value;
7392102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            }
740ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
741ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        return res;
742ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
743ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
744ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
745ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return a movie object associated with the particular resource ID.
7462102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param id The desired resource identifier, as generated by the aapt
747ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
748ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
749ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
750ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
751ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
752ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public Movie getMovie(int id) throws NotFoundException {
753ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        InputStream is = openRawResource(id);
754ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        Movie movie = Movie.decodeStream(is);
755ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        try {
756ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            is.close();
757ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
758ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        catch (java.io.IOException e) {
759ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            // don't care, since the return value is valid
760ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
761ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        return movie;
762ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
763ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
764ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
765ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return a color integer associated with a particular resource ID.
766ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * If the resource holds a complex
767ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * {@link android.content.res.ColorStateList}, then the default color from
768ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * the set is returned.
769ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
770ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
771ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
772ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
7732102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
774ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
775ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
776ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return Returns a single color value in the form 0xAARRGGBB.
777ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
778ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public int getColor(int id) throws NotFoundException {
779ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        TypedValue value;
780ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
7812102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            value = mTmpValue;
782ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value == null) {
783ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                value = new TypedValue();
784ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
785ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            getValue(id, value, true);
786ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value.type >= TypedValue.TYPE_FIRST_INT
787ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                && value.type <= TypedValue.TYPE_LAST_INT) {
788ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = value;
78952617bbff8607cdc208ba107ec111bd1471433cbTsuwei Chen                return value.data;
790ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            } else if (value.type != TypedValue.TYPE_STRING) {
791ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                throw new NotFoundException(
792ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
793ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    + Integer.toHexString(value.type) + " is not valid");
794ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
795ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            mTmpValue = null;
79652617bbff8607cdc208ba107ec111bd1471433cbTsuwei Chen        }
7972102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        ColorStateList csl = loadColorStateList(value, id);
798ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
799ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (mTmpValue == null) {
800ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = value;
801ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
802ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
803ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        return csl.getDefaultColor();
804ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
8052102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
80652617bbff8607cdc208ba107ec111bd1471433cbTsuwei Chen    /**
807ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return a color state list associated with a particular resource ID.  The
808ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * resource may contain either a single raw color value, or a complex
809ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * {@link android.content.res.ColorStateList} holding multiple possible colors.
8102102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
811ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier of a {@link ColorStateList},
8122102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *        as generated by the aapt tool. This integer encodes the package, type, and resource
8132102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *        entry. The value 0 is an invalid identifier.
814ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
815ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
816ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
8172102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @return Returns a ColorStateList object containing either a single
8182102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * solid color or multiple colors that can be selected based on a state.
819ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
8202102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    public ColorStateList getColorStateList(int id) throws NotFoundException {
821ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        TypedValue value;
8222102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        synchronized (mAccessLock) {
8232102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            value = mTmpValue;
824ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value == null) {
825ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                value = new TypedValue();
826ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            } else {
8272102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                mTmpValue = null;
828ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
8292102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            getValue(id, value, true);
8302102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        }
8312102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        ColorStateList res = loadColorStateList(value, id);
832ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
833ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (mTmpValue == null) {
834ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = value;
8352102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            }
836ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
8372102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        return res;
8382102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    }
8392102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
840ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
841ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return a boolean associated with a particular resource ID.  This can be
842ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * used with any integral resource value, and will return true if it is
843ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * non-zero.
844ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
845ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
8462102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *           tool. This integer encodes the package, type, and resource
847ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
848ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
849ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
850ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
851ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return Returns the boolean value contained in the resource.
852ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
853ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public boolean getBoolean(int id) throws NotFoundException {
854ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
855ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            TypedValue value = mTmpValue;
856ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value == null) {
857ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = value = new TypedValue();
858ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
859ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            getValue(id, value, true);
860ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value.type >= TypedValue.TYPE_FIRST_INT
861ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                && value.type <= TypedValue.TYPE_LAST_INT) {
862ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                return value.data != 0;
863ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
864ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            throw new NotFoundException(
865ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
8662102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                + Integer.toHexString(value.type) + " is not valid");
867ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
868ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
869ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
870ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
871ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return an integer associated with a particular resource ID.
872ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
873ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
8742102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *           tool. This integer encodes the package, type, and resource
875ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
876ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
877ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
878ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
879ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return Returns the integer value contained in the resource.
880ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
881ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public int getInteger(int id) throws NotFoundException {
8822102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        synchronized (mAccessLock) {
883ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            TypedValue value = mTmpValue;
884ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value == null) {
885ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = value = new TypedValue();
886ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
887ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            getValue(id, value, true);
888ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value.type >= TypedValue.TYPE_FIRST_INT
889ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                && value.type <= TypedValue.TYPE_LAST_INT) {
890ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                return value.data;
891ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
892ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            throw new NotFoundException(
893ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
894ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                + Integer.toHexString(value.type) + " is not valid");
895ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
896ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
897ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
898ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
8992102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * Return an XmlResourceParser through which you can read a view layout
900ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * description for the given resource ID.  This parser has limited
901ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * functionality -- in particular, you can't change its input, and only
902ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * the high-level events are available.
903ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
904ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * <p>This function is really a simple wrapper for calling
905ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * {@link #getXml} with a layout resource.
906ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
9072102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param id The desired resource identifier, as generated by the aapt
908ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
909ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
910ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
911ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
912ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
913ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return A new parser object through which you can read
9142102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *         the XML data.
915ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
916ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @see #getXml
917ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
918ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public XmlResourceParser getLayout(int id) throws NotFoundException {
919ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        return loadXmlResourceParser(id, "layout");
920ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
9212102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
922ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
923ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return an XmlResourceParser through which you can read an animation
924ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * description for the given resource ID.  This parser has limited
925ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * functionality -- in particular, you can't change its input, and only
926ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * the high-level events are available.
927ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
928ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * <p>This function is really a simple wrapper for calling
929ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * {@link #getXml} with an animation resource.
930ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
931ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
932ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
933ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
934ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
935ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
936ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
937ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return A new parser object through which you can read
938ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *         the XML data.
939ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
940ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @see #getXml
941ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
942ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public XmlResourceParser getAnimation(int id) throws NotFoundException {
943ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        return loadXmlResourceParser(id, "anim");
944ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
945ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
9462102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /**
947ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return an XmlResourceParser through which you can read a generic XML
9482102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * resource for the given resource ID.
949ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
950ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * <p>The XmlPullParser implementation returned here has some limited
951ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * functionality.  In particular, you can't change its input, and only
952ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * high-level parsing events are available (since the document was
953ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * pre-parsed for you at build time, which involved merging text and
954ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * stripping comments).
955ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
9562102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param id The desired resource identifier, as generated by the aapt
957ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
958ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
959ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
960ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
961ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
962ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return A new parser object through which you can read
963ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *         the XML data.
964ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
965ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @see android.util.AttributeSet
966ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
967ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public XmlResourceParser getXml(int id) throws NotFoundException {
968ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        return loadXmlResourceParser(id, "xml");
969ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
970ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
971ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
9722102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * Open a data stream for reading a raw resource.  This can only be used
973ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * with resources whose value is the name of an asset files -- that is, it can be
974ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * used to open drawable, sound, and raw resources; it will fail on string
975ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * and color resources.
976ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
977ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The resource identifier to open, as generated by the appt
978ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool.
979ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
9802102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @return InputStream Access to the resource data.
981ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
982ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
983ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
984ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
985ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public InputStream openRawResource(int id) throws NotFoundException {
986ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        TypedValue value;
987ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
9882102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            value = mTmpValue;
989ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value == null) {
990ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                value = new TypedValue();
991ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            } else {
992ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = null;
993ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
994ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
995ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        InputStream res = openRawResource(id, value);
996ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
997ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (mTmpValue == null) {
998ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = value;
999ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
1000ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
1001ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        return res;
1002ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
1003ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
1004ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
1005ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Open a data stream for reading a raw resource.  This can only be used
10062102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * with resources whose value is the name of an asset file -- that is, it can be
1007ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * used to open drawable, sound, and raw resources; it will fail on string
1008ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * and color resources.
1009ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
1010ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The resource identifier to open, as generated by the appt tool.
1011ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param value The TypedValue object to hold the resource information.
1012ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
1013ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return InputStream Access to the resource data.
10142102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
1015ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1016ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
1017ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public InputStream openRawResource(int id, TypedValue value) throws NotFoundException {
1018ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        getValue(id, value, true);
1019ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
1020ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        try {
1021ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            return mAssets.openNonAsset(value.assetCookie, value.string.toString(),
10222102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    AssetManager.ACCESS_STREAMING);
1023ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        } catch (Exception e) {
1024ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            NotFoundException rnf = new NotFoundException("File " + value.string.toString() +
1025ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    " from drawable resource ID #0x" + Integer.toHexString(id));
1026ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            rnf.initCause(e);
1027ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            throw rnf;
1028ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
1029ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
1030ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
1031ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
1032ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Open a file descriptor for reading a raw resource.  This can only be used
1033ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * with resources whose value is the name of an asset files -- that is, it can be
1034ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * used to open drawable, sound, and raw resources; it will fail on string
1035ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * and color resources.
1036ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
1037ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * <p>This function only works for resources that are stored in the package
1038ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * as uncompressed data, which typically includes things like mp3 files
1039ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * and png images.
1040ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
10412102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param id The resource identifier to open, as generated by the appt
1042ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool.
1043ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
1044ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @return AssetFileDescriptor A new file descriptor you can use to read
1045ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * the resource.  This includes the file descriptor itself, as well as the
1046ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * offset and length of data where the resource appears in the file.  A
1047ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * null is returned if the file exists but is compressed.
1048ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
10492102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1050ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
1051ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
1052ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public AssetFileDescriptor openRawResourceFd(int id) throws NotFoundException {
1053ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        TypedValue value;
1054ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mAccessLock) {
1055ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            value = mTmpValue;
1056ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (value == null) {
10572102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                value = new TypedValue();
1058ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            } else {
1059ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                mTmpValue = null;
1060ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
1061ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            getValue(id, value, true);
1062ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
1063ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        try {
1064ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            return mAssets.openNonAssetFd(
1065ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                value.assetCookie, value.string.toString());
1066ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        } catch (Exception e) {
1067ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            NotFoundException rnf = new NotFoundException(
1068ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                "File " + value.string.toString()
1069ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                + " from drawable resource ID #0x"
1070ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                + Integer.toHexString(id));
1071ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            rnf.initCause(e);
1072ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            throw rnf;
1073ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        } finally {
1074ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            synchronized (mAccessLock) {
1075ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                if (mTmpValue == null) {
10762102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    mTmpValue = value;
1077ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                }
1078ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
1079ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
1080ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
1081ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
1082ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
1083ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return the raw data associated with a particular resource ID.
10842102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
1085ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id The desired resource identifier, as generated by the aapt
1086ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           tool. This integer encodes the package, type, and resource
1087ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *           entry. The value 0 is an invalid identifier.
1088ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param outValue Object in which to place the resource data.
1089ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param resolveRefs If true, a resource that is a reference to another
1090ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *                    resource will be followed so that you receive the
1091ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *                    actual final resource data.  If false, the TypedValue
10922102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *                    will be filled in with the reference itself.
1093ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
1094ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1095ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
1096ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
1097ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public void getValue(int id, TypedValue outValue, boolean resolveRefs)
1098ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            throws NotFoundException {
1099ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
1100ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        if (found) {
1101ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            return;
1102ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
1103ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        throw new NotFoundException("Resource ID #0x"
1104ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                                    + Integer.toHexString(id));
1105ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
1106ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
1107ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
1108ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Get the raw value associated with a resource with associated density.
1109ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
1110ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param id resource identifier
11112102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * @param density density in DPI
1112ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param resolveRefs If true, a resource that is a reference to another
1113ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *            resource will be followed so that you receive the actual final
1114ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *            resource data. If false, the TypedValue will be filled in with
1115ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *            the reference itself.
1116ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does
1117ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *             not exist.
1118ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @see #getValue(String, TypedValue, boolean)
11192102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     */
1120ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public void getValueForDensity(int id, int density, TypedValue outValue, boolean resolveRefs)
1121ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            throws NotFoundException {
1122ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
1123ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        if (found) {
1124ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            return;
1125ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
1126ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
1127ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
1128ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
11292102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa    /**
1130ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * Return the raw data associated with a particular resource ID.
1131ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * See getIdentifier() for information on how names are mapped to resource
1132ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * IDs, and getString(int) for information on how string resources are
1133ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * retrieved.
1134ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
1135ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * <p>Note: use of this function is discouraged.  It is much more
1136ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * efficient to retrieve resources by identifier than by name.
1137ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
1138ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param name The name of the desired resource.  This is passed to
1139ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *             getIdentifier() with a default type of "string".
1140ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param outValue Object in which to place the resource data.
1141ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @param resolveRefs If true, a resource that is a reference to another
1142ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *                    resource will be followed so that you receive the
1143ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *                    actual final resource data.  If false, the TypedValue
1144ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *                    will be filled in with the reference itself.
11452102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
1146ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
11472102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
11482102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     */
1149ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public void getValue(String name, TypedValue outValue, boolean resolveRefs)
115081cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa            throws NotFoundException {
1151ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        int id = getIdentifier(name, "string", null);
1152ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        if (id != 0) {
1153ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            getValue(id, outValue, resolveRefs);
11542102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            return;
1155ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
1156ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        throw new NotFoundException("String resource name " + name);
1157ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
1158ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
1159ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    /**
1160ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * This class holds the current attribute values for a particular theme.
1161ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * In other words, a Theme is a set of values for resource attributes;
1162ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * these are used in conjunction with {@link TypedArray}
1163ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * to resolve the final value for an attribute.
1164ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     *
11652102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * <p>The Theme's attributes come into play in two ways: (1) a styled
116652617bbff8607cdc208ba107ec111bd1471433cbTsuwei Chen     * attribute can explicit reference a value in the theme through the
11672102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     * "?themeAttribute" syntax; (2) if no value has been defined for a
1168ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * particular styled attribute, as a last resort we will try to find that
1169ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * attribute's value in the Theme.
11702102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa     *
1171ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * <p>You will normally use the {@link #obtainStyledAttributes} APIs to
1172ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     * retrieve XML attributes with style and theme information applied.
1173ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa     */
1174ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public final class Theme {
1175ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        /**
1176ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * Place new attribute values into the theme.  The style resource
1177ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * specified by <var>resid</var> will be retrieved from this Theme's
1178ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * resources, its values placed into the Theme object.
1179ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
1180ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * <p>The semantics of this function depends on the <var>force</var>
1181ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * argument:  If false, only values that are not already defined in
1182ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * the theme will be copied from the system resource; otherwise, if
1183ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * any of the style's attributes are already defined in the theme, the
1184ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * current values in the theme will be overwritten.
1185ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
1186ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @param resid The resource ID of a style resource from which to
1187ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *              obtain attribute values.
11882102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         * @param force If true, values in the style resource will always be
1189ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *              used in the theme; otherwise, they will only be used
11902102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         *              if not already defined in the theme.
11912102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         */
1192ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        public void applyStyle(int resid, boolean force) {
119381cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa            AssetManager.applyThemeStyle(mTheme, resid, force);
1194ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
1195ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
1196ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        /**
11972102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         * Set this theme to hold the same contents as the theme
1198ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * <var>other</var>.  If both of these themes are from the same
1199ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * Resources object, they will be identical after this function
1200ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * returns.  If they are from different Resources, only the resources
1201ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * they have in common will be set in this theme.
1202ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
1203ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @param other The existing Theme to copy from.
1204ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         */
1205ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        public void setTo(Theme other) {
1206ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            AssetManager.copyTheme(mTheme, other.mTheme);
1207ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
12082102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
1209ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        /**
12102102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         * Return a TypedArray holding the values defined by
1211ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * <var>Theme</var> which are listed in <var>attrs</var>.
1212ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
12132102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         * <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done
1214ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * with the array.
1215ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
1216ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @param attrs The desired attributes.
1217ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
1218ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1219ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
1220ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @return Returns a TypedArray holding an array of the attribute values.
1221ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
1222ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * when done with it.
1223ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
1224ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @see Resources#obtainAttributes
1225ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @see #obtainStyledAttributes(int, int[])
1226ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @see #obtainStyledAttributes(AttributeSet, int[], int, int)
1227ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         */
1228ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        public TypedArray obtainStyledAttributes(int[] attrs) {
1229ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            int len = attrs.length;
1230ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            TypedArray array = getCachedStyledAttributes(len);
1231ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            array.mRsrcs = attrs;
1232ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            AssetManager.applyStyle(mTheme, 0, 0, 0, attrs,
1233ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    array.mData, array.mIndices);
1234ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            return array;
12352102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        }
12362102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
12372102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        /**
1238ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * Return a TypedArray holding the values defined by the style
123981cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa         * resource <var>resid</var> which are listed in <var>attrs</var>.
124081cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa         *
124181cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa         * <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done
124281cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa         * with the array.
124381cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa         *
124481cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa         * @param resid The desired style resource.
1245ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @param attrs The desired attributes in the style.
1246ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
1247ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1248ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
1249ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @return Returns a TypedArray holding an array of the attribute values.
1250ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
1251ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * when done with it.
1252ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
1253ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @see Resources#obtainAttributes
1254ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @see #obtainStyledAttributes(int[])
1255ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @see #obtainStyledAttributes(AttributeSet, int[], int, int)
12562102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         */
12572102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        public TypedArray obtainStyledAttributes(int resid, int[] attrs)
12582102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                throws NotFoundException {
12592102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            int len = attrs.length;
12602102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            TypedArray array = getCachedStyledAttributes(len);
1261ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            array.mRsrcs = attrs;
1262ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
1263ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            AssetManager.applyStyle(mTheme, 0, resid, 0, attrs,
1264ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    array.mData, array.mIndices);
1265ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (false) {
1266ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                int[] data = array.mData;
1267ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
1268ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                System.out.println("**********************************************************");
1269ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                System.out.println("**********************************************************");
12702102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                System.out.println("**********************************************************");
1271ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                System.out.println("Attributes:");
12722102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                String s = "  Attrs:";
1273ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                int i;
1274ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                for (i=0; i<attrs.length; i++) {
1275ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    s = s + " 0x" + Integer.toHexString(attrs[i]);
1276ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                }
12772102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                System.out.println(s);
1278ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                s = "  Found:";
12792102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                TypedValue value = new TypedValue();
1280ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                for (i=0; i<attrs.length; i++) {
1281ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    int d = i*AssetManager.STYLE_NUM_ENTRIES;
1282ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    value.type = data[d+AssetManager.STYLE_TYPE];
1283ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    value.data = data[d+AssetManager.STYLE_DATA];
12842102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    value.assetCookie = data[d+AssetManager.STYLE_ASSET_COOKIE];
1285ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    value.resourceId = data[d+AssetManager.STYLE_RESOURCE_ID];
1286ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                    s = s + " 0x" + Integer.toHexString(attrs[i])
1287ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                        + "=" + value;
1288ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                }
12892102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                System.out.println(s);
1290ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
1291ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            return array;
1292ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
1293ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
12942102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        /**
1295ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * Return a TypedArray holding the attribute values in
12962102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         * <var>set</var>
1297ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * that are listed in <var>attrs</var>.  In addition, if the given
1298ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * AttributeSet specifies a style class (through the "style" attribute),
1299ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * that style will be applied on top of the base attributes it defines.
1300ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
1301ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done
1302ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * with the array.
13032102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         *
1304ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * <p>When determining the final value of a particular attribute, there
1305ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * are four inputs that come into play:</p>
1306ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
13072102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         * <ol>
13082102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         *     <li> Any attribute values in the given AttributeSet.
1309ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *     <li> The style resource specified in the AttributeSet (named
1310ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *     "style").
1311ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *     <li> The default style specified by <var>defStyleAttr</var> and
1312ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *     <var>defStyleRes</var>
13132102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         *     <li> The base values in this theme.
1314ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * </ol>
13152102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         *
1316ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * <p>Each of these inputs is considered in-order, with the first listed
1317ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * taking precedence over the following ones.  In other words, if in the
1318ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * AttributeSet you have supplied <code>&lt;Button
1319ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * textColor="#ff000000"&gt;</code>, then the button's text will
1320ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * <em>always</em> be black, regardless of what is specified in any of
1321ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * the styles.
13222102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         *
1323ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @param set The base set of attribute values.  May be null.
1324ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @param attrs The desired attributes to be retrieved.
1325ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @param defStyleAttr An attribute in the current theme that contains a
1326ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *                     reference to a style resource that supplies
13272102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         *                     defaults values for the TypedArray.  Can be
1328ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *                     0 to not look for defaults.
13292102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         * @param defStyleRes A resource identifier of a style resource that
1330ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *                    supplies default values for the TypedArray,
1331ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *                    used only if defStyleAttr is 0 or can not be found
1332ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *                    in the theme.  Can be 0 to not look for defaults.
1333ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
13342102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         * @return Returns a TypedArray holding an array of the attribute values.
1335ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
13362102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa         * when done with it.
1337ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         *
1338ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @see Resources#obtainAttributes
1339ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @see #obtainStyledAttributes(int[])
1340ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         * @see #obtainStyledAttributes(int, int[])
1341ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa         */
13422102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa        public TypedArray obtainStyledAttributes(AttributeSet set,
13432102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                int[] attrs, int defStyleAttr, int defStyleRes) {
13442102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            int len = attrs.length;
13452102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            TypedArray array = getCachedStyledAttributes(len);
13462102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
13472102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            // XXX note that for now we only work with compiled XML files.
13482102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            // To support generic XML files we will need to manually parse
134981cabb8a7fb5b61f16bf49c2757ccb51bc88e708destradaa            // out the attributes from the XML file (applying type information
13502102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            // contained in the resources and such).
13512102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            XmlBlock.Parser parser = (XmlBlock.Parser)set;
13522102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            AssetManager.applyStyle(
13532102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                mTheme, defStyleAttr, defStyleRes,
13542102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                parser != null ? parser.mParseState : 0, attrs,
13552102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                        array.mData, array.mIndices);
13562102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
13572102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            array.mRsrcs = attrs;
13582102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            array.mXml = parser;
13592102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
13602102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            if (false) {
13612102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                int[] data = array.mData;
13622102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
13632102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                System.out.println("Attributes:");
13642102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                String s = "  Attrs:";
13652102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                int i;
13662102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                for (i=0; i<set.getAttributeCount(); i++) {
13672102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    s = s + " " + set.getAttributeName(i);
13682102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    int id = set.getAttributeNameResource(i);
13692102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    if (id != 0) {
13702102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                        s = s + "(0x" + Integer.toHexString(id) + ")";
13712102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    }
13722102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    s = s + "=" + set.getAttributeValue(i);
13732102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                }
13742102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                System.out.println(s);
13752102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                s = "  Found:";
13762102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                TypedValue value = new TypedValue();
13772102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                for (i=0; i<attrs.length; i++) {
13782102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    int d = i*AssetManager.STYLE_NUM_ENTRIES;
13792102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    value.type = data[d+AssetManager.STYLE_TYPE];
13802102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    value.data = data[d+AssetManager.STYLE_DATA];
13812102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    value.assetCookie = data[d+AssetManager.STYLE_ASSET_COOKIE];
13822102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    value.resourceId = data[d+AssetManager.STYLE_RESOURCE_ID];
13832102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                    s = s + " 0x" + Integer.toHexString(attrs[i])
13842102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                        + "=" + value;
13852102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                }
13862102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa                System.out.println(s);
13872102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa            }
13882102dd725540bcf51bf324a2775fbcffe45dd32fdestradaa
1389ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            return array;
1390        }
1391
1392        /**
1393         * Retrieve the value of an attribute in the Theme.  The contents of
1394         * <var>outValue</var> are ultimately filled in by
1395         * {@link Resources#getValue}.
1396         *
1397         * @param resid The resource identifier of the desired theme
1398         *              attribute.
1399         * @param outValue Filled in with the ultimate resource value supplied
1400         *                 by the attribute.
1401         * @param resolveRefs If true, resource references will be walked; if
1402         *                    false, <var>outValue</var> may be a
1403         *                    TYPE_REFERENCE.  In either case, it will never
1404         *                    be a TYPE_ATTRIBUTE.
1405         *
1406         * @return boolean Returns true if the attribute was found and
1407         *         <var>outValue</var> is valid, else false.
1408         */
1409        public boolean resolveAttribute(int resid, TypedValue outValue,
1410                boolean resolveRefs) {
1411            boolean got = mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs);
1412            if (false) {
1413                System.out.println(
1414                    "resolveAttribute #" + Integer.toHexString(resid)
1415                    + " got=" + got + ", type=0x" + Integer.toHexString(outValue.type)
1416                    + ", data=0x" + Integer.toHexString(outValue.data));
1417            }
1418            return got;
1419        }
1420
1421        /**
1422         * Print contents of this theme out to the log.  For debugging only.
1423         *
1424         * @param priority The log priority to use.
1425         * @param tag The log tag to use.
1426         * @param prefix Text to prefix each line printed.
1427         */
1428        public void dump(int priority, String tag, String prefix) {
1429            AssetManager.dumpTheme(mTheme, priority, tag, prefix);
1430        }
1431
1432        protected void finalize() throws Throwable {
1433            super.finalize();
1434            mAssets.releaseTheme(mTheme);
1435        }
1436
1437        /*package*/ Theme() {
1438            mAssets = Resources.this.mAssets;
1439            mTheme = mAssets.createTheme();
1440        }
1441
1442        private final AssetManager mAssets;
1443        private final int mTheme;
1444    }
1445
1446    /**
1447     * Generate a new Theme object for this set of Resources.  It initially
1448     * starts out empty.
1449     *
1450     * @return Theme The newly created Theme container.
1451     */
1452    public final Theme newTheme() {
1453        return new Theme();
1454    }
1455
1456    /**
1457     * Retrieve a set of basic attribute values from an AttributeSet, not
1458     * performing styling of them using a theme and/or style resources.
1459     *
1460     * @param set The current attribute values to retrieve.
1461     * @param attrs The specific attributes to be retrieved.
1462     * @return Returns a TypedArray holding an array of the attribute values.
1463     * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
1464     * when done with it.
1465     *
1466     * @see Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
1467     */
1468    public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
1469        int len = attrs.length;
1470        TypedArray array = getCachedStyledAttributes(len);
1471
1472        // XXX note that for now we only work with compiled XML files.
1473        // To support generic XML files we will need to manually parse
1474        // out the attributes from the XML file (applying type information
1475        // contained in the resources and such).
1476        XmlBlock.Parser parser = (XmlBlock.Parser)set;
1477        mAssets.retrieveAttributes(parser.mParseState, attrs,
1478                array.mData, array.mIndices);
1479
1480        array.mRsrcs = attrs;
1481        array.mXml = parser;
1482
1483        return array;
1484    }
1485
1486    /**
1487     * Store the newly updated configuration.
1488     */
1489    public void updateConfiguration(Configuration config,
1490            DisplayMetrics metrics) {
1491        updateConfiguration(config, metrics, null);
1492    }
1493
1494    /**
1495     * @hide
1496     */
1497    public void updateConfiguration(Configuration config,
1498            DisplayMetrics metrics, CompatibilityInfo compat) {
1499        synchronized (mAccessLock) {
1500            if (false) {
1501                Slog.i(TAG, "**** Updating config of " + this + ": old config is "
1502                        + mConfiguration + " old compat is " + mCompatibilityInfo);
1503                Slog.i(TAG, "**** Updating config of " + this + ": new config is "
1504                        + config + " new compat is " + compat);
1505            }
1506            if (compat != null) {
1507                mCompatibilityInfo = compat;
1508            }
1509            if (metrics != null) {
1510                mMetrics.setTo(metrics);
1511            }
1512            // NOTE: We should re-arrange this code to create a Display
1513            // with the CompatibilityInfo that is used everywhere we deal
1514            // with the display in relation to this app, rather than
1515            // doing the conversion here.  This impl should be okay because
1516            // we make sure to return a compatible display in the places
1517            // where there are public APIs to retrieve the display...  but
1518            // it would be cleaner and more maintainble to just be
1519            // consistently dealing with a compatible display everywhere in
1520            // the framework.
1521            if (mCompatibilityInfo != null) {
1522                mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
1523            }
1524            int configChanges = 0xfffffff;
1525            if (config != null) {
1526                mTmpConfig.setTo(config);
1527                int density = config.densityDpi;
1528                if (density == Configuration.DENSITY_DPI_UNDEFINED) {
1529                    density = mMetrics.noncompatDensityDpi;
1530                }
1531                if (mCompatibilityInfo != null) {
1532                    mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
1533                }
1534                if (mTmpConfig.locale == null) {
1535                    mTmpConfig.locale = Locale.getDefault();
1536                    mTmpConfig.setLayoutDirection(mTmpConfig.locale);
1537                }
1538                configChanges = mConfiguration.updateFrom(mTmpConfig);
1539                configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
1540            }
1541            if (mConfiguration.locale == null) {
1542                mConfiguration.locale = Locale.getDefault();
1543                mConfiguration.setLayoutDirection(mConfiguration.locale);
1544            }
1545            if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
1546                mMetrics.densityDpi = mConfiguration.densityDpi;
1547                mMetrics.density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
1548            }
1549            mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
1550
1551            String locale = null;
1552            if (mConfiguration.locale != null) {
1553                locale = mConfiguration.locale.getLanguage();
1554                if (mConfiguration.locale.getCountry() != null) {
1555                    locale += "-" + mConfiguration.locale.getCountry();
1556                }
1557            }
1558            int width, height;
1559            if (mMetrics.widthPixels >= mMetrics.heightPixels) {
1560                width = mMetrics.widthPixels;
1561                height = mMetrics.heightPixels;
1562            } else {
1563                //noinspection SuspiciousNameCombination
1564                width = mMetrics.heightPixels;
1565                //noinspection SuspiciousNameCombination
1566                height = mMetrics.widthPixels;
1567            }
1568            int keyboardHidden = mConfiguration.keyboardHidden;
1569            if (keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
1570                    && mConfiguration.hardKeyboardHidden
1571                            == Configuration.HARDKEYBOARDHIDDEN_YES) {
1572                keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT;
1573            }
1574            mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
1575                    locale, mConfiguration.orientation,
1576                    mConfiguration.touchscreen,
1577                    mConfiguration.densityDpi, mConfiguration.keyboard,
1578                    keyboardHidden, mConfiguration.navigation, width, height,
1579                    mConfiguration.smallestScreenWidthDp,
1580                    mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
1581                    mConfiguration.screenLayout, mConfiguration.uiMode,
1582                    Build.VERSION.RESOURCES_SDK_INT);
1583
1584            if (DEBUG_CONFIG) {
1585                Slog.i(TAG, "**** Updating config of " + this + ": final config is " + mConfiguration
1586                        + " final compat is " + mCompatibilityInfo);
1587            }
1588
1589            clearDrawableCacheLocked(mDrawableCache, configChanges);
1590            clearDrawableCacheLocked(mColorDrawableCache, configChanges);
1591
1592            mColorStateListCache.clear();
1593
1594            flushLayoutCache();
1595        }
1596        synchronized (sSync) {
1597            if (mPluralRule != null) {
1598                mPluralRule = NativePluralRules.forLocale(config.locale);
1599            }
1600        }
1601    }
1602
1603    private void clearDrawableCacheLocked(
1604            LongSparseArray<WeakReference<ConstantState>> cache,
1605            int configChanges) {
1606        int N = cache.size();
1607        if (DEBUG_CONFIG) {
1608            Log.d(TAG, "Cleaning up drawables config changes: 0x"
1609                    + Integer.toHexString(configChanges));
1610        }
1611        for (int i=0; i<N; i++) {
1612            WeakReference<Drawable.ConstantState> ref = cache.valueAt(i);
1613            if (ref != null) {
1614                Drawable.ConstantState cs = ref.get();
1615                if (cs != null) {
1616                    if (Configuration.needNewResources(
1617                            configChanges, cs.getChangingConfigurations())) {
1618                        if (DEBUG_CONFIG) {
1619                            Log.d(TAG, "FLUSHING #0x"
1620                                    + Long.toHexString(mDrawableCache.keyAt(i))
1621                                    + " / " + cs + " with changes: 0x"
1622                                    + Integer.toHexString(cs.getChangingConfigurations()));
1623                        }
1624                        cache.setValueAt(i, null);
1625                    } else if (DEBUG_CONFIG) {
1626                        Log.d(TAG, "(Keeping #0x"
1627                                + Long.toHexString(cache.keyAt(i))
1628                                + " / " + cs + " with changes: 0x"
1629                                + Integer.toHexString(cs.getChangingConfigurations())
1630                                + ")");
1631                    }
1632                }
1633            }
1634        }
1635    }
1636
1637    /**
1638     * Update the system resources configuration if they have previously
1639     * been initialized.
1640     *
1641     * @hide
1642     */
1643    public static void updateSystemConfiguration(Configuration config, DisplayMetrics metrics,
1644            CompatibilityInfo compat) {
1645        if (mSystem != null) {
1646            mSystem.updateConfiguration(config, metrics, compat);
1647            //Log.i(TAG, "Updated system resources " + mSystem
1648            //        + ": " + mSystem.getConfiguration());
1649        }
1650    }
1651
1652    /**
1653     * @hide
1654     */
1655    public static void updateSystemConfiguration(Configuration config, DisplayMetrics metrics) {
1656        updateSystemConfiguration(config, metrics, null);
1657    }
1658
1659    /**
1660     * Return the current display metrics that are in effect for this resource
1661     * object.  The returned object should be treated as read-only.
1662     *
1663     * @return The resource's current display metrics.
1664     */
1665    public DisplayMetrics getDisplayMetrics() {
1666        if (DEBUG_CONFIG) Slog.v(TAG, "Returning DisplayMetrics: " + mMetrics.widthPixels
1667                + "x" + mMetrics.heightPixels + " " + mMetrics.density);
1668        return mMetrics;
1669    }
1670
1671    /**
1672     * Return the current configuration that is in effect for this resource
1673     * object.  The returned object should be treated as read-only.
1674     *
1675     * @return The resource's current configuration.
1676     */
1677    public Configuration getConfiguration() {
1678        return mConfiguration;
1679    }
1680
1681    /**
1682     * Return the compatibility mode information for the application.
1683     * The returned object should be treated as read-only.
1684     *
1685     * @return compatibility info.
1686     * @hide
1687     */
1688    public CompatibilityInfo getCompatibilityInfo() {
1689        return mCompatibilityInfo != null ? mCompatibilityInfo
1690                : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
1691    }
1692
1693    /**
1694     * This is just for testing.
1695     * @hide
1696     */
1697    public void setCompatibilityInfo(CompatibilityInfo ci) {
1698        mCompatibilityInfo = ci;
1699        updateConfiguration(mConfiguration, mMetrics);
1700    }
1701
1702    /**
1703     * Return a resource identifier for the given resource name.  A fully
1704     * qualified resource name is of the form "package:type/entry".  The first
1705     * two components (package and type) are optional if defType and
1706     * defPackage, respectively, are specified here.
1707     *
1708     * <p>Note: use of this function is discouraged.  It is much more
1709     * efficient to retrieve resources by identifier than by name.
1710     *
1711     * @param name The name of the desired resource.
1712     * @param defType Optional default resource type to find, if "type/" is
1713     *                not included in the name.  Can be null to require an
1714     *                explicit type.
1715     * @param defPackage Optional default package to find, if "package:" is
1716     *                   not included in the name.  Can be null to require an
1717     *                   explicit package.
1718     *
1719     * @return int The associated resource identifier.  Returns 0 if no such
1720     *         resource was found.  (0 is not a valid resource ID.)
1721     */
1722    public int getIdentifier(String name, String defType, String defPackage) {
1723        if (name == null) {
1724            throw new NullPointerException("name is null");
1725        }
1726        try {
1727            return Integer.parseInt(name);
1728        } catch (Exception e) {
1729            // Ignore
1730        }
1731        return mAssets.getResourceIdentifier(name, defType, defPackage);
1732    }
1733
1734    /**
1735     * Return the full name for a given resource identifier.  This name is
1736     * a single string of the form "package:type/entry".
1737     *
1738     * @param resid The resource identifier whose name is to be retrieved.
1739     *
1740     * @return A string holding the name of the resource.
1741     *
1742     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1743     *
1744     * @see #getResourcePackageName
1745     * @see #getResourceTypeName
1746     * @see #getResourceEntryName
1747     */
1748    public String getResourceName(int resid) throws NotFoundException {
1749        String str = mAssets.getResourceName(resid);
1750        if (str != null) return str;
1751        throw new NotFoundException("Unable to find resource ID #0x"
1752                + Integer.toHexString(resid));
1753    }
1754
1755    /**
1756     * Return the package name for a given resource identifier.
1757     *
1758     * @param resid The resource identifier whose package name is to be
1759     * retrieved.
1760     *
1761     * @return A string holding the package name of the resource.
1762     *
1763     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1764     *
1765     * @see #getResourceName
1766     */
1767    public String getResourcePackageName(int resid) throws NotFoundException {
1768        String str = mAssets.getResourcePackageName(resid);
1769        if (str != null) return str;
1770        throw new NotFoundException("Unable to find resource ID #0x"
1771                + Integer.toHexString(resid));
1772    }
1773
1774    /**
1775     * Return the type name for a given resource identifier.
1776     *
1777     * @param resid The resource identifier whose type name is to be
1778     * retrieved.
1779     *
1780     * @return A string holding the type name of the resource.
1781     *
1782     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1783     *
1784     * @see #getResourceName
1785     */
1786    public String getResourceTypeName(int resid) throws NotFoundException {
1787        String str = mAssets.getResourceTypeName(resid);
1788        if (str != null) return str;
1789        throw new NotFoundException("Unable to find resource ID #0x"
1790                + Integer.toHexString(resid));
1791    }
1792
1793    /**
1794     * Return the entry name for a given resource identifier.
1795     *
1796     * @param resid The resource identifier whose entry name is to be
1797     * retrieved.
1798     *
1799     * @return A string holding the entry name of the resource.
1800     *
1801     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
1802     *
1803     * @see #getResourceName
1804     */
1805    public String getResourceEntryName(int resid) throws NotFoundException {
1806        String str = mAssets.getResourceEntryName(resid);
1807        if (str != null) return str;
1808        throw new NotFoundException("Unable to find resource ID #0x"
1809                + Integer.toHexString(resid));
1810    }
1811
1812    /**
1813     * Parse a series of {@link android.R.styleable#Extra &lt;extra&gt;} tags from
1814     * an XML file.  You call this when you are at the parent tag of the
1815     * extra tags, and it will return once all of the child tags have been parsed.
1816     * This will call {@link #parseBundleExtra} for each extra tag encountered.
1817     *
1818     * @param parser The parser from which to retrieve the extras.
1819     * @param outBundle A Bundle in which to place all parsed extras.
1820     * @throws XmlPullParserException
1821     * @throws IOException
1822     */
1823    public void parseBundleExtras(XmlResourceParser parser, Bundle outBundle)
1824            throws XmlPullParserException, IOException {
1825        int outerDepth = parser.getDepth();
1826        int type;
1827        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1828               && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1829            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1830                continue;
1831            }
1832
1833            String nodeName = parser.getName();
1834            if (nodeName.equals("extra")) {
1835                parseBundleExtra("extra", parser, outBundle);
1836                XmlUtils.skipCurrentTag(parser);
1837
1838            } else {
1839                XmlUtils.skipCurrentTag(parser);
1840            }
1841        }
1842    }
1843
1844    /**
1845     * Parse a name/value pair out of an XML tag holding that data.  The
1846     * AttributeSet must be holding the data defined by
1847     * {@link android.R.styleable#Extra}.  The following value types are supported:
1848     * <ul>
1849     * <li> {@link TypedValue#TYPE_STRING}:
1850     * {@link Bundle#putCharSequence Bundle.putCharSequence()}
1851     * <li> {@link TypedValue#TYPE_INT_BOOLEAN}:
1852     * {@link Bundle#putCharSequence Bundle.putBoolean()}
1853     * <li> {@link TypedValue#TYPE_FIRST_INT}-{@link TypedValue#TYPE_LAST_INT}:
1854     * {@link Bundle#putCharSequence Bundle.putBoolean()}
1855     * <li> {@link TypedValue#TYPE_FLOAT}:
1856     * {@link Bundle#putCharSequence Bundle.putFloat()}
1857     * </ul>
1858     *
1859     * @param tagName The name of the tag these attributes come from; this is
1860     * only used for reporting error messages.
1861     * @param attrs The attributes from which to retrieve the name/value pair.
1862     * @param outBundle The Bundle in which to place the parsed value.
1863     * @throws XmlPullParserException If the attributes are not valid.
1864     */
1865    public void parseBundleExtra(String tagName, AttributeSet attrs,
1866            Bundle outBundle) throws XmlPullParserException {
1867        TypedArray sa = obtainAttributes(attrs,
1868                com.android.internal.R.styleable.Extra);
1869
1870        String name = sa.getString(
1871                com.android.internal.R.styleable.Extra_name);
1872        if (name == null) {
1873            sa.recycle();
1874            throw new XmlPullParserException("<" + tagName
1875                    + "> requires an android:name attribute at "
1876                    + attrs.getPositionDescription());
1877        }
1878
1879        TypedValue v = sa.peekValue(
1880                com.android.internal.R.styleable.Extra_value);
1881        if (v != null) {
1882            if (v.type == TypedValue.TYPE_STRING) {
1883                CharSequence cs = v.coerceToString();
1884                outBundle.putCharSequence(name, cs);
1885            } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
1886                outBundle.putBoolean(name, v.data != 0);
1887            } else if (v.type >= TypedValue.TYPE_FIRST_INT
1888                    && v.type <= TypedValue.TYPE_LAST_INT) {
1889                outBundle.putInt(name, v.data);
1890            } else if (v.type == TypedValue.TYPE_FLOAT) {
1891                outBundle.putFloat(name, v.getFloat());
1892            } else {
1893                sa.recycle();
1894                throw new XmlPullParserException("<" + tagName
1895                        + "> only supports string, integer, float, color, and boolean at "
1896                        + attrs.getPositionDescription());
1897            }
1898        } else {
1899            sa.recycle();
1900            throw new XmlPullParserException("<" + tagName
1901                    + "> requires an android:value or android:resource attribute at "
1902                    + attrs.getPositionDescription());
1903        }
1904
1905        sa.recycle();
1906    }
1907
1908    /**
1909     * Retrieve underlying AssetManager storage for these resources.
1910     */
1911    public final AssetManager getAssets() {
1912        return mAssets;
1913    }
1914
1915    /**
1916     * Call this to remove all cached loaded layout resources from the
1917     * Resources object.  Only intended for use with performance testing
1918     * tools.
1919     */
1920    public final void flushLayoutCache() {
1921        synchronized (mCachedXmlBlockIds) {
1922            // First see if this block is in our cache.
1923            final int num = mCachedXmlBlockIds.length;
1924            for (int i=0; i<num; i++) {
1925                mCachedXmlBlockIds[i] = -0;
1926                XmlBlock oldBlock = mCachedXmlBlocks[i];
1927                if (oldBlock != null) {
1928                    oldBlock.close();
1929                }
1930                mCachedXmlBlocks[i] = null;
1931            }
1932        }
1933    }
1934
1935    /**
1936     * Start preloading of resource data using this Resources object.  Only
1937     * for use by the zygote process for loading common system resources.
1938     * {@hide}
1939     */
1940    public final void startPreloading() {
1941        synchronized (sSync) {
1942            if (sPreloaded) {
1943                throw new IllegalStateException("Resources already preloaded");
1944            }
1945            sPreloaded = true;
1946            mPreloading = true;
1947            sPreloadedDensity = DisplayMetrics.DENSITY_DEVICE;
1948            mConfiguration.densityDpi = sPreloadedDensity;
1949            updateConfiguration(null, null);
1950        }
1951    }
1952
1953    /**
1954     * Called by zygote when it is done preloading resources, to change back
1955     * to normal Resources operation.
1956     */
1957    public final void finishPreloading() {
1958        if (mPreloading) {
1959            mPreloading = false;
1960            flushLayoutCache();
1961        }
1962    }
1963
1964    private boolean verifyPreloadConfig(TypedValue value, String name) {
1965        if ((value.changingConfigurations&~(ActivityInfo.CONFIG_FONT_SCALE
1966                | ActivityInfo.CONFIG_DENSITY)) != 0) {
1967            String resName;
1968            try {
1969                resName = getResourceName(value.resourceId);
1970            } catch (NotFoundException e) {
1971                resName = "?";
1972            }
1973            Log.w(TAG, "Preloaded " + name + " resource #0x"
1974                    + Integer.toHexString(value.resourceId)
1975                    + " (" + resName + ") that varies with configuration!!");
1976            return false;
1977        }
1978        return true;
1979    }
1980
1981    /*package*/ Drawable loadDrawable(TypedValue value, int id)
1982            throws NotFoundException {
1983
1984        if (TRACE_FOR_PRELOAD) {
1985            // Log only framework resources
1986            if ((id >>> 24) == 0x1) {
1987                final String name = getResourceName(id);
1988                if (name != null) android.util.Log.d("PreloadDrawable", name);
1989            }
1990        }
1991
1992        boolean isColorDrawable = false;
1993        if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
1994                value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
1995            isColorDrawable = true;
1996        }
1997        final long key = isColorDrawable ? value.data :
1998                (((long) value.assetCookie) << 32) | value.data;
1999
2000        Drawable dr = getCachedDrawable(isColorDrawable ? mColorDrawableCache : mDrawableCache, key);
2001
2002        if (dr != null) {
2003            return dr;
2004        }
2005
2006        Drawable.ConstantState cs = isColorDrawable
2007                ? sPreloadedColorDrawables.get(key)
2008                : (sPreloadedDensity == mConfiguration.densityDpi
2009                        ? sPreloadedDrawables.get(key) : null);
2010        if (cs != null) {
2011            dr = cs.newDrawable(this);
2012        } else {
2013            if (isColorDrawable) {
2014                dr = new ColorDrawable(value.data);
2015            }
2016
2017            if (dr == null) {
2018                if (value.string == null) {
2019                    throw new NotFoundException(
2020                            "Resource is not a Drawable (color or path): " + value);
2021                }
2022
2023                String file = value.string.toString();
2024
2025                if (TRACE_FOR_MISS_PRELOAD) {
2026                    // Log only framework resources
2027                    if ((id >>> 24) == 0x1) {
2028                        final String name = getResourceName(id);
2029                        if (name != null) android.util.Log.d(TAG, "Loading framework drawable #"
2030                                + Integer.toHexString(id) + ": " + name
2031                                + " at " + file);
2032                    }
2033                }
2034
2035                if (DEBUG_LOAD) Log.v(TAG, "Loading drawable for cookie "
2036                        + value.assetCookie + ": " + file);
2037
2038                if (file.endsWith(".xml")) {
2039                    try {
2040                        XmlResourceParser rp = loadXmlResourceParser(
2041                                file, id, value.assetCookie, "drawable");
2042                        dr = Drawable.createFromXml(this, rp);
2043                        rp.close();
2044                    } catch (Exception e) {
2045                        NotFoundException rnf = new NotFoundException(
2046                            "File " + file + " from drawable resource ID #0x"
2047                            + Integer.toHexString(id));
2048                        rnf.initCause(e);
2049                        throw rnf;
2050                    }
2051
2052                } else {
2053                    try {
2054                        InputStream is = mAssets.openNonAsset(
2055                                value.assetCookie, file, AssetManager.ACCESS_STREAMING);
2056        //                System.out.println("Opened file " + file + ": " + is);
2057                        dr = Drawable.createFromResourceStream(this, value, is,
2058                                file, null);
2059                        is.close();
2060        //                System.out.println("Created stream: " + dr);
2061                    } catch (Exception e) {
2062                        NotFoundException rnf = new NotFoundException(
2063                            "File " + file + " from drawable resource ID #0x"
2064                            + Integer.toHexString(id));
2065                        rnf.initCause(e);
2066                        throw rnf;
2067                    }
2068                }
2069            }
2070        }
2071
2072        if (dr != null) {
2073            dr.setChangingConfigurations(value.changingConfigurations);
2074            cs = dr.getConstantState();
2075            if (cs != null) {
2076                if (mPreloading) {
2077                    if (verifyPreloadConfig(value, "drawable")) {
2078                        if (isColorDrawable) {
2079                            sPreloadedColorDrawables.put(key, cs);
2080                        } else {
2081                            sPreloadedDrawables.put(key, cs);
2082                        }
2083                    }
2084                } else {
2085                    synchronized (mAccessLock) {
2086                        //Log.i(TAG, "Saving cached drawable @ #" +
2087                        //        Integer.toHexString(key.intValue())
2088                        //        + " in " + this + ": " + cs);
2089                        if (isColorDrawable) {
2090                            mColorDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
2091                        } else {
2092                            mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
2093                        }
2094                    }
2095                }
2096            }
2097        }
2098
2099        return dr;
2100    }
2101
2102    private Drawable getCachedDrawable(
2103            LongSparseArray<WeakReference<ConstantState>> drawableCache,
2104            long key) {
2105        synchronized (mAccessLock) {
2106            WeakReference<Drawable.ConstantState> wr = drawableCache.get(key);
2107            if (wr != null) {   // we have the key
2108                Drawable.ConstantState entry = wr.get();
2109                if (entry != null) {
2110                    //Log.i(TAG, "Returning cached drawable @ #" +
2111                    //        Integer.toHexString(((Integer)key).intValue())
2112                    //        + " in " + this + ": " + entry);
2113                    return entry.newDrawable(this);
2114                }
2115                else {  // our entry has been purged
2116                    drawableCache.delete(key);
2117                }
2118            }
2119        }
2120        return null;
2121    }
2122
2123    /*package*/ ColorStateList loadColorStateList(TypedValue value, int id)
2124            throws NotFoundException {
2125        if (TRACE_FOR_PRELOAD) {
2126            // Log only framework resources
2127            if ((id >>> 24) == 0x1) {
2128                final String name = getResourceName(id);
2129                if (name != null) android.util.Log.d("PreloadColorStateList", name);
2130            }
2131        }
2132
2133        final long key = (((long) value.assetCookie) << 32) | value.data;
2134
2135        ColorStateList csl;
2136
2137        if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
2138                value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
2139
2140            csl = sPreloadedColorStateLists.get(key);
2141            if (csl != null) {
2142                return csl;
2143            }
2144
2145            csl = ColorStateList.valueOf(value.data);
2146            if (mPreloading) {
2147                if (verifyPreloadConfig(value, "color")) {
2148                    sPreloadedColorStateLists.put(key, csl);
2149                }
2150            }
2151
2152            return csl;
2153        }
2154
2155        csl = getCachedColorStateList(key);
2156        if (csl != null) {
2157            return csl;
2158        }
2159
2160        csl = sPreloadedColorStateLists.get(key);
2161        if (csl != null) {
2162            return csl;
2163        }
2164
2165        if (value.string == null) {
2166            throw new NotFoundException(
2167                    "Resource is not a ColorStateList (color or path): " + value);
2168        }
2169
2170        String file = value.string.toString();
2171
2172        if (file.endsWith(".xml")) {
2173            try {
2174                XmlResourceParser rp = loadXmlResourceParser(
2175                        file, id, value.assetCookie, "colorstatelist");
2176                csl = ColorStateList.createFromXml(this, rp);
2177                rp.close();
2178            } catch (Exception e) {
2179                NotFoundException rnf = new NotFoundException(
2180                    "File " + file + " from color state list resource ID #0x"
2181                    + Integer.toHexString(id));
2182                rnf.initCause(e);
2183                throw rnf;
2184            }
2185        } else {
2186            throw new NotFoundException(
2187                    "File " + file + " from drawable resource ID #0x"
2188                    + Integer.toHexString(id) + ": .xml extension required");
2189        }
2190
2191        if (csl != null) {
2192            if (mPreloading) {
2193                if (verifyPreloadConfig(value, "color")) {
2194                    sPreloadedColorStateLists.put(key, csl);
2195                }
2196            } else {
2197                synchronized (mAccessLock) {
2198                    //Log.i(TAG, "Saving cached color state list @ #" +
2199                    //        Integer.toHexString(key.intValue())
2200                    //        + " in " + this + ": " + csl);
2201                    mColorStateListCache.put(key, new WeakReference<ColorStateList>(csl));
2202                }
2203            }
2204        }
2205
2206        return csl;
2207    }
2208
2209    private ColorStateList getCachedColorStateList(long key) {
2210        synchronized (mAccessLock) {
2211            WeakReference<ColorStateList> wr = mColorStateListCache.get(key);
2212            if (wr != null) {   // we have the key
2213                ColorStateList entry = wr.get();
2214                if (entry != null) {
2215                    //Log.i(TAG, "Returning cached color state list @ #" +
2216                    //        Integer.toHexString(((Integer)key).intValue())
2217                    //        + " in " + this + ": " + entry);
2218                    return entry;
2219                } else {  // our entry has been purged
2220                    mColorStateListCache.delete(key);
2221                }
2222            }
2223        }
2224        return null;
2225    }
2226
2227    /*package*/ XmlResourceParser loadXmlResourceParser(int id, String type)
2228            throws NotFoundException {
2229        synchronized (mAccessLock) {
2230            TypedValue value = mTmpValue;
2231            if (value == null) {
2232                mTmpValue = value = new TypedValue();
2233            }
2234            getValue(id, value, true);
2235            if (value.type == TypedValue.TYPE_STRING) {
2236                return loadXmlResourceParser(value.string.toString(), id,
2237                        value.assetCookie, type);
2238            }
2239            throw new NotFoundException(
2240                    "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
2241                    + Integer.toHexString(value.type) + " is not valid");
2242        }
2243    }
2244
2245    /*package*/ XmlResourceParser loadXmlResourceParser(String file, int id,
2246            int assetCookie, String type) throws NotFoundException {
2247        if (id != 0) {
2248            try {
2249                // These may be compiled...
2250                synchronized (mCachedXmlBlockIds) {
2251                    // First see if this block is in our cache.
2252                    final int num = mCachedXmlBlockIds.length;
2253                    for (int i=0; i<num; i++) {
2254                        if (mCachedXmlBlockIds[i] == id) {
2255                            //System.out.println("**** REUSING XML BLOCK!  id="
2256                            //                   + id + ", index=" + i);
2257                            return mCachedXmlBlocks[i].newParser();
2258                        }
2259                    }
2260
2261                    // Not in the cache, create a new block and put it at
2262                    // the next slot in the cache.
2263                    XmlBlock block = mAssets.openXmlBlockAsset(
2264                            assetCookie, file);
2265                    if (block != null) {
2266                        int pos = mLastCachedXmlBlockIndex+1;
2267                        if (pos >= num) pos = 0;
2268                        mLastCachedXmlBlockIndex = pos;
2269                        XmlBlock oldBlock = mCachedXmlBlocks[pos];
2270                        if (oldBlock != null) {
2271                            oldBlock.close();
2272                        }
2273                        mCachedXmlBlockIds[pos] = id;
2274                        mCachedXmlBlocks[pos] = block;
2275                        //System.out.println("**** CACHING NEW XML BLOCK!  id="
2276                        //                   + id + ", index=" + pos);
2277                        return block.newParser();
2278                    }
2279                }
2280            } catch (Exception e) {
2281                NotFoundException rnf = new NotFoundException(
2282                        "File " + file + " from xml type " + type + " resource ID #0x"
2283                        + Integer.toHexString(id));
2284                rnf.initCause(e);
2285                throw rnf;
2286            }
2287        }
2288
2289        throw new NotFoundException(
2290                "File " + file + " from xml type " + type + " resource ID #0x"
2291                + Integer.toHexString(id));
2292    }
2293
2294    private TypedArray getCachedStyledAttributes(int len) {
2295        synchronized (mAccessLock) {
2296            TypedArray attrs = mCachedStyledAttributes;
2297            if (attrs != null) {
2298                mCachedStyledAttributes = null;
2299                if (DEBUG_ATTRIBUTES_CACHE) {
2300                    mLastRetrievedAttrs = new RuntimeException("here");
2301                    mLastRetrievedAttrs.fillInStackTrace();
2302                }
2303
2304                attrs.mLength = len;
2305                int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
2306                if (attrs.mData.length >= fullLen) {
2307                    return attrs;
2308                }
2309                attrs.mData = new int[fullLen];
2310                attrs.mIndices = new int[1+len];
2311                return attrs;
2312            }
2313            if (DEBUG_ATTRIBUTES_CACHE) {
2314                RuntimeException here = new RuntimeException("here");
2315                here.fillInStackTrace();
2316                if (mLastRetrievedAttrs != null) {
2317                    Log.i(TAG, "Allocated new TypedArray of " + len + " in " + this, here);
2318                    Log.i(TAG, "Last retrieved attributes here", mLastRetrievedAttrs);
2319                }
2320                mLastRetrievedAttrs = here;
2321            }
2322            return new TypedArray(this,
2323                    new int[len*AssetManager.STYLE_NUM_ENTRIES],
2324                    new int[1+len], len);
2325        }
2326    }
2327
2328    private Resources() {
2329        mAssets = AssetManager.getSystem();
2330        // NOTE: Intentionally leaving this uninitialized (all values set
2331        // to zero), so that anyone who tries to do something that requires
2332        // metrics will get a very wrong value.
2333        mConfiguration.setToDefaults();
2334        mMetrics.setToDefaults();
2335        updateConfiguration(null, null);
2336        mAssets.ensureStringBlocks();
2337        mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
2338    }
2339}
2340