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