blob: d36e076381ebe3b001b4293aa61ecc45edeef254 [file] [log] [blame]
Kenny Root15a4d2f2010-03-11 18:20:12 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017package android.content.res;
18
Tor Norbye7b9c9122013-05-30 16:48:33 -070019import android.annotation.AnyRes;
Tor Norbye80756e32015-03-02 09:39:27 -080020import android.annotation.ColorInt;
Alan Viverettefde4e3b2014-09-22 16:19:51 -070021import android.annotation.Nullable;
Aurimas Liutikasce7c99c2018-12-18 16:20:49 -080022import android.annotation.StyleRes;
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -070023import android.annotation.StyleableRes;
Mathew Inwood5c0d3542018-08-14 13:54:31 +010024import android.annotation.UnsupportedAppUsage;
Alan Viveretteac85f902016-03-11 15:15:51 -050025import android.content.pm.ActivityInfo;
26import android.content.pm.ActivityInfo.Config;
Clara Bayarried00bfd2017-01-20 14:58:21 +000027import android.graphics.Typeface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.graphics.drawable.Drawable;
Alan Viverette6bbb47b2015-01-05 18:12:44 -080029import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.util.AttributeSet;
31import android.util.DisplayMetrics;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.util.TypedValue;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080033
34import com.android.internal.util.XmlUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035
John Reckf32adf42016-11-23 10:39:40 -080036import dalvik.system.VMRuntime;
37
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import java.util.Arrays;
39
40/**
41 * Container for an array of values that were retrieved with
42 * {@link Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}
43 * or {@link Resources#obtainAttributes}. Be
44 * sure to call {@link #recycle} when done with them.
Alan Viverettefd274a02014-03-27 15:39:15 -070045 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046 * The indices used to retrieve values from this structure correspond to
47 * the positions of the attributes given to obtainStyledAttributes.
48 */
49public class TypedArray {
Alan Viverette52b999f2014-03-24 18:00:26 -070050
51 static TypedArray obtain(Resources res, int len) {
John Reckf32adf42016-11-23 10:39:40 -080052 TypedArray attrs = res.mTypedArrayPool.acquire();
53 if (attrs == null) {
54 attrs = new TypedArray(res);
Alan Viverette52b999f2014-03-24 18:00:26 -070055 }
56
John Reckf32adf42016-11-23 10:39:40 -080057 attrs.mRecycled = false;
58 // Reset the assets, which may have changed due to configuration changes
59 // or further resource loading.
60 attrs.mAssets = res.getAssets();
Adam Lesinskiec05bc02017-04-18 14:42:22 -070061 attrs.mMetrics = res.getDisplayMetrics();
John Reckf32adf42016-11-23 10:39:40 -080062 attrs.resize(len);
63 return attrs;
Alan Viverette52b999f2014-03-24 18:00:26 -070064 }
65
Adam Lesinskibebfcc42018-02-12 14:27:46 -080066 // STYLE_ prefixed constants are offsets within the typed data array.
Aurimas Liutikasce7c99c2018-12-18 16:20:49 -080067 // Keep this in sync with libs/androidfw/include/androidfw/AttributeResolution.h
68 static final int STYLE_NUM_ENTRIES = 7;
Adam Lesinskibebfcc42018-02-12 14:27:46 -080069 static final int STYLE_TYPE = 0;
70 static final int STYLE_DATA = 1;
71 static final int STYLE_ASSET_COOKIE = 2;
72 static final int STYLE_RESOURCE_ID = 3;
73 static final int STYLE_CHANGING_CONFIGURATIONS = 4;
74 static final int STYLE_DENSITY = 5;
Aurimas Liutikas949b05d2019-01-30 17:20:41 -080075 static final int SYTLE_SOURCE_RESOURCE_ID = 6;
Adam Lesinskibebfcc42018-02-12 14:27:46 -080076
Mathew Inwood5c0d3542018-08-14 13:54:31 +010077 @UnsupportedAppUsage
Alan Viverette8b5b25b2014-09-13 19:30:11 -070078 private final Resources mResources;
Mathew Inwood5c0d3542018-08-14 13:54:31 +010079 @UnsupportedAppUsage
Adam Lesinskiec05bc02017-04-18 14:42:22 -070080 private DisplayMetrics mMetrics;
Mathew Inwood5c0d3542018-08-14 13:54:31 +010081 @UnsupportedAppUsage
Adam Lesinskie60064a2016-07-13 12:09:24 -070082 private AssetManager mAssets;
Alan Viverette8b5b25b2014-09-13 19:30:11 -070083
Mathew Inwood5c0d3542018-08-14 13:54:31 +010084 @UnsupportedAppUsage
Alan Viverettefd274a02014-03-27 15:39:15 -070085 private boolean mRecycled;
86
Mathew Inwood5c0d3542018-08-14 13:54:31 +010087 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 /*package*/ XmlBlock.Parser mXml;
Mathew Inwood5c0d3542018-08-14 13:54:31 +010089 @UnsupportedAppUsage
Alan Viverette52b999f2014-03-24 18:00:26 -070090 /*package*/ Resources.Theme mTheme;
Aurimas Liutikasbf1c1fc2018-08-27 15:38:36 -070091 /**
92 * mData is used to hold the value/id and other metadata about each attribute.
93 *
94 * [type, data, asset cookie, resource id, changing configuration, density]
95 *
96 * type - type of this attribute, see TypedValue#TYPE_*
97 *
98 * data - can be used in various ways:
99 * a) actual value of the attribute if type is between #TYPE_FIRST_INT and #TYPE_LAST_INT
100 * 1) color represented by an integer (#TYPE_INT_COLOR_*)
101 * 2) boolean represented by an integer (#TYPE_INT_BOOLEAN)
102 * 3) integer number (#TYPE_TYPE_INT_DEC or #TYPE_INT_HEX)
103 * 4) float number where integer gets interpreted as float (#TYPE_FLOAT, #TYPE_FRACTION
104 * and #TYPE_DIMENSION)
105 * b) index into string block inside AssetManager (#TYPE_STRING)
106 * c) attribute resource id in the current theme/style (#TYPE_ATTRIBUTE)
107 *
108 * asset cookie - used in two ways:
109 * a) for strings, drawables, and fonts it specifies the set of apk assets to look at
110 * (multi-apk case)
111 * b) cookie + asset as a unique identifier for drawable caches
112 *
113 * resource id - id that was finally used to resolve this attribute
114 *
115 * changing configuration - a mask of the configuration parameters for which the values in this
116 * attribute may change
117 *
118 * density - density of drawable pointed to by this attribute
119 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100120 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 /*package*/ int[] mData;
Aurimas Liutikasbf1c1fc2018-08-27 15:38:36 -0700122 /**
123 * Pointer to the start of the memory address of mData. It is passed via JNI and used to write
124 * to mData array directly from native code (AttributeResolution.cpp).
125 */
John Reckf32adf42016-11-23 10:39:40 -0800126 /*package*/ long mDataAddress;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100127 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 /*package*/ int[] mIndices;
Aurimas Liutikasbf1c1fc2018-08-27 15:38:36 -0700129 /**
130 * Similar to mDataAddress, but instead it is a pointer to mIndices address.
131 */
John Reckf32adf42016-11-23 10:39:40 -0800132 /*package*/ long mIndicesAddress;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100133 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 /*package*/ int mLength;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100135 @UnsupportedAppUsage
Xavier Ducrohet7f9f99ea2011-08-11 10:16:17 -0700136 /*package*/ TypedValue mValue = new TypedValue();
Alan Viverette8eea3ea2014-02-03 18:40:20 -0800137
John Reckf32adf42016-11-23 10:39:40 -0800138 private void resize(int len) {
139 mLength = len;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800140 final int dataLen = len * STYLE_NUM_ENTRIES;
John Reckf32adf42016-11-23 10:39:40 -0800141 final int indicesLen = len + 1;
142 final VMRuntime runtime = VMRuntime.getRuntime();
John Reckabd917d2017-01-04 19:04:25 -0800143 if (mDataAddress == 0 || mData.length < dataLen) {
John Reckf32adf42016-11-23 10:39:40 -0800144 mData = (int[]) runtime.newNonMovableArray(int.class, dataLen);
145 mDataAddress = runtime.addressOf(mData);
146 mIndices = (int[]) runtime.newNonMovableArray(int.class, indicesLen);
147 mIndicesAddress = runtime.addressOf(mIndices);
148 }
149 }
150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800152 * Returns the number of values in this array.
153 *
154 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 */
156 public int length() {
Alan Viverettefd274a02014-03-27 15:39:15 -0700157 if (mRecycled) {
158 throw new RuntimeException("Cannot make calls to a recycled instance!");
159 }
160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 return mLength;
162 }
Alan Viverettefd274a02014-03-27 15:39:15 -0700163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 /**
Adam Lesinski32e75012017-05-09 15:25:37 -0700165 * Returns the number of indices in the array that actually have data. Attributes with a value
166 * of @empty are included, as this is an explicit indicator.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800167 *
168 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 */
170 public int getIndexCount() {
Alan Viverettefd274a02014-03-27 15:39:15 -0700171 if (mRecycled) {
172 throw new RuntimeException("Cannot make calls to a recycled instance!");
173 }
174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 return mIndices[0];
176 }
Alan Viverettefd274a02014-03-27 15:39:15 -0700177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 /**
Adam Lesinski32e75012017-05-09 15:25:37 -0700179 * Returns an index in the array that has data. Attributes with a value of @empty are included,
180 * as this is an explicit indicator.
Alan Viverettefd274a02014-03-27 15:39:15 -0700181 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 * @param at The index you would like to returned, ranging from 0 to
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800183 * {@link #getIndexCount()}.
Alan Viverettefd274a02014-03-27 15:39:15 -0700184 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 * @return The index at the given offset, which can be used with
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800186 * {@link #getValue} and related APIs.
187 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 */
189 public int getIndex(int at) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700190 if (mRecycled) {
191 throw new RuntimeException("Cannot make calls to a recycled instance!");
192 }
193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 return mIndices[1+at];
195 }
Alan Viverettefd274a02014-03-27 15:39:15 -0700196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800198 * Returns the Resources object this array was loaded from.
199 *
200 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 */
202 public Resources getResources() {
Alan Viverettefd274a02014-03-27 15:39:15 -0700203 if (mRecycled) {
204 throw new RuntimeException("Cannot make calls to a recycled instance!");
205 }
206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 return mResources;
208 }
Alan Viverettefd274a02014-03-27 15:39:15 -0700209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800211 * Retrieves the styled string value for the attribute at <var>index</var>.
212 * <p>
213 * If the attribute is not a string, this method will attempt to coerce
214 * it to a string.
Alan Viverettefd274a02014-03-27 15:39:15 -0700215 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 * @param index Index of attribute to retrieve.
Alan Viverettefd274a02014-03-27 15:39:15 -0700217 *
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800218 * @return CharSequence holding string data. May be styled. Returns
219 * {@code null} if the attribute is not defined or could not be
220 * coerced to a string.
221 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700223 public CharSequence getText(@StyleableRes int index) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700224 if (mRecycled) {
225 throw new RuntimeException("Cannot make calls to a recycled instance!");
226 }
227
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800228 index *= STYLE_NUM_ENTRIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800230 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 if (type == TypedValue.TYPE_NULL) {
232 return null;
233 } else if (type == TypedValue.TYPE_STRING) {
234 return loadStringValueAt(index);
235 }
236
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800237 final TypedValue v = mValue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 if (getValueAt(index, v)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 return v.coerceToString();
240 }
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800241
242 // We already checked for TYPE_NULL. This should never happen.
243 throw new RuntimeException("getText of bad type: 0x" + Integer.toHexString(type));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 }
245
246 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800247 * Retrieves the string value for the attribute at <var>index</var>.
248 * <p>
249 * If the attribute is not a string, this method will attempt to coerce
250 * it to a string.
Alan Viverettefd274a02014-03-27 15:39:15 -0700251 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 * @param index Index of attribute to retrieve.
Alan Viverettefd274a02014-03-27 15:39:15 -0700253 *
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800254 * @return String holding string data. Any styling information is removed.
255 * Returns {@code null} if the attribute is not defined or could
256 * not be coerced to a string.
257 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 */
Alan Viverettea6f354b2015-05-18 15:26:57 -0700259 @Nullable
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700260 public String getString(@StyleableRes int index) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700261 if (mRecycled) {
262 throw new RuntimeException("Cannot make calls to a recycled instance!");
263 }
264
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800265 index *= STYLE_NUM_ENTRIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800267 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 if (type == TypedValue.TYPE_NULL) {
269 return null;
270 } else if (type == TypedValue.TYPE_STRING) {
271 return loadStringValueAt(index).toString();
272 }
273
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800274 final TypedValue v = mValue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 if (getValueAt(index, v)) {
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800276 final CharSequence cs = v.coerceToString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 return cs != null ? cs.toString() : null;
278 }
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800279
280 // We already checked for TYPE_NULL. This should never happen.
281 throw new RuntimeException("getString of bad type: 0x" + Integer.toHexString(type));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 }
283
284 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800285 * Retrieves the string value for the attribute at <var>index</var>, but
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 * only if that string comes from an immediate value in an XML file. That
287 * is, this does not allow references to string resources, string
288 * attributes, or conversions from other types. As such, this method
289 * will only return strings for TypedArray objects that come from
290 * attributes in an XML file.
Alan Viverettefd274a02014-03-27 15:39:15 -0700291 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 * @param index Index of attribute to retrieve.
Alan Viverettefd274a02014-03-27 15:39:15 -0700293 *
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800294 * @return String holding string data. Any styling information is removed.
295 * Returns {@code null} if the attribute is not defined or is not
296 * an immediate string value.
297 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700299 public String getNonResourceString(@StyleableRes int index) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700300 if (mRecycled) {
301 throw new RuntimeException("Cannot make calls to a recycled instance!");
302 }
303
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800304 index *= STYLE_NUM_ENTRIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800306 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 if (type == TypedValue.TYPE_STRING) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800308 final int cookie = data[index + STYLE_ASSET_COOKIE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800309 if (cookie < 0) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800310 return mXml.getPooledString(data[index + STYLE_DATA]).toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 }
312 }
313 return null;
314 }
Alan Viverettefd274a02014-03-27 15:39:15 -0700315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800317 * Retrieves the string value for the attribute at <var>index</var> that is
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800318 * not allowed to change with the given configurations.
Alan Viverettefd274a02014-03-27 15:39:15 -0700319 *
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800320 * @param index Index of attribute to retrieve.
321 * @param allowedChangingConfigs Bit mask of configurations from
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800322 * {@link Configuration}.NATIVE_CONFIG_* that are allowed to change.
Dianne Hackborn1d0b1772013-09-06 14:02:54 -0700323 *
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800324 * @return String holding string data. Any styling information is removed.
325 * Returns {@code null} if the attribute is not defined.
326 * @throws RuntimeException if the TypedArray has already been recycled.
327 * @hide
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800328 */
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100329 @UnsupportedAppUsage
Alan Viveretteac85f902016-03-11 15:15:51 -0500330 public String getNonConfigurationString(@StyleableRes int index,
331 @Config int allowedChangingConfigs) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700332 if (mRecycled) {
333 throw new RuntimeException("Cannot make calls to a recycled instance!");
334 }
335
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800336 index *= STYLE_NUM_ENTRIES;
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800337 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800338 final int type = data[index + STYLE_TYPE];
Alan Viveretteac85f902016-03-11 15:15:51 -0500339 final @Config int changingConfigs = ActivityInfo.activityInfoConfigNativeToJava(
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800340 data[index + STYLE_CHANGING_CONFIGURATIONS]);
Alan Viveretteac85f902016-03-11 15:15:51 -0500341 if ((changingConfigs & ~allowedChangingConfigs) != 0) {
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800342 return null;
343 }
344 if (type == TypedValue.TYPE_NULL) {
345 return null;
346 } else if (type == TypedValue.TYPE_STRING) {
347 return loadStringValueAt(index).toString();
348 }
349
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800350 final TypedValue v = mValue;
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800351 if (getValueAt(index, v)) {
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800352 final CharSequence cs = v.coerceToString();
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800353 return cs != null ? cs.toString() : null;
354 }
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800355
356 // We already checked for TYPE_NULL. This should never happen.
357 throw new RuntimeException("getNonConfigurationString of bad type: 0x"
358 + Integer.toHexString(type));
Dianne Hackborncf244ad2010-03-09 15:00:30 -0800359 }
360
361 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 * Retrieve the boolean value for the attribute at <var>index</var>.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800363 * <p>
364 * If the attribute is an integer value, this method will return whether
365 * it is equal to zero. If the attribute is not a boolean or integer value,
366 * this method will attempt to coerce it to an integer using
367 * {@link Integer#decode(String)} and return whether it is equal to zero.
Alan Viverettefd274a02014-03-27 15:39:15 -0700368 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 * @param index Index of attribute to retrieve.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800370 * @param defValue Value to return if the attribute is not defined or
371 * cannot be coerced to an integer.
Alan Viverettefd274a02014-03-27 15:39:15 -0700372 *
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800373 * @return Boolean value of the attribute, or defValue if the attribute was
374 * not defined or could not be coerced to an integer.
375 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700377 public boolean getBoolean(@StyleableRes int index, boolean defValue) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700378 if (mRecycled) {
379 throw new RuntimeException("Cannot make calls to a recycled instance!");
380 }
381
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800382 index *= STYLE_NUM_ENTRIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800384 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 if (type == TypedValue.TYPE_NULL) {
386 return defValue;
387 } else if (type >= TypedValue.TYPE_FIRST_INT
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800388 && type <= TypedValue.TYPE_LAST_INT) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800389 return data[index + STYLE_DATA] != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 }
391
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800392 final TypedValue v = mValue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393 if (getValueAt(index, v)) {
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800394 StrictMode.noteResourceMismatch(v);
395 return XmlUtils.convertValueToBoolean(v.coerceToString(), defValue);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 }
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800397
398 // We already checked for TYPE_NULL. This should never happen.
399 throw new RuntimeException("getBoolean of bad type: 0x" + Integer.toHexString(type));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 }
401
402 /**
403 * Retrieve the integer value for the attribute at <var>index</var>.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800404 * <p>
405 * If the attribute is not an integer, this method will attempt to coerce
406 * it to an integer using {@link Integer#decode(String)}.
Alan Viverettefd274a02014-03-27 15:39:15 -0700407 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 * @param index Index of attribute to retrieve.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800409 * @param defValue Value to return if the attribute is not defined or
410 * cannot be coerced to an integer.
Alan Viverettefd274a02014-03-27 15:39:15 -0700411 *
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800412 * @return Integer value of the attribute, or defValue if the attribute was
413 * not defined or could not be coerced to an integer.
414 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700416 public int getInt(@StyleableRes int index, int defValue) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700417 if (mRecycled) {
418 throw new RuntimeException("Cannot make calls to a recycled instance!");
419 }
420
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800421 index *= STYLE_NUM_ENTRIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800423 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800424 if (type == TypedValue.TYPE_NULL) {
425 return defValue;
426 } else if (type >= TypedValue.TYPE_FIRST_INT
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800427 && type <= TypedValue.TYPE_LAST_INT) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800428 return data[index + STYLE_DATA];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 }
430
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800431 final TypedValue v = mValue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 if (getValueAt(index, v)) {
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800433 StrictMode.noteResourceMismatch(v);
434 return XmlUtils.convertValueToInt(v.coerceToString(), defValue);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 }
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800436
437 // We already checked for TYPE_NULL. This should never happen.
438 throw new RuntimeException("getInt of bad type: 0x" + Integer.toHexString(type));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 }
440
441 /**
442 * Retrieve the float value for the attribute at <var>index</var>.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800443 * <p>
444 * If the attribute is not a float or an integer, this method will attempt
445 * to coerce it to a float using {@link Float#parseFloat(String)}.
Alan Viverettefd274a02014-03-27 15:39:15 -0700446 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 * @param index Index of attribute to retrieve.
Alan Viverettefd274a02014-03-27 15:39:15 -0700448 *
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800449 * @return Attribute float value, or defValue if the attribute was
450 * not defined or could not be coerced to a float.
451 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700453 public float getFloat(@StyleableRes int index, float defValue) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700454 if (mRecycled) {
455 throw new RuntimeException("Cannot make calls to a recycled instance!");
456 }
457
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800458 index *= STYLE_NUM_ENTRIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800460 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 if (type == TypedValue.TYPE_NULL) {
462 return defValue;
463 } else if (type == TypedValue.TYPE_FLOAT) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800464 return Float.intBitsToFloat(data[index + STYLE_DATA]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465 } else if (type >= TypedValue.TYPE_FIRST_INT
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800466 && type <= TypedValue.TYPE_LAST_INT) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800467 return data[index + STYLE_DATA];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 }
469
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800470 final TypedValue v = mValue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800471 if (getValueAt(index, v)) {
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800472 final CharSequence str = v.coerceToString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 if (str != null) {
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800474 StrictMode.noteResourceMismatch(v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 return Float.parseFloat(str.toString());
476 }
477 }
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800478
479 // We already checked for TYPE_NULL. This should never happen.
480 throw new RuntimeException("getFloat of bad type: 0x" + Integer.toHexString(type));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 }
Alan Viverettefd274a02014-03-27 15:39:15 -0700482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483 /**
484 * Retrieve the color value for the attribute at <var>index</var>. If
485 * the attribute references a color resource holding a complex
486 * {@link android.content.res.ColorStateList}, then the default color from
487 * the set is returned.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800488 * <p>
489 * This method will throw an exception if the attribute is defined but is
490 * not an integer color or color state list.
Alan Viverettefd274a02014-03-27 15:39:15 -0700491 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492 * @param index Index of attribute to retrieve.
493 * @param defValue Value to return if the attribute is not defined or
494 * not a resource.
Alan Viverettefd274a02014-03-27 15:39:15 -0700495 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496 * @return Attribute color value, or defValue if not defined.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800497 * @throws RuntimeException if the TypedArray has already been recycled.
498 * @throws UnsupportedOperationException if the attribute is defined but is
499 * not an integer color or color state list.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 */
Tor Norbye80756e32015-03-02 09:39:27 -0800501 @ColorInt
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700502 public int getColor(@StyleableRes int index, @ColorInt int defValue) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700503 if (mRecycled) {
504 throw new RuntimeException("Cannot make calls to a recycled instance!");
505 }
506
Alan Viverette5b90e822016-02-24 09:06:47 -0500507 final int attrIndex = index;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800508 index *= STYLE_NUM_ENTRIES;
Alan Viverette5b90e822016-02-24 09:06:47 -0500509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800511 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 if (type == TypedValue.TYPE_NULL) {
513 return defValue;
514 } else if (type >= TypedValue.TYPE_FIRST_INT
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800515 && type <= TypedValue.TYPE_LAST_INT) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800516 return data[index + STYLE_DATA];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517 } else if (type == TypedValue.TYPE_STRING) {
518 final TypedValue value = mValue;
519 if (getValueAt(index, value)) {
Alan Viverette45c4bbb2015-01-05 14:59:19 -0800520 final ColorStateList csl = mResources.loadColorStateList(
521 value, value.resourceId, mTheme);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522 return csl.getDefaultColor();
523 }
524 return defValue;
Alan Viverette216d3e62014-07-29 10:35:42 -0700525 } else if (type == TypedValue.TYPE_ATTRIBUTE) {
Alan Viverette93795052015-03-09 15:32:50 -0700526 final TypedValue value = mValue;
Alan Viverette5b90e822016-02-24 09:06:47 -0500527 getValueAt(index, value);
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800528 throw new UnsupportedOperationException(
Alan Viverette5b90e822016-02-24 09:06:47 -0500529 "Failed to resolve attribute at index " + attrIndex + ": " + value);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 }
531
Alan Viverette5b90e822016-02-24 09:06:47 -0500532 throw new UnsupportedOperationException("Can't convert value at index " + attrIndex
533 + " to color: type=0x" + Integer.toHexString(type));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 }
535
536 /**
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800537 * Retrieve the ComplexColor for the attribute at <var>index</var>.
538 * The value may be either a {@link android.content.res.ColorStateList} which can wrap a simple
539 * color value or a {@link android.content.res.GradientColor}
540 * <p>
541 * This method will return {@code null} if the attribute is not defined or
542 * is not an integer color, color state list or GradientColor.
543 *
544 * @param index Index of attribute to retrieve.
545 *
546 * @return ComplexColor for the attribute, or {@code null} if not defined.
547 * @throws RuntimeException if the attribute if the TypedArray has already
548 * been recycled.
549 * @throws UnsupportedOperationException if the attribute is defined but is
550 * not an integer color, color state list or GradientColor.
Teng-Hui Zhue03c4692016-03-17 10:38:43 -0700551 * @hide
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800552 */
553 @Nullable
554 public ComplexColor getComplexColor(@StyleableRes int index) {
555 if (mRecycled) {
556 throw new RuntimeException("Cannot make calls to a recycled instance!");
557 }
558
559 final TypedValue value = mValue;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800560 if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800561 if (value.type == TypedValue.TYPE_ATTRIBUTE) {
562 throw new UnsupportedOperationException(
563 "Failed to resolve attribute at index " + index + ": " + value);
564 }
565 return mResources.loadComplexColor(value, value.resourceId, mTheme);
566 }
567 return null;
568 }
569
570 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 * Retrieve the ColorStateList for the attribute at <var>index</var>.
572 * The value may be either a single solid color or a reference to
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800573 * a color or complex {@link android.content.res.ColorStateList}
574 * description.
575 * <p>
576 * This method will return {@code null} if the attribute is not defined or
577 * is not an integer color or color state list.
Alan Viverettefd274a02014-03-27 15:39:15 -0700578 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800579 * @param index Index of attribute to retrieve.
Alan Viverettefd274a02014-03-27 15:39:15 -0700580 *
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800581 * @return ColorStateList for the attribute, or {@code null} if not
582 * defined.
583 * @throws RuntimeException if the attribute if the TypedArray has already
584 * been recycled.
585 * @throws UnsupportedOperationException if the attribute is defined but is
586 * not an integer color or color state list.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 */
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800588 @Nullable
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700589 public ColorStateList getColorStateList(@StyleableRes int index) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700590 if (mRecycled) {
591 throw new RuntimeException("Cannot make calls to a recycled instance!");
592 }
593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 final TypedValue value = mValue;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800595 if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
Alan Viverette216d3e62014-07-29 10:35:42 -0700596 if (value.type == TypedValue.TYPE_ATTRIBUTE) {
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800597 throw new UnsupportedOperationException(
Alan Viverette93795052015-03-09 15:32:50 -0700598 "Failed to resolve attribute at index " + index + ": " + value);
Alan Viverette216d3e62014-07-29 10:35:42 -0700599 }
Alan Viverette45c4bbb2015-01-05 14:59:19 -0800600 return mResources.loadColorStateList(value, value.resourceId, mTheme);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 }
602 return null;
603 }
604
605 /**
606 * Retrieve the integer value for the attribute at <var>index</var>.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800607 * <p>
608 * Unlike {@link #getInt(int, int)}, this method will throw an exception if
609 * the attribute is defined but is not an integer.
Alan Viverettefd274a02014-03-27 15:39:15 -0700610 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800611 * @param index Index of attribute to retrieve.
612 * @param defValue Value to return if the attribute is not defined or
613 * not a resource.
Alan Viverettefd274a02014-03-27 15:39:15 -0700614 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615 * @return Attribute integer value, or defValue if not defined.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800616 * @throws RuntimeException if the TypedArray has already been recycled.
617 * @throws UnsupportedOperationException if the attribute is defined but is
618 * not an integer.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700620 public int getInteger(@StyleableRes int index, int defValue) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700621 if (mRecycled) {
622 throw new RuntimeException("Cannot make calls to a recycled instance!");
623 }
624
Alan Viverette5b90e822016-02-24 09:06:47 -0500625 final int attrIndex = index;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800626 index *= STYLE_NUM_ENTRIES;
Alan Viverette5b90e822016-02-24 09:06:47 -0500627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800629 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630 if (type == TypedValue.TYPE_NULL) {
631 return defValue;
632 } else if (type >= TypedValue.TYPE_FIRST_INT
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800633 && type <= TypedValue.TYPE_LAST_INT) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800634 return data[index + STYLE_DATA];
Alan Viverette216d3e62014-07-29 10:35:42 -0700635 } else if (type == TypedValue.TYPE_ATTRIBUTE) {
Alan Viverette93795052015-03-09 15:32:50 -0700636 final TypedValue value = mValue;
Alan Viverette5b90e822016-02-24 09:06:47 -0500637 getValueAt(index, value);
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800638 throw new UnsupportedOperationException(
Alan Viverette5b90e822016-02-24 09:06:47 -0500639 "Failed to resolve attribute at index " + attrIndex + ": " + value);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640 }
641
Alan Viverette5b90e822016-02-24 09:06:47 -0500642 throw new UnsupportedOperationException("Can't convert value at index " + attrIndex
643 + " to integer: type=0x" + Integer.toHexString(type));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644 }
645
646 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800647 * Retrieve a dimensional unit attribute at <var>index</var>. Unit
Alan Viverettefd274a02014-03-27 15:39:15 -0700648 * conversions are based on the current {@link DisplayMetrics}
649 * associated with the resources this {@link TypedArray} object
650 * came from.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800651 * <p>
652 * This method will throw an exception if the attribute is defined but is
653 * not a dimension.
Alan Viverettefd274a02014-03-27 15:39:15 -0700654 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800655 * @param index Index of attribute to retrieve.
656 * @param defValue Value to return if the attribute is not defined or
657 * not a resource.
Alan Viverettefd274a02014-03-27 15:39:15 -0700658 *
659 * @return Attribute dimension value multiplied by the appropriate
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800660 * metric, or defValue if not defined.
661 * @throws RuntimeException if the TypedArray has already been recycled.
662 * @throws UnsupportedOperationException if the attribute is defined but is
663 * not an integer.
Alan Viverettefd274a02014-03-27 15:39:15 -0700664 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665 * @see #getDimensionPixelOffset
666 * @see #getDimensionPixelSize
667 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700668 public float getDimension(@StyleableRes int index, float defValue) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700669 if (mRecycled) {
670 throw new RuntimeException("Cannot make calls to a recycled instance!");
671 }
672
Alan Viverette5b90e822016-02-24 09:06:47 -0500673 final int attrIndex = index;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800674 index *= STYLE_NUM_ENTRIES;
Alan Viverette5b90e822016-02-24 09:06:47 -0500675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800677 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 if (type == TypedValue.TYPE_NULL) {
679 return defValue;
680 } else if (type == TypedValue.TYPE_DIMENSION) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800681 return TypedValue.complexToDimension(data[index + STYLE_DATA], mMetrics);
Alan Viverette216d3e62014-07-29 10:35:42 -0700682 } else if (type == TypedValue.TYPE_ATTRIBUTE) {
Alan Viverette93795052015-03-09 15:32:50 -0700683 final TypedValue value = mValue;
Alan Viverette5b90e822016-02-24 09:06:47 -0500684 getValueAt(index, value);
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800685 throw new UnsupportedOperationException(
Alan Viverette5b90e822016-02-24 09:06:47 -0500686 "Failed to resolve attribute at index " + attrIndex + ": " + value);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800687 }
688
Alan Viverette5b90e822016-02-24 09:06:47 -0500689 throw new UnsupportedOperationException("Can't convert value at index " + attrIndex
690 + " to dimension: type=0x" + Integer.toHexString(type));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 }
692
693 /**
694 * Retrieve a dimensional unit attribute at <var>index</var> for use
695 * as an offset in raw pixels. This is the same as
696 * {@link #getDimension}, except the returned value is converted to
697 * integer pixels for you. An offset conversion involves simply
698 * truncating the base value to an integer.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800699 * <p>
700 * This method will throw an exception if the attribute is defined but is
701 * not a dimension.
Alan Viverettefd274a02014-03-27 15:39:15 -0700702 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703 * @param index Index of attribute to retrieve.
704 * @param defValue Value to return if the attribute is not defined or
705 * not a resource.
Alan Viverettefd274a02014-03-27 15:39:15 -0700706 *
707 * @return Attribute dimension value multiplied by the appropriate
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800708 * metric and truncated to integer pixels, or defValue if not defined.
709 * @throws RuntimeException if the TypedArray has already been recycled.
710 * @throws UnsupportedOperationException if the attribute is defined but is
711 * not an integer.
Alan Viverettefd274a02014-03-27 15:39:15 -0700712 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713 * @see #getDimension
714 * @see #getDimensionPixelSize
715 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700716 public int getDimensionPixelOffset(@StyleableRes int index, int defValue) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700717 if (mRecycled) {
718 throw new RuntimeException("Cannot make calls to a recycled instance!");
719 }
720
Alan Viverette5b90e822016-02-24 09:06:47 -0500721 final int attrIndex = index;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800722 index *= STYLE_NUM_ENTRIES;
Alan Viverette5b90e822016-02-24 09:06:47 -0500723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800724 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800725 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 if (type == TypedValue.TYPE_NULL) {
727 return defValue;
728 } else if (type == TypedValue.TYPE_DIMENSION) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800729 return TypedValue.complexToDimensionPixelOffset(data[index + STYLE_DATA], mMetrics);
Alan Viverette216d3e62014-07-29 10:35:42 -0700730 } else if (type == TypedValue.TYPE_ATTRIBUTE) {
Alan Viverette93795052015-03-09 15:32:50 -0700731 final TypedValue value = mValue;
Alan Viverette5b90e822016-02-24 09:06:47 -0500732 getValueAt(index, value);
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800733 throw new UnsupportedOperationException(
Alan Viverette5b90e822016-02-24 09:06:47 -0500734 "Failed to resolve attribute at index " + attrIndex + ": " + value);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 }
736
Alan Viverette5b90e822016-02-24 09:06:47 -0500737 throw new UnsupportedOperationException("Can't convert value at index " + attrIndex
738 + " to dimension: type=0x" + Integer.toHexString(type));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800739 }
740
741 /**
742 * Retrieve a dimensional unit attribute at <var>index</var> for use
743 * as a size in raw pixels. This is the same as
744 * {@link #getDimension}, except the returned value is converted to
745 * integer pixels for use as a size. A size conversion involves
746 * rounding the base value, and ensuring that a non-zero base value
747 * is at least one pixel in size.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800748 * <p>
749 * This method will throw an exception if the attribute is defined but is
750 * not a dimension.
Alan Viverettefd274a02014-03-27 15:39:15 -0700751 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 * @param index Index of attribute to retrieve.
753 * @param defValue Value to return if the attribute is not defined or
754 * not a resource.
Alan Viverettefd274a02014-03-27 15:39:15 -0700755 *
756 * @return Attribute dimension value multiplied by the appropriate
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800757 * metric and truncated to integer pixels, or defValue if not defined.
758 * @throws RuntimeException if the TypedArray has already been recycled.
759 * @throws UnsupportedOperationException if the attribute is defined but is
760 * not a dimension.
Alan Viverettefd274a02014-03-27 15:39:15 -0700761 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 * @see #getDimension
763 * @see #getDimensionPixelOffset
764 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700765 public int getDimensionPixelSize(@StyleableRes int index, int defValue) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700766 if (mRecycled) {
767 throw new RuntimeException("Cannot make calls to a recycled instance!");
768 }
769
Alan Viverette5b90e822016-02-24 09:06:47 -0500770 final int attrIndex = index;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800771 index *= STYLE_NUM_ENTRIES;
Alan Viverette5b90e822016-02-24 09:06:47 -0500772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800774 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775 if (type == TypedValue.TYPE_NULL) {
776 return defValue;
777 } else if (type == TypedValue.TYPE_DIMENSION) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800778 return TypedValue.complexToDimensionPixelSize(data[index + STYLE_DATA], mMetrics);
Alan Viverette216d3e62014-07-29 10:35:42 -0700779 } else if (type == TypedValue.TYPE_ATTRIBUTE) {
Alan Viverette93795052015-03-09 15:32:50 -0700780 final TypedValue value = mValue;
Alan Viverette5b90e822016-02-24 09:06:47 -0500781 getValueAt(index, value);
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800782 throw new UnsupportedOperationException(
Alan Viverette5b90e822016-02-24 09:06:47 -0500783 "Failed to resolve attribute at index " + attrIndex + ": " + value);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 }
785
Alan Viverette5b90e822016-02-24 09:06:47 -0500786 throw new UnsupportedOperationException("Can't convert value at index " + attrIndex
787 + " to dimension: type=0x" + Integer.toHexString(type));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 }
789
790 /**
791 * Special version of {@link #getDimensionPixelSize} for retrieving
792 * {@link android.view.ViewGroup}'s layout_width and layout_height
793 * attributes. This is only here for performance reasons; applications
794 * should use {@link #getDimensionPixelSize}.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800795 * <p>
796 * This method will throw an exception if the attribute is defined but is
797 * not a dimension or integer (enum).
Alan Viverettefd274a02014-03-27 15:39:15 -0700798 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799 * @param index Index of the attribute to retrieve.
800 * @param name Textual name of attribute for error reporting.
Alan Viverettefd274a02014-03-27 15:39:15 -0700801 *
802 * @return Attribute dimension value multiplied by the appropriate
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800803 * metric and truncated to integer pixels.
804 * @throws RuntimeException if the TypedArray has already been recycled.
805 * @throws UnsupportedOperationException if the attribute is defined but is
806 * not a dimension or integer (enum).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700808 public int getLayoutDimension(@StyleableRes int index, String name) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700809 if (mRecycled) {
810 throw new RuntimeException("Cannot make calls to a recycled instance!");
811 }
812
Alan Viverette5b90e822016-02-24 09:06:47 -0500813 final int attrIndex = index;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800814 index *= STYLE_NUM_ENTRIES;
Alan Viverette5b90e822016-02-24 09:06:47 -0500815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800817 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800818 if (type >= TypedValue.TYPE_FIRST_INT
819 && type <= TypedValue.TYPE_LAST_INT) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800820 return data[index + STYLE_DATA];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800821 } else if (type == TypedValue.TYPE_DIMENSION) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800822 return TypedValue.complexToDimensionPixelSize(data[index + STYLE_DATA], mMetrics);
Alan Viverette216d3e62014-07-29 10:35:42 -0700823 } else if (type == TypedValue.TYPE_ATTRIBUTE) {
Alan Viverette93795052015-03-09 15:32:50 -0700824 final TypedValue value = mValue;
Alan Viverette5b90e822016-02-24 09:06:47 -0500825 getValueAt(index, value);
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800826 throw new UnsupportedOperationException(
Alan Viverette5b90e822016-02-24 09:06:47 -0500827 "Failed to resolve attribute at index " + attrIndex + ": " + value);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828 }
829
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800830 throw new UnsupportedOperationException(getPositionDescription()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 + ": You must supply a " + name + " attribute.");
832 }
Alan Viverettefd274a02014-03-27 15:39:15 -0700833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 /**
835 * Special version of {@link #getDimensionPixelSize} for retrieving
836 * {@link android.view.ViewGroup}'s layout_width and layout_height
837 * attributes. This is only here for performance reasons; applications
838 * should use {@link #getDimensionPixelSize}.
Alan Viverettefd274a02014-03-27 15:39:15 -0700839 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 * @param index Index of the attribute to retrieve.
841 * @param defValue The default value to return if this attribute is not
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800842 * default or contains the wrong type of data.
Alan Viverettefd274a02014-03-27 15:39:15 -0700843 *
844 * @return Attribute dimension value multiplied by the appropriate
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800845 * metric and truncated to integer pixels.
846 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800847 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700848 public int getLayoutDimension(@StyleableRes int index, int defValue) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700849 if (mRecycled) {
850 throw new RuntimeException("Cannot make calls to a recycled instance!");
851 }
852
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800853 index *= STYLE_NUM_ENTRIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800854 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800855 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 if (type >= TypedValue.TYPE_FIRST_INT
857 && type <= TypedValue.TYPE_LAST_INT) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800858 return data[index + STYLE_DATA];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859 } else if (type == TypedValue.TYPE_DIMENSION) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800860 return TypedValue.complexToDimensionPixelSize(data[index + STYLE_DATA], mMetrics);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800861 }
862
863 return defValue;
864 }
865
866 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800867 * Retrieves a fractional unit attribute at <var>index</var>.
Alan Viverettefd274a02014-03-27 15:39:15 -0700868 *
869 * @param index Index of attribute to retrieve.
870 * @param base The base value of this fraction. In other words, a
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800871 * standard fraction is multiplied by this value.
Alan Viverettefd274a02014-03-27 15:39:15 -0700872 * @param pbase The parent base value of this fraction. In other
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 * words, a parent fraction (nn%p) is multiplied by this
874 * value.
875 * @param defValue Value to return if the attribute is not defined or
876 * not a resource.
Alan Viverettefd274a02014-03-27 15:39:15 -0700877 *
878 * @return Attribute fractional value multiplied by the appropriate
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800879 * base value, or defValue if not defined.
880 * @throws RuntimeException if the TypedArray has already been recycled.
881 * @throws UnsupportedOperationException if the attribute is defined but is
882 * not a fraction.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700884 public float getFraction(@StyleableRes int index, int base, int pbase, float defValue) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700885 if (mRecycled) {
886 throw new RuntimeException("Cannot make calls to a recycled instance!");
887 }
888
Alan Viverette5b90e822016-02-24 09:06:47 -0500889 final int attrIndex = index;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800890 index *= STYLE_NUM_ENTRIES;
Alan Viverette5b90e822016-02-24 09:06:47 -0500891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800893 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800894 if (type == TypedValue.TYPE_NULL) {
895 return defValue;
896 } else if (type == TypedValue.TYPE_FRACTION) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800897 return TypedValue.complexToFraction(data[index + STYLE_DATA], base, pbase);
Alan Viverette216d3e62014-07-29 10:35:42 -0700898 } else if (type == TypedValue.TYPE_ATTRIBUTE) {
Alan Viverette93795052015-03-09 15:32:50 -0700899 final TypedValue value = mValue;
Alan Viverette5b90e822016-02-24 09:06:47 -0500900 getValueAt(index, value);
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800901 throw new UnsupportedOperationException(
Alan Viverette5b90e822016-02-24 09:06:47 -0500902 "Failed to resolve attribute at index " + attrIndex + ": " + value);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903 }
904
Alan Viverette5b90e822016-02-24 09:06:47 -0500905 throw new UnsupportedOperationException("Can't convert value at index " + attrIndex
906 + " to fraction: type=0x" + Integer.toHexString(type));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 }
908
909 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800910 * Retrieves the resource identifier for the attribute at
Alan Viverettefd274a02014-03-27 15:39:15 -0700911 * <var>index</var>. Note that attribute resource as resolved when
912 * the overall {@link TypedArray} object is retrieved. As a
913 * result, this function will return the resource identifier of the
914 * final resource value that was found, <em>not</em> necessarily the
915 * original resource that was specified by the attribute.
916 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 * @param index Index of attribute to retrieve.
918 * @param defValue Value to return if the attribute is not defined or
919 * not a resource.
Alan Viverettefd274a02014-03-27 15:39:15 -0700920 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 * @return Attribute resource identifier, or defValue if not defined.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800922 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923 */
Tor Norbye7b9c9122013-05-30 16:48:33 -0700924 @AnyRes
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700925 public int getResourceId(@StyleableRes int index, int defValue) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700926 if (mRecycled) {
927 throw new RuntimeException("Cannot make calls to a recycled instance!");
928 }
929
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800930 index *= STYLE_NUM_ENTRIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800931 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800932 if (data[index + STYLE_TYPE] != TypedValue.TYPE_NULL) {
933 final int resid = data[index + STYLE_RESOURCE_ID];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 if (resid != 0) {
935 return resid;
936 }
937 }
938 return defValue;
939 }
940
941 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800942 * Retrieves the theme attribute resource identifier for the attribute at
Alan Viverette500c5602014-07-29 11:30:35 -0700943 * <var>index</var>.
944 *
945 * @param index Index of attribute to retrieve.
946 * @param defValue Value to return if the attribute is not defined or not a
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800947 * resource.
948 *
Alan Viverette500c5602014-07-29 11:30:35 -0700949 * @return Theme attribute resource identifier, or defValue if not defined.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800950 * @throws RuntimeException if the TypedArray has already been recycled.
Alan Viverette500c5602014-07-29 11:30:35 -0700951 * @hide
952 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700953 public int getThemeAttributeId(@StyleableRes int index, int defValue) {
Alan Viverette500c5602014-07-29 11:30:35 -0700954 if (mRecycled) {
955 throw new RuntimeException("Cannot make calls to a recycled instance!");
956 }
957
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800958 index *= STYLE_NUM_ENTRIES;
Alan Viverette500c5602014-07-29 11:30:35 -0700959 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800960 if (data[index + STYLE_TYPE] == TypedValue.TYPE_ATTRIBUTE) {
961 return data[index + STYLE_DATA];
Alan Viverette500c5602014-07-29 11:30:35 -0700962 }
963 return defValue;
964 }
965
966 /**
Alan Viverettefde4e3b2014-09-22 16:19:51 -0700967 * Retrieve the Drawable for the attribute at <var>index</var>.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800968 * <p>
969 * This method will throw an exception if the attribute is defined but is
970 * not a color or drawable resource.
Alan Viverettefd274a02014-03-27 15:39:15 -0700971 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 * @param index Index of attribute to retrieve.
Alan Viverettefd274a02014-03-27 15:39:15 -0700973 *
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800974 * @return Drawable for the attribute, or {@code null} if not defined.
975 * @throws RuntimeException if the TypedArray has already been recycled.
976 * @throws UnsupportedOperationException if the attribute is defined but is
977 * not a color or drawable resource.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 */
Alan Viverettefde4e3b2014-09-22 16:19:51 -0700979 @Nullable
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -0700980 public Drawable getDrawable(@StyleableRes int index) {
Adam Lesinski50954d22017-04-14 18:41:52 -0700981 return getDrawableForDensity(index, 0);
982 }
983
984 /**
985 * Version of {@link #getDrawable(int)} that accepts an override density.
986 * @hide
987 */
988 @Nullable
989 public Drawable getDrawableForDensity(@StyleableRes int index, int density) {
Alan Viverettefd274a02014-03-27 15:39:15 -0700990 if (mRecycled) {
991 throw new RuntimeException("Cannot make calls to a recycled instance!");
992 }
993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 final TypedValue value = mValue;
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800995 if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
Alan Viverette216d3e62014-07-29 10:35:42 -0700996 if (value.type == TypedValue.TYPE_ATTRIBUTE) {
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800997 throw new UnsupportedOperationException(
Alan Viverette93795052015-03-09 15:32:50 -0700998 "Failed to resolve attribute at index " + index + ": " + value);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 }
Adam Lesinski50954d22017-04-14 18:41:52 -07001000
1001 if (density > 0) {
1002 // If the density is overridden, the value in the TypedArray will not reflect this.
1003 // Do a separate lookup of the resourceId with the density override.
1004 mResources.getValueForDensity(value.resourceId, density, value, true);
1005 }
1006 return mResources.loadDrawable(value, value.resourceId, density, mTheme);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 }
1008 return null;
1009 }
1010
1011 /**
Clara Bayarried00bfd2017-01-20 14:58:21 +00001012 * Retrieve the Typeface for the attribute at <var>index</var>.
1013 * <p>
1014 * This method will throw an exception if the attribute is defined but is
1015 * not a font.
1016 *
1017 * @param index Index of attribute to retrieve.
1018 *
1019 * @return Typeface for the attribute, or {@code null} if not defined.
1020 * @throws RuntimeException if the TypedArray has already been recycled.
1021 * @throws UnsupportedOperationException if the attribute is defined but is
1022 * not a font resource.
1023 */
1024 @Nullable
1025 public Typeface getFont(@StyleableRes int index) {
1026 if (mRecycled) {
1027 throw new RuntimeException("Cannot make calls to a recycled instance!");
1028 }
1029
1030 final TypedValue value = mValue;
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001031 if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
Clara Bayarried00bfd2017-01-20 14:58:21 +00001032 if (value.type == TypedValue.TYPE_ATTRIBUTE) {
1033 throw new UnsupportedOperationException(
1034 "Failed to resolve attribute at index " + index + ": " + value);
1035 }
1036 return mResources.getFont(value, value.resourceId);
1037 }
1038 return null;
1039 }
1040
1041 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042 * Retrieve the CharSequence[] for the attribute at <var>index</var>.
1043 * This gets the resource ID of the selected attribute, and uses
1044 * {@link Resources#getTextArray Resources.getTextArray} of the owning
1045 * Resources object to retrieve its String[].
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001046 * <p>
1047 * This method will throw an exception if the attribute is defined but is
1048 * not a text array resource.
Alan Viverettefd274a02014-03-27 15:39:15 -07001049 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001050 * @param index Index of attribute to retrieve.
Alan Viverettefd274a02014-03-27 15:39:15 -07001051 *
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001052 * @return CharSequence[] for the attribute, or {@code null} if not
1053 * defined.
1054 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -07001056 public CharSequence[] getTextArray(@StyleableRes int index) {
Alan Viverettefd274a02014-03-27 15:39:15 -07001057 if (mRecycled) {
1058 throw new RuntimeException("Cannot make calls to a recycled instance!");
1059 }
1060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061 final TypedValue value = mValue;
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001062 if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 return mResources.getTextArray(value.resourceId);
1064 }
1065 return null;
1066 }
1067
1068 /**
1069 * Retrieve the raw TypedValue for the attribute at <var>index</var>.
Alan Viverettefd274a02014-03-27 15:39:15 -07001070 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 * @param index Index of attribute to retrieve.
1072 * @param outValue TypedValue object in which to place the attribute's
1073 * data.
Alan Viverettefd274a02014-03-27 15:39:15 -07001074 *
Adam Lesinski32e75012017-05-09 15:25:37 -07001075 * @return {@code true} if the value was retrieved and not @empty, {@code false} otherwise.
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001076 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -07001078 public boolean getValue(@StyleableRes int index, TypedValue outValue) {
Alan Viverettefd274a02014-03-27 15:39:15 -07001079 if (mRecycled) {
1080 throw new RuntimeException("Cannot make calls to a recycled instance!");
Alan Viverette52b999f2014-03-24 18:00:26 -07001081 }
Alan Viverettefd274a02014-03-27 15:39:15 -07001082
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001083 return getValueAt(index * STYLE_NUM_ENTRIES, outValue);
Alan Viverette52b999f2014-03-24 18:00:26 -07001084 }
1085
1086 /**
1087 * Returns the type of attribute at the specified index.
1088 *
1089 * @param index Index of attribute whose type to retrieve.
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001090 *
Alan Viverette52b999f2014-03-24 18:00:26 -07001091 * @return Attribute type.
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001092 * @throws RuntimeException if the TypedArray has already been recycled.
Alan Viverette52b999f2014-03-24 18:00:26 -07001093 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -07001094 public int getType(@StyleableRes int index) {
Alan Viverettefd274a02014-03-27 15:39:15 -07001095 if (mRecycled) {
1096 throw new RuntimeException("Cannot make calls to a recycled instance!");
1097 }
1098
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001099 index *= STYLE_NUM_ENTRIES;
1100 return mData[index + STYLE_TYPE];
Alan Viverette52b999f2014-03-24 18:00:26 -07001101 }
1102
1103 /**
Aurimas Liutikas949b05d2019-01-30 17:20:41 -08001104 * Returns the resource ID of the style or layout against which the specified attribute was
1105 * resolved, otherwise returns defValue.
1106 *
1107 * For example, if you we resolving two attributes {@code android:attribute1} and
1108 * {@code android:attribute2} and you were inflating a {@link android.view.View} from
1109 * {@code layout/my_layout.xml}:
1110 * <pre>
1111 * &lt;View
1112 * style="@style/viewStyle"
1113 * android:layout_width="wrap_content"
1114 * android:layout_height="wrap_content"
1115 * android:attribute1="foo"/&gt;
1116 * </pre>
1117 *
1118 * and {@code @style/viewStyle} is:
1119 * <pre>
1120 * &lt;style android:name="viewStyle"&gt;
1121 * &lt;item name="android:attribute2"&gt;bar&lt;item/&gt;
1122 * &lt;style/&gt;
1123 * </pre>
1124 *
1125 * then resolved {@link TypedArray} will have values that return source resource ID of
1126 * {@code R.layout.my_layout} for {@code android:attribute1} and {@code R.style.viewStyle} for
1127 * {@code android:attribute2}.
Aurimas Liutikasce7c99c2018-12-18 16:20:49 -08001128 *
1129 * @param index Index of attribute whose source style to retrieve.
Aurimas Liutikas949b05d2019-01-30 17:20:41 -08001130 * @param defaultValue Value to return if the attribute is not defined or
1131 * not a resource.
Aurimas Liutikasce7c99c2018-12-18 16:20:49 -08001132 *
Aurimas Liutikas949b05d2019-01-30 17:20:41 -08001133 * @return Either a style resource ID, layout resource ID, or defaultValue if it was not
1134 * resolved in a style or layout.
Aurimas Liutikasce7c99c2018-12-18 16:20:49 -08001135 * @throws RuntimeException if the TypedArray has already been recycled.
1136 */
1137 @StyleRes
Aurimas Liutikas949b05d2019-01-30 17:20:41 -08001138 public int getSourceResourceId(@StyleableRes int index, @StyleRes int defaultValue) {
Aurimas Liutikasce7c99c2018-12-18 16:20:49 -08001139 if (mRecycled) {
1140 throw new RuntimeException("Cannot make calls to a recycled instance!");
1141 }
1142
1143 index *= STYLE_NUM_ENTRIES;
Aurimas Liutikas949b05d2019-01-30 17:20:41 -08001144 final int resid = mData[index + SYTLE_SOURCE_RESOURCE_ID];
Aurimas Liutikasce7c99c2018-12-18 16:20:49 -08001145 if (resid != 0) {
1146 return resid;
1147 }
Aurimas Liutikas949b05d2019-01-30 17:20:41 -08001148 return defaultValue;
Aurimas Liutikasce7c99c2018-12-18 16:20:49 -08001149 }
1150
1151 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 * Determines whether there is an attribute at <var>index</var>.
Alan Viverettef2969402014-10-29 17:09:36 -07001153 * <p>
1154 * <strong>Note:</strong> If the attribute was set to {@code @empty} or
1155 * {@code @undefined}, this method returns {@code false}.
Alan Viverettefd274a02014-03-27 15:39:15 -07001156 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 * @param index Index of attribute to retrieve.
Alan Viverettefd274a02014-03-27 15:39:15 -07001158 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 * @return True if the attribute has a value, false otherwise.
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001160 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -07001162 public boolean hasValue(@StyleableRes int index) {
Alan Viverettefd274a02014-03-27 15:39:15 -07001163 if (mRecycled) {
1164 throw new RuntimeException("Cannot make calls to a recycled instance!");
1165 }
1166
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001167 index *= STYLE_NUM_ENTRIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001168 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001169 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170 return type != TypedValue.TYPE_NULL;
1171 }
Alan Viverettefd274a02014-03-27 15:39:15 -07001172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 /**
Alan Viverettef2969402014-10-29 17:09:36 -07001174 * Determines whether there is an attribute at <var>index</var>, returning
1175 * {@code true} if the attribute was explicitly set to {@code @empty} and
1176 * {@code false} only if the attribute was undefined.
1177 *
1178 * @param index Index of attribute to retrieve.
1179 *
1180 * @return True if the attribute has a value or is empty, false otherwise.
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001181 * @throws RuntimeException if the TypedArray has already been recycled.
Alan Viverettef2969402014-10-29 17:09:36 -07001182 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -07001183 public boolean hasValueOrEmpty(@StyleableRes int index) {
Alan Viverettef2969402014-10-29 17:09:36 -07001184 if (mRecycled) {
1185 throw new RuntimeException("Cannot make calls to a recycled instance!");
1186 }
1187
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001188 index *= STYLE_NUM_ENTRIES;
Alan Viverettef2969402014-10-29 17:09:36 -07001189 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001190 final int type = data[index + STYLE_TYPE];
Alan Viverettef2969402014-10-29 17:09:36 -07001191 return type != TypedValue.TYPE_NULL
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001192 || data[index + STYLE_DATA] == TypedValue.DATA_NULL_EMPTY;
Alan Viverettef2969402014-10-29 17:09:36 -07001193 }
1194
1195 /**
Alan Viverettefd274a02014-03-27 15:39:15 -07001196 * Retrieve the raw TypedValue for the attribute at <var>index</var>
1197 * and return a temporary object holding its data. This object is only
1198 * valid until the next call on to {@link TypedArray}.
1199 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200 * @param index Index of attribute to retrieve.
Alan Viverettefd274a02014-03-27 15:39:15 -07001201 *
1202 * @return Returns a TypedValue object if the attribute is defined,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 * containing its data; otherwise returns null. (You will not
1204 * receive a TypedValue whose type is TYPE_NULL.)
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001205 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001206 */
Deepanshu Guptad7bb3f82015-08-05 16:38:21 -07001207 public TypedValue peekValue(@StyleableRes int index) {
Alan Viverettefd274a02014-03-27 15:39:15 -07001208 if (mRecycled) {
1209 throw new RuntimeException("Cannot make calls to a recycled instance!");
1210 }
1211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 final TypedValue value = mValue;
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001213 if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214 return value;
1215 }
1216 return null;
1217 }
1218
1219 /**
1220 * Returns a message about the parser state suitable for printing error messages.
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001221 *
1222 * @return Human-readable description of current parser state.
1223 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 */
1225 public String getPositionDescription() {
Alan Viverettefd274a02014-03-27 15:39:15 -07001226 if (mRecycled) {
1227 throw new RuntimeException("Cannot make calls to a recycled instance!");
1228 }
1229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001230 return mXml != null ? mXml.getPositionDescription() : "<internal>";
1231 }
1232
1233 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001234 * Recycles the TypedArray, to be re-used by a later caller. After calling
Alan Viverettefd274a02014-03-27 15:39:15 -07001235 * this function you must not ever touch the typed array again.
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001236 *
1237 * @throws RuntimeException if the TypedArray has already been recycled.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 */
1239 public void recycle() {
Alan Viverettefd274a02014-03-27 15:39:15 -07001240 if (mRecycled) {
1241 throw new RuntimeException(toString() + " recycled twice!");
1242 }
1243
1244 mRecycled = true;
Alan Viverette8eea3ea2014-02-03 18:40:20 -08001245
Alan Viverette52b999f2014-03-24 18:00:26 -07001246 // These may have been set by the client.
Alan Viverette8eea3ea2014-02-03 18:40:20 -08001247 mXml = null;
Alan Viverette8eea3ea2014-02-03 18:40:20 -08001248 mTheme = null;
Adam Lesinskie60064a2016-07-13 12:09:24 -07001249 mAssets = null;
Alan Viverette52b999f2014-03-24 18:00:26 -07001250
Alan Viverette8b5b25b2014-09-13 19:30:11 -07001251 mResources.mTypedArrayPool.release(this);
Alan Viverette52b999f2014-03-24 18:00:26 -07001252 }
1253
1254 /**
1255 * Extracts theme attributes from a typed array for later resolution using
Alan Viverette9cd14fc2014-06-20 14:45:11 -07001256 * {@link android.content.res.Resources.Theme#resolveAttributes(int[], int[])}.
1257 * Removes the entries from the typed array so that subsequent calls to typed
1258 * getters will return the default value without crashing.
Alan Viverette52b999f2014-03-24 18:00:26 -07001259 *
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001260 * @return an array of length {@link #getIndexCount()} populated with theme
1261 * attributes, or null if there are no theme attributes in the typed
1262 * array
1263 * @throws RuntimeException if the TypedArray has already been recycled.
Alan Viverette52b999f2014-03-24 18:00:26 -07001264 * @hide
1265 */
Alan Viverette45c4bbb2015-01-05 14:59:19 -08001266 @Nullable
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001267 @UnsupportedAppUsage
Alan Viverette52b999f2014-03-24 18:00:26 -07001268 public int[] extractThemeAttrs() {
Alan Viverette45c4bbb2015-01-05 14:59:19 -08001269 return extractThemeAttrs(null);
1270 }
1271
1272 /**
1273 * @hide
1274 */
1275 @Nullable
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001276 @UnsupportedAppUsage
Alan Viverette45c4bbb2015-01-05 14:59:19 -08001277 public int[] extractThemeAttrs(@Nullable int[] scrap) {
Alan Viverettefd274a02014-03-27 15:39:15 -07001278 if (mRecycled) {
1279 throw new RuntimeException("Cannot make calls to a recycled instance!");
1280 }
1281
Alan Viverette52b999f2014-03-24 18:00:26 -07001282 int[] attrs = null;
1283
Alan Viverette0cfb8772014-05-14 17:40:53 -07001284 final int[] data = mData;
Alan Viverette1cd46122014-03-25 17:58:50 -07001285 final int N = length();
Alan Viverette52b999f2014-03-24 18:00:26 -07001286 for (int i = 0; i < N; i++) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001287 final int index = i * STYLE_NUM_ENTRIES;
1288 if (data[index + STYLE_TYPE] != TypedValue.TYPE_ATTRIBUTE) {
Alan Viverette45c4bbb2015-01-05 14:59:19 -08001289 // Not an attribute, ignore.
Alan Viverette0cfb8772014-05-14 17:40:53 -07001290 continue;
Alan Viverette52b999f2014-03-24 18:00:26 -07001291 }
Alan Viverette0cfb8772014-05-14 17:40:53 -07001292
1293 // Null the entry so that we can safely call getZzz().
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001294 data[index + STYLE_TYPE] = TypedValue.TYPE_NULL;
Alan Viverette0cfb8772014-05-14 17:40:53 -07001295
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001296 final int attr = data[index + STYLE_DATA];
Alan Viverette0cfb8772014-05-14 17:40:53 -07001297 if (attr == 0) {
Alan Viverette45c4bbb2015-01-05 14:59:19 -08001298 // Useless data, ignore.
Alan Viverette0cfb8772014-05-14 17:40:53 -07001299 continue;
1300 }
1301
Alan Viverette45c4bbb2015-01-05 14:59:19 -08001302 // Ensure we have a usable attribute array.
Alan Viverette0cfb8772014-05-14 17:40:53 -07001303 if (attrs == null) {
Alan Viverette45c4bbb2015-01-05 14:59:19 -08001304 if (scrap != null && scrap.length == N) {
1305 attrs = scrap;
1306 Arrays.fill(attrs, 0);
1307 } else {
1308 attrs = new int[N];
1309 }
Alan Viverette0cfb8772014-05-14 17:40:53 -07001310 }
Alan Viverette45c4bbb2015-01-05 14:59:19 -08001311
Alan Viverette0cfb8772014-05-14 17:40:53 -07001312 attrs[i] = attr;
Alan Viverette52b999f2014-03-24 18:00:26 -07001313 }
1314
1315 return attrs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001316 }
1317
Alan Viverette8e5e11b2014-07-07 14:06:15 -07001318 /**
1319 * Return a mask of the configuration parameters for which the values in
1320 * this typed array may change.
1321 *
1322 * @return Returns a mask of the changing configuration parameters, as
1323 * defined by {@link android.content.pm.ActivityInfo}.
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001324 * @throws RuntimeException if the TypedArray has already been recycled.
Alan Viverette8e5e11b2014-07-07 14:06:15 -07001325 * @see android.content.pm.ActivityInfo
1326 */
Alan Viveretteac85f902016-03-11 15:15:51 -05001327 public @Config int getChangingConfigurations() {
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001328 if (mRecycled) {
1329 throw new RuntimeException("Cannot make calls to a recycled instance!");
1330 }
1331
Alan Viveretteac85f902016-03-11 15:15:51 -05001332 @Config int changingConfig = 0;
Alan Viverette8e5e11b2014-07-07 14:06:15 -07001333
1334 final int[] data = mData;
1335 final int N = length();
1336 for (int i = 0; i < N; i++) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001337 final int index = i * STYLE_NUM_ENTRIES;
1338 final int type = data[index + STYLE_TYPE];
Alan Viverette8e5e11b2014-07-07 14:06:15 -07001339 if (type == TypedValue.TYPE_NULL) {
1340 continue;
1341 }
Alan Viveretteac85f902016-03-11 15:15:51 -05001342 changingConfig |= ActivityInfo.activityInfoConfigNativeToJava(
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001343 data[index + STYLE_CHANGING_CONFIGURATIONS]);
Alan Viverette8e5e11b2014-07-07 14:06:15 -07001344 }
1345 return changingConfig;
1346 }
1347
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001348 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 private boolean getValueAt(int index, TypedValue outValue) {
1350 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001351 final int type = data[index + STYLE_TYPE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 if (type == TypedValue.TYPE_NULL) {
1353 return false;
1354 }
1355 outValue.type = type;
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001356 outValue.data = data[index + STYLE_DATA];
1357 outValue.assetCookie = data[index + STYLE_ASSET_COOKIE];
1358 outValue.resourceId = data[index + STYLE_RESOURCE_ID];
Alan Viveretteac85f902016-03-11 15:15:51 -05001359 outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001360 data[index + STYLE_CHANGING_CONFIGURATIONS]);
1361 outValue.density = data[index + STYLE_DENSITY];
Gilles Debunne75399682010-08-19 11:26:14 -07001362 outValue.string = (type == TypedValue.TYPE_STRING) ? loadStringValueAt(index) : null;
Aurimas Liutikas949b05d2019-01-30 17:20:41 -08001363 outValue.sourceResourceId = data[index + SYTLE_SOURCE_RESOURCE_ID];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 return true;
1365 }
1366
1367 private CharSequence loadStringValueAt(int index) {
1368 final int[] data = mData;
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001369 final int cookie = data[index + STYLE_ASSET_COOKIE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001370 if (cookie < 0) {
1371 if (mXml != null) {
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001372 return mXml.getPooledString(data[index + STYLE_DATA]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 }
1374 return null;
1375 }
Adam Lesinskibebfcc42018-02-12 14:27:46 -08001376 return mAssets.getPooledStringForCookie(cookie, data[index + STYLE_DATA]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 }
1378
John Reckf32adf42016-11-23 10:39:40 -08001379 /** @hide */
1380 protected TypedArray(Resources resources) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 mResources = resources;
Adam Lesinskifb302cc2016-02-29 16:50:38 -08001382 mMetrics = mResources.getDisplayMetrics();
1383 mAssets = mResources.getAssets();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 }
1385
Alan Viverette562a6a82014-01-31 11:07:29 -08001386 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001387 public String toString() {
1388 return Arrays.toString(mData);
1389 }
Kenny Root15a4d2f2010-03-11 18:20:12 -08001390}