aboutsummaryrefslogtreecommitdiff
path: root/src/com/android/tv/dvr/recorder/InputTaskScheduler.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/tv/dvr/recorder/InputTaskScheduler.java')
-rw-r--r--src/com/android/tv/dvr/recorder/InputTaskScheduler.java172
1 files changed, 101 insertions, 71 deletions
diff --git a/src/com/android/tv/dvr/recorder/InputTaskScheduler.java b/src/com/android/tv/dvr/recorder/InputTaskScheduler.java
index fee4568e..1021b2bc 100644
--- a/src/com/android/tv/dvr/recorder/InputTaskScheduler.java
+++ b/src/com/android/tv/dvr/recorder/InputTaskScheduler.java
@@ -25,17 +25,15 @@ import android.support.annotation.VisibleForTesting;
import android.util.ArrayMap;
import android.util.Log;
import android.util.LongSparseArray;
-
import com.android.tv.InputSessionManager;
-import com.android.tv.data.Channel;
+import com.android.tv.common.util.Clock;
import com.android.tv.data.ChannelDataManager;
+import com.android.tv.data.api.Channel;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.WritableDvrDataManager;
import com.android.tv.dvr.data.ScheduledRecording;
-import com.android.tv.util.Clock;
import com.android.tv.util.CompositeComparator;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -43,9 +41,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
-/**
- * The scheduler for a TV input.
- */
+/** The scheduler for a TV input. */
public class InputTaskScheduler {
private static final String TAG = "InputTaskScheduler";
private static final boolean DEBUG = false;
@@ -66,9 +62,7 @@ public class InputTaskScheduler {
RecordingTask.END_TIME_COMPARATOR,
RecordingTask.ID_COMPARATOR);
- /**
- * Returns the comparator which the schedules are sorted with when executed.
- */
+ /** Returns the comparator which the schedules are sorted with when executed. */
public static Comparator<ScheduledRecording> getRecordingOrderComparator() {
return ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR;
}
@@ -81,8 +75,8 @@ public class InputTaskScheduler {
private final long mId;
private final RecordingTask mTask;
- HandlerWrapper(Looper looper, ScheduledRecording scheduledRecording,
- RecordingTask recordingTask) {
+ HandlerWrapper(
+ Looper looper, ScheduledRecording scheduledRecording, RecordingTask recordingTask) {
super(looper, recordingTask);
mId = scheduledRecording.getId();
mTask = recordingTask;
@@ -94,7 +88,7 @@ public class InputTaskScheduler {
// The RecordingTask gets a chance first.
// It must return false to pass this message to here.
if (msg.what == MESSAGE_REMOVE) {
- if (DEBUG) Log.d(TAG, "done " + mId);
+ if (DEBUG) Log.d(TAG, "done " + mId);
mPendingRecordings.remove(mId);
}
removeCallbacksAndMessages(null);
@@ -120,17 +114,37 @@ public class InputTaskScheduler {
private final Object mInputLock = new Object();
private final RecordingTaskFactory mRecordingTaskFactory;
- public InputTaskScheduler(Context context, TvInputInfo input, Looper looper,
- ChannelDataManager channelDataManager, DvrManager dvrManager,
- DvrDataManager dataManager, InputSessionManager sessionManager, Clock clock) {
- this(context, input, looper, channelDataManager, dvrManager, dataManager, sessionManager,
- clock, null);
+ public InputTaskScheduler(
+ Context context,
+ TvInputInfo input,
+ Looper looper,
+ ChannelDataManager channelDataManager,
+ DvrManager dvrManager,
+ DvrDataManager dataManager,
+ InputSessionManager sessionManager,
+ Clock clock) {
+ this(
+ context,
+ input,
+ looper,
+ channelDataManager,
+ dvrManager,
+ dataManager,
+ sessionManager,
+ clock,
+ null);
}
@VisibleForTesting
- InputTaskScheduler(Context context, TvInputInfo input, Looper looper,
- ChannelDataManager channelDataManager, DvrManager dvrManager,
- DvrDataManager dataManager, InputSessionManager sessionManager, Clock clock,
+ InputTaskScheduler(
+ Context context,
+ TvInputInfo input,
+ Looper looper,
+ ChannelDataManager channelDataManager,
+ DvrManager dvrManager,
+ DvrDataManager dataManager,
+ InputSessionManager sessionManager,
+ Clock clock,
RecordingTaskFactory recordingTaskFactory) {
if (DEBUG) Log.d(TAG, "Creating scheduler for " + input);
mContext = context;
@@ -142,22 +156,32 @@ public class InputTaskScheduler {
mSessionManager = sessionManager;
mClock = clock;
mMainThreadHandler = new Handler(Looper.getMainLooper());
- mRecordingTaskFactory = recordingTaskFactory != null ? recordingTaskFactory
- : new RecordingTaskFactory() {
- @Override
- public RecordingTask createRecordingTask(ScheduledRecording schedule, Channel channel,
- DvrManager dvrManager, InputSessionManager sessionManager,
- WritableDvrDataManager dataManager, Clock clock) {
- return new RecordingTask(mContext, schedule, channel, mDvrManager, mSessionManager,
- mDataManager, mClock);
- }
- };
+ mRecordingTaskFactory =
+ recordingTaskFactory != null
+ ? recordingTaskFactory
+ : new RecordingTaskFactory() {
+ @Override
+ public RecordingTask createRecordingTask(
+ ScheduledRecording schedule,
+ Channel channel,
+ DvrManager dvrManager,
+ InputSessionManager sessionManager,
+ WritableDvrDataManager dataManager,
+ Clock clock) {
+ return new RecordingTask(
+ mContext,
+ schedule,
+ channel,
+ mDvrManager,
+ mSessionManager,
+ mDataManager,
+ mClock);
+ }
+ };
mHandler = new WorkerThreadHandler(looper);
}
- /**
- * Adds a {@link ScheduledRecording}.
- */
+ /** Adds a {@link ScheduledRecording}. */
public void addSchedule(ScheduledRecording schedule) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_ADD_SCHEDULED_RECORDING, schedule));
}
@@ -173,9 +197,7 @@ public class InputTaskScheduler {
mHandler.sendEmptyMessage(MSG_BUILD_SCHEDULE);
}
- /**
- * Removes the {@link ScheduledRecording}.
- */
+ /** Removes the {@link ScheduledRecording}. */
public void removeSchedule(ScheduledRecording schedule) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_REMOVE_SCHEDULED_RECORDING, schedule));
}
@@ -194,9 +216,7 @@ public class InputTaskScheduler {
}
}
- /**
- * Updates the {@link ScheduledRecording}.
- */
+ /** Updates the {@link ScheduledRecording}. */
public void updateSchedule(ScheduledRecording schedule) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_SCHEDULED_RECORDING, schedule));
}
@@ -224,18 +244,14 @@ public class InputTaskScheduler {
}
}
- /**
- * Updates the TV input.
- */
+ /** Updates the TV input. */
public void updateTvInputInfo(TvInputInfo input) {
synchronized (mInputLock) {
mInput = input;
}
}
- /**
- * Stops the input task scheduler.
- */
+ /** Stops the input task scheduler. */
public void stop() {
mHandler.removeCallbacksAndMessages(null);
mHandler.sendEmptyMessage(MSG_STOP_SCHEDULE);
@@ -262,7 +278,9 @@ public class InputTaskScheduler {
ScheduledRecording schedule = iter.next();
if (schedule.getEndTimeMs() - currentTimeMs
<= MIN_REMAIN_DURATION_PERCENT * schedule.getDuration()) {
- fail(schedule);
+ Log.e(TAG, "Error! Program ended before recording started:" + schedule);
+ fail(schedule,
+ ScheduledRecording.FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED);
iter.remove();
}
}
@@ -274,7 +292,8 @@ public class InputTaskScheduler {
for (ScheduledRecording schedule : mWaitingSchedules.values()) {
if (schedule.getState() != ScheduledRecording.STATE_RECORDING_CANCELED
&& schedule.getStartTimeMs() - RecordingTask.RECORDING_EARLY_START_OFFSET_MS
- <= currentTimeMs && schedule.getEndTimeMs() > currentTimeMs) {
+ <= currentTimeMs
+ && schedule.getEndTimeMs() > currentTimeMs) {
schedulesToStart.add(schedule);
}
}
@@ -321,10 +340,12 @@ public class InputTaskScheduler {
earliest = schedule.getEndTimeMs();
}
} else {
- if (earliest > schedule.getStartTimeMs()
- - RecordingTask.RECORDING_EARLY_START_OFFSET_MS) {
- earliest = schedule.getStartTimeMs()
- - RecordingTask.RECORDING_EARLY_START_OFFSET_MS;
+ if (earliest
+ > schedule.getStartTimeMs()
+ - RecordingTask.RECORDING_EARLY_START_OFFSET_MS) {
+ earliest =
+ schedule.getStartTimeMs()
+ - RecordingTask.RECORDING_EARLY_START_OFFSET_MS;
}
}
}
@@ -333,8 +354,9 @@ public class InputTaskScheduler {
private RecordingTask createRecordingTask(ScheduledRecording schedule) {
Channel channel = mChannelDataManager.getChannel(schedule.getChannelId());
- RecordingTask recordingTask = mRecordingTaskFactory.createRecordingTask(schedule, channel,
- mDvrManager, mSessionManager, mDataManager, mClock);
+ RecordingTask recordingTask =
+ mRecordingTaskFactory.createRecordingTask(
+ schedule, channel, mDvrManager, mSessionManager, mDataManager, mClock);
HandlerWrapper handlerWrapper = new HandlerWrapper(mLooper, schedule, recordingTask);
mPendingRecordings.put(schedule.getId(), handlerWrapper);
return recordingTask;
@@ -369,21 +391,24 @@ public class InputTaskScheduler {
return candidate;
}
- private void fail(ScheduledRecording schedule) {
+ private void fail(ScheduledRecording schedule, int reason) {
// It's called when the scheduling has been failed without creating RecordingTask.
- runOnMainHandler(new Runnable() {
- @Override
- public void run() {
- ScheduledRecording scheduleInManager =
- mDataManager.getScheduledRecording(schedule.getId());
- if (scheduleInManager != null) {
- // The schedule should be updated based on the object from DataManager in case
- // when it has been updated.
- mDataManager.changeState(scheduleInManager,
- ScheduledRecording.STATE_RECORDING_FAILED);
- }
- }
- });
+ runOnMainHandler(
+ new Runnable() {
+ @Override
+ public void run() {
+ ScheduledRecording scheduleInManager =
+ mDataManager.getScheduledRecording(schedule.getId());
+ if (scheduleInManager != null) {
+ // The schedule should be updated based on the object from DataManager
+ // in case when it has been updated.
+ mDataManager.changeState(
+ scheduleInManager,
+ ScheduledRecording.STATE_RECORDING_FAILED,
+ reason);
+ }
+ }
+ });
}
private void runOnMainHandler(Runnable runnable) {
@@ -396,9 +421,13 @@ public class InputTaskScheduler {
@VisibleForTesting
interface RecordingTaskFactory {
- RecordingTask createRecordingTask(ScheduledRecording scheduledRecording, Channel channel,
- DvrManager dvrManager, InputSessionManager sessionManager,
- WritableDvrDataManager dataManager, Clock clock);
+ RecordingTask createRecordingTask(
+ ScheduledRecording scheduledRecording,
+ Channel channel,
+ DvrManager dvrManager,
+ InputSessionManager sessionManager,
+ WritableDvrDataManager dataManager,
+ Clock clock);
}
private class WorkerThreadHandler extends Handler {
@@ -417,6 +446,7 @@ public class InputTaskScheduler {
break;
case MSG_UPDATE_SCHEDULED_RECORDING:
handleUpdateSchedule((ScheduledRecording) msg.obj);
+ break;
case MSG_BUILD_SCHEDULE:
handleBuildSchedule();
break;