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