1919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho/* 2919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho * Copyright (C) 2016 The Android Open Source Project 3919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho * 4919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho * Licensed under the Apache License, Version 2.0 (the "License"); 5919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho * you may not use this file except in compliance with the License. 6919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho * You may obtain a copy of the License at 7919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho * 8919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho * http://www.apache.org/licenses/LICENSE-2.0 9919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho * 10919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho * Unless required by applicable law or agreed to in writing, software 11919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho * distributed under the License is distributed on an "AS IS" BASIS, 12919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho * See the License for the specific language governing permissions and 14919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho * limitations under the License 15919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho */ 16919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 176ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkopackage com.android.tv.dvr.recorder; 18919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 196ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport static android.support.test.InstrumentationRegistry.getContext; 206ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport static org.junit.Assert.assertTrue; 21919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport static org.mockito.Matchers.any; 22919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport static org.mockito.Matchers.anyLong; 23919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport static org.mockito.Matchers.eq; 24919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport static org.mockito.Mockito.mock; 256ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport static org.mockito.Mockito.never; 26919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport static org.mockito.Mockito.timeout; 27919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport static org.mockito.Mockito.verify; 28919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport static org.mockito.Mockito.when; 29919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 30919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport android.app.AlarmManager; 31919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport android.media.tv.TvInputInfo; 32919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport android.os.Build; 33919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport android.os.Looper; 346ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport android.os.SystemClock; 35919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport android.support.test.filters.SdkSuppress; 36919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport android.support.test.filters.SmallTest; 37919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 38919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport com.android.tv.InputSessionManager; 39919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport com.android.tv.data.Channel; 40919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport com.android.tv.data.ChannelDataManager; 416ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.DvrManager; 426ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.WritableDvrDataManager; 436ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.ScheduledRecording; 446ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.recorder.InputTaskScheduler.RecordingTaskFactory; 45919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport com.android.tv.testing.FakeClock; 46919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport com.android.tv.testing.dvr.RecordingTestUtils; 47919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport com.android.tv.util.Clock; 48919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport com.android.tv.util.TestUtils; 49919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 506ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport org.junit.Before; 516ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport org.junit.Test; 52919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport org.mockito.Mock; 53919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport org.mockito.MockitoAnnotations; 54919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 55919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport java.util.ArrayList; 56919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport java.util.List; 57919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Choimport java.util.concurrent.TimeUnit; 58919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 59919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho/** 60919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho * Tests for {@link InputTaskScheduler}. 61919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho */ 62919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho@SmallTest 63919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N) 646ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkopublic class InputTaskSchedulerTest { 65919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho private static final String INPUT_ID = "input_id"; 66919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho private static final int CHANNEL_ID = 1; 67919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho private static final long LISTENER_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(1); 68919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho private static final int TUNER_COUNT_ONE = 1; 69919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho private static final int TUNER_COUNT_TWO = 2; 70919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho private static final long LOW_PRIORITY = 1; 71919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho private static final long HIGH_PRIORITY = 2; 72919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 73919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho private FakeClock mFakeClock; 74919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho private InputTaskScheduler mScheduler; 75919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho @Mock private DvrManager mDvrManager; 76919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho @Mock private WritableDvrDataManager mDataManager; 77919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho @Mock private InputSessionManager mSessionManager; 78919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho @Mock private AlarmManager mMockAlarmManager; 79919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho @Mock private ChannelDataManager mChannelDataManager; 80919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho private List<RecordingTask> mRecordingTasks; 81919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 826ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Before 836ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void setUp() throws Exception { 84919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho if (Looper.myLooper() == null) { 85919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho Looper.prepare(); 86919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho } 87919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mRecordingTasks = new ArrayList(); 88919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho MockitoAnnotations.initMocks(this); 89919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mFakeClock = FakeClock.createWithCurrentTime(); 90919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho TvInputInfo input = createTvInputInfo(TUNER_COUNT_ONE); 91919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler = new InputTaskScheduler(getContext(), input, Looper.myLooper(), 92919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mChannelDataManager, mDvrManager, mDataManager, mSessionManager, mFakeClock, 936ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko new RecordingTaskFactory() { 94919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho @Override 95919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho public RecordingTask createRecordingTask(ScheduledRecording scheduledRecording, 96919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho Channel channel, DvrManager dvrManager, 97919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho InputSessionManager sessionManager, WritableDvrDataManager dataManager, 98919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho Clock clock) { 99919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho RecordingTask task = mock(RecordingTask.class); 100919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho when(task.getPriority()).thenReturn(scheduledRecording.getPriority()); 101919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho when(task.getEndTimeMs()).thenReturn(scheduledRecording.getEndTimeMs()); 102919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mRecordingTasks.add(task); 103919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho return task; 104919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho } 105919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho }); 106919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho } 107919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 1086ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Test 1096ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void testAddSchedule_past() { 110919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho ScheduledRecording r = RecordingTestUtils.createTestRecordingWithPeriod(INPUT_ID, 111919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho CHANNEL_ID, 0L, 1L); 112919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho when(mDataManager.getScheduledRecording(anyLong())).thenReturn(r); 113919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleAddSchedule(r); 114919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleBuildSchedule(); 115919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho verify(mDataManager, timeout((int) LISTENER_TIMEOUT_MS).times(1)) 116919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho .changeState(any(ScheduledRecording.class), 117919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho eq(ScheduledRecording.STATE_RECORDING_FAILED)); 118919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho } 119919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 1206ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Test 1216ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void testAddSchedule_start() { 122919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleAddSchedule(RecordingTestUtils.createTestRecordingWithPeriod(INPUT_ID, 123919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho CHANNEL_ID, mFakeClock.currentTimeMillis(), 124919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mFakeClock.currentTimeMillis() + TimeUnit.HOURS.toMillis(1))); 125919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleBuildSchedule(); 126919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho verify(mRecordingTasks.get(0), timeout((int) LISTENER_TIMEOUT_MS).times(1)).start(); 127919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho } 128919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 1296ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Test 1306ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void testAddSchedule_consecutiveNoStop() { 131919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho long startTimeMs = mFakeClock.currentTimeMillis(); 132919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho long endTimeMs = startTimeMs + TimeUnit.SECONDS.toMillis(1); 133919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho long id = 0; 134919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleAddSchedule( 135919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho RecordingTestUtils.createTestRecordingWithIdAndPriorityAndPeriod(++id, CHANNEL_ID, 136919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho LOW_PRIORITY, startTimeMs, endTimeMs)); 137919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleBuildSchedule(); 138919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho startTimeMs = endTimeMs; 139919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho endTimeMs = startTimeMs + TimeUnit.SECONDS.toMillis(1); 140919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleAddSchedule( 141919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho RecordingTestUtils.createTestRecordingWithIdAndPriorityAndPeriod(++id, CHANNEL_ID, 142919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho HIGH_PRIORITY, startTimeMs, endTimeMs)); 143919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleBuildSchedule(); 144919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho verify(mRecordingTasks.get(0), timeout((int) LISTENER_TIMEOUT_MS).times(1)).start(); 145919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho // The first schedule should not be stopped because the second one should wait for the end 146919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho // of the first schedule. 1476ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko SystemClock.sleep(LISTENER_TIMEOUT_MS); 1486ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko verify(mRecordingTasks.get(0), never()).stop(); 149919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho } 150919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 1516ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Test 1526ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void testAddSchedule_consecutiveNoFail() { 153919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho long startTimeMs = mFakeClock.currentTimeMillis(); 154919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho long endTimeMs = startTimeMs + TimeUnit.SECONDS.toMillis(1); 155919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho long id = 0; 156919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho when(mDataManager.getScheduledRecording(anyLong())).thenReturn(ScheduledRecording 157919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho .builder(INPUT_ID, CHANNEL_ID, 0L, 0L).build()); 158919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleAddSchedule( 159919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho RecordingTestUtils.createTestRecordingWithIdAndPriorityAndPeriod(++id, CHANNEL_ID, 160919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho HIGH_PRIORITY, startTimeMs, endTimeMs)); 161919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleBuildSchedule(); 162919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho startTimeMs = endTimeMs; 163919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho endTimeMs = startTimeMs + TimeUnit.SECONDS.toMillis(1); 164919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleAddSchedule( 165919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho RecordingTestUtils.createTestRecordingWithIdAndPriorityAndPeriod(++id, CHANNEL_ID, 166919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho LOW_PRIORITY, startTimeMs, endTimeMs)); 167919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleBuildSchedule(); 168919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho verify(mRecordingTasks.get(0), timeout((int) LISTENER_TIMEOUT_MS).times(1)).start(); 1696ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko SystemClock.sleep(LISTENER_TIMEOUT_MS); 1706ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko verify(mRecordingTasks.get(0), never()).stop(); 171919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho // The second schedule should not fail because it can starts after the first one finishes. 1726ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko SystemClock.sleep(LISTENER_TIMEOUT_MS); 1736ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko verify(mDataManager, never()) 174919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho .changeState(any(ScheduledRecording.class), 175919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho eq(ScheduledRecording.STATE_RECORDING_FAILED)); 176919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho } 177919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 1786ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Test 179919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho public void testAddSchedule_consecutiveUseLessSession() throws Exception { 180919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho TvInputInfo input = createTvInputInfo(TUNER_COUNT_TWO); 181919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.updateTvInputInfo(input); 182919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho long startTimeMs = mFakeClock.currentTimeMillis(); 183919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho long endTimeMs = startTimeMs + TimeUnit.SECONDS.toMillis(1); 184919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho long id = 0; 185919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleAddSchedule( 186919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho RecordingTestUtils.createTestRecordingWithIdAndPriorityAndPeriod(++id, CHANNEL_ID, 187919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho LOW_PRIORITY, startTimeMs, endTimeMs)); 188919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleBuildSchedule(); 189919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho startTimeMs = endTimeMs; 190919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho endTimeMs = startTimeMs + TimeUnit.SECONDS.toMillis(1); 191919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleAddSchedule( 192919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho RecordingTestUtils.createTestRecordingWithIdAndPriorityAndPeriod(++id, CHANNEL_ID, 193919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho HIGH_PRIORITY, startTimeMs, endTimeMs)); 194919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleBuildSchedule(); 195919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho verify(mRecordingTasks.get(0), timeout((int) LISTENER_TIMEOUT_MS).times(1)).start(); 1966ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko SystemClock.sleep(LISTENER_TIMEOUT_MS); 1976ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko verify(mRecordingTasks.get(0), never()).stop(); 198919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho // The second schedule should wait until the first one finishes rather than creating a new 199919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho // session even though there are available tuners. 200919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho assertTrue(mRecordingTasks.size() == 1); 201919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho } 202919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 2036ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Test 2046ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void testUpdateSchedule_noCancel() { 205919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho ScheduledRecording r = RecordingTestUtils.createTestRecordingWithPeriod(INPUT_ID, 206919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho CHANNEL_ID, mFakeClock.currentTimeMillis(), 207919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mFakeClock.currentTimeMillis() + TimeUnit.HOURS.toMillis(1)); 208919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleAddSchedule(r); 209919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleBuildSchedule(); 210919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleUpdateSchedule(r); 2116ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko SystemClock.sleep(LISTENER_TIMEOUT_MS); 2126ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko verify(mRecordingTasks.get(0), never()).cancel(); 213919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho } 214919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 2156ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Test 2166ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void testUpdateSchedule_cancel() { 217919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho ScheduledRecording r = RecordingTestUtils.createTestRecordingWithPeriod(INPUT_ID, 218919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho CHANNEL_ID, mFakeClock.currentTimeMillis(), 219919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mFakeClock.currentTimeMillis() + TimeUnit.HOURS.toMillis(2)); 220919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleAddSchedule(r); 221919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleBuildSchedule(); 222919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho mScheduler.handleUpdateSchedule(ScheduledRecording.buildFrom(r) 223919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho .setStartTimeMs(mFakeClock.currentTimeMillis() + TimeUnit.HOURS.toMillis(1)) 224919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho .build()); 225919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho verify(mRecordingTasks.get(0), timeout((int) LISTENER_TIMEOUT_MS).times(1)).cancel(); 226919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho } 227919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho 228919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho private TvInputInfo createTvInputInfo(int tunerCount) throws Exception { 229919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho return TestUtils.createTvInputInfo(null, null, null, 0, false, true, tunerCount); 230919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho } 231919e1ed7e914029a1a0054237d86dc7b19ced898Youngsang Cho} 232