1 /* 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 17 package android.graphics.drawable.cts; 18 19 import com.android.cts.graphics.R; 20 21 import android.content.res.Resources; 22 import android.graphics.Bitmap; 23 import android.graphics.Bitmap.Config; 24 import android.graphics.Canvas; 25 import android.graphics.drawable.Drawable; 26 import android.graphics.drawable.TransitionDrawable; 27 import android.test.InstrumentationTestCase; 28 29 public class TransitionDrawableTest extends InstrumentationTestCase { 30 private static final int COLOR1 = 0xff0000ff; 31 32 private static final int COLOR0 = 0xffff0000; 33 34 private static final int CANVAS_WIDTH = 10; 35 36 private static final int CANVAS_HEIGHT = 10; 37 38 private TransitionDrawable mTransitionDrawable; 39 40 private Bitmap mBitmap; 41 42 private Canvas mCanvas; 43 44 @Override 45 protected void setUp() throws Exception { 46 super.setUp(); 47 mTransitionDrawable = (TransitionDrawable) getInstrumentation().getTargetContext() 48 .getResources().getDrawable(R.drawable.transition_test); 49 mTransitionDrawable.setBounds(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); 50 51 mBitmap = Bitmap.createBitmap(CANVAS_WIDTH, CANVAS_HEIGHT, Config.ARGB_8888); 52 mCanvas = new Canvas(mBitmap); 53 } 54 55 public void testConstructor() { 56 Resources resources = getInstrumentation().getTargetContext().getResources(); 57 Drawable[] drawables = new Drawable[] { 58 resources.getDrawable(R.drawable.testimage), 59 resources.getDrawable(R.drawable.levellistdrawable) 60 }; 61 new TransitionDrawable(drawables); 62 } 63 64 public void testStartTransition() { 65 MockCallBack cb = new MockCallBack(); 66 mTransitionDrawable.setCallback(cb); 67 68 // start when there is no transition 69 cb.reset(); 70 mTransitionDrawable.startTransition(2000); 71 assertTrue(cb.hasCalledInvalidateDrawable()); 72 assertTransition(COLOR0, COLOR1, 2000); 73 74 // start when there is a transition in progress 75 makeTransitionInProgress(2000, 1000); 76 cb.reset(); 77 mTransitionDrawable.startTransition(2000); 78 assertTrue(cb.hasCalledInvalidateDrawable()); 79 assertTransition(COLOR0, COLOR1, 2000); 80 81 // start when there is a reverse transition in progress 82 makeReverseTransitionInProgress(2000, 1000); 83 cb.reset(); 84 mTransitionDrawable.startTransition(2000); 85 assertTrue(cb.hasCalledInvalidateDrawable()); 86 assertTransition(COLOR0, COLOR1, 2000); 87 88 // should not accept negative duration 89 mTransitionDrawable.startTransition(-1); 90 } 91 92 public void testResetTransition() { 93 MockCallBack cb = new MockCallBack(); 94 mTransitionDrawable.setCallback(cb); 95 96 // reset when there is no transition 97 cb.reset(); 98 mTransitionDrawable.resetTransition(); 99 assertTrue(cb.hasCalledInvalidateDrawable()); 100 101 // reset when there is a transition in progress 102 makeTransitionInProgress(2000, 1000); 103 cb.reset(); 104 mTransitionDrawable.resetTransition(); 105 assertTrue(cb.hasCalledInvalidateDrawable()); 106 assertTransitionStart(COLOR0); 107 assertTransitionEnd(COLOR0, 2000); 108 109 // reset when there is a reverse transition in progress 110 makeReverseTransitionInProgress(2000, 1000); 111 cb.reset(); 112 mTransitionDrawable.resetTransition(); 113 assertTrue(cb.hasCalledInvalidateDrawable()); 114 assertTransitionStart(COLOR0); 115 assertTransitionEnd(COLOR0, 2000); 116 } 117 118 public void testReverseTransition() { 119 MockCallBack cb = new MockCallBack(); 120 mTransitionDrawable.setCallback(cb); 121 122 // reverse when there is no transition 123 cb.reset(); 124 mTransitionDrawable.reverseTransition(2000); 125 assertTrue(cb.hasCalledInvalidateDrawable()); 126 assertTransition(COLOR0, COLOR1, 2000); 127 128 // reverse after the other transition ends 129 cb.reset(); 130 mTransitionDrawable.reverseTransition(2000); 131 assertTrue(cb.hasCalledInvalidateDrawable()); 132 assertTransition(COLOR1, COLOR0, 2000); 133 134 // reverse when there is a transition in progress 135 makeTransitionInProgress(2000, 1000); 136 cb.reset(); 137 mTransitionDrawable.reverseTransition(20000); 138 assertFalse(cb.hasCalledInvalidateDrawable()); 139 int colorFrom = mBitmap.getPixel(0, 0); 140 assertTransition(colorFrom, COLOR0, 1500); 141 142 // reverse when there is a reverse transition in progress 143 makeReverseTransitionInProgress(2000, 1000); 144 cb.reset(); 145 mTransitionDrawable.reverseTransition(20000); 146 assertFalse(cb.hasCalledInvalidateDrawable()); 147 colorFrom = mBitmap.getPixel(0, 0); 148 assertTransition(colorFrom, COLOR1, 1500); 149 150 // should not accept negative duration 151 mTransitionDrawable.reverseTransition(-1); 152 } 153 154 public void testDrawWithNUllCanvas() { 155 try { 156 mTransitionDrawable.draw(null); 157 fail("The method should check whether the canvas is null."); 158 } catch (NullPointerException e) { 159 } 160 } 161 162 // This boolean takes effect when the drawable is drawn and the effect can not be tested. 163 public void testAccessCrossFadeEnabled() { 164 assertFalse(mTransitionDrawable.isCrossFadeEnabled()); 165 166 mTransitionDrawable.setCrossFadeEnabled(true); 167 assertTrue(mTransitionDrawable.isCrossFadeEnabled()); 168 169 mTransitionDrawable.setCrossFadeEnabled(false); 170 assertFalse(mTransitionDrawable.isCrossFadeEnabled()); 171 } 172 173 private void assertTransition(int colorFrom, int colorTo, long delay) { 174 assertTransitionStart(colorFrom); 175 assertTransitionInProgress(colorFrom, colorTo, delay / 2); 176 assertTransitionEnd(colorTo, delay); 177 } 178 179 private void assertTransitionStart(int colorFrom) { 180 mBitmap.eraseColor(0x00000000); 181 mTransitionDrawable.draw(mCanvas); 182 assertColorFillRect(mBitmap, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, colorFrom); 183 } 184 185 private void assertTransitionInProgress(int colorFrom, int colorTo, long delay) { 186 drawAfterDelaySync(delay); 187 assertColorNotFillRect(mBitmap, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, colorFrom); 188 assertColorNotFillRect(mBitmap, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, colorTo); 189 } 190 191 private void assertTransitionEnd(int colorTo, long delay) { 192 drawAfterDelaySync(delay); 193 assertColorFillRect(mBitmap, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, colorTo); 194 } 195 196 private void assertColorFillRect(Bitmap bmp, int x, int y, int w, int h, int color) { 197 for (int i = x; i < x + w; i++) { 198 for (int j = y; j < y + h; j++) { 199 assertEquals(color, bmp.getPixel(i, j)); 200 } 201 } 202 } 203 204 private void assertColorNotFillRect(Bitmap bmp, int x, int y, int w, int h, int color) { 205 for (int i = x; i < x + w; i++) { 206 for (int j = y; j < y + h; j++) { 207 assertTrue(color != bmp.getPixel(i, j)); 208 } 209 } 210 } 211 212 private void makeReverseTransitionInProgress(int duration, int delay) { 213 mTransitionDrawable.resetTransition(); 214 mTransitionDrawable.startTransition(2000); 215 assertTransition(COLOR0, COLOR1, 2000); 216 mTransitionDrawable.reverseTransition(duration); 217 assertTransitionStart(COLOR1); 218 assertTransitionInProgress(COLOR1, COLOR0, delay); 219 } 220 221 private void makeTransitionInProgress(int duration, int delay) { 222 mTransitionDrawable.resetTransition(); 223 mTransitionDrawable.startTransition(duration); 224 assertTransitionStart(COLOR0); 225 assertTransitionInProgress(COLOR0, COLOR1, delay); 226 } 227 228 private void drawAfterDelaySync(long delay) { 229 Thread t = new Thread(new Runnable() { 230 public void run() { 231 mBitmap.eraseColor(0x00000000); 232 mTransitionDrawable.draw(mCanvas); 233 } 234 }); 235 try { 236 Thread.sleep(delay); 237 t.start(); 238 t.join(); 239 } catch (InterruptedException e) { 240 // catch and fail, because propagating this all the way up is messy 241 fail(e.getMessage()); 242 } 243 } 244 245 private class MockCallBack implements Drawable.Callback { 246 private boolean mHasCalledInvalidateDrawable; 247 248 public boolean hasCalledInvalidateDrawable() { 249 return mHasCalledInvalidateDrawable; 250 } 251 public void reset() { 252 mHasCalledInvalidateDrawable = false; 253 } 254 255 public void invalidateDrawable(Drawable who) { 256 mHasCalledInvalidateDrawable = true; 257 } 258 259 public void scheduleDrawable(Drawable who, Runnable what, long when) { 260 } 261 262 public void unscheduleDrawable(Drawable who, Runnable what) { 263 } 264 265 public int getResolvedLayoutDirection(Drawable who) { 266 return 0; 267 } 268 } 269 } 270