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.assertNotNull; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertSame; 24 import static org.junit.Assert.assertTrue; 25 26 import android.app.Activity; 27 import android.app.Instrumentation; 28 import android.app.Instrumentation.ActivityMonitor; 29 import android.app.PendingIntent; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.content.res.ColorStateList; 33 import android.graphics.Bitmap; 34 import android.graphics.BitmapFactory; 35 import android.graphics.drawable.BitmapDrawable; 36 import android.graphics.drawable.Icon; 37 import android.net.Uri; 38 import android.os.Bundle; 39 import android.os.Parcel; 40 import android.text.TextUtils; 41 import android.util.TypedValue; 42 import android.view.View; 43 import android.view.ViewGroup; 44 import android.widget.AbsoluteLayout; 45 import android.widget.AnalogClock; 46 import android.widget.Button; 47 import android.widget.Chronometer; 48 import android.widget.DatePicker; 49 import android.widget.EditText; 50 import android.widget.FrameLayout; 51 import android.widget.GridLayout; 52 import android.widget.GridView; 53 import android.widget.ImageButton; 54 import android.widget.ImageView; 55 import android.widget.LinearLayout; 56 import android.widget.ListView; 57 import android.widget.NumberPicker; 58 import android.widget.ProgressBar; 59 import android.widget.RatingBar; 60 import android.widget.RelativeLayout; 61 import android.widget.RemoteViews; 62 import android.widget.RemoteViews.ActionException; 63 import android.widget.SeekBar; 64 import android.widget.StackView; 65 import android.widget.TextClock; 66 import android.widget.TextView; 67 import android.widget.ViewFlipper; 68 import android.widget.cts.util.TestUtils; 69 70 import androidx.test.InstrumentationRegistry; 71 import androidx.test.annotation.UiThreadTest; 72 import androidx.test.filters.LargeTest; 73 import androidx.test.filters.MediumTest; 74 import androidx.test.rule.ActivityTestRule; 75 import androidx.test.runner.AndroidJUnit4; 76 77 import com.android.compatibility.common.util.WidgetTestUtils; 78 79 import org.junit.Before; 80 import org.junit.Rule; 81 import org.junit.Test; 82 import org.junit.rules.ExpectedException; 83 import org.junit.runner.RunWith; 84 85 import java.io.File; 86 import java.io.FileOutputStream; 87 import java.io.IOException; 88 import java.io.InputStream; 89 import java.io.OutputStream; 90 91 /** 92 * Test {@link RemoteViews}. 93 */ 94 @MediumTest 95 @RunWith(AndroidJUnit4.class) 96 public class RemoteViewsTest { 97 private static final String PACKAGE_NAME = "android.widget.cts"; 98 99 private static final int INVALID_ID = -1; 100 101 private static final long TEST_TIMEOUT = 5000; 102 103 @Rule 104 public ActivityTestRule<RemoteViewsCtsActivity> mActivityRule = 105 new ActivityTestRule<>(RemoteViewsCtsActivity.class); 106 107 @Rule 108 public ExpectedException mExpectedException = ExpectedException.none(); 109 110 private Instrumentation mInstrumentation; 111 112 private Context mContext; 113 114 private RemoteViews mRemoteViews; 115 116 private View mResult; 117 118 @UiThreadTest 119 @Before setup()120 public void setup() { 121 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 122 mContext = mInstrumentation.getTargetContext(); 123 mRemoteViews = new RemoteViews(PACKAGE_NAME, R.layout.remoteviews_good); 124 mResult = mRemoteViews.apply(mContext, null); 125 126 // Add our host view to the activity behind this test. This is similar to how launchers 127 // add widgets to the on-screen UI. 128 ViewGroup root = (ViewGroup) mActivityRule.getActivity().findViewById 129 (R.id.remoteView_host); 130 FrameLayout.MarginLayoutParams lp = new FrameLayout.MarginLayoutParams( 131 ViewGroup.LayoutParams.MATCH_PARENT, 132 ViewGroup.LayoutParams.MATCH_PARENT); 133 mResult.setLayoutParams(lp); 134 135 root.addView(mResult); 136 } 137 138 @Test testConstructor()139 public void testConstructor() { 140 new RemoteViews(PACKAGE_NAME, R.layout.remoteviews_good); 141 142 new RemoteViews(Parcel.obtain()); 143 } 144 145 @Test testGetPackage()146 public void testGetPackage() { 147 assertEquals(PACKAGE_NAME, mRemoteViews.getPackage()); 148 149 mRemoteViews = new RemoteViews(null, R.layout.remoteviews_good); 150 assertNull(mRemoteViews.getPackage()); 151 } 152 153 @Test testGetLayoutId()154 public void testGetLayoutId() { 155 assertEquals(R.layout.remoteviews_good, mRemoteViews.getLayoutId()); 156 157 mRemoteViews = new RemoteViews(PACKAGE_NAME, R.layout.listview_layout); 158 assertEquals(R.layout.listview_layout, mRemoteViews.getLayoutId()); 159 160 mRemoteViews = new RemoteViews(PACKAGE_NAME, INVALID_ID); 161 assertEquals(INVALID_ID, mRemoteViews.getLayoutId()); 162 163 mRemoteViews = new RemoteViews(PACKAGE_NAME, 0); 164 assertEquals(0, mRemoteViews.getLayoutId()); 165 } 166 167 @Test testSetContentDescription()168 public void testSetContentDescription() throws Throwable { 169 View view = mResult.findViewById(R.id.remoteView_frame); 170 171 assertNull(view.getContentDescription()); 172 173 CharSequence contentDescription = mContext.getString(R.string.remote_content_description); 174 mRemoteViews.setContentDescription(R.id.remoteView_frame, contentDescription); 175 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 176 assertTrue(TextUtils.equals(contentDescription, view.getContentDescription())); 177 } 178 179 @Test testSetViewVisibility()180 public void testSetViewVisibility() throws Throwable { 181 View view = mResult.findViewById(R.id.remoteView_chronometer); 182 assertEquals(View.VISIBLE, view.getVisibility()); 183 184 mRemoteViews.setViewVisibility(R.id.remoteView_chronometer, View.INVISIBLE); 185 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 186 assertEquals(View.INVISIBLE, view.getVisibility()); 187 188 mRemoteViews.setViewVisibility(R.id.remoteView_chronometer, View.GONE); 189 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 190 assertEquals(View.GONE, view.getVisibility()); 191 192 mRemoteViews.setViewVisibility(R.id.remoteView_chronometer, View.VISIBLE); 193 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 194 assertEquals(View.VISIBLE, view.getVisibility()); 195 } 196 197 @Test testSetTextViewText()198 public void testSetTextViewText() throws Throwable { 199 TextView textView = (TextView) mResult.findViewById(R.id.remoteView_text); 200 assertEquals("", textView.getText().toString()); 201 202 String expected = "This is content"; 203 mRemoteViews.setTextViewText(R.id.remoteView_text, expected); 204 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 205 assertEquals(expected, textView.getText().toString()); 206 207 mRemoteViews.setTextViewText(R.id.remoteView_text, null); 208 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 209 assertEquals("", textView.getText().toString()); 210 211 mExpectedException.expect(ActionException.class); 212 mRemoteViews.setTextViewText(R.id.remoteView_absolute, ""); 213 mRemoteViews.reapply(mContext, mResult); 214 } 215 216 @Test testSetTextViewTextSize()217 public void testSetTextViewTextSize() throws Throwable { 218 TextView textView = (TextView) mResult.findViewById(R.id.remoteView_text); 219 220 mRemoteViews.setTextViewTextSize(R.id.remoteView_text, TypedValue.COMPLEX_UNIT_SP, 18); 221 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 222 assertEquals(mContext.getResources().getDisplayMetrics().scaledDensity * 18, 223 textView.getTextSize(), 0.001f); 224 225 mExpectedException.expect(Throwable.class); 226 mRemoteViews.setTextViewTextSize(R.id.remoteView_absolute, TypedValue.COMPLEX_UNIT_SP, 20); 227 mRemoteViews.reapply(mContext, mResult); 228 } 229 230 @Test testSetIcon()231 public void testSetIcon() throws Throwable { 232 ImageView image = (ImageView) mResult.findViewById(R.id.remoteView_image); 233 assertNull(image.getDrawable()); 234 235 Icon iconBlack = Icon.createWithResource(mContext, R.drawable.icon_black); 236 mRemoteViews.setIcon(R.id.remoteView_image, "setImageIcon", iconBlack); 237 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 238 assertNotNull(image.getDrawable()); 239 BitmapDrawable dBlack = (BitmapDrawable) mContext.getDrawable(R.drawable.icon_black); 240 WidgetTestUtils.assertEquals(dBlack.getBitmap(), 241 ((BitmapDrawable) image.getDrawable()).getBitmap()); 242 } 243 244 @Test testSetImageViewIcon()245 public void testSetImageViewIcon() throws Throwable { 246 ImageView image = (ImageView) mResult.findViewById(R.id.remoteView_image); 247 assertNull(image.getDrawable()); 248 249 Icon iconBlue = Icon.createWithResource(mContext, R.drawable.icon_blue); 250 mRemoteViews.setImageViewIcon(R.id.remoteView_image, iconBlue); 251 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 252 assertNotNull(image.getDrawable()); 253 BitmapDrawable dBlue = (BitmapDrawable) mContext.getDrawable(R.drawable.icon_blue); 254 WidgetTestUtils.assertEquals(dBlue.getBitmap(), 255 ((BitmapDrawable) image.getDrawable()).getBitmap()); 256 257 } 258 259 @Test testSetImageViewResource()260 public void testSetImageViewResource() throws Throwable { 261 ImageView image = (ImageView) mResult.findViewById(R.id.remoteView_image); 262 assertNull(image.getDrawable()); 263 264 mRemoteViews.setImageViewResource(R.id.remoteView_image, R.drawable.testimage); 265 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 266 assertNotNull(image.getDrawable()); 267 BitmapDrawable d = (BitmapDrawable) mContext.getDrawable(R.drawable.testimage); 268 WidgetTestUtils.assertEquals(d.getBitmap(), 269 ((BitmapDrawable) image.getDrawable()).getBitmap()); 270 271 mExpectedException.expect(ActionException.class); 272 mRemoteViews.setImageViewResource(R.id.remoteView_absolute, R.drawable.testimage); 273 mRemoteViews.reapply(mContext, mResult); 274 } 275 276 @Test testSetImageViewUri()277 public void testSetImageViewUri() throws Throwable { 278 String path = getTestImagePath(); 279 File imageFile = new File(path); 280 281 try { 282 createSampleImage(imageFile, R.raw.testimage); 283 284 Uri uri = Uri.parse(path); 285 ImageView image = (ImageView) mResult.findViewById(R.id.remoteView_image); 286 assertNull(image.getDrawable()); 287 288 mRemoteViews.setImageViewUri(R.id.remoteView_image, uri); 289 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 290 291 Bitmap imageViewBitmap = ((BitmapDrawable) image.getDrawable()).getBitmap(); 292 Bitmap expectedBitmap = WidgetTestUtils.getUnscaledAndDitheredBitmap( 293 mContext.getResources(), R.raw.testimage, imageViewBitmap.getConfig()); 294 WidgetTestUtils.assertEquals(expectedBitmap, imageViewBitmap); 295 } finally { 296 imageFile.delete(); 297 } 298 } 299 300 /** 301 * Returns absolute file path of location where test image should be stored 302 */ getTestImagePath()303 private String getTestImagePath() { 304 return mContext.getFilesDir() + "/test.jpg"; 305 } 306 307 @Test testSetChronometer()308 public void testSetChronometer() throws Throwable { 309 long base1 = 50; 310 long base2 = -50; 311 Chronometer chronometer = (Chronometer) mResult.findViewById(R.id.remoteView_chronometer); 312 313 mRemoteViews.setChronometer(R.id.remoteView_chronometer, base1, "HH:MM:SS", 314 false); 315 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 316 assertEquals(base1, chronometer.getBase()); 317 assertEquals("HH:MM:SS", chronometer.getFormat()); 318 319 mRemoteViews.setChronometer(R.id.remoteView_chronometer, base2, "HH:MM:SS", 320 false); 321 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 322 assertEquals(base2, chronometer.getBase()); 323 assertEquals("HH:MM:SS", chronometer.getFormat()); 324 325 mRemoteViews.setChronometer(R.id.remoteView_chronometer, base1, "invalid", 326 true); 327 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 328 assertEquals(base1, chronometer.getBase()); 329 assertEquals("invalid", chronometer.getFormat()); 330 331 mExpectedException.expect(ActionException.class); 332 mRemoteViews.setChronometer(R.id.remoteView_absolute, base1, "invalid", true); 333 mRemoteViews.reapply(mContext, mResult); 334 } 335 336 @Test testSetChronometerCountDown()337 public void testSetChronometerCountDown() throws Throwable { 338 Chronometer chronometer = (Chronometer) mResult.findViewById(R.id.remoteView_chronometer); 339 340 mRemoteViews.setChronometerCountDown(R.id.remoteView_chronometer, true); 341 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 342 assertTrue(chronometer.isCountDown()); 343 344 mRemoteViews.setChronometerCountDown(R.id.remoteView_chronometer, false); 345 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 346 assertFalse(chronometer.isCountDown()); 347 348 mExpectedException.expect(ActionException.class); 349 mRemoteViews.setChronometerCountDown(R.id.remoteView_absolute, true); 350 mRemoteViews.reapply(mContext, mResult); 351 } 352 353 @Test testSetProgressBar()354 public void testSetProgressBar() throws Throwable { 355 ProgressBar progress = (ProgressBar) mResult.findViewById(R.id.remoteView_progress); 356 assertEquals(100, progress.getMax()); 357 assertEquals(0, progress.getProgress()); 358 // the view uses style progressBarHorizontal, so the default is false 359 assertFalse(progress.isIndeterminate()); 360 361 mRemoteViews.setProgressBar(R.id.remoteView_progress, 80, 50, true); 362 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 363 // make the bar indeterminate will not affect max and progress 364 assertEquals(100, progress.getMax()); 365 assertEquals(0, progress.getProgress()); 366 assertTrue(progress.isIndeterminate()); 367 368 mRemoteViews.setProgressBar(R.id.remoteView_progress, 60, 50, false); 369 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 370 assertEquals(60, progress.getMax()); 371 assertEquals(50, progress.getProgress()); 372 assertFalse(progress.isIndeterminate()); 373 374 mExpectedException.expect(ActionException.class); 375 mRemoteViews.setProgressBar(R.id.remoteView_relative, 60, 50, false); 376 mRemoteViews.reapply(mContext, mResult); 377 } 378 379 @Test testApply()380 public void testApply() { 381 assertNotNull(mResult); 382 assertNotNull(mResult.findViewById(R.id.remoteViews_good)); 383 assertNotNull(mResult.findViewById(R.id.remoteView_absolute)); 384 assertNotNull(mResult.findViewById(R.id.remoteView_chronometer)); 385 assertNotNull(mResult.findViewById(R.id.remoteView_frame)); 386 assertNotNull(mResult.findViewById(R.id.remoteView_image)); 387 assertNotNull(mResult.findViewById(R.id.remoteView_linear)); 388 assertNotNull(mResult.findViewById(R.id.remoteView_progress)); 389 assertNotNull(mResult.findViewById(R.id.remoteView_relative)); 390 assertNotNull(mResult.findViewById(R.id.remoteView_text)); 391 } 392 393 @Test testReapply()394 public void testReapply() throws Throwable { 395 ImageView image = (ImageView) mResult.findViewById(R.id.remoteView_image); 396 assertNull(image.getDrawable()); 397 398 mRemoteViews.setImageViewResource(R.id.remoteView_image, R.drawable.testimage); 399 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, image)); 400 assertNotNull(image.getDrawable()); 401 BitmapDrawable d = (BitmapDrawable) mContext 402 .getResources().getDrawable(R.drawable.testimage); 403 WidgetTestUtils.assertEquals(d.getBitmap(), 404 ((BitmapDrawable) image.getDrawable()).getBitmap()); 405 } 406 407 @Test testOnLoadClass()408 public void testOnLoadClass() { 409 mRemoteViews = new RemoteViews(Parcel.obtain()); 410 411 assertTrue(mRemoteViews.onLoadClass(AbsoluteLayout.class)); 412 assertTrue(mRemoteViews.onLoadClass(AnalogClock.class)); 413 assertTrue(mRemoteViews.onLoadClass(Button.class)); 414 assertTrue(mRemoteViews.onLoadClass(Chronometer.class)); 415 assertTrue(mRemoteViews.onLoadClass(FrameLayout.class)); 416 assertTrue(mRemoteViews.onLoadClass(GridLayout.class)); 417 assertTrue(mRemoteViews.onLoadClass(GridView.class)); 418 assertTrue(mRemoteViews.onLoadClass(ImageButton.class)); 419 assertTrue(mRemoteViews.onLoadClass(ImageView.class)); 420 assertTrue(mRemoteViews.onLoadClass(LinearLayout.class)); 421 assertTrue(mRemoteViews.onLoadClass(ListView.class)); 422 assertTrue(mRemoteViews.onLoadClass(ProgressBar.class)); 423 assertTrue(mRemoteViews.onLoadClass(RelativeLayout.class)); 424 assertTrue(mRemoteViews.onLoadClass(StackView.class)); 425 assertTrue(mRemoteViews.onLoadClass(TextClock.class)); 426 assertTrue(mRemoteViews.onLoadClass(TextView.class)); 427 assertTrue(mRemoteViews.onLoadClass(ViewFlipper.class)); 428 429 // those classes without annotation @RemoteView 430 assertFalse(mRemoteViews.onLoadClass(EditText.class)); 431 assertFalse(mRemoteViews.onLoadClass(DatePicker.class)); 432 assertFalse(mRemoteViews.onLoadClass(NumberPicker.class)); 433 assertFalse(mRemoteViews.onLoadClass(RatingBar.class)); 434 assertFalse(mRemoteViews.onLoadClass(SeekBar.class)); 435 } 436 437 @Test testDescribeContents()438 public void testDescribeContents() { 439 mRemoteViews = new RemoteViews(Parcel.obtain()); 440 mRemoteViews.describeContents(); 441 } 442 443 @Test testWriteToParcel()444 public void testWriteToParcel() { 445 mRemoteViews.setTextViewText(R.id.remoteView_text, "This is content"); 446 mRemoteViews.setViewVisibility(R.id.remoteView_frame, View.GONE); 447 Parcel p = Parcel.obtain(); 448 mRemoteViews.writeToParcel(p, 0); 449 p.setDataPosition(0); 450 451 // the package and layout are successfully written into parcel 452 mRemoteViews = RemoteViews.CREATOR.createFromParcel(p); 453 View result = mRemoteViews.apply(mContext, null); 454 assertEquals(PACKAGE_NAME, mRemoteViews.getPackage()); 455 assertEquals(R.layout.remoteviews_good, mRemoteViews.getLayoutId()); 456 assertEquals("This is content", ((TextView) result.findViewById(R.id.remoteView_text)) 457 .getText().toString()); 458 assertEquals(View.GONE, result.findViewById(R.id.remoteView_frame).getVisibility()); 459 460 p = Parcel.obtain(); 461 462 // currently the flag is not used 463 mRemoteViews.writeToParcel(p, -1); 464 465 p.recycle(); 466 467 RemoteViews[] remote = RemoteViews.CREATOR.newArray(1); 468 assertNotNull(remote); 469 assertEquals(1, remote.length); 470 } 471 472 @Test(expected=NullPointerException.class) testWriteNullToParcel()473 public void testWriteNullToParcel() { 474 mRemoteViews.writeToParcel(null, 0); 475 } 476 477 @Test(expected=NegativeArraySizeException.class) testCreateNegativeSizedArray()478 public void testCreateNegativeSizedArray() { 479 RemoteViews.CREATOR.newArray(-1); 480 } 481 482 @Test testSetImageViewBitmap()483 public void testSetImageViewBitmap() throws Throwable { 484 ImageView image = (ImageView) mResult.findViewById(R.id.remoteView_image); 485 assertNull(image.getDrawable()); 486 487 Bitmap bitmap = 488 BitmapFactory.decodeResource(mContext.getResources(), R.drawable.testimage); 489 mRemoteViews.setImageViewBitmap(R.id.remoteView_image, bitmap); 490 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 491 assertNotNull(image.getDrawable()); 492 WidgetTestUtils.assertEquals(bitmap, ((BitmapDrawable) image.getDrawable()).getBitmap()); 493 494 mExpectedException.expect(ActionException.class); 495 mRemoteViews.setImageViewBitmap(R.id.remoteView_absolute, bitmap); 496 mRemoteViews.reapply(mContext, mResult); 497 } 498 499 @Test testSetBitmap()500 public void testSetBitmap() throws Throwable { 501 ImageView image = (ImageView) mResult.findViewById(R.id.remoteView_image); 502 assertNull(image.getDrawable()); 503 504 Bitmap bitmap = 505 BitmapFactory.decodeResource(mContext.getResources(), R.drawable.testimage); 506 mRemoteViews.setBitmap(R.id.remoteView_image, "setImageBitmap", bitmap); 507 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 508 assertNotNull(image.getDrawable()); 509 WidgetTestUtils.assertEquals(bitmap, ((BitmapDrawable) image.getDrawable()).getBitmap()); 510 511 mExpectedException.expect(ActionException.class); 512 mRemoteViews.setBitmap(R.id.remoteView_absolute, "setImageBitmap", bitmap); 513 mRemoteViews.reapply(mContext, mResult); 514 } 515 516 @Test testSetBoolean()517 public void testSetBoolean() throws Throwable { 518 ProgressBar progress = (ProgressBar) mResult.findViewById(R.id.remoteView_progress); 519 // the view uses style progressBarHorizontal, so the default is false 520 assertFalse(progress.isIndeterminate()); 521 522 mRemoteViews.setBoolean(R.id.remoteView_progress, "setIndeterminate", true); 523 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 524 assertTrue(progress.isIndeterminate()); 525 526 mExpectedException.expect(ActionException.class); 527 mRemoteViews.setBoolean(R.id.remoteView_relative, "setIndeterminate", false); 528 mRemoteViews.reapply(mContext, mResult); 529 } 530 531 @Test testSetCharSequence()532 public void testSetCharSequence() throws Throwable { 533 TextView textView = (TextView) mResult.findViewById(R.id.remoteView_text); 534 assertEquals("", textView.getText().toString()); 535 536 String expected = "test setCharSequence"; 537 mRemoteViews.setCharSequence(R.id.remoteView_text, "setText", expected); 538 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 539 assertEquals(expected, textView.getText().toString()); 540 541 mRemoteViews.setCharSequence(R.id.remoteView_text, "setText", null); 542 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 543 assertEquals("", textView.getText().toString()); 544 545 mExpectedException.expect(ActionException.class); 546 mRemoteViews.setCharSequence(R.id.remoteView_absolute, "setText", ""); 547 mRemoteViews.reapply(mContext, mResult); 548 } 549 550 @Test testSetInt()551 public void testSetInt() throws Throwable { 552 View view = mResult.findViewById(R.id.remoteView_chronometer); 553 assertEquals(View.VISIBLE, view.getVisibility()); 554 555 mRemoteViews.setInt(R.id.remoteView_chronometer, "setVisibility", View.INVISIBLE); 556 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 557 assertEquals(View.INVISIBLE, view.getVisibility()); 558 559 mRemoteViews.setInt(R.id.remoteView_chronometer, "setVisibility", View.GONE); 560 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 561 assertEquals(View.GONE, view.getVisibility()); 562 563 mRemoteViews.setInt(R.id.remoteView_chronometer, "setVisibility", View.VISIBLE); 564 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 565 assertEquals(View.VISIBLE, view.getVisibility()); 566 } 567 568 @Test testSetString()569 public void testSetString() throws Throwable { 570 String format = "HH:MM:SS"; 571 Chronometer chronometer = (Chronometer) mResult.findViewById(R.id.remoteView_chronometer); 572 assertNull(chronometer.getFormat()); 573 574 mRemoteViews.setString(R.id.remoteView_chronometer, "setFormat", format); 575 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 576 assertEquals(format, chronometer.getFormat()); 577 578 mExpectedException.expect(ActionException.class); 579 mRemoteViews.setString(R.id.remoteView_image, "setFormat", format); 580 mRemoteViews.reapply(mContext, mResult); 581 } 582 583 @Test testSetUri()584 public void testSetUri() throws Throwable { 585 String path = getTestImagePath(); 586 File imagefile = new File(path); 587 588 try { 589 createSampleImage(imagefile, R.raw.testimage); 590 591 Uri uri = Uri.parse(path); 592 ImageView image = (ImageView) mResult.findViewById(R.id.remoteView_image); 593 assertNull(image.getDrawable()); 594 595 mRemoteViews.setUri(R.id.remoteView_image, "setImageURI", uri); 596 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 597 598 Bitmap imageViewBitmap = ((BitmapDrawable) image.getDrawable()).getBitmap(); 599 Bitmap expectedBitmap = WidgetTestUtils.getUnscaledAndDitheredBitmap( 600 mContext.getResources(), R.raw.testimage, imageViewBitmap.getConfig()); 601 WidgetTestUtils.assertEquals(expectedBitmap, imageViewBitmap); 602 603 mExpectedException.expect(ActionException.class); 604 mRemoteViews.setUri(R.id.remoteView_absolute, "setImageURI", uri); 605 mRemoteViews.reapply(mContext, mResult); 606 } finally { 607 // remove the test image file 608 imagefile.delete(); 609 } 610 } 611 612 @Test testSetTextColor()613 public void testSetTextColor() throws Throwable { 614 TextView textView = (TextView) mResult.findViewById(R.id.remoteView_text); 615 616 mRemoteViews.setTextColor(R.id.remoteView_text, R.color.testcolor1); 617 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 618 assertSame(ColorStateList.valueOf(R.color.testcolor1), textView.getTextColors()); 619 620 mRemoteViews.setTextColor(R.id.remoteView_text, R.color.testcolor2); 621 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 622 assertSame(ColorStateList.valueOf(R.color.testcolor2), textView.getTextColors()); 623 624 mExpectedException.expect(ActionException.class); 625 mRemoteViews.setTextColor(R.id.remoteView_absolute, R.color.testcolor1); 626 mRemoteViews.reapply(mContext, mResult); 627 } 628 629 @Test testSetTextCompoundDrawables()630 public void testSetTextCompoundDrawables() throws Throwable { 631 TextView textView = (TextView) mResult.findViewById(R.id.remoteView_text); 632 633 TestUtils.verifyCompoundDrawables(textView, -1, -1, -1, -1); 634 635 mRemoteViews.setTextViewCompoundDrawables(R.id.remoteView_text, R.drawable.start, 636 R.drawable.pass, R.drawable.failed, 0); 637 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 638 TestUtils.verifyCompoundDrawables(textView, R.drawable.start, R.drawable.failed, 639 R.drawable.pass, -1); 640 641 mRemoteViews.setTextViewCompoundDrawables(R.id.remoteView_text, 0, 642 R.drawable.icon_black, R.drawable.icon_red, R.drawable.icon_green); 643 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 644 TestUtils.verifyCompoundDrawables(textView, -1, R.drawable.icon_red, R.drawable.icon_black, 645 R.drawable.icon_green); 646 647 mExpectedException.expect(Throwable.class); 648 mRemoteViews.setTextViewCompoundDrawables(R.id.remoteView_absolute, 0, 649 R.drawable.start, R.drawable.failed, 0); 650 mRemoteViews.reapply(mContext, mResult); 651 } 652 653 @Test testSetTextCompoundDrawablesRelative()654 public void testSetTextCompoundDrawablesRelative() throws Throwable { 655 TextView textViewLtr = (TextView) mResult.findViewById(R.id.remoteView_text_ltr); 656 TextView textViewRtl = (TextView) mResult.findViewById(R.id.remoteView_text_rtl); 657 658 TestUtils.verifyCompoundDrawables(textViewLtr, -1, -1, -1, -1); 659 TestUtils.verifyCompoundDrawables(textViewRtl, -1, -1, -1, -1); 660 661 mRemoteViews.setTextViewCompoundDrawablesRelative(R.id.remoteView_text_ltr, 662 R.drawable.start, R.drawable.pass, R.drawable.failed, 0); 663 mRemoteViews.setTextViewCompoundDrawablesRelative(R.id.remoteView_text_rtl, 664 R.drawable.start, R.drawable.pass, R.drawable.failed, 0); 665 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 666 TestUtils.verifyCompoundDrawables(textViewLtr, R.drawable.start, R.drawable.failed, 667 R.drawable.pass, -1); 668 TestUtils.verifyCompoundDrawables(textViewRtl, R.drawable.failed, R.drawable.start, 669 R.drawable.pass, -1); 670 671 mRemoteViews.setTextViewCompoundDrawablesRelative(R.id.remoteView_text_ltr, 0, 672 R.drawable.icon_black, R.drawable.icon_red, R.drawable.icon_green); 673 mRemoteViews.setTextViewCompoundDrawablesRelative(R.id.remoteView_text_rtl, 0, 674 R.drawable.icon_black, R.drawable.icon_red, R.drawable.icon_green); 675 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 676 TestUtils.verifyCompoundDrawables(textViewLtr, -1, R.drawable.icon_red, 677 R.drawable.icon_black, R.drawable.icon_green); 678 TestUtils.verifyCompoundDrawables(textViewRtl, R.drawable.icon_red, -1, 679 R.drawable.icon_black, R.drawable.icon_green); 680 681 mExpectedException.expect(Throwable.class); 682 mRemoteViews.setTextViewCompoundDrawablesRelative(R.id.remoteView_absolute, 0, 683 R.drawable.start, R.drawable.failed, 0); 684 mRemoteViews.reapply(mContext, mResult); 685 } 686 687 @LargeTest 688 @Test testSetOnClickPendingIntent()689 public void testSetOnClickPendingIntent() throws Throwable { 690 Uri uri = Uri.parse("ctstest://RemoteView/test"); 691 ActivityMonitor am = mInstrumentation.addMonitor(MockURLSpanTestActivity.class.getName(), 692 null, false); 693 View view = mResult.findViewById(R.id.remoteView_image); 694 view.performClick(); 695 Activity newActivity = am.waitForActivityWithTimeout(TEST_TIMEOUT); 696 assertNull(newActivity); 697 698 Intent intent = new Intent(Intent.ACTION_VIEW, uri); 699 PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0); 700 mRemoteViews.setOnClickPendingIntent(R.id.remoteView_image, pendingIntent); 701 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 702 mActivityRule.runOnUiThread(() -> view.performClick()); 703 newActivity = am.waitForActivityWithTimeout(TEST_TIMEOUT); 704 assertNotNull(newActivity); 705 assertTrue(newActivity instanceof MockURLSpanTestActivity); 706 newActivity.finish(); 707 } 708 709 @Test testSetLong()710 public void testSetLong() throws Throwable { 711 long base1 = 50; 712 long base2 = -50; 713 Chronometer chronometer = (Chronometer) mResult.findViewById(R.id.remoteView_chronometer); 714 715 mRemoteViews.setLong(R.id.remoteView_chronometer, "setBase", base1); 716 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 717 assertEquals(base1, chronometer.getBase()); 718 719 mRemoteViews.setLong(R.id.remoteView_chronometer, "setBase", base2); 720 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 721 assertEquals(base2, chronometer.getBase()); 722 723 mExpectedException.expect(ActionException.class); 724 mRemoteViews.setLong(R.id.remoteView_absolute, "setBase", base1); 725 mRemoteViews.reapply(mContext, mResult); 726 } 727 728 @Test testSetFloat()729 public void testSetFloat() throws Throwable { 730 LinearLayout linearLayout = (LinearLayout) mResult.findViewById(R.id.remoteView_linear); 731 assertTrue(linearLayout.getWeightSum() <= 0.0f); 732 733 mRemoteViews.setFloat(R.id.remoteView_linear, "setWeightSum", 0.5f); 734 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 735 assertEquals(0.5f, linearLayout.getWeightSum(), 0.001f); 736 737 mExpectedException.expect(ActionException.class); 738 mRemoteViews.setFloat(R.id.remoteView_absolute, "setWeightSum", 1.0f); 739 mRemoteViews.reapply(mContext, mResult); 740 } 741 742 @Test testSetByte()743 public void testSetByte() throws Throwable { 744 MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom); 745 assertEquals(0, customView.getByteField()); 746 747 byte b = 100; 748 mRemoteViews.setByte(R.id.remoteView_custom, "setByteField", b); 749 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 750 assertEquals(b, customView.getByteField()); 751 752 mExpectedException.expect(ActionException.class); 753 mRemoteViews.setByte(R.id.remoteView_absolute, "setByteField", b); 754 mRemoteViews.reapply(mContext, mResult); 755 } 756 757 @Test testSetChar()758 public void testSetChar() throws Throwable { 759 MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom); 760 assertEquals('\u0000', customView.getCharField()); 761 762 mRemoteViews.setChar(R.id.remoteView_custom, "setCharField", 'q'); 763 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 764 assertEquals('q', customView.getCharField()); 765 766 mExpectedException.expect(ActionException.class); 767 mRemoteViews.setChar(R.id.remoteView_absolute, "setCharField", 'w'); 768 mRemoteViews.reapply(mContext, mResult); 769 } 770 771 @Test testSetDouble()772 public void testSetDouble() throws Throwable { 773 MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom); 774 assertEquals(0.0, customView.getDoubleField(), 0.0f); 775 776 mRemoteViews.setDouble(R.id.remoteView_custom, "setDoubleField", 0.5); 777 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 778 assertEquals(0.5, customView.getDoubleField(), 0.001f); 779 780 mExpectedException.expect(ActionException.class); 781 mRemoteViews.setDouble(R.id.remoteView_absolute, "setDoubleField", 1.0); 782 mRemoteViews.reapply(mContext, mResult); 783 } 784 785 @Test testSetShort()786 public void testSetShort() throws Throwable { 787 MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom); 788 assertEquals(0, customView.getShortField()); 789 790 short s = 25; 791 mRemoteViews.setShort(R.id.remoteView_custom, "setShortField", s); 792 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 793 assertEquals(s, customView.getShortField()); 794 795 mExpectedException.expect(ActionException.class); 796 mRemoteViews.setShort(R.id.remoteView_absolute, "setShortField", s); 797 mRemoteViews.reapply(mContext, mResult); 798 } 799 800 @Test testSetBundle()801 public void testSetBundle() throws Throwable { 802 MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom); 803 assertNull(customView.getBundleField()); 804 805 final Bundle bundle = new Bundle(); 806 bundle.putString("STR", "brexit"); 807 bundle.putInt("INT", 2016); 808 mRemoteViews.setBundle(R.id.remoteView_custom, "setBundleField", bundle); 809 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 810 final Bundle fromRemote = customView.getBundleField(); 811 assertEquals("brexit", fromRemote.getString("STR", "")); 812 assertEquals(2016, fromRemote.getInt("INT", 0)); 813 814 mExpectedException.expect(ActionException.class); 815 mRemoteViews.setBundle(R.id.remoteView_absolute, "setBundleField", bundle); 816 mRemoteViews.reapply(mContext, mResult); 817 } 818 819 @Test testSetIntent()820 public void testSetIntent() throws Throwable { 821 MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom); 822 assertNull(customView.getIntentField()); 823 824 final Intent intent = new Intent(mContext, SwitchCtsActivity.class); 825 intent.putExtra("STR", "brexit"); 826 intent.putExtra("INT", 2016); 827 mRemoteViews.setIntent(R.id.remoteView_custom, "setIntentField", intent); 828 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 829 final Intent fromRemote = customView.getIntentField(); 830 assertEquals(SwitchCtsActivity.class.getName(), fromRemote.getComponent().getClassName()); 831 assertEquals("brexit", fromRemote.getStringExtra("STR")); 832 assertEquals(2016, fromRemote.getIntExtra("INT", 0)); 833 834 mExpectedException.expect(ActionException.class); 835 mRemoteViews.setIntent(R.id.remoteView_absolute, "setIntentField", intent); 836 mRemoteViews.reapply(mContext, mResult); 837 } 838 839 @Test testRemoveAllViews()840 public void testRemoveAllViews() throws Throwable { 841 ViewGroup root = (ViewGroup) mResult.findViewById(R.id.remoteViews_good); 842 assertTrue(root.getChildCount() > 0); 843 844 mRemoteViews.removeAllViews(R.id.remoteViews_good); 845 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 846 assertEquals(0, root.getChildCount()); 847 } 848 849 @Test testAddView()850 public void testAddView() throws Throwable { 851 ViewGroup root = (ViewGroup) mResult.findViewById(R.id.remoteViews_good); 852 int originalChildCount = root.getChildCount(); 853 854 assertNull(root.findViewById(R.id.remoteView_frame_extra)); 855 856 // Create a RemoteViews wrapper around a layout and add it to our root 857 RemoteViews extra = new RemoteViews(PACKAGE_NAME, R.layout.remoteviews_extra); 858 mRemoteViews.addView(R.id.remoteViews_good, extra); 859 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 860 861 // Verify that our root has that layout as its last (new) child 862 assertEquals(originalChildCount + 1, root.getChildCount()); 863 assertNotNull(root.findViewById(R.id.remoteView_frame_extra)); 864 assertEquals(R.id.remoteView_frame_extra, root.getChildAt(originalChildCount).getId()); 865 } 866 867 @Test testSetLabelFor()868 public void testSetLabelFor() throws Throwable { 869 View labelView = mResult.findViewById(R.id.remoteView_label); 870 assertEquals(View.NO_ID, labelView.getLabelFor()); 871 872 mRemoteViews.setLabelFor(R.id.remoteView_label, R.id.remoteView_text); 873 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 874 assertEquals(R.id.remoteView_text, labelView.getLabelFor()); 875 } 876 877 @Test testSetAccessibilityTraversalAfter()878 public void testSetAccessibilityTraversalAfter() throws Throwable { 879 View textView = mResult.findViewById(R.id.remoteView_text); 880 881 mRemoteViews.setAccessibilityTraversalAfter(R.id.remoteView_text, R.id.remoteView_frame); 882 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 883 assertEquals(R.id.remoteView_frame, textView.getAccessibilityTraversalAfter()); 884 885 mRemoteViews.setAccessibilityTraversalAfter(R.id.remoteView_text, R.id.remoteView_linear); 886 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 887 assertEquals(R.id.remoteView_linear, textView.getAccessibilityTraversalAfter()); 888 } 889 890 @Test testSetAccessibilityTraversalBefore()891 public void testSetAccessibilityTraversalBefore() throws Throwable { 892 View textView = mResult.findViewById(R.id.remoteView_text); 893 894 mRemoteViews.setAccessibilityTraversalBefore(R.id.remoteView_text, R.id.remoteView_frame); 895 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 896 assertEquals(R.id.remoteView_frame, textView.getAccessibilityTraversalBefore()); 897 898 mRemoteViews.setAccessibilityTraversalBefore(R.id.remoteView_text, R.id.remoteView_linear); 899 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 900 assertEquals(R.id.remoteView_linear, textView.getAccessibilityTraversalBefore()); 901 } 902 903 @Test testSetViewPadding()904 public void testSetViewPadding() throws Throwable { 905 View textView = mResult.findViewById(R.id.remoteView_text); 906 907 mRemoteViews.setViewPadding(R.id.remoteView_text, 10, 20, 30, 40); 908 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 909 assertEquals(10, textView.getPaddingLeft()); 910 assertEquals(20, textView.getPaddingTop()); 911 assertEquals(30, textView.getPaddingRight()); 912 assertEquals(40, textView.getPaddingBottom()); 913 914 mRemoteViews.setViewPadding(R.id.remoteView_text, 40, 30, 20, 10); 915 mActivityRule.runOnUiThread(() -> mRemoteViews.reapply(mContext, mResult)); 916 assertEquals(40, textView.getPaddingLeft()); 917 assertEquals(30, textView.getPaddingTop()); 918 assertEquals(20, textView.getPaddingRight()); 919 assertEquals(10, textView.getPaddingBottom()); 920 } 921 createSampleImage(File imagefile, int resid)922 private void createSampleImage(File imagefile, int resid) throws IOException { 923 try (InputStream source = mContext.getResources().openRawResource(resid); 924 OutputStream target = new FileOutputStream(imagefile)) { 925 926 byte[] buffer = new byte[1024]; 927 for (int len = source.read(buffer); len > 0; len = source.read(buffer)) { 928 target.write(buffer, 0, len); 929 } 930 } 931 } 932 } 933