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 17 package android.media.tv.cts; 18 19 import android.app.Activity; 20 import android.app.Instrumentation; 21 import android.content.Context; 22 import android.cts.util.PollingCheck; 23 import android.media.PlaybackParams; 24 import android.media.tv.TvContentRating; 25 import android.media.tv.TvContract; 26 import android.media.tv.TvInputInfo; 27 import android.media.tv.TvInputManager; 28 import android.media.tv.TvRecordingClient; 29 import android.media.tv.TvTrackInfo; 30 import android.media.tv.TvView; 31 import android.media.tv.cts.TvInputServiceTest.CountingTvInputService.CountingSession; 32 import android.media.tv.cts.TvInputServiceTest.CountingTvInputService.CountingRecordingSession; 33 import android.net.Uri; 34 import android.os.Bundle; 35 import android.os.SystemClock; 36 import android.test.ActivityInstrumentationTestCase2; 37 import android.text.TextUtils; 38 import android.view.InputDevice; 39 import android.view.KeyEvent; 40 import android.view.MotionEvent; 41 import android.view.Surface; 42 import android.view.SurfaceView; 43 import android.view.View; 44 import android.widget.LinearLayout; 45 46 import android.tv.cts.R; 47 48 import java.util.ArrayList; 49 import java.util.Arrays; 50 import java.util.List; 51 import java.util.Objects; 52 import java.util.Set; 53 54 55 /** 56 * Test {@link android.media.tv.TvInputService}. 57 */ 58 public class TvInputServiceTest extends ActivityInstrumentationTestCase2<TvViewStubActivity> { 59 /** The maximum time to wait for an operation. */ 60 private static final long TIME_OUT = 15000L; 61 private static final String DUMMT_TRACK_ID = "dummyTrackId"; 62 private static final TvTrackInfo DUMMY_TRACK = 63 new TvTrackInfo.Builder(TvTrackInfo.TYPE_VIDEO, DUMMT_TRACK_ID) 64 .setVideoWidth(1920).setVideoHeight(1080).setLanguage("und").build(); 65 private static Bundle sDummyBundle; 66 67 private TvView mTvView; 68 private TvRecordingClient mTvRecordingClient; 69 private Activity mActivity; 70 private Instrumentation mInstrumentation; 71 private TvInputManager mManager; 72 private TvInputInfo mStubInfo; 73 private TvInputInfo mFaultyStubInfo; 74 private final StubCallback mCallback = new StubCallback(); 75 private final StubTimeShiftPositionCallback mTimeShiftPositionCallback = 76 new StubTimeShiftPositionCallback(); 77 private final StubRecordingCallback mRecordingCallback = new StubRecordingCallback(); 78 79 private static class StubCallback extends TvView.TvInputCallback { 80 private int mChannelRetunedCount; 81 private int mVideoAvailableCount; 82 private int mVideoUnavailableCount; 83 private int mTrackSelectedCount; 84 private int mTrackChangedCount; 85 private int mVideoSizeChanged; 86 private int mContentAllowedCount; 87 private int mContentBlockedCount; 88 private int mTimeShiftStatusChangedCount; 89 90 private Uri mChannelRetunedUri; 91 private Integer mVideoUnavailableReason; 92 private Integer mTrackSelectedType; 93 private String mTrackSelectedTrackId; 94 private List<TvTrackInfo> mTracksChangedTrackList; 95 private TvContentRating mContentBlockedRating; 96 private Integer mTimeShiftStatusChangedStatus; 97 98 @Override onChannelRetuned(String inputId, Uri channelUri)99 public void onChannelRetuned(String inputId, Uri channelUri) { 100 mChannelRetunedCount++; 101 mChannelRetunedUri = channelUri; 102 } 103 104 @Override onVideoAvailable(String inputId)105 public void onVideoAvailable(String inputId) { 106 mVideoAvailableCount++; 107 } 108 109 @Override onVideoUnavailable(String inputId, int reason)110 public void onVideoUnavailable(String inputId, int reason) { 111 mVideoUnavailableCount++; 112 mVideoUnavailableReason = reason; 113 } 114 115 @Override onTrackSelected(String inputId, int type, String trackId)116 public void onTrackSelected(String inputId, int type, String trackId) { 117 mTrackSelectedCount++; 118 mTrackSelectedType = type; 119 mTrackSelectedTrackId = trackId; 120 } 121 122 @Override onTracksChanged(String inputId, List<TvTrackInfo> trackList)123 public void onTracksChanged(String inputId, List<TvTrackInfo> trackList) { 124 mTrackChangedCount++; 125 mTracksChangedTrackList = trackList; 126 } 127 128 @Override onVideoSizeChanged(String inputId, int width, int height)129 public void onVideoSizeChanged(String inputId, int width, int height) { 130 mVideoSizeChanged++; 131 } 132 133 @Override onContentAllowed(String inputId)134 public void onContentAllowed(String inputId) { 135 mContentAllowedCount++; 136 } 137 138 @Override onContentBlocked(String inputId, TvContentRating rating)139 public void onContentBlocked(String inputId, TvContentRating rating) { 140 mContentBlockedCount++; 141 mContentBlockedRating = rating; 142 } 143 144 @Override onTimeShiftStatusChanged(String inputId, int status)145 public void onTimeShiftStatusChanged(String inputId, int status) { 146 mTimeShiftStatusChangedCount++; 147 mTimeShiftStatusChangedStatus = status; 148 } 149 resetCounts()150 public void resetCounts() { 151 mChannelRetunedCount = 0; 152 mVideoAvailableCount = 0; 153 mVideoUnavailableCount = 0; 154 mTrackSelectedCount = 0; 155 mTrackChangedCount = 0; 156 mContentAllowedCount = 0; 157 mContentBlockedCount = 0; 158 mTimeShiftStatusChangedCount = 0; 159 } 160 resetPassedValues()161 public void resetPassedValues() { 162 mChannelRetunedUri = null; 163 mVideoUnavailableReason = null; 164 mTrackSelectedType = null; 165 mTrackSelectedTrackId = null; 166 mTracksChangedTrackList = null; 167 mContentBlockedRating = null; 168 mTimeShiftStatusChangedStatus = null; 169 } 170 } 171 172 private static class StubTimeShiftPositionCallback extends TvView.TimeShiftPositionCallback { 173 private int mTimeShiftStartPositionChanged; 174 private int mTimeShiftCurrentPositionChanged; 175 176 @Override onTimeShiftStartPositionChanged(String inputId, long timeMs)177 public void onTimeShiftStartPositionChanged(String inputId, long timeMs) { 178 mTimeShiftStartPositionChanged++; 179 } 180 181 @Override onTimeShiftCurrentPositionChanged(String inputId, long timeMs)182 public void onTimeShiftCurrentPositionChanged(String inputId, long timeMs) { 183 mTimeShiftCurrentPositionChanged++; 184 } 185 resetCounts()186 public void resetCounts() { 187 mTimeShiftStartPositionChanged = 0; 188 mTimeShiftCurrentPositionChanged = 0; 189 } 190 } 191 TvInputServiceTest()192 public TvInputServiceTest() { 193 super(TvViewStubActivity.class); 194 } 195 196 @Override setUp()197 protected void setUp() throws Exception { 198 super.setUp(); 199 if (!Utils.hasTvInputFramework(getActivity())) { 200 return; 201 } 202 mActivity = getActivity(); 203 mInstrumentation = getInstrumentation(); 204 mTvView = (TvView) mActivity.findViewById(R.id.tvview); 205 mTvRecordingClient = new TvRecordingClient(mActivity, "TvInputServiceTest", 206 mRecordingCallback, null); 207 mManager = (TvInputManager) mActivity.getSystemService(Context.TV_INPUT_SERVICE); 208 for (TvInputInfo info : mManager.getTvInputList()) { 209 if (info.getServiceInfo().name.equals(CountingTvInputService.class.getName())) { 210 mStubInfo = info; 211 } 212 if (info.getServiceInfo().name.equals(FaultyTvInputService.class.getName())) { 213 mFaultyStubInfo = info; 214 } 215 if (mStubInfo != null && mFaultyStubInfo != null) { 216 break; 217 } 218 } 219 assertNotNull(mStubInfo); 220 mTvView.setCallback(mCallback); 221 222 CountingTvInputService.sSession = null; 223 } 224 testTvInputServiceSession()225 public void testTvInputServiceSession() throws Throwable { 226 if (!Utils.hasTvInputFramework(getActivity())) { 227 return; 228 } 229 initDummyBundle(); 230 verifyCommandTune(); 231 verifyCommandTuneWithBundle(); 232 verifyCommandSendAppPrivateCommand(); 233 verifyCommandSetStreamVolume(); 234 verifyCommandSetCaptionEnabled(); 235 verifyCommandSelectTrack(); 236 verifyCommandDispatchKeyDown(); 237 verifyCommandDispatchKeyMultiple(); 238 verifyCommandDispatchKeyUp(); 239 verifyCommandDispatchTouchEvent(); 240 verifyCommandDispatchTrackballEvent(); 241 verifyCommandDispatchGenericMotionEvent(); 242 verifyCommandTimeShiftPause(); 243 verifyCommandTimeShiftResume(); 244 verifyCommandTimeShiftSeekTo(); 245 verifyCommandTimeShiftSetPlaybackParams(); 246 verifyCommandTimeShiftPlay(); 247 verifyCommandSetTimeShiftPositionCallback(); 248 verifyCommandOverlayViewSizeChanged(); 249 verifyCallbackChannelRetuned(); 250 verifyCallbackVideoAvailable(); 251 verifyCallbackVideoUnavailable(); 252 verifyCallbackTracksChanged(); 253 verifyCallbackTrackSelected(); 254 verifyCallbackVideoSizeChanged(); 255 verifyCallbackContentAllowed(); 256 verifyCallbackContentBlocked(); 257 verifyCallbackTimeShiftStatusChanged(); 258 verifyCallbackLayoutSurface(); 259 260 runTestOnUiThread(new Runnable() { 261 @Override 262 public void run() { 263 mTvView.reset(); 264 } 265 }); 266 mInstrumentation.waitForIdleSync(); 267 } 268 testTvInputServiceRecordingSession()269 public void testTvInputServiceRecordingSession() throws Throwable { 270 if (!Utils.hasTvInputFramework(getActivity())) { 271 return; 272 } 273 initDummyBundle(); 274 verifyCommandTuneForRecording(); 275 verifyCallbackConnectionFailed(); 276 verifyCommandTuneForRecordingWithBundle(); 277 verifyCallbackTuned(); 278 verifyCommandStartRecording(); 279 verifyCommandStopRecording(); 280 verifyCommandSendAppPrivateCommandForRecording(); 281 verifyCallbackRecordingStopped(); 282 verifyCallbackError(); 283 verifyCommandRelease(); 284 verifyCallbackDisconnected(); 285 } 286 verifyCommandTuneForRecording()287 public void verifyCommandTuneForRecording() { 288 resetCounts(); 289 resetPassedValues(); 290 final Uri fakeChannelUri = TvContract.buildChannelUri(0); 291 mTvRecordingClient.tune(mStubInfo.getId(), fakeChannelUri); 292 new PollingCheck(TIME_OUT) { 293 @Override 294 protected boolean check() { 295 final CountingRecordingSession session = CountingTvInputService.sRecordingSession; 296 return session != null && session.mTuneCount > 0 297 && Objects.equals(session.mTunedChannelUri, fakeChannelUri); 298 } 299 }.run(); 300 } 301 verifyCommandTuneForRecordingWithBundle()302 public void verifyCommandTuneForRecordingWithBundle() { 303 resetCounts(); 304 resetPassedValues(); 305 final Uri fakeChannelUri = TvContract.buildChannelUri(0); 306 mTvRecordingClient.tune(mStubInfo.getId(), fakeChannelUri, sDummyBundle); 307 new PollingCheck(TIME_OUT) { 308 @Override 309 protected boolean check() { 310 final CountingRecordingSession session = CountingTvInputService.sRecordingSession; 311 return session != null 312 && session.mTuneCount > 0 313 && session.mTuneWithBundleCount > 0 314 && Objects.equals(session.mTunedChannelUri, fakeChannelUri) 315 && bundleEquals(session.mTuneWithBundleData, sDummyBundle); 316 } 317 }.run(); 318 } 319 verifyCommandRelease()320 public void verifyCommandRelease() { 321 resetCounts(); 322 mTvRecordingClient.release(); 323 new PollingCheck(TIME_OUT) { 324 @Override 325 protected boolean check() { 326 final CountingRecordingSession session = CountingTvInputService.sRecordingSession; 327 return session != null && session.mReleaseCount > 0; 328 } 329 }.run(); 330 } 331 verifyCommandStartRecording()332 public void verifyCommandStartRecording() { 333 resetCounts(); 334 resetPassedValues(); 335 final Uri fakeChannelUri = TvContract.buildChannelUri(0); 336 mTvRecordingClient.startRecording(fakeChannelUri); 337 new PollingCheck(TIME_OUT) { 338 @Override 339 protected boolean check() { 340 final CountingRecordingSession session = CountingTvInputService.sRecordingSession; 341 return session != null 342 && session.mStartRecordingCount > 0 343 && Objects.equals(session.mProgramHint, fakeChannelUri); 344 } 345 }.run(); 346 } 347 verifyCommandStopRecording()348 public void verifyCommandStopRecording() { 349 resetCounts(); 350 mTvRecordingClient.stopRecording(); 351 new PollingCheck(TIME_OUT) { 352 @Override 353 protected boolean check() { 354 final CountingRecordingSession session = CountingTvInputService.sRecordingSession; 355 return session != null && session.mStopRecordingCount > 0; 356 } 357 }.run(); 358 } 359 verifyCommandSendAppPrivateCommandForRecording()360 public void verifyCommandSendAppPrivateCommandForRecording() { 361 resetCounts(); 362 resetPassedValues(); 363 final String action = "android.media.tv.cts.TvInputServiceTest.privateCommand"; 364 mTvRecordingClient.sendAppPrivateCommand(action, sDummyBundle); 365 new PollingCheck(TIME_OUT) { 366 @Override 367 protected boolean check() { 368 final CountingRecordingSession session = CountingTvInputService.sRecordingSession; 369 return session != null 370 && session.mAppPrivateCommandCount > 0 371 && bundleEquals(session.mAppPrivateCommandData, sDummyBundle) 372 && TextUtils.equals(session.mAppPrivateCommandAction, action); 373 } 374 }.run(); 375 } 376 verifyCallbackTuned()377 public void verifyCallbackTuned() { 378 resetCounts(); 379 resetPassedValues(); 380 final CountingRecordingSession session = CountingTvInputService.sRecordingSession; 381 assertNotNull(session); 382 final Uri fakeChannelUri = TvContract.buildChannelUri(0); 383 session.notifyTuned(fakeChannelUri); 384 new PollingCheck(TIME_OUT) { 385 @Override 386 protected boolean check() { 387 return mRecordingCallback.mTunedCount > 0 388 && Objects.equals(mRecordingCallback.mTunedChannelUri, fakeChannelUri); 389 } 390 }.run(); 391 } 392 verifyCallbackError()393 public void verifyCallbackError() { 394 resetCounts(); 395 resetPassedValues(); 396 final CountingRecordingSession session = CountingTvInputService.sRecordingSession; 397 assertNotNull(session); 398 final int error = TvInputManager.RECORDING_ERROR_UNKNOWN; 399 session.notifyError(error); 400 new PollingCheck(TIME_OUT) { 401 @Override 402 protected boolean check() { 403 return mRecordingCallback.mErrorCount > 0 404 && mRecordingCallback.mError == error; 405 } 406 }.run(); 407 } 408 verifyCallbackRecordingStopped()409 public void verifyCallbackRecordingStopped() { 410 resetCounts(); 411 resetPassedValues(); 412 final CountingRecordingSession session = CountingTvInputService.sRecordingSession; 413 assertNotNull(session); 414 final Uri fakeChannelUri = TvContract.buildChannelUri(0); 415 session.notifyRecordingStopped(fakeChannelUri); 416 new PollingCheck(TIME_OUT) { 417 @Override 418 protected boolean check() { 419 return mRecordingCallback.mRecordingStoppedCount > 0 420 && Objects.equals(mRecordingCallback.mRecordedProgramUri, fakeChannelUri); 421 } 422 }.run(); 423 } 424 verifyCallbackConnectionFailed()425 public void verifyCallbackConnectionFailed() { 426 resetCounts(); 427 final Uri fakeChannelUri = TvContract.buildChannelUri(0); 428 mTvRecordingClient.tune("invalid_input_id", fakeChannelUri); 429 new PollingCheck(TIME_OUT) { 430 @Override 431 protected boolean check() { 432 return mRecordingCallback.mConnectionFailedCount > 0; 433 } 434 }.run(); 435 } 436 verifyCallbackDisconnected()437 public void verifyCallbackDisconnected() { 438 resetCounts(); 439 final Uri fakeChannelUri = TvContract.buildChannelUri(0); 440 mTvRecordingClient.tune(mFaultyStubInfo.getId(), fakeChannelUri); 441 new PollingCheck(TIME_OUT) { 442 @Override 443 protected boolean check() { 444 return mRecordingCallback.mDisconnectedCount > 0; 445 } 446 }.run(); 447 } 448 verifyCommandTune()449 public void verifyCommandTune() { 450 resetCounts(); 451 resetPassedValues(); 452 final Uri fakeChannelUri = TvContract.buildChannelUri(0); 453 mTvView.tune(mStubInfo.getId(), fakeChannelUri); 454 mInstrumentation.waitForIdleSync(); 455 new PollingCheck(TIME_OUT) { 456 @Override 457 protected boolean check() { 458 final CountingSession session = CountingTvInputService.sSession; 459 return session != null 460 && session.mTuneCount > 0 461 && session.mCreateOverlayView > 0 462 && Objects.equals(session.mTunedChannelUri, fakeChannelUri); 463 } 464 }.run(); 465 } 466 verifyCommandTuneWithBundle()467 public void verifyCommandTuneWithBundle() { 468 resetCounts(); 469 resetPassedValues(); 470 final Uri fakeChannelUri = TvContract.buildChannelUri(0); 471 mTvView.tune(mStubInfo.getId(), fakeChannelUri, sDummyBundle); 472 mInstrumentation.waitForIdleSync(); 473 new PollingCheck(TIME_OUT) { 474 @Override 475 protected boolean check() { 476 final CountingSession session = CountingTvInputService.sSession; 477 return session != null 478 && session.mTuneCount > 0 479 && session.mTuneWithBundleCount > 0 480 && Objects.equals(session.mTunedChannelUri, fakeChannelUri) 481 && bundleEquals(session.mTuneWithBundleData, sDummyBundle); 482 } 483 }.run(); 484 } 485 verifyCommandSetStreamVolume()486 public void verifyCommandSetStreamVolume() { 487 resetCounts(); 488 resetPassedValues(); 489 final float volume = 0.8f; 490 mTvView.setStreamVolume(volume); 491 mInstrumentation.waitForIdleSync(); 492 new PollingCheck(TIME_OUT) { 493 @Override 494 protected boolean check() { 495 final CountingSession session = CountingTvInputService.sSession; 496 return session != null && session.mSetStreamVolumeCount > 0 497 && session.mStreamVolume == volume; 498 } 499 }.run(); 500 } 501 verifyCommandSetCaptionEnabled()502 public void verifyCommandSetCaptionEnabled() { 503 resetCounts(); 504 resetPassedValues(); 505 final boolean enable = true; 506 mTvView.setCaptionEnabled(enable); 507 mInstrumentation.waitForIdleSync(); 508 new PollingCheck(TIME_OUT) { 509 @Override 510 protected boolean check() { 511 final CountingSession session = CountingTvInputService.sSession; 512 return session != null && session.mSetCaptionEnabledCount > 0 513 && session.mCaptionEnabled == enable; 514 } 515 }.run(); 516 } 517 verifyCommandSelectTrack()518 public void verifyCommandSelectTrack() { 519 resetCounts(); 520 resetPassedValues(); 521 verifyCallbackTracksChanged(); 522 final int dummyTrackType = DUMMY_TRACK.getType(); 523 final String dummyTrackId = DUMMY_TRACK.getId(); 524 mTvView.selectTrack(dummyTrackType, dummyTrackId); 525 mInstrumentation.waitForIdleSync(); 526 new PollingCheck(TIME_OUT) { 527 @Override 528 protected boolean check() { 529 final CountingSession session = CountingTvInputService.sSession; 530 return session != null 531 && session.mSelectTrackCount > 0 532 && session.mSelectTrackType == dummyTrackType 533 && TextUtils.equals(session.mSelectTrackId, dummyTrackId); 534 } 535 }.run(); 536 } 537 verifyCommandDispatchKeyDown()538 public void verifyCommandDispatchKeyDown() { 539 resetCounts(); 540 resetPassedValues(); 541 final int keyCode = KeyEvent.KEYCODE_Q; 542 final KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode); 543 mTvView.dispatchKeyEvent(event); 544 mInstrumentation.waitForIdleSync(); 545 new PollingCheck(TIME_OUT) { 546 @Override 547 protected boolean check() { 548 final CountingSession session = CountingTvInputService.sSession; 549 return session != null 550 && session.mKeyDownCount > 0 551 && session.mKeyDownCode == keyCode 552 && keyEventEquals(event, session.mKeyDownEvent); 553 } 554 }.run(); 555 } 556 verifyCommandDispatchKeyMultiple()557 public void verifyCommandDispatchKeyMultiple() { 558 resetCounts(); 559 resetPassedValues(); 560 final int keyCode = KeyEvent.KEYCODE_Q; 561 final KeyEvent event = new KeyEvent(KeyEvent.ACTION_MULTIPLE, keyCode); 562 mTvView.dispatchKeyEvent(event); 563 mInstrumentation.waitForIdleSync(); 564 new PollingCheck(TIME_OUT) { 565 @Override 566 protected boolean check() { 567 final CountingSession session = CountingTvInputService.sSession; 568 return session != null 569 && session.mKeyMultipleCount > 0 570 && session.mKeyMultipleCode == keyCode 571 && keyEventEquals(event, session.mKeyMultipleEvent) 572 && session.mKeyMultipleNumber == event.getRepeatCount(); 573 } 574 }.run(); 575 } 576 verifyCommandDispatchKeyUp()577 public void verifyCommandDispatchKeyUp() { 578 resetCounts(); 579 resetPassedValues(); 580 final int keyCode = KeyEvent.KEYCODE_Q; 581 final KeyEvent event = new KeyEvent(KeyEvent.ACTION_UP, keyCode); 582 mTvView.dispatchKeyEvent(event); 583 mInstrumentation.waitForIdleSync(); 584 new PollingCheck(TIME_OUT) { 585 @Override 586 protected boolean check() { 587 final CountingSession session = CountingTvInputService.sSession; 588 return session != null 589 && session.mKeyUpCount > 0 590 && session.mKeyUpCode == keyCode 591 && keyEventEquals(event, session.mKeyUpEvent); 592 } 593 }.run(); 594 } 595 verifyCommandDispatchTouchEvent()596 public void verifyCommandDispatchTouchEvent() { 597 resetCounts(); 598 resetPassedValues(); 599 final long now = SystemClock.uptimeMillis(); 600 final MotionEvent event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 1.0f, 1.0f, 601 1.0f, 1.0f, 0, 1.0f, 1.0f, 0, 0); 602 event.setSource(InputDevice.SOURCE_TOUCHSCREEN); 603 mTvView.dispatchTouchEvent(event); 604 mInstrumentation.waitForIdleSync(); 605 new PollingCheck(TIME_OUT) { 606 @Override 607 protected boolean check() { 608 final CountingSession session = CountingTvInputService.sSession; 609 return session != null 610 && session.mTouchEventCount > 0 611 && motionEventEquals(session.mTouchEvent, event); 612 } 613 }.run(); 614 } 615 verifyCommandDispatchTrackballEvent()616 public void verifyCommandDispatchTrackballEvent() { 617 resetCounts(); 618 resetPassedValues(); 619 final long now = SystemClock.uptimeMillis(); 620 final MotionEvent event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 1.0f, 1.0f, 621 1.0f, 1.0f, 0, 1.0f, 1.0f, 0, 0); 622 event.setSource(InputDevice.SOURCE_TRACKBALL); 623 mTvView.dispatchTouchEvent(event); 624 mInstrumentation.waitForIdleSync(); 625 new PollingCheck(TIME_OUT) { 626 @Override 627 protected boolean check() { 628 final CountingSession session = CountingTvInputService.sSession; 629 return session != null 630 && session.mTrackballEventCount > 0 631 && motionEventEquals(session.mTrackballEvent, event); 632 } 633 }.run(); 634 } 635 verifyCommandDispatchGenericMotionEvent()636 public void verifyCommandDispatchGenericMotionEvent() { 637 resetCounts(); 638 resetPassedValues(); 639 final long now = SystemClock.uptimeMillis(); 640 final MotionEvent event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 1.0f, 1.0f, 641 1.0f, 1.0f, 0, 1.0f, 1.0f, 0, 0); 642 mTvView.dispatchGenericMotionEvent(event); 643 mInstrumentation.waitForIdleSync(); 644 new PollingCheck(TIME_OUT) { 645 @Override 646 protected boolean check() { 647 final CountingSession session = CountingTvInputService.sSession; 648 return session != null 649 && session.mGenricMotionEventCount > 0 650 && motionEventEquals(session.mGenricMotionEvent, event); 651 } 652 }.run(); 653 } 654 verifyCommandTimeShiftPause()655 public void verifyCommandTimeShiftPause() { 656 resetCounts(); 657 mTvView.timeShiftPause(); 658 mInstrumentation.waitForIdleSync(); 659 new PollingCheck(TIME_OUT) { 660 @Override 661 protected boolean check() { 662 final CountingSession session = CountingTvInputService.sSession; 663 return session != null && session.mTimeShiftPauseCount > 0; 664 } 665 }.run(); 666 } 667 verifyCommandTimeShiftResume()668 public void verifyCommandTimeShiftResume() { 669 resetCounts(); 670 mTvView.timeShiftResume(); 671 mInstrumentation.waitForIdleSync(); 672 new PollingCheck(TIME_OUT) { 673 @Override 674 protected boolean check() { 675 final CountingSession session = CountingTvInputService.sSession; 676 return session != null && session.mTimeShiftResumeCount > 0; 677 } 678 }.run(); 679 } 680 verifyCommandTimeShiftSeekTo()681 public void verifyCommandTimeShiftSeekTo() { 682 resetCounts(); 683 resetPassedValues(); 684 final long timeMs = 0; 685 mTvView.timeShiftSeekTo(timeMs); 686 mInstrumentation.waitForIdleSync(); 687 new PollingCheck(TIME_OUT) { 688 @Override 689 protected boolean check() { 690 final CountingSession session = CountingTvInputService.sSession; 691 return session != null && session.mTimeShiftSeekToCount > 0 692 && session.mTimeShiftSeekTo == timeMs; 693 } 694 }.run(); 695 } 696 verifyCommandTimeShiftSetPlaybackParams()697 public void verifyCommandTimeShiftSetPlaybackParams() { 698 resetCounts(); 699 resetPassedValues(); 700 final PlaybackParams param = new PlaybackParams().setSpeed(2.0f) 701 .setAudioFallbackMode(PlaybackParams.AUDIO_FALLBACK_MODE_DEFAULT); 702 mTvView.timeShiftSetPlaybackParams(param); 703 mInstrumentation.waitForIdleSync(); 704 new PollingCheck(TIME_OUT) { 705 @Override 706 protected boolean check() { 707 final CountingSession session = CountingTvInputService.sSession; 708 return session != null && session.mTimeShiftSetPlaybackParamsCount > 0 709 && playbackParamsEquals(session.mTimeShiftSetPlaybackParams, param); 710 } 711 }.run(); 712 } 713 verifyCommandTimeShiftPlay()714 public void verifyCommandTimeShiftPlay() { 715 resetCounts(); 716 resetPassedValues(); 717 final Uri fakeRecordedProgramUri = TvContract.buildRecordedProgramUri(0); 718 mTvView.timeShiftPlay(mStubInfo.getId(), fakeRecordedProgramUri); 719 mInstrumentation.waitForIdleSync(); 720 new PollingCheck(TIME_OUT) { 721 @Override 722 protected boolean check() { 723 final CountingSession session = CountingTvInputService.sSession; 724 return session != null && session.mTimeShiftPlayCount > 0 725 && Objects.equals(session.mRecordedProgramUri, fakeRecordedProgramUri); 726 } 727 }.run(); 728 } 729 verifyCommandSetTimeShiftPositionCallback()730 public void verifyCommandSetTimeShiftPositionCallback() { 731 resetCounts(); 732 mTvView.setTimeShiftPositionCallback(mTimeShiftPositionCallback); 733 mInstrumentation.waitForIdleSync(); 734 new PollingCheck(TIME_OUT) { 735 @Override 736 protected boolean check() { 737 return mTimeShiftPositionCallback.mTimeShiftCurrentPositionChanged > 0 738 && mTimeShiftPositionCallback.mTimeShiftStartPositionChanged > 0; 739 } 740 }.run(); 741 } 742 verifyCommandOverlayViewSizeChanged()743 public void verifyCommandOverlayViewSizeChanged() { 744 resetCounts(); 745 resetPassedValues(); 746 final int width = 10; 747 final int height = 20; 748 mActivity.runOnUiThread(new Runnable() { 749 public void run() { 750 mTvView.setLayoutParams(new LinearLayout.LayoutParams(width, height)); 751 } 752 }); 753 mInstrumentation.waitForIdleSync(); 754 new PollingCheck(TIME_OUT) { 755 @Override 756 protected boolean check() { 757 final CountingSession session = CountingTvInputService.sSession; 758 return session != null 759 && session.mOverlayViewSizeChangedCount > 0 760 && session.mOverlayViewSizeChangedWidth == width 761 && session.mOverlayViewSizeChangedHeight == height; 762 } 763 }.run(); 764 } 765 verifyCommandSendAppPrivateCommand()766 public void verifyCommandSendAppPrivateCommand() { 767 resetCounts(); 768 final String action = "android.media.tv.cts.TvInputServiceTest.privateCommand"; 769 mTvView.sendAppPrivateCommand(action, sDummyBundle); 770 mInstrumentation.waitForIdleSync(); 771 new PollingCheck(TIME_OUT) { 772 @Override 773 protected boolean check() { 774 final CountingSession session = CountingTvInputService.sSession; 775 return session != null 776 && session.mAppPrivateCommandCount > 0 777 && bundleEquals(session.mAppPrivateCommandData, sDummyBundle) 778 && TextUtils.equals(session.mAppPrivateCommandAction, action); 779 } 780 }.run(); 781 } 782 verifyCallbackChannelRetuned()783 public void verifyCallbackChannelRetuned() { 784 resetCounts(); 785 resetPassedValues(); 786 final CountingSession session = CountingTvInputService.sSession; 787 assertNotNull(session); 788 final Uri fakeChannelUri = TvContract.buildChannelUri(0); 789 session.notifyChannelRetuned(fakeChannelUri); 790 new PollingCheck(TIME_OUT) { 791 @Override 792 protected boolean check() { 793 return mCallback.mChannelRetunedCount > 0 794 && Objects.equals(mCallback.mChannelRetunedUri, fakeChannelUri); 795 } 796 }.run(); 797 } 798 verifyCallbackVideoAvailable()799 public void verifyCallbackVideoAvailable() { 800 resetCounts(); 801 final CountingSession session = CountingTvInputService.sSession; 802 assertNotNull(session); 803 session.notifyVideoAvailable(); 804 new PollingCheck(TIME_OUT) { 805 @Override 806 protected boolean check() { 807 return mCallback.mVideoAvailableCount > 0; 808 } 809 }.run(); 810 } 811 verifyCallbackVideoUnavailable()812 public void verifyCallbackVideoUnavailable() { 813 resetCounts(); 814 resetPassedValues(); 815 final CountingSession session = CountingTvInputService.sSession; 816 assertNotNull(session); 817 final int reason = TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING; 818 session.notifyVideoUnavailable(reason); 819 new PollingCheck(TIME_OUT) { 820 @Override 821 protected boolean check() { 822 return mCallback.mVideoUnavailableCount > 0 823 && mCallback.mVideoUnavailableReason == reason; 824 } 825 }.run(); 826 } 827 verifyCallbackTracksChanged()828 public void verifyCallbackTracksChanged() { 829 resetCounts(); 830 resetPassedValues(); 831 final CountingSession session = CountingTvInputService.sSession; 832 assertNotNull(session); 833 ArrayList<TvTrackInfo> tracks = new ArrayList<>(); 834 tracks.add(DUMMY_TRACK); 835 session.notifyTracksChanged(tracks); 836 new PollingCheck(TIME_OUT) { 837 @Override 838 protected boolean check() { 839 return mCallback.mTrackChangedCount > 0 840 && Objects.equals(mCallback.mTracksChangedTrackList, tracks); 841 } 842 }.run(); 843 } 844 verifyCallbackVideoSizeChanged()845 public void verifyCallbackVideoSizeChanged() { 846 resetCounts(); 847 final CountingSession session = CountingTvInputService.sSession; 848 assertNotNull(session); 849 ArrayList<TvTrackInfo> tracks = new ArrayList<>(); 850 tracks.add(DUMMY_TRACK); 851 session.notifyTracksChanged(tracks); 852 new PollingCheck(TIME_OUT) { 853 @Override 854 protected boolean check() { 855 return mCallback.mVideoSizeChanged > 0; 856 } 857 }.run(); 858 } 859 verifyCallbackTrackSelected()860 public void verifyCallbackTrackSelected() { 861 resetCounts(); 862 resetPassedValues(); 863 final CountingSession session = CountingTvInputService.sSession; 864 assertNotNull(session); 865 assertNotNull(DUMMY_TRACK); 866 session.notifyTrackSelected(DUMMY_TRACK.getType(), DUMMY_TRACK.getId()); 867 new PollingCheck(TIME_OUT) { 868 @Override 869 protected boolean check() { 870 return mCallback.mTrackSelectedCount > 0 871 && mCallback.mTrackSelectedType == DUMMY_TRACK.getType() 872 && TextUtils.equals(DUMMY_TRACK.getId(), mCallback.mTrackSelectedTrackId); 873 } 874 }.run(); 875 } 876 verifyCallbackContentAllowed()877 public void verifyCallbackContentAllowed() { 878 resetCounts(); 879 final CountingSession session = CountingTvInputService.sSession; 880 assertNotNull(session); 881 session.notifyContentAllowed(); 882 new PollingCheck(TIME_OUT) { 883 @Override 884 protected boolean check() { 885 return mCallback.mContentAllowedCount > 0; 886 } 887 }.run(); 888 } 889 verifyCallbackContentBlocked()890 public void verifyCallbackContentBlocked() { 891 resetCounts(); 892 resetPassedValues(); 893 final CountingSession session = CountingTvInputService.sSession; 894 assertNotNull(session); 895 final TvContentRating rating = TvContentRating.createRating("android.media.tv", "US_TVPG", 896 "US_TVPG_TV_MA", "US_TVPG_S", "US_TVPG_V"); 897 session.notifyContentBlocked(rating); 898 new PollingCheck(TIME_OUT) { 899 @Override 900 protected boolean check() { 901 return mCallback.mContentBlockedCount > 0 902 && Objects.equals(mCallback.mContentBlockedRating, rating); 903 } 904 }.run(); 905 } 906 verifyCallbackTimeShiftStatusChanged()907 public void verifyCallbackTimeShiftStatusChanged() { 908 resetCounts(); 909 resetPassedValues(); 910 final CountingSession session = CountingTvInputService.sSession; 911 assertNotNull(session); 912 final int status = TvInputManager.TIME_SHIFT_STATUS_AVAILABLE; 913 session.notifyTimeShiftStatusChanged(status); 914 new PollingCheck(TIME_OUT) { 915 @Override 916 protected boolean check() { 917 return mCallback.mTimeShiftStatusChangedCount > 0 918 && mCallback.mTimeShiftStatusChangedStatus == status; 919 } 920 }.run(); 921 } 922 verifyCallbackLayoutSurface()923 public void verifyCallbackLayoutSurface() { 924 resetCounts(); 925 final int left = 10; 926 final int top = 20; 927 final int right = 30; 928 final int bottom = 40; 929 final CountingSession session = CountingTvInputService.sSession; 930 assertNotNull(session); 931 session.layoutSurface(left, top, right, bottom); 932 new PollingCheck(TIME_OUT) { 933 @Override 934 protected boolean check() { 935 int childCount = mTvView.getChildCount(); 936 for (int i = 0; i < childCount; ++i) { 937 View v = mTvView.getChildAt(i); 938 if (v instanceof SurfaceView) { 939 return v.getLeft() == left && v.getTop() == top && v.getRight() == right 940 && v.getBottom() == bottom; 941 } 942 } 943 return false; 944 } 945 }.run(); 946 } 947 keyEventEquals(KeyEvent event, KeyEvent other)948 public static boolean keyEventEquals(KeyEvent event, KeyEvent other) { 949 if (event == other) return true; 950 if (event == null || other == null) return false; 951 return event.getDownTime() == other.getDownTime() 952 && event.getEventTime() == other.getEventTime() 953 && event.getAction() == other.getAction() 954 && event.getKeyCode() == other.getKeyCode() 955 && event.getRepeatCount() == other.getRepeatCount() 956 && event.getMetaState() == other.getMetaState() 957 && event.getDeviceId() == other.getDeviceId() 958 && event.getScanCode() == other.getScanCode() 959 && event.getFlags() == other.getFlags() 960 && event.getSource() == other.getSource() 961 && TextUtils.equals(event.getCharacters(), other.getCharacters()); 962 } 963 motionEventEquals(MotionEvent event, MotionEvent other)964 public static boolean motionEventEquals(MotionEvent event, MotionEvent other) { 965 if (event == other) return true; 966 if (event == null || other == null) return false; 967 return event.getDownTime() == other.getDownTime() 968 && event.getEventTime() == other.getEventTime() 969 && event.getAction() == other.getAction() 970 && event.getX() == other.getX() 971 && event.getY() == other.getY() 972 && event.getPressure() == other.getPressure() 973 && event.getSize() == other.getSize() 974 && event.getMetaState() == other.getMetaState() 975 && event.getXPrecision() == other.getXPrecision() 976 && event.getYPrecision() == other.getYPrecision() 977 && event.getDeviceId() == other.getDeviceId() 978 && event.getEdgeFlags() == other.getEdgeFlags() 979 && event.getSource() == other.getSource(); 980 } 981 playbackParamsEquals(PlaybackParams param, PlaybackParams other)982 public static boolean playbackParamsEquals(PlaybackParams param, PlaybackParams other) { 983 if (param == other) return true; 984 if (param == null || other == null) return false; 985 return param.getAudioFallbackMode() == other.getAudioFallbackMode() 986 && param.getSpeed() == other.getSpeed(); 987 } 988 bundleEquals(Bundle b, Bundle other)989 public static boolean bundleEquals(Bundle b, Bundle other) { 990 if (b == other) return true; 991 if (b == null || other == null) return false; 992 if (b.size() != other.size()) return false; 993 994 Set<String> keys = b.keySet(); 995 for (String key : keys) { 996 if (!other.containsKey(key)) return false; 997 Object objOne = b.get(key); 998 Object objTwo = other.get(key); 999 if (!Objects.equals(objOne, objTwo)) { 1000 return false; 1001 } 1002 } 1003 return true; 1004 } 1005 initDummyBundle()1006 public void initDummyBundle() { 1007 sDummyBundle = new Bundle(); 1008 sDummyBundle.putString("stringKey", new String("Test String")); 1009 } 1010 resetCounts()1011 private void resetCounts() { 1012 if (CountingTvInputService.sSession != null) { 1013 CountingTvInputService.sSession.resetCounts(); 1014 } 1015 if (CountingTvInputService.sRecordingSession != null) { 1016 CountingTvInputService.sRecordingSession.resetCounts(); 1017 } 1018 mCallback.resetCounts(); 1019 mTimeShiftPositionCallback.resetCounts(); 1020 mRecordingCallback.resetCounts(); 1021 } 1022 resetPassedValues()1023 private void resetPassedValues() { 1024 if (CountingTvInputService.sSession != null) { 1025 CountingTvInputService.sSession.resetPassedValues(); 1026 } 1027 if (CountingTvInputService.sRecordingSession != null) { 1028 CountingTvInputService.sRecordingSession.resetPassedValues(); 1029 } 1030 mCallback.resetPassedValues(); 1031 mRecordingCallback.resetPassedValues(); 1032 } 1033 1034 public static class CountingTvInputService extends StubTvInputService { 1035 static CountingSession sSession; 1036 static CountingRecordingSession sRecordingSession; 1037 1038 @Override onCreateSession(String inputId)1039 public Session onCreateSession(String inputId) { 1040 sSession = new CountingSession(this); 1041 sSession.setOverlayViewEnabled(true); 1042 return sSession; 1043 } 1044 1045 @Override onCreateRecordingSession(String inputId)1046 public RecordingSession onCreateRecordingSession(String inputId) { 1047 sRecordingSession = new CountingRecordingSession(this); 1048 return sRecordingSession; 1049 } 1050 1051 public static class CountingSession extends Session { 1052 public volatile int mTuneCount; 1053 public volatile int mTuneWithBundleCount; 1054 public volatile int mSetStreamVolumeCount; 1055 public volatile int mSetCaptionEnabledCount; 1056 public volatile int mSelectTrackCount; 1057 public volatile int mCreateOverlayView; 1058 public volatile int mKeyDownCount; 1059 public volatile int mKeyLongPressCount; 1060 public volatile int mKeyMultipleCount; 1061 public volatile int mKeyUpCount; 1062 public volatile int mTouchEventCount; 1063 public volatile int mTrackballEventCount; 1064 public volatile int mGenricMotionEventCount; 1065 public volatile int mOverlayViewSizeChangedCount; 1066 public volatile int mTimeShiftPauseCount; 1067 public volatile int mTimeShiftResumeCount; 1068 public volatile int mTimeShiftSeekToCount; 1069 public volatile int mTimeShiftSetPlaybackParamsCount; 1070 public volatile int mTimeShiftPlayCount; 1071 public volatile long mTimeShiftGetCurrentPositionCount; 1072 public volatile long mTimeShiftGetStartPositionCount; 1073 public volatile int mAppPrivateCommandCount; 1074 1075 public volatile String mAppPrivateCommandAction; 1076 public volatile Bundle mAppPrivateCommandData; 1077 public volatile Uri mTunedChannelUri; 1078 public volatile Bundle mTuneWithBundleData; 1079 public volatile Float mStreamVolume; 1080 public volatile Boolean mCaptionEnabled; 1081 public volatile Integer mSelectTrackType; 1082 public volatile String mSelectTrackId; 1083 public volatile Integer mKeyDownCode; 1084 public volatile KeyEvent mKeyDownEvent; 1085 public volatile Integer mKeyLongPressCode; 1086 public volatile KeyEvent mKeyLongPressEvent; 1087 public volatile Integer mKeyMultipleCode; 1088 public volatile Integer mKeyMultipleNumber; 1089 public volatile KeyEvent mKeyMultipleEvent; 1090 public volatile Integer mKeyUpCode; 1091 public volatile KeyEvent mKeyUpEvent; 1092 public volatile MotionEvent mTouchEvent; 1093 public volatile MotionEvent mTrackballEvent; 1094 public volatile MotionEvent mGenricMotionEvent; 1095 public volatile Long mTimeShiftSeekTo; 1096 public volatile PlaybackParams mTimeShiftSetPlaybackParams; 1097 public volatile Uri mRecordedProgramUri; 1098 public volatile Integer mOverlayViewSizeChangedWidth; 1099 public volatile Integer mOverlayViewSizeChangedHeight; 1100 CountingSession(Context context)1101 CountingSession(Context context) { 1102 super(context); 1103 } 1104 resetCounts()1105 public void resetCounts() { 1106 mTuneCount = 0; 1107 mTuneWithBundleCount = 0; 1108 mSetStreamVolumeCount = 0; 1109 mSetCaptionEnabledCount = 0; 1110 mSelectTrackCount = 0; 1111 mCreateOverlayView = 0; 1112 mKeyDownCount = 0; 1113 mKeyLongPressCount = 0; 1114 mKeyMultipleCount = 0; 1115 mKeyUpCount = 0; 1116 mTouchEventCount = 0; 1117 mTrackballEventCount = 0; 1118 mGenricMotionEventCount = 0; 1119 mOverlayViewSizeChangedCount = 0; 1120 mTimeShiftPauseCount = 0; 1121 mTimeShiftResumeCount = 0; 1122 mTimeShiftSeekToCount = 0; 1123 mTimeShiftSetPlaybackParamsCount = 0; 1124 mTimeShiftPlayCount = 0; 1125 mTimeShiftGetCurrentPositionCount = 0; 1126 mTimeShiftGetStartPositionCount = 0; 1127 mAppPrivateCommandCount = 0; 1128 } 1129 resetPassedValues()1130 public void resetPassedValues() { 1131 mAppPrivateCommandAction = null; 1132 mAppPrivateCommandData = null; 1133 mTunedChannelUri = null; 1134 mTuneWithBundleData = null; 1135 mStreamVolume = null; 1136 mCaptionEnabled = null; 1137 mSelectTrackType = null; 1138 mSelectTrackId = null; 1139 mKeyDownCode = null; 1140 mKeyDownEvent = null; 1141 mKeyLongPressCode = null; 1142 mKeyLongPressEvent = null; 1143 mKeyMultipleCode = null; 1144 mKeyMultipleNumber = null; 1145 mKeyMultipleEvent = null; 1146 mKeyUpCode = null; 1147 mKeyUpEvent = null; 1148 mTouchEvent = null; 1149 mTrackballEvent = null; 1150 mGenricMotionEvent = null; 1151 mTimeShiftSeekTo = null; 1152 mTimeShiftSetPlaybackParams = null; 1153 mRecordedProgramUri = null; 1154 mOverlayViewSizeChangedWidth = null; 1155 mOverlayViewSizeChangedHeight = null; 1156 } 1157 1158 @Override onAppPrivateCommand(String action, Bundle data)1159 public void onAppPrivateCommand(String action, Bundle data) { 1160 mAppPrivateCommandCount++; 1161 mAppPrivateCommandAction = action; 1162 mAppPrivateCommandData = data; 1163 } 1164 1165 @Override onRelease()1166 public void onRelease() { 1167 } 1168 1169 @Override onSetSurface(Surface surface)1170 public boolean onSetSurface(Surface surface) { 1171 return false; 1172 } 1173 1174 @Override onTune(Uri channelUri)1175 public boolean onTune(Uri channelUri) { 1176 mTuneCount++; 1177 mTunedChannelUri = channelUri; 1178 return false; 1179 } 1180 1181 @Override onTune(Uri channelUri, Bundle data)1182 public boolean onTune(Uri channelUri, Bundle data) { 1183 mTuneWithBundleCount++; 1184 mTuneWithBundleData = data; 1185 // Also calls {@link #onTune(Uri)} since it will never be called if the 1186 // implementation overrides {@link #onTune(Uri, Bundle)}. 1187 onTune(channelUri); 1188 return false; 1189 } 1190 1191 @Override onSetStreamVolume(float volume)1192 public void onSetStreamVolume(float volume) { 1193 mSetStreamVolumeCount++; 1194 mStreamVolume = volume; 1195 } 1196 1197 @Override onSetCaptionEnabled(boolean enabled)1198 public void onSetCaptionEnabled(boolean enabled) { 1199 mSetCaptionEnabledCount++; 1200 mCaptionEnabled = enabled; 1201 } 1202 1203 @Override onSelectTrack(int type, String id)1204 public boolean onSelectTrack(int type, String id) { 1205 mSelectTrackCount++; 1206 mSelectTrackType = type; 1207 mSelectTrackId = id; 1208 return false; 1209 } 1210 1211 @Override onCreateOverlayView()1212 public View onCreateOverlayView() { 1213 mCreateOverlayView++; 1214 return null; 1215 } 1216 1217 @Override onKeyDown(int keyCode, KeyEvent event)1218 public boolean onKeyDown(int keyCode, KeyEvent event) { 1219 mKeyDownCount++; 1220 mKeyDownCode = keyCode; 1221 mKeyDownEvent = event; 1222 return false; 1223 } 1224 1225 @Override onKeyLongPress(int keyCode, KeyEvent event)1226 public boolean onKeyLongPress(int keyCode, KeyEvent event) { 1227 mKeyLongPressCount++; 1228 mKeyLongPressCode = keyCode; 1229 mKeyLongPressEvent = event; 1230 return false; 1231 } 1232 1233 @Override onKeyMultiple(int keyCode, int count, KeyEvent event)1234 public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) { 1235 mKeyMultipleCount++; 1236 mKeyMultipleCode = keyCode; 1237 mKeyMultipleNumber = count; 1238 mKeyMultipleEvent = event; 1239 return false; 1240 } 1241 1242 @Override onKeyUp(int keyCode, KeyEvent event)1243 public boolean onKeyUp(int keyCode, KeyEvent event) { 1244 mKeyUpCount++; 1245 mKeyUpCode = keyCode; 1246 mKeyUpEvent = event; 1247 return false; 1248 } 1249 1250 @Override onTouchEvent(MotionEvent event)1251 public boolean onTouchEvent(MotionEvent event) { 1252 mTouchEventCount++; 1253 mTouchEvent = event; 1254 return false; 1255 } 1256 1257 @Override onTrackballEvent(MotionEvent event)1258 public boolean onTrackballEvent(MotionEvent event) { 1259 mTrackballEventCount++; 1260 mTrackballEvent = event; 1261 return false; 1262 } 1263 1264 @Override onGenericMotionEvent(MotionEvent event)1265 public boolean onGenericMotionEvent(MotionEvent event) { 1266 mGenricMotionEventCount++; 1267 mGenricMotionEvent = event; 1268 return false; 1269 } 1270 1271 @Override onTimeShiftPause()1272 public void onTimeShiftPause() { 1273 mTimeShiftPauseCount++; 1274 } 1275 1276 @Override onTimeShiftResume()1277 public void onTimeShiftResume() { 1278 mTimeShiftResumeCount++; 1279 } 1280 1281 @Override onTimeShiftSeekTo(long timeMs)1282 public void onTimeShiftSeekTo(long timeMs) { 1283 mTimeShiftSeekToCount++; 1284 mTimeShiftSeekTo = timeMs; 1285 } 1286 1287 @Override onTimeShiftSetPlaybackParams(PlaybackParams param)1288 public void onTimeShiftSetPlaybackParams(PlaybackParams param) { 1289 mTimeShiftSetPlaybackParamsCount++; 1290 mTimeShiftSetPlaybackParams = param; 1291 } 1292 1293 @Override onTimeShiftPlay(Uri recordedProgramUri)1294 public void onTimeShiftPlay(Uri recordedProgramUri) { 1295 mTimeShiftPlayCount++; 1296 mRecordedProgramUri = recordedProgramUri; 1297 } 1298 1299 @Override onTimeShiftGetCurrentPosition()1300 public long onTimeShiftGetCurrentPosition() { 1301 return ++mTimeShiftGetCurrentPositionCount; 1302 } 1303 1304 @Override onTimeShiftGetStartPosition()1305 public long onTimeShiftGetStartPosition() { 1306 return ++mTimeShiftGetStartPositionCount; 1307 } 1308 1309 @Override onOverlayViewSizeChanged(int width, int height)1310 public void onOverlayViewSizeChanged(int width, int height) { 1311 mOverlayViewSizeChangedCount++; 1312 mOverlayViewSizeChangedWidth = width; 1313 mOverlayViewSizeChangedHeight = height; 1314 } 1315 } 1316 1317 public static class CountingRecordingSession extends RecordingSession { 1318 public volatile int mTuneCount; 1319 public volatile int mTuneWithBundleCount; 1320 public volatile int mReleaseCount; 1321 public volatile int mStartRecordingCount; 1322 public volatile int mStopRecordingCount; 1323 public volatile int mAppPrivateCommandCount; 1324 1325 public volatile Uri mTunedChannelUri; 1326 public volatile Bundle mTuneWithBundleData; 1327 public volatile Uri mProgramHint; 1328 public volatile String mAppPrivateCommandAction; 1329 public volatile Bundle mAppPrivateCommandData; 1330 CountingRecordingSession(Context context)1331 CountingRecordingSession(Context context) { 1332 super(context); 1333 } 1334 resetCounts()1335 public void resetCounts() { 1336 mTuneCount = 0; 1337 mTuneWithBundleCount = 0; 1338 mReleaseCount = 0; 1339 mStartRecordingCount = 0; 1340 mStopRecordingCount = 0; 1341 mAppPrivateCommandCount = 0; 1342 } 1343 resetPassedValues()1344 public void resetPassedValues() { 1345 mTunedChannelUri = null; 1346 mTuneWithBundleData = null; 1347 mProgramHint = null; 1348 mAppPrivateCommandAction = null; 1349 mAppPrivateCommandData = null; 1350 } 1351 1352 @Override onTune(Uri channelUri)1353 public void onTune(Uri channelUri) { 1354 mTuneCount++; 1355 mTunedChannelUri = channelUri; 1356 } 1357 1358 @Override onTune(Uri channelUri, Bundle data)1359 public void onTune(Uri channelUri, Bundle data) { 1360 mTuneWithBundleCount++; 1361 mTuneWithBundleData = data; 1362 // Also calls {@link #onTune(Uri)} since it will never be called if the 1363 // implementation overrides {@link #onTune(Uri, Bundle)}. 1364 onTune(channelUri); 1365 } 1366 1367 @Override onRelease()1368 public void onRelease() { 1369 mReleaseCount++; 1370 } 1371 1372 @Override onStartRecording(Uri programHint)1373 public void onStartRecording(Uri programHint) { 1374 mStartRecordingCount++; 1375 mProgramHint = programHint; 1376 } 1377 1378 @Override onStopRecording()1379 public void onStopRecording() { 1380 mStopRecordingCount++; 1381 } 1382 1383 @Override onAppPrivateCommand(String action, Bundle data)1384 public void onAppPrivateCommand(String action, Bundle data) { 1385 mAppPrivateCommandCount++; 1386 mAppPrivateCommandAction = action; 1387 mAppPrivateCommandData = data; 1388 } 1389 } 1390 } 1391 1392 private static class StubRecordingCallback extends TvRecordingClient.RecordingCallback { 1393 private int mTunedCount; 1394 private int mRecordingStoppedCount; 1395 private int mErrorCount; 1396 private int mConnectionFailedCount; 1397 private int mDisconnectedCount; 1398 1399 private Uri mTunedChannelUri; 1400 private Uri mRecordedProgramUri; 1401 private Integer mError; 1402 1403 @Override onTuned(Uri channelUri)1404 public void onTuned(Uri channelUri) { 1405 mTunedCount++; 1406 mTunedChannelUri = channelUri; 1407 } 1408 1409 @Override onRecordingStopped(Uri recordedProgramUri)1410 public void onRecordingStopped(Uri recordedProgramUri) { 1411 mRecordingStoppedCount++; 1412 mRecordedProgramUri = recordedProgramUri; 1413 } 1414 1415 @Override onError(int error)1416 public void onError(int error) { 1417 mErrorCount++; 1418 mError = error; 1419 } 1420 1421 @Override onConnectionFailed(String inputId)1422 public void onConnectionFailed(String inputId) { 1423 mConnectionFailedCount++; 1424 } 1425 1426 @Override onDisconnected(String inputId)1427 public void onDisconnected(String inputId) { 1428 mDisconnectedCount++; 1429 } 1430 resetCounts()1431 public void resetCounts() { 1432 mTunedCount = 0; 1433 mRecordingStoppedCount = 0; 1434 mErrorCount = 0; 1435 mConnectionFailedCount = 0; 1436 mDisconnectedCount = 0; 1437 } 1438 resetPassedValues()1439 public void resetPassedValues() { 1440 mTunedChannelUri = null; 1441 mRecordedProgramUri = null; 1442 mError = null; 1443 } 1444 } 1445 } 1446