blob: 7068035300c28314a69452f3d0c8bd8aa4531a15 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.media.tv.cts;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.cts.util.PollingCheck;
import android.media.tv.TvContentRating;
import android.media.tv.TvContract;
import android.media.tv.TvInputInfo;
import android.media.tv.TvInputManager;
import android.media.tv.TvTrackInfo;
import android.media.tv.TvView;
import android.media.tv.cts.TvInputServiceTest.CountingTvInputService.CountingSession;
import android.net.Uri;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import com.android.cts.tv.R;
import java.util.ArrayList;
import java.util.List;
/**
* Test {@link android.media.tv.TvInputService}.
*/
public class TvInputServiceTest extends ActivityInstrumentationTestCase2<TvViewStubActivity> {
/** The maximum time to wait for an operation. */
private static final long TIME_OUT = 15000L;
private static final String mDummyTrackId = "dummyTrackId";
private static final TvTrackInfo mDummyTrack =
new TvTrackInfo.Builder(TvTrackInfo.TYPE_VIDEO, mDummyTrackId)
.setVideoWidth(1920).setVideoHeight(1080).setLanguage("und").build();
private TvView mTvView;
private Activity mActivity;
private Instrumentation mInstrumentation;
private TvInputManager mManager;
private TvInputInfo mStubInfo;
private final StubCallback mCallback = new StubCallback();
private static class StubCallback extends TvView.TvInputCallback {
private int mChannelRetunedCount;
private int mVideoAvailableCount;
private int mVideoUnavailableCount;
private int mTrackSelectedCount;
private int mTrackChangedCount;
private int mVideoSizeChanged;
private int mContentAllowedCount;
private int mContentBlockedCount;
@Override
public void onChannelRetuned(String inputId, Uri channelUri) {
mChannelRetunedCount++;
}
@Override
public void onVideoAvailable(String inputId) {
mVideoAvailableCount++;
}
@Override
public void onVideoUnavailable(String inputId, int reason) {
mVideoUnavailableCount++;
}
@Override
public void onTrackSelected(String inputId, int type, String trackId) {
mTrackSelectedCount++;
}
@Override
public void onTracksChanged(String inputId, List<TvTrackInfo> trackList) {
mTrackChangedCount++;
}
@Override
public void onVideoSizeChanged(String inputId, int width, int height) {
mVideoSizeChanged++;
}
@Override
public void onContentAllowed(String inputId) {
mContentAllowedCount++;
}
@Override
public void onContentBlocked(String inputId, TvContentRating rating) {
mContentBlockedCount++;
}
public void resetCounts() {
mChannelRetunedCount = 0;
mVideoAvailableCount = 0;
mVideoUnavailableCount = 0;
mTrackSelectedCount = 0;
mTrackChangedCount = 0;
mContentAllowedCount = 0;
mContentBlockedCount = 0;
}
}
public TvInputServiceTest() {
super(TvViewStubActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
if (!Utils.hasTvInputFramework(getActivity())) {
return;
}
mActivity = getActivity();
mInstrumentation = getInstrumentation();
mTvView = (TvView) mActivity.findViewById(R.id.tvview);
mManager = (TvInputManager) mActivity.getSystemService(Context.TV_INPUT_SERVICE);
for (TvInputInfo info : mManager.getTvInputList()) {
if (info.getServiceInfo().name.equals(CountingTvInputService.class.getName())) {
mStubInfo = info;
break;
}
}
assertNotNull(mStubInfo);
mTvView.setCallback(mCallback);
CountingTvInputService.sSession = null;
}
public void testTvInputService() throws Throwable {
if (!Utils.hasTvInputFramework(getActivity())) {
return;
}
verifyCommandTune();
verifyCommandSetStreamVolume();
verifyCommandSetCaptionEnabled();
verifyCommandSelectTrack();
verifyCommandDispatchKeyDown();
verifyCommandDispatchKeyMultiple();
verifyCommandDispatchKeyUp();
verifyCommandDispatchTouchEvent();
verifyCommandDispatchTrackballEvent();
verifyCommandDispatchGenericMotionEvent();
verifyCallbackChannelRetuned();
verifyCallbackVideoAvailable();
verifyCallbackVideoUnavailable();
verifyCallbackTracksChanged();
verifyCallbackTrackSelected();
verifyCallbackContentAllowed();
verifyCallbackContentBlocked();
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mTvView.reset();
}
});
mInstrumentation.waitForIdleSync();
}
public void verifyCommandTune() {
Uri fakeChannelUri = TvContract.buildChannelUri(0);
mTvView.tune(mStubInfo.getId(), fakeChannelUri);
mInstrumentation.waitForIdleSync();
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
CountingSession session = CountingTvInputService.sSession;
return session != null && session.mTuneCount > 0 && session.mCreateOverlayView > 0;
}
}.run();
}
public void verifyCommandSetStreamVolume() {
resetCounts();
mTvView.setStreamVolume(1.0f);
mInstrumentation.waitForIdleSync();
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
CountingSession session = CountingTvInputService.sSession;
return session != null && session.mSetStreamVolumeCount > 0;
}
}.run();
}
public void verifyCommandSetCaptionEnabled() {
resetCounts();
mTvView.setCaptionEnabled(true);
mInstrumentation.waitForIdleSync();
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
CountingSession session = CountingTvInputService.sSession;
return session != null && session.mSetCaptionEnabledCount > 0;
}
}.run();
}
public void verifyCommandSelectTrack() {
resetCounts();
verifyCallbackTracksChanged();
mTvView.selectTrack(mDummyTrack.getType(), mDummyTrack.getId());
mInstrumentation.waitForIdleSync();
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
CountingSession session = CountingTvInputService.sSession;
return session != null && session.mSelectTrackCount > 0;
}
}.run();
}
public void verifyCommandDispatchKeyDown() {
resetCounts();
mTvView.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_K));
mInstrumentation.waitForIdleSync();
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
CountingSession session = CountingTvInputService.sSession;
return session != null && session.mKeyDownCount > 0;
}
}.run();
}
public void verifyCommandDispatchKeyMultiple() {
resetCounts();
mTvView.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_K));
mInstrumentation.waitForIdleSync();
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
CountingSession session = CountingTvInputService.sSession;
return session != null && session.mKeyMultipleCount > 0;
}
}.run();
}
public void verifyCommandDispatchKeyUp() {
resetCounts();
mTvView.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_K));
mInstrumentation.waitForIdleSync();
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
CountingSession session = CountingTvInputService.sSession;
return session != null && session.mKeyUpCount > 0;
}
}.run();
}
public void verifyCommandDispatchTouchEvent() {
resetCounts();
long now = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 1.0f, 1.0f,
1.0f, 1.0f, 0, 1.0f, 1.0f, 0, 0);
event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
mTvView.dispatchTouchEvent(event);
mInstrumentation.waitForIdleSync();
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
CountingSession session = CountingTvInputService.sSession;
return session != null && session.mTouchEventCount > 0;
}
}.run();
}
public void verifyCommandDispatchTrackballEvent() {
resetCounts();
long now = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 1.0f, 1.0f,
1.0f, 1.0f, 0, 1.0f, 1.0f, 0, 0);
event.setSource(InputDevice.SOURCE_TRACKBALL);
mTvView.dispatchTouchEvent(event);
mInstrumentation.waitForIdleSync();
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
CountingSession session = CountingTvInputService.sSession;
return session != null && session.mTrackballEventCount > 0;
}
}.run();
}
public void verifyCommandDispatchGenericMotionEvent() {
resetCounts();
long now = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 1.0f, 1.0f,
1.0f, 1.0f, 0, 1.0f, 1.0f, 0, 0);
mTvView.dispatchGenericMotionEvent(event);
mInstrumentation.waitForIdleSync();
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
CountingSession session = CountingTvInputService.sSession;
return session != null && session.mGenricMotionEventCount > 0;
}
}.run();
}
public void verifyCallbackChannelRetuned() {
resetCounts();
CountingSession session = CountingTvInputService.sSession;
assertNotNull(session);
Uri fakeChannelUri = TvContract.buildChannelUri(0);
session.notifyChannelRetuned(fakeChannelUri);
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
return mCallback.mChannelRetunedCount > 0;
}
}.run();
}
public void verifyCallbackVideoAvailable() {
resetCounts();
CountingSession session = CountingTvInputService.sSession;
assertNotNull(session);
session.notifyVideoAvailable();
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
return mCallback.mVideoAvailableCount > 0;
}
}.run();
}
public void verifyCallbackVideoUnavailable() {
resetCounts();
CountingSession session = CountingTvInputService.sSession;
assertNotNull(session);
session.notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING);
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
return mCallback.mVideoUnavailableCount > 0;
}
}.run();
}
public void verifyCallbackTracksChanged() {
resetCounts();
CountingSession session = CountingTvInputService.sSession;
assertNotNull(session);
ArrayList<TvTrackInfo> tracks = new ArrayList<>();
tracks.add(mDummyTrack);
session.notifyTracksChanged(tracks);
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
return mCallback.mTrackChangedCount > 0;
}
}.run();
}
public void verifyCallbackVideoSizeChanged() {
resetCounts();
CountingSession session = CountingTvInputService.sSession;
assertNotNull(session);
ArrayList<TvTrackInfo> tracks = new ArrayList<>();
tracks.add(mDummyTrack);
session.notifyTracksChanged(tracks);
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
return mCallback.mVideoSizeChanged > 0;
}
}.run();
}
public void verifyCallbackTrackSelected() {
resetCounts();
CountingSession session = CountingTvInputService.sSession;
assertNotNull(session);
session.notifyTrackSelected(mDummyTrack.getType(), mDummyTrack.getId());
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
return mCallback.mTrackSelectedCount > 0;
}
}.run();
}
public void verifyCallbackContentAllowed() {
resetCounts();
CountingSession session = CountingTvInputService.sSession;
assertNotNull(session);
session.notifyContentAllowed();
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
return mCallback.mContentAllowedCount > 0;
}
}.run();
}
public void verifyCallbackContentBlocked() {
resetCounts();
CountingSession session = CountingTvInputService.sSession;
assertNotNull(session);
TvContentRating rating = TvContentRating.createRating("android.media.tv", "US_TVPG",
"US_TVPG_TV_MA", "US_TVPG_S", "US_TVPG_V");
session.notifyContentBlocked(rating);
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
return mCallback.mContentBlockedCount > 0;
}
}.run();
}
private void resetCounts() {
if (CountingTvInputService.sSession != null) {
CountingTvInputService.sSession.resetCounts();
}
mCallback.resetCounts();
}
public static class CountingTvInputService extends StubTvInputService {
static CountingSession sSession;
@Override
public Session onCreateSession(String inputId) {
sSession = new CountingSession(this);
sSession.setOverlayViewEnabled(true);
return sSession;
}
public static class CountingSession extends Session {
public volatile int mTuneCount;
public volatile int mSetStreamVolumeCount;
public volatile int mSetCaptionEnabledCount;
public volatile int mSelectTrackCount;
public volatile int mCreateOverlayView;
public volatile int mKeyDownCount;
public volatile int mKeyLongPressCount;
public volatile int mKeyMultipleCount;
public volatile int mKeyUpCount;
public volatile int mTouchEventCount;
public volatile int mTrackballEventCount;
public volatile int mGenricMotionEventCount;
CountingSession(Context context) {
super(context);
}
public void resetCounts() {
mTuneCount = 0;
mSetStreamVolumeCount = 0;
mSetCaptionEnabledCount = 0;
mSelectTrackCount = 0;
mCreateOverlayView = 0;
mKeyDownCount = 0;
mKeyLongPressCount = 0;
mKeyMultipleCount = 0;
mKeyUpCount = 0;
mTouchEventCount = 0;
mTrackballEventCount = 0;
mGenricMotionEventCount = 0;
}
@Override
public void onRelease() {
}
@Override
public boolean onSetSurface(Surface surface) {
return false;
}
@Override
public boolean onTune(Uri channelUri) {
mTuneCount++;
return false;
}
@Override
public void onSetStreamVolume(float volume) {
mSetStreamVolumeCount++;
}
@Override
public void onSetCaptionEnabled(boolean enabled) {
mSetCaptionEnabledCount++;
}
@Override
public boolean onSelectTrack(int type, String id) {
mSelectTrackCount++;
return false;
}
@Override
public View onCreateOverlayView() {
mCreateOverlayView++;
return null;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
mKeyDownCount++;
return false;
}
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
mKeyLongPressCount++;
return false;
}
@Override
public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
mKeyMultipleCount++;
return false;
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
mKeyUpCount++;
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mTouchEventCount++;
return false;
}
@Override
public boolean onTrackballEvent(MotionEvent event) {
mTrackballEventCount++;
return false;
}
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
mGenricMotionEventCount++;
return false;
}
}
}
}