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.widget.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertSame; 22 import static org.junit.Assert.assertTrue; 23 import static org.mockito.Mockito.atLeastOnce; 24 import static org.mockito.Mockito.reset; 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.times; 27 import static org.mockito.Mockito.verify; 28 29 import android.Manifest; 30 import android.app.Activity; 31 import android.app.Instrumentation; 32 import android.content.Context; 33 import android.content.res.ColorStateList; 34 import android.graphics.BlendMode; 35 import android.graphics.Color; 36 import android.graphics.PorterDuff; 37 import android.graphics.drawable.ColorDrawable; 38 import android.graphics.drawable.Drawable; 39 import android.util.AttributeSet; 40 import android.view.KeyEvent; 41 import android.widget.AbsSeekBar; 42 import android.widget.SeekBar; 43 import android.widget.cts.util.TestUtils; 44 45 import androidx.test.InstrumentationRegistry; 46 import androidx.test.annotation.UiThreadTest; 47 import androidx.test.filters.SmallTest; 48 import androidx.test.rule.ActivityTestRule; 49 import androidx.test.runner.AndroidJUnit4; 50 51 import com.android.compatibility.common.util.AdoptShellPermissionsRule; 52 import com.android.compatibility.common.util.PollingCheck; 53 import com.android.compatibility.common.util.WidgetTestUtils; 54 55 import org.junit.Before; 56 import org.junit.Rule; 57 import org.junit.Test; 58 import org.junit.runner.RunWith; 59 import org.mockito.ArgumentCaptor; 60 61 import java.util.List; 62 63 /** 64 * Test {@link AbsSeekBar}. 65 */ 66 @SmallTest 67 @RunWith(AndroidJUnit4.class) 68 public class AbsSeekBarTest { 69 private Instrumentation mInstrumentation; 70 private Activity mActivity; 71 72 @Rule(order = 0) 73 public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule( 74 androidx.test.platform.app.InstrumentationRegistry 75 .getInstrumentation().getUiAutomation(), 76 Manifest.permission.START_ACTIVITIES_FROM_SDK_SANDBOX); 77 78 @Rule(order = 1) 79 public ActivityTestRule<AbsSeekBarCtsActivity> mActivityRule = 80 new ActivityTestRule<>(AbsSeekBarCtsActivity.class); 81 82 @Before setup()83 public void setup() { 84 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 85 mActivity = mActivityRule.getActivity(); 86 } 87 88 @Test testConstructor()89 public void testConstructor() { 90 new MyAbsSeekBar(mActivity); 91 92 new MyAbsSeekBar(mActivity, null); 93 94 new MyAbsSeekBar(mActivity, null, android.R.attr.progressBarStyle); 95 96 new MyAbsSeekBar(mActivity, null, 0, android.R.style.Widget_Material_Light_ProgressBar); 97 } 98 99 @Test testAccessThumbOffset()100 public void testAccessThumbOffset() { 101 AbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity); 102 final int positive = 5; 103 final int negative = -5; 104 final int zero = 0; 105 106 myAbsSeekBar.setThumbOffset(positive); 107 assertEquals(positive, myAbsSeekBar.getThumbOffset()); 108 109 myAbsSeekBar.setThumbOffset(zero); 110 assertEquals(zero, myAbsSeekBar.getThumbOffset()); 111 112 myAbsSeekBar.setThumbOffset(negative); 113 assertEquals(negative, myAbsSeekBar.getThumbOffset()); 114 } 115 116 @Test testAccessThumb()117 public void testAccessThumb() { 118 // Both are pointing to the same object. This works around current limitation in CTS 119 // coverage report tool for properly reporting coverage of base class method calls. 120 final MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity); 121 final AbsSeekBar absSeekBar = myAbsSeekBar; 122 123 Drawable drawable1 = mActivity.getDrawable(R.drawable.scenery); 124 Drawable drawable2 = mActivity.getDrawable(R.drawable.pass); 125 126 assertFalse(myAbsSeekBar.verifyDrawable(drawable1)); 127 assertFalse(myAbsSeekBar.verifyDrawable(drawable2)); 128 129 absSeekBar.setThumb(drawable1); 130 assertSame(drawable1, absSeekBar.getThumb()); 131 assertTrue(myAbsSeekBar.verifyDrawable(drawable1)); 132 assertFalse(myAbsSeekBar.verifyDrawable(drawable2)); 133 134 absSeekBar.setThumb(drawable2); 135 assertSame(drawable2, absSeekBar.getThumb()); 136 assertFalse(myAbsSeekBar.verifyDrawable(drawable1)); 137 assertTrue(myAbsSeekBar.verifyDrawable(drawable2)); 138 } 139 140 @Test testAccessTickMark()141 public void testAccessTickMark() { 142 // Both are pointing to the same object. This works around current limitation in CTS 143 // coverage report tool for properly reporting coverage of base class method calls. 144 final MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity); 145 final AbsSeekBar absSeekBar = myAbsSeekBar; 146 147 Drawable drawable1 = mActivity.getDrawable(R.drawable.black); 148 Drawable drawable2 = mActivity.getDrawable(R.drawable.black); 149 150 assertFalse(myAbsSeekBar.verifyDrawable(drawable1)); 151 assertFalse(myAbsSeekBar.verifyDrawable(drawable2)); 152 153 absSeekBar.setTickMark(drawable1); 154 assertSame(drawable1, absSeekBar.getTickMark()); 155 assertTrue(myAbsSeekBar.verifyDrawable(drawable1)); 156 assertFalse(myAbsSeekBar.verifyDrawable(drawable2)); 157 158 absSeekBar.setTickMark(drawable2); 159 assertSame(drawable2, absSeekBar.getTickMark()); 160 assertFalse(myAbsSeekBar.verifyDrawable(drawable1)); 161 assertTrue(myAbsSeekBar.verifyDrawable(drawable2)); 162 } 163 164 @Test testDrawableStateChanged()165 public void testDrawableStateChanged() { 166 MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity); 167 Drawable mockProgressDrawable = spy(new ColorDrawable(Color.YELLOW)); 168 myAbsSeekBar.setProgressDrawable(mockProgressDrawable); 169 170 ArgumentCaptor<Integer> alphaCaptor = ArgumentCaptor.forClass(Integer.class); 171 myAbsSeekBar.setEnabled(false); 172 myAbsSeekBar.drawableStateChanged(); 173 verify(mockProgressDrawable, atLeastOnce()).setAlpha(alphaCaptor.capture()); 174 // Verify that the last call to setAlpha was with argument 0x00 175 List<Integer> alphaCaptures = alphaCaptor.getAllValues(); 176 assertTrue(!alphaCaptures.isEmpty()); 177 assertEquals(Integer.valueOf(0x00), alphaCaptures.get(alphaCaptures.size() - 1)); 178 179 alphaCaptor = ArgumentCaptor.forClass(Integer.class); 180 myAbsSeekBar.setEnabled(true); 181 myAbsSeekBar.drawableStateChanged(); 182 verify(mockProgressDrawable, atLeastOnce()).setAlpha(alphaCaptor.capture()); 183 // Verify that the last call to setAlpha was with argument 0xFF 184 alphaCaptures = alphaCaptor.getAllValues(); 185 assertTrue(!alphaCaptures.isEmpty()); 186 assertEquals(Integer.valueOf(0xFF), alphaCaptures.get(alphaCaptures.size() - 1)); 187 } 188 189 @Test testVerifyDrawable()190 public void testVerifyDrawable() { 191 MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity); 192 Drawable drawable1 = mActivity.getDrawable(R.drawable.scenery); 193 Drawable drawable2 = mActivity.getDrawable(R.drawable.pass); 194 Drawable drawable3 = mActivity.getDrawable(R.drawable.blue); 195 Drawable drawable4 = mActivity.getDrawable(R.drawable.black); 196 197 assertFalse(myAbsSeekBar.verifyDrawable(drawable1)); 198 assertFalse(myAbsSeekBar.verifyDrawable(drawable2)); 199 assertFalse(myAbsSeekBar.verifyDrawable(drawable3)); 200 assertFalse(myAbsSeekBar.verifyDrawable(drawable4)); 201 202 myAbsSeekBar.setThumb(drawable1); 203 assertTrue(myAbsSeekBar.verifyDrawable(drawable1)); 204 assertFalse(myAbsSeekBar.verifyDrawable(drawable2)); 205 assertFalse(myAbsSeekBar.verifyDrawable(drawable3)); 206 assertFalse(myAbsSeekBar.verifyDrawable(drawable4)); 207 208 myAbsSeekBar.setThumb(drawable2); 209 assertFalse(myAbsSeekBar.verifyDrawable(drawable1)); 210 assertTrue(myAbsSeekBar.verifyDrawable(drawable2)); 211 assertFalse(myAbsSeekBar.verifyDrawable(drawable3)); 212 assertFalse(myAbsSeekBar.verifyDrawable(drawable4)); 213 214 myAbsSeekBar.setBackgroundDrawable(drawable2); 215 myAbsSeekBar.setProgressDrawable(drawable3); 216 myAbsSeekBar.setIndeterminateDrawable(drawable4); 217 assertFalse(myAbsSeekBar.verifyDrawable(drawable1)); 218 assertTrue(myAbsSeekBar.verifyDrawable(drawable2)); 219 assertTrue(myAbsSeekBar.verifyDrawable(drawable3)); 220 assertTrue(myAbsSeekBar.verifyDrawable(drawable4)); 221 } 222 223 @Test testAccessKeyProgressIncrement()224 public void testAccessKeyProgressIncrement() throws Throwable { 225 // AbsSeekBar is an abstract class, use its subclass: SeekBar to do this test. 226 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(), 227 () -> mActivity.setContentView(R.layout.seekbar_layout)); 228 229 final SeekBar seekBar = (SeekBar) mActivity.findViewById(R.id.seekBar); 230 final int keyProgressIncrement = 2; 231 mActivityRule.runOnUiThread(() -> { 232 seekBar.setKeyProgressIncrement(keyProgressIncrement); 233 seekBar.setFocusableInTouchMode(true); 234 seekBar.requestFocus(); 235 }); 236 PollingCheck.waitFor(1000, seekBar::hasWindowFocus); 237 assertEquals(keyProgressIncrement, seekBar.getKeyProgressIncrement()); 238 239 int oldProgress = seekBar.getProgress(); 240 KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT); 241 mInstrumentation.sendKeySync(keyEvent); 242 assertEquals(oldProgress + keyProgressIncrement, seekBar.getProgress()); 243 oldProgress = seekBar.getProgress(); 244 keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT); 245 mInstrumentation.sendKeySync(keyEvent); 246 assertEquals(oldProgress - keyProgressIncrement, seekBar.getProgress()); 247 } 248 249 @Test testAccessMax()250 public void testAccessMax() { 251 AbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity, null, R.style.TestProgressBar); 252 253 int progress = 10; 254 myAbsSeekBar.setProgress(progress); 255 int max = progress + 1; 256 myAbsSeekBar.setMax(max); 257 assertEquals(max, myAbsSeekBar.getMax()); 258 assertEquals(progress, myAbsSeekBar.getProgress()); 259 assertEquals(1, myAbsSeekBar.getKeyProgressIncrement()); 260 261 max = progress - 1; 262 myAbsSeekBar.setMax(max); 263 assertEquals(max, myAbsSeekBar.getMax()); 264 assertEquals(max, myAbsSeekBar.getProgress()); 265 assertEquals(1, myAbsSeekBar.getKeyProgressIncrement()); 266 267 int keyProgressIncrement = 10; 268 myAbsSeekBar.setKeyProgressIncrement(keyProgressIncrement); 269 assertEquals(keyProgressIncrement, myAbsSeekBar.getKeyProgressIncrement()); 270 max = (keyProgressIncrement - 1) * 20; 271 myAbsSeekBar.setMax(max); 272 assertEquals(keyProgressIncrement, myAbsSeekBar.getKeyProgressIncrement()); 273 max = (keyProgressIncrement + 1) * 20; 274 myAbsSeekBar.setMax(max); 275 assertEquals(keyProgressIncrement + 1, myAbsSeekBar.getKeyProgressIncrement()); 276 } 277 278 @Test testAccessMin()279 public void testAccessMin() { 280 AbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity, null, R.style.TestProgressBar); 281 282 int progress = -5; 283 int min = progress - 1; 284 int max = 5; 285 myAbsSeekBar.setMax(max); 286 myAbsSeekBar.setMin(min); 287 myAbsSeekBar.setProgress(progress); 288 assertEquals(min, myAbsSeekBar.getMin()); 289 assertEquals(progress, myAbsSeekBar.getProgress()); 290 assertEquals(1, myAbsSeekBar.getKeyProgressIncrement()); 291 292 min = progress + 1; 293 myAbsSeekBar.setMin(min); 294 assertEquals(min, myAbsSeekBar.getMin()); 295 assertEquals(min, myAbsSeekBar.getProgress()); 296 assertEquals(1, myAbsSeekBar.getKeyProgressIncrement()); 297 298 int keyProgressIncrement = 10; 299 myAbsSeekBar.setKeyProgressIncrement(keyProgressIncrement); 300 assertEquals(keyProgressIncrement, myAbsSeekBar.getKeyProgressIncrement()); 301 max = (keyProgressIncrement - 1) * 10; 302 min = -1 * keyProgressIncrement * 10; 303 myAbsSeekBar.setMax(max); 304 myAbsSeekBar.setMin(min); 305 assertEquals(keyProgressIncrement, myAbsSeekBar.getKeyProgressIncrement()); 306 307 max += 20; 308 myAbsSeekBar.setMax(max); 309 assertEquals(keyProgressIncrement + 1, myAbsSeekBar.getKeyProgressIncrement()); 310 assertEquals(min, myAbsSeekBar.getMin()); 311 assertEquals(max, myAbsSeekBar.getMax()); 312 } 313 314 @UiThreadTest 315 @Test testThumbTint()316 public void testThumbTint() { 317 AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.thumb_tint); 318 319 assertEquals("Thumb tint inflated correctly", 320 Color.WHITE, inflatedView.getThumbTintList().getDefaultColor()); 321 assertEquals("Thumb tint mode inflated correctly", 322 PorterDuff.Mode.SRC_OVER, inflatedView.getThumbTintMode()); 323 324 Drawable mockThumb = spy(new ColorDrawable(Color.BLUE)); 325 326 inflatedView.setThumb(mockThumb); 327 verify(mockThumb, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE)); 328 329 reset(mockThumb); 330 inflatedView.setThumbTintList(ColorStateList.valueOf(Color.RED)); 331 verify(mockThumb, times(1)) 332 .setTintList(TestUtils.colorStateListOf(Color.RED)); 333 334 inflatedView.setThumbTintMode(PorterDuff.Mode.DST_ATOP); 335 assertEquals("Thumb tint mode changed correctly", 336 PorterDuff.Mode.DST_ATOP, inflatedView.getThumbTintMode()); 337 338 reset(mockThumb); 339 inflatedView.setThumb(null); 340 inflatedView.setThumb(mockThumb); 341 verify(mockThumb, times(1)) 342 .setTintList(TestUtils.colorStateListOf(Color.RED)); 343 } 344 345 @UiThreadTest 346 @Test testThumbTintBlendMode()347 public void testThumbTintBlendMode() { 348 AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.thumb_tint); 349 350 assertEquals("Thumb tint inflated correctly", 351 Color.WHITE, inflatedView.getThumbTintList().getDefaultColor()); 352 assertEquals("Thumb tint mode inflated correctly", 353 BlendMode.SRC_OVER, inflatedView.getThumbTintBlendMode()); 354 355 Drawable mockThumb = spy(new ColorDrawable(Color.BLUE)); 356 357 inflatedView.setThumb(mockThumb); 358 verify(mockThumb, times(1)) 359 .setTintList(TestUtils.colorStateListOf(Color.WHITE)); 360 361 reset(mockThumb); 362 inflatedView.setThumbTintList(ColorStateList.valueOf(Color.RED)); 363 verify(mockThumb, times(1)) 364 .setTintList(TestUtils.colorStateListOf(Color.RED)); 365 366 inflatedView.setThumbTintBlendMode(BlendMode.DST_ATOP); 367 assertEquals("Thumb tint mode changed correctly", 368 BlendMode.DST_ATOP, inflatedView.getThumbTintBlendMode()); 369 370 reset(mockThumb); 371 inflatedView.setThumb(null); 372 inflatedView.setThumb(mockThumb); 373 verify(mockThumb, times(1)) 374 .setTintList(TestUtils.colorStateListOf(Color.RED)); 375 } 376 377 @UiThreadTest 378 @Test testTickMarkTint()379 public void testTickMarkTint() { 380 AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.tick_mark_tint); 381 382 assertEquals("TickMark tint inflated correctly", 383 Color.WHITE, inflatedView.getTickMarkTintList().getDefaultColor()); 384 assertEquals("TickMark tint mode inflated correctly", 385 PorterDuff.Mode.SRC_OVER, inflatedView.getTickMarkTintMode()); 386 387 Drawable mockTickMark = spy(new ColorDrawable(Color.BLUE)); 388 389 inflatedView.setTickMark(mockTickMark); 390 verify(mockTickMark, times(1)) 391 .setTintList(TestUtils.colorStateListOf(Color.WHITE)); 392 393 reset(mockTickMark); 394 inflatedView.setTickMarkTintList(ColorStateList.valueOf(Color.RED)); 395 verify(mockTickMark, times(1)) 396 .setTintList(TestUtils.colorStateListOf(Color.RED)); 397 398 inflatedView.setTickMarkTintMode(PorterDuff.Mode.DARKEN); 399 assertEquals("TickMark tint mode changed correctly", 400 PorterDuff.Mode.DARKEN, inflatedView.getTickMarkTintMode()); 401 402 reset(mockTickMark); 403 inflatedView.setTickMark(null); 404 inflatedView.setTickMark(mockTickMark); 405 verify(mockTickMark, times(1)) 406 .setTintList(TestUtils.colorStateListOf(Color.RED)); 407 } 408 409 @UiThreadTest 410 @Test testTickMarkTintBlendMode()411 public void testTickMarkTintBlendMode() { 412 AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.tick_mark_tint); 413 414 assertEquals("TickMark tint inflated correctly", 415 Color.WHITE, inflatedView.getTickMarkTintList().getDefaultColor()); 416 assertEquals("TickMark tint mode inflated correctly", 417 BlendMode.SRC_OVER, inflatedView.getTickMarkTintBlendMode()); 418 419 Drawable mockTickMark = spy(new ColorDrawable(Color.BLUE)); 420 421 inflatedView.setTickMark(mockTickMark); 422 verify(mockTickMark, times(1)) 423 .setTintList(TestUtils.colorStateListOf(Color.WHITE)); 424 425 reset(mockTickMark); 426 inflatedView.setTickMarkTintList(ColorStateList.valueOf(Color.RED)); 427 verify(mockTickMark, times(1)) 428 .setTintList(TestUtils.colorStateListOf(Color.RED)); 429 430 inflatedView.setTickMarkTintBlendMode(BlendMode.DARKEN); 431 assertEquals("TickMark tint mode changed correctly", 432 BlendMode.DARKEN, inflatedView.getTickMarkTintBlendMode()); 433 434 reset(mockTickMark); 435 inflatedView.setTickMark(null); 436 inflatedView.setTickMark(mockTickMark); 437 verify(mockTickMark, times(1)) 438 .setTintList(TestUtils.colorStateListOf(Color.RED)); 439 } 440 441 @Test testAccessSplitTrack()442 public void testAccessSplitTrack() throws Throwable { 443 AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.tick_mark_tint); 444 445 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, inflatedView, 446 () -> inflatedView.setSplitTrack(true)); 447 assertTrue(inflatedView.getSplitTrack()); 448 449 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, inflatedView, 450 () -> inflatedView.setSplitTrack(false)); 451 assertFalse(inflatedView.getSplitTrack()); 452 } 453 454 private static class MyAbsSeekBar extends AbsSeekBar { MyAbsSeekBar(Context context)455 public MyAbsSeekBar(Context context) { 456 super(context); 457 } 458 MyAbsSeekBar(Context context, AttributeSet attrs)459 public MyAbsSeekBar(Context context, AttributeSet attrs) { 460 super(context, attrs); 461 } 462 MyAbsSeekBar(Context context, AttributeSet attrs, int defStyle)463 public MyAbsSeekBar(Context context, AttributeSet attrs, int defStyle) { 464 super(context, attrs, defStyle); 465 } 466 MyAbsSeekBar(Context context, AttributeSet attrs, int defStyle, int defStyleRes)467 public MyAbsSeekBar(Context context, AttributeSet attrs, int defStyle, int defStyleRes) { 468 super(context, attrs, defStyle, defStyleRes); 469 } 470 471 @Override drawableStateChanged()472 protected void drawableStateChanged() { 473 super.drawableStateChanged(); 474 } 475 476 @Override verifyDrawable(Drawable who)477 protected boolean verifyDrawable(Drawable who) { 478 return super.verifyDrawable(who); 479 } 480 } 481 } 482