1 /*
2  * Copyright 2018 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  *     https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.content.res.cts;
18 
19 import android.content.Context;
20 import android.content.cts.R;
21 import android.content.cts.util.XmlUtils;
22 import android.content.pm.ActivityInfo;
23 import android.content.res.AssetManager;
24 import android.content.res.ColorStateList;
25 import android.content.res.Configuration;
26 import android.content.res.Resources;
27 import android.content.res.Resources.NotFoundException;
28 import android.content.res.TypedArray;
29 import android.content.res.XmlResourceParser;
30 import android.graphics.Paint;
31 import android.graphics.Typeface;
32 import android.graphics.drawable.AdaptiveIconDrawable;
33 import android.graphics.drawable.ColorDrawable;
34 import android.graphics.drawable.ColorStateListDrawable;
35 import android.graphics.drawable.Drawable;
36 import android.os.Bundle;
37 import android.os.LocaleList;
38 import android.platform.test.annotations.AppModeFull;
39 import android.test.AndroidTestCase;
40 import android.util.AttributeSet;
41 import android.util.DisplayMetrics;
42 import android.util.TypedValue;
43 import android.util.Xml;
44 import android.view.Display;
45 import android.view.LayoutInflater;
46 import android.view.View;
47 import android.view.WindowManager;
48 
49 import androidx.test.InstrumentationRegistry;
50 
51 import org.xmlpull.v1.XmlPullParser;
52 import org.xmlpull.v1.XmlPullParserException;
53 
54 import java.io.IOException;
55 import java.io.InputStream;
56 import java.util.Locale;
57 
58 public class ResourcesTest extends AndroidTestCase {
59     private static final String CONFIG_VARYING = "configVarying";
60     private static final String SIMPLE = "simple";
61     private static final String CONFIG_VARYING_SIMPLE = "configVarying/simple";
62     private static final String PACKAGE_NAME = "android.content.cts";
63     private static final String COM_ANDROID_CTS_STUB_IDENTIFIER =
64                 "android.content.cts:configVarying/simple";
65     private Resources mResources;
66 
67     @Override
setUp()68     protected void setUp() throws Exception {
69         super.setUp();
70 
71         mResources = getContext().getResources();
72     }
73 
testIdNull()74     public void testIdNull() {
75         assertEquals(0, Resources.ID_NULL);
76     }
77 
testResources()78     public void testResources() {
79         final AssetManager am = new AssetManager();
80         final Configuration cfg = new Configuration();
81         cfg.keyboard = Configuration.KEYBOARDHIDDEN_YES;
82         final DisplayMetrics dm = new DisplayMetrics();
83         dm.setToDefaults();
84 
85         final Resources r = new Resources(am, dm, cfg);
86         final Configuration c = r.getConfiguration();
87         assertEquals(Configuration.KEYBOARDHIDDEN_YES, c.keyboard);
88     }
89 
testGetString()90     public void testGetString() {
91         try {
92             mResources.getString(-1, "%s");
93             fail("Failed at testGetString2");
94         } catch (NotFoundException e) {
95           //expected
96         }
97 
98         final String strGo = mResources.getString(R.string.go, "%1$s%%", 12);
99         assertEquals("Go", strGo);
100     }
101 
testObtainAttributes()102     public void testObtainAttributes() throws XmlPullParserException, IOException {
103         final XmlPullParser parser = mResources.getXml(R.xml.test_color);
104         XmlUtils.beginDocument(parser, "resources");
105         final AttributeSet set = Xml.asAttributeSet(parser);
106         final TypedArray testTypedArray = mResources.obtainAttributes(set, R.styleable.Style1);
107         assertNotNull(testTypedArray);
108         assertEquals(2, testTypedArray.length());
109         assertEquals(0, testTypedArray.getColor(0, 0));
110         assertEquals(128, testTypedArray.getColor(1, 128));
111         assertEquals(mResources, testTypedArray.getResources());
112         testTypedArray.recycle();
113     }
114 
testObtainTypedArray()115     public void testObtainTypedArray() {
116         try {
117             mResources.obtainTypedArray(-1);
118             fail("Failed at testObtainTypedArray");
119         } catch (NotFoundException e) {
120             //expected
121         }
122 
123         final TypedArray ta = mResources.obtainTypedArray(R.array.string);
124         assertEquals(3, ta.length());
125         assertEquals("Test String 1", ta.getString(0));
126         assertEquals("Test String 2", ta.getString(1));
127         assertEquals("Test String 3", ta.getString(2));
128         assertEquals(mResources, ta.getResources());
129     }
130 
getResources(final Configuration config, final int mcc, final int mnc, final int touchscreen, final int keyboard, final int keysHidden, final int navigation, final int width, final int height)131     private Resources getResources(final Configuration config, final int mcc, final int mnc,
132             final int touchscreen, final int keyboard, final int keysHidden, final int navigation,
133             final int width, final int height) {
134         final AssetManager assmgr = new AssetManager();
135         assmgr.addAssetPath(mContext.getPackageResourcePath());
136         final DisplayMetrics metrics = new DisplayMetrics();
137         final WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
138         final Display d = wm.getDefaultDisplay();
139         d.getMetrics(metrics);
140         config.mcc = mcc;
141         config.mnc = mnc;
142         config.touchscreen = touchscreen;
143         config.keyboard = keyboard;
144         config.keyboardHidden = keysHidden;
145         config.navigation = navigation;
146         metrics.widthPixels = width;
147         metrics.heightPixels = height;
148         return new Resources(assmgr, metrics, config);
149     }
150 
checkGetText1(final Resources res, final int resId, final String expectedValue)151     private static void checkGetText1(final Resources res, final int resId,
152             final String expectedValue) {
153         final String actual = res.getText(resId).toString();
154         assertNotNull("Returned wrong configuration-based simple value: expected <nothing>, "
155                 + "got '" + actual + "' from resource 0x" + Integer.toHexString(resId),
156                 expectedValue);
157         assertEquals("Returned wrong configuration-based simple value: expected " + expectedValue
158                 + ", got '" + actual + "' from resource 0x" + Integer.toHexString(resId),
159                 expectedValue, actual);
160     }
161 
checkGetText2(final Resources res, final int resId, final String expectedValue)162     private static void checkGetText2(final Resources res, final int resId,
163             final String expectedValue) {
164         final String actual = res.getText(resId, null).toString();
165         assertNotNull("Returned wrong configuration-based simple value: expected <nothing>, "
166                 + "got '" + actual + "' from resource 0x" + Integer.toHexString(resId),
167                 expectedValue);
168         assertEquals("Returned wrong configuration-based simple value: expected " + expectedValue
169                 + ", got '" + actual + "' from resource 0x" + Integer.toHexString(resId),
170                 expectedValue, actual);
171     }
172 
testGetMovie()173     public void testGetMovie() {
174         try {
175             mResources.getMovie(-1);
176             fail("Failed at testGetMovie");
177         } catch (NotFoundException e) {
178             //expected
179         }
180     }
181 
testGetDimension()182     public void testGetDimension() {
183         try {
184             mResources.getDimension(-1);
185             fail("Failed at testGetDimension");
186         } catch (NotFoundException e) {
187             //expected
188         }
189 
190         // app_icon_size is 48px, as defined in cts/tests/res/values/resources_test.xml
191         final float dim = mResources.getDimension(R.dimen.app_icon_size);
192         assertEquals(48.0f, dim);
193     }
194 
testGetDimensionPixelOffset()195     public void testGetDimensionPixelOffset() {
196         try {
197             mResources.getDimensionPixelOffset(-1);
198             fail("Failed at testGetDimensionPixelOffset");
199         } catch (NotFoundException e) {
200             //expected
201         }
202 
203         // app_icon_size is 48px, as defined in cts/tests/res/values/resources_test.xml
204         final int dim = mResources.getDimensionPixelOffset(R.dimen.app_icon_size);
205         assertEquals(48, dim);
206     }
207 
testGetColorStateList()208     public void testGetColorStateList() {
209         try {
210             mResources.getColorStateList(-1);
211             fail("Failed at testGetColorStateList");
212         } catch (NotFoundException e) {
213             //expected
214         }
215 
216         final ColorStateList colorStateList = mResources.getColorStateList(R.color.color1);
217         final int[] focusedState = {android.R.attr.state_focused};
218         final int focusColor = colorStateList.getColorForState(focusedState, R.color.failColor);
219         assertEquals(mResources.getColor(R.color.testcolor1), focusColor);
220     }
221 
testGetColorStateListThrows()222     public void testGetColorStateListThrows() {
223         try {
224             // XML that's not a selector or gradient throws
225             mResources.getColorStateList(R.drawable.density_test);
226             fail("Failed at testGetColorStateList");
227         } catch (NotFoundException expected) {
228             // expected
229         }
230     }
231 
testGetColor()232     public void testGetColor() {
233         try {
234             mResources.getColor(-1);
235             fail("Failed at testGetColor");
236         } catch (NotFoundException e) {
237             //expected
238         }
239 
240         final int color = mResources.getColor(R.color.testcolor1);
241         assertEquals(0xff00ff00, color);
242     }
243 
createNewResources()244     public Resources createNewResources() {
245         final DisplayMetrics dm = new DisplayMetrics();
246         dm.setToDefaults();
247         final Configuration cfg = new Configuration();
248         cfg.setToDefaults();
249         return new Resources(new AssetManager(), dm, cfg);
250     }
251 
testUpdateConfiguration()252     public void testUpdateConfiguration() {
253         Resources res = createNewResources();
254         final Configuration cfg = new Configuration(res.getConfiguration());
255         assertTrue(cfg.fontScale != 5);
256 
257         cfg.fontScale = 5;
258         res.updateConfiguration(cfg, null);
259         assertEquals(5.0f, res.getConfiguration().fontScale, 0.001f);
260     }
261 
testUpdateConfiguration_emptyLocaleIsOverridden()262     public void testUpdateConfiguration_emptyLocaleIsOverridden() {
263         Resources res = createNewResources();
264         res.getConfiguration().setLocales(null);
265         assertTrue(res.getConfiguration().getLocales().isEmpty());
266 
267         final Configuration cfg = new Configuration();
268         cfg.setToDefaults();
269         assertTrue(cfg.getLocales().isEmpty());
270 
271         res.updateConfiguration(cfg, null);
272         assertEquals(LocaleList.getDefault(), res.getConfiguration().getLocales());
273     }
274 
testUpdateConfiguration_copyLocales()275     public void testUpdateConfiguration_copyLocales() {
276         Resources res = createNewResources();
277         final Configuration cfg = new Configuration(res.getConfiguration());
278 
279         cfg.setLocales(LocaleList.forLanguageTags("az-Arab,ru"));
280 
281         res.updateConfiguration(cfg, null);
282 
283         // Depending on the locales available in the framework resources, the LocaleList may be
284         // re-arranged. Check that any valid permutation is present.
285         final LocaleList locales = res.getConfiguration().getLocales();
286         assertTrue(LocaleList.forLanguageTags("az-Arab,ru").equals(locales) ||
287                 LocaleList.forLanguageTags("ru,az-Arab").equals(locales));
288     }
289 
testUpdateConfiguration_emptyAfterUpdate()290     public void testUpdateConfiguration_emptyAfterUpdate() {
291         Resources res = createNewResources();
292         final Configuration cfg = new Configuration(res.getConfiguration());
293         cfg.setLocales(LocaleList.forLanguageTags("az-Arab"));
294 
295         res.updateConfiguration(cfg, null);
296         assertEquals(LocaleList.forLanguageTags("az-Arab"), res.getConfiguration().getLocales());
297 
298         res.getConfiguration().setLocales(null);
299         cfg.setLocales(null);
300         res.updateConfiguration(cfg, null);
301         assertEquals(LocaleList.getDefault(), res.getConfiguration().getLocales());
302     }
303 
testGetDimensionPixelSize()304     public void testGetDimensionPixelSize() {
305         try {
306             mResources.getDimensionPixelSize(-1);
307             fail("Failed at testGetDimensionPixelSize");
308         } catch (NotFoundException e) {
309             //expected
310         }
311 
312         // app_icon_size is 48px, as defined in cts/tests/res/values/resources_test.xml
313         final int size = mResources.getDimensionPixelSize(R.dimen.app_icon_size);
314         assertEquals(48, size);
315         assertEquals(1, mResources.getDimensionPixelSize(R.dimen.pos_dimen_149));
316         assertEquals(2, mResources.getDimensionPixelSize(R.dimen.pos_dimen_151));
317         assertEquals(-1, mResources.getDimensionPixelSize(R.dimen.neg_dimen_149));
318         assertEquals(-2, mResources.getDimensionPixelSize(R.dimen.neg_dimen_151));
319     }
320 
testGetDrawable()321     public void testGetDrawable() {
322         try {
323             mResources.getDrawable(-1);
324             fail("Failed at testGetDrawable");
325         } catch (NotFoundException e) {
326             //expected
327         }
328 
329         // testimage is defined in cts/tests/res/drawable/testimage.jpg and measures 212px x 142px
330         final Drawable draw = mResources.getDrawable(R.drawable.testimage);
331         int targetDensity = mResources.getDisplayMetrics().densityDpi;
332         int defaultDensity = DisplayMetrics.DENSITY_DEFAULT;
333         assertNotNull(draw);
334         assertEquals(212 * targetDensity / defaultDensity, draw.getIntrinsicWidth(), 1);
335         assertEquals(142 * targetDensity / defaultDensity, draw.getIntrinsicHeight(), 1);
336 
337         // Some apps rely on the fact that this will return null (rather than throwing).
338         assertNull(mResources.getDrawable(R.drawable.fake_image_will_not_decode));
339     }
340 
testGetDrawable_StackOverflowErrorDrawable()341     public void testGetDrawable_StackOverflowErrorDrawable() {
342         try {
343             mResources.getDrawable(R.drawable.drawable_recursive);
344             fail("Failed at testGetDrawable_StackOverflowErrorDrawable");
345         } catch (NotFoundException e) {
346             //expected
347         }
348     }
349 
testGetDrawable_StackOverflowErrorDrawable_mipmap()350     public void testGetDrawable_StackOverflowErrorDrawable_mipmap() {
351         try {
352             mResources.getDrawable(R.mipmap.icon_recursive);
353             fail("Failed at testGetDrawable_StackOverflowErrorDrawable_mipmap");
354         } catch (NotFoundException e) {
355             //expected
356         }
357     }
358 
testGetDrawableForDensity()359     public void testGetDrawableForDensity() {
360         final Drawable ldpi = mResources.getDrawableForDensity(
361                 R.drawable.density_test, DisplayMetrics.DENSITY_LOW);
362         assertEquals(300, ldpi.getIntrinsicWidth());
363 
364         final Drawable mdpi = mResources.getDrawableForDensity(
365                 R.drawable.density_test, DisplayMetrics.DENSITY_MEDIUM);
366         assertEquals(200, mdpi.getIntrinsicWidth());
367 
368         final Drawable hdpi = mResources.getDrawableForDensity(
369                 R.drawable.density_test, DisplayMetrics.DENSITY_HIGH);
370         assertEquals(100, hdpi.getIntrinsicWidth());
371     }
372 
testGetDrawableForDensityWithZeroDensityIsSameAsGetDrawable()373     public void testGetDrawableForDensityWithZeroDensityIsSameAsGetDrawable() {
374         final Drawable defaultDrawable = mResources.getDrawable(R.drawable.density_test, null);
375         assertNotNull(defaultDrawable);
376 
377         final Drawable densityDrawable = mResources.getDrawableForDensity(R.drawable.density_test,
378                 0 /*density*/, null);
379         assertNotNull(densityDrawable);
380 
381         assertEquals(defaultDrawable.getIntrinsicWidth(), densityDrawable.getIntrinsicWidth());
382     }
383 
extractForegroundFromAdaptiveIconDrawable(int id, int density)384     private Drawable extractForegroundFromAdaptiveIconDrawable(int id, int density) {
385         final Drawable drawable = mResources.getDrawableForDensity(id, density, null);
386         assertTrue(drawable instanceof AdaptiveIconDrawable);
387         return ((AdaptiveIconDrawable) drawable).getForeground();
388     }
389 
testGetDrawableForDensityWithAdaptiveIconDrawable()390     public void testGetDrawableForDensityWithAdaptiveIconDrawable() {
391         final Drawable ldpi = extractForegroundFromAdaptiveIconDrawable(R.drawable.adaptive_icon,
392                 DisplayMetrics.DENSITY_LOW);
393         assertNotNull(ldpi);
394         assertEquals(300, ldpi.getIntrinsicWidth());
395 
396         final Drawable mdpi = extractForegroundFromAdaptiveIconDrawable(R.drawable.adaptive_icon,
397                 DisplayMetrics.DENSITY_MEDIUM);
398         assertNotNull(mdpi);
399         assertEquals(200, mdpi.getIntrinsicWidth());
400 
401         final Drawable hdpi = extractForegroundFromAdaptiveIconDrawable(R.drawable.adaptive_icon,
402                 DisplayMetrics.DENSITY_HIGH);
403         assertNotNull(hdpi);
404         assertEquals(100, hdpi.getIntrinsicWidth());
405     }
406 
testGetAnimation()407     public void testGetAnimation() throws Exception {
408         try {
409             mResources.getAnimation(-1);
410             fail("Failed at testGetAnimation");
411         } catch (NotFoundException e) {
412             //expected
413         }
414 
415         final XmlResourceParser ani = mResources.getAnimation(R.anim.anim_rotate);
416         assertNotNull(ani);
417         XmlUtils.beginDocument(ani, "rotate");
418         assertEquals(7, ani.getAttributeCount());
419         assertEquals("Binary XML file line #18", ani.getPositionDescription());
420         assertEquals("interpolator", ani.getAttributeName(0));
421         assertEquals("@17432582", ani.getAttributeValue(0));
422     }
423 
testGetQuantityString1()424     public void testGetQuantityString1() {
425         try {
426             mResources.getQuantityString(-1, 1, "");
427             fail("Failed at testGetQuantityString1");
428         } catch (NotFoundException e) {
429             //expected
430         }
431 
432         final String strGo = mResources.getQuantityString(R.plurals.plurals_test, 1, "");
433         assertEquals("A dog", strGo);
434     }
435 
testGetQuantityString2()436     public void testGetQuantityString2() {
437         try {
438             mResources.getQuantityString(-1, 1);
439             fail("Failed at testGetQuantityString2");
440         } catch (NotFoundException e) {
441             //expected
442         }
443 
444         final String strGo = mResources.getQuantityString(R.plurals.plurals_test, 1);
445         assertEquals("A dog", strGo);
446     }
447 
testGetInteger()448     public void testGetInteger() {
449         try {
450             mResources.getInteger(-1);
451             fail("Failed at testGetInteger");
452         } catch (NotFoundException e) {
453             //expected
454         }
455 
456         final int i = mResources.getInteger(R.integer.resource_test_int);
457         assertEquals(10, i);
458     }
459 
testGetValue()460     public void testGetValue() {
461         final TypedValue tv = new TypedValue();
462 
463         try {
464             mResources.getValue("null", tv, false);
465             fail("Failed at testGetValue");
466         } catch (NotFoundException e) {
467             //expected
468         }
469 
470         mResources.getValue("android.content.cts:raw/text", tv, false);
471         assertNotNull(tv);
472         assertEquals("res/raw/text.txt", tv.coerceToString());
473     }
474 
testGetValueForDensity()475     public void testGetValueForDensity() {
476         final TypedValue tv = new TypedValue();
477 
478         mResources.getValueForDensity(R.string.density_string,
479                 DisplayMetrics.DENSITY_LOW, tv, false);
480         assertEquals("ldpi", tv.coerceToString());
481 
482         mResources.getValueForDensity(R.string.density_string,
483                 DisplayMetrics.DENSITY_MEDIUM, tv, false);
484         assertEquals("mdpi", tv.coerceToString());
485 
486         mResources.getValueForDensity(R.string.density_string,
487                 DisplayMetrics.DENSITY_HIGH, tv, false);
488         assertEquals("hdpi", tv.coerceToString());
489     }
490 
testGetValueForDensityWithZeroDensityIsSameAsGetValue()491     public void testGetValueForDensityWithZeroDensityIsSameAsGetValue() {
492         final TypedValue defaultTv = new TypedValue();
493         mResources.getValue(R.string.density_string, defaultTv, false);
494 
495         final TypedValue densityTv = new TypedValue();
496         mResources.getValueForDensity(R.string.density_string, 0 /*density*/, densityTv, false);
497 
498         assertEquals(defaultTv.assetCookie, densityTv.assetCookie);
499         assertEquals(defaultTv.data, densityTv.data);
500         assertEquals(defaultTv.type, densityTv.type);
501         assertEquals(defaultTv.string, densityTv.string);
502     }
503 
testGetAssets()504     public void testGetAssets() {
505         final AssetManager aM = mResources.getAssets();
506         assertNotNull(aM);
507         assertTrue(aM.isUpToDate());
508     }
509 
testGetSystem()510     public void testGetSystem() {
511         assertNotNull(Resources.getSystem());
512     }
513 
testGetLayout()514     public void testGetLayout() throws Exception {
515         try {
516             mResources.getLayout(-1);
517             fail("Failed at testGetLayout");
518         } catch (NotFoundException e) {
519             //expected
520         }
521 
522         final XmlResourceParser layout = mResources.getLayout(R.layout.abslistview_layout);
523         assertNotNull(layout);
524         XmlUtils.beginDocument(layout, "ViewGroup_Layout");
525         assertEquals(3, layout.getAttributeCount());
526         assertEquals("id", layout.getAttributeName(0));
527         assertEquals("@" + R.id.abslistview_root, layout.getAttributeValue(0));
528     }
529 
testGetBoolean()530     public void testGetBoolean() {
531         try {
532             mResources.getBoolean(-1);
533             fail("Failed at testGetBoolean");
534         } catch (NotFoundException e) {
535             //expected
536         }
537 
538         final boolean b = mResources.getBoolean(R.integer.resource_test_int);
539         assertTrue(b);
540     }
541 
testgetFraction()542     public void testgetFraction() {
543         assertEquals(1, (int)mResources.getFraction(R.dimen.frac100perc, 1, 1));
544         assertEquals(100, (int)mResources.getFraction(R.dimen.frac100perc, 100, 1));
545     }
546 
testParseBundleExtras()547     public void testParseBundleExtras() throws XmlPullParserException, IOException {
548         final Bundle b = new Bundle();
549         XmlResourceParser parser = mResources.getXml(R.xml.extra);
550         XmlUtils.beginDocument(parser, "tag");
551 
552         assertEquals(0, b.size());
553         mResources.parseBundleExtras(parser, b);
554         assertEquals(1, b.size());
555         assertEquals("android", b.getString("google"));
556     }
557 
testParseBundleExtra()558     public void testParseBundleExtra() throws XmlPullParserException, IOException {
559         final Bundle b = new Bundle();
560         XmlResourceParser parser = mResources.getXml(R.xml.extra);
561 
562         XmlUtils.beginDocument(parser, "tag");
563         assertEquals(0, b.size());
564         mResources.parseBundleExtra("test", parser, b);
565         assertEquals(1, b.size());
566         assertEquals("Lee", b.getString("Bruce"));
567     }
568 
testGetIdentifier()569     public void testGetIdentifier() {
570 
571         int resid = mResources.getIdentifier(COM_ANDROID_CTS_STUB_IDENTIFIER, null, null);
572         assertEquals(R.configVarying.simple, resid);
573 
574         resid = mResources.getIdentifier(CONFIG_VARYING_SIMPLE, null, PACKAGE_NAME);
575         assertEquals(R.configVarying.simple, resid);
576 
577         resid = mResources.getIdentifier(SIMPLE, CONFIG_VARYING, PACKAGE_NAME);
578         assertEquals(R.configVarying.simple, resid);
579     }
580 
testGetIntArray()581     public void testGetIntArray() {
582         final int NO_EXIST_ID = -1;
583         try {
584             mResources.getIntArray(NO_EXIST_ID);
585             fail("should throw out NotFoundException");
586         } catch (NotFoundException e) {
587             // expected
588         }
589         // expected value is defined in res/value/arrays.xml
590         final int[] expectedArray1 = new int[] {
591                 0, 0, 0
592         };
593         final int[] expectedArray2 = new int[] {
594                 0, 1, 101
595         };
596         int[]array1 = mResources.getIntArray(R.array.strings);
597         int[]array2 = mResources.getIntArray(R.array.integers);
598 
599         checkArrayEqual(expectedArray1, array1);
600         checkArrayEqual(expectedArray2, array2);
601 
602     }
603 
checkArrayEqual(int[] array1, int[] array2)604     private void checkArrayEqual(int[] array1, int[] array2) {
605         assertNotNull(array2);
606         assertEquals(array1.length, array2.length);
607         for (int i = 0; i < array1.length; i++) {
608             assertEquals(array1[i], array2[i]);
609         }
610     }
611 
testGetQuantityText()612     public void testGetQuantityText() {
613         CharSequence cs;
614         final Resources res = resourcesForLanguage("cs");
615 
616         cs = res.getQuantityText(R.plurals.plurals_test, 0);
617         assertEquals("Some Czech dogs", cs.toString());
618 
619         cs = res.getQuantityText(R.plurals.plurals_test, 1);
620         assertEquals("A Czech dog", cs.toString());
621 
622         cs = res.getQuantityText(R.plurals.plurals_test, 2);
623         assertEquals("Few Czech dogs", cs.toString());
624 
625         cs = res.getQuantityText(R.plurals.plurals_test, 5);
626         assertEquals("Some Czech dogs", cs.toString());
627 
628         cs = res.getQuantityText(R.plurals.plurals_test, 500);
629         assertEquals("Some Czech dogs", cs.toString());
630 
631     }
632 
testChangingConfiguration()633     public void testChangingConfiguration() {
634         ColorDrawable dr1 = (ColorDrawable) mResources.getDrawable(R.color.varies_uimode);
635         assertEquals(ActivityInfo.CONFIG_UI_MODE, dr1.getChangingConfigurations());
636 
637         // Test again with a drawable obtained from the cache.
638         ColorDrawable dr2 = (ColorDrawable) mResources.getDrawable(R.color.varies_uimode);
639         assertEquals(ActivityInfo.CONFIG_UI_MODE, dr2.getChangingConfigurations());
640     }
641 
resourcesForLanguage(final String lang)642     private Resources resourcesForLanguage(final String lang) {
643         final Configuration config = new Configuration();
644         config.updateFrom(mResources.getConfiguration());
645         config.setLocale(new Locale(lang));
646         return new Resources(mResources.getAssets(), mResources.getDisplayMetrics(), config);
647     }
648 
testGetResourceEntryName()649     public void testGetResourceEntryName() {
650         assertEquals(SIMPLE, mResources.getResourceEntryName(R.configVarying.simple));
651     }
652 
testGetResourceName()653     public void testGetResourceName() {
654         final String fullName = mResources.getResourceName(R.configVarying.simple);
655         assertEquals(COM_ANDROID_CTS_STUB_IDENTIFIER, fullName);
656 
657         final String packageName = mResources.getResourcePackageName(R.configVarying.simple);
658         assertEquals(PACKAGE_NAME, packageName);
659 
660         final String typeName = mResources.getResourceTypeName(R.configVarying.simple);
661         assertEquals(CONFIG_VARYING, typeName);
662     }
663 
testGetStringWithIntParam()664     public void testGetStringWithIntParam() {
665         checkString(R.string.formattedStringNone,
666                 mResources.getString(R.string.formattedStringNone),
667                 "Format[]");
668         checkString(R.string.formattedStringOne,
669                 mResources.getString(R.string.formattedStringOne),
670                 "Format[%d]");
671         checkString(R.string.formattedStringTwo, mResources.getString(R.string.formattedStringTwo),
672                 "Format[%3$d,%2$s]");
673         // Make sure the formatted one works
674         checkString(R.string.formattedStringNone,
675                 mResources.getString(R.string.formattedStringNone),
676                 "Format[]");
677         checkString(R.string.formattedStringOne,
678                 mResources.getString(R.string.formattedStringOne, 42),
679                 "Format[42]");
680         checkString(R.string.formattedStringTwo,
681                 mResources.getString(R.string.formattedStringTwo, "unused", "hi", 43),
682                 "Format[43,hi]");
683     }
684 
checkString(final int resid, final String actual, final String expected)685     private static void checkString(final int resid, final String actual, final String expected) {
686         assertEquals("Expecting string value \"" + expected + "\" got \""
687                 + actual + "\" in resources 0x" + Integer.toHexString(resid),
688                 expected, actual);
689     }
690 
testGetStringArray()691     public void testGetStringArray() {
692         checkStringArray(R.array.strings, new String[] {
693                 "zero", "1", "here"
694         });
695         checkTextArray(R.array.strings, new String[] {
696                 "zero", "1", "here"
697         });
698         checkStringArray(R.array.integers, new String[] {
699                 null, null, null
700         });
701         checkTextArray(R.array.integers, new String[] {
702                 null, null, null
703         });
704     }
705 
checkStringArray(final int resid, final String[] expected)706     private void checkStringArray(final int resid, final String[] expected) {
707         final String[] res = mResources.getStringArray(resid);
708         assertEquals(res.length, expected.length);
709         for (int i = 0; i < expected.length; i++) {
710             checkEntry(resid, i, res[i], expected[i]);
711         }
712     }
713 
checkEntry(final int resid, final int index, final Object res, final Object expected)714     private void checkEntry(final int resid, final int index, final Object res,
715             final Object expected) {
716         assertEquals("in resource 0x" + Integer.toHexString(resid)
717                 + " at index " + index, expected, res);
718     }
719 
checkTextArray(final int resid, final String[] expected)720     private void checkTextArray(final int resid, final String[] expected) {
721         final CharSequence[] res = mResources.getTextArray(resid);
722         assertEquals(res.length, expected.length);
723         for (int i = 0; i < expected.length; i++) {
724             checkEntry(resid, i, res[i], expected[i]);
725         }
726     }
727 
testGetValueWithID()728     public void testGetValueWithID() {
729         tryBoolean(R.bool.trueRes, true);
730         tryBoolean(R.bool.falseRes, false);
731 
732         tryString(R.string.coerceIntegerToString, "100");
733         tryString(R.string.coerceBooleanToString, "true");
734         tryString(R.string.coerceColorToString, "#fff");
735         tryString(R.string.coerceFloatToString, "100.0");
736         tryString(R.string.coerceDimensionToString, "100px");
737         tryString(R.string.coerceFractionToString, "100%");
738     }
739 
tryBoolean(final int resid, final boolean expected)740     private void tryBoolean(final int resid, final boolean expected) {
741         final TypedValue v = new TypedValue();
742         mContext.getResources().getValue(resid, v, true);
743         assertEquals(TypedValue.TYPE_INT_BOOLEAN, v.type);
744         assertEquals("Expecting boolean value " + expected + " got " + v
745                 + " from TypedValue: in resource 0x" + Integer.toHexString(resid),
746                 expected, v.data != 0);
747         assertEquals("Expecting boolean value " + expected + " got " + v
748                 + " from getBoolean(): in resource 0x" + Integer.toHexString(resid),
749                 expected, mContext.getResources().getBoolean(resid));
750     }
751 
tryString(final int resid, final String expected)752     private void tryString(final int resid, final String expected) {
753         final TypedValue v = new TypedValue();
754         mContext.getResources().getValue(resid, v, true);
755         assertEquals(TypedValue.TYPE_STRING, v.type);
756         assertEquals("Expecting string value " + expected + " got " + v
757                 + ": in resource 0x" + Integer.toHexString(resid),
758                 expected, v.string);
759     }
760 
testRawResource()761     public void testRawResource() throws Exception {
762         assertNotNull(mResources.newTheme());
763 
764         InputStream is = mResources.openRawResource(R.raw.text);
765         verifyTextAsset(is);
766 
767         is = mResources.openRawResource(R.raw.text, new TypedValue());
768         verifyTextAsset(is);
769 
770         assertNotNull(mResources.openRawResourceFd(R.raw.text));
771     }
772 
verifyTextAsset(final InputStream is)773     static void verifyTextAsset(final InputStream is) throws IOException {
774         final String expectedString = "OneTwoThreeFourFiveSixSevenEightNineTen";
775         final byte[] buffer = new byte[10];
776 
777         int readCount;
778         int curIndex = 0;
779         while ((readCount = is.read(buffer, 0, buffer.length)) > 0) {
780             for (int i = 0; i < readCount; i++) {
781                 assertEquals("At index " + curIndex
782                             + " expected " + expectedString.charAt(curIndex)
783                             + " but found " + ((char) buffer[i]),
784                         buffer[i], expectedString.charAt(curIndex));
785                 curIndex++;
786             }
787         }
788 
789         readCount = is.read(buffer, 0, buffer.length);
790         assertEquals("Reading end of buffer: expected readCount=-1 but got " + readCount,
791                 -1, readCount);
792 
793         readCount = is.read(buffer, buffer.length, 0);
794         assertEquals("Reading end of buffer length 0: expected readCount=0 but got " + readCount,
795                 0, readCount);
796 
797         is.close();
798     }
799 
testGetFont_invalidResourceId()800     public void testGetFont_invalidResourceId() {
801         try {
802             mResources.getFont(-1);
803             fail("Font resource -1 should not be found.");
804         } catch (NotFoundException e) {
805             //expected
806         }
807     }
808 
testGetFont_fontFile()809     public void testGetFont_fontFile() {
810         Typeface font = mResources.getFont(R.font.sample_regular_font);
811 
812         assertNotNull(font);
813         assertNotSame(Typeface.DEFAULT, font);
814     }
815 
testGetFont_xmlFile()816     public void testGetFont_xmlFile() {
817         Typeface font = mResources.getFont(R.font.samplexmlfont);
818 
819         assertNotNull(font);
820         assertNotSame(Typeface.DEFAULT, font);
821     }
822 
getLargerTypeface(String text, Typeface typeface1, Typeface typeface2)823     private Typeface getLargerTypeface(String text, Typeface typeface1, Typeface typeface2) {
824         Paint p1 = new Paint();
825         p1.setTypeface(typeface1);
826         float width1 = p1.measureText(text);
827         Paint p2 = new Paint();
828         p2.setTypeface(typeface2);
829         float width2 = p2.measureText(text);
830 
831         if (width1 > width2) {
832             return typeface1;
833         } else if (width1 < width2) {
834             return typeface2;
835         } else {
836             fail("The widths of the text should not be the same");
837             return null;
838         }
839     }
840 
testGetFont_xmlFileWithTtc()841     public void testGetFont_xmlFileWithTtc() {
842         // Here we test that building typefaces by indexing in font collections works correctly.
843         // We want to ensure that the built typefaces correspond to the fonts with the right index.
844         // sample_font_collection.ttc contains two fonts (with indices 0 and 1). The first one has
845         // glyph "a" of 3em width, and all the other glyphs 1em. The second one has glyph "b" of
846         // 3em width, and all the other glyphs 1em. Hence, we can compare the width of these
847         // glyphs to assert that ttc indexing works.
848         Typeface normalFont = mResources.getFont(R.font.sample_ttc_family);
849         assertNotNull(normalFont);
850         Typeface italicFont = Typeface.create(normalFont, Typeface.ITALIC);
851         assertNotNull(italicFont);
852 
853         assertEquals(getLargerTypeface("a", normalFont, italicFont), normalFont);
854         assertEquals(getLargerTypeface("b", normalFont, italicFont), italicFont);
855     }
856 
testGetFont_xmlFileWithVariationSettings()857     public void testGetFont_xmlFileWithVariationSettings() {
858         // Here we test that specifying variation settings for fonts in XMLs works.
859         // We build typefaces from two families containing one font each, using the same font
860         // resource, but having different values for the 'wdth' tag. Then we measure the painted
861         // text to ensure that the tag affects the text width. The font resource used supports
862         // the 'wdth' axis for the dash (-) character.
863         Typeface typeface1 = mResources.getFont(R.font.sample_variation_settings_family1);
864         assertNotNull(typeface1);
865         Typeface typeface2 = mResources.getFont(R.font.sample_variation_settings_family2);
866         assertNotNull(typeface2);
867 
868         assertNotSame(typeface1, typeface2);
869         assertEquals(getLargerTypeface("-", typeface1, typeface2), typeface2);
870     }
871 
testGetFont_invalidXmlFile()872     public void testGetFont_invalidXmlFile() {
873         try {
874             assertNull(mResources.getFont(R.font.invalid_xmlfamily));
875         } catch (NotFoundException e) {
876             // pass
877         }
878 
879         try {
880             assertNull(mResources.getFont(R.font.invalid_xmlempty));
881         } catch (NotFoundException e) {
882             // pass
883         }
884     }
885 
testGetFont_invalidFontFiles()886     public void testGetFont_invalidFontFiles() {
887         try {
888             mResources.getFont(R.font.invalid_xmlfont);
889             fail();
890         } catch (RuntimeException e) {
891             // pass
892         }
893 
894         try {
895             mResources.getFont(R.font.invalid_font);
896             fail();
897         } catch (RuntimeException e) {
898             // pass
899         }
900 
901         try {
902             mResources.getFont(R.font.invalid_xmlfont_contains_invalid_font_file);
903             fail();
904         } catch (RuntimeException e) {
905             // pass
906         }
907 
908         try {
909             mResources.getFont(R.font.invalid_xmlfont_nosource);
910             fail();
911         } catch (RuntimeException e) {
912             // pass
913         }
914 
915     }
916 
testGetFont_brokenFontFiles()917     public void testGetFont_brokenFontFiles() {
918         try {
919             mResources.getFont(R.font.brokenfont);
920             fail();
921         } catch (RuntimeException e) {
922             // pass
923         }
924 
925         try {
926             mResources.getFont(R.font.broken_xmlfont);
927             fail();
928         } catch (RuntimeException e) {
929             // pass
930         }
931     }
932 
testGetFont_fontFileIsCached()933     public void testGetFont_fontFileIsCached() {
934         Typeface font = mResources.getFont(R.font.sample_regular_font);
935         Typeface font2 = mResources.getFont(R.font.sample_regular_font);
936 
937         assertEquals(font, font2);
938     }
939 
testGetFont_xmlFileIsCached()940     public void testGetFont_xmlFileIsCached() {
941         Typeface font = mResources.getFont(R.font.samplexmlfont);
942         Typeface font2 = mResources.getFont(R.font.samplexmlfont);
943 
944         assertEquals(font, font2);
945     }
946 
testGetFont_resolveByFontTable()947     public void testGetFont_resolveByFontTable() {
948         assertEquals(Typeface.NORMAL, mResources.getFont(R.font.sample_regular_font).getStyle());
949         assertEquals(Typeface.BOLD, mResources.getFont(R.font.sample_bold_font).getStyle());
950         assertEquals(Typeface.ITALIC, mResources.getFont(R.font.sample_italic_font).getStyle());
951         assertEquals(Typeface.BOLD_ITALIC,
952                 mResources.getFont(R.font.sample_bolditalic_font).getStyle());
953 
954         assertEquals(Typeface.NORMAL, mResources.getFont(R.font.sample_regular_family).getStyle());
955         assertEquals(Typeface.BOLD, mResources.getFont(R.font.sample_bold_family).getStyle());
956         assertEquals(Typeface.ITALIC, mResources.getFont(R.font.sample_italic_family).getStyle());
957         assertEquals(Typeface.BOLD_ITALIC,
958                 mResources.getFont(R.font.sample_bolditalic_family).getStyle());
959     }
960 
961     // TODO Figure out why it fails in the instant mode.
962     @AppModeFull
testComplextColorDrawableAttrInflation()963     public void testComplextColorDrawableAttrInflation() {
964         Context context = InstrumentationRegistry.getTargetContext();
965         LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(
966                 Context.LAYOUT_INFLATER_SERVICE);
967 
968         View view = layoutInflater.inflate(R.layout.complex_color_drawable_attr_layout, null);
969         assertTrue(view.getBackground() instanceof ColorStateListDrawable);
970     }
971 
testGetAttributeSetSourceResId()972     public void testGetAttributeSetSourceResId() {
973         assertEquals(Resources.ID_NULL, Resources.getAttributeSetSourceResId(null));
974 
975         XmlPullParser test_color_parser = mResources.getXml(R.xml.test_color);
976         AttributeSet test_color_set = Xml.asAttributeSet(test_color_parser);
977         assertEquals(R.xml.test_color, Resources.getAttributeSetSourceResId(test_color_set));
978 
979         XmlPullParser colors_parser = mResources.getXml(R.xml.colors);
980         AttributeSet colors_set = Xml.asAttributeSet(colors_parser);
981         assertEquals(R.xml.colors, Resources.getAttributeSetSourceResId(colors_set));
982 
983         XmlPullParser content_layout_parser = mResources.getLayout(R.layout.context_layout);
984         AttributeSet content_layout_set = Xml.asAttributeSet(content_layout_parser);
985         assertEquals(R.layout.context_layout,
986                 Resources.getAttributeSetSourceResId(content_layout_set));
987 
988         XmlPullParser anim_rotate_parser = mResources.getAnimation(R.anim.anim_rotate);
989         AttributeSet anim_rotate_set = Xml.asAttributeSet(anim_rotate_parser);
990         assertEquals(R.anim.anim_rotate, Resources.getAttributeSetSourceResId(anim_rotate_set));
991     }
992 }
993