ResourcesImpl.java revision ee7e8f13ea2293e93ef9dd9f3f088186edd4864e
1fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski/*
2fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski * Copyright (C) 2016 The Android Open Source Project
3fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski *
4fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski * use this file except in compliance with the License. You may obtain a copy of
6fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski * the License at
7fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski *
8fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0
9fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski *
10fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski * Unless required by applicable law or agreed to in writing, software
11fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski * License for the specific language governing permissions and limitations under
14fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski * the License.
15fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski */
16fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskipackage android.content.res;
17fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
18ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viveretteimport org.xmlpull.v1.XmlPullParser;
19ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viveretteimport org.xmlpull.v1.XmlPullParserException;
20ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette
21fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.animation.Animator;
22fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.animation.StateListAnimator;
23fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.annotation.AnyRes;
24fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.annotation.AttrRes;
25fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.annotation.NonNull;
26fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.annotation.Nullable;
27fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.annotation.PluralsRes;
28fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.annotation.RawRes;
29fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.annotation.StyleRes;
30fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.annotation.StyleableRes;
31fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.content.pm.ActivityInfo;
32ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viveretteimport android.content.pm.ActivityInfo.Config;
339ad386b37c4c4ebe1176caa8eeab131387fc93edAlan Viveretteimport android.content.res.Configuration.NativeConfig;
34fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.content.res.Resources.NotFoundException;
354b5a4d221f377686a730182a3bffb8c6f190e313Clara Bayarriimport android.graphics.FontFamily;
3618e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarriimport android.graphics.Typeface;
37fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.graphics.drawable.ColorDrawable;
38fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.graphics.drawable.Drawable;
39ee7e8f13ea2293e93ef9dd9f3f088186edd4864eztenghuiimport android.graphics.drawable.DrawableContainer;
40fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.icu.text.PluralRules;
41fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.os.Build;
4223cbe85610f780134cc77dd4a54732a22ed6e86eYohei Yukawaimport android.os.LocaleList;
43fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.os.Trace;
44ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarriimport android.text.FontConfig;
45fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.util.AttributeSet;
46fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.util.DisplayMetrics;
47fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.util.Log;
48fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.util.LongSparseArray;
49fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.util.Slog;
50fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.util.TypedValue;
51fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport android.util.Xml;
524ece3d6bb18a609afcd0e82f0340b7d36ba24eeaAdam Lesinskiimport android.view.DisplayAdjustments;
53fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
5418e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarriimport java.io.IOException;
55fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport java.io.InputStream;
56fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport java.util.Arrays;
574b5a4d221f377686a730182a3bffb8c6f190e313Clara Bayarriimport java.util.List;
58fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskiimport java.util.Locale;
59fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
60fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski/**
61082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski * The implementation of Resource access. This class contains the AssetManager and all caches
62082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski * associated with it.
63082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski *
64082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski * {@link Resources} is just a thing wrapper around this class. When a configuration change
65082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski * occurs, clients can retain the same {@link Resources} reference because the underlying
66082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski * {@link ResourcesImpl} object will be updated or re-created.
67082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski *
68fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski * @hide
69fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski */
70fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinskipublic class ResourcesImpl {
71fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    static final String TAG = "Resources";
72fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
73fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private static final boolean DEBUG_LOAD = false;
74fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private static final boolean DEBUG_CONFIG = false;
75fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private static final boolean TRACE_FOR_PRELOAD = false;
76fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private static final boolean TRACE_FOR_MISS_PRELOAD = false;
77fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
78fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
79fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private static final int ID_OTHER = 0x01000004;
80fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
81fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private static final Object sSync = new Object();
82fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
83fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private static boolean sPreloaded;
84fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private boolean mPreloading;
85fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
86fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    // Information about preloaded resources.  Note that they are not
87fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    // protected by a lock, because while preloading in zygote we are all
88fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    // single-threaded, and after that these are immutable.
89fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private static final LongSparseArray<Drawable.ConstantState>[] sPreloadedDrawables;
90fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
91fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            = new LongSparseArray<>();
92fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private static final LongSparseArray<android.content.res.ConstantState<ComplexColor>>
93fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            sPreloadedComplexColors = new LongSparseArray<>();
94fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
95fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    /** Lock object used to protect access to caches and configuration. */
96fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private final Object mAccessLock = new Object();
97fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
98fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    // These are protected by mAccessLock.
99fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private final Configuration mTmpConfig = new Configuration();
100fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private final DrawableCache mDrawableCache = new DrawableCache();
101fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private final DrawableCache mColorDrawableCache = new DrawableCache();
102fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private final ConfigurationBoundResourceCache<ComplexColor> mComplexColorCache =
103fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            new ConfigurationBoundResourceCache<>();
104fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private final ConfigurationBoundResourceCache<Animator> mAnimatorCache =
105fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            new ConfigurationBoundResourceCache<>();
106fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
107fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            new ConfigurationBoundResourceCache<>();
108fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
109fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    /** Size of the cyclical cache used to map XML files to blocks. */
110fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private static final int XML_BLOCK_CACHE_SIZE = 4;
111fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
112fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    // Cyclical cache used for recently-accessed XML files.
113fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private int mLastCachedXmlBlockIndex = -1;
114fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private final int[] mCachedXmlBlockCookies = new int[XML_BLOCK_CACHE_SIZE];
115fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private final String[] mCachedXmlBlockFiles = new String[XML_BLOCK_CACHE_SIZE];
116fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[XML_BLOCK_CACHE_SIZE];
117fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
118fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
119fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    final AssetManager mAssets;
1204ece3d6bb18a609afcd0e82f0340b7d36ba24eeaAdam Lesinski    private final DisplayMetrics mMetrics = new DisplayMetrics();
1218e8d23214a71d8813ebd3676b192924c530cb913Adam Lesinski    private final DisplayAdjustments mDisplayAdjustments;
122fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
123fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private PluralRules mPluralRule;
124fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
125fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private final Configuration mConfiguration = new Configuration();
126fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
127fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    static {
128fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        sPreloadedDrawables = new LongSparseArray[2];
129fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        sPreloadedDrawables[0] = new LongSparseArray<>();
130fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        sPreloadedDrawables[1] = new LongSparseArray<>();
131fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
132fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
133fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    /**
134fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * Creates a new ResourcesImpl object with CompatibilityInfo.
135fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     *
136fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * @param assets Previously created AssetManager.
137fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * @param metrics Current display metrics to consider when
138fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     *                selecting/computing resource values.
139fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * @param config Desired device configuration to consider when
140fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     *               selecting/computing resource values (optional).
1418e8d23214a71d8813ebd3676b192924c530cb913Adam Lesinski     * @param displayAdjustments this resource's Display override and compatibility info.
1428e8d23214a71d8813ebd3676b192924c530cb913Adam Lesinski     *                           Must not be null.
143fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     */
1444ece3d6bb18a609afcd0e82f0340b7d36ba24eeaAdam Lesinski    public ResourcesImpl(@NonNull AssetManager assets, @Nullable DisplayMetrics metrics,
1458e8d23214a71d8813ebd3676b192924c530cb913Adam Lesinski            @Nullable Configuration config, @NonNull DisplayAdjustments displayAdjustments) {
146fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        mAssets = assets;
147fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        mMetrics.setToDefaults();
1488e8d23214a71d8813ebd3676b192924c530cb913Adam Lesinski        mDisplayAdjustments = displayAdjustments;
149bad43fcae487a19865c174483c11829379817c8aAdam Lesinski        mConfiguration.setToDefaults();
1508e8d23214a71d8813ebd3676b192924c530cb913Adam Lesinski        updateConfiguration(config, metrics, displayAdjustments.getCompatibilityInfo());
151fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        mAssets.ensureStringBlocks();
152fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
153fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1544ece3d6bb18a609afcd0e82f0340b7d36ba24eeaAdam Lesinski    public DisplayAdjustments getDisplayAdjustments() {
1554ece3d6bb18a609afcd0e82f0340b7d36ba24eeaAdam Lesinski        return mDisplayAdjustments;
1564ece3d6bb18a609afcd0e82f0340b7d36ba24eeaAdam Lesinski    }
1574ece3d6bb18a609afcd0e82f0340b7d36ba24eeaAdam Lesinski
158082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski    public AssetManager getAssets() {
159fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return mAssets;
160fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
161fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
162fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    DisplayMetrics getDisplayMetrics() {
163fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (DEBUG_CONFIG) Slog.v(TAG, "Returning DisplayMetrics: " + mMetrics.widthPixels
164fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                + "x" + mMetrics.heightPixels + " " + mMetrics.density);
165fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return mMetrics;
166fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
167fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
168fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    Configuration getConfiguration() {
169fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return mConfiguration;
170fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
171fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
172fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    Configuration[] getSizeConfigurations() {
173fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return mAssets.getSizeConfigurations();
174fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
175fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
176fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    CompatibilityInfo getCompatibilityInfo() {
1778e8d23214a71d8813ebd3676b192924c530cb913Adam Lesinski        return mDisplayAdjustments.getCompatibilityInfo();
178fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
179fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
180fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private PluralRules getPluralRule() {
181fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        synchronized (sSync) {
182fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if (mPluralRule == null) {
183fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
184fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
185fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return mPluralRule;
186fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
187fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
188fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
189fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs)
190fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            throws NotFoundException {
191fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
192fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (found) {
193fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return;
194fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
195fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
196fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
197fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
198fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    void getValueForDensity(@AnyRes int id, int density, TypedValue outValue,
199082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski            boolean resolveRefs) throws NotFoundException {
200fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
201fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (found) {
202fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return;
203fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
204fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
205fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
206fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
207fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    void getValue(String name, TypedValue outValue, boolean resolveRefs)
208fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            throws NotFoundException {
209fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        int id = getIdentifier(name, "string", null);
210fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (id != 0) {
211fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            getValue(id, outValue, resolveRefs);
212fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return;
213fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
214fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        throw new NotFoundException("String resource name " + name);
215fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
216fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
217fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    int getIdentifier(String name, String defType, String defPackage) {
218fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (name == null) {
219fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            throw new NullPointerException("name is null");
220fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
221fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        try {
222fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return Integer.parseInt(name);
223fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        } catch (Exception e) {
224fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // Ignore
225fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
226fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return mAssets.getResourceIdentifier(name, defType, defPackage);
227fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
228fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
229fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    @NonNull
230fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    String getResourceName(@AnyRes int resid) throws NotFoundException {
231fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        String str = mAssets.getResourceName(resid);
232fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (str != null) return str;
233fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        throw new NotFoundException("Unable to find resource ID #0x"
234fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                + Integer.toHexString(resid));
235fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
236fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
237fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    @NonNull
238fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    String getResourcePackageName(@AnyRes int resid) throws NotFoundException {
239fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        String str = mAssets.getResourcePackageName(resid);
240fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (str != null) return str;
241fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        throw new NotFoundException("Unable to find resource ID #0x"
242fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                + Integer.toHexString(resid));
243fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
244fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
245fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    @NonNull
246fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    String getResourceTypeName(@AnyRes int resid) throws NotFoundException {
247fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        String str = mAssets.getResourceTypeName(resid);
248fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (str != null) return str;
249fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        throw new NotFoundException("Unable to find resource ID #0x"
250fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                + Integer.toHexString(resid));
251fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
252fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
253fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    @NonNull
254fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    String getResourceEntryName(@AnyRes int resid) throws NotFoundException {
255fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        String str = mAssets.getResourceEntryName(resid);
256fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (str != null) return str;
257fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        throw new NotFoundException("Unable to find resource ID #0x"
258fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                + Integer.toHexString(resid));
259fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
260fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
261fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    @NonNull
262fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    CharSequence getQuantityText(@PluralsRes int id, int quantity) throws NotFoundException {
263fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        PluralRules rule = getPluralRule();
264fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        CharSequence res = mAssets.getResourceBagText(id,
265fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                attrForQuantityCode(rule.select(quantity)));
266fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (res != null) {
267fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return res;
268fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
269fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        res = mAssets.getResourceBagText(id, ID_OTHER);
270fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (res != null) {
271fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return res;
272fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
273fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        throw new NotFoundException("Plural resource ID #0x" + Integer.toHexString(id)
274fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                + " quantity=" + quantity
275fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                + " item=" + rule.select(quantity));
276fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
277fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
278fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private static int attrForQuantityCode(String quantityCode) {
279fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        switch (quantityCode) {
280fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            case PluralRules.KEYWORD_ZERO: return 0x01000005;
281fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            case PluralRules.KEYWORD_ONE:  return 0x01000006;
282fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            case PluralRules.KEYWORD_TWO:  return 0x01000007;
283fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            case PluralRules.KEYWORD_FEW:  return 0x01000008;
284fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            case PluralRules.KEYWORD_MANY: return 0x01000009;
285fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            default:                       return ID_OTHER;
286fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
287fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
288fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
289fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    @NonNull
290fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    AssetFileDescriptor openRawResourceFd(@RawRes int id, TypedValue tempValue)
291fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            throws NotFoundException {
292fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        getValue(id, tempValue, true);
293fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        try {
294fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return mAssets.openNonAssetFd(tempValue.assetCookie, tempValue.string.toString());
295fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        } catch (Exception e) {
296fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            throw new NotFoundException("File " + tempValue.string.toString() + " from drawable "
297fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    + "resource ID #0x" + Integer.toHexString(id), e);
298fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
299fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
300fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
301fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    @NonNull
302fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    InputStream openRawResource(@RawRes int id, TypedValue value) throws NotFoundException {
303fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        getValue(id, value, true);
304fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        try {
305fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return mAssets.openNonAsset(value.assetCookie, value.string.toString(),
306fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    AssetManager.ACCESS_STREAMING);
307fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        } catch (Exception e) {
308f135b271bfaa5a23f3af5a15ce59fd4ffb44a6beChristopher Tate            // Note: value.string might be null
309f135b271bfaa5a23f3af5a15ce59fd4ffb44a6beChristopher Tate            NotFoundException rnf = new NotFoundException("File "
310f135b271bfaa5a23f3af5a15ce59fd4ffb44a6beChristopher Tate                    + (value.string == null ? "(null)" : value.string.toString())
311f135b271bfaa5a23f3af5a15ce59fd4ffb44a6beChristopher Tate                    + " from drawable resource ID #0x" + Integer.toHexString(id));
312fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            rnf.initCause(e);
313fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            throw rnf;
314fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
315fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
316fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
317fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    ConfigurationBoundResourceCache<Animator> getAnimatorCache() {
318fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return mAnimatorCache;
319fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
320fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
321fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    ConfigurationBoundResourceCache<StateListAnimator> getStateListAnimatorCache() {
322fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return mStateListAnimatorCache;
323fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
324fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
325082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski    public void updateConfiguration(Configuration config, DisplayMetrics metrics,
326082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski                                    CompatibilityInfo compat) {
327991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ResourcesImpl#updateConfiguration");
328991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski        try {
329991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski            synchronized (mAccessLock) {
330991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                if (false) {
331991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    Slog.i(TAG, "**** Updating config of " + this + ": old config is "
3328e8d23214a71d8813ebd3676b192924c530cb913Adam Lesinski                            + mConfiguration + " old compat is "
3338e8d23214a71d8813ebd3676b192924c530cb913Adam Lesinski                            + mDisplayAdjustments.getCompatibilityInfo());
334991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    Slog.i(TAG, "**** Updating config of " + this + ": new config is "
335991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                            + config + " new compat is " + compat);
336991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                }
337991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                if (compat != null) {
3388e8d23214a71d8813ebd3676b192924c530cb913Adam Lesinski                    mDisplayAdjustments.setCompatibilityInfo(compat);
339991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                }
340991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                if (metrics != null) {
341991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    mMetrics.setTo(metrics);
342991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                }
343991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                // NOTE: We should re-arrange this code to create a Display
344991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                // with the CompatibilityInfo that is used everywhere we deal
345991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                // with the display in relation to this app, rather than
346991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                // doing the conversion here.  This impl should be okay because
347991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                // we make sure to return a compatible display in the places
348991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                // where there are public APIs to retrieve the display...  but
349b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                // it would be cleaner and more maintainable to just be
350991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                // consistently dealing with a compatible display everywhere in
351991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                // the framework.
3528e8d23214a71d8813ebd3676b192924c530cb913Adam Lesinski                mDisplayAdjustments.getCompatibilityInfo().applyToDisplayMetrics(mMetrics);
353991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski
354991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                final @Config int configChanges = calcConfigChanges(config);
355991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski
356b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                // If even after the update there are no Locales set, grab the default locales.
357991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                LocaleList locales = mConfiguration.getLocales();
358991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                if (locales.isEmpty()) {
359b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                    locales = LocaleList.getDefault();
360991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    mConfiguration.setLocales(locales);
361991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                }
362b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski
363b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                if ((configChanges & ActivityInfo.CONFIG_LOCALE) != 0) {
364b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                    if (locales.size() > 1) {
365b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                        // The LocaleList has changed. We must query the AssetManager's available
366b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                        // Locales and figure out the best matching Locale in the new LocaleList.
367b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                        String[] availableLocales = mAssets.getNonSystemLocales();
368b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                        if (LocaleList.isPseudoLocalesOnly(availableLocales)) {
369b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                            // No app defined locales, so grab the system locales.
370b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                            availableLocales = mAssets.getLocales();
371b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                            if (LocaleList.isPseudoLocalesOnly(availableLocales)) {
372b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                                availableLocales = null;
373b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                            }
374b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                        }
375b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski
376b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                        if (availableLocales != null) {
377b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                            final Locale bestLocale = locales.getFirstMatchWithEnglishSupported(
378b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                                    availableLocales);
379b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                            if (bestLocale != null && bestLocale != locales.get(0)) {
380b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                                mConfiguration.setLocales(new LocaleList(bestLocale, locales));
381b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                            }
382b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                        }
383b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                    }
384b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                }
385b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski
386991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
387991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    mMetrics.densityDpi = mConfiguration.densityDpi;
388991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    mMetrics.density =
389991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                            mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
390991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                }
391bad43fcae487a19865c174483c11829379817c8aAdam Lesinski
392bad43fcae487a19865c174483c11829379817c8aAdam Lesinski                // Protect against an unset fontScale.
393bad43fcae487a19865c174483c11829379817c8aAdam Lesinski                mMetrics.scaledDensity = mMetrics.density *
394bad43fcae487a19865c174483c11829379817c8aAdam Lesinski                        (mConfiguration.fontScale != 0 ? mConfiguration.fontScale : 1.0f);
395991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski
396991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                final int width, height;
397991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                if (mMetrics.widthPixels >= mMetrics.heightPixels) {
398991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    width = mMetrics.widthPixels;
399991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    height = mMetrics.heightPixels;
400991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                } else {
401991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    //noinspection SuspiciousNameCombination
402991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    width = mMetrics.heightPixels;
403991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    //noinspection SuspiciousNameCombination
404991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    height = mMetrics.widthPixels;
405991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                }
406991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski
407991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                final int keyboardHidden;
408991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                if (mConfiguration.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
409991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                        && mConfiguration.hardKeyboardHidden
410991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                        == Configuration.HARDKEYBOARDHIDDEN_YES) {
411991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT;
412991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                } else {
413991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    keyboardHidden = mConfiguration.keyboardHidden;
414991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                }
415991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski
416991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
417b61e405397200f78b1c652143cba7c751df05a00Adam Lesinski                        adjustLanguageTag(mConfiguration.getLocales().get(0).toLanguageTag()),
418991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                        mConfiguration.orientation,
419991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                        mConfiguration.touchscreen,
420991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                        mConfiguration.densityDpi, mConfiguration.keyboard,
421991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                        keyboardHidden, mConfiguration.navigation, width, height,
422991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                        mConfiguration.smallestScreenWidthDp,
423991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                        mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
424991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                        mConfiguration.screenLayout, mConfiguration.uiMode,
425408afbf06040ea29d1a9d60e9dc50d1923068de4Romain Guy                        mConfiguration.colorMode, Build.VERSION.RESOURCES_SDK_INT);
426991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski
427991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                if (DEBUG_CONFIG) {
428991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    Slog.i(TAG, "**** Updating config of " + this + ": final config is "
4298e8d23214a71d8813ebd3676b192924c530cb913Adam Lesinski                            + mConfiguration + " final compat is "
4308e8d23214a71d8813ebd3676b192924c530cb913Adam Lesinski                            + mDisplayAdjustments.getCompatibilityInfo());
431991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                }
432991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski
433991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                mDrawableCache.onConfigurationChange(configChanges);
434991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                mColorDrawableCache.onConfigurationChange(configChanges);
435991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                mComplexColorCache.onConfigurationChange(configChanges);
436991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                mAnimatorCache.onConfigurationChange(configChanges);
437991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                mStateListAnimatorCache.onConfigurationChange(configChanges);
438991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski
439991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                flushLayoutCache();
440fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
441991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski            synchronized (sSync) {
442991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                if (mPluralRule != null) {
443991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                    mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
444991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski                }
445fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
446991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski        } finally {
447991357fe25b3addabf85b871df3f4098fc4b833bAdam Lesinski            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
448fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
449fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
450fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
451fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    /**
452ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette     * Applies the new configuration, returning a bitmask of the changes
453ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette     * between the old and new configurations.
454ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette     *
455ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette     * @param config the new configuration
456ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette     * @return bitmask of config changes
457fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     */
458ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette    public @Config int calcConfigChanges(@Nullable Configuration config) {
459ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        if (config == null) {
460ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette            // If there is no configuration, assume all flags have changed.
461ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette            return 0xFFFFFFFF;
462ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        }
463fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
464ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        mTmpConfig.setTo(config);
465ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        int density = config.densityDpi;
466ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        if (density == Configuration.DENSITY_DPI_UNDEFINED) {
467ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette            density = mMetrics.noncompatDensityDpi;
468ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        }
469fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
4708e8d23214a71d8813ebd3676b192924c530cb913Adam Lesinski        mDisplayAdjustments.getCompatibilityInfo().applyToConfiguration(density, mTmpConfig);
471ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette
472ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        if (mTmpConfig.getLocales().isEmpty()) {
473ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette            mTmpConfig.setLocales(LocaleList.getDefault());
474fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
475ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        return mConfiguration.updateFrom(mTmpConfig);
476fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
477fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
478fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    /**
479fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * {@code Locale.toLanguageTag} will transform the obsolete (and deprecated)
480fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively.
481fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     *
482fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * All released versions of android prior to "L" used the deprecated language
483fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * tags, so we will need to support them for backwards compatibility.
484fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     *
485fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * Note that this conversion needs to take place *after* the call to
486fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * {@code toLanguageTag} because that will convert all the deprecated codes to
487fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * the new ones, even if they're set manually.
488fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     */
489fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private static String adjustLanguageTag(String languageTag) {
490fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        final int separator = languageTag.indexOf('-');
491fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        final String language;
492fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        final String remainder;
493fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
494fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (separator == -1) {
495fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            language = languageTag;
496fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            remainder = "";
497fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        } else {
498fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            language = languageTag.substring(0, separator);
499fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            remainder = languageTag.substring(separator);
500fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
501fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
502fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return Locale.adjustLanguageCode(language) + remainder;
503fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
504fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
505fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    /**
506fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * Call this to remove all cached loaded layout resources from the
507fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * Resources object.  Only intended for use with performance testing
508fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * tools.
509fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     */
510fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    public void flushLayoutCache() {
511fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        synchronized (mCachedXmlBlocks) {
512fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            Arrays.fill(mCachedXmlBlockCookies, 0);
513fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            Arrays.fill(mCachedXmlBlockFiles, null);
514fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
515fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
516fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            for (int i = 0; i < XML_BLOCK_CACHE_SIZE; i++) {
517fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final XmlBlock oldBlock = cachedXmlBlocks[i];
518fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                if (oldBlock != null) {
519fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    oldBlock.close();
520fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
521fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
522fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            Arrays.fill(cachedXmlBlocks, null);
523fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
524fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
525fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
526fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    @Nullable
52750954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski    Drawable loadDrawable(@NonNull Resources wrapper, @NonNull TypedValue value, int id,
52850954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski            int density, @Nullable Resources.Theme theme)
52950954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski            throws NotFoundException {
53050954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski        // If the drawable's XML lives in our current density qualifier,
53150954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski        // it's okay to use a scaled version from the cache. Otherwise, we
53250954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski        // need to actually load the drawable from XML.
53350954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski        final boolean useCache = density == 0 || value.density == mMetrics.densityDpi;
53450954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski
53550954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski        // Pretend the requested density is actually the display density. If
53650954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski        // the drawable returned is not the requested density, then force it
53750954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski        // to be scaled later by dividing its density by the ratio of
53850954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski        // requested density to actual device density. Drawables that have
53950954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski        // undefined density or no density don't need to be handled here.
54050954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski        if (density > 0 && value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
54150954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski            if (value.density == density) {
54250954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski                value.density = mMetrics.densityDpi;
54350954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski            } else {
54450954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski                value.density = (value.density * mMetrics.densityDpi) / density;
54550954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski            }
54650954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski        }
54750954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski
548fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        try {
549fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if (TRACE_FOR_PRELOAD) {
550fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                // Log only framework resources
551fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                if ((id >>> 24) == 0x1) {
552fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    final String name = getResourceName(id);
553fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    if (name != null) {
554fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        Log.d("PreloadDrawable", name);
555fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    }
556fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
557fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
558fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
559fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            final boolean isColorDrawable;
560fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            final DrawableCache caches;
561fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            final long key;
562fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
563fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
564fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                isColorDrawable = true;
565fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                caches = mColorDrawableCache;
566fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                key = value.data;
567fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            } else {
568fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                isColorDrawable = false;
569fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                caches = mDrawableCache;
570fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                key = (((long) value.assetCookie) << 32) | value.data;
571fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
572fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
573fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // First, check whether we have a cached version of this drawable
574fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // that was inflated against the specified theme. Skip the cache if
575fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // we're currently preloading or we're not using the cache.
576fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if (!mPreloading && useCache) {
577fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final Drawable cachedDrawable = caches.getInstance(key, wrapper, theme);
578fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                if (cachedDrawable != null) {
57958857c8b2bd64272d2320f62fd860783bb671da8Alan Viverette                    cachedDrawable.setChangingConfigurations(value.changingConfigurations);
580fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    return cachedDrawable;
581fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
582fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
583fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
584fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // Next, check preloaded drawables. Preloaded drawables may contain
585fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // unresolved theme attributes.
586fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            final Drawable.ConstantState cs;
587fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if (isColorDrawable) {
588fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                cs = sPreloadedColorDrawables.get(key);
589fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            } else {
590fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);
591fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
592fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
593fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            Drawable dr;
594ee7e8f13ea2293e93ef9dd9f3f088186edd4864eztenghui            boolean needsNewDrawableAfterCache = false;
595fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if (cs != null) {
596fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                dr = cs.newDrawable(wrapper);
597fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            } else if (isColorDrawable) {
598fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                dr = new ColorDrawable(value.data);
599fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            } else {
60050954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski                dr = loadDrawableForCookie(wrapper, value, id, density, null);
601fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
602ee7e8f13ea2293e93ef9dd9f3f088186edd4864eztenghui            // DrawableContainer' constant state has drawables instances. In order to leave the
603ee7e8f13ea2293e93ef9dd9f3f088186edd4864eztenghui            // constant state intact in the cache, we need to create a new DrawableContainer after
604ee7e8f13ea2293e93ef9dd9f3f088186edd4864eztenghui            // added to cache.
605ee7e8f13ea2293e93ef9dd9f3f088186edd4864eztenghui            if (dr instanceof DrawableContainer)  {
606ee7e8f13ea2293e93ef9dd9f3f088186edd4864eztenghui                needsNewDrawableAfterCache = true;
607ee7e8f13ea2293e93ef9dd9f3f088186edd4864eztenghui            }
608fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
609fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // Determine if the drawable has unresolved theme attributes. If it
610fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // does, we'll need to apply a theme and store it in a theme-specific
611fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // cache.
612fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            final boolean canApplyTheme = dr != null && dr.canApplyTheme();
613fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if (canApplyTheme && theme != null) {
614fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                dr = dr.mutate();
615fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                dr.applyTheme(theme);
616fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                dr.clearMutated();
617fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
618fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
619fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // If we were able to obtain a drawable, store it in the appropriate
620fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // cache: preload, not themed, null theme, or theme-specific. Don't
621fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // pollute the cache with drawables loaded from a foreign density.
62258857c8b2bd64272d2320f62fd860783bb671da8Alan Viverette            if (dr != null) {
623fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                dr.setChangingConfigurations(value.changingConfigurations);
62458857c8b2bd64272d2320f62fd860783bb671da8Alan Viverette                if (useCache) {
62558857c8b2bd64272d2320f62fd860783bb671da8Alan Viverette                    cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr);
626ee7e8f13ea2293e93ef9dd9f3f088186edd4864eztenghui                    if (needsNewDrawableAfterCache) {
627ee7e8f13ea2293e93ef9dd9f3f088186edd4864eztenghui                        Drawable.ConstantState state = dr.getConstantState();
628ee7e8f13ea2293e93ef9dd9f3f088186edd4864eztenghui                        if (state != null) {
629ee7e8f13ea2293e93ef9dd9f3f088186edd4864eztenghui                            dr = state.newDrawable(wrapper);
630ee7e8f13ea2293e93ef9dd9f3f088186edd4864eztenghui                        }
631ee7e8f13ea2293e93ef9dd9f3f088186edd4864eztenghui                    }
63258857c8b2bd64272d2320f62fd860783bb671da8Alan Viverette                }
633fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
634fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
635fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return dr;
636fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        } catch (Exception e) {
637fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            String name;
638fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            try {
639fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                name = getResourceName(id);
640fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            } catch (NotFoundException e2) {
641fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                name = "(missing name)";
642fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
643fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
644fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // The target drawable might fail to load for any number of
645fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // reasons, but we always want to include the resource name.
646fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // Since the client already expects this method to throw a
647fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // NotFoundException, just throw one of those.
648fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            final NotFoundException nfe = new NotFoundException("Drawable " + name
649fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    + " with resource ID #0x" + Integer.toHexString(id), e);
650fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            nfe.setStackTrace(new StackTraceElement[0]);
651fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            throw nfe;
652fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
653fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
654fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
655fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private void cacheDrawable(TypedValue value, boolean isColorDrawable, DrawableCache caches,
656082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski            Resources.Theme theme, boolean usesTheme, long key, Drawable dr) {
657fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        final Drawable.ConstantState cs = dr.getConstantState();
658fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (cs == null) {
659fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return;
660fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
661fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
662fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (mPreloading) {
663fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            final int changingConfigs = cs.getChangingConfigurations();
664fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if (isColorDrawable) {
665fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                if (verifyPreloadConfig(changingConfigs, 0, value.resourceId, "drawable")) {
666fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    sPreloadedColorDrawables.put(key, cs);
667fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
668fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            } else {
669fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                if (verifyPreloadConfig(
670a8a66ccf1c6c042a71817d61fc159f10c21f4844Alan Viverette                        changingConfigs, ActivityInfo.CONFIG_LAYOUT_DIRECTION, value.resourceId, "drawable")) {
671a8a66ccf1c6c042a71817d61fc159f10c21f4844Alan Viverette                    if ((changingConfigs & ActivityInfo.CONFIG_LAYOUT_DIRECTION) == 0) {
672fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        // If this resource does not vary based on layout direction,
673fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        // we can put it in all of the preload maps.
674fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        sPreloadedDrawables[0].put(key, cs);
675fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        sPreloadedDrawables[1].put(key, cs);
676fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    } else {
677fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        // Otherwise, only in the layout dir we loaded it for.
678fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        sPreloadedDrawables[mConfiguration.getLayoutDirection()].put(key, cs);
679fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    }
680fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
681fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
682fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        } else {
683fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            synchronized (mAccessLock) {
684fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                caches.put(key, theme, cs, usesTheme);
685fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
686fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
687fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
688fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
689ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette    private boolean verifyPreloadConfig(@Config int changingConfigurations,
690ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette            @Config int allowVarying, @AnyRes int resourceId, @Nullable String name) {
691fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        // We allow preloading of resources even if they vary by font scale (which
692fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        // doesn't impact resource selection) or density (which we handle specially by
693fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        // simply turning off all preloading), as well as any other configs specified
694fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        // by the caller.
695fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (((changingConfigurations&~(ActivityInfo.CONFIG_FONT_SCALE |
696fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                ActivityInfo.CONFIG_DENSITY)) & ~allowVarying) != 0) {
697fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            String resName;
698fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            try {
699fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                resName = getResourceName(resourceId);
700fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            } catch (NotFoundException e) {
701fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                resName = "?";
702fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
703fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // This should never happen in production, so we should log a
704fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // warning even if we're not debugging.
705fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            Log.w(TAG, "Preloaded " + name + " resource #0x"
706fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    + Integer.toHexString(resourceId)
707fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    + " (" + resName + ") that varies with configuration!!");
708fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return false;
709fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
710fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (TRACE_FOR_PRELOAD) {
711fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            String resName;
712fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            try {
713fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                resName = getResourceName(resourceId);
714fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            } catch (NotFoundException e) {
715fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                resName = "?";
716fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
717fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            Log.w(TAG, "Preloading " + name + " resource #0x"
718fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    + Integer.toHexString(resourceId)
719fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    + " (" + resName + ")");
720fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
721fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return true;
722fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
723fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
724fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    /**
725fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * Loads a drawable from XML or resources stream.
726fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     */
72750954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski    private Drawable loadDrawableForCookie(@NonNull Resources wrapper, @NonNull TypedValue value,
72850954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski            int id, int density, @Nullable Resources.Theme theme) {
729fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (value.string == null) {
730fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
731fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    + Integer.toHexString(id) + ") is not a Drawable (color or path): " + value);
732fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
733fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
734fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        final String file = value.string.toString();
735fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
736fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (TRACE_FOR_MISS_PRELOAD) {
737fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // Log only framework resources
738fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if ((id >>> 24) == 0x1) {
739fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final String name = getResourceName(id);
740fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                if (name != null) {
741fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    Log.d(TAG, "Loading framework drawable #" + Integer.toHexString(id)
742fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                            + ": " + name + " at " + file);
743fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
744fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
745fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
746fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
747fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (DEBUG_LOAD) {
748fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            Log.v(TAG, "Loading drawable for cookie " + value.assetCookie + ": " + file);
749fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
750fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
751fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        final Drawable dr;
752fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
753fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
754fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        try {
755fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if (file.endsWith(".xml")) {
756fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final XmlResourceParser rp = loadXmlResourceParser(
757fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        file, id, value.assetCookie, "drawable");
75850954d2b4ea938d787ef5021d75f6bc02826607aAdam Lesinski                dr = Drawable.createFromXmlForDensity(wrapper, rp, density, theme);
759fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                rp.close();
760fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            } else {
761fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final InputStream is = mAssets.openNonAsset(
762fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        value.assetCookie, file, AssetManager.ACCESS_STREAMING);
763fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                dr = Drawable.createFromResourceStream(wrapper, value, is, file, null);
764fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                is.close();
765fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
766fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        } catch (Exception e) {
767fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
768fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            final NotFoundException rnf = new NotFoundException(
769fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    "File " + file + " from drawable resource ID #0x" + Integer.toHexString(id));
770fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            rnf.initCause(e);
771fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            throw rnf;
772fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
773fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
774fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
775fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return dr;
776fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
777fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
778fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    /**
77918e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri     * Loads a font from XML or resources stream.
78018e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri     */
78118e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri    @Nullable
782ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri    public Typeface loadFont(Resources wrapper, TypedValue value, int id) {
78318e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri        if (value.string == null) {
78418e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri            throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
78518e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri                    + Integer.toHexString(id) + ") is not a Font: " + value);
78618e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri        }
78718e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri
78818e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri        final String file = value.string.toString();
789b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri        Typeface cached = Typeface.findFromCache(mAssets, file);
790ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri        if (cached != null) {
791ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri            return cached;
792ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri        }
79318e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri
79418e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri        if (DEBUG_LOAD) {
79518e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri            Log.v(TAG, "Loading font for cookie " + value.assetCookie + ": " + file);
79618e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri        }
79718e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri
79818e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
79918e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri        try {
800ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri            if (file.endsWith("xml")) {
801ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri                final XmlResourceParser rp = loadXmlResourceParser(
802ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri                        file, id, value.assetCookie, "font");
803ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka                final FontResourcesParser.FamilyResourceEntry familyEntry =
804ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka                        FontResourcesParser.parse(rp, wrapper);
805ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka                if (familyEntry == null) {
806ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka                    return null;
807ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka                }
808ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka                return Typeface.createFromResources(familyEntry, mAssets, file);
80918e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri            }
810ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri            return Typeface.createFromResources(mAssets, file, value.assetCookie);
811ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri        } catch (XmlPullParserException e) {
812ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri            Log.e(TAG, "Failed to parse xml resource " + file, e);
813ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri        } catch (IOException e) {
814ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri            Log.e(TAG, "Failed to read xml resource " + file, e);
81518e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri        } finally {
81618e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
81718e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri        }
81818e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri        return null;
81918e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri    }
82018e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri
82118e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri    /**
822fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * Given the value and id, we can get the XML filename as in value.data, based on that, we
823fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * first try to load CSL from the cache. If not found, try to get from the constant state.
824fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * Last, parse the XML and generate the CSL.
825fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     */
826fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private ComplexColor loadComplexColorFromName(Resources wrapper, Resources.Theme theme,
827082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski            TypedValue value, int id) {
828fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        final long key = (((long) value.assetCookie) << 32) | value.data;
829fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        final ConfigurationBoundResourceCache<ComplexColor> cache = mComplexColorCache;
830fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        ComplexColor complexColor = cache.getInstance(key, wrapper, theme);
831fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (complexColor != null) {
832fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return complexColor;
833fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
834fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
835fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        final android.content.res.ConstantState<ComplexColor> factory =
836fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                sPreloadedComplexColors.get(key);
837fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
838fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (factory != null) {
839fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            complexColor = factory.newInstance(wrapper, theme);
840fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
841fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (complexColor == null) {
842fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            complexColor = loadComplexColorForCookie(wrapper, value, id, theme);
843fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
844fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
845fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (complexColor != null) {
8460b9295d06750dc6da032a2b2092e2c500c65393fAlan Viverette            complexColor.setBaseChangingConfigurations(value.changingConfigurations);
8470b9295d06750dc6da032a2b2092e2c500c65393fAlan Viverette
848fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if (mPreloading) {
8490b9295d06750dc6da032a2b2092e2c500c65393fAlan Viverette                if (verifyPreloadConfig(complexColor.getChangingConfigurations(),
8500b9295d06750dc6da032a2b2092e2c500c65393fAlan Viverette                        0, value.resourceId, "color")) {
851fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    sPreloadedComplexColors.put(key, complexColor.getConstantState());
852fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
853fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            } else {
854fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                cache.put(key, theme, complexColor.getConstantState());
855fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
856fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
857fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return complexColor;
858fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
859fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
860fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    @Nullable
861fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    ComplexColor loadComplexColor(Resources wrapper, @NonNull TypedValue value, int id,
862082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski            Resources.Theme theme) {
863fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (TRACE_FOR_PRELOAD) {
864fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // Log only framework resources
865fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if ((id >>> 24) == 0x1) {
866fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final String name = getResourceName(id);
867fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                if (name != null) android.util.Log.d("loadComplexColor", name);
868fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
869fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
870fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
871fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        final long key = (((long) value.assetCookie) << 32) | value.data;
872fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
873fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        // Handle inline color definitions.
874fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
875fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
876fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return getColorStateListFromInt(value, key);
877fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
878fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
879fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        final String file = value.string.toString();
880fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
881fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        ComplexColor complexColor;
882fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (file.endsWith(".xml")) {
883fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            try {
884fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                complexColor = loadComplexColorFromName(wrapper, theme, value, id);
885fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            } catch (Exception e) {
886fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final NotFoundException rnf = new NotFoundException(
887fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        "File " + file + " from complex color resource ID #0x"
888fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                                + Integer.toHexString(id));
889fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                rnf.initCause(e);
890fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                throw rnf;
891fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
892fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        } else {
893fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            throw new NotFoundException(
894fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    "File " + file + " from drawable resource ID #0x"
895fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                            + Integer.toHexString(id) + ": .xml extension required");
896fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
897fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
898fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return complexColor;
899fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
900fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
901fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    @Nullable
902fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    ColorStateList loadColorStateList(Resources wrapper, TypedValue value, int id,
903082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski            Resources.Theme theme)
904fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            throws NotFoundException {
905fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (TRACE_FOR_PRELOAD) {
906fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // Log only framework resources
907fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if ((id >>> 24) == 0x1) {
908fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final String name = getResourceName(id);
909fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                if (name != null) android.util.Log.d("PreloadColorStateList", name);
910fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
911fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
912fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
913fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        final long key = (((long) value.assetCookie) << 32) | value.data;
914fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
915fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        // Handle inline color definitions.
916fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
917fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
918fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return getColorStateListFromInt(value, key);
919fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
920fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
921fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        ComplexColor complexColor = loadComplexColorFromName(wrapper, theme, value, id);
922fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (complexColor != null && complexColor instanceof ColorStateList) {
923fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return (ColorStateList) complexColor;
924fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
925fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
926fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        throw new NotFoundException(
927fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                "Can't find ColorStateList from drawable resource ID #0x"
928fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        + Integer.toHexString(id));
929fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
930fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
931fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    @NonNull
932fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private ColorStateList getColorStateListFromInt(@NonNull TypedValue value, long key) {
933fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        ColorStateList csl;
934fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        final android.content.res.ConstantState<ComplexColor> factory =
935fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                sPreloadedComplexColors.get(key);
936fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (factory != null) {
937fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return (ColorStateList) factory.newInstance();
938fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
939fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
940fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        csl = ColorStateList.valueOf(value.data);
941fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
942fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (mPreloading) {
943fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
944fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    "color")) {
945fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                sPreloadedComplexColors.put(key, csl.getConstantState());
946fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
947fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
948fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
949fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return csl;
950fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
951fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
952fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    /**
953fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * Load a ComplexColor based on the XML file content. The result can be a GradientColor or
954fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * ColorStateList. Note that pure color will be wrapped into a ColorStateList.
955fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     *
956fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * We deferred the parser creation to this function b/c we need to differentiate b/t gradient
957fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * and selector tag.
958fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     *
959fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * @return a ComplexColor (GradientColor or ColorStateList) based on the XML file content.
960fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     */
961fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    @Nullable
962fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    private ComplexColor loadComplexColorForCookie(Resources wrapper, TypedValue value, int id,
963082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski            Resources.Theme theme) {
964fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (value.string == null) {
965fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            throw new UnsupportedOperationException(
966fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    "Can't convert to ComplexColor: type=0x" + value.type);
967fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
968fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
969fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        final String file = value.string.toString();
970fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
971fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (TRACE_FOR_MISS_PRELOAD) {
972fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            // Log only framework resources
973fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if ((id >>> 24) == 0x1) {
974fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final String name = getResourceName(id);
975fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                if (name != null) {
976fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    Log.d(TAG, "Loading framework ComplexColor #" + Integer.toHexString(id)
977fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                            + ": " + name + " at " + file);
978fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
979fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
980fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
981fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
982fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (DEBUG_LOAD) {
983fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            Log.v(TAG, "Loading ComplexColor for cookie " + value.assetCookie + ": " + file);
984fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
985fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
986fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        ComplexColor complexColor = null;
987fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
988fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
989fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (file.endsWith(".xml")) {
990fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            try {
991fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final XmlResourceParser parser = loadXmlResourceParser(
992fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        file, id, value.assetCookie, "ComplexColor");
993fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
994fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final AttributeSet attrs = Xml.asAttributeSet(parser);
995fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                int type;
996fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                while ((type = parser.next()) != XmlPullParser.START_TAG
997fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        && type != XmlPullParser.END_DOCUMENT) {
998fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    // Seek parser to start tag.
999fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
1000fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                if (type != XmlPullParser.START_TAG) {
1001fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    throw new XmlPullParserException("No start tag found");
1002fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
1003fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1004fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final String name = parser.getName();
1005fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                if (name.equals("gradient")) {
1006fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    complexColor = GradientColor.createFromXmlInner(wrapper, parser, attrs, theme);
1007fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                } else if (name.equals("selector")) {
1008fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    complexColor = ColorStateList.createFromXmlInner(wrapper, parser, attrs, theme);
1009fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
1010fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                parser.close();
1011fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            } catch (Exception e) {
1012fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
1013fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final NotFoundException rnf = new NotFoundException(
1014fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        "File " + file + " from ComplexColor resource ID #0x"
1015fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                                + Integer.toHexString(id));
1016fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                rnf.initCause(e);
1017fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                throw rnf;
1018fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
1019fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        } else {
1020fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
1021fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            throw new NotFoundException(
1022fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    "File " + file + " from drawable resource ID #0x"
1023fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                            + Integer.toHexString(id) + ": .xml extension required");
1024fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1025fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
1026fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1027fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return complexColor;
1028fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
1029fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1030fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    /**
1031fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * Loads an XML parser for the specified file.
1032fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     *
1033fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * @param file the path for the XML file to parse
1034fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * @param id the resource identifier for the file
1035fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * @param assetCookie the asset cookie for the file
1036fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * @param type the type of resource (used for logging)
1037fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * @return a parser for the specified XML file
1038fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * @throws NotFoundException if the file could not be loaded
1039fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     */
1040fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    @NonNull
1041082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski    XmlResourceParser loadXmlResourceParser(@NonNull String file, @AnyRes int id, int assetCookie,
1042082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski            @NonNull String type)
1043fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            throws NotFoundException {
1044fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (id != 0) {
1045fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            try {
1046fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                synchronized (mCachedXmlBlocks) {
1047fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    final int[] cachedXmlBlockCookies = mCachedXmlBlockCookies;
1048fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    final String[] cachedXmlBlockFiles = mCachedXmlBlockFiles;
1049fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
1050fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    // First see if this block is in our cache.
1051fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    final int num = cachedXmlBlockFiles.length;
1052fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    for (int i = 0; i < num; i++) {
1053fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        if (cachedXmlBlockCookies[i] == assetCookie && cachedXmlBlockFiles[i] != null
1054fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                                && cachedXmlBlockFiles[i].equals(file)) {
1055fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                            return cachedXmlBlocks[i].newParser();
1056fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        }
1057fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    }
1058fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1059fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    // Not in the cache, create a new block and put it at
1060fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    // the next slot in the cache.
1061fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    final XmlBlock block = mAssets.openXmlBlockAsset(assetCookie, file);
1062fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    if (block != null) {
1063fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        final int pos = (mLastCachedXmlBlockIndex + 1) % num;
1064fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        mLastCachedXmlBlockIndex = pos;
1065fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        final XmlBlock oldBlock = cachedXmlBlocks[pos];
1066fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        if (oldBlock != null) {
1067fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                            oldBlock.close();
1068fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        }
1069fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        cachedXmlBlockCookies[pos] = assetCookie;
1070fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        cachedXmlBlockFiles[pos] = file;
1071fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        cachedXmlBlocks[pos] = block;
1072fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        return block.newParser();
1073fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    }
1074fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
1075fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            } catch (Exception e) {
1076fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final NotFoundException rnf = new NotFoundException("File " + file
1077fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        + " from xml type " + type + " resource ID #0x" + Integer.toHexString(id));
1078fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                rnf.initCause(e);
1079fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                throw rnf;
1080fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
1081fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1082fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1083fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        throw new NotFoundException("File " + file + " from xml type " + type + " resource ID #0x"
1084fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                + Integer.toHexString(id));
1085fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
1086fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1087fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    /**
1088fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * Start preloading of resource data using this Resources object.  Only
1089fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * for use by the zygote process for loading common system resources.
1090fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * {@hide}
1091fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     */
1092fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    public final void startPreloading() {
1093fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        synchronized (sSync) {
1094fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            if (sPreloaded) {
1095fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                throw new IllegalStateException("Resources already preloaded");
1096fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
1097fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            sPreloaded = true;
1098fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            mPreloading = true;
1099fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            mConfiguration.densityDpi = DisplayMetrics.DENSITY_DEVICE;
1100fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            updateConfiguration(null, null, null);
1101fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1102fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
1103fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1104fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    /**
1105fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * Called by zygote when it is done preloading resources, to change back
1106fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     * to normal Resources operation.
1107fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski     */
1108fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    void finishPreloading() {
1109fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        if (mPreloading) {
1110fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            mPreloading = false;
1111fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            flushLayoutCache();
1112fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1113fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
1114fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1115fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    LongSparseArray<Drawable.ConstantState> getPreloadedDrawables() {
1116fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return sPreloadedDrawables[0];
1117fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
1118fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1119fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    ThemeImpl newThemeImpl() {
1120fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        return new ThemeImpl();
1121fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
1122fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1123082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski    /**
1124082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski     * Creates a new ThemeImpl which is already set to the given Resources.ThemeKey.
1125082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski     */
1126082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski    ThemeImpl newThemeImpl(Resources.ThemeKey key) {
1127082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski        ThemeImpl impl = new ThemeImpl();
1128082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski        impl.mKey.setTo(key);
1129082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski        impl.rebase();
1130082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski        return impl;
1131082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski    }
1132082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski
1133fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    public class ThemeImpl {
1134fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        /**
1135fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski         * Unique key for the series of styles applied to this theme.
1136fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski         */
1137fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        private final Resources.ThemeKey mKey = new Resources.ThemeKey();
1138fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1139fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        @SuppressWarnings("hiding")
1140fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        private final AssetManager mAssets;
1141fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        private final long mTheme;
1142fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1143fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        /**
1144fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski         * Resource identifier for the theme.
1145fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski         */
1146fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        private int mThemeResId = 0;
1147fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1148fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        /*package*/ ThemeImpl() {
1149fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            mAssets = ResourcesImpl.this.mAssets;
1150fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            mTheme = mAssets.createTheme();
1151fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1152fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1153fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        @Override
1154fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        protected void finalize() throws Throwable {
1155fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            super.finalize();
1156fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            mAssets.releaseTheme(mTheme);
1157fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1158fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1159fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        /*package*/ Resources.ThemeKey getKey() {
1160fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return mKey;
1161fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1162fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1163fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        /*package*/ long getNativeTheme() {
1164fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return mTheme;
1165fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1166fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1167fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        /*package*/ int getAppliedStyleResId() {
1168fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return mThemeResId;
1169fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1170fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1171fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        void applyStyle(int resId, boolean force) {
1172fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            synchronized (mKey) {
1173fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                AssetManager.applyThemeStyle(mTheme, resId, force);
1174fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1175fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                mThemeResId = resId;
1176fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                mKey.append(resId, force);
1177fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
1178fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1179fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1180fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        void setTo(ThemeImpl other) {
1181fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            synchronized (mKey) {
1182fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                synchronized (other.mKey) {
1183fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    AssetManager.copyTheme(mTheme, other.mTheme);
1184fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1185fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    mThemeResId = other.mThemeResId;
1186fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    mKey.setTo(other.getKey());
1187fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
1188fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
1189fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1190fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1191fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        @NonNull
1192fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        TypedArray obtainStyledAttributes(@NonNull Resources.Theme wrapper,
1193082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski                AttributeSet set,
1194082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski                @StyleableRes int[] attrs,
1195082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski                @AttrRes int defStyleAttr,
1196082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski                @StyleRes int defStyleRes) {
1197fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            synchronized (mKey) {
1198fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final int len = attrs.length;
1199fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
1200fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1201fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                // XXX note that for now we only work with compiled XML files.
1202fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                // To support generic XML files we will need to manually parse
1203fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                // out the attributes from the XML file (applying type information
1204fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                // contained in the resources and such).
1205fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final XmlBlock.Parser parser = (XmlBlock.Parser) set;
1206fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
1207fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        parser != null ? parser.mParseState : 0,
1208f32adf447511d54c2aa0948d3c1ef44d461538acJohn Reck                        attrs, attrs.length, array.mDataAddress, array.mIndicesAddress);
1209fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                array.mTheme = wrapper;
1210fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                array.mXml = parser;
1211fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1212fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                return array;
1213fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
1214fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1215fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1216fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        @NonNull
1217fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        TypedArray resolveAttributes(@NonNull Resources.Theme wrapper,
1218082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski                @NonNull int[] values,
1219082614c6a57a115ee0c5975e3579bf34a178c0f8Adam Lesinski                @NonNull int[] attrs) {
1220fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            synchronized (mKey) {
1221fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final int len = attrs.length;
1222fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                if (values == null || len != values.length) {
1223fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    throw new IllegalArgumentException(
1224fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                            "Base attribute values must the same length as attrs");
1225fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
1226fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1227fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
1228fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                AssetManager.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
1229fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                array.mTheme = wrapper;
1230fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                array.mXml = null;
1231fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                return array;
1232fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
1233fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1234fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1235fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        boolean resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
1236fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            synchronized (mKey) {
1237fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                return mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs);
1238fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
1239fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1240fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1241fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        int[] getAllAttributes() {
1242fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            return mAssets.getStyleAttributes(getAppliedStyleResId());
1243fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1244fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1245ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        @Config int getChangingConfigurations() {
1246fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            synchronized (mKey) {
12479ad386b37c4c4ebe1176caa8eeab131387fc93edAlan Viverette                final @NativeConfig int nativeChangingConfig =
1248fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        AssetManager.getThemeChangingConfigurations(mTheme);
1249fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig);
1250fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
1251fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1252fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1253fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        public void dump(int priority, String tag, String prefix) {
1254fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            synchronized (mKey) {
1255fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                AssetManager.dumpTheme(mTheme, priority, tag, prefix);
1256fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
1257fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1258fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1259fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        String[] getTheme() {
1260fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            synchronized (mKey) {
1261fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final int N = mKey.mCount;
1262fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                final String[] themes = new String[N * 2];
1263fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                for (int i = 0, j = N - 1; i < themes.length; i += 2, --j) {
1264fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    final int resId = mKey.mResId[j];
1265fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    final boolean forced = mKey.mForce[j];
1266fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    try {
1267fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        themes[i] = getResourceName(resId);
1268fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    } catch (NotFoundException e) {
1269fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                        themes[i] = Integer.toHexString(i);
1270fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    }
1271fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    themes[i + 1] = forced ? "forced" : "not forced";
1272fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
1273fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                return themes;
1274fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
1275fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1276fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1277fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        /**
1278fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski         * Rebases the theme against the parent Resource object's current
1279fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski         * configuration by re-applying the styles passed to
1280fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski         * {@link #applyStyle(int, boolean)}.
1281fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski         */
1282fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        void rebase() {
1283fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            synchronized (mKey) {
1284fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                AssetManager.clearTheme(mTheme);
1285fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski
1286fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                // Reapply the same styles in the same order.
1287fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                for (int i = 0; i < mKey.mCount; i++) {
1288fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    final int resId = mKey.mResId[i];
1289fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    final boolean force = mKey.mForce[i];
1290fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                    AssetManager.applyThemeStyle(mTheme, resId, force);
1291fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski                }
1292fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski            }
1293fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski        }
1294fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski    }
1295fb302ccd8e0610a09691ea5503ff8111dc7a2e41Adam Lesinski}
1296