/* * Copyright (C) 2015 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 com.android.tv.menu; import static androidx.test.InstrumentationRegistry.getInstrumentation; import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.fail; import android.media.tv.TvTrackInfo; import android.os.SystemClock; import android.text.TextUtils; import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; import com.android.tv.common.flags.impl.DefaultLegacyFlags; import com.android.tv.common.flags.impl.DefaultUiFlags; import com.android.tv.testing.activities.BaseMainActivityTestCase; import com.android.tv.testing.constants.Constants; import com.android.tv.testing.testinput.ChannelState; import com.android.tv.testing.testinput.ChannelStateData; import com.android.tv.testing.testinput.TvTestInputConstants; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.util.Collections; import java.util.List; /** Tests for {@link TvOptionsRowAdapter}. */ @MediumTest @RunWith(AndroidJUnit4.class) public class TvOptionsRowAdapterTest extends BaseMainActivityTestCase { private static final int WAIT_TRACK_EVENT_TIMEOUT_MS = 300; public static final int TRACK_CHECK_INTERVAL_MS = 10; // TODO: Refactor TvOptionsRowAdapter so it does not rely on MainActivity private TvOptionsRowAdapter mTvOptionsRowAdapter; @Override @Before public void setUp() { super.setUp(); mTvOptionsRowAdapter = new TvOptionsRowAdapter( mActivity, Collections.emptyList(), DefaultLegacyFlags.DEFAULT, new DefaultUiFlags()); tuneToChannel(TvTestInputConstants.CH_1_DEFAULT_DONT_MODIFY); waitUntilAudioTracksHaveSize(1); waitUntilAudioTrackSelected(ChannelState.DEFAULT.getSelectedAudioTrackId()); // update should be called on the main thread to avoid the multi-thread problem. getInstrumentation() .runOnMainSync( new Runnable() { @Override public void run() { mTvOptionsRowAdapter.update(); } }); } @Test public void testUpdateAudioAction_2tracks() { ChannelStateData data = new ChannelStateData(); data.mTvTrackInfos.add(Constants.GENERIC_AUDIO_TRACK); updateThenTune(data, TvTestInputConstants.CH_2); waitUntilAudioTracksHaveSize(2); waitUntilAudioTrackSelected(Constants.EN_STEREO_AUDIO_TRACK.getId()); boolean result = mTvOptionsRowAdapter.updateMultiAudioAction(); assertWithMessage("update Action had change").that(result).isTrue(); assertWithMessage("Multi Audio enabled") .that(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.isEnabled()) .isTrue(); } @Test public void testUpdateAudioAction_1track() { ChannelStateData data = new ChannelStateData(); data.mTvTrackInfos.clear(); data.mTvTrackInfos.add(Constants.GENERIC_AUDIO_TRACK); data.mSelectedVideoTrackId = null; data.mSelectedAudioTrackId = Constants.GENERIC_AUDIO_TRACK.getId(); updateThenTune(data, TvTestInputConstants.CH_2); waitUntilAudioTracksHaveSize(1); waitUntilAudioTrackSelected(Constants.GENERIC_AUDIO_TRACK.getId()); boolean result = mTvOptionsRowAdapter.updateMultiAudioAction(); assertWithMessage("update Action had change").that(result).isTrue(); assertWithMessage("Multi Audio enabled") .that(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.isEnabled()) .isFalse(); } @Test public void testUpdateAudioAction_noTracks() { ChannelStateData data = new ChannelStateData(); data.mTvTrackInfos.clear(); data.mTvTrackInfos.add(ChannelState.DEFAULT_VIDEO_TRACK); data.mSelectedVideoTrackId = ChannelState.DEFAULT_VIDEO_TRACK.getId(); data.mSelectedAudioTrackId = null; updateThenTune(data, TvTestInputConstants.CH_2); // Wait for the video tracks, because there's no audio track. waitUntilVideoTracksHaveSize(1); waitUntilVideoTrackSelected(data.mSelectedVideoTrackId); boolean result = mTvOptionsRowAdapter.updateMultiAudioAction(); assertWithMessage("update Action had change").that(result).isTrue(); assertWithMessage("Multi Audio enabled") .that(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.isEnabled()) .isFalse(); } private void waitUntilAudioTracksHaveSize(int expected) { waitUntilTracksHaveSize(TvTrackInfo.TYPE_AUDIO, expected); } private void waitUntilVideoTracksHaveSize(int expected) { waitUntilTracksHaveSize(TvTrackInfo.TYPE_VIDEO, expected); } private void waitUntilTracksHaveSize(int trackType, int expected) { long start = SystemClock.elapsedRealtime(); int size = -1; while (SystemClock.elapsedRealtime() < start + WAIT_TRACK_EVENT_TIMEOUT_MS) { getInstrumentation().waitForIdleSync(); List tracks = mActivity.getTracks(trackType); if (tracks != null) { size = tracks.size(); if (size == expected) { return; } } SystemClock.sleep(TRACK_CHECK_INTERVAL_MS); } fail( "Waited for " + WAIT_TRACK_EVENT_TIMEOUT_MS + " milliseconds for track size to be " + expected + " but was " + size); } private void waitUntilAudioTrackSelected(String trackId) { waitUntilTrackSelected(TvTrackInfo.TYPE_AUDIO, trackId); } private void waitUntilVideoTrackSelected(String trackId) { waitUntilTrackSelected(TvTrackInfo.TYPE_VIDEO, trackId); } private void waitUntilTrackSelected(int trackType, String trackId) { long start = SystemClock.elapsedRealtime(); String selectedTrackId = null; while (SystemClock.elapsedRealtime() < start + WAIT_TRACK_EVENT_TIMEOUT_MS) { getInstrumentation().waitForIdleSync(); selectedTrackId = mActivity.getSelectedTrack(trackType); if (TextUtils.equals(selectedTrackId, trackId)) { return; } SystemClock.sleep(TRACK_CHECK_INTERVAL_MS); } fail( "Waited for " + WAIT_TRACK_EVENT_TIMEOUT_MS + " milliseconds for track ID to be " + trackId + " but was " + selectedTrackId); } }