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  *      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 package android.graphics.drawable.cts;
17 
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNotEquals;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertTrue;
24 
25 import android.R;
26 import android.content.res.ColorStateList;
27 import android.graphics.Bitmap;
28 import android.graphics.Canvas;
29 import android.graphics.Color;
30 import android.graphics.ColorFilter;
31 import android.graphics.LightingColorFilter;
32 import android.graphics.PixelFormat;
33 import android.graphics.drawable.ColorDrawable;
34 import android.graphics.drawable.ColorStateListDrawable;
35 import android.graphics.drawable.Drawable;
36 import android.os.SystemClock;
37 
38 import androidx.test.filters.SmallTest;
39 import androidx.test.runner.AndroidJUnit4;
40 
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 
45 @SmallTest
46 @RunWith(AndroidJUnit4.class)
47 public class ColorStateListDrawableTest {
48     private ColorStateList mColorStateList;
49     private ColorStateListDrawable mDrawable;
50     private static final int[] STATE_RED = new int[]{1};
51     private static final int[] STATE_BLUE = new int[]{2};
52 
53     @Before
setup()54     public void setup() {
55         final int[][] state = new int[][]{STATE_RED, STATE_BLUE};
56         final int[] colors = new int[]{Color.RED, Color.BLUE};
57         mColorStateList = new ColorStateList(state, colors);
58         mDrawable = new ColorStateListDrawable(mColorStateList);
59     }
60 
61     @Test
testDefaultConstructor()62     public void testDefaultConstructor() {
63         ColorStateListDrawable drawable = new ColorStateListDrawable();
64         assertFalse(drawable.isStateful());
65         assertEquals(
66                 drawable.getColorStateList().getDefaultColor(),
67                 new ColorDrawable().getColor());
68     }
69 
70     @Test
testDraw()71     public void testDraw() {
72         Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
73 
74         try {
75             Canvas canvas = new Canvas(bitmap);
76             mDrawable.setBounds(0, 0, 1, 1);
77 
78             mDrawable.setState(STATE_RED);
79             mDrawable.draw(canvas);
80             assertEquals(Color.RED, bitmap.getPixel(0, 0));
81 
82             mDrawable.setState(STATE_BLUE);
83             mDrawable.draw(canvas);
84             assertEquals(Color.BLUE, bitmap.getPixel(0, 0));
85         } finally {
86             bitmap.recycle();
87         }
88     }
89 
90     @Test
testGetCurrent()91     public void testGetCurrent() {
92         assertTrue(mDrawable.getCurrent() instanceof ColorDrawable);
93     }
94 
95     @Test
testIsStateful()96     public void testIsStateful() {
97         assertTrue(mDrawable.isStateful());
98         mDrawable.setColorStateList(ColorStateList.valueOf(Color.GREEN));
99         assertFalse(mDrawable.isStateful());
100     }
101 
102     @Test
testHasFocusStateSpecified()103     public void testHasFocusStateSpecified() {
104         assertFalse(mDrawable.hasFocusStateSpecified());
105         final int[][] state = new int[][]{new int[]{1}, new int[]{2, R.attr.state_focused}};
106         final int[] colors = new int[]{Color.MAGENTA, Color.CYAN};
107         mDrawable.setColorStateList(new ColorStateList(state, colors));
108         assertTrue(mDrawable.hasFocusStateSpecified());
109     }
110 
111     @Test
testAlpha()112     public void testAlpha() {
113         int transBlue = (Color.BLUE & 0xFFFFFF) | 127 << 24;
114         mDrawable.setColorStateList(ColorStateList.valueOf(transBlue));
115         assertEquals(mDrawable.getOpacity(), PixelFormat.TRANSLUCENT);
116         assertEquals(mDrawable.getAlpha(), 127);
117 
118         mDrawable.setAlpha(0);
119         assertEquals(mDrawable.getOpacity(), PixelFormat.TRANSPARENT);
120         assertEquals(mDrawable.getAlpha(), 0);
121         assertEquals(mDrawable.getColorStateList().getDefaultColor(), transBlue);
122 
123         mDrawable.setAlpha(255);
124         assertEquals(mDrawable.getOpacity(), PixelFormat.OPAQUE);
125         assertEquals(mDrawable.getAlpha(), 255);
126         assertEquals(mDrawable.getColorStateList().getDefaultColor(), transBlue);
127 
128         mDrawable.clearAlpha();
129         assertEquals(mDrawable.getAlpha(), 127);
130     }
131 
132     @Test
testColorFilter()133     public void testColorFilter() {
134         final ColorDrawable colorDrawable = (ColorDrawable) mDrawable.getCurrent();
135         final ColorFilter colorFilter = new LightingColorFilter(Color.GRAY, Color.GREEN);
136 
137         assertNull(mDrawable.getColorFilter());
138         mDrawable.setColorFilter(colorFilter);
139         assertEquals(colorFilter, mDrawable.getColorFilter());
140     }
141 
142     @Test
testColorStateListAccess()143     public void testColorStateListAccess() {
144         final ColorStateListDrawable cslDrawable = new ColorStateListDrawable();
145         final ColorDrawable colorDrawable = (ColorDrawable) cslDrawable.getCurrent();
146         assertNotNull(cslDrawable.getColorStateList());
147         assertEquals(
148                 colorDrawable.getColor(),
149                 cslDrawable
150                         .getColorStateList()
151                         .getColorForState(cslDrawable.getState(), Color.YELLOW));
152 
153         cslDrawable.setColorStateList(mColorStateList);
154         assertEquals(mColorStateList, cslDrawable.getColorStateList());
155     }
156 
157     @Test
testSetState()158     public void testSetState() {
159         ColorDrawable colorDrawable = (ColorDrawable) mDrawable.getCurrent();
160         assertEquals(colorDrawable.getColor(), mColorStateList.getDefaultColor());
161         mDrawable.setState(STATE_BLUE);
162         assertEquals(colorDrawable.getColor(), Color.BLUE);
163         mDrawable.setState(STATE_RED);
164         assertEquals(colorDrawable.getColor(), Color.RED);
165     }
166 
167     @Test
testMutate()168     public void testMutate() {
169         Drawable.ConstantState oldState = mDrawable.getConstantState();
170         assertEquals(mDrawable.mutate(), mDrawable);
171         assertNotEquals(mDrawable.getConstantState(), oldState);
172     }
173 
174     @Test
testInvalidationCallbackProxy()175     public void testInvalidationCallbackProxy() {
176         final TestCallback callback = new TestCallback();
177         mDrawable.setCallback(callback);
178 
179         callback.mInvalidatedDrawable = null;
180         mDrawable.invalidateSelf();
181         assertEquals(mDrawable, callback.mInvalidatedDrawable);
182 
183         callback.mInvalidatedDrawable = null;
184         mDrawable.getCurrent().invalidateSelf();
185         assertEquals(mDrawable, callback.mInvalidatedDrawable);
186     }
187 
188     @Test
testScheduleCallbackProxy()189     public void testScheduleCallbackProxy() {
190         final Runnable runnable = new NoOpRunnable();
191         final long scheduledTime = SystemClock.uptimeMillis() + 100;
192         final TestCallback callback = new TestCallback();
193         mDrawable.setCallback(callback);
194 
195         mDrawable.getCurrent().scheduleSelf(runnable, scheduledTime);
196         assertEquals(mDrawable, callback.mScheduledDrawable);
197         assertEquals(runnable, callback.mScheduledRunnable);
198         assertEquals(scheduledTime, callback.mScheduledTime);
199     }
200 
201     @Test
testUnscheduleCallbackProxy()202     public void testUnscheduleCallbackProxy() {
203         final Runnable runnable = new NoOpRunnable();
204         final TestCallback callback = new TestCallback();
205         mDrawable.setCallback(callback);
206 
207         mDrawable.getCurrent().unscheduleSelf(runnable);
208 
209         assertEquals(mDrawable, callback.mUnscheduledDrawable);
210         assertEquals(runnable, callback.mUnscheduledRunnable);
211     }
212 
213     private final class TestCallback implements Drawable.Callback {
214         private Drawable mInvalidatedDrawable;
215         private Drawable mScheduledDrawable;
216         private Drawable mUnscheduledDrawable;
217 
218         private Runnable mScheduledRunnable;
219         private Runnable mUnscheduledRunnable;
220 
221         private long mScheduledTime;
222 
223         @Override
invalidateDrawable(Drawable who)224         public void invalidateDrawable(Drawable who) {
225             mInvalidatedDrawable = who;
226         }
227 
228         @Override
scheduleDrawable(Drawable who, Runnable what, long when)229         public void scheduleDrawable(Drawable who, Runnable what, long when) {
230             mScheduledDrawable = who;
231             mScheduledRunnable = what;
232             mScheduledTime = when;
233         }
234 
235         @Override
unscheduleDrawable(Drawable who, Runnable what)236         public void unscheduleDrawable(Drawable who, Runnable what) {
237             mUnscheduledDrawable = who;
238             mUnscheduledRunnable = what;
239         }
240     }
241 
242     private final class NoOpRunnable implements Runnable {
243         @Override
run()244         public void run() {
245 
246         }
247     }
248 }
249