1/*
2 * Copyright (C) 2015 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 */
16package android.support.v4.content.res;
17
18import android.content.res.ColorStateList;
19import android.content.res.Resources;
20import android.graphics.drawable.Drawable;
21import android.os.Build;
22import android.support.compat.test.R;
23import android.support.test.InstrumentationRegistry;
24import android.support.v4.testutils.TestUtils;
25import android.test.suitebuilder.annotation.SmallTest;
26import android.util.DisplayMetrics;
27import org.junit.Before;
28import org.junit.Test;
29
30import static org.junit.Assert.assertEquals;
31
32@SmallTest
33public class ResourcesCompatTest {
34    private Resources mResources;
35
36    @Before
37    public void setup() {
38        mResources = InstrumentationRegistry.getContext().getResources();
39    }
40
41    @Test
42    public void testGetColor() throws Throwable {
43        assertEquals("Unthemed color load",
44                ResourcesCompat.getColor(mResources, R.color.text_color, null),
45                0xFFFF8090);
46
47        if (Build.VERSION.SDK_INT >= 23) {
48            // The following tests are only expected to pass on v23+ devices. The result of
49            // calling theme-aware getColor() in pre-v23 is undefined.
50            final Resources.Theme yellowTheme = mResources.newTheme();
51            yellowTheme.applyStyle(R.style.YellowTheme, true);
52            assertEquals("Themed yellow color load", 0xFFF0B000,
53                    ResourcesCompat.getColor(mResources, R.color.simple_themed_selector,
54                            yellowTheme));
55
56            final Resources.Theme lilacTheme = mResources.newTheme();
57            lilacTheme.applyStyle(R.style.LilacTheme, true);
58            assertEquals("Themed lilac color load", 0xFFF080F0,
59                    ResourcesCompat.getColor(mResources, R.color.simple_themed_selector,
60                            lilacTheme));
61        }
62    }
63
64    @Test
65    public void testGetColorStateList() throws Throwable {
66        final ColorStateList unthemedColorStateList =
67                ResourcesCompat.getColorStateList(mResources, R.color.complex_unthemed_selector,
68                        null);
69        assertEquals("Unthemed color state list load: default", 0xFF70A0C0,
70                unthemedColorStateList.getDefaultColor());
71        assertEquals("Unthemed color state list load: focused", 0xFF70B0F0,
72                unthemedColorStateList.getColorForState(
73                        new int[]{android.R.attr.state_focused}, 0));
74        assertEquals("Unthemed color state list load: pressed", 0xFF6080B0,
75                unthemedColorStateList.getColorForState(
76                        new int[]{android.R.attr.state_pressed}, 0));
77
78        if (Build.VERSION.SDK_INT >= 23) {
79            // The following tests are only expected to pass on v23+ devices. The result of
80            // calling theme-aware getColorStateList() in pre-v23 is undefined.
81            final Resources.Theme yellowTheme = mResources.newTheme();
82            yellowTheme.applyStyle(R.style.YellowTheme, true);
83            final ColorStateList themedYellowColorStateList =
84                    ResourcesCompat.getColorStateList(mResources, R.color.complex_themed_selector,
85                            yellowTheme);
86            assertEquals("Themed yellow color state list load: default", 0xFFF0B000,
87                    themedYellowColorStateList.getDefaultColor());
88            assertEquals("Themed yellow color state list load: focused", 0xFFF0A020,
89                    themedYellowColorStateList.getColorForState(
90                            new int[]{android.R.attr.state_focused}, 0));
91            assertEquals("Themed yellow color state list load: pressed", 0xFFE0A040,
92                    themedYellowColorStateList.getColorForState(
93                            new int[]{android.R.attr.state_pressed}, 0));
94
95            final Resources.Theme lilacTheme = mResources.newTheme();
96            lilacTheme.applyStyle(R.style.LilacTheme, true);
97            final ColorStateList themedLilacColorStateList =
98                    ResourcesCompat.getColorStateList(mResources, R.color.complex_themed_selector,
99                            lilacTheme);
100            assertEquals("Themed lilac color state list load: default", 0xFFF080F0,
101                    themedLilacColorStateList.getDefaultColor());
102            assertEquals("Themed lilac color state list load: focused", 0xFFF070D0,
103                    themedLilacColorStateList.getColorForState(
104                            new int[]{android.R.attr.state_focused}, 0));
105            assertEquals("Themed lilac color state list load: pressed", 0xFFE070A0,
106                    themedLilacColorStateList.getColorForState(
107                            new int[]{android.R.attr.state_pressed}, 0));
108        }
109    }
110
111    @Test
112    public void testGetDrawable() throws Throwable {
113        final Drawable unthemedDrawable =
114                ResourcesCompat.getDrawable(mResources, R.drawable.test_drawable_red, null);
115        TestUtils.assertAllPixelsOfColor("Unthemed drawable load",
116                unthemedDrawable, mResources.getColor(R.color.test_red));
117
118        if (Build.VERSION.SDK_INT >= 23) {
119            // The following tests are only expected to pass on v23+ devices. The result of
120            // calling theme-aware getDrawable() in pre-v23 is undefined.
121            final Resources.Theme yellowTheme = mResources.newTheme();
122            yellowTheme.applyStyle(R.style.YellowTheme, true);
123            final Drawable themedYellowDrawable =
124                    ResourcesCompat.getDrawable(mResources, R.drawable.themed_drawable,
125                            yellowTheme);
126            TestUtils.assertAllPixelsOfColor("Themed yellow drawable load",
127                    themedYellowDrawable, 0xFFF0B000);
128
129            final Resources.Theme lilacTheme = mResources.newTheme();
130            lilacTheme.applyStyle(R.style.LilacTheme, true);
131            final Drawable themedLilacDrawable =
132                    ResourcesCompat.getDrawable(mResources, R.drawable.themed_drawable, lilacTheme);
133            TestUtils.assertAllPixelsOfColor("Themed lilac drawable load",
134                    themedLilacDrawable, 0xFFF080F0);
135        }
136    }
137
138    @Test
139    public void testGetDrawableForDensityUnthemed() throws Throwable {
140        // Density-aware drawable loading for now only works on raw bitmap drawables.
141
142        // Different variants of density_aware_drawable are set up in the following way:
143        //    mdpi - 12x12 px which is 12x12 dip
144        //    hdpi - 21x21 px which is 14x14 dip
145        //   xhdpi - 32x32 px which is 16x16 dip
146        //  xxhdpi - 54x54 px which is 18x18 dip
147        // The tests below (on v15+ devices) are checking that an unthemed density-aware
148        // loading of raw bitmap drawables returns a drawable with matching intrinsic
149        // dimensions.
150
151        final Drawable unthemedDrawableForMediumDensity =
152                ResourcesCompat.getDrawableForDensity(mResources, R.drawable.density_aware_drawable,
153                        DisplayMetrics.DENSITY_MEDIUM, null);
154        // For pre-v15 devices we should get a drawable that corresponds to the density of the
155        // current device. For v15+ devices we should get a drawable that corresponds to the
156        // density requested in the API call.
157        final int expectedSizeForMediumDensity = (Build.VERSION.SDK_INT < 15) ?
158                mResources.getDimensionPixelSize(R.dimen.density_aware_size) : 12;
159        assertEquals("Unthemed density-aware drawable load: medium width",
160                expectedSizeForMediumDensity, unthemedDrawableForMediumDensity.getIntrinsicWidth());
161        assertEquals("Unthemed density-aware drawable load: medium height",
162                expectedSizeForMediumDensity,
163                unthemedDrawableForMediumDensity.getIntrinsicHeight());
164
165        final Drawable unthemedDrawableForHighDensity =
166                ResourcesCompat.getDrawableForDensity(mResources, R.drawable.density_aware_drawable,
167                        DisplayMetrics.DENSITY_HIGH, null);
168        // For pre-v15 devices we should get a drawable that corresponds to the density of the
169        // current device. For v15+ devices we should get a drawable that corresponds to the
170        // density requested in the API call.
171        final int expectedSizeForHighDensity = (Build.VERSION.SDK_INT < 15) ?
172                mResources.getDimensionPixelSize(R.dimen.density_aware_size) : 21;
173        assertEquals("Unthemed density-aware drawable load: high width",
174                expectedSizeForHighDensity, unthemedDrawableForHighDensity.getIntrinsicWidth());
175        assertEquals("Unthemed density-aware drawable load: high height",
176                expectedSizeForHighDensity, unthemedDrawableForHighDensity.getIntrinsicHeight());
177
178        final Drawable unthemedDrawableForXHighDensity =
179                ResourcesCompat.getDrawableForDensity(mResources, R.drawable.density_aware_drawable,
180                        DisplayMetrics.DENSITY_XHIGH, null);
181        // For pre-v15 devices we should get a drawable that corresponds to the density of the
182        // current device. For v15+ devices we should get a drawable that corresponds to the
183        // density requested in the API call.
184        final int expectedSizeForXHighDensity = (Build.VERSION.SDK_INT < 15) ?
185                mResources.getDimensionPixelSize(R.dimen.density_aware_size) : 32;
186        assertEquals("Unthemed density-aware drawable load: xhigh width",
187                expectedSizeForXHighDensity, unthemedDrawableForXHighDensity.getIntrinsicWidth());
188        assertEquals("Unthemed density-aware drawable load: xhigh height",
189                expectedSizeForXHighDensity, unthemedDrawableForXHighDensity.getIntrinsicHeight());
190
191        final Drawable unthemedDrawableForXXHighDensity =
192                ResourcesCompat.getDrawableForDensity(mResources, R.drawable.density_aware_drawable,
193                        DisplayMetrics.DENSITY_XXHIGH, null);
194        // For pre-v15 devices we should get a drawable that corresponds to the density of the
195        // current device. For v15+ devices we should get a drawable that corresponds to the
196        // density requested in the API call.
197        final int expectedSizeForXXHighDensity = (Build.VERSION.SDK_INT < 15) ?
198                mResources.getDimensionPixelSize(R.dimen.density_aware_size) : 54;
199        assertEquals("Unthemed density-aware drawable load: xxhigh width",
200                expectedSizeForXXHighDensity, unthemedDrawableForXXHighDensity.getIntrinsicWidth());
201        assertEquals("Unthemed density-aware drawable load: xxhigh height",
202                expectedSizeForXXHighDensity,
203                unthemedDrawableForXXHighDensity.getIntrinsicHeight());
204    }
205
206    @Test
207    public void testGetDrawableForDensityThemed() throws Throwable {
208        if (Build.VERSION.SDK_INT < 21) {
209            // The following tests are only expected to pass on v21+ devices. The result of
210            // calling theme-aware getDrawableForDensity() in pre-v21 is undefined.
211            return;
212        }
213
214        // Density- and theme-aware drawable loading for now only works partially. This test
215        // checks only for theming of a tinted bitmap XML drawable, but not correct scaling.
216
217        // Set up the two test themes, yellow and lilac.
218        final Resources.Theme yellowTheme = mResources.newTheme();
219        yellowTheme.applyStyle(R.style.YellowTheme, true);
220
221        final Resources.Theme lilacTheme = mResources.newTheme();
222        lilacTheme.applyStyle(R.style.LilacTheme, true);
223
224        Drawable themedYellowDrawableForMediumDensity =
225                ResourcesCompat.getDrawableForDensity(mResources, R.drawable.themed_bitmap,
226                        DisplayMetrics.DENSITY_MEDIUM, yellowTheme);
227        // We should get a drawable that corresponds to the theme requested in the API call.
228        TestUtils.assertAllPixelsOfColor("Themed yellow density-aware drawable load : medium color",
229                themedYellowDrawableForMediumDensity, 0xFFF0B000);
230
231        Drawable themedLilacDrawableForMediumDensity =
232                ResourcesCompat.getDrawableForDensity(mResources, R.drawable.themed_bitmap,
233                        DisplayMetrics.DENSITY_MEDIUM, lilacTheme);
234        // We should get a drawable that corresponds to the theme requested in the API call.
235        TestUtils.assertAllPixelsOfColor("Themed lilac density-aware drawable load : medium color",
236                themedLilacDrawableForMediumDensity, 0xFFF080F0);
237
238        Drawable themedYellowDrawableForHighDensity =
239                ResourcesCompat.getDrawableForDensity(mResources, R.drawable.themed_bitmap,
240                        DisplayMetrics.DENSITY_HIGH, yellowTheme);
241        // We should get a drawable that corresponds to the theme requested in the API call.
242        TestUtils.assertAllPixelsOfColor("Themed yellow density-aware drawable load : high color",
243                themedYellowDrawableForHighDensity, 0xFFF0B000);
244
245        Drawable themedLilacDrawableForHighDensity =
246                ResourcesCompat.getDrawableForDensity(mResources, R.drawable.themed_bitmap,
247                        DisplayMetrics.DENSITY_HIGH, lilacTheme);
248        // We should get a drawable that corresponds to the theme requested in the API call.
249        TestUtils.assertAllPixelsOfColor("Themed lilac density-aware drawable load : high color",
250                themedLilacDrawableForHighDensity, 0xFFF080F0);
251
252        Drawable themedYellowDrawableForXHighDensity =
253                ResourcesCompat.getDrawableForDensity(mResources, R.drawable.themed_bitmap,
254                        DisplayMetrics.DENSITY_XHIGH, yellowTheme);
255        // We should get a drawable that corresponds to the theme requested in the API call.
256        TestUtils.assertAllPixelsOfColor("Themed yellow density-aware drawable load : xhigh color",
257                themedYellowDrawableForXHighDensity, 0xFFF0B000);
258
259        Drawable themedLilacDrawableForXHighDensity =
260                ResourcesCompat.getDrawableForDensity(mResources, R.drawable.themed_bitmap,
261                        DisplayMetrics.DENSITY_XHIGH, lilacTheme);
262        // We should get a drawable that corresponds to the theme requested in the API call.
263        TestUtils.assertAllPixelsOfColor("Themed lilac density-aware drawable load : xhigh color",
264                themedLilacDrawableForXHighDensity, 0xFFF080F0);
265
266        Drawable themedYellowDrawableForXXHighDensity =
267                ResourcesCompat.getDrawableForDensity(mResources, R.drawable.themed_bitmap,
268                        DisplayMetrics.DENSITY_XXHIGH, yellowTheme);
269        // We should get a drawable that corresponds to the theme requested in the API call.
270        TestUtils.assertAllPixelsOfColor("Themed yellow density-aware drawable load : xxhigh color",
271                themedYellowDrawableForXXHighDensity, 0xFFF0B000);
272
273        Drawable themedLilacDrawableForXXHighDensity =
274                ResourcesCompat.getDrawableForDensity(mResources, R.drawable.themed_bitmap,
275                        DisplayMetrics.DENSITY_XXHIGH, lilacTheme);
276        // We should get a drawable that corresponds to the theme requested in the API call.
277        TestUtils.assertAllPixelsOfColor("Themed lilac density-aware drawable load : xxhigh color",
278                themedLilacDrawableForXXHighDensity, 0xFFF080F0);
279    }
280}
281