1/*
2 * Copyright (C) 2014 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
17package android.content.res;
18
19import android.test.ActivityInstrumentationTestCase2;
20import android.util.TypedValue;
21
22import com.android.frameworks.coretests.R;
23
24import java.lang.reflect.InvocationTargetException;
25import java.lang.reflect.Method;
26
27public class ConfigurationBoundResourceCacheTest
28        extends ActivityInstrumentationTestCase2<ResourceCacheActivity> {
29
30    ConfigurationBoundResourceCache<Float> mCache;
31
32    Method mCalcConfigChanges;
33
34    public ConfigurationBoundResourceCacheTest() {
35        super(ResourceCacheActivity.class);
36    }
37
38    @Override
39    protected void setUp() throws Exception {
40        super.setUp();
41        mCache = new ConfigurationBoundResourceCache<Float>(getActivity().getResources());
42    }
43
44    public void testGetEmpty() {
45        assertNull(mCache.get(-1, null));
46    }
47
48    public void testSetGet() {
49        mCache.put(1, null, new DummyFloatConstantState(5f));
50        assertEquals(5f, mCache.get(1, null));
51        assertNotSame(5f, mCache.get(1, null));
52        assertEquals(null, mCache.get(1, getActivity().getTheme()));
53    }
54
55    public void testSetGetThemed() {
56        mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f));
57        assertEquals(null, mCache.get(1, null));
58        assertEquals(5f, mCache.get(1, getActivity().getTheme()));
59        assertNotSame(5f, mCache.get(1, getActivity().getTheme()));
60    }
61
62    public void testMultiThreadPutGet() {
63        mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f));
64        mCache.put(1, null, new DummyFloatConstantState(10f));
65        assertEquals(10f, mCache.get(1, null));
66        assertNotSame(10f, mCache.get(1, null));
67        assertEquals(5f, mCache.get(1, getActivity().getTheme()));
68        assertNotSame(5f, mCache.get(1, getActivity().getTheme()));
69    }
70
71    public void testVoidConfigChange()
72            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
73        TypedValue staticValue = new TypedValue();
74        long key = 3L;
75        final Resources res = getActivity().getResources();
76        res.getValue(R.dimen.resource_cache_test_generic, staticValue, true);
77        float staticDim = TypedValue.complexToDimension(staticValue.data, res.getDisplayMetrics());
78        mCache.put(key, getActivity().getTheme(),
79                new DummyFloatConstantState(staticDim, staticValue.changingConfigurations));
80        final Configuration cfg = res.getConfiguration();
81        Configuration newCnf = new Configuration(cfg);
82        newCnf.orientation = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE ?
83                Configuration.ORIENTATION_PORTRAIT
84                : Configuration.ORIENTATION_LANDSCAPE;
85        int changes = calcConfigChanges(res, newCnf);
86        assertEquals(staticDim, mCache.get(key, getActivity().getTheme()));
87        mCache.onConfigurationChange(changes);
88        assertEquals(staticDim, mCache.get(key, getActivity().getTheme()));
89    }
90
91    public void testEffectiveConfigChange()
92            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
93        TypedValue changingValue = new TypedValue();
94        long key = 4L;
95        final Resources res = getActivity().getResources();
96        res.getValue(R.dimen.resource_cache_test_orientation_dependent, changingValue, true);
97        float changingDim = TypedValue.complexToDimension(changingValue.data,
98                res.getDisplayMetrics());
99        mCache.put(key, getActivity().getTheme(),
100                new DummyFloatConstantState(changingDim, changingValue.changingConfigurations));
101
102        final Configuration cfg = res.getConfiguration();
103        Configuration newCnf = new Configuration(cfg);
104        newCnf.orientation = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE ?
105                Configuration.ORIENTATION_PORTRAIT
106                : Configuration.ORIENTATION_LANDSCAPE;
107        int changes = calcConfigChanges(res, newCnf);
108        assertEquals(changingDim, mCache.get(key, getActivity().getTheme()));
109        mCache.onConfigurationChange(changes);
110        assertNull(mCache.get(key, getActivity().getTheme()));
111    }
112
113    public void testConfigChangeMultipleResources()
114            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
115        TypedValue staticValue = new TypedValue();
116        TypedValue changingValue = new TypedValue();
117        final Resources res = getActivity().getResources();
118        res.getValue(R.dimen.resource_cache_test_generic, staticValue, true);
119        res.getValue(R.dimen.resource_cache_test_orientation_dependent, changingValue, true);
120        float staticDim = TypedValue.complexToDimension(staticValue.data, res.getDisplayMetrics());
121        float changingDim = TypedValue.complexToDimension(changingValue.data,
122                res.getDisplayMetrics());
123        mCache.put(R.dimen.resource_cache_test_generic, getActivity().getTheme(),
124                new DummyFloatConstantState(staticDim, staticValue.changingConfigurations));
125        mCache.put(R.dimen.resource_cache_test_orientation_dependent, getActivity().getTheme(),
126                new DummyFloatConstantState(changingDim, changingValue.changingConfigurations));
127        final Configuration cfg = res.getConfiguration();
128        Configuration newCnf = new Configuration(cfg);
129        newCnf.orientation = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE ?
130                Configuration.ORIENTATION_PORTRAIT
131                : Configuration.ORIENTATION_LANDSCAPE;
132        int changes = calcConfigChanges(res, newCnf);
133        assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic,
134                getActivity().getTheme()));
135        assertEquals(changingDim, mCache.get(R.dimen.resource_cache_test_orientation_dependent,
136                getActivity().getTheme()));
137        mCache.onConfigurationChange(changes);
138        assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic,
139                getActivity().getTheme()));
140        assertNull(mCache.get(R.dimen.resource_cache_test_orientation_dependent,
141                getActivity().getTheme()));
142    }
143
144    public void testConfigChangeMultipleThemes()
145            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
146        TypedValue[] staticValues = new TypedValue[]{new TypedValue(), new TypedValue()};
147        TypedValue[] changingValues = new TypedValue[]{new TypedValue(), new TypedValue()};
148        float staticDim = 0;
149        float changingDim = 0;
150        final Resources res = getActivity().getResources();
151        for (int i = 0; i < 2; i++) {
152            res.getValue(R.dimen.resource_cache_test_generic, staticValues[i], true);
153            staticDim = TypedValue
154                    .complexToDimension(staticValues[i].data, res.getDisplayMetrics());
155
156            res.getValue(R.dimen.resource_cache_test_orientation_dependent, changingValues[i],
157                    true);
158            changingDim = TypedValue.complexToDimension(changingValues[i].data,
159                    res.getDisplayMetrics());
160            final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
161            mCache.put(R.dimen.resource_cache_test_generic, theme,
162                    new DummyFloatConstantState(staticDim, staticValues[i].changingConfigurations));
163            mCache.put(R.dimen.resource_cache_test_orientation_dependent, theme,
164                    new DummyFloatConstantState(changingDim,
165                            changingValues[i].changingConfigurations));
166        }
167        final Configuration cfg = res.getConfiguration();
168        Configuration newCnf = new Configuration(cfg);
169        newCnf.orientation = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE ?
170                Configuration.ORIENTATION_PORTRAIT
171                : Configuration.ORIENTATION_LANDSCAPE;
172        int changes = calcConfigChanges(res, newCnf);
173        for (int i = 0; i < 2; i++) {
174            final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
175            assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic, theme));
176            assertEquals(changingDim,
177                    mCache.get(R.dimen.resource_cache_test_orientation_dependent, theme));
178        }
179        mCache.onConfigurationChange(changes);
180        for (int i = 0; i < 2; i++) {
181            final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
182            assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic, theme));
183            assertNull(mCache.get(R.dimen.resource_cache_test_orientation_dependent, theme));
184        }
185    }
186
187    private int calcConfigChanges(Resources resources, Configuration configuration)
188            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
189        if (mCalcConfigChanges == null) {
190            mCalcConfigChanges = Resources.class.getDeclaredMethod("calcConfigChanges",
191                    Configuration.class);
192            mCalcConfigChanges.setAccessible(true);
193        }
194        return (Integer) mCalcConfigChanges.invoke(resources, configuration);
195
196    }
197
198    static class DummyFloatConstantState extends
199            ConstantState<Float> {
200
201        final Float mObj;
202
203        int mChangingConf = 0;
204
205        DummyFloatConstantState(Float obj) {
206            mObj = obj;
207        }
208
209        DummyFloatConstantState(Float obj, int changingConf) {
210            mObj = obj;
211            mChangingConf = changingConf;
212        }
213
214        @Override
215        public int getChangingConfigurations() {
216            return mChangingConf;
217        }
218
219        @Override
220        public Float newInstance() {
221            return new Float(mObj);
222        }
223    }
224}
225