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