aboutsummaryrefslogtreecommitdiff
path: root/src/com/android/tv/dvr
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/tv/dvr')
-rw-r--r--src/com/android/tv/dvr/BaseDvrDataManager.java106
-rw-r--r--src/com/android/tv/dvr/DvrDataManager.java152
-rw-r--r--src/com/android/tv/dvr/DvrDataManagerImpl.java439
-rw-r--r--src/com/android/tv/dvr/DvrManager.java391
-rw-r--r--src/com/android/tv/dvr/DvrScheduleManager.java596
-rw-r--r--src/com/android/tv/dvr/DvrStorageStatusManager.java334
-rw-r--r--src/com/android/tv/dvr/DvrWatchedPositionManager.java61
-rw-r--r--src/com/android/tv/dvr/WritableDvrDataManager.java37
-rw-r--r--src/com/android/tv/dvr/data/IdGenerator.java20
-rw-r--r--src/com/android/tv/dvr/data/RecordedProgram.java473
-rw-r--r--src/com/android/tv/dvr/data/ScheduledRecording.java659
-rw-r--r--src/com/android/tv/dvr/data/SeasonEpisodeNumber.java27
-rw-r--r--src/com/android/tv/dvr/data/SeriesInfo.java28
-rw-r--r--src/com/android/tv/dvr/data/SeriesRecording.java399
-rw-r--r--src/com/android/tv/dvr/provider/AsyncDvrDbTask.java60
-rw-r--r--src/com/android/tv/dvr/provider/DvrContract.java120
-rw-r--r--src/com/android/tv/dvr/provider/DvrDatabaseHelper.java285
-rw-r--r--src/com/android/tv/dvr/provider/DvrDbSync.java202
-rw-r--r--src/com/android/tv/dvr/provider/EpisodicProgramLoadTask.java157
-rw-r--r--src/com/android/tv/dvr/recorder/ConflictChecker.java113
-rw-r--r--src/com/android/tv/dvr/recorder/DvrRecordingService.java58
-rw-r--r--src/com/android/tv/dvr/recorder/DvrStartRecordingReceiver.java12
-rw-r--r--src/com/android/tv/dvr/recorder/InputTaskScheduler.java172
-rw-r--r--src/com/android/tv/dvr/recorder/RecordingScheduler.java118
-rw-r--r--src/com/android/tv/dvr/recorder/RecordingTask.java362
-rw-r--r--src/com/android/tv/dvr/recorder/ScheduledProgramReaper.java16
-rw-r--r--src/com/android/tv/dvr/recorder/SeriesRecordingScheduler.java283
-rw-r--r--src/com/android/tv/dvr/ui/BigArguments.java20
-rw-r--r--src/com/android/tv/dvr/ui/ChangeImageTransformWithScaledParent.java24
-rw-r--r--src/com/android/tv/dvr/ui/DvrAlreadyRecordedFragment.java47
-rw-r--r--src/com/android/tv/dvr/ui/DvrAlreadyScheduledFragment.java57
-rw-r--r--src/com/android/tv/dvr/ui/DvrChannelRecordDurationOptionFragment.java57
-rw-r--r--src/com/android/tv/dvr/ui/DvrConflictFragment.java159
-rw-r--r--src/com/android/tv/dvr/ui/DvrFutureProgramInfoFragment.java87
-rw-r--r--src/com/android/tv/dvr/ui/DvrGuidedActionsStylist.java15
-rw-r--r--src/com/android/tv/dvr/ui/DvrGuidedStepFragment.java92
-rw-r--r--src/com/android/tv/dvr/ui/DvrHalfSizedDialogFragment.java62
-rw-r--r--src/com/android/tv/dvr/ui/DvrInsufficientSpaceErrorFragment.java83
-rw-r--r--src/com/android/tv/dvr/ui/DvrMissingStorageErrorFragment.java24
-rw-r--r--src/com/android/tv/dvr/ui/DvrPrioritySettingsFragment.java86
-rw-r--r--src/com/android/tv/dvr/ui/DvrScheduleFragment.java114
-rw-r--r--src/com/android/tv/dvr/ui/DvrSeriesDeletionActivity.java13
-rw-r--r--src/com/android/tv/dvr/ui/DvrSeriesDeletionFragment.java126
-rw-r--r--src/com/android/tv/dvr/ui/DvrSeriesScheduledDialogActivity.java13
-rw-r--r--src/com/android/tv/dvr/ui/DvrSeriesScheduledFragment.java119
-rw-r--r--src/com/android/tv/dvr/ui/DvrSeriesSettingsActivity.java32
-rw-r--r--src/com/android/tv/dvr/ui/DvrSeriesSettingsFragment.java151
-rw-r--r--src/com/android/tv/dvr/ui/DvrStopRecordingFragment.java57
-rw-r--r--src/com/android/tv/dvr/ui/DvrStopSeriesRecordingDialogFragment.java9
-rw-r--r--src/com/android/tv/dvr/ui/DvrStopSeriesRecordingFragment.java40
-rw-r--r--src/com/android/tv/dvr/ui/DvrUiHelper.java547
-rw-r--r--src/com/android/tv/dvr/ui/FadeBackground.java17
-rw-r--r--src/com/android/tv/dvr/ui/SortedArrayAdapter.java34
-rw-r--r--src/com/android/tv/dvr/ui/TrackedGuidedStepFragment.java5
-rw-r--r--src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java34
-rw-r--r--src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java28
-rw-r--r--src/com/android/tv/dvr/ui/browse/DetailsContent.java172
-rw-r--r--src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java188
-rw-r--r--src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java17
-rw-r--r--src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java11
-rw-r--r--src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java339
-rw-r--r--src/com/android/tv/dvr/ui/browse/DvrDetailsActivity.java48
-rw-r--r--src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java151
-rw-r--r--src/com/android/tv/dvr/ui/browse/DvrHistoryCardHolder.java25
-rw-r--r--src/com/android/tv/dvr/ui/browse/DvrHistoryCardPresenter.java64
-rw-r--r--src/com/android/tv/dvr/ui/browse/DvrItemPresenter.java41
-rw-r--r--src/com/android/tv/dvr/ui/browse/DvrListRowPresenter.java1
-rw-r--r--src/com/android/tv/dvr/ui/browse/FullScheduleCardHolder.java10
-rw-r--r--src/com/android/tv/dvr/ui/browse/FullSchedulesCardPresenter.java35
-rw-r--r--src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java71
-rw-r--r--src/com/android/tv/dvr/ui/browse/RecordedProgramPresenter.java55
-rw-r--r--src/com/android/tv/dvr/ui/browse/RecordingCardView.java92
-rw-r--r--src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java27
-rw-r--r--src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java45
-rw-r--r--src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java102
-rw-r--r--src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java104
-rw-r--r--src/com/android/tv/dvr/ui/browse/SeriesRecordingPresenter.java44
-rw-r--r--src/com/android/tv/dvr/ui/list/BaseDvrSchedulesFragment.java87
-rw-r--r--src/com/android/tv/dvr/ui/list/DvrHistoryActivity.java39
-rw-r--r--src/com/android/tv/dvr/ui/list/DvrHistoryFragment.java166
-rw-r--r--src/com/android/tv/dvr/ui/list/DvrHistoryRowAdapter.java353
-rw-r--r--src/com/android/tv/dvr/ui/list/DvrSchedulesActivity.java47
-rw-r--r--src/com/android/tv/dvr/ui/list/DvrSchedulesFocusView.java11
-rw-r--r--src/com/android/tv/dvr/ui/list/DvrSchedulesFragment.java15
-rw-r--r--src/com/android/tv/dvr/ui/list/DvrSeriesSchedulesFragment.java117
-rw-r--r--src/com/android/tv/dvr/ui/list/EpisodicProgramRow.java19
-rw-r--r--src/com/android/tv/dvr/ui/list/ScheduleRow.java111
-rw-r--r--src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java174
-rw-r--r--src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java611
-rw-r--r--src/com/android/tv/dvr/ui/list/SchedulesHeaderRow.java63
-rw-r--r--src/com/android/tv/dvr/ui/list/SchedulesHeaderRowPresenter.java198
-rw-r--r--src/com/android/tv/dvr/ui/list/SeriesScheduleRowAdapter.java66
-rw-r--r--src/com/android/tv/dvr/ui/list/SeriesScheduleRowPresenter.java71
-rw-r--r--src/com/android/tv/dvr/ui/playback/DvrPlaybackActivity.java19
-rw-r--r--src/com/android/tv/dvr/ui/playback/DvrPlaybackCardPresenter.java14
-rw-r--r--src/com/android/tv/dvr/ui/playback/DvrPlaybackControlHelper.java132
-rw-r--r--src/com/android/tv/dvr/ui/playback/DvrPlaybackMediaSessionHelper.java171
-rw-r--r--src/com/android/tv/dvr/ui/playback/DvrPlaybackOverlayFragment.java188
-rw-r--r--src/com/android/tv/dvr/ui/playback/DvrPlaybackSideFragment.java59
-rw-r--r--src/com/android/tv/dvr/ui/playback/DvrPlayer.java361
100 files changed, 6940 insertions, 5626 deletions
diff --git a/src/com/android/tv/dvr/BaseDvrDataManager.java b/src/com/android/tv/dvr/BaseDvrDataManager.java
index a8637449..b8bffa18 100644
--- a/src/com/android/tv/dvr/BaseDvrDataManager.java
+++ b/src/com/android/tv/dvr/BaseDvrDataManager.java
@@ -23,15 +23,13 @@ import android.support.annotation.MainThread;
import android.support.annotation.NonNull;
import android.util.ArraySet;
import android.util.Log;
-
import com.android.tv.common.SoftPreconditions;
import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.common.util.Clock;
import com.android.tv.dvr.data.RecordedProgram;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.ScheduledRecording.RecordingState;
import com.android.tv.dvr.data.SeriesRecording;
-import com.android.tv.util.Clock;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -42,14 +40,12 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
-/**
- * Base implementation of @{link DataManagerInternal}.
- */
+/** Base implementation of @{link DataManagerInternal}. */
@MainThread
@TargetApi(Build.VERSION_CODES.N)
public abstract class BaseDvrDataManager implements WritableDvrDataManager {
- private final static String TAG = "BaseDvrDataManager";
- private final static boolean DEBUG = false;
+ private static final String TAG = "BaseDvrDataManager";
+ private static final boolean DEBUG = false;
protected final Clock mClock;
private final Set<OnDvrScheduleLoadFinishedListener> mOnDvrScheduleLoadFinishedListeners =
@@ -61,7 +57,7 @@ public abstract class BaseDvrDataManager implements WritableDvrDataManager {
private final Set<RecordedProgramListener> mRecordedProgramListeners = new ArraySet<>();
private final HashMap<Long, ScheduledRecording> mDeletedScheduleMap = new HashMap<>();
- BaseDvrDataManager(Context context, Clock clock) {
+ public BaseDvrDataManager(Context context, Clock clock) {
SoftPreconditions.checkFeatureEnabled(context, CommonFeatures.DVR, TAG);
mClock = clock;
}
@@ -129,8 +125,8 @@ public abstract class BaseDvrDataManager implements WritableDvrDataManager {
}
/**
- * Calls {@link OnRecordedProgramLoadFinishedListener#onRecordedProgramLoadFinished()}
- * for each listener.
+ * Calls {@link OnRecordedProgramLoadFinishedListener#onRecordedProgramLoadFinished()} for each
+ * listener.
*/
protected final void notifyRecordedProgramLoadFinished() {
for (OnRecordedProgramLoadFinishedListener l : mOnRecordedProgramLoadFinishedListeners) {
@@ -139,10 +135,7 @@ public abstract class BaseDvrDataManager implements WritableDvrDataManager {
}
}
- /**
- * Calls {@link RecordedProgramListener#onRecordedProgramsAdded}
- * for each listener.
- */
+ /** Calls {@link RecordedProgramListener#onRecordedProgramsAdded} for each listener. */
protected final void notifyRecordedProgramsAdded(RecordedProgram... recordedPrograms) {
for (RecordedProgramListener l : mRecordedProgramListeners) {
if (DEBUG) Log.d(TAG, "notify " + l + " added " + Arrays.asList(recordedPrograms));
@@ -150,10 +143,7 @@ public abstract class BaseDvrDataManager implements WritableDvrDataManager {
}
}
- /**
- * Calls {@link RecordedProgramListener#onRecordedProgramsChanged}
- * for each listener.
- */
+ /** Calls {@link RecordedProgramListener#onRecordedProgramsChanged} for each listener. */
protected final void notifyRecordedProgramsChanged(RecordedProgram... recordedPrograms) {
for (RecordedProgramListener l : mRecordedProgramListeners) {
if (DEBUG) Log.d(TAG, "notify " + l + " changed " + Arrays.asList(recordedPrograms));
@@ -161,10 +151,7 @@ public abstract class BaseDvrDataManager implements WritableDvrDataManager {
}
}
- /**
- * Calls {@link RecordedProgramListener#onRecordedProgramsRemoved}
- * for each listener.
- */
+ /** Calls {@link RecordedProgramListener#onRecordedProgramsRemoved} for each listener. */
protected final void notifyRecordedProgramsRemoved(RecordedProgram... recordedPrograms) {
for (RecordedProgramListener l : mRecordedProgramListeners) {
if (DEBUG) Log.d(TAG, "notify " + l + " removed " + Arrays.asList(recordedPrograms));
@@ -172,10 +159,7 @@ public abstract class BaseDvrDataManager implements WritableDvrDataManager {
}
}
- /**
- * Calls {@link SeriesRecordingListener#onSeriesRecordingAdded}
- * for each listener.
- */
+ /** Calls {@link SeriesRecordingListener#onSeriesRecordingAdded} for each listener. */
protected final void notifySeriesRecordingAdded(SeriesRecording... seriesRecordings) {
for (SeriesRecordingListener l : mSeriesRecordingListeners) {
if (DEBUG) Log.d(TAG, "notify " + l + " added " + Arrays.asList(seriesRecordings));
@@ -183,10 +167,7 @@ public abstract class BaseDvrDataManager implements WritableDvrDataManager {
}
}
- /**
- * Calls {@link SeriesRecordingListener#onSeriesRecordingRemoved}
- * for each listener.
- */
+ /** Calls {@link SeriesRecordingListener#onSeriesRecordingRemoved} for each listener. */
protected final void notifySeriesRecordingRemoved(SeriesRecording... seriesRecordings) {
for (SeriesRecordingListener l : mSeriesRecordingListeners) {
if (DEBUG) Log.d(TAG, "notify " + l + " removed " + Arrays.asList(seriesRecordings));
@@ -194,11 +175,7 @@ public abstract class BaseDvrDataManager implements WritableDvrDataManager {
}
}
- /**
- * Calls
- * {@link SeriesRecordingListener#onSeriesRecordingChanged}
- * for each listener.
- */
+ /** Calls {@link SeriesRecordingListener#onSeriesRecordingChanged} for each listener. */
protected final void notifySeriesRecordingChanged(SeriesRecording... seriesRecordings) {
for (SeriesRecordingListener l : mSeriesRecordingListeners) {
if (DEBUG) Log.d(TAG, "notify " + l + " changed " + Arrays.asList(seriesRecordings));
@@ -206,10 +183,7 @@ public abstract class BaseDvrDataManager implements WritableDvrDataManager {
}
}
- /**
- * Calls {@link ScheduledRecordingListener#onScheduledRecordingAdded}
- * for each listener.
- */
+ /** Calls {@link ScheduledRecordingListener#onScheduledRecordingAdded} for each listener. */
protected final void notifyScheduledRecordingAdded(ScheduledRecording... scheduledRecording) {
for (ScheduledRecordingListener l : mScheduledRecordingListeners) {
if (DEBUG) Log.d(TAG, "notify " + l + " added " + Arrays.asList(scheduledRecording));
@@ -217,10 +191,7 @@ public abstract class BaseDvrDataManager implements WritableDvrDataManager {
}
}
- /**
- * Calls {@link ScheduledRecordingListener#onScheduledRecordingRemoved}
- * for each listener.
- */
+ /** Calls {@link ScheduledRecordingListener#onScheduledRecordingRemoved} for each listener. */
protected final void notifyScheduledRecordingRemoved(ScheduledRecording... scheduledRecording) {
for (ScheduledRecordingListener l : mScheduledRecordingListeners) {
if (DEBUG) Log.d(TAG, "notify " + l + " removed " + Arrays.asList(scheduledRecording));
@@ -229,9 +200,7 @@ public abstract class BaseDvrDataManager implements WritableDvrDataManager {
}
/**
- * Calls
- * {@link ScheduledRecordingListener#onScheduledRecordingStatusChanged}
- * for each listener.
+ * Calls {@link ScheduledRecordingListener#onScheduledRecordingStatusChanged} for each listener.
*/
protected final void notifyScheduledRecordingStatusChanged(
ScheduledRecording... scheduledRecording) {
@@ -257,28 +226,47 @@ public abstract class BaseDvrDataManager implements WritableDvrDataManager {
@Override
public List<ScheduledRecording> getAvailableScheduledRecordings() {
- return filterEndTimeIsPast(getRecordingsWithState(
- ScheduledRecording.STATE_RECORDING_IN_PROGRESS,
- ScheduledRecording.STATE_RECORDING_NOT_STARTED));
+ return filterEndTimeIsPast(
+ getRecordingsWithState(
+ ScheduledRecording.STATE_RECORDING_IN_PROGRESS,
+ ScheduledRecording.STATE_RECORDING_NOT_STARTED));
}
@Override
public List<ScheduledRecording> getStartedRecordings() {
- return filterEndTimeIsPast(getRecordingsWithState(
- ScheduledRecording.STATE_RECORDING_IN_PROGRESS));
+ return filterEndTimeIsPast(
+ getRecordingsWithState(ScheduledRecording.STATE_RECORDING_IN_PROGRESS));
}
@Override
public List<ScheduledRecording> getNonStartedScheduledRecordings() {
- return filterEndTimeIsPast(getRecordingsWithState(
- ScheduledRecording.STATE_RECORDING_NOT_STARTED));
+ return filterEndTimeIsPast(
+ getRecordingsWithState(ScheduledRecording.STATE_RECORDING_NOT_STARTED));
+ }
+
+ @Override
+ public List<ScheduledRecording> getFailedScheduledRecordings() {
+ return getRecordingsWithState(ScheduledRecording.STATE_RECORDING_FAILED);
}
@Override
public void changeState(ScheduledRecording scheduledRecording, @RecordingState int newState) {
if (scheduledRecording.getState() != newState) {
- updateScheduledRecording(ScheduledRecording.buildFrom(scheduledRecording)
- .setState(newState).build());
+ updateScheduledRecording(
+ ScheduledRecording.buildFrom(scheduledRecording).setState(newState).build());
+ }
+ }
+
+ @Override
+ public void changeState(
+ ScheduledRecording scheduledRecording, @RecordingState int newState, int reason) {
+ if (scheduledRecording.getState() != newState) {
+ ScheduledRecording.Builder builder =
+ ScheduledRecording.buildFrom(scheduledRecording).setState(newState);
+ if (newState == ScheduledRecording.STATE_RECORDING_FAILED) {
+ builder.setFailedReason(reason);
+ }
+ updateScheduledRecording(builder.build());
}
}
@@ -300,9 +288,7 @@ public abstract class BaseDvrDataManager implements WritableDvrDataManager {
return mDeletedScheduleMap;
}
- /**
- * Returns the schedules whose state is contained by states.
- */
+ /** Returns the schedules whose state is contained by states. */
protected abstract List<ScheduledRecording> getRecordingsWithState(int... states);
@Override
@@ -357,5 +343,5 @@ public abstract class BaseDvrDataManager implements WritableDvrDataManager {
}
@Override
- public void forgetStorage(String inputId) { }
+ public void forgetStorage(String inputId) {}
}
diff --git a/src/com/android/tv/dvr/DvrDataManager.java b/src/com/android/tv/dvr/DvrDataManager.java
index 6d400b82..10dfc4c9 100644
--- a/src/com/android/tv/dvr/DvrDataManager.java
+++ b/src/com/android/tv/dvr/DvrDataManager.java
@@ -20,48 +20,36 @@ import android.support.annotation.MainThread;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Range;
-
import com.android.tv.dvr.data.RecordedProgram;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.ScheduledRecording.RecordingState;
import com.android.tv.dvr.data.SeriesRecording;
-
import java.util.Collection;
import java.util.List;
-/**
- * Read only data manager.
- */
+/** Read only data manager. */
@MainThread
public interface DvrDataManager {
long NEXT_START_TIME_NOT_FOUND = -1;
boolean isInitialized();
- /**
- * Returns {@code true} if the schedules were loaded, otherwise {@code false}.
- */
+ /** Returns {@code true} if the schedules were loaded, otherwise {@code false}. */
boolean isDvrScheduleLoadFinished();
- /**
- * Returns {@code true} if the recorded programs were loaded, otherwise {@code false}.
- */
+ /** Returns {@code true} if the recorded programs were loaded, otherwise {@code false}. */
boolean isRecordedProgramLoadFinished();
- /**
- * Returns past recordings.
- */
+ /** Returns past recordings. */
List<RecordedProgram> getRecordedPrograms();
- /**
- * Returns past recorded programs in the given series.
- */
+ /** Returns past recorded programs in the given series. */
List<RecordedProgram> getRecordedPrograms(long seriesRecordingId);
/**
* Returns all {@link ScheduledRecording} regardless of state.
- * <p>
- * The result doesn't contain the deleted schedules.
+ *
+ * <p>The result doesn't contain the deleted schedules.
*/
List<ScheduledRecording> getAllScheduledRecordings();
@@ -71,29 +59,24 @@ public interface DvrDataManager {
*/
List<ScheduledRecording> getAvailableScheduledRecordings();
- /**
- * Returns started recordings that expired.
- */
+ /** Returns started recordings that expired. */
List<ScheduledRecording> getStartedRecordings();
- /**
- * Returns scheduled but not started recordings that have not expired.
- */
+ /** Returns scheduled but not started recordings that have not expired. */
List<ScheduledRecording> getNonStartedScheduledRecordings();
- /**
- * Returns series recordings.
- */
+ /** Returns failed recordings. */
+ List<ScheduledRecording> getFailedScheduledRecordings();
+
+ /** Returns series recordings. */
List<SeriesRecording> getSeriesRecordings();
- /**
- * Returns series recordings from the given input.
- */
+ /** Returns series recordings from the given input. */
List<SeriesRecording> getSeriesRecordings(String inputId);
/**
- * Returns the next start time after {@code time} or {@link #NEXT_START_TIME_NOT_FOUND}
- * if none is found.
+ * Returns the next start time after {@code time} or {@link #NEXT_START_TIME_NOT_FOUND} if none
+ * is found.
*
* @param time time milliseconds
*/
@@ -103,73 +86,48 @@ public interface DvrDataManager {
* Returns a list of the schedules with a overlap with the given time period inclusive and with
* the given state.
*
- * <p> A recording overlaps with a period when
- * {@code recording.getStartTime() <= period.getUpper() &&
- * recording.getEndTime() >= period.getLower()}.
+ * <p>A recording overlaps with a period when {@code recording.getStartTime() <=
+ * period.getUpper() && recording.getEndTime() >= period.getLower()}.
*
* @param period a time period in milliseconds.
* @param state the state of the schedule.
*/
List<ScheduledRecording> getScheduledRecordings(Range<Long> period, @RecordingState int state);
- /**
- * Returns a list of the schedules in the given series.
- */
+ /** Returns a list of the schedules in the given series. */
List<ScheduledRecording> getScheduledRecordings(long seriesRecordingId);
- /**
- * Returns a list of the schedules from the given input.
- */
+ /** Returns a list of the schedules from the given input. */
List<ScheduledRecording> getScheduledRecordings(String inputId);
- /**
- * Add a {@link OnDvrScheduleLoadFinishedListener}.
- */
+ /** Add a {@link OnDvrScheduleLoadFinishedListener}. */
void addDvrScheduleLoadFinishedListener(OnDvrScheduleLoadFinishedListener listener);
- /**
- * Remove a {@link OnDvrScheduleLoadFinishedListener}.
- */
+ /** Remove a {@link OnDvrScheduleLoadFinishedListener}. */
void removeDvrScheduleLoadFinishedListener(OnDvrScheduleLoadFinishedListener listener);
- /**
- * Add a {@link OnRecordedProgramLoadFinishedListener}.
- */
+ /** Add a {@link OnRecordedProgramLoadFinishedListener}. */
void addRecordedProgramLoadFinishedListener(OnRecordedProgramLoadFinishedListener listener);
- /**
- * Remove a {@link OnRecordedProgramLoadFinishedListener}.
- */
+ /** Remove a {@link OnRecordedProgramLoadFinishedListener}. */
void removeRecordedProgramLoadFinishedListener(OnRecordedProgramLoadFinishedListener listener);
- /**
- * Add a {@link ScheduledRecordingListener}.
- */
+ /** Add a {@link ScheduledRecordingListener}. */
void addScheduledRecordingListener(ScheduledRecordingListener scheduledRecordingListener);
- /**
- * Remove a {@link ScheduledRecordingListener}.
- */
+ /** Remove a {@link ScheduledRecordingListener}. */
void removeScheduledRecordingListener(ScheduledRecordingListener scheduledRecordingListener);
- /**
- * Add a {@link RecordedProgramListener}.
- */
+ /** Add a {@link RecordedProgramListener}. */
void addRecordedProgramListener(RecordedProgramListener listener);
- /**
- * Remove a {@link RecordedProgramListener}.
- */
+ /** Remove a {@link RecordedProgramListener}. */
void removeRecordedProgramListener(RecordedProgramListener listener);
- /**
- * Add a {@link ScheduledRecordingListener}.
- */
+ /** Add a {@link ScheduledRecordingListener}. */
void addSeriesRecordingListener(SeriesRecordingListener seriesRecordingListener);
- /**
- * Remove a {@link ScheduledRecordingListener}.
- */
+ /** Remove a {@link ScheduledRecordingListener}. */
void removeSeriesRecordingListener(SeriesRecordingListener seriesRecordingListener);
/**
@@ -178,65 +136,47 @@ public interface DvrDataManager {
@Nullable
ScheduledRecording getScheduledRecording(long recordingId);
- /**
- * Returns the scheduled recording program with the given programId or null if is not found.
- */
+ /** Returns the scheduled recording program with the given programId or null if is not found. */
@Nullable
ScheduledRecording getScheduledRecordingForProgramId(long programId);
- /**
- * Returns the recorded program with the given recordingId or null if is not found.
- */
+ /** Returns the recorded program with the given recordingId or null if is not found. */
@Nullable
RecordedProgram getRecordedProgram(long recordingId);
- /**
- * Returns the series recording with the given seriesId or null if is not found.
- */
+ /** Returns the series recording with the given seriesId or null if is not found. */
@Nullable
SeriesRecording getSeriesRecording(long seriesRecordingId);
- /**
- * Returns the series recording with the given series ID or {@code null} if not found.
- */
+ /** Returns the series recording with the given series ID or {@code null} if not found. */
@Nullable
SeriesRecording getSeriesRecording(String seriesId);
- /**
- * Returns the schedules which are marked deleted.
- */
+ /** Returns the schedules which are marked deleted. */
Collection<ScheduledRecording> getDeletedSchedules();
- /**
- * Returns the program IDs which is not allowed to make a schedule automatically.
- */
+ /** Returns the program IDs which is not allowed to make a schedule automatically. */
@NonNull
Collection<Long> getDisallowedProgramIds();
/**
- * Checks each of the give series recordings to see if it's empty, i.e., it doesn't contains
- * any available schedules or recorded programs, and it's status is
- * {@link SeriesRecording#STATE_SERIES_STOPPED}; and removes those empty series recordings.
+ * Checks each of the give series recordings to see if it's empty, i.e., it doesn't contains any
+ * available schedules or recorded programs, and it's status is {@link
+ * SeriesRecording#STATE_SERIES_STOPPED}; and removes those empty series recordings.
*/
void checkAndRemoveEmptySeriesRecording(long... seriesRecordingIds);
- /**
- * Listens for the DVR schedules loading finished.
- */
+ /** Listens for the DVR schedules loading finished. */
interface OnDvrScheduleLoadFinishedListener {
void onDvrScheduleLoadFinished();
}
- /**
- * Listens for the recorded program loading finished.
- */
+ /** Listens for the recorded program loading finished. */
interface OnRecordedProgramLoadFinishedListener {
void onRecordedProgramLoadFinished();
}
- /**
- * Listens for changes to {@link ScheduledRecording}s.
- */
+ /** Listens for changes to {@link ScheduledRecording}s. */
interface ScheduledRecordingListener {
void onScheduledRecordingAdded(ScheduledRecording... scheduledRecordings);
@@ -250,9 +190,7 @@ public interface DvrDataManager {
void onScheduledRecordingStatusChanged(ScheduledRecording... scheduledRecordings);
}
- /**
- * Listens for changes to {@link SeriesRecording}s.
- */
+ /** Listens for changes to {@link SeriesRecording}s. */
interface SeriesRecordingListener {
void onSeriesRecordingAdded(SeriesRecording... seriesRecordings);
@@ -261,9 +199,7 @@ public interface DvrDataManager {
void onSeriesRecordingChanged(SeriesRecording... seriesRecordings);
}
- /**
- * Listens for changes to {@link RecordedProgram}s.
- */
+ /** Listens for changes to {@link RecordedProgram}s. */
interface RecordedProgramListener {
void onRecordedProgramsAdded(RecordedProgram... recordedPrograms);
diff --git a/src/com/android/tv/dvr/DvrDataManagerImpl.java b/src/com/android/tv/dvr/DvrDataManagerImpl.java
index 6094ca72..2b4ecbf5 100644
--- a/src/com/android/tv/dvr/DvrDataManagerImpl.java
+++ b/src/com/android/tv/dvr/DvrDataManagerImpl.java
@@ -38,10 +38,12 @@ import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Range;
-
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
-import com.android.tv.dvr.DvrStorageStatusManager.OnStorageMountChangedListener;
+import com.android.tv.common.recording.RecordingStorageStatusManager;
+import com.android.tv.common.recording.RecordingStorageStatusManager.OnStorageMountChangedListener;
+import com.android.tv.common.util.Clock;
+import com.android.tv.common.util.CommonUtils;
import com.android.tv.dvr.data.IdGenerator;
import com.android.tv.dvr.data.RecordedProgram;
import com.android.tv.dvr.data.ScheduledRecording;
@@ -59,12 +61,9 @@ import com.android.tv.dvr.provider.DvrDbSync;
import com.android.tv.dvr.recorder.SeriesRecordingScheduler;
import com.android.tv.util.AsyncDbTask;
import com.android.tv.util.AsyncDbTask.AsyncRecordedProgramQueryTask;
-import com.android.tv.util.Clock;
import com.android.tv.util.Filter;
import com.android.tv.util.TvInputManagerHelper;
import com.android.tv.util.TvUriMatcher;
-import com.android.tv.util.Utils;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -73,10 +72,9 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.concurrent.Executor;
-/**
- * DVR Data manager to handle recordings and schedules.
- */
+/** DVR Data manager to handle recordings and schedules. */
@MainThread
@TargetApi(Build.VERSION_CODES.N)
public class DvrDataManagerImpl extends BaseDvrDataManager {
@@ -98,52 +96,54 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
private final HashMap<Long, SeriesRecording> mSeriesRecordingsForRemovedInput = new HashMap<>();
private final Context mContext;
- private final ContentObserver mContentObserver = new ContentObserver(new Handler(
- Looper.getMainLooper())) {
- @Override
- public void onChange(boolean selfChange) {
- onChange(selfChange, null);
- }
+ private Executor mDbExecutor;
+ private final ContentObserver mContentObserver =
+ new ContentObserver(new Handler(Looper.getMainLooper())) {
+ @Override
+ public void onChange(boolean selfChange) {
+ onChange(selfChange, null);
+ }
- @Override
- public void onChange(boolean selfChange, final @Nullable Uri uri) {
- RecordedProgramsQueryTask task = new RecordedProgramsQueryTask(
- mContext.getContentResolver(), uri);
- task.executeOnDbThread();
- mPendingTasks.add(task);
- }
- };
+ @Override
+ public void onChange(boolean selfChange, final @Nullable Uri uri) {
+ RecordedProgramsQueryTask task =
+ new RecordedProgramsQueryTask(mContext.getContentResolver(), uri);
+ task.executeOnDbThread();
+ mPendingTasks.add(task);
+ }
+ };
private boolean mDvrLoadFinished;
private boolean mRecordedProgramLoadFinished;
private final Set<AsyncTask> mPendingTasks = new ArraySet<>();
private DvrDbSync mDbSync;
- private DvrStorageStatusManager mStorageStatusManager;
+ private RecordingStorageStatusManager mStorageStatusManager;
- private final TvInputCallback mInputCallback = new TvInputCallback() {
- @Override
- public void onInputAdded(String inputId) {
- if (DEBUG) Log.d(TAG, "onInputAdded " + inputId);
- if (!isInputAvailable(inputId)) {
- if (DEBUG) Log.d(TAG, "Not available for recording");
- return;
- }
- unhideInput(inputId);
- }
+ private final TvInputCallback mInputCallback =
+ new TvInputCallback() {
+ @Override
+ public void onInputAdded(String inputId) {
+ if (DEBUG) Log.d(TAG, "onInputAdded " + inputId);
+ if (!isInputAvailable(inputId)) {
+ if (DEBUG) Log.d(TAG, "Not available for recording");
+ return;
+ }
+ unhideInput(inputId);
+ }
- @Override
- public void onInputRemoved(String inputId) {
- if (DEBUG) Log.d(TAG, "onInputRemoved " + inputId);
- hideInput(inputId);
- }
- };
+ @Override
+ public void onInputRemoved(String inputId) {
+ if (DEBUG) Log.d(TAG, "onInputRemoved " + inputId);
+ hideInput(inputId);
+ }
+ };
private final OnStorageMountChangedListener mStorageMountChangedListener =
new OnStorageMountChangedListener() {
@Override
public void onStorageMountChanged(boolean storageMounted) {
for (TvInputInfo input : mInputManager.getTvInputInfos(true, true)) {
- if (Utils.isBundledInput(input.getId())) {
+ if (CommonUtils.isBundledInput(input.getId())) {
if (storageMounted) {
unhideInput(input.getId());
} else {
@@ -154,8 +154,8 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
}
};
- private static <T> List<T> moveElements(HashMap<Long, T> from, HashMap<Long, T> to,
- Filter<T> filter) {
+ private static <T> List<T> moveElements(
+ HashMap<Long, T> from, HashMap<Long, T> to, Filter<T> filter) {
List<T> moved = new ArrayList<>();
Iterator<Entry<Long, T>> iter = from.entrySet().iterator();
while (iter.hasNext()) {
@@ -172,119 +172,139 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
public DvrDataManagerImpl(Context context, Clock clock) {
super(context, clock);
mContext = context;
- mInputManager = TvApplication.getSingletons(context).getTvInputManagerHelper();
- mStorageStatusManager = TvApplication.getSingletons(context).getDvrStorageStatusManager();
+ TvSingletons tvSingletons = TvSingletons.getSingletons(context);
+ mInputManager = tvSingletons.getTvInputManagerHelper();
+ mStorageStatusManager = tvSingletons.getRecordingStorageStatusManager();
+ mDbExecutor = tvSingletons.getDbExecutor();
}
public void start() {
mInputManager.addCallback(mInputCallback);
mStorageStatusManager.addListener(mStorageMountChangedListener);
- AsyncDvrQuerySeriesRecordingTask dvrQuerySeriesRecordingTask
- = new AsyncDvrQuerySeriesRecordingTask(mContext) {
- @Override
- protected void onCancelled(List<SeriesRecording> seriesRecordings) {
- mPendingTasks.remove(this);
- }
+ AsyncDvrQuerySeriesRecordingTask dvrQuerySeriesRecordingTask =
+ new AsyncDvrQuerySeriesRecordingTask(mContext) {
+ @Override
+ protected void onCancelled(List<SeriesRecording> seriesRecordings) {
+ mPendingTasks.remove(this);
+ }
- @Override
- protected void onPostExecute(List<SeriesRecording> seriesRecordings) {
- mPendingTasks.remove(this);
- long maxId = 0;
- HashSet<String> seriesIds = new HashSet<>();
- for (SeriesRecording r : seriesRecordings) {
- if (SoftPreconditions.checkState(!seriesIds.contains(r.getSeriesId()), TAG,
- "Skip loading series recording with duplicate series ID: " + r)) {
- seriesIds.add(r.getSeriesId());
- if (isInputAvailable(r.getInputId())) {
- mSeriesRecordings.put(r.getId(), r);
- mSeriesId2SeriesRecordings.put(r.getSeriesId(), r);
- } else {
- mSeriesRecordingsForRemovedInput.put(r.getId(), r);
+ @Override
+ protected void onPostExecute(List<SeriesRecording> seriesRecordings) {
+ mPendingTasks.remove(this);
+ long maxId = 0;
+ HashSet<String> seriesIds = new HashSet<>();
+ for (SeriesRecording r : seriesRecordings) {
+ if (SoftPreconditions.checkState(
+ !seriesIds.contains(r.getSeriesId()),
+ TAG,
+ "Skip loading series recording with duplicate series ID: "
+ + r)) {
+ seriesIds.add(r.getSeriesId());
+ if (isInputAvailable(r.getInputId())) {
+ mSeriesRecordings.put(r.getId(), r);
+ mSeriesId2SeriesRecordings.put(r.getSeriesId(), r);
+ } else {
+ mSeriesRecordingsForRemovedInput.put(r.getId(), r);
+ }
+ }
+ if (maxId < r.getId()) {
+ maxId = r.getId();
+ }
}
+ IdGenerator.SERIES_RECORDING.setMaxId(maxId);
}
- if (maxId < r.getId()) {
- maxId = r.getId();
- }
- }
- IdGenerator.SERIES_RECORDING.setMaxId(maxId);
- }
- };
+ };
dvrQuerySeriesRecordingTask.executeOnDbThread();
mPendingTasks.add(dvrQuerySeriesRecordingTask);
- AsyncDvrQueryScheduleTask dvrQueryScheduleTask
- = new AsyncDvrQueryScheduleTask(mContext) {
- @Override
- protected void onCancelled(List<ScheduledRecording> scheduledRecordings) {
- mPendingTasks.remove(this);
- }
+ AsyncDvrQueryScheduleTask dvrQueryScheduleTask =
+ new AsyncDvrQueryScheduleTask(mContext) {
+ @Override
+ protected void onCancelled(List<ScheduledRecording> scheduledRecordings) {
+ mPendingTasks.remove(this);
+ }
- @SuppressLint("SwitchIntDef")
- @Override
- protected void onPostExecute(List<ScheduledRecording> result) {
- mPendingTasks.remove(this);
- long maxId = 0;
- List<SeriesRecording> seriesRecordingsToAdd = new ArrayList<>();
- List<ScheduledRecording> toUpdate = new ArrayList<>();
- List<ScheduledRecording> toDelete = new ArrayList<>();
- for (ScheduledRecording r : result) {
- if (!isInputAvailable(r.getInputId())) {
- mScheduledRecordingsForRemovedInput.put(r.getId(), r);
- } else if (r.getState() == ScheduledRecording.STATE_RECORDING_DELETED) {
- getDeletedScheduleMap().put(r.getProgramId(), r);
- } else {
- mScheduledRecordings.put(r.getId(), r);
- if (r.getProgramId() != ScheduledRecording.ID_NOT_SET) {
- mProgramId2ScheduledRecordings.put(r.getProgramId(), r);
- }
- // Adjust the state of the schedules before DB loading is finished.
- switch (r.getState()) {
- case ScheduledRecording.STATE_RECORDING_IN_PROGRESS:
- if (r.getEndTimeMs() <= mClock.currentTimeMillis()) {
- toUpdate.add(ScheduledRecording.buildFrom(r)
- .setState(ScheduledRecording.STATE_RECORDING_FAILED)
- .build());
- } else {
- toUpdate.add(ScheduledRecording.buildFrom(r)
- .setState(
- ScheduledRecording.STATE_RECORDING_NOT_STARTED)
- .build());
+ @SuppressLint("SwitchIntDef")
+ @Override
+ protected void onPostExecute(List<ScheduledRecording> result) {
+ mPendingTasks.remove(this);
+ long maxId = 0;
+ int reasonNotStarted =
+ ScheduledRecording
+ .FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED;
+ List<ScheduledRecording> toUpdate = new ArrayList<>();
+ List<ScheduledRecording> toDelete = new ArrayList<>();
+ for (ScheduledRecording r : result) {
+ if (!isInputAvailable(r.getInputId())) {
+ mScheduledRecordingsForRemovedInput.put(r.getId(), r);
+ } else if (r.getState() == ScheduledRecording.STATE_RECORDING_DELETED) {
+ getDeletedScheduleMap().put(r.getProgramId(), r);
+ } else {
+ mScheduledRecordings.put(r.getId(), r);
+ if (r.getProgramId() != ScheduledRecording.ID_NOT_SET) {
+ mProgramId2ScheduledRecordings.put(r.getProgramId(), r);
}
- break;
- case ScheduledRecording.STATE_RECORDING_NOT_STARTED:
- if (r.getEndTimeMs() <= mClock.currentTimeMillis()) {
- toUpdate.add(ScheduledRecording.buildFrom(r)
- .setState(ScheduledRecording.STATE_RECORDING_FAILED)
- .build());
+ // Adjust the state of the schedules before DB loading is finished.
+ switch (r.getState()) {
+ case ScheduledRecording.STATE_RECORDING_IN_PROGRESS:
+ if (r.getEndTimeMs() <= mClock.currentTimeMillis()) {
+ int reason =
+ ScheduledRecording.FAILED_REASON_NOT_FINISHED;
+ toUpdate.add(
+ ScheduledRecording.buildFrom(r)
+ .setState(
+ ScheduledRecording
+ .STATE_RECORDING_FAILED)
+ .setFailedReason(reason)
+ .build());
+ } else {
+ toUpdate.add(
+ ScheduledRecording.buildFrom(r)
+ .setState(
+ ScheduledRecording
+ .STATE_RECORDING_NOT_STARTED)
+ .build());
+ }
+ break;
+ case ScheduledRecording.STATE_RECORDING_NOT_STARTED:
+ if (r.getEndTimeMs() <= mClock.currentTimeMillis()) {
+ toUpdate.add(
+ ScheduledRecording.buildFrom(r)
+ .setState(
+ ScheduledRecording
+ .STATE_RECORDING_FAILED)
+ .setFailedReason(reasonNotStarted)
+ .build());
+ }
+ break;
+ case ScheduledRecording.STATE_RECORDING_CANCELED:
+ toDelete.add(r);
+ break;
+ default: // fall out
}
- break;
- case ScheduledRecording.STATE_RECORDING_CANCELED:
- toDelete.add(r);
- break;
+ }
+ if (maxId < r.getId()) {
+ maxId = r.getId();
+ }
+ }
+ if (!toUpdate.isEmpty()) {
+ updateScheduledRecording(ScheduledRecording.toArray(toUpdate));
+ }
+ if (!toDelete.isEmpty()) {
+ removeScheduledRecording(ScheduledRecording.toArray(toDelete));
+ }
+ IdGenerator.SCHEDULED_RECORDING.setMaxId(maxId);
+ if (mRecordedProgramLoadFinished) {
+ validateSeriesRecordings();
+ }
+ mDvrLoadFinished = true;
+ notifyDvrScheduleLoadFinished();
+ if (isInitialized()) {
+ mDbSync = new DvrDbSync(mContext, DvrDataManagerImpl.this);
+ mDbSync.start();
+ SeriesRecordingScheduler.getInstance(mContext).start();
}
}
- if (maxId < r.getId()) {
- maxId = r.getId();
- }
- }
- if (!toUpdate.isEmpty()) {
- updateScheduledRecording(ScheduledRecording.toArray(toUpdate));
- }
- if (!toDelete.isEmpty()) {
- removeScheduledRecording(ScheduledRecording.toArray(toDelete));
- }
- IdGenerator.SCHEDULED_RECORDING.setMaxId(maxId);
- if (mRecordedProgramLoadFinished) {
- validateSeriesRecordings();
- }
- mDvrLoadFinished = true;
- notifyDvrScheduleLoadFinished();
- if (isInitialized()) {
- mDbSync = new DvrDbSync(mContext, DvrDataManagerImpl.this);
- mDbSync.start();
- SeriesRecordingScheduler.getInstance(mContext).start();
- }
- }
- };
+ };
dvrQueryScheduleTask.executeOnDbThread();
mPendingTasks.add(dvrQueryScheduleTask);
RecordedProgramsQueryTask mRecordedProgramQueryTask =
@@ -341,8 +361,8 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
mRecordedProgramsForRemovedInput.clear();
notifyRecordedProgramsRemoved(RecordedProgram.toArray(oldRecordedPrograms));
} else {
- HashMap<Long, RecordedProgram> oldRecordedPrograms
- = new HashMap<>(mRecordedPrograms);
+ HashMap<Long, RecordedProgram> oldRecordedPrograms =
+ new HashMap<>(mRecordedPrograms);
mRecordedPrograms.clear();
mRecordedProgramsForRemovedInput.clear();
List<RecordedProgram> addedRecordedPrograms = new ArrayList<>();
@@ -492,7 +512,8 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
}
@VisibleForTesting
- static long getNextStartTimeAfter(List<ScheduledRecording> scheduledRecordings, long startTime) {
+ static long getNextStartTimeAfter(
+ List<ScheduledRecording> scheduledRecordings, long startTime) {
int start = 0;
int end = scheduledRecordings.size() - 1;
while (start <= end) {
@@ -503,13 +524,14 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
end = mid - 1;
}
}
- return start < scheduledRecordings.size() ? scheduledRecordings.get(start).getStartTimeMs()
+ return start < scheduledRecordings.size()
+ ? scheduledRecordings.get(start).getStartTimeMs()
: NEXT_START_TIME_NOT_FOUND;
}
@Override
- public List<ScheduledRecording> getScheduledRecordings(Range<Long> period,
- @RecordingState int state) {
+ public List<ScheduledRecording> getScheduledRecordings(
+ Range<Long> period, @RecordingState int state) {
List<ScheduledRecording> result = new ArrayList<>();
for (ScheduledRecording r : mScheduledRecordings.values()) {
if (r.isOverLapping(period) && r.getState() == state) {
@@ -595,8 +617,11 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
r.setId(IdGenerator.SERIES_RECORDING.newId());
mSeriesRecordings.put(r.getId(), r);
SeriesRecording previousSeries = mSeriesId2SeriesRecordings.put(r.getSeriesId(), r);
- SoftPreconditions.checkArgument(previousSeries == null, TAG, "Attempt to add series"
- + " recording with the duplicate series ID: " + r.getSeriesId());
+ SoftPreconditions.checkArgument(
+ previousSeries == null,
+ TAG,
+ "Attempt to add series" + " recording with the duplicate series ID: %s",
+ r.getSeriesId());
}
if (mDvrLoadFinished) {
notifySeriesRecordingAdded(seriesRecordings);
@@ -620,20 +645,23 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
mProgramId2ScheduledRecordings.remove(r.getProgramId());
if (r.getSeriesRecordingId() != SeriesRecording.ID_NOT_SET
&& (r.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED
- || r.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS)) {
+ || r.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS)) {
seriesRecordingIdsToCheck.add(r.getSeriesRecordingId());
}
boolean isScheduleForRemovedInput =
mScheduledRecordingsForRemovedInput.remove(r.getProgramId()) != null;
// If it belongs to the series recording and it's not started yet, just mark delete
// instead of deleting it.
- if (!isScheduleForRemovedInput && !forceRemove
+ if (!isScheduleForRemovedInput
+ && !forceRemove
&& r.getSeriesRecordingId() != SeriesRecording.ID_NOT_SET
&& (r.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED
- || r.getState() == ScheduledRecording.STATE_RECORDING_CANCELED)) {
+ || r.getState() == ScheduledRecording.STATE_RECORDING_CANCELED)) {
SoftPreconditions.checkState(r.getProgramId() != ScheduledRecording.ID_NOT_SET);
- ScheduledRecording deleted = ScheduledRecording.buildFrom(r)
- .setState(ScheduledRecording.STATE_RECORDING_DELETED).build();
+ ScheduledRecording deleted =
+ ScheduledRecording.buildFrom(r)
+ .setState(ScheduledRecording.STATE_RECORDING_DELETED)
+ .build();
getDeletedScheduleMap().put(deleted.getProgramId(), deleted);
schedulesNotToDelete.add(deleted);
} else {
@@ -655,12 +683,12 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
}
}
if (!schedulesToDelete.isEmpty()) {
- new AsyncDeleteScheduleTask(mContext).executeOnDbThread(
- ScheduledRecording.toArray(schedulesToDelete));
+ new AsyncDeleteScheduleTask(mContext)
+ .executeOnDbThread(ScheduledRecording.toArray(schedulesToDelete));
}
if (!schedulesNotToDelete.isEmpty()) {
- new AsyncUpdateScheduleTask(mContext).executeOnDbThread(
- ScheduledRecording.toArray(schedulesNotToDelete));
+ new AsyncUpdateScheduleTask(mContext)
+ .executeOnDbThread(ScheduledRecording.toArray(schedulesNotToDelete));
}
}
@@ -680,8 +708,10 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
if (r.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED) {
toDelete.add(r);
} else {
- toUpdate.add(ScheduledRecording.buildFrom(r)
- .setSeriesRecordingId(SeriesRecording.ID_NOT_SET).build());
+ toUpdate.add(
+ ScheduledRecording.buildFrom(r)
+ .setSeriesRecordingId(SeriesRecording.ID_NOT_SET)
+ .build());
}
}
}
@@ -709,7 +739,9 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
List<ScheduledRecording> toUpdate = new ArrayList<>();
Set<Long> seriesRecordingIdsToCheck = new HashSet<>();
for (ScheduledRecording r : schedules) {
- if (!SoftPreconditions.checkState(mScheduledRecordings.containsKey(r.getId()), TAG,
+ if (!SoftPreconditions.checkState(
+ mScheduledRecordings.containsKey(r.getId()),
+ TAG,
"Recording not found for: " + r)) {
continue;
}
@@ -720,8 +752,8 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
long programId = r.getProgramId();
if (oldScheduledRecording.getProgramId() != programId
&& oldScheduledRecording.getProgramId() != ScheduledRecording.ID_NOT_SET) {
- ScheduledRecording oldValueForProgramId = mProgramId2ScheduledRecordings
- .get(oldScheduledRecording.getProgramId());
+ ScheduledRecording oldValueForProgramId =
+ mProgramId2ScheduledRecordings.get(oldScheduledRecording.getProgramId());
if (oldValueForProgramId.getId() == r.getId()) {
// Only remove the old ScheduledRecording if it has the same ID as the new one.
mProgramId2ScheduledRecordings.remove(oldScheduledRecording.getProgramId());
@@ -755,14 +787,17 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
@Override
public void updateSeriesRecording(final SeriesRecording... seriesRecordings) {
for (SeriesRecording r : seriesRecordings) {
- if (!SoftPreconditions.checkArgument(mSeriesRecordings.containsKey(r.getId()), TAG,
- "Non Existing Series ID: " + r)) {
+ if (!SoftPreconditions.checkArgument(
+ mSeriesRecordings.containsKey(r.getId()),
+ TAG,
+ "Non Existing Series ID: %s",
+ r)) {
continue;
}
SeriesRecording old1 = mSeriesRecordings.put(r.getId(), r);
SeriesRecording old2 = mSeriesId2SeriesRecordings.put(r.getSeriesId(), r);
- SoftPreconditions.checkArgument(old1.equals(old2), TAG, "Series ID cannot be"
- + " updated: " + r);
+ SoftPreconditions.checkArgument(
+ old1.equals(old2), TAG, "Series ID cannot be updated: %s", r);
}
if (mDvrLoadFinished) {
notifySeriesRecordingChanged(seriesRecordings);
@@ -772,7 +807,8 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
private boolean isInputAvailable(String inputId) {
return mInputManager.hasTvInputInfo(inputId)
- && (!Utils.isBundledInput(inputId) || mStorageStatusManager.isStorageMounted());
+ && (!CommonUtils.isBundledInput(inputId)
+ || mStorageStatusManager.isStorageMounted());
}
private void removeDeletedSchedules(ScheduledRecording... addedSchedules) {
@@ -784,8 +820,8 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
}
}
if (!schedulesToDelete.isEmpty()) {
- new AsyncDeleteScheduleTask(mContext).executeOnDbThread(
- ScheduledRecording.toArray(schedulesToDelete));
+ new AsyncDeleteScheduleTask(mContext)
+ .executeOnDbThread(ScheduledRecording.toArray(schedulesToDelete));
}
}
@@ -805,15 +841,17 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
}
}
if (!schedulesToDelete.isEmpty()) {
- new AsyncDeleteScheduleTask(mContext).executeOnDbThread(
- ScheduledRecording.toArray(schedulesToDelete));
+ new AsyncDeleteScheduleTask(mContext)
+ .executeOnDbThread(ScheduledRecording.toArray(schedulesToDelete));
}
}
private void unhideInput(String inputId) {
if (DEBUG) Log.d(TAG, "unhideInput " + inputId);
List<ScheduledRecording> movedSchedules =
- moveElements(mScheduledRecordingsForRemovedInput, mScheduledRecordings,
+ moveElements(
+ mScheduledRecordingsForRemovedInput,
+ mScheduledRecordings,
new Filter<ScheduledRecording>() {
@Override
public boolean filter(ScheduledRecording r) {
@@ -821,7 +859,9 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
}
});
List<RecordedProgram> movedRecordedPrograms =
- moveElements(mRecordedProgramsForRemovedInput, mRecordedPrograms,
+ moveElements(
+ mRecordedProgramsForRemovedInput,
+ mRecordedPrograms,
new Filter<RecordedProgram>() {
@Override
public boolean filter(RecordedProgram r) {
@@ -830,7 +870,9 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
});
List<SeriesRecording> removedSeriesRecordings = new ArrayList<>();
List<SeriesRecording> movedSeriesRecordings =
- moveElements(mSeriesRecordingsForRemovedInput, mSeriesRecordings,
+ moveElements(
+ mSeriesRecordingsForRemovedInput,
+ mSeriesRecordings,
new Filter<SeriesRecording>() {
@Override
public boolean filter(SeriesRecording r) {
@@ -856,8 +898,8 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
for (SeriesRecording r : removedSeriesRecordings) {
mSeriesRecordingsForRemovedInput.remove(r.getId());
}
- new AsyncDeleteSeriesRecordingTask(mContext).executeOnDbThread(
- SeriesRecording.toArray(removedSeriesRecordings));
+ new AsyncDeleteSeriesRecordingTask(mContext)
+ .executeOnDbThread(SeriesRecording.toArray(removedSeriesRecordings));
// Notify after all the data are moved.
if (!movedSchedules.isEmpty()) {
notifyScheduledRecordingAdded(ScheduledRecording.toArray(movedSchedules));
@@ -873,7 +915,9 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
private void hideInput(String inputId) {
if (DEBUG) Log.d(TAG, "hideInput " + inputId);
List<ScheduledRecording> movedSchedules =
- moveElements(mScheduledRecordings, mScheduledRecordingsForRemovedInput,
+ moveElements(
+ mScheduledRecordings,
+ mScheduledRecordingsForRemovedInput,
new Filter<ScheduledRecording>() {
@Override
public boolean filter(ScheduledRecording r) {
@@ -881,7 +925,9 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
}
});
List<SeriesRecording> movedSeriesRecordings =
- moveElements(mSeriesRecordings, mSeriesRecordingsForRemovedInput,
+ moveElements(
+ mSeriesRecordings,
+ mSeriesRecordingsForRemovedInput,
new Filter<SeriesRecording>() {
@Override
public boolean filter(SeriesRecording r) {
@@ -889,7 +935,9 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
}
});
List<RecordedProgram> movedRecordedPrograms =
- moveElements(mRecordedPrograms, mRecordedProgramsForRemovedInput,
+ moveElements(
+ mRecordedPrograms,
+ mRecordedProgramsForRemovedInput,
new Filter<RecordedProgram>() {
@Override
public boolean filter(RecordedProgram r) {
@@ -931,7 +979,8 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
public void forgetStorage(String inputId) {
List<ScheduledRecording> schedulesToDelete = new ArrayList<>();
for (Iterator<ScheduledRecording> i =
- mScheduledRecordingsForRemovedInput.values().iterator(); i.hasNext(); ) {
+ mScheduledRecordingsForRemovedInput.values().iterator();
+ i.hasNext(); ) {
ScheduledRecording r = i.next();
if (inputId.equals(r.getInputId())) {
schedulesToDelete.add(r);
@@ -939,32 +988,34 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
}
}
List<SeriesRecording> seriesRecordingsToDelete = new ArrayList<>();
- for (Iterator<SeriesRecording> i =
- mSeriesRecordingsForRemovedInput.values().iterator(); i.hasNext(); ) {
+ for (Iterator<SeriesRecording> i = mSeriesRecordingsForRemovedInput.values().iterator();
+ i.hasNext(); ) {
SeriesRecording r = i.next();
if (inputId.equals(r.getInputId())) {
seriesRecordingsToDelete.add(r);
i.remove();
}
}
- for (Iterator<RecordedProgram> i =
- mRecordedProgramsForRemovedInput.values().iterator(); i.hasNext(); ) {
+ for (Iterator<RecordedProgram> i = mRecordedProgramsForRemovedInput.values().iterator();
+ i.hasNext(); ) {
if (inputId.equals(i.next().getInputId())) {
i.remove();
}
}
- new AsyncDeleteScheduleTask(mContext).executeOnDbThread(
- ScheduledRecording.toArray(schedulesToDelete));
- new AsyncDeleteSeriesRecordingTask(mContext).executeOnDbThread(
- SeriesRecording.toArray(seriesRecordingsToDelete));
- new AsyncDbTask<Void, Void, Void>() {
+ new AsyncDeleteScheduleTask(mContext)
+ .executeOnDbThread(ScheduledRecording.toArray(schedulesToDelete));
+ new AsyncDeleteSeriesRecordingTask(mContext)
+ .executeOnDbThread(SeriesRecording.toArray(seriesRecordingsToDelete));
+ new AsyncDbTask<Void, Void, Void>(mDbExecutor) {
@Override
protected Void doInBackground(Void... params) {
ContentResolver resolver = mContext.getContentResolver();
- String args[] = { inputId };
+ String[] args = {inputId};
try {
- resolver.delete(RecordedPrograms.CONTENT_URI,
- RecordedPrograms.COLUMN_INPUT_ID + " = ?", args);
+ resolver.delete(
+ RecordedPrograms.CONTENT_URI,
+ RecordedPrograms.COLUMN_INPUT_ID + " = ?",
+ args);
} catch (SQLiteException e) {
Log.e(TAG, "Failed to delete recorded programs for inputId: " + inputId, e);
}
@@ -996,7 +1047,7 @@ public class DvrDataManagerImpl extends BaseDvrDataManager {
private final Uri mUri;
public RecordedProgramsQueryTask(ContentResolver contentResolver, Uri uri) {
- super(contentResolver, uri == null ? RecordedPrograms.CONTENT_URI : uri);
+ super(mDbExecutor, contentResolver, uri == null ? RecordedPrograms.CONTENT_URI : uri);
mUri = uri;
}
diff --git a/src/com/android/tv/dvr/DvrManager.java b/src/com/android/tv/dvr/DvrManager.java
index d222003d..63a245a3 100644
--- a/src/com/android/tv/dvr/DvrManager.java
+++ b/src/com/android/tv/dvr/DvrManager.java
@@ -36,13 +36,12 @@ import android.support.annotation.VisibleForTesting;
import android.support.annotation.WorkerThread;
import android.util.Log;
import android.util.Range;
-
-import com.android.tv.ApplicationSingletons;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
import com.android.tv.common.feature.CommonFeatures;
-import com.android.tv.data.Channel;
+import com.android.tv.common.util.CommonUtils;
import com.android.tv.data.Program;
+import com.android.tv.data.api.Channel;
import com.android.tv.dvr.DvrDataManager.OnRecordedProgramLoadFinishedListener;
import com.android.tv.dvr.DvrDataManager.RecordedProgramListener;
import com.android.tv.dvr.DvrScheduleManager.OnInitializeListener;
@@ -51,7 +50,6 @@ import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.util.AsyncDbTask;
import com.android.tv.util.Utils;
-
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
@@ -60,6 +58,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.concurrent.Executor;
/**
* DVR manager class to add and remove recordings. UI can modify recording list through this class,
@@ -76,13 +75,15 @@ public class DvrManager {
// @GuardedBy("mListener")
private final Map<Listener, Handler> mListener = new HashMap<>();
private final Context mAppContext;
+ private final Executor mDbExecutor;
public DvrManager(Context context) {
SoftPreconditions.checkFeatureEnabled(context, CommonFeatures.DVR, TAG);
mAppContext = context.getApplicationContext();
- ApplicationSingletons appSingletons = TvApplication.getSingletons(context);
- mDataManager = (WritableDvrDataManager) appSingletons.getDvrDataManager();
- mScheduleManager = appSingletons.getDvrScheduleManager();
+ TvSingletons tvSingletons = TvSingletons.getSingletons(context);
+ mDbExecutor = tvSingletons.getDbExecutor();
+ mDataManager = (WritableDvrDataManager) tvSingletons.getDvrDataManager();
+ mScheduleManager = tvSingletons.getDvrScheduleManager();
if (mDataManager.isInitialized() && mScheduleManager.isInitialized()) {
createSeriesRecordingsForRecordedProgramsIfNeeded(mDataManager.getRecordedPrograms());
} else {
@@ -103,37 +104,41 @@ public class DvrManager {
});
}
if (!mScheduleManager.isInitialized()) {
- mScheduleManager.addOnInitializeListener(new OnInitializeListener() {
+ mScheduleManager.addOnInitializeListener(
+ new OnInitializeListener() {
+ @Override
+ public void onInitialize() {
+ mScheduleManager.removeOnInitializeListener(this);
+ if (mDataManager.isInitialized()
+ && mScheduleManager.isInitialized()) {
+ createSeriesRecordingsForRecordedProgramsIfNeeded(
+ mDataManager.getRecordedPrograms());
+ }
+ }
+ });
+ }
+ }
+ mDataManager.addRecordedProgramListener(
+ new RecordedProgramListener() {
@Override
- public void onInitialize() {
- mScheduleManager.removeOnInitializeListener(this);
- if (mDataManager.isInitialized() && mScheduleManager.isInitialized()) {
- createSeriesRecordingsForRecordedProgramsIfNeeded(
- mDataManager.getRecordedPrograms());
+ public void onRecordedProgramsAdded(RecordedProgram... recordedPrograms) {
+ if (!mDataManager.isInitialized() || !mScheduleManager.isInitialized()) {
+ return;
+ }
+ for (RecordedProgram recordedProgram : recordedPrograms) {
+ createSeriesRecordingForRecordedProgramIfNeeded(recordedProgram);
}
}
- });
- }
- }
- mDataManager.addRecordedProgramListener(new RecordedProgramListener() {
- @Override
- public void onRecordedProgramsAdded(RecordedProgram... recordedPrograms) {
- if (!mDataManager.isInitialized() || !mScheduleManager.isInitialized()) {
- return;
- }
- for (RecordedProgram recordedProgram : recordedPrograms) {
- createSeriesRecordingForRecordedProgramIfNeeded(recordedProgram);
- }
- }
- @Override
- public void onRecordedProgramsChanged(RecordedProgram... recordedPrograms) { }
+ @Override
+ public void onRecordedProgramsChanged(RecordedProgram... recordedPrograms) {}
- @Override
- public void onRecordedProgramsRemoved(RecordedProgram... recordedPrograms) {
- // Removing series recording is handled in the SeriesRecordingDetailsFragment.
- }
- });
+ @Override
+ public void onRecordedProgramsRemoved(RecordedProgram... recordedPrograms) {
+ // Removing series recording is handled in the
+ // SeriesRecordingDetailsFragment.
+ }
+ });
}
private void createSeriesRecordingsForRecordedProgramsIfNeeded(
@@ -153,33 +158,38 @@ public class DvrManager {
}
}
- /**
- * Schedules a recording for {@code program}.
- */
+ /** Schedules a recording for {@code program}. */
public ScheduledRecording addSchedule(Program program) {
if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) {
return null;
}
SeriesRecording seriesRecording = getSeriesRecording(program);
- return addSchedule(program, seriesRecording == null
- ? mScheduleManager.suggestNewPriority()
- : seriesRecording.getPriority());
+ return addSchedule(
+ program,
+ seriesRecording == null
+ ? mScheduleManager.suggestNewPriority()
+ : seriesRecording.getPriority());
}
/**
- * Schedules a recording for {@code program} with the highest priority so that the schedule
- * can be recorded.
+ * Schedules a recording for {@code program} with the highest priority so that the schedule can
+ * be recorded.
*/
public ScheduledRecording addScheduleWithHighestPriority(Program program) {
if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) {
return null;
}
SeriesRecording seriesRecording = getSeriesRecording(program);
- return addSchedule(program, seriesRecording == null
- ? mScheduleManager.suggestNewPriority()
- : mScheduleManager.suggestHighestPriority(seriesRecording.getInputId(),
- new Range(program.getStartTimeUtcMillis(), program.getEndTimeUtcMillis()),
- seriesRecording.getPriority()));
+ return addSchedule(
+ program,
+ seriesRecording == null
+ ? mScheduleManager.suggestNewPriority()
+ : mScheduleManager.suggestHighestPriority(
+ seriesRecording.getInputId(),
+ new Range(
+ program.getStartTimeUtcMillis(),
+ program.getEndTimeUtcMillis()),
+ seriesRecording.getPriority()));
}
private ScheduledRecording addSchedule(Program program, long priority) {
@@ -190,21 +200,28 @@ public class DvrManager {
}
ScheduledRecording schedule;
SeriesRecording seriesRecording = getSeriesRecording(program);
- schedule = createScheduledRecordingBuilder(input.getId(), program)
- .setPriority(priority)
- .setSeriesRecordingId(seriesRecording == null ? SeriesRecording.ID_NOT_SET
- : seriesRecording.getId())
- .build();
+ schedule =
+ createScheduledRecordingBuilder(input.getId(), program)
+ .setPriority(priority)
+ .setSeriesRecordingId(
+ seriesRecording == null
+ ? SeriesRecording.ID_NOT_SET
+ : seriesRecording.getId())
+ .build();
mDataManager.addScheduledRecording(schedule);
return schedule;
}
- /**
- * Adds a recording schedule with a time range.
- */
+ /** Adds a recording schedule with a time range. */
public void addSchedule(Channel channel, long startTime, long endTime) {
- Log.i(TAG, "Adding scheduled recording of channel " + channel + " starting at " +
- Utils.toTimeString(startTime) + " and ending at " + Utils.toTimeString(endTime));
+ Log.i(
+ TAG,
+ "Adding scheduled recording of channel "
+ + channel
+ + " starting at "
+ + Utils.toTimeString(startTime)
+ + " and ending at "
+ + Utils.toTimeString(endTime));
if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) {
return;
}
@@ -216,9 +233,7 @@ public class DvrManager {
addScheduleInternal(input.getId(), channel.getId(), startTime, endTime);
}
- /**
- * Adds the schedule.
- */
+ /** Adds the schedule. */
public void addSchedule(ScheduledRecording schedule) {
if (mDataManager.isDvrScheduleLoadFinished()) {
mDataManager.addScheduledRecording(schedule);
@@ -226,19 +241,23 @@ public class DvrManager {
}
private void addScheduleInternal(String inputId, long channelId, long startTime, long endTime) {
- mDataManager.addScheduledRecording(ScheduledRecording
- .builder(inputId, channelId, startTime, endTime)
- .setPriority(mScheduleManager.suggestNewPriority())
- .build());
+ mDataManager.addScheduledRecording(
+ ScheduledRecording.builder(inputId, channelId, startTime, endTime)
+ .setPriority(mScheduleManager.suggestNewPriority())
+ .build());
}
- /**
- * Adds a new series recording and schedules for the programs with the initial state.
- */
- public SeriesRecording addSeriesRecording(Program selectedProgram,
- List<Program> programsToSchedule, @SeriesRecording.SeriesState int initialState) {
- Log.i(TAG, "Adding series recording for program " + selectedProgram + ", and schedules: "
- + programsToSchedule);
+ /** Adds a new series recording and schedules for the programs with the initial state. */
+ public SeriesRecording addSeriesRecording(
+ Program selectedProgram,
+ List<Program> programsToSchedule,
+ @SeriesRecording.SeriesState int initialState) {
+ Log.i(
+ TAG,
+ "Adding series recording for program "
+ + selectedProgram
+ + ", and schedules: "
+ + programsToSchedule);
if (!SoftPreconditions.checkState(mDataManager.isInitialized())) {
return null;
}
@@ -247,10 +266,11 @@ public class DvrManager {
Log.e(TAG, "Can't find input for program: " + selectedProgram);
return null;
}
- SeriesRecording seriesRecording = SeriesRecording.builder(input.getId(), selectedProgram)
- .setPriority(mScheduleManager.suggestNewSeriesPriority())
- .setState(initialState)
- .build();
+ SeriesRecording seriesRecording =
+ SeriesRecording.builder(input.getId(), selectedProgram)
+ .setPriority(mScheduleManager.suggestNewSeriesPriority())
+ .setState(initialState)
+ .build();
mDataManager.addSeriesRecording(seriesRecording);
// The schedules for the recorded programs should be added not to create the schedule the
// duplicate episodes.
@@ -279,9 +299,11 @@ public class DvrManager {
// Duplicate schedules can exist, but they will be deleted in a few days. And it's
// also guaranteed that the schedules don't belong to any series recordings because
// there are no more than one series recordings which have the same program title.
- toAdd.add(ScheduledRecording.builder(recordedProgram)
- .setPriority(series.getPriority())
- .setSeriesRecordingId(series.getId()).build());
+ toAdd.add(
+ ScheduledRecording.builder(recordedProgram)
+ .setPriority(series.getPriority())
+ .setSeriesRecordingId(series.getId())
+ .build());
}
}
if (!toAdd.isEmpty()) {
@@ -291,11 +313,11 @@ public class DvrManager {
/**
* Adds {@link ScheduledRecording}s for the series recording.
- * <p>
- * This method doesn't add the series recording.
+ *
+ * <p>This method doesn't add the series recording.
*/
- public void addScheduleToSeriesRecording(SeriesRecording series,
- List<Program> programsToSchedule) {
+ public void addScheduleToSeriesRecording(
+ SeriesRecording series, List<Program> programsToSchedule) {
if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) {
return;
}
@@ -311,18 +333,20 @@ public class DvrManager {
mDataManager.getScheduledRecordingForProgramId(program.getId());
if (scheduleWithSameProgram != null) {
if (scheduleWithSameProgram.isNotStarted()) {
- ScheduledRecording r = ScheduledRecording.buildFrom(scheduleWithSameProgram)
- .setSeriesRecordingId(series.getId())
- .build();
+ ScheduledRecording r =
+ ScheduledRecording.buildFrom(scheduleWithSameProgram)
+ .setSeriesRecordingId(series.getId())
+ .build();
if (!r.equals(scheduleWithSameProgram)) {
toUpdate.add(r);
}
}
} else {
- toAdd.add(createScheduledRecordingBuilder(input.getId(), program)
- .setPriority(series.getPriority())
- .setSeriesRecordingId(series.getId())
- .build());
+ toAdd.add(
+ createScheduledRecordingBuilder(input.getId(), program)
+ .setPriority(series.getPriority())
+ .setSeriesRecordingId(series.getId())
+ .build());
}
}
if (!toAdd.isEmpty()) {
@@ -333,9 +357,7 @@ public class DvrManager {
}
}
- /**
- * Updates the series recording.
- */
+ /** Updates the series recording. */
public void updateSeriesRecording(SeriesRecording series) {
if (SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) {
SeriesRecording previousSeries = mDataManager.getSeriesRecording(series.getId());
@@ -344,7 +366,7 @@ public class DvrManager {
// schedules will be added by SeriesRecordingScheduler or by SeriesSettingsFragment.
if (previousSeries.getChannelOption() != series.getChannelOption()
|| (previousSeries.getChannelOption() == SeriesRecording.OPTION_CHANNEL_ONE
- && previousSeries.getChannelId() != series.getChannelId())) {
+ && previousSeries.getChannelId() != series.getChannelId())) {
List<ScheduledRecording> schedules =
mDataManager.getScheduledRecordings(series.getId());
List<ScheduledRecording> schedulesToRemove = new ArrayList<>();
@@ -365,20 +387,21 @@ public class DvrManager {
schedulesToRemove.add(deletedSchedule);
}
}
- mDataManager.removeScheduledRecording(true,
- ScheduledRecording.toArray(schedulesToRemove));
+ mDataManager.removeScheduledRecording(
+ true, ScheduledRecording.toArray(schedulesToRemove));
}
}
mDataManager.updateSeriesRecording(series);
- if (previousSeries == null
- || previousSeries.getPriority() != series.getPriority()) {
+ if (previousSeries == null || previousSeries.getPriority() != series.getPriority()) {
long priority = series.getPriority();
List<ScheduledRecording> schedulesToUpdate = new ArrayList<>();
- for (ScheduledRecording schedule
- : mDataManager.getScheduledRecordings(series.getId())) {
+ for (ScheduledRecording schedule :
+ mDataManager.getScheduledRecordings(series.getId())) {
if (schedule.isNotStarted() || schedule.isInProgress()) {
- schedulesToUpdate.add(ScheduledRecording.buildFrom(schedule)
- .setPriority(priority).build());
+ schedulesToUpdate.add(
+ ScheduledRecording.buildFrom(schedule)
+ .setPriority(priority)
+ .build());
}
}
if (!schedulesToUpdate.isEmpty()) {
@@ -411,28 +434,26 @@ public class DvrManager {
mDataManager.removeSeriesRecording(series);
}
- /**
- * Stops the currently recorded program
- */
+ /** Stops the currently recorded program */
public void stopRecording(final ScheduledRecording recording) {
if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) {
return;
}
synchronized (mListener) {
for (final Entry<Listener, Handler> entry : mListener.entrySet()) {
- entry.getValue().post(new Runnable() {
- @Override
- public void run() {
- entry.getKey().onStopRecordingRequested(recording);
- }
- });
+ entry.getValue()
+ .post(
+ new Runnable() {
+ @Override
+ public void run() {
+ entry.getKey().onStopRecordingRequested(recording);
+ }
+ });
}
}
}
- /**
- * Removes scheduled recordings or an existing recordings.
- */
+ /** Removes scheduled recordings or an existing recordings. */
public void removeScheduledRecording(ScheduledRecording... schedules) {
Log.i(TAG, "Removing " + Arrays.asList(schedules));
if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) {
@@ -447,9 +468,7 @@ public class DvrManager {
}
}
- /**
- * Removes scheduled recordings without changing to the DELETED state.
- */
+ /** Removes scheduled recordings without changing to the DELETED state. */
public void forceRemoveScheduledRecording(ScheduledRecording... schedules) {
Log.i(TAG, "Force removing " + Arrays.asList(schedules));
if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) {
@@ -464,9 +483,7 @@ public class DvrManager {
}
}
- /**
- * Removes the recorded program. It deletes the file if possible.
- */
+ /** Removes the recorded program. It deletes the file if possible. */
public void removeRecordedProgram(Uri recordedProgramUri) {
if (!SoftPreconditions.checkState(mDataManager.isInitialized())) {
return;
@@ -474,9 +491,7 @@ public class DvrManager {
removeRecordedProgram(ContentUris.parseId(recordedProgramUri));
}
- /**
- * Removes the recorded program. It deletes the file if possible.
- */
+ /** Removes the recorded program. It deletes the file if possible. */
public void removeRecordedProgram(long recordedProgramId) {
if (!SoftPreconditions.checkState(mDataManager.isInitialized())) {
return;
@@ -487,14 +502,12 @@ public class DvrManager {
}
}
- /**
- * Removes the recorded program. It deletes the file if possible.
- */
+ /** Removes the recorded program. It deletes the file if possible. */
public void removeRecordedProgram(final RecordedProgram recordedProgram) {
if (!SoftPreconditions.checkState(mDataManager.isInitialized())) {
return;
}
- new AsyncDbTask<Void, Void, Integer>() {
+ new AsyncDbTask<Void, Void, Integer>(mDbExecutor) {
@Override
protected Integer doInBackground(Void... params) {
ContentResolver resolver = mAppContext.getContentResolver();
@@ -526,7 +539,7 @@ public class DvrManager {
dbOperations.add(ContentProviderOperation.newDelete(r.getUri()).build());
}
}
- new AsyncDbTask<Void, Void, Boolean>() {
+ new AsyncDbTask<Void, Void, Boolean>(mDbExecutor) {
@Override
protected Boolean doInBackground(Void... params) {
ContentResolver resolver = mAppContext.getContentResolver();
@@ -556,9 +569,7 @@ public class DvrManager {
}.executeOnDbThread();
}
- /**
- * Updates the scheduled recording.
- */
+ /** Updates the scheduled recording. */
public void updateScheduledRecording(ScheduledRecording recording) {
if (SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) {
mDataManager.updateScheduledRecording(recording);
@@ -566,8 +577,8 @@ public class DvrManager {
}
/**
- * Returns priority ordered list of all scheduled recordings that will not be recorded if
- * this program is.
+ * Returns priority ordered list of all scheduled recordings that will not be recorded if this
+ * program is.
*
* @see DvrScheduleManager#getConflictingSchedules(Program)
*/
@@ -579,13 +590,13 @@ public class DvrManager {
}
/**
- * Returns priority ordered list of all scheduled recordings that will not be recorded if
- * this channel is.
+ * Returns priority ordered list of all scheduled recordings that will not be recorded if this
+ * channel is.
*
* @see DvrScheduleManager#getConflictingSchedules(long, long, long)
*/
- public List<ScheduledRecording> getConflictingSchedules(long channelId, long startTimeMs,
- long endTimeMs) {
+ public List<ScheduledRecording> getConflictingSchedules(
+ long channelId, long startTimeMs, long endTimeMs) {
if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) {
return Collections.emptyList();
}
@@ -595,8 +606,8 @@ public class DvrManager {
/**
* Checks if the schedule is conflicting.
*
- * <p>Note that the {@code schedule} should be the existing one. If not, this returns
- * {@code false}.
+ * <p>Note that the {@code schedule} should be the existing one. If not, this returns {@code
+ * false}.
*/
public boolean isConflicting(ScheduledRecording schedule) {
return schedule != null
@@ -605,8 +616,8 @@ public class DvrManager {
}
/**
- * Returns priority ordered list of all scheduled recording that will not be recorded if
- * this channel is tuned to.
+ * Returns priority ordered list of all scheduled recording that will not be recorded if this
+ * channel is tuned to.
*
* @see DvrScheduleManager#getConflictingSchedulesForTune
*/
@@ -617,22 +628,18 @@ public class DvrManager {
return mScheduleManager.getConflictingSchedulesForTune(channelId);
}
- /**
- * Sets the highest priority to the schedule.
- */
+ /** Sets the highest priority to the schedule. */
public void setHighestPriority(ScheduledRecording schedule) {
if (SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) {
long newPriority = mScheduleManager.suggestHighestPriority(schedule);
if (newPriority != schedule.getPriority()) {
- mDataManager.updateScheduledRecording(ScheduledRecording.buildFrom(schedule)
- .setPriority(newPriority).build());
+ mDataManager.updateScheduledRecording(
+ ScheduledRecording.buildFrom(schedule).setPriority(newPriority).build());
}
}
}
- /**
- * Suggests the higher priority than the schedules which overlap with {@code schedule}.
- */
+ /** Suggests the higher priority than the schedules which overlap with {@code schedule}. */
public long suggestHighestPriority(ScheduledRecording schedule) {
if (SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) {
return mScheduleManager.suggestHighestPriority(schedule);
@@ -642,9 +649,9 @@ public class DvrManager {
/**
* Returns {@code true} if the channel can be recorded.
- * <p>
- * Note that this method doesn't check the conflict of the schedule or available tuners.
- * This can be called from the UI before the schedules are loaded.
+ *
+ * <p>Note that this method doesn't check the conflict of the schedule or available tuners. This
+ * can be called from the UI before the schedules are loaded.
*/
public boolean isChannelRecordable(Channel channel) {
if (!mDataManager.isDvrScheduleLoadFinished() || channel == null) {
@@ -661,23 +668,27 @@ public class DvrManager {
if (!info.canRecord()) {
return false;
}
- Program program = TvApplication.getSingletons(mAppContext).getProgramDataManager()
- .getCurrentProgram(channel.getId());
+ Program program =
+ TvSingletons.getSingletons(mAppContext)
+ .getProgramDataManager()
+ .getCurrentProgram(channel.getId());
return program == null || !program.isRecordingProhibited();
}
/**
* Returns {@code true} if the program can be recorded.
- * <p>
- * Note that this method doesn't check the conflict of the schedule or available tuners.
- * This can be called from the UI before the schedules are loaded.
+ *
+ * <p>Note that this method doesn't check the conflict of the schedule or available tuners. This
+ * can be called from the UI before the schedules are loaded.
*/
public boolean isProgramRecordable(Program program) {
if (!mDataManager.isInitialized()) {
return false;
}
- Channel channel = TvApplication.getSingletons(mAppContext).getChannelDataManager()
- .getChannel(program.getChannelId());
+ Channel channel =
+ TvSingletons.getSingletons(mAppContext)
+ .getChannelDataManager()
+ .getChannel(program.getChannelId());
if (channel == null || channel.isRecordingProhibited()) {
return false;
}
@@ -691,8 +702,8 @@ public class DvrManager {
/**
* Returns the current recording for the channel.
- * <p>
- * This can be called from the UI before the schedules are loaded.
+ *
+ * <p>This can be called from the UI before the schedules are loaded.
*/
public ScheduledRecording getCurrentRecording(long channelId) {
if (!mDataManager.isDvrScheduleLoadFinished()) {
@@ -707,8 +718,8 @@ public class DvrManager {
}
/**
- * Returns schedules which is available (i.e., isNotStarted or isInProgress) and belongs to
- * the series recording {@code seriesRecordingId}.
+ * Returns schedules which is available (i.e., isNotStarted or isInProgress) and belongs to the
+ * series recording {@code seriesRecordingId}.
*/
public List<ScheduledRecording> getAvailableScheduledRecording(long seriesRecordingId) {
if (!mDataManager.isDvrScheduleLoadFinished()) {
@@ -723,9 +734,7 @@ public class DvrManager {
return schedules;
}
- /**
- * Returns the series recording related to the program.
- */
+ /** Returns the series recording related to the program. */
@Nullable
public SeriesRecording getSeriesRecording(Program program) {
if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) {
@@ -735,8 +744,8 @@ public class DvrManager {
}
/**
- * Returns if there are valid items. Valid item contains {@link RecordedProgram},
- * available {@link ScheduledRecording} and {@link SeriesRecording}.
+ * Returns if there are valid items. Valid item contains {@link RecordedProgram}, available
+ * {@link ScheduledRecording} and {@link SeriesRecording}.
*/
public boolean hasValidItems() {
return !(mDataManager.getRecordedPrograms().isEmpty()
@@ -768,8 +777,8 @@ public class DvrManager {
* Returns ScheduledRecording.builder based on {@code program}. If program is already started,
* recording started time is clipped to the current time.
*/
- private ScheduledRecording.Builder createScheduledRecordingBuilder(String inputId,
- Program program) {
+ private ScheduledRecording.Builder createScheduledRecordingBuilder(
+ String inputId, Program program) {
ScheduledRecording.Builder builder = ScheduledRecording.builder(inputId, program);
long time = System.currentTimeMillis();
if (program.getStartTimeUtcMillis() < time && time < program.getEndTimeUtcMillis()) {
@@ -778,13 +787,13 @@ public class DvrManager {
return builder;
}
- /**
- * Returns a schedule which matches to the given episode.
- */
- public ScheduledRecording getScheduledRecording(String title, String seasonNumber,
- String episodeNumber) {
- if (!SoftPreconditions.checkState(mDataManager.isInitialized()) || title == null
- || seasonNumber == null || episodeNumber == null) {
+ /** Returns a schedule which matches to the given episode. */
+ public ScheduledRecording getScheduledRecording(
+ String title, String seasonNumber, String episodeNumber) {
+ if (!SoftPreconditions.checkState(mDataManager.isInitialized())
+ || title == null
+ || seasonNumber == null
+ || episodeNumber == null) {
return null;
}
for (ScheduledRecording r : mDataManager.getAllScheduledRecordings()) {
@@ -797,13 +806,13 @@ public class DvrManager {
return null;
}
- /**
- * Returns a recorded program which is the same episode as the given {@code program}.
- */
- public RecordedProgram getRecordedProgram(String title, String seasonNumber,
- String episodeNumber) {
- if (!SoftPreconditions.checkState(mDataManager.isInitialized()) || title == null
- || seasonNumber == null || episodeNumber == null) {
+ /** Returns a recorded program which is the same episode as the given {@code program}. */
+ public RecordedProgram getRecordedProgram(
+ String title, String seasonNumber, String episodeNumber) {
+ if (!SoftPreconditions.checkState(mDataManager.isInitialized())
+ || title == null
+ || seasonNumber == null
+ || episodeNumber == null) {
return null;
}
for (RecordedProgram r : mDataManager.getRecordedPrograms()) {
@@ -820,13 +829,14 @@ public class DvrManager {
@WorkerThread
private void removeRecordedData(Uri dataUri) {
try {
- if (dataUri != null && ContentResolver.SCHEME_FILE.equals(dataUri.getScheme())
+ if (dataUri != null
+ && ContentResolver.SCHEME_FILE.equals(dataUri.getScheme())
&& dataUri.getPath() != null) {
File recordedProgramPath = new File(dataUri.getPath());
if (!recordedProgramPath.exists()) {
if (DEBUG) Log.d(TAG, "File to delete not exist: " + recordedProgramPath);
} else {
- Utils.deleteDirOrFile(recordedProgramPath);
+ CommonUtils.deleteDirOrFile(recordedProgramPath);
if (DEBUG) {
Log.d(TAG, "Sucessfully deleted files of the recorded program: " + dataUri);
}
@@ -834,16 +844,19 @@ public class DvrManager {
}
} catch (SecurityException e) {
if (DEBUG) {
- Log.d(TAG, "To delete this recorded program, please manually delete video data at"
- + "\nadb shell rm -rf " + dataUri);
+ Log.d(
+ TAG,
+ "To delete this recorded program, please manually delete video data at"
+ + "\nadb shell rm -rf "
+ + dataUri);
}
}
}
/**
* Remove all the records related to the input.
- * <p>
- * Note that this should be called after the input was removed.
+ *
+ * <p>Note that this should be called after the input was removed.
*/
public void forgetStorage(String inputId) {
if (mDataManager.isInitialized()) {
diff --git a/src/com/android/tv/dvr/DvrScheduleManager.java b/src/com/android/tv/dvr/DvrScheduleManager.java
index b72117aa..d5126b12 100644
--- a/src/com/android/tv/dvr/DvrScheduleManager.java
+++ b/src/com/android/tv/dvr/DvrScheduleManager.java
@@ -25,21 +25,18 @@ import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
import android.util.ArraySet;
import android.util.Range;
-
-import com.android.tv.ApplicationSingletons;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
-import com.android.tv.data.Channel;
import com.android.tv.data.ChannelDataManager;
import com.android.tv.data.Program;
+import com.android.tv.data.api.Channel;
import com.android.tv.dvr.DvrDataManager.OnDvrScheduleLoadFinishedListener;
import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
-import com.android.tv.dvr.recorder.InputTaskScheduler;
-import com.android.tv.util.CompositeComparator;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.SeriesRecording;
+import com.android.tv.dvr.recorder.InputTaskScheduler;
+import com.android.tv.util.CompositeComparator;
import com.android.tv.util.Utils;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -50,21 +47,16 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
-/**
- * A class to manage the schedules.
- */
+/** A class to manage the schedules. */
@TargetApi(Build.VERSION_CODES.N)
@MainThread
+@SuppressWarnings("AndroidApiChecker") // TODO(b/32513850) remove when error prone is updated
public class DvrScheduleManager {
private static final String TAG = "DvrScheduleManager";
- /**
- * The default priority of scheduled recording.
- */
+ /** The default priority of scheduled recording. */
public static final long DEFAULT_PRIORITY = Long.MAX_VALUE >> 1;
- /**
- * The default priority of series recording.
- */
+ /** The default priority of series recording. */
public static final long DEFAULT_SERIES_PRIORITY = DEFAULT_PRIORITY >> 1;
// The new priority will have the offset from the existing one.
private static final long PRIORITY_OFFSET = 1024;
@@ -102,9 +94,9 @@ public class DvrScheduleManager {
public DvrScheduleManager(Context context) {
mContext = context;
- ApplicationSingletons appSingletons = TvApplication.getSingletons(context);
- mDataManager = (DvrDataManagerImpl) appSingletons.getDvrDataManager();
- mChannelDataManager = appSingletons.getChannelDataManager();
+ TvSingletons tvSingletons = TvSingletons.getSingletons(context);
+ mDataManager = (DvrDataManagerImpl) tvSingletons.getDvrDataManager();
+ mChannelDataManager = tvSingletons.getChannelDataManager();
if (mDataManager.isDvrScheduleLoadFinished() && mChannelDataManager.isDbLoadFinished()) {
buildData();
} else {
@@ -119,146 +111,151 @@ public class DvrScheduleManager {
}
});
}
- ScheduledRecordingListener scheduledRecordingListener = new ScheduledRecordingListener() {
- @Override
- public void onScheduledRecordingAdded(ScheduledRecording... scheduledRecordings) {
- if (!mInitialized) {
- return;
- }
- for (ScheduledRecording schedule : scheduledRecordings) {
- if (!schedule.isNotStarted() && !schedule.isInProgress()) {
- continue;
- }
- TvInputInfo input = Utils
- .getTvInputInfoForInputId(mContext, schedule.getInputId());
- if (!SoftPreconditions.checkArgument(input != null, TAG,
- "Input was removed for : " + schedule)) {
- // Input removed.
- mInputScheduleMap.remove(schedule.getInputId());
- mInputConflictInfoMap.remove(schedule.getInputId());
- continue;
- }
- String inputId = input.getId();
- List<ScheduledRecording> schedules = mInputScheduleMap.get(inputId);
- if (schedules == null) {
- schedules = new ArrayList<>();
- mInputScheduleMap.put(inputId, schedules);
+ ScheduledRecordingListener scheduledRecordingListener =
+ new ScheduledRecordingListener() {
+ @Override
+ public void onScheduledRecordingAdded(
+ ScheduledRecording... scheduledRecordings) {
+ if (!mInitialized) {
+ return;
+ }
+ for (ScheduledRecording schedule : scheduledRecordings) {
+ if (!schedule.isNotStarted() && !schedule.isInProgress()) {
+ continue;
+ }
+ TvInputInfo input =
+ Utils.getTvInputInfoForInputId(mContext, schedule.getInputId());
+ if (!SoftPreconditions.checkArgument(
+ input != null, TAG, "Input was removed for : %s", schedule)) {
+ // Input removed.
+ mInputScheduleMap.remove(schedule.getInputId());
+ mInputConflictInfoMap.remove(schedule.getInputId());
+ continue;
+ }
+ String inputId = input.getId();
+ List<ScheduledRecording> schedules = mInputScheduleMap.get(inputId);
+ if (schedules == null) {
+ schedules = new ArrayList<>();
+ mInputScheduleMap.put(inputId, schedules);
+ }
+ schedules.add(schedule);
+ }
+ onSchedulesChanged();
+ notifyScheduledRecordingAdded(scheduledRecordings);
}
- schedules.add(schedule);
- }
- onSchedulesChanged();
- notifyScheduledRecordingAdded(scheduledRecordings);
- }
- @Override
- public void onScheduledRecordingRemoved(ScheduledRecording... scheduledRecordings) {
- if (!mInitialized) {
- return;
- }
- for (ScheduledRecording schedule : scheduledRecordings) {
- TvInputInfo input = Utils
- .getTvInputInfoForInputId(mContext, schedule.getInputId());
- if (input == null) {
- // Input removed.
- mInputScheduleMap.remove(schedule.getInputId());
- mInputConflictInfoMap.remove(schedule.getInputId());
- continue;
- }
- String inputId = input.getId();
- List<ScheduledRecording> schedules = mInputScheduleMap.get(inputId);
- if (schedules != null) {
- schedules.remove(schedule);
- if (schedules.isEmpty()) {
- mInputScheduleMap.remove(inputId);
+ @Override
+ public void onScheduledRecordingRemoved(
+ ScheduledRecording... scheduledRecordings) {
+ if (!mInitialized) {
+ return;
}
- }
- Map<Long, ConflictInfo> conflictInfo = mInputConflictInfoMap.get(inputId);
- if (conflictInfo != null) {
- conflictInfo.remove(schedule.getId());
- if (conflictInfo.isEmpty()) {
- mInputConflictInfoMap.remove(inputId);
+ for (ScheduledRecording schedule : scheduledRecordings) {
+ TvInputInfo input =
+ Utils.getTvInputInfoForInputId(mContext, schedule.getInputId());
+ if (input == null) {
+ // Input removed.
+ mInputScheduleMap.remove(schedule.getInputId());
+ mInputConflictInfoMap.remove(schedule.getInputId());
+ continue;
+ }
+ String inputId = input.getId();
+ List<ScheduledRecording> schedules = mInputScheduleMap.get(inputId);
+ if (schedules != null) {
+ schedules.remove(schedule);
+ if (schedules.isEmpty()) {
+ mInputScheduleMap.remove(inputId);
+ }
+ }
+ Map<Long, ConflictInfo> conflictInfo =
+ mInputConflictInfoMap.get(inputId);
+ if (conflictInfo != null) {
+ conflictInfo.remove(schedule.getId());
+ if (conflictInfo.isEmpty()) {
+ mInputConflictInfoMap.remove(inputId);
+ }
+ }
}
+ onSchedulesChanged();
+ notifyScheduledRecordingRemoved(scheduledRecordings);
}
- }
- onSchedulesChanged();
- notifyScheduledRecordingRemoved(scheduledRecordings);
- }
- @Override
- public void onScheduledRecordingStatusChanged(
- ScheduledRecording... scheduledRecordings) {
- if (!mInitialized) {
- return;
- }
- for (ScheduledRecording schedule : scheduledRecordings) {
- TvInputInfo input = Utils
- .getTvInputInfoForInputId(mContext, schedule.getInputId());
- if (!SoftPreconditions.checkArgument(input != null, TAG,
- "Input was removed for : " + schedule)) {
- // Input removed.
- mInputScheduleMap.remove(schedule.getInputId());
- mInputConflictInfoMap.remove(schedule.getInputId());
- continue;
- }
- String inputId = input.getId();
- List<ScheduledRecording> schedules = mInputScheduleMap.get(inputId);
- if (schedules == null) {
- schedules = new ArrayList<>();
- mInputScheduleMap.put(inputId, schedules);
- }
- // Compare ID because ScheduledRecording.equals() doesn't work if the state
- // is changed.
- for (Iterator<ScheduledRecording> i = schedules.iterator(); i.hasNext(); ) {
- if (i.next().getId() == schedule.getId()) {
- i.remove();
- break;
+ @Override
+ public void onScheduledRecordingStatusChanged(
+ ScheduledRecording... scheduledRecordings) {
+ if (!mInitialized) {
+ return;
}
- }
- if (schedule.isNotStarted() || schedule.isInProgress()) {
- schedules.add(schedule);
- }
- if (schedules.isEmpty()) {
- mInputScheduleMap.remove(inputId);
- }
- // Update conflict list as well
- Map<Long, ConflictInfo> conflictInfo = mInputConflictInfoMap.get(inputId);
- if (conflictInfo != null) {
- ConflictInfo oldConflictInfo = conflictInfo.get(schedule.getId());
- if (oldConflictInfo != null) {
- oldConflictInfo.schedule = schedule;
+ for (ScheduledRecording schedule : scheduledRecordings) {
+ TvInputInfo input =
+ Utils.getTvInputInfoForInputId(mContext, schedule.getInputId());
+ if (!SoftPreconditions.checkArgument(
+ input != null, TAG, "Input was removed for : %s", schedule)) {
+ // Input removed.
+ mInputScheduleMap.remove(schedule.getInputId());
+ mInputConflictInfoMap.remove(schedule.getInputId());
+ continue;
+ }
+ String inputId = input.getId();
+ List<ScheduledRecording> schedules = mInputScheduleMap.get(inputId);
+ if (schedules == null) {
+ schedules = new ArrayList<>();
+ mInputScheduleMap.put(inputId, schedules);
+ }
+ // Compare ID because ScheduledRecording.equals() doesn't work if the
+ // state
+ // is changed.
+ for (Iterator<ScheduledRecording> i = schedules.iterator();
+ i.hasNext(); ) {
+ if (i.next().getId() == schedule.getId()) {
+ i.remove();
+ break;
+ }
+ }
+ if (schedule.isNotStarted() || schedule.isInProgress()) {
+ schedules.add(schedule);
+ }
+ if (schedules.isEmpty()) {
+ mInputScheduleMap.remove(inputId);
+ }
+ // Update conflict list as well
+ Map<Long, ConflictInfo> conflictInfo =
+ mInputConflictInfoMap.get(inputId);
+ if (conflictInfo != null) {
+ ConflictInfo oldConflictInfo = conflictInfo.get(schedule.getId());
+ if (oldConflictInfo != null) {
+ oldConflictInfo.schedule = schedule;
+ }
+ }
}
+ onSchedulesChanged();
+ notifyScheduledRecordingStatusChanged(scheduledRecordings);
}
- }
- onSchedulesChanged();
- notifyScheduledRecordingStatusChanged(scheduledRecordings);
- }
- };
+ };
mDataManager.addScheduledRecordingListener(scheduledRecordingListener);
- ChannelDataManager.Listener channelDataManagerListener = new ChannelDataManager.Listener() {
- @Override
- public void onLoadFinished() {
- if (mDataManager.isDvrScheduleLoadFinished() && !mInitialized) {
- buildData();
- }
- }
+ ChannelDataManager.Listener channelDataManagerListener =
+ new ChannelDataManager.Listener() {
+ @Override
+ public void onLoadFinished() {
+ if (mDataManager.isDvrScheduleLoadFinished() && !mInitialized) {
+ buildData();
+ }
+ }
- @Override
- public void onChannelListUpdated() {
- if (mDataManager.isDvrScheduleLoadFinished()) {
- buildData();
- }
- }
+ @Override
+ public void onChannelListUpdated() {
+ if (mDataManager.isDvrScheduleLoadFinished()) {
+ buildData();
+ }
+ }
- @Override
- public void onChannelBrowsableChanged() {
- }
- };
+ @Override
+ public void onChannelBrowsableChanged() {}
+ };
mChannelDataManager.addListener(channelDataManagerListener);
}
- /**
- * Returns the started recordings for the given input.
- */
+ /** Returns the started recordings for the given input. */
private List<ScheduledRecording> getStartedRecordings(String inputId) {
if (!SoftPreconditions.checkState(mInitialized, TAG, "Not initialized yet")) {
return Collections.emptyList();
@@ -337,39 +334,29 @@ public class DvrScheduleManager {
}
}
- /**
- * Returns {@code true} if this class has been initialized.
- */
+ /** Returns {@code true} if this class has been initialized. */
public boolean isInitialized() {
return mInitialized;
}
- /**
- * Adds a {@link ScheduledRecordingListener}.
- */
+ /** Adds a {@link ScheduledRecordingListener}. */
public final void addScheduledRecordingListener(ScheduledRecordingListener listener) {
mScheduledRecordingListeners.add(listener);
}
- /**
- * Removes a {@link ScheduledRecordingListener}.
- */
+ /** Removes a {@link ScheduledRecordingListener}. */
public final void removeScheduledRecordingListener(ScheduledRecordingListener listener) {
mScheduledRecordingListeners.remove(listener);
}
- /**
- * Calls {@link ScheduledRecordingListener#onScheduledRecordingAdded} for each listener.
- */
+ /** Calls {@link ScheduledRecordingListener#onScheduledRecordingAdded} for each listener. */
private void notifyScheduledRecordingAdded(ScheduledRecording... scheduledRecordings) {
for (ScheduledRecordingListener l : mScheduledRecordingListeners) {
l.onScheduledRecordingAdded(scheduledRecordings);
}
}
- /**
- * Calls {@link ScheduledRecordingListener#onScheduledRecordingRemoved} for each listener.
- */
+ /** Calls {@link ScheduledRecordingListener#onScheduledRecordingRemoved} for each listener. */
private void notifyScheduledRecordingRemoved(ScheduledRecording... scheduledRecordings) {
for (ScheduledRecordingListener l : mScheduledRecordingListeners) {
l.onScheduledRecordingRemoved(scheduledRecordings);
@@ -385,48 +372,36 @@ public class DvrScheduleManager {
}
}
- /**
- * Adds a {@link OnInitializeListener}.
- */
+ /** Adds a {@link OnInitializeListener}. */
public final void addOnInitializeListener(OnInitializeListener listener) {
mOnInitializeListeners.add(listener);
}
- /**
- * Removes a {@link OnInitializeListener}.
- */
+ /** Removes a {@link OnInitializeListener}. */
public final void removeOnInitializeListener(OnInitializeListener listener) {
mOnInitializeListeners.remove(listener);
}
- /**
- * Calls {@link OnInitializeListener#onInitialize} for each listener.
- */
+ /** Calls {@link OnInitializeListener#onInitialize} for each listener. */
private void notifyInitialize() {
for (OnInitializeListener l : mOnInitializeListeners) {
l.onInitialize();
}
}
- /**
- * Adds a {@link OnConflictStateChangeListener}.
- */
+ /** Adds a {@link OnConflictStateChangeListener}. */
public final void addOnConflictStateChangeListener(OnConflictStateChangeListener listener) {
mOnConflictStateChangeListeners.add(listener);
}
- /**
- * Removes a {@link OnConflictStateChangeListener}.
- */
+ /** Removes a {@link OnConflictStateChangeListener}. */
public final void removeOnConflictStateChangeListener(OnConflictStateChangeListener listener) {
mOnConflictStateChangeListeners.remove(listener);
}
- /**
- * Calls {@link OnConflictStateChangeListener#onConflictStateChange} for each listener.
- */
- private void notifyConflictStateChange(boolean conflict,
- ScheduledRecording... scheduledRecordings) {
+ /** Calls {@link OnConflictStateChangeListener#onConflictStateChange} for each listener. */
+ private void notifyConflictStateChange(
+ boolean conflict, ScheduledRecording... scheduledRecordings) {
for (OnConflictStateChangeListener l : mOnConflictStateChangeListeners) {
l.onConflictStateChange(conflict, scheduledRecordings);
}
@@ -434,8 +409,8 @@ public class DvrScheduleManager {
/**
* Returns the priority for the program if it is recorded.
- * <p>
- * The recording will have the higher priority than the existing ones.
+ *
+ * <p>The recording will have the higher priority than the existing ones.
*/
public long suggestNewPriority() {
if (!SoftPreconditions.checkState(mInitialized, TAG, "Not initialized yet")) {
@@ -454,9 +429,7 @@ public class DvrScheduleManager {
return highestPriority + PRIORITY_OFFSET;
}
- /**
- * Suggests the higher priority than the schedules which overlap with {@code schedule}.
- */
+ /** Suggests the higher priority than the schedules which overlap with {@code schedule}. */
public long suggestHighestPriority(ScheduledRecording schedule) {
List<ScheduledRecording> schedules = mInputScheduleMap.get(schedule.getInputId());
if (schedules == null) {
@@ -464,7 +437,8 @@ public class DvrScheduleManager {
}
long highestPriority = Long.MIN_VALUE;
for (ScheduledRecording r : schedules) {
- if (!r.equals(schedule) && r.isOverLapping(schedule)
+ if (!r.equals(schedule)
+ && r.isOverLapping(schedule)
&& r.getPriority() > highestPriority) {
highestPriority = r.getPriority();
}
@@ -475,9 +449,7 @@ public class DvrScheduleManager {
return highestPriority + PRIORITY_OFFSET;
}
- /**
- * Suggests the higher priority than the schedules which overlap with {@code schedule}.
- */
+ /** Suggests the higher priority than the schedules which overlap with {@code schedule}. */
public long suggestHighestPriority(String inputId, Range<Long> peroid, long basePriority) {
List<ScheduledRecording> schedules = mInputScheduleMap.get(inputId);
if (schedules == null) {
@@ -497,8 +469,8 @@ public class DvrScheduleManager {
/**
* Returns the priority for a series recording.
- * <p>
- * The recording will have the higher priority than the existing series.
+ *
+ * <p>The recording will have the higher priority than the existing series.
*/
public long suggestNewSeriesPriority() {
if (!SoftPreconditions.checkState(mInitialized, TAG, "Not initialized yet")) {
@@ -510,7 +482,7 @@ public class DvrScheduleManager {
/**
* Returns the priority for a series recording by order of series recording priority.
*
- * Higher order will have higher priority.
+ * <p>Higher order will have higher priority.
*/
public static long suggestSeriesPriority(int order) {
return DEFAULT_SERIES_PRIORITY + order * PRIORITY_OFFSET;
@@ -527,21 +499,23 @@ public class DvrScheduleManager {
}
/**
- * Returns a sorted list of all scheduled recordings that will not be recorded if
- * this program is going to be recorded, with their priorities in decending order.
- * <p>
- * An empty list means there is no conflicts. If there is conflict, a priority higher than
+ * Returns a sorted list of all scheduled recordings that will not be recorded if this program
+ * is going to be recorded, with their priorities in decending order.
+ *
+ * <p>An empty list means there is no conflicts. If there is conflict, a priority higher than
* the first recording in the returned list should be assigned to the new schedule of this
* program to guarantee the program would be completely recorded.
*/
public List<ScheduledRecording> getConflictingSchedules(Program program) {
SoftPreconditions.checkState(mInitialized, TAG, "Not initialized yet");
- SoftPreconditions.checkState(Program.isValid(program), TAG,
- "Program is invalid: " + program);
SoftPreconditions.checkState(
- program.getStartTimeUtcMillis() < program.getEndTimeUtcMillis(), TAG,
+ Program.isProgramValid(program), TAG, "Program is invalid: " + program);
+ SoftPreconditions.checkState(
+ program.getStartTimeUtcMillis() < program.getEndTimeUtcMillis(),
+ TAG,
"Program duration is empty: " + program);
- if (!mInitialized || !Program.isValid(program)
+ if (!mInitialized
+ || !Program.isProgramValid(program)
|| program.getStartTimeUtcMillis() >= program.getEndTimeUtcMillis()) {
return Collections.emptyList();
}
@@ -549,17 +523,19 @@ public class DvrScheduleManager {
if (input == null || !input.canRecord() || input.getTunerCount() <= 0) {
return Collections.emptyList();
}
- return getConflictingSchedules(input, Collections.singletonList(
- ScheduledRecording.builder(input.getId(), program)
- .setPriority(suggestHighestPriority())
- .build()));
+ return getConflictingSchedules(
+ input,
+ Collections.singletonList(
+ ScheduledRecording.builder(input.getId(), program)
+ .setPriority(suggestHighestPriority())
+ .build()));
}
/**
* Returns list of all conflicting scheduled recordings for the given {@code seriesRecording}
* recording.
- * <p>
- * Any empty list means there is no conflicts.
+ *
+ * <p>Any empty list means there is no conflicts.
*/
public List<ScheduledRecording> getConflictingSchedules(SeriesRecording seriesRecording) {
SoftPreconditions.checkState(mInitialized, TAG, "Not initialized yet");
@@ -571,8 +547,8 @@ public class DvrScheduleManager {
if (input == null || !input.canRecord() || input.getTunerCount() <= 0) {
return Collections.emptyList();
}
- List<ScheduledRecording> scheduledRecordingForSeries = mDataManager.getScheduledRecordings(
- seriesRecording.getId());
+ List<ScheduledRecording> scheduledRecordingForSeries =
+ mDataManager.getScheduledRecordings(seriesRecording.getId());
List<ScheduledRecording> availableScheduledRecordingForSeries = new ArrayList<>();
for (ScheduledRecording scheduledRecording : scheduledRecordingForSeries) {
if (scheduledRecording.isNotStarted() || scheduledRecording.isInProgress()) {
@@ -586,15 +562,15 @@ public class DvrScheduleManager {
}
/**
- * Returns a sorted list of all scheduled recordings that will not be recorded if
- * this channel is going to be recorded, with their priority in decending order.
- * <p>
- * An empty list means there is no conflicts. If there is conflict, a priority higher than
+ * Returns a sorted list of all scheduled recordings that will not be recorded if this channel
+ * is going to be recorded, with their priority in decending order.
+ *
+ * <p>An empty list means there is no conflicts. If there is conflict, a priority higher than
* the first recording in the returned list should be assigned to the new schedule of this
* channel to guarantee the channel would be completely recorded in the designated time range.
*/
- public List<ScheduledRecording> getConflictingSchedules(long channelId, long startTimeMs,
- long endTimeMs) {
+ public List<ScheduledRecording> getConflictingSchedules(
+ long channelId, long startTimeMs, long endTimeMs) {
SoftPreconditions.checkState(mInitialized, TAG, "Not initialized yet");
SoftPreconditions.checkState(channelId != Channel.INVALID_ID, TAG, "Invalid channel ID");
SoftPreconditions.checkState(startTimeMs < endTimeMs, TAG, "Recording duration is empty.");
@@ -605,10 +581,12 @@ public class DvrScheduleManager {
if (input == null || !input.canRecord() || input.getTunerCount() <= 0) {
return Collections.emptyList();
}
- return getConflictingSchedules(input, Collections.singletonList(
- ScheduledRecording.builder(input.getId(), channelId, startTimeMs, endTimeMs)
- .setPriority(suggestHighestPriority())
- .build()));
+ return getConflictingSchedules(
+ input,
+ Collections.singletonList(
+ ScheduledRecording.builder(input.getId(), channelId, startTimeMs, endTimeMs)
+ .setPriority(suggestHighestPriority())
+ .build()));
}
/**
@@ -633,14 +611,14 @@ public class DvrScheduleManager {
/**
* Checks if the schedule is conflicting.
*
- * <p>Note that the {@code schedule} should be the existing one. If not, this returns
- * {@code false}.
+ * <p>Note that the {@code schedule} should be the existing one. If not, this returns {@code
+ * false}.
*/
public boolean isConflicting(ScheduledRecording schedule) {
SoftPreconditions.checkState(mInitialized, TAG, "Not initialized yet");
TvInputInfo input = Utils.getTvInputInfoForInputId(mContext, schedule.getInputId());
- SoftPreconditions.checkState(input != null, TAG, "Can't find input for channel ID : "
- + schedule.getChannelId());
+ SoftPreconditions.checkState(
+ input != null, TAG, "Can't find input for channel ID : " + schedule.getChannelId());
if (!mInitialized || input == null) {
return false;
}
@@ -651,15 +629,15 @@ public class DvrScheduleManager {
/**
* Checks if the schedule is partially conflicting, i.e., part of the scheduled program might be
* recorded even if the priority of the schedule is not raised.
- * <p>
- * If the given schedule is not conflicting or is totally conflicting, i.e., cannot be recorded
- * at all, this method returns {@code false} in both cases.
+ *
+ * <p>If the given schedule is not conflicting or is totally conflicting, i.e., cannot be
+ * recorded at all, this method returns {@code false} in both cases.
*/
public boolean isPartiallyConflicting(@NonNull ScheduledRecording schedule) {
SoftPreconditions.checkState(mInitialized, TAG, "Not initialized yet");
TvInputInfo input = Utils.getTvInputInfoForInputId(mContext, schedule.getInputId());
- SoftPreconditions.checkState(input != null, TAG, "Can't find input for channel ID : "
- + schedule.getChannelId());
+ SoftPreconditions.checkState(
+ input != null, TAG, "Can't find input for channel ID : " + schedule.getChannelId());
if (!mInitialized || input == null) {
return false;
}
@@ -672,27 +650,35 @@ public class DvrScheduleManager {
}
/**
- * Returns priority ordered list of all scheduled recordings that will not be recorded if
- * this channel is tuned to.
+ * Returns priority ordered list of all scheduled recordings that will not be recorded if this
+ * channel is tuned to.
*/
public List<ScheduledRecording> getConflictingSchedulesForTune(long channelId) {
SoftPreconditions.checkState(mInitialized, TAG, "Not initialized yet");
SoftPreconditions.checkState(channelId != Channel.INVALID_ID, TAG, "Invalid channel ID");
TvInputInfo input = Utils.getTvInputInfoForChannelId(mContext, channelId);
- SoftPreconditions.checkState(input != null, TAG, "Can't find input for channel ID: "
- + channelId);
+ SoftPreconditions.checkState(
+ input != null, TAG, "Can't find input for channel ID: " + channelId);
if (!mInitialized || channelId == Channel.INVALID_ID || input == null) {
return Collections.emptyList();
}
- return getConflictingSchedulesForTune(input.getId(), channelId, System.currentTimeMillis(),
- suggestHighestPriority(), getStartedRecordings(input.getId()),
+ return getConflictingSchedulesForTune(
+ input.getId(),
+ channelId,
+ System.currentTimeMillis(),
+ suggestHighestPriority(),
+ getStartedRecordings(input.getId()),
input.getTunerCount());
}
@VisibleForTesting
- public static List<ScheduledRecording> getConflictingSchedulesForTune(String inputId,
- long channelId, long currentTimeMs, long newPriority,
- List<ScheduledRecording> startedRecordings, int tunerCount) {
+ public static List<ScheduledRecording> getConflictingSchedulesForTune(
+ String inputId,
+ long channelId,
+ long currentTimeMs,
+ long newPriority,
+ List<ScheduledRecording> startedRecordings,
+ int tunerCount) {
boolean channelFound = false;
for (ScheduledRecording schedule : startedRecordings) {
if (schedule.getChannelId() == channelId) {
@@ -704,10 +690,10 @@ public class DvrScheduleManager {
if (!channelFound) {
// The current channel is not being recorded.
schedules = new ArrayList<>(startedRecordings);
- schedules.add(ScheduledRecording
- .builder(inputId, channelId, currentTimeMs, currentTimeMs + 1)
- .setPriority(newPriority)
- .build());
+ schedules.add(
+ ScheduledRecording.builder(inputId, channelId, currentTimeMs, currentTimeMs + 1)
+ .setPriority(newPriority)
+ .build());
} else {
schedules = startedRecordings;
}
@@ -715,17 +701,17 @@ public class DvrScheduleManager {
}
/**
- * Returns priority ordered list of all scheduled recordings that will not be recorded if
- * the user keeps watching this channel.
- * <p>
- * Note that if the user keeps watching the channel, the channel can be recorded.
+ * Returns priority ordered list of all scheduled recordings that will not be recorded if the
+ * user keeps watching this channel.
+ *
+ * <p>Note that if the user keeps watching the channel, the channel can be recorded.
*/
public List<ScheduledRecording> getConflictingSchedulesForWatching(long channelId) {
SoftPreconditions.checkState(mInitialized, TAG, "Not initialized yet");
SoftPreconditions.checkState(channelId != Channel.INVALID_ID, TAG, "Invalid channel ID");
TvInputInfo input = Utils.getTvInputInfoForChannelId(mContext, channelId);
- SoftPreconditions.checkState(input != null, TAG, "Can't find input for channel ID: "
- + channelId);
+ SoftPreconditions.checkState(
+ input != null, TAG, "Can't find input for channel ID: " + channelId);
if (!mInitialized || channelId == Channel.INVALID_ID || input == null) {
return Collections.emptyList();
}
@@ -733,12 +719,17 @@ public class DvrScheduleManager {
if (schedules == null || schedules.isEmpty()) {
return Collections.emptyList();
}
- return getConflictingSchedulesForWatching(input.getId(), channelId,
- System.currentTimeMillis(), suggestNewPriority(), schedules, input.getTunerCount());
+ return getConflictingSchedulesForWatching(
+ input.getId(),
+ channelId,
+ System.currentTimeMillis(),
+ suggestNewPriority(),
+ schedules,
+ input.getTunerCount());
}
- private List<ScheduledRecording> getConflictingSchedules(TvInputInfo input,
- List<ScheduledRecording> schedulesToAdd) {
+ private List<ScheduledRecording> getConflictingSchedules(
+ TvInputInfo input, List<ScheduledRecording> schedulesToAdd) {
SoftPreconditions.checkNotNull(input);
if (input == null || !input.canRecord() || input.getTunerCount() <= 0) {
return Collections.emptyList();
@@ -751,9 +742,13 @@ public class DvrScheduleManager {
}
@VisibleForTesting
- static List<ScheduledRecording> getConflictingSchedulesForWatching(String inputId,
- long channelId, long currentTimeMs, long newPriority,
- @NonNull List<ScheduledRecording> schedules, int tunerCount) {
+ static List<ScheduledRecording> getConflictingSchedulesForWatching(
+ String inputId,
+ long channelId,
+ long currentTimeMs,
+ long newPriority,
+ @NonNull List<ScheduledRecording> schedules,
+ int tunerCount) {
List<ScheduledRecording> schedulesToCheck = new ArrayList<>(schedules);
List<ScheduledRecording> schedulesSameChannel = new ArrayList<>();
for (ScheduledRecording schedule : schedules) {
@@ -763,10 +758,10 @@ public class DvrScheduleManager {
}
}
// Assume that the user will watch the current channel forever.
- schedulesToCheck.add(ScheduledRecording
- .builder(inputId, channelId, currentTimeMs, Long.MAX_VALUE)
- .setPriority(newPriority)
- .build());
+ schedulesToCheck.add(
+ ScheduledRecording.builder(inputId, channelId, currentTimeMs, Long.MAX_VALUE)
+ .setPriority(newPriority)
+ .build());
List<ScheduledRecording> result = new ArrayList<>();
result.addAll(getConflictingSchedules(schedulesSameChannel, 1));
result.addAll(getConflictingSchedules(schedulesToCheck, tunerCount));
@@ -775,8 +770,10 @@ public class DvrScheduleManager {
}
@VisibleForTesting
- static List<ScheduledRecording> getConflictingSchedules(List<ScheduledRecording> schedulesToAdd,
- List<ScheduledRecording> currentSchedules, int tunerCount) {
+ static List<ScheduledRecording> getConflictingSchedules(
+ List<ScheduledRecording> schedulesToAdd,
+ List<ScheduledRecording> currentSchedules,
+ int tunerCount) {
List<ScheduledRecording> schedulesToCheck = new ArrayList<>(currentSchedules);
// When the duplicate schedule is to be added, remove the current duplicate recording.
for (Iterator<ScheduledRecording> iter = schedulesToCheck.iterator(); iter.hasNext(); ) {
@@ -805,9 +802,7 @@ public class DvrScheduleManager {
return getConflictingSchedules(schedulesToCheck, tunerCount, ranges);
}
- /**
- * Returns all conflicting scheduled recordings for the given schedules and count of tuner.
- */
+ /** Returns all conflicting scheduled recordings for the given schedules and count of tuner. */
public static List<ScheduledRecording> getConflictingSchedules(
List<ScheduledRecording> schedules, int tunerCount) {
return getConflictingSchedules(schedules, tunerCount, null);
@@ -825,21 +820,21 @@ public class DvrScheduleManager {
}
@VisibleForTesting
- static List<ConflictInfo> getConflictingSchedulesInfo(List<ScheduledRecording> schedules,
- int tunerCount) {
+ static List<ConflictInfo> getConflictingSchedulesInfo(
+ List<ScheduledRecording> schedules, int tunerCount) {
return getConflictingSchedulesInfo(schedules, tunerCount, null);
}
/**
* This is the core method to calculate all the conflicting schedules (in given periods).
- * <p>
- * Note that this method will ignore duplicated schedules with a same hash code. (Please refer
- * to {@link ScheduledRecording#hashCode}.)
+ *
+ * <p>Note that this method will ignore duplicated schedules with a same hash code. (Please
+ * refer to {@link ScheduledRecording#hashCode}.)
*
* @return A {@link HashMap} from {@link ScheduledRecording} to {@link Boolean}. The boolean
- * value denotes if the scheduled recording is partially conflicting, i.e., is possible
- * to be partially recorded under the given schedules and tuner count {@code true},
- * or not {@code false}.
+ * value denotes if the scheduled recording is partially conflicting, i.e., is possible to
+ * be partially recorded under the given schedules and tuner count {@code true}, or not
+ * {@code false}.
*/
private static List<ConflictInfo> getConflictingSchedulesInfo(
List<ScheduledRecording> schedules, int tunerCount, List<Range<Long>> periods) {
@@ -886,14 +881,19 @@ public class DvrScheduleManager {
if (earliestEndTime < schedule.getEndTimeMs()) {
// The schedule can starts when other recording ends even though it's
// clipped.
- ScheduledRecording modifiedSchedule = ScheduledRecording.buildFrom(schedule)
- .setStartTimeMs(earliestEndTime).build();
+ ScheduledRecording modifiedSchedule =
+ ScheduledRecording.buildFrom(schedule)
+ .setStartTimeMs(earliestEndTime)
+ .build();
ScheduledRecording originalSchedule =
modified2OriginalSchedules.getOrDefault(schedule, schedule);
modified2OriginalSchedules.put(modifiedSchedule, originalSchedule);
- int insertPosition = Collections.binarySearch(schedulesToCheck,
- modifiedSchedule,
- ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR);
+ int insertPosition =
+ Collections.binarySearch(
+ schedulesToCheck,
+ modifiedSchedule,
+ ScheduledRecording
+ .START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR);
if (insertPosition >= 0) {
schedulesToCheck.add(insertPosition, modifiedSchedule);
} else {
@@ -921,17 +921,19 @@ public class DvrScheduleManager {
}
}
List<ConflictInfo> result = new ArrayList<>(conflicts.values());
- Collections.sort(result, new Comparator<ConflictInfo>() {
- @Override
- public int compare(ConflictInfo lhs, ConflictInfo rhs) {
- return RESULT_COMPARATOR.compare(lhs.schedule, rhs.schedule);
- }
- });
+ Collections.sort(
+ result,
+ new Comparator<ConflictInfo>() {
+ @Override
+ public int compare(ConflictInfo lhs, ConflictInfo rhs) {
+ return RESULT_COMPARATOR.compare(lhs.schedule, rhs.schedule);
+ }
+ });
return result;
}
- private static void removeFinishedRecordings(List<ScheduledRecording> recordings,
- long currentTimeMs) {
+ private static void removeFinishedRecordings(
+ List<ScheduledRecording> recordings, long currentTimeMs) {
for (Iterator<ScheduledRecording> iter = recordings.iterator(); iter.hasNext(); ) {
if (iter.next().getEndTimeMs() <= currentTimeMs) {
iter.remove();
@@ -939,11 +941,9 @@ public class DvrScheduleManager {
}
}
- /**
- * @see InputTaskScheduler#getReplacableTask
- */
- private static ScheduledRecording findReplaceableRecording(List<ScheduledRecording> recordings,
- ScheduledRecording schedule) {
+ /** @see InputTaskScheduler#getReplacableTask */
+ private static ScheduledRecording findReplaceableRecording(
+ List<ScheduledRecording> recordings, ScheduledRecording schedule) {
// Returns the recording with the following priority.
// 1. The recording with the lowest priority is returned.
// 2. If the priorities are the same, the recording which finishes early is returned.
@@ -980,30 +980,24 @@ public class DvrScheduleManager {
}
}
- /**
- * A listener which is notified the initialization of schedule manager.
- */
+ /** A listener which is notified the initialization of schedule manager. */
public interface OnInitializeListener {
- /**
- * Called when the schedule manager has been initialized.
- */
+ /** Called when the schedule manager has been initialized. */
void onInitialize();
}
- /**
- * A listener which is notified the conflict state change of the schedules.
- */
+ /** A listener which is notified the conflict state change of the schedules. */
public interface OnConflictStateChangeListener {
/**
* Called when the conflicting schedules change.
- * <p>
- * Note that this can be called before
- * {@link ScheduledRecordingListener#onScheduledRecordingAdded} is called.
+ *
+ * <p>Note that this can be called before {@link
+ * ScheduledRecordingListener#onScheduledRecordingAdded} is called.
*
* @param conflict {@code true} if the {@code schedules} are the new conflicts, otherwise
- * {@code false}.
+ * {@code false}.
* @param schedules the schedules
*/
void onConflictStateChange(boolean conflict, ScheduledRecording... schedules);
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/DvrStorageStatusManager.java b/src/com/android/tv/dvr/DvrStorageStatusManager.java
index 2d41d732..ed8d6903 100644
--- a/src/com/android/tv/dvr/DvrStorageStatusManager.java
+++ b/src/com/android/tv/dvr/DvrStorageStatusManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -11,291 +11,55 @@
* 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
+ * limitations under the License.
*/
-
package com.android.tv.dvr;
-import android.content.BroadcastReceiver;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.OperationApplicationException;
import android.database.Cursor;
-import android.media.tv.TvContract;
import android.media.tv.TvInputInfo;
import android.net.Uri;
import android.os.AsyncTask;
-import android.os.Environment;
-import android.os.Looper;
import android.os.RemoteException;
-import android.os.StatFs;
-import android.support.annotation.AnyThread;
-import android.support.annotation.IntDef;
-import android.support.annotation.WorkerThread;
+import android.support.media.tv.TvContractCompat;
import android.util.Log;
-
-import com.android.tv.TvApplication;
-import com.android.tv.common.SoftPreconditions;
-import com.android.tv.common.feature.CommonFeatures;
-import com.android.tv.tuner.tvinput.TunerTvInputService;
+import com.android.tv.TvSingletons;
+import com.android.tv.common.recording.RecordingStorageStatusManager;
+import com.android.tv.common.util.CommonUtils;
import com.android.tv.util.TvInputManagerHelper;
-import com.android.tv.util.Utils;
-
import java.io.File;
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArraySet;
-/**
- * Signals DVR storage status change such as plugging/unplugging.
- */
-public class DvrStorageStatusManager {
+/** A class for extending TV app-specific function to {@link RecordingStorageStatusManager}. */
+public class DvrStorageStatusManager extends RecordingStorageStatusManager {
private static final String TAG = "DvrStorageStatusManager";
- private static final boolean DEBUG = false;
-
- /**
- * Minimum storage size to support DVR
- */
- public static final long MIN_STORAGE_SIZE_FOR_DVR_IN_BYTES = 50 * 1024 * 1024 * 1024L; // 50GB
- private static final long MIN_FREE_STORAGE_SIZE_FOR_DVR_IN_BYTES
- = 10 * 1024 * 1024 * 1024L; // 10GB
- private static final String RECORDING_DATA_SUB_PATH = "/recording";
-
- private static final String[] PROJECTION = {
- TvContract.RecordedPrograms._ID,
- TvContract.RecordedPrograms.COLUMN_PACKAGE_NAME,
- TvContract.RecordedPrograms.COLUMN_RECORDING_DATA_URI
- };
- private final static int BATCH_OPERATION_COUNT = 100;
-
- @IntDef({STORAGE_STATUS_OK, STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL,
- STORAGE_STATUS_FREE_SPACE_INSUFFICIENT, STORAGE_STATUS_MISSING})
- @Retention(RetentionPolicy.SOURCE)
- public @interface StorageStatus {
- }
-
- /**
- * Current storage is OK to record a program.
- */
- public static final int STORAGE_STATUS_OK = 0;
-
- /**
- * Current storage's total capacity is smaller than DVR requirement.
- */
- public static final int STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL = 1;
-
- /**
- * Current storage's free space is insufficient to record programs.
- */
- public static final int STORAGE_STATUS_FREE_SPACE_INSUFFICIENT = 2;
-
- /**
- * Current storage is missing.
- */
- public static final int STORAGE_STATUS_MISSING = 3;
private final Context mContext;
- private final Set<OnStorageMountChangedListener> mOnStorageMountChangedListeners =
- new CopyOnWriteArraySet<>();
- private final boolean mRunningInMainProcess;
- private MountedStorageStatus mMountedStorageStatus;
- private boolean mStorageValid;
private CleanUpDbTask mCleanUpDbTask;
- private class MountedStorageStatus {
- private final boolean mStorageMounted;
- private final File mStorageMountedDir;
- private final long mStorageMountedCapacity;
-
- private MountedStorageStatus(boolean mounted, File mountedDir, long capacity) {
- mStorageMounted = mounted;
- mStorageMountedDir = mountedDir;
- mStorageMountedCapacity = capacity;
- }
-
- private boolean isValidForDvr() {
- return mStorageMounted && mStorageMountedCapacity >= MIN_STORAGE_SIZE_FOR_DVR_IN_BYTES;
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof MountedStorageStatus)) {
- return false;
- }
- MountedStorageStatus status = (MountedStorageStatus) other;
- return mStorageMounted == status.mStorageMounted
- && Objects.equals(mStorageMountedDir, status.mStorageMountedDir)
- && mStorageMountedCapacity == status.mStorageMountedCapacity;
- }
- }
-
- public interface OnStorageMountChangedListener {
-
- /**
- * Listener for DVR storage status change.
- *
- * @param storageMounted {@code true} when DVR possible storage is mounted,
- * {@code false} otherwise.
- */
- void onStorageMountChanged(boolean storageMounted);
- }
-
- private final class StorageStatusBroadcastReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- MountedStorageStatus result = getStorageStatusInternal();
- if (mMountedStorageStatus.equals(result)) {
- return;
- }
- mMountedStorageStatus = result;
- if (result.mStorageMounted && mRunningInMainProcess) {
- // Cleans up DB in LC process.
- // Tuner process is not always on.
- if (mCleanUpDbTask != null) {
- mCleanUpDbTask.cancel(true);
- }
- mCleanUpDbTask = new CleanUpDbTask();
- mCleanUpDbTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- }
- boolean valid = result.isValidForDvr();
- if (valid == mStorageValid) {
- return;
- }
- mStorageValid = valid;
- for (OnStorageMountChangedListener l : mOnStorageMountChangedListeners) {
- l.onStorageMountChanged(valid);
- }
- }
- }
+ private static final String[] PROJECTION = {
+ TvContractCompat.RecordedPrograms._ID,
+ TvContractCompat.RecordedPrograms.COLUMN_PACKAGE_NAME,
+ TvContractCompat.RecordedPrograms.COLUMN_RECORDING_DATA_URI
+ };
+ private static final int BATCH_OPERATION_COUNT = 100;
- /**
- * Creates DvrStorageStatusManager.
- *
- * @param context {@link Context}
- */
- public DvrStorageStatusManager(final Context context, boolean runningInMainProcess) {
+ public DvrStorageStatusManager(Context context) {
+ super(context);
mContext = context;
- mRunningInMainProcess = runningInMainProcess;
- mMountedStorageStatus = getStorageStatusInternal();
- mStorageValid = mMountedStorageStatus.isValidForDvr();
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
- filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
- filter.addAction(Intent.ACTION_MEDIA_EJECT);
- filter.addAction(Intent.ACTION_MEDIA_REMOVED);
- filter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
- filter.addDataScheme(ContentResolver.SCHEME_FILE);
- mContext.registerReceiver(new StorageStatusBroadcastReceiver(), filter);
}
- /**
- * Adds the listener for receiving storage status change.
- *
- * @param listener
- */
- public void addListener(OnStorageMountChangedListener listener) {
- mOnStorageMountChangedListeners.add(listener);
- }
-
- /**
- * Removes the current listener.
- */
- public void removeListener(OnStorageMountChangedListener listener) {
- mOnStorageMountChangedListeners.remove(listener);
- }
-
- /**
- * Returns true if a storage is mounted.
- */
- public boolean isStorageMounted() {
- return mMountedStorageStatus.mStorageMounted;
- }
-
- /**
- * Returns the path to DVR recording data directory.
- * This can take for a while sometimes.
- */
- @WorkerThread
- public File getRecordingRootDataDirectory() {
- SoftPreconditions.checkState(Looper.myLooper() != Looper.getMainLooper());
- if (mMountedStorageStatus.mStorageMountedDir == null) {
- return null;
- }
- File root = mContext.getExternalFilesDir(null);
- String rootPath;
- try {
- rootPath = root != null ? root.getCanonicalPath() : null;
- } catch (IOException | SecurityException e) {
- return null;
- }
- return rootPath == null ? null : new File(rootPath + RECORDING_DATA_SUB_PATH);
- }
-
- /**
- * Returns the current storage status for DVR recordings.
- *
- * @return {@link StorageStatus}
- */
- @AnyThread
- public @StorageStatus int getDvrStorageStatus() {
- MountedStorageStatus status = mMountedStorageStatus;
- if (status.mStorageMountedDir == null) {
- return STORAGE_STATUS_MISSING;
- }
- if (CommonFeatures.FORCE_RECORDING_UNTIL_NO_SPACE.isEnabled(mContext)) {
- return STORAGE_STATUS_OK;
- }
- if (status.mStorageMountedCapacity < MIN_STORAGE_SIZE_FOR_DVR_IN_BYTES) {
- return STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL;
- }
- try {
- StatFs statFs = new StatFs(status.mStorageMountedDir.toString());
- if (statFs.getAvailableBytes() < MIN_FREE_STORAGE_SIZE_FOR_DVR_IN_BYTES) {
- return STORAGE_STATUS_FREE_SPACE_INSUFFICIENT;
- }
- } catch (IllegalArgumentException e) {
- // In rare cases, storage status change was not notified yet.
- SoftPreconditions.checkState(false);
- return STORAGE_STATUS_FREE_SPACE_INSUFFICIENT;
- }
- return STORAGE_STATUS_OK;
- }
-
- /**
- * Returns whether the storage has sufficient storage.
- *
- * @return {@code true} when there is sufficient storage, {@code false} otherwise
- */
- public boolean isStorageSufficient() {
- return getDvrStorageStatus() == STORAGE_STATUS_OK;
- }
-
- private MountedStorageStatus getStorageStatusInternal() {
- boolean storageMounted =
- Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
- File storageMountedDir = storageMounted ? Environment.getExternalStorageDirectory() : null;
- storageMounted = storageMounted && storageMountedDir != null;
- long storageMountedCapacity = 0L;
- if (storageMounted) {
- try {
- StatFs statFs = new StatFs(storageMountedDir.toString());
- storageMountedCapacity = statFs.getTotalBytes();
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Storage mount status was changed.");
- storageMounted = false;
- storageMountedDir = null;
- }
+ @Override
+ protected void cleanUpDbIfNeeded() {
+ if (mCleanUpDbTask != null) {
+ mCleanUpDbTask.cancel(true);
}
- return new MountedStorageStatus(
- storageMounted, storageMountedDir, storageMountedCapacity);
+ mCleanUpDbTask = new CleanUpDbTask();
+ mCleanUpDbTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private class CleanUpDbTask extends AsyncTask<Void, Void, Boolean> {
@@ -307,26 +71,29 @@ public class DvrStorageStatusManager {
@Override
protected Boolean doInBackground(Void... params) {
- @DvrStorageStatusManager.StorageStatus int storageStatus = getDvrStorageStatus();
- if (storageStatus == DvrStorageStatusManager.STORAGE_STATUS_MISSING) {
+ @StorageStatus int storageStatus = getDvrStorageStatus();
+ if (storageStatus == STORAGE_STATUS_MISSING) {
return null;
}
- if (storageStatus == DvrStorageStatusManager.STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL) {
+ if (storageStatus == STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL) {
return true;
}
List<ContentProviderOperation> ops = getDeleteOps();
if (ops == null || ops.isEmpty()) {
return null;
}
- Log.i(TAG, "New device storage mounted. # of recordings to be forgotten : "
- + ops.size());
- for (int i = 0 ; i < ops.size() && !isCancelled() ; i += BATCH_OPERATION_COUNT) {
- int toIndex = (i + BATCH_OPERATION_COUNT) > ops.size()
- ? ops.size() : (i + BATCH_OPERATION_COUNT);
+ Log.i(
+ TAG,
+ "New device storage mounted. # of recordings to be forgotten : " + ops.size());
+ for (int i = 0; i < ops.size() && !isCancelled(); i += BATCH_OPERATION_COUNT) {
+ int toIndex =
+ (i + BATCH_OPERATION_COUNT) > ops.size()
+ ? ops.size()
+ : (i + BATCH_OPERATION_COUNT);
ArrayList<ContentProviderOperation> batchOps =
new ArrayList<>(ops.subList(i, toIndex));
try {
- mContext.getContentResolver().applyBatch(TvContract.AUTHORITY, batchOps);
+ mContext.getContentResolver().applyBatch(TvContractCompat.AUTHORITY, batchOps);
} catch (RemoteException | OperationApplicationException e) {
Log.e(TAG, "Failed to clean up RecordedPrograms.", e);
}
@@ -337,16 +104,16 @@ public class DvrStorageStatusManager {
@Override
protected void onPostExecute(Boolean forgetStorage) {
if (forgetStorage != null && forgetStorage == true) {
- DvrManager dvrManager = TvApplication.getSingletons(mContext).getDvrManager();
+ DvrManager dvrManager = TvSingletons.getSingletons(mContext).getDvrManager();
TvInputManagerHelper tvInputManagerHelper =
- TvApplication.getSingletons(mContext).getTvInputManagerHelper();
+ TvSingletons.getSingletons(mContext).getTvInputManagerHelper();
List<TvInputInfo> tvInputInfoList =
tvInputManagerHelper.getTvInputInfos(true, false);
if (tvInputInfoList == null || tvInputInfoList.isEmpty()) {
return;
}
for (TvInputInfo info : tvInputInfoList) {
- if (Utils.isBundledInput(info.getId())) {
+ if (CommonUtils.isBundledInput(info.getId())) {
dvrManager.forgetStorage(info.getId());
}
}
@@ -359,16 +126,19 @@ public class DvrStorageStatusManager {
private List<ContentProviderOperation> getDeleteOps() {
List<ContentProviderOperation> ops = new ArrayList<>();
- try (Cursor c = mContentResolver.query(
- TvContract.RecordedPrograms.CONTENT_URI, PROJECTION, null, null, null)) {
+ try (Cursor c =
+ mContentResolver.query(
+ TvContractCompat.RecordedPrograms.CONTENT_URI,
+ PROJECTION,
+ null,
+ null,
+ null)) {
if (c == null) {
return null;
}
while (c.moveToNext()) {
- @DvrStorageStatusManager.StorageStatus int storageStatus =
- getDvrStorageStatus();
- if (isCancelled()
- || storageStatus == DvrStorageStatusManager.STORAGE_STATUS_MISSING) {
+ @StorageStatus int storageStatus = getDvrStorageStatus();
+ if (isCancelled() || storageStatus == STORAGE_STATUS_MISSING) {
ops.clear();
break;
}
@@ -379,15 +149,19 @@ public class DvrStorageStatusManager {
continue;
}
Uri dataUri = Uri.parse(dataUriString);
- if (!Utils.isInBundledPackageSet(packageName)
- || dataUri == null || dataUri.getPath() == null
+ if (!CommonUtils.isInBundledPackageSet(packageName)
+ || dataUri == null
+ || dataUri.getPath() == null
|| !ContentResolver.SCHEME_FILE.equals(dataUri.getScheme())) {
continue;
}
File recordedProgramDir = new File(dataUri.getPath());
if (!recordedProgramDir.exists()) {
- ops.add(ContentProviderOperation.newDelete(
- TvContract.buildRecordedProgramUri(Long.parseLong(id))).build());
+ ops.add(
+ ContentProviderOperation.newDelete(
+ TvContractCompat.buildRecordedProgramUri(
+ Long.parseLong(id)))
+ .build());
}
}
return ops;
diff --git a/src/com/android/tv/dvr/DvrWatchedPositionManager.java b/src/com/android/tv/dvr/DvrWatchedPositionManager.java
index da6ddb1a..8616962f 100644
--- a/src/com/android/tv/dvr/DvrWatchedPositionManager.java
+++ b/src/com/android/tv/dvr/DvrWatchedPositionManager.java
@@ -20,10 +20,8 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.media.tv.TvInputManager;
import android.support.annotation.IntDef;
-
-import com.android.tv.common.SharedPreferencesUtils;
+import com.android.tv.common.util.SharedPreferencesUtils;
import com.android.tv.dvr.data.RecordedProgram;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -33,8 +31,8 @@ import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
/**
- * A class to manage DVR watched state.
- * It will remember and provides previous watched position of DVR playback.
+ * A class to manage DVR watched state. It will remember and provides previous watched position of
+ * DVR playback.
*/
public class DvrWatchedPositionManager {
private SharedPreferences mWatchedPositions;
@@ -49,55 +47,46 @@ public class DvrWatchedPositionManager {
@Retention(RetentionPolicy.SOURCE)
@IntDef({DVR_WATCHED_STATUS_NEW, DVR_WATCHED_STATUS_WATCHING, DVR_WATCHED_STATUS_WATCHED})
public @interface DvrWatchedStatus {}
- /**
- * The status indicates the recorded program has not been watched at all.
- */
+ /** The status indicates the recorded program has not been watched at all. */
public static final int DVR_WATCHED_STATUS_NEW = 0;
- /**
- * The status indicates the recorded program is being watched.
- */
+ /** The status indicates the recorded program is being watched. */
public static final int DVR_WATCHED_STATUS_WATCHING = 1;
- /**
- * The status indicates the recorded program was completely watched.
- */
+ /** The status indicates the recorded program was completely watched. */
public static final int DVR_WATCHED_STATUS_WATCHED = 2;
public DvrWatchedPositionManager(Context context) {
- mWatchedPositions = context.getSharedPreferences(
- SharedPreferencesUtils.SHARED_PREF_DVR_WATCHED_POSITION, Context.MODE_PRIVATE);
+ mWatchedPositions =
+ context.getSharedPreferences(
+ SharedPreferencesUtils.SHARED_PREF_DVR_WATCHED_POSITION,
+ Context.MODE_PRIVATE);
}
- /**
- * Sets the watched position of the give program.
- */
+ /** Sets the watched position of the give program. */
public void setWatchedPosition(long recordedProgramId, long positionMs) {
mWatchedPositions.edit().putLong(Long.toString(recordedProgramId), positionMs).apply();
notifyWatchedPositionChanged(recordedProgramId, positionMs);
}
- /**
- * Gets the watched position of the give program.
- */
+ /** Gets the watched position of the give program. */
public long getWatchedPosition(long recordedProgramId) {
- return mWatchedPositions.getLong(Long.toString(recordedProgramId),
- TvInputManager.TIME_SHIFT_INVALID_TIME);
+ return mWatchedPositions.getLong(
+ Long.toString(recordedProgramId), TvInputManager.TIME_SHIFT_INVALID_TIME);
}
- @DvrWatchedStatus public int getWatchedStatus(RecordedProgram recordedProgram) {
+ @DvrWatchedStatus
+ public int getWatchedStatus(RecordedProgram recordedProgram) {
long watchedPosition = getWatchedPosition(recordedProgram.getId());
if (watchedPosition == TvInputManager.TIME_SHIFT_INVALID_TIME) {
return DVR_WATCHED_STATUS_NEW;
- } else if (watchedPosition > recordedProgram
- .getDurationMillis() * DVR_WATCHED_THRESHOLD_RATE) {
+ } else if (watchedPosition
+ > recordedProgram.getDurationMillis() * DVR_WATCHED_THRESHOLD_RATE) {
return DVR_WATCHED_STATUS_WATCHED;
} else {
return DVR_WATCHED_STATUS_WATCHING;
}
}
- /**
- * Adds {@link WatchedPositionChangedListener}.
- */
+ /** Adds {@link WatchedPositionChangedListener}. */
public void addListener(WatchedPositionChangedListener listener, long recordedProgramId) {
if (recordedProgramId == RecordedProgram.ID_NOT_SET) {
return;
@@ -110,18 +99,14 @@ public class DvrWatchedPositionManager {
listenerSet.add(listener);
}
- /**
- * Removes {@link WatchedPositionChangedListener}.
- */
+ /** Removes {@link WatchedPositionChangedListener}. */
public void removeListener(WatchedPositionChangedListener listener) {
for (long recordedProgramId : new ArrayList<>(mListeners.keySet())) {
removeListener(listener, recordedProgramId);
}
}
- /**
- * Removes {@link WatchedPositionChangedListener}.
- */
+ /** Removes {@link WatchedPositionChangedListener}. */
public void removeListener(WatchedPositionChangedListener listener, long recordedProgramId) {
Set<WatchedPositionChangedListener> listenerSet = mListeners.get(recordedProgramId);
if (listenerSet == null) {
@@ -144,9 +129,7 @@ public class DvrWatchedPositionManager {
}
public interface WatchedPositionChangedListener {
- /**
- * Called when the watched position of some program is changed.
- */
+ /** Called when the watched position of some program is changed. */
void onWatchedPositionChanged(long recordedProgramId, long positionMs);
}
}
diff --git a/src/com/android/tv/dvr/WritableDvrDataManager.java b/src/com/android/tv/dvr/WritableDvrDataManager.java
index 129ba153..1b505e80 100644
--- a/src/com/android/tv/dvr/WritableDvrDataManager.java
+++ b/src/com/android/tv/dvr/WritableDvrDataManager.java
@@ -17,7 +17,6 @@
package com.android.tv.dvr;
import android.support.annotation.MainThread;
-
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.ScheduledRecording.RecordingState;
import com.android.tv.dvr.data.SeriesRecording;
@@ -30,19 +29,13 @@ import com.android.tv.dvr.data.SeriesRecording;
*/
@MainThread
public interface WritableDvrDataManager extends DvrDataManager {
- /**
- * Adds new recordings.
- */
+ /** Adds new recordings. */
void addScheduledRecording(ScheduledRecording... scheduledRecordings);
- /**
- * Adds new series recordings.
- */
+ /** Adds new series recordings. */
void addSeriesRecording(SeriesRecording... seriesRecordings);
- /**
- * Removes recordings.
- */
+ /** Removes recordings. */
void removeScheduledRecording(ScheduledRecording... scheduledRecordings);
/**
@@ -51,30 +44,30 @@ public interface WritableDvrDataManager extends DvrDataManager {
*/
void removeScheduledRecording(boolean forceRemove, ScheduledRecording... scheduledRecordings);
- /**
- * Removes series recordings.
- */
+ /** Removes series recordings. */
void removeSeriesRecording(SeriesRecording... seasonSchedules);
- /**
- * Updates existing recordings.
- */
+ /** Updates existing recordings. */
void updateScheduledRecording(ScheduledRecording... scheduledRecordings);
- /**
- * Updates existing series recordings.
- */
+ /** Updates existing series recordings. */
void updateSeriesRecording(SeriesRecording... seriesRecordings);
+ /** Changes the state of the recording. */
+ void changeState(ScheduledRecording scheduledRecording, @RecordingState int newState);
+
/**
* Changes the state of the recording.
+ *
+ * @param reason the reason of this change
*/
- void changeState(ScheduledRecording scheduledRecording, @RecordingState int newState);
+ void changeState(
+ ScheduledRecording scheduledRecording, @RecordingState int newState, int reason);
/**
* Remove all the records related to the input.
- * <p>
- * Note that this should be called after the input was removed.
+ *
+ * <p>Note that this should be called after the input was removed.
*/
void forgetStorage(String inputId);
}
diff --git a/src/com/android/tv/dvr/data/IdGenerator.java b/src/com/android/tv/dvr/data/IdGenerator.java
index 2ade1dad..496651ba 100644
--- a/src/com/android/tv/dvr/data/IdGenerator.java
+++ b/src/com/android/tv/dvr/data/IdGenerator.java
@@ -18,32 +18,22 @@ package com.android.tv.dvr.data;
import java.util.concurrent.atomic.AtomicLong;
-/**
- * A class which generate the ID which increases sequentially.
- */
+/** A class which generate the ID which increases sequentially. */
public class IdGenerator {
- /**
- * ID generator for the scheduled recording.
- */
+ /** ID generator for the scheduled recording. */
public static final IdGenerator SCHEDULED_RECORDING = new IdGenerator();
- /**
- * ID generator for the series recording.
- */
+ /** ID generator for the series recording. */
public static final IdGenerator SERIES_RECORDING = new IdGenerator();
private final AtomicLong mMaxId = new AtomicLong(0);
- /**
- * Sets the new maximum ID.
- */
+ /** Sets the new maximum ID. */
public void setMaxId(long maxId) {
mMaxId.set(maxId);
}
- /**
- * Returns the new ID which is greater than the existing maximum ID by 1.
- */
+ /** Returns the new ID which is greater than the existing maximum ID by 1. */
public long newId() {
return mMaxId.incrementAndGet();
}
diff --git a/src/com/android/tv/dvr/data/RecordedProgram.java b/src/com/android/tv/dvr/data/RecordedProgram.java
index 2e953a52..e1fbca8c 100644
--- a/src/com/android/tv/dvr/data/RecordedProgram.java
+++ b/src/com/android/tv/dvr/data/RecordedProgram.java
@@ -28,99 +28,97 @@ import android.net.Uri;
import android.os.Build;
import android.support.annotation.Nullable;
import android.text.TextUtils;
-
import com.android.tv.common.R;
import com.android.tv.common.TvContentRatingCache;
+import com.android.tv.common.util.CommonUtils;
import com.android.tv.data.BaseProgram;
import com.android.tv.data.GenreItems;
import com.android.tv.data.InternalDataUtils;
-import com.android.tv.util.Utils;
-
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
-/**
- * Immutable instance of {@link android.media.tv.TvContract.RecordedPrograms}.
- */
+/** Immutable instance of {@link android.media.tv.TvContract.RecordedPrograms}. */
@TargetApi(Build.VERSION_CODES.N)
public class RecordedProgram extends BaseProgram {
public static final int ID_NOT_SET = -1;
- public final static String[] PROJECTION = {
- // These are in exactly the order listed in RecordedPrograms
- RecordedPrograms._ID,
- RecordedPrograms.COLUMN_PACKAGE_NAME,
- RecordedPrograms.COLUMN_INPUT_ID,
- RecordedPrograms.COLUMN_CHANNEL_ID,
- RecordedPrograms.COLUMN_TITLE,
- RecordedPrograms.COLUMN_SEASON_DISPLAY_NUMBER,
- RecordedPrograms.COLUMN_SEASON_TITLE,
- RecordedPrograms.COLUMN_EPISODE_DISPLAY_NUMBER,
- RecordedPrograms.COLUMN_EPISODE_TITLE,
- RecordedPrograms.COLUMN_START_TIME_UTC_MILLIS,
- RecordedPrograms.COLUMN_END_TIME_UTC_MILLIS,
- RecordedPrograms.COLUMN_BROADCAST_GENRE,
- RecordedPrograms.COLUMN_CANONICAL_GENRE,
- RecordedPrograms.COLUMN_SHORT_DESCRIPTION,
- RecordedPrograms.COLUMN_LONG_DESCRIPTION,
- RecordedPrograms.COLUMN_VIDEO_WIDTH,
- RecordedPrograms.COLUMN_VIDEO_HEIGHT,
- RecordedPrograms.COLUMN_AUDIO_LANGUAGE,
- RecordedPrograms.COLUMN_CONTENT_RATING,
- RecordedPrograms.COLUMN_POSTER_ART_URI,
- RecordedPrograms.COLUMN_THUMBNAIL_URI,
- RecordedPrograms.COLUMN_SEARCHABLE,
- RecordedPrograms.COLUMN_RECORDING_DATA_URI,
- RecordedPrograms.COLUMN_RECORDING_DATA_BYTES,
- RecordedPrograms.COLUMN_RECORDING_DURATION_MILLIS,
- RecordedPrograms.COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS,
- RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG1,
- RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG2,
- RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG3,
- RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG4,
- RecordedPrograms.COLUMN_VERSION_NUMBER,
- RecordedPrograms.COLUMN_INTERNAL_PROVIDER_DATA,
+ public static final String[] PROJECTION = {
+ // These are in exactly the order listed in RecordedPrograms
+ RecordedPrograms._ID,
+ RecordedPrograms.COLUMN_PACKAGE_NAME,
+ RecordedPrograms.COLUMN_INPUT_ID,
+ RecordedPrograms.COLUMN_CHANNEL_ID,
+ RecordedPrograms.COLUMN_TITLE,
+ RecordedPrograms.COLUMN_SEASON_DISPLAY_NUMBER,
+ RecordedPrograms.COLUMN_SEASON_TITLE,
+ RecordedPrograms.COLUMN_EPISODE_DISPLAY_NUMBER,
+ RecordedPrograms.COLUMN_EPISODE_TITLE,
+ RecordedPrograms.COLUMN_START_TIME_UTC_MILLIS,
+ RecordedPrograms.COLUMN_END_TIME_UTC_MILLIS,
+ RecordedPrograms.COLUMN_BROADCAST_GENRE,
+ RecordedPrograms.COLUMN_CANONICAL_GENRE,
+ RecordedPrograms.COLUMN_SHORT_DESCRIPTION,
+ RecordedPrograms.COLUMN_LONG_DESCRIPTION,
+ RecordedPrograms.COLUMN_VIDEO_WIDTH,
+ RecordedPrograms.COLUMN_VIDEO_HEIGHT,
+ RecordedPrograms.COLUMN_AUDIO_LANGUAGE,
+ RecordedPrograms.COLUMN_CONTENT_RATING,
+ RecordedPrograms.COLUMN_POSTER_ART_URI,
+ RecordedPrograms.COLUMN_THUMBNAIL_URI,
+ RecordedPrograms.COLUMN_SEARCHABLE,
+ RecordedPrograms.COLUMN_RECORDING_DATA_URI,
+ RecordedPrograms.COLUMN_RECORDING_DATA_BYTES,
+ RecordedPrograms.COLUMN_RECORDING_DURATION_MILLIS,
+ RecordedPrograms.COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS,
+ RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG1,
+ RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG2,
+ RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG3,
+ RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG4,
+ RecordedPrograms.COLUMN_VERSION_NUMBER,
+ RecordedPrograms.COLUMN_INTERNAL_PROVIDER_DATA,
};
public static RecordedProgram fromCursor(Cursor cursor) {
int index = 0;
- Builder builder = builder()
- .setId(cursor.getLong(index++))
- .setPackageName(cursor.getString(index++))
- .setInputId(cursor.getString(index++))
- .setChannelId(cursor.getLong(index++))
- .setTitle(cursor.getString(index++))
- .setSeasonNumber(cursor.getString(index++))
- .setSeasonTitle(cursor.getString(index++))
- .setEpisodeNumber(cursor.getString(index++))
- .setEpisodeTitle(cursor.getString(index++))
- .setStartTimeUtcMillis(cursor.getLong(index++))
- .setEndTimeUtcMillis(cursor.getLong(index++))
- .setBroadcastGenres(cursor.getString(index++))
- .setCanonicalGenres(cursor.getString(index++))
- .setShortDescription(cursor.getString(index++))
- .setLongDescription(cursor.getString(index++))
- .setVideoWidth(cursor.getInt(index++))
- .setVideoHeight(cursor.getInt(index++))
- .setAudioLanguage(cursor.getString(index++))
- .setContentRatings(
- TvContentRatingCache.getInstance().getRatings(cursor.getString(index++)))
- .setPosterArtUri(cursor.getString(index++))
- .setThumbnailUri(cursor.getString(index++))
- .setSearchable(cursor.getInt(index++) == 1)
- .setDataUri(cursor.getString(index++))
- .setDataBytes(cursor.getLong(index++))
- .setDurationMillis(cursor.getLong(index++))
- .setExpireTimeUtcMillis(cursor.getLong(index++))
- .setInternalProviderFlag1(cursor.getInt(index++))
- .setInternalProviderFlag2(cursor.getInt(index++))
- .setInternalProviderFlag3(cursor.getInt(index++))
- .setInternalProviderFlag4(cursor.getInt(index++))
- .setVersionNumber(cursor.getInt(index++));
- if (Utils.isInBundledPackageSet(builder.mPackageName)) {
+ Builder builder =
+ builder()
+ .setId(cursor.getLong(index++))
+ .setPackageName(cursor.getString(index++))
+ .setInputId(cursor.getString(index++))
+ .setChannelId(cursor.getLong(index++))
+ .setTitle(cursor.getString(index++))
+ .setSeasonNumber(cursor.getString(index++))
+ .setSeasonTitle(cursor.getString(index++))
+ .setEpisodeNumber(cursor.getString(index++))
+ .setEpisodeTitle(cursor.getString(index++))
+ .setStartTimeUtcMillis(cursor.getLong(index++))
+ .setEndTimeUtcMillis(cursor.getLong(index++))
+ .setBroadcastGenres(cursor.getString(index++))
+ .setCanonicalGenres(cursor.getString(index++))
+ .setShortDescription(cursor.getString(index++))
+ .setLongDescription(cursor.getString(index++))
+ .setVideoWidth(cursor.getInt(index++))
+ .setVideoHeight(cursor.getInt(index++))
+ .setAudioLanguage(cursor.getString(index++))
+ .setContentRatings(
+ TvContentRatingCache.getInstance()
+ .getRatings(cursor.getString(index++)))
+ .setPosterArtUri(cursor.getString(index++))
+ .setThumbnailUri(cursor.getString(index++))
+ .setSearchable(cursor.getInt(index++) == 1)
+ .setDataUri(cursor.getString(index++))
+ .setDataBytes(cursor.getLong(index++))
+ .setDurationMillis(cursor.getLong(index++))
+ .setExpireTimeUtcMillis(cursor.getLong(index++))
+ .setInternalProviderFlag1(cursor.getInt(index++))
+ .setInternalProviderFlag2(cursor.getInt(index++))
+ .setInternalProviderFlag3(cursor.getInt(index++))
+ .setInternalProviderFlag4(cursor.getInt(index++))
+ .setVersionNumber(cursor.getInt(index++));
+ if (CommonUtils.isInBundledPackageSet(builder.mPackageName)) {
InternalDataUtils.deserializeInternalProviderData(cursor.getBlob(index), builder);
}
return builder.build();
@@ -138,12 +136,14 @@ public class RecordedProgram extends BaseProgram {
values.put(RecordedPrograms.COLUMN_SEASON_TITLE, recordedProgram.mSeasonTitle);
values.put(RecordedPrograms.COLUMN_EPISODE_DISPLAY_NUMBER, recordedProgram.mEpisodeNumber);
values.put(RecordedPrograms.COLUMN_EPISODE_TITLE, recordedProgram.mTitle);
- values.put(RecordedPrograms.COLUMN_START_TIME_UTC_MILLIS,
- recordedProgram.mStartTimeUtcMillis);
+ values.put(
+ RecordedPrograms.COLUMN_START_TIME_UTC_MILLIS, recordedProgram.mStartTimeUtcMillis);
values.put(RecordedPrograms.COLUMN_END_TIME_UTC_MILLIS, recordedProgram.mEndTimeUtcMillis);
- values.put(RecordedPrograms.COLUMN_BROADCAST_GENRE,
+ values.put(
+ RecordedPrograms.COLUMN_BROADCAST_GENRE,
safeEncode(recordedProgram.mBroadcastGenres));
- values.put(RecordedPrograms.COLUMN_CANONICAL_GENRE,
+ values.put(
+ RecordedPrograms.COLUMN_CANONICAL_GENRE,
safeEncode(recordedProgram.mCanonicalGenres));
values.put(RecordedPrograms.COLUMN_SHORT_DESCRIPTION, recordedProgram.mShortDescription);
values.put(RecordedPrograms.COLUMN_LONG_DESCRIPTION, recordedProgram.mLongDescription);
@@ -158,33 +158,40 @@ public class RecordedProgram extends BaseProgram {
values.put(RecordedPrograms.COLUMN_VIDEO_HEIGHT, recordedProgram.mVideoHeight);
}
values.put(RecordedPrograms.COLUMN_AUDIO_LANGUAGE, recordedProgram.mAudioLanguage);
- values.put(RecordedPrograms.COLUMN_CONTENT_RATING,
+ values.put(
+ RecordedPrograms.COLUMN_CONTENT_RATING,
TvContentRatingCache.contentRatingsToString(recordedProgram.mContentRatings));
values.put(RecordedPrograms.COLUMN_POSTER_ART_URI, recordedProgram.mPosterArtUri);
values.put(RecordedPrograms.COLUMN_THUMBNAIL_URI, recordedProgram.mThumbnailUri);
values.put(RecordedPrograms.COLUMN_SEARCHABLE, recordedProgram.mSearchable ? 1 : 0);
- values.put(RecordedPrograms.COLUMN_RECORDING_DATA_URI,
- safeToString(recordedProgram.mDataUri));
+ values.put(
+ RecordedPrograms.COLUMN_RECORDING_DATA_URI, safeToString(recordedProgram.mDataUri));
values.put(RecordedPrograms.COLUMN_RECORDING_DATA_BYTES, recordedProgram.mDataBytes);
- values.put(RecordedPrograms.COLUMN_RECORDING_DURATION_MILLIS,
- recordedProgram.mDurationMillis);
- values.put(RecordedPrograms.COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS,
+ values.put(
+ RecordedPrograms.COLUMN_RECORDING_DURATION_MILLIS, recordedProgram.mDurationMillis);
+ values.put(
+ RecordedPrograms.COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS,
recordedProgram.mExpireTimeUtcMillis);
- values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_DATA,
+ values.put(
+ RecordedPrograms.COLUMN_INTERNAL_PROVIDER_DATA,
InternalDataUtils.serializeInternalProviderData(recordedProgram));
- values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG1,
+ values.put(
+ RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG1,
recordedProgram.mInternalProviderFlag1);
- values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG2,
+ values.put(
+ RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG2,
recordedProgram.mInternalProviderFlag2);
- values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG3,
+ values.put(
+ RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG3,
recordedProgram.mInternalProviderFlag3);
- values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG4,
+ values.put(
+ RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG4,
recordedProgram.mInternalProviderFlag4);
values.put(RecordedPrograms.COLUMN_VERSION_NUMBER, recordedProgram.mVersionNumber);
return values;
}
- public static class Builder{
+ public static class Builder {
private long mId = ID_NOT_SET;
private String mPackageName;
private String mInputId;
@@ -414,18 +421,45 @@ public class RecordedProgram extends BaseProgram {
// If series ID is not set, generate it for the episodic program of other TV input.
setSeriesId(BaseProgram.generateSeriesId(mPackageName, mTitle));
}
- return new RecordedProgram(mId, mPackageName, mInputId, mChannelId, mTitle, mSeriesId,
- mSeasonNumber, mSeasonTitle, mEpisodeNumber, mEpisodeTitle, mStartTimeUtcMillis,
- mEndTimeUtcMillis, mBroadcastGenres, mCanonicalGenres, mShortDescription,
- mLongDescription, mVideoWidth, mVideoHeight, mAudioLanguage, mContentRatings,
- mPosterArtUri, mThumbnailUri, mSearchable, mDataUri, mDataBytes,
- mDurationMillis, mExpireTimeUtcMillis, mInternalProviderFlag1,
- mInternalProviderFlag2, mInternalProviderFlag3, mInternalProviderFlag4,
+ return new RecordedProgram(
+ mId,
+ mPackageName,
+ mInputId,
+ mChannelId,
+ mTitle,
+ mSeriesId,
+ mSeasonNumber,
+ mSeasonTitle,
+ mEpisodeNumber,
+ mEpisodeTitle,
+ mStartTimeUtcMillis,
+ mEndTimeUtcMillis,
+ mBroadcastGenres,
+ mCanonicalGenres,
+ mShortDescription,
+ mLongDescription,
+ mVideoWidth,
+ mVideoHeight,
+ mAudioLanguage,
+ mContentRatings,
+ mPosterArtUri,
+ mThumbnailUri,
+ mSearchable,
+ mDataUri,
+ mDataBytes,
+ mDurationMillis,
+ mExpireTimeUtcMillis,
+ mInternalProviderFlag1,
+ mInternalProviderFlag2,
+ mInternalProviderFlag3,
+ mInternalProviderFlag4,
mVersionNumber);
}
}
- public static Builder builder() { return new Builder(); }
+ public static Builder builder() {
+ return new Builder();
+ }
public static Builder buildFrom(RecordedProgram orig) {
return builder()
@@ -470,7 +504,7 @@ public class RecordedProgram extends BaseProgram {
}
return Long.compare(lhs.mId, rhs.mId);
}
- };
+ };
private static final long CLIPPED_THRESHOLD_MS = TimeUnit.MINUTES.toMillis(5);
@@ -507,15 +541,38 @@ public class RecordedProgram extends BaseProgram {
private final int mInternalProviderFlag4;
private final int mVersionNumber;
- private RecordedProgram(long id, String packageName, String inputId, long channelId,
- String title, String seriesId, String seasonNumber, String seasonTitle,
- String episodeNumber, String episodeTitle, long startTimeUtcMillis,
- long endTimeUtcMillis, String[] broadcastGenres, String[] canonicalGenres,
- String shortDescription, String longDescription, int videoWidth, int videoHeight,
- String audioLanguage, TvContentRating[] contentRatings, String posterArtUri,
- String thumbnailUri, boolean searchable, Uri dataUri, long dataBytes,
- long durationMillis, long expireTimeUtcMillis, int internalProviderFlag1,
- int internalProviderFlag2, int internalProviderFlag3, int internalProviderFlag4,
+ private RecordedProgram(
+ long id,
+ String packageName,
+ String inputId,
+ long channelId,
+ String title,
+ String seriesId,
+ String seasonNumber,
+ String seasonTitle,
+ String episodeNumber,
+ String episodeTitle,
+ long startTimeUtcMillis,
+ long endTimeUtcMillis,
+ String[] broadcastGenres,
+ String[] canonicalGenres,
+ String shortDescription,
+ String longDescription,
+ int videoWidth,
+ int videoHeight,
+ String audioLanguage,
+ TvContentRating[] contentRatings,
+ String posterArtUri,
+ String thumbnailUri,
+ boolean searchable,
+ Uri dataUri,
+ long dataBytes,
+ long durationMillis,
+ long expireTimeUtcMillis,
+ int internalProviderFlag1,
+ int internalProviderFlag2,
+ int internalProviderFlag3,
+ int internalProviderFlag4,
int versionNumber) {
mId = id;
mPackageName = packageName;
@@ -564,9 +621,7 @@ public class RecordedProgram extends BaseProgram {
return mCanonicalGenres;
}
- /**
- * Returns array of canonical genre ID's for this recorded program.
- */
+ /** Returns array of canonical genre ID's for this recorded program. */
@Override
public int[] getCanonicalGenreIds() {
if (mCanonicalGenres == null) {
@@ -623,11 +678,15 @@ public class RecordedProgram extends BaseProgram {
if (!TextUtils.isEmpty(mEpisodeNumber)) {
if (TextUtils.equals(mSeasonNumber, "0")) {
// Do not show "S0: ".
- return String.format(context.getResources().getString(
- R.string.display_episode_number_format_no_season_number), mEpisodeNumber);
+ return String.format(
+ context.getResources()
+ .getString(R.string.display_episode_number_format_no_season_number),
+ mEpisodeNumber);
} else {
- return String.format(context.getResources().getString(
- R.string.display_episode_number_format), mSeasonNumber, mEpisodeNumber);
+ return String.format(
+ context.getResources().getString(R.string.display_episode_number_format),
+ mSeasonNumber,
+ mEpisodeNumber);
}
}
return null;
@@ -734,9 +793,7 @@ public class RecordedProgram extends BaseProgram {
return mVideoWidth;
}
- /**
- * Checks whether the recording has been clipped or not.
- */
+ /** Checks whether the recording has been clipped or not. */
public boolean isClipped() {
return mEndTimeUtcMillis - mStartTimeUtcMillis - mDurationMillis > CLIPPED_THRESHOLD_MS;
}
@@ -746,40 +803,38 @@ public class RecordedProgram extends BaseProgram {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RecordedProgram that = (RecordedProgram) o;
- return Objects.equals(mId, that.mId) &&
- Objects.equals(mChannelId, that.mChannelId) &&
- Objects.equals(mSeriesId, that.mSeriesId) &&
- Objects.equals(mSeasonNumber, that.mSeasonNumber) &&
- Objects.equals(mSeasonTitle, that.mSeasonTitle) &&
- Objects.equals(mEpisodeNumber, that.mEpisodeNumber) &&
- Objects.equals(mStartTimeUtcMillis, that.mStartTimeUtcMillis) &&
- Objects.equals(mEndTimeUtcMillis, that.mEndTimeUtcMillis) &&
- Objects.equals(mVideoWidth, that.mVideoWidth) &&
- Objects.equals(mVideoHeight, that.mVideoHeight) &&
- Objects.equals(mSearchable, that.mSearchable) &&
- Objects.equals(mDataBytes, that.mDataBytes) &&
- Objects.equals(mDurationMillis, that.mDurationMillis) &&
- Objects.equals(mExpireTimeUtcMillis, that.mExpireTimeUtcMillis) &&
- Objects.equals(mInternalProviderFlag1, that.mInternalProviderFlag1) &&
- Objects.equals(mInternalProviderFlag2, that.mInternalProviderFlag2) &&
- Objects.equals(mInternalProviderFlag3, that.mInternalProviderFlag3) &&
- Objects.equals(mInternalProviderFlag4, that.mInternalProviderFlag4) &&
- Objects.equals(mVersionNumber, that.mVersionNumber) &&
- Objects.equals(mTitle, that.mTitle) &&
- Objects.equals(mEpisodeTitle, that.mEpisodeTitle) &&
- Arrays.equals(mBroadcastGenres, that.mBroadcastGenres) &&
- Arrays.equals(mCanonicalGenres, that.mCanonicalGenres) &&
- Objects.equals(mShortDescription, that.mShortDescription) &&
- Objects.equals(mLongDescription, that.mLongDescription) &&
- Objects.equals(mAudioLanguage, that.mAudioLanguage) &&
- Arrays.equals(mContentRatings, that.mContentRatings) &&
- Objects.equals(mPosterArtUri, that.mPosterArtUri) &&
- Objects.equals(mThumbnailUri, that.mThumbnailUri);
- }
-
- /**
- * Hashes based on the ID.
- */
+ return Objects.equals(mId, that.mId)
+ && Objects.equals(mChannelId, that.mChannelId)
+ && Objects.equals(mSeriesId, that.mSeriesId)
+ && Objects.equals(mSeasonNumber, that.mSeasonNumber)
+ && Objects.equals(mSeasonTitle, that.mSeasonTitle)
+ && Objects.equals(mEpisodeNumber, that.mEpisodeNumber)
+ && Objects.equals(mStartTimeUtcMillis, that.mStartTimeUtcMillis)
+ && Objects.equals(mEndTimeUtcMillis, that.mEndTimeUtcMillis)
+ && Objects.equals(mVideoWidth, that.mVideoWidth)
+ && Objects.equals(mVideoHeight, that.mVideoHeight)
+ && Objects.equals(mSearchable, that.mSearchable)
+ && Objects.equals(mDataBytes, that.mDataBytes)
+ && Objects.equals(mDurationMillis, that.mDurationMillis)
+ && Objects.equals(mExpireTimeUtcMillis, that.mExpireTimeUtcMillis)
+ && Objects.equals(mInternalProviderFlag1, that.mInternalProviderFlag1)
+ && Objects.equals(mInternalProviderFlag2, that.mInternalProviderFlag2)
+ && Objects.equals(mInternalProviderFlag3, that.mInternalProviderFlag3)
+ && Objects.equals(mInternalProviderFlag4, that.mInternalProviderFlag4)
+ && Objects.equals(mVersionNumber, that.mVersionNumber)
+ && Objects.equals(mTitle, that.mTitle)
+ && Objects.equals(mEpisodeTitle, that.mEpisodeTitle)
+ && Arrays.equals(mBroadcastGenres, that.mBroadcastGenres)
+ && Arrays.equals(mCanonicalGenres, that.mCanonicalGenres)
+ && Objects.equals(mShortDescription, that.mShortDescription)
+ && Objects.equals(mLongDescription, that.mLongDescription)
+ && Objects.equals(mAudioLanguage, that.mAudioLanguage)
+ && Arrays.equals(mContentRatings, that.mContentRatings)
+ && Objects.equals(mPosterArtUri, that.mPosterArtUri)
+ && Objects.equals(mThumbnailUri, that.mThumbnailUri);
+ }
+
+ /** Hashes based on the ID. */
@Override
public int hashCode() {
return Objects.hash(mId);
@@ -788,42 +843,80 @@ public class RecordedProgram extends BaseProgram {
@Override
public String toString() {
return "RecordedProgram"
- + "[" + mId +
- "]{ mPackageName=" + mPackageName +
- ", mInputId='" + mInputId + '\'' +
- ", mChannelId='" + mChannelId + '\'' +
- ", mTitle='" + mTitle + '\'' +
- ", mSeriesId='" + mSeriesId + '\'' +
- ", mEpisodeNumber=" + mEpisodeNumber +
- ", mEpisodeTitle='" + mEpisodeTitle + '\'' +
- ", mStartTimeUtcMillis=" + mStartTimeUtcMillis +
- ", mEndTimeUtcMillis=" + mEndTimeUtcMillis +
- ", mBroadcastGenres=" +
- (mBroadcastGenres != null ? Arrays.toString(mBroadcastGenres) : "null") +
- ", mCanonicalGenres=" +
- (mCanonicalGenres != null ? Arrays.toString(mCanonicalGenres) : "null") +
- ", mShortDescription='" + mShortDescription + '\'' +
- ", mLongDescription='" + mLongDescription + '\'' +
- ", mVideoHeight=" + mVideoHeight +
- ", mVideoWidth=" + mVideoWidth +
- ", mAudioLanguage='" + mAudioLanguage + '\'' +
- ", mContentRatings='" +
- TvContentRatingCache.contentRatingsToString(mContentRatings) + '\'' +
- ", mPosterArtUri=" + mPosterArtUri +
- ", mThumbnailUri=" + mThumbnailUri +
- ", mSearchable=" + mSearchable +
- ", mDataUri=" + mDataUri +
- ", mDataBytes=" + mDataBytes +
- ", mDurationMillis=" + mDurationMillis +
- ", mExpireTimeUtcMillis=" + mExpireTimeUtcMillis +
- ", mInternalProviderFlag1=" + mInternalProviderFlag1 +
- ", mInternalProviderFlag2=" + mInternalProviderFlag2 +
- ", mInternalProviderFlag3=" + mInternalProviderFlag3 +
- ", mInternalProviderFlag4=" + mInternalProviderFlag4 +
- ", mSeasonNumber=" + mSeasonNumber +
- ", mSeasonTitle=" + mSeasonTitle +
- ", mVersionNumber=" + mVersionNumber +
- '}';
+ + "["
+ + mId
+ + "]{ mPackageName="
+ + mPackageName
+ + ", mInputId='"
+ + mInputId
+ + '\''
+ + ", mChannelId='"
+ + mChannelId
+ + '\''
+ + ", mTitle='"
+ + mTitle
+ + '\''
+ + ", mSeriesId='"
+ + mSeriesId
+ + '\''
+ + ", mEpisodeNumber="
+ + mEpisodeNumber
+ + ", mEpisodeTitle='"
+ + mEpisodeTitle
+ + '\''
+ + ", mStartTimeUtcMillis="
+ + mStartTimeUtcMillis
+ + ", mEndTimeUtcMillis="
+ + mEndTimeUtcMillis
+ + ", mBroadcastGenres="
+ + (mBroadcastGenres != null ? Arrays.toString(mBroadcastGenres) : "null")
+ + ", mCanonicalGenres="
+ + (mCanonicalGenres != null ? Arrays.toString(mCanonicalGenres) : "null")
+ + ", mShortDescription='"
+ + mShortDescription
+ + '\''
+ + ", mLongDescription='"
+ + mLongDescription
+ + '\''
+ + ", mVideoHeight="
+ + mVideoHeight
+ + ", mVideoWidth="
+ + mVideoWidth
+ + ", mAudioLanguage='"
+ + mAudioLanguage
+ + '\''
+ + ", mContentRatings='"
+ + TvContentRatingCache.contentRatingsToString(mContentRatings)
+ + '\''
+ + ", mPosterArtUri="
+ + mPosterArtUri
+ + ", mThumbnailUri="
+ + mThumbnailUri
+ + ", mSearchable="
+ + mSearchable
+ + ", mDataUri="
+ + mDataUri
+ + ", mDataBytes="
+ + mDataBytes
+ + ", mDurationMillis="
+ + mDurationMillis
+ + ", mExpireTimeUtcMillis="
+ + mExpireTimeUtcMillis
+ + ", mInternalProviderFlag1="
+ + mInternalProviderFlag1
+ + ", mInternalProviderFlag2="
+ + mInternalProviderFlag2
+ + ", mInternalProviderFlag3="
+ + mInternalProviderFlag3
+ + ", mInternalProviderFlag4="
+ + mInternalProviderFlag4
+ + ", mSeasonNumber="
+ + mSeasonNumber
+ + ", mSeasonTitle="
+ + mSeasonTitle
+ + ", mVersionNumber="
+ + mVersionNumber
+ + '}';
}
@Nullable
@@ -836,9 +929,7 @@ public class RecordedProgram extends BaseProgram {
return genres == null ? null : TvContract.Programs.Genres.encode(genres);
}
- /**
- * Returns an array containing all of the elements in the list.
- */
+ /** Returns an array containing all of the elements in the list. */
public static RecordedProgram[] toArray(Collection<RecordedProgram> recordedPrograms) {
return recordedPrograms.toArray(new RecordedProgram[recordedPrograms.size()]);
}
diff --git a/src/com/android/tv/dvr/data/ScheduledRecording.java b/src/com/android/tv/dvr/data/ScheduledRecording.java
index 5d11c0f3..7c2d12d9 100644
--- a/src/com/android/tv/dvr/data/ScheduledRecording.java
+++ b/src/com/android/tv/dvr/data/ScheduledRecording.java
@@ -16,107 +16,97 @@
package com.android.tv.dvr.data;
+import android.annotation.TargetApi;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.IntDef;
+import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Range;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
-import com.android.tv.data.Channel;
+import com.android.tv.common.util.CommonUtils;
import com.android.tv.data.Program;
+import com.android.tv.data.api.Channel;
import com.android.tv.dvr.DvrScheduleManager;
import com.android.tv.dvr.provider.DvrContract.Schedules;
import com.android.tv.util.CompositeComparator;
-import com.android.tv.util.Utils;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collection;
import java.util.Comparator;
import java.util.Objects;
-/**
- * A data class for one recording contents.
- */
+/** A data class for one recording contents. */
+@TargetApi(Build.VERSION_CODES.N)
+@SuppressWarnings("AndroidApiChecker") // TODO(b/32513850) remove when error prone is updated
public final class ScheduledRecording implements Parcelable {
private static final String TAG = "ScheduledRecording";
- /**
- * Indicates that the ID is not assigned yet.
- */
+ /** Indicates that the ID is not assigned yet. */
public static final long ID_NOT_SET = 0;
- /**
- * The default priority of the recording.
- */
+ /** The default priority of the recording. */
public static final long DEFAULT_PRIORITY = Long.MAX_VALUE >> 1;
- /**
- * Compares the start time in ascending order.
- */
- public static final Comparator<ScheduledRecording> START_TIME_COMPARATOR
- = new Comparator<ScheduledRecording>() {
- @Override
- public int compare(ScheduledRecording lhs, ScheduledRecording rhs) {
- return Long.compare(lhs.mStartTimeMs, rhs.mStartTimeMs);
- }
- };
-
- /**
- * Compares the end time in ascending order.
- */
- public static final Comparator<ScheduledRecording> END_TIME_COMPARATOR
- = new Comparator<ScheduledRecording>() {
- @Override
- public int compare(ScheduledRecording lhs, ScheduledRecording rhs) {
- return Long.compare(lhs.mEndTimeMs, rhs.mEndTimeMs);
- }
- };
-
- /**
- * Compares ID in ascending order. The schedule with the larger ID was created later.
- */
- public static final Comparator<ScheduledRecording> ID_COMPARATOR
- = new Comparator<ScheduledRecording>() {
- @Override
- public int compare(ScheduledRecording lhs, ScheduledRecording rhs) {
- return Long.compare(lhs.mId, rhs.mId);
- }
- };
-
- /**
- * Compares the priority in ascending order.
- */
- public static final Comparator<ScheduledRecording> PRIORITY_COMPARATOR
- = new Comparator<ScheduledRecording>() {
- @Override
- public int compare(ScheduledRecording lhs, ScheduledRecording rhs) {
- return Long.compare(lhs.mPriority, rhs.mPriority);
- }
- };
+ /** Compares the start time in ascending order. */
+ public static final Comparator<ScheduledRecording> START_TIME_COMPARATOR =
+ new Comparator<ScheduledRecording>() {
+ @Override
+ public int compare(ScheduledRecording lhs, ScheduledRecording rhs) {
+ return Long.compare(lhs.mStartTimeMs, rhs.mStartTimeMs);
+ }
+ };
+
+ /** Compares the end time in ascending order. */
+ public static final Comparator<ScheduledRecording> END_TIME_COMPARATOR =
+ new Comparator<ScheduledRecording>() {
+ @Override
+ public int compare(ScheduledRecording lhs, ScheduledRecording rhs) {
+ return Long.compare(lhs.mEndTimeMs, rhs.mEndTimeMs);
+ }
+ };
+
+ /** Compares ID in ascending order. The schedule with the larger ID was created later. */
+ public static final Comparator<ScheduledRecording> ID_COMPARATOR =
+ new Comparator<ScheduledRecording>() {
+ @Override
+ public int compare(ScheduledRecording lhs, ScheduledRecording rhs) {
+ return Long.compare(lhs.mId, rhs.mId);
+ }
+ };
+
+ /** Compares the priority in ascending order. */
+ public static final Comparator<ScheduledRecording> PRIORITY_COMPARATOR =
+ new Comparator<ScheduledRecording>() {
+ @Override
+ public int compare(ScheduledRecording lhs, ScheduledRecording rhs) {
+ return Long.compare(lhs.mPriority, rhs.mPriority);
+ }
+ };
/**
* Compares start time in ascending order and then priority in descending order and then ID in
* descending order.
*/
- public static final Comparator<ScheduledRecording> START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR
- = new CompositeComparator<>(START_TIME_COMPARATOR, PRIORITY_COMPARATOR.reversed(),
- ID_COMPARATOR.reversed());
+ public static final Comparator<ScheduledRecording> START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR =
+ new CompositeComparator<>(
+ START_TIME_COMPARATOR,
+ PRIORITY_COMPARATOR.reversed(),
+ ID_COMPARATOR.reversed());
- /**
- * Builds scheduled recordings from programs.
- */
+ /** Builds scheduled recordings from programs. */
public static Builder builder(String inputId, Program p) {
return new Builder()
.setInputId(inputId)
.setChannelId(p.getChannelId())
- .setStartTimeMs(p.getStartTimeUtcMillis()).setEndTimeMs(p.getEndTimeUtcMillis())
+ .setStartTimeMs(p.getStartTimeUtcMillis())
+ .setEndTimeMs(p.getEndTimeUtcMillis())
.setProgramId(p.getId())
.setProgramTitle(p.getTitle())
.setSeasonNumber(p.getSeasonNumber())
@@ -138,9 +128,7 @@ public final class ScheduledRecording implements Parcelable {
.setType(TYPE_TIMED);
}
- /**
- * Creates a new Builder with the values set from the {@link RecordedProgram}.
- */
+ /** Creates a new Builder with the values set from the {@link RecordedProgram}. */
public static Builder builder(RecordedProgram p) {
boolean isProgramRecording = !TextUtils.isEmpty(p.getTitle());
return new Builder()
@@ -157,7 +145,8 @@ public final class ScheduledRecording implements Parcelable {
.setProgramLongDescription(p.getLongDescription())
.setProgramPosterArtUri(p.getPosterArtUri())
.setProgramThumbnailUri(p.getThumbnailUri())
- .setState(STATE_RECORDING_FINISHED);
+ .setState(STATE_RECORDING_FINISHED)
+ .setRecordedProgramId(p.getId());
}
public static final class Builder {
@@ -179,8 +168,10 @@ public final class ScheduledRecording implements Parcelable {
private String mProgramThumbnailUri;
private @RecordingState int mState;
private long mSeriesRecordingId = ID_NOT_SET;
+ private Long mRecodedProgramId;
+ private Integer mFailedReason;
- private Builder() { }
+ private Builder() {}
public Builder setId(long id) {
mId = id;
@@ -272,17 +263,42 @@ public final class ScheduledRecording implements Parcelable {
return this;
}
+ public Builder setRecordedProgramId(Long recordedProgramId) {
+ mRecodedProgramId = recordedProgramId;
+ return this;
+ }
+
+ public Builder setFailedReason(Integer reason) {
+ mFailedReason = reason;
+ return this;
+ }
+
public ScheduledRecording build() {
- return new ScheduledRecording(mId, mPriority, mInputId, mChannelId, mProgramId,
- mProgramTitle, mType, mStartTimeMs, mEndTimeMs, mSeasonNumber, mEpisodeNumber,
- mEpisodeTitle, mProgramDescription, mProgramLongDescription,
- mProgramPosterArtUri, mProgramThumbnailUri, mState, mSeriesRecordingId);
+ return new ScheduledRecording(
+ mId,
+ mPriority,
+ mInputId,
+ mChannelId,
+ mProgramId,
+ mProgramTitle,
+ mType,
+ mStartTimeMs,
+ mEndTimeMs,
+ mSeasonNumber,
+ mEpisodeNumber,
+ mEpisodeTitle,
+ mProgramDescription,
+ mProgramLongDescription,
+ mProgramPosterArtUri,
+ mProgramThumbnailUri,
+ mState,
+ mSeriesRecordingId,
+ mRecodedProgramId,
+ mFailedReason);
}
}
- /**
- * Creates {@link Builder} object from the given original {@code Recording}.
- */
+ /** Creates {@link Builder} object from the given original {@code Recording}. */
public static Builder buildFrom(ScheduledRecording orig) {
return new Builder()
.setId(orig.mId)
@@ -301,14 +317,23 @@ public final class ScheduledRecording implements Parcelable {
.setProgramLongDescription(orig.getProgramLongDescription())
.setProgramPosterArtUri(orig.getProgramPosterArtUri())
.setProgramThumbnailUri(orig.getProgramThumbnailUri())
- .setState(orig.mState).setType(orig.mType);
+ .setState(orig.mState)
+ .setFailedReason(orig.getFailedReason())
+ .setType(orig.mType);
}
@Retention(RetentionPolicy.SOURCE)
- @IntDef({STATE_RECORDING_NOT_STARTED, STATE_RECORDING_IN_PROGRESS, STATE_RECORDING_FINISHED,
- STATE_RECORDING_FAILED, STATE_RECORDING_CLIPPED, STATE_RECORDING_DELETED,
- STATE_RECORDING_CANCELED})
+ @IntDef({
+ STATE_RECORDING_NOT_STARTED,
+ STATE_RECORDING_IN_PROGRESS,
+ STATE_RECORDING_FINISHED,
+ STATE_RECORDING_FAILED,
+ STATE_RECORDING_CLIPPED,
+ STATE_RECORDING_DELETED,
+ STATE_RECORDING_CANCELED
+ })
public @interface RecordingState {}
+
public static final int STATE_RECORDING_NOT_STARTED = 0;
public static final int STATE_RECORDING_IN_PROGRESS = 1;
public static final int STATE_RECORDING_FINISHED = 2;
@@ -317,48 +342,74 @@ public final class ScheduledRecording implements Parcelable {
public static final int STATE_RECORDING_DELETED = 5;
public static final int STATE_RECORDING_CANCELED = 6;
+ /** The reasons of failed recordings */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ FAILED_REASON_OTHER,
+ FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED,
+ FAILED_REASON_NOT_FINISHED,
+ FAILED_REASON_SCHEDULER_STOPPED,
+ FAILED_REASON_INVALID_CHANNEL,
+ FAILED_REASON_MESSAGE_NOT_SENT,
+ FAILED_REASON_CONNECTION_FAILED,
+ FAILED_REASON_RESOURCE_BUSY,
+ FAILED_REASON_INPUT_UNAVAILABLE,
+ FAILED_REASON_INPUT_DVR_UNSUPPORTED,
+ FAILED_REASON_INSUFFICIENT_SPACE
+ })
+ public @interface RecordingFailedReason {}
+
+ public static final int FAILED_REASON_OTHER = 0;
+ public static final int FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED = 1;
+ public static final int FAILED_REASON_NOT_FINISHED = 2;
+ public static final int FAILED_REASON_SCHEDULER_STOPPED = 3;
+ public static final int FAILED_REASON_INVALID_CHANNEL = 4;
+ public static final int FAILED_REASON_MESSAGE_NOT_SENT = 5;
+ public static final int FAILED_REASON_CONNECTION_FAILED = 6;
+ public static final int FAILED_REASON_RESOURCE_BUSY = 7;
+ // For the following reasons, show advice to users
+ public static final int FAILED_REASON_INPUT_UNAVAILABLE = 8;
+ public static final int FAILED_REASON_INPUT_DVR_UNSUPPORTED = 9;
+ public static final int FAILED_REASON_INSUFFICIENT_SPACE = 10;
+
@Retention(RetentionPolicy.SOURCE)
@IntDef({TYPE_TIMED, TYPE_PROGRAM})
public @interface RecordingType {}
- /**
- * Record with given time range.
- */
+ /** Record with given time range. */
public static final int TYPE_TIMED = 1;
- /**
- * Record with a given program.
- */
+ /** Record with a given program. */
public static final int TYPE_PROGRAM = 2;
@RecordingType private final int mType;
/**
- * Use this projection if you want to create {@link ScheduledRecording} object using
- * {@link #fromCursor}.
+ * Use this projection if you want to create {@link ScheduledRecording} object using {@link
+ * #fromCursor}.
*/
public static final String[] PROJECTION = {
- // Columns must match what is read in #fromCursor
- Schedules._ID,
- Schedules.COLUMN_PRIORITY,
- Schedules.COLUMN_TYPE,
- Schedules.COLUMN_INPUT_ID,
- Schedules.COLUMN_CHANNEL_ID,
- Schedules.COLUMN_PROGRAM_ID,
- Schedules.COLUMN_PROGRAM_TITLE,
- Schedules.COLUMN_START_TIME_UTC_MILLIS,
- Schedules.COLUMN_END_TIME_UTC_MILLIS,
- Schedules.COLUMN_SEASON_NUMBER,
- Schedules.COLUMN_EPISODE_NUMBER,
- Schedules.COLUMN_EPISODE_TITLE,
- Schedules.COLUMN_PROGRAM_DESCRIPTION,
- Schedules.COLUMN_PROGRAM_LONG_DESCRIPTION,
- Schedules.COLUMN_PROGRAM_POST_ART_URI,
- Schedules.COLUMN_PROGRAM_THUMBNAIL_URI,
- Schedules.COLUMN_STATE,
- Schedules.COLUMN_SERIES_RECORDING_ID};
+ // Columns must match what is read in #fromCursor
+ Schedules._ID,
+ Schedules.COLUMN_PRIORITY,
+ Schedules.COLUMN_TYPE,
+ Schedules.COLUMN_INPUT_ID,
+ Schedules.COLUMN_CHANNEL_ID,
+ Schedules.COLUMN_PROGRAM_ID,
+ Schedules.COLUMN_PROGRAM_TITLE,
+ Schedules.COLUMN_START_TIME_UTC_MILLIS,
+ Schedules.COLUMN_END_TIME_UTC_MILLIS,
+ Schedules.COLUMN_SEASON_NUMBER,
+ Schedules.COLUMN_EPISODE_NUMBER,
+ Schedules.COLUMN_EPISODE_TITLE,
+ Schedules.COLUMN_PROGRAM_DESCRIPTION,
+ Schedules.COLUMN_PROGRAM_LONG_DESCRIPTION,
+ Schedules.COLUMN_PROGRAM_POST_ART_URI,
+ Schedules.COLUMN_PROGRAM_THUMBNAIL_URI,
+ Schedules.COLUMN_STATE,
+ Schedules.COLUMN_FAILED_REASON,
+ Schedules.COLUMN_SERIES_RECORDING_ID
+ };
- /**
- * Creates {@link ScheduledRecording} object from the given {@link Cursor}.
- */
+ /** Creates {@link ScheduledRecording} object from the given {@link Cursor}. */
public static ScheduledRecording fromCursor(Cursor c) {
int index = -1;
return new Builder()
@@ -379,6 +430,7 @@ public final class ScheduledRecording implements Parcelable {
.setProgramPosterArtUri(c.getString(++index))
.setProgramThumbnailUri(c.getString(++index))
.setState(recordingState(c.getString(++index)))
+ .setFailedReason(recordingFailedReason(c.getString(++index)))
.setSeriesRecordingId(c.getLong(++index))
.build();
}
@@ -403,6 +455,7 @@ public final class ScheduledRecording implements Parcelable {
values.put(Schedules.COLUMN_PROGRAM_POST_ART_URI, r.getProgramPosterArtUri());
values.put(Schedules.COLUMN_PROGRAM_THUMBNAIL_URI, r.getProgramThumbnailUri());
values.put(Schedules.COLUMN_STATE, recordingState(r.getState()));
+ values.put(Schedules.COLUMN_FAILED_REASON, recordingFailedReason(r.getFailedReason()));
values.put(Schedules.COLUMN_TYPE, recordingType(r.getType()));
if (r.getSeriesRecordingId() != ID_NOT_SET) {
values.put(Schedules.COLUMN_SERIES_RECORDING_ID, r.getSeriesRecordingId());
@@ -431,42 +484,40 @@ public final class ScheduledRecording implements Parcelable {
.setProgramPosterArtUri(in.readString())
.setProgramThumbnailUri(in.readString())
.setState(in.readInt())
+ .setFailedReason(recordingFailedReason(in.readString()))
.setSeriesRecordingId(in.readLong())
.build();
}
public static final Parcelable.Creator<ScheduledRecording> CREATOR =
new Parcelable.Creator<ScheduledRecording>() {
- @Override
- public ScheduledRecording createFromParcel(Parcel in) {
- return ScheduledRecording.fromParcel(in);
- }
-
- @Override
- public ScheduledRecording[] newArray(int size) {
- return new ScheduledRecording[size];
- }
- };
-
- /**
- * The ID internal to Live TV
- */
+ @Override
+ public ScheduledRecording createFromParcel(Parcel in) {
+ return ScheduledRecording.fromParcel(in);
+ }
+
+ @Override
+ public ScheduledRecording[] newArray(int size) {
+ return new ScheduledRecording[size];
+ }
+ };
+
+ /** The ID internal to Live TV */
private long mId;
/**
* The priority of this recording.
*
- * <p> The highest number is recorded first. If there is a tie in priority then the higher id
+ * <p>The highest number is recorded first. If there is a tie in priority then the higher id
* wins.
*/
private final long mPriority;
private final String mInputId;
private final long mChannelId;
- /**
- * Optional id of the associated program.
- */
+ /** Optional id of the associated program. */
private final long mProgramId;
+
private final String mProgramTitle;
private final long mStartTimeMs;
@@ -480,12 +531,30 @@ public final class ScheduledRecording implements Parcelable {
private final String mProgramThumbnailUri;
@RecordingState private final int mState;
private final long mSeriesRecordingId;
-
- private ScheduledRecording(long id, long priority, String inputId, long channelId, long programId,
- String programTitle, @RecordingType int type, long startTime, long endTime,
- String seasonNumber, String episodeNumber, String episodeTitle,
- String programDescription, String programLongDescription, String programPosterArtUri,
- String programThumbnailUri, @RecordingState int state, long seriesRecordingId) {
+ private final Long mRecordedProgramId;
+ private final Integer mFailedReason;
+
+ private ScheduledRecording(
+ long id,
+ long priority,
+ String inputId,
+ long channelId,
+ long programId,
+ String programTitle,
+ @RecordingType int type,
+ long startTime,
+ long endTime,
+ String seasonNumber,
+ String episodeNumber,
+ String episodeTitle,
+ String programDescription,
+ String programLongDescription,
+ String programPosterArtUri,
+ String programThumbnailUri,
+ @RecordingState int state,
+ long seriesRecordingId,
+ Long recordedProgramId,
+ Integer failedReason) {
mId = id;
mPriority = priority;
mInputId = inputId;
@@ -504,139 +573,122 @@ public final class ScheduledRecording implements Parcelable {
mProgramThumbnailUri = programThumbnailUri;
mState = state;
mSeriesRecordingId = seriesRecordingId;
+ mRecordedProgramId = recordedProgramId;
+ mFailedReason = failedReason;
}
/**
- * Returns recording schedule type. The possible types are {@link #TYPE_PROGRAM} and
- * {@link #TYPE_TIMED}.
+ * Returns recording schedule type. The possible types are {@link #TYPE_PROGRAM} and {@link
+ * #TYPE_TIMED}.
*/
@RecordingType
public int getType() {
return mType;
}
- /**
- * Returns schedules' input id.
- */
+ /** Returns schedules' input id. */
public String getInputId() {
return mInputId;
}
- /**
- * Returns recorded {@link Channel}.
- */
+ /** Returns recorded {@link Channel}. */
public long getChannelId() {
return mChannelId;
}
- /**
- * Return the optional program id
- */
+ /** Return the optional program id */
public long getProgramId() {
return mProgramId;
}
- /**
- * Return the optional program Title
- */
+ /** Return the optional program Title */
public String getProgramTitle() {
return mProgramTitle;
}
- /**
- * Returns started time.
- */
+ /** Returns started time. */
public long getStartTimeMs() {
return mStartTimeMs;
}
- /**
- * Returns ended time.
- */
+ /** Returns ended time. */
public long getEndTimeMs() {
return mEndTimeMs;
}
- /**
- * Returns the season number.
- */
+ /** Returns the season number. */
public String getSeasonNumber() {
return mSeasonNumber;
}
- /**
- * Returns the episode number.
- */
+ /** Returns the episode number. */
public String getEpisodeNumber() {
return mEpisodeNumber;
}
- /**
- * Returns the episode title.
- */
+ /** Returns the episode title. */
public String getEpisodeTitle() {
return mEpisodeTitle;
}
- /**
- * Returns the description of program.
- */
+ /** Returns the description of program. */
public String getProgramDescription() {
return mProgramDescription;
}
- /**
- * Returns the long description of program.
- */
+ /** Returns the long description of program. */
public String getProgramLongDescription() {
return mProgramLongDescription;
}
- /**
- * Returns the poster uri of program.
- */
+ /** Returns the poster uri of program. */
public String getProgramPosterArtUri() {
return mProgramPosterArtUri;
}
- /**
- * Returns the thumb nail uri of program.
- */
+ /** Returns the thumb nail uri of program. */
public String getProgramThumbnailUri() {
return mProgramThumbnailUri;
}
- /**
- * Returns duration.
- */
+ /** Returns duration. */
public long getDuration() {
return mEndTimeMs - mStartTimeMs;
}
/**
- * Returns the state. The possible states are {@link #STATE_RECORDING_NOT_STARTED},
- * {@link #STATE_RECORDING_IN_PROGRESS}, {@link #STATE_RECORDING_FINISHED},
- * {@link #STATE_RECORDING_FAILED}, {@link #STATE_RECORDING_CLIPPED} and
- * {@link #STATE_RECORDING_DELETED}.
+ * Returns the state. The possible states are {@link #STATE_RECORDING_NOT_STARTED}, {@link
+ * #STATE_RECORDING_IN_PROGRESS}, {@link #STATE_RECORDING_FINISHED}, {@link
+ * #STATE_RECORDING_FAILED}, {@link #STATE_RECORDING_CLIPPED} and {@link
+ * #STATE_RECORDING_DELETED}.
*/
- @RecordingState public int getState() {
+ @RecordingState
+ public int getState() {
return mState;
}
- /**
- * Returns the ID of the {@link SeriesRecording} including this schedule.
- */
+ /** Returns the ID of the {@link SeriesRecording} including this schedule. */
public long getSeriesRecordingId() {
return mSeriesRecordingId;
}
+ /** Returns the ID of the corresponding {@link RecordedProgram}. */
+ @Nullable
+ public Long getRecordedProgramId() {
+ return mRecordedProgramId;
+ }
+
+ /** Returns the failed reason of the {@link ScheduledRecording}. */
+ @Nullable @RecordingFailedReason
+ public Integer getFailedReason() {
+ return mFailedReason;
+ }
+
public long getId() {
return mId;
}
- /**
- * Sets the ID;
- */
+ /** Sets the ID; */
public void setId(long id) {
mId = id;
}
@@ -645,21 +697,23 @@ public final class ScheduledRecording implements Parcelable {
return mPriority;
}
- /**
- * Returns season number, episode number and episode title for display.
- */
+ /** Returns season number, episode number and episode title for display. */
public String getEpisodeDisplayTitle(Context context) {
if (!TextUtils.isEmpty(mEpisodeNumber)) {
String episodeTitle = mEpisodeTitle == null ? "" : mEpisodeTitle;
if (TextUtils.equals(mSeasonNumber, "0")) {
// Do not show "S0: ".
- return String.format(context.getResources().getString(
- R.string.display_episode_title_format_no_season_number),
- mEpisodeNumber, episodeTitle);
+ return String.format(
+ context.getResources()
+ .getString(R.string.display_episode_title_format_no_season_number),
+ mEpisodeNumber,
+ episodeTitle);
} else {
- return String.format(context.getResources().getString(
- R.string.display_episode_title_format),
- mSeasonNumber, mEpisodeNumber, episodeTitle);
+ return String.format(
+ context.getResources().getString(R.string.display_episode_title_format),
+ mSeasonNumber,
+ mEpisodeNumber,
+ episodeTitle);
}
}
return mEpisodeTitle;
@@ -673,15 +727,14 @@ public final class ScheduledRecording implements Parcelable {
if (!TextUtils.isEmpty(mProgramTitle)) {
return mProgramTitle;
}
- Channel channel = TvApplication.getSingletons(context).getChannelDataManager()
- .getChannel(mChannelId);
- return channel != null ? channel.getDisplayName()
+ Channel channel =
+ TvSingletons.getSingletons(context).getChannelDataManager().getChannel(mChannelId);
+ return channel != null
+ ? channel.getDisplayName()
: context.getString(R.string.no_program_information);
}
- /**
- * Converts a string to a @RecordingType int, defaulting to {@link #TYPE_TIMED}.
- */
+ /** Converts a string to a @RecordingType int, defaulting to {@link #TYPE_TIMED}. */
private static @RecordingType int recordingType(String type) {
switch (type) {
case Schedules.TYPE_TIMED:
@@ -689,14 +742,12 @@ public final class ScheduledRecording implements Parcelable {
case Schedules.TYPE_PROGRAM:
return TYPE_PROGRAM;
default:
- SoftPreconditions.checkArgument(false, TAG, "Unknown recording type " + type);
+ SoftPreconditions.checkArgument(false, TAG, "Unknown recording type %s", type);
return TYPE_TIMED;
}
}
- /**
- * Converts a @RecordingType int to a string, defaulting to {@link Schedules#TYPE_TIMED}.
- */
+ /** Converts a @RecordingType int to a string, defaulting to {@link Schedules#TYPE_TIMED}. */
private static String recordingType(@RecordingType int type) {
switch (type) {
case TYPE_TIMED:
@@ -704,14 +755,14 @@ public final class ScheduledRecording implements Parcelable {
case TYPE_PROGRAM:
return Schedules.TYPE_PROGRAM;
default:
- SoftPreconditions.checkArgument(false, TAG, "Unknown recording type " + type);
+ SoftPreconditions.checkArgument(false, TAG, "Unknown recording type %s", type);
return Schedules.TYPE_TIMED;
}
}
/**
- * Converts a string to a @RecordingState int, defaulting to
- * {@link #STATE_RECORDING_NOT_STARTED}.
+ * Converts a string to a @RecordingState int, defaulting to {@link
+ * #STATE_RECORDING_NOT_STARTED}.
*/
private static @RecordingState int recordingState(String state) {
switch (state) {
@@ -730,14 +781,14 @@ public final class ScheduledRecording implements Parcelable {
case Schedules.STATE_RECORDING_CANCELED:
return STATE_RECORDING_CANCELED;
default:
- SoftPreconditions.checkArgument(false, TAG, "Unknown recording state" + state);
+ SoftPreconditions.checkArgument(false, TAG, "Unknown recording state %s", state);
return STATE_RECORDING_NOT_STARTED;
}
}
/**
- * Converts a @RecordingState int to string, defaulting to
- * {@link Schedules#STATE_RECORDING_NOT_STARTED}.
+ * Converts a @RecordingState int to string, defaulting to {@link
+ * Schedules#STATE_RECORDING_NOT_STARTED}.
*/
private static String recordingState(@RecordingState int state) {
switch (state) {
@@ -756,46 +807,138 @@ public final class ScheduledRecording implements Parcelable {
case STATE_RECORDING_CANCELED:
return Schedules.STATE_RECORDING_CANCELED;
default:
- SoftPreconditions.checkArgument(false, TAG, "Unknown recording state" + state);
+ SoftPreconditions.checkArgument(false, TAG, "Unknown recording state %s", state);
return Schedules.STATE_RECORDING_NOT_STARTED;
}
}
/**
- * Checks if the {@code period} overlaps with the recording time.
+ * Converts a string to a failed reason integer, defaulting to {@link
+ * #FAILED_REASON_OTHER}.
*/
- public boolean isOverLapping(Range<Long> period) {
- return mStartTimeMs < period.getUpper() && mEndTimeMs > period.getLower();
+ private static Integer recordingFailedReason(String reason) {
+ if (TextUtils.isEmpty(reason)) {
+ return null;
+ }
+ switch (reason) {
+ case Schedules.FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED:
+ return FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED;
+ case Schedules.FAILED_REASON_NOT_FINISHED:
+ return FAILED_REASON_NOT_FINISHED;
+ case Schedules.FAILED_REASON_SCHEDULER_STOPPED:
+ return FAILED_REASON_SCHEDULER_STOPPED;
+ case Schedules.FAILED_REASON_INVALID_CHANNEL:
+ return FAILED_REASON_INVALID_CHANNEL;
+ case Schedules.FAILED_REASON_MESSAGE_NOT_SENT:
+ return FAILED_REASON_MESSAGE_NOT_SENT;
+ case Schedules.FAILED_REASON_CONNECTION_FAILED:
+ return FAILED_REASON_CONNECTION_FAILED;
+ case Schedules.FAILED_REASON_RESOURCE_BUSY:
+ return FAILED_REASON_RESOURCE_BUSY;
+ case Schedules.FAILED_REASON_INPUT_UNAVAILABLE:
+ return FAILED_REASON_INPUT_UNAVAILABLE;
+ case Schedules.FAILED_REASON_INPUT_DVR_UNSUPPORTED:
+ return FAILED_REASON_INPUT_DVR_UNSUPPORTED;
+ case Schedules.FAILED_REASON_INSUFFICIENT_SPACE:
+ return FAILED_REASON_INSUFFICIENT_SPACE;
+ case Schedules.FAILED_REASON_OTHER:
+ default:
+ return FAILED_REASON_OTHER;
+ }
}
/**
- * Checks if the {@code schedule} overlaps with this schedule.
+ * Converts a failed reason integer to string, defaulting to {@link
+ * Schedules#FAILED_REASON_OTHER}.
*/
+ private static String recordingFailedReason(Integer reason) {
+ if (reason == null) {
+ return null;
+ }
+ switch (reason) {
+ case FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED:
+ return Schedules.FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED;
+ case FAILED_REASON_NOT_FINISHED:
+ return Schedules.FAILED_REASON_NOT_FINISHED;
+ case FAILED_REASON_SCHEDULER_STOPPED:
+ return Schedules.FAILED_REASON_SCHEDULER_STOPPED;
+ case FAILED_REASON_INVALID_CHANNEL:
+ return Schedules.FAILED_REASON_INVALID_CHANNEL;
+ case FAILED_REASON_MESSAGE_NOT_SENT:
+ return Schedules.FAILED_REASON_MESSAGE_NOT_SENT;
+ case FAILED_REASON_CONNECTION_FAILED:
+ return Schedules.FAILED_REASON_CONNECTION_FAILED;
+ case FAILED_REASON_RESOURCE_BUSY:
+ return Schedules.FAILED_REASON_RESOURCE_BUSY;
+ case FAILED_REASON_INPUT_UNAVAILABLE:
+ return Schedules.FAILED_REASON_INPUT_UNAVAILABLE;
+ case FAILED_REASON_INPUT_DVR_UNSUPPORTED:
+ return Schedules.FAILED_REASON_INPUT_DVR_UNSUPPORTED;
+ case FAILED_REASON_INSUFFICIENT_SPACE:
+ return Schedules.FAILED_REASON_INSUFFICIENT_SPACE;
+ case FAILED_REASON_OTHER: // fall through
+ default:
+ return Schedules.FAILED_REASON_OTHER;
+ }
+ }
+
+ /** Checks if the {@code period} overlaps with the recording time. */
+ public boolean isOverLapping(Range<Long> period) {
+ return mStartTimeMs < period.getUpper() && mEndTimeMs > period.getLower();
+ }
+
+ /** Checks if the {@code schedule} overlaps with this schedule. */
public boolean isOverLapping(ScheduledRecording schedule) {
return mStartTimeMs < schedule.getEndTimeMs() && mEndTimeMs > schedule.getStartTimeMs();
}
@Override
public String toString() {
- return "ScheduledRecording[" + mId
+ return "ScheduledRecording["
+ + mId
+ "]"
- + "(inputId=" + mInputId
- + ",channelId=" + mChannelId
- + ",programId=" + mProgramId
- + ",programTitle=" + mProgramTitle
- + ",type=" + mType
- + ",startTime=" + Utils.toIsoDateTimeString(mStartTimeMs) + "(" + mStartTimeMs + ")"
- + ",endTime=" + Utils.toIsoDateTimeString(mEndTimeMs) + "(" + mEndTimeMs + ")"
- + ",seasonNumber=" + mSeasonNumber
- + ",episodeNumber=" + mEpisodeNumber
- + ",episodeTitle=" + mEpisodeTitle
- + ",programDescription=" + mProgramDescription
- + ",programLongDescription=" + mProgramLongDescription
- + ",programPosterArtUri=" + mProgramPosterArtUri
- + ",programThumbnailUri=" + mProgramThumbnailUri
- + ",state=" + mState
- + ",priority=" + mPriority
- + ",seriesRecordingId=" + mSeriesRecordingId
+ + "(inputId="
+ + mInputId
+ + ",channelId="
+ + mChannelId
+ + ",programId="
+ + mProgramId
+ + ",programTitle="
+ + mProgramTitle
+ + ",type="
+ + mType
+ + ",startTime="
+ + CommonUtils.toIsoDateTimeString(mStartTimeMs)
+ + "("
+ + mStartTimeMs
+ + ")"
+ + ",endTime="
+ + CommonUtils.toIsoDateTimeString(mEndTimeMs)
+ + "("
+ + mEndTimeMs
+ + ")"
+ + ",seasonNumber="
+ + mSeasonNumber
+ + ",episodeNumber="
+ + mEpisodeNumber
+ + ",episodeTitle="
+ + mEpisodeTitle
+ + ",programDescription="
+ + mProgramDescription
+ + ",programLongDescription="
+ + mProgramLongDescription
+ + ",programPosterArtUri="
+ + mProgramPosterArtUri
+ + ",programThumbnailUri="
+ + mProgramThumbnailUri
+ + ",state="
+ + mState
+ + ",failedReason="
+ + mFailedReason
+ + ",priority="
+ + mPriority
+ + ",seriesRecordingId="
+ + mSeriesRecordingId
+ ")";
}
@@ -823,23 +966,25 @@ public final class ScheduledRecording implements Parcelable {
out.writeString(mProgramPosterArtUri);
out.writeString(mProgramThumbnailUri);
out.writeInt(mState);
+ out.writeString(recordingFailedReason(mFailedReason));
out.writeLong(mSeriesRecordingId);
}
- /**
- * Returns {@code true} if the recording is not started yet, otherwise @{code false}.
- */
+ /** Returns {@code true} if the recording is not started yet, otherwise @{code false}. */
public boolean isNotStarted() {
return mState == STATE_RECORDING_NOT_STARTED;
}
- /**
- * Returns {@code true} if the recording is in progress, otherwise @{code false}.
- */
+ /** Returns {@code true} if the recording is in progress, otherwise @{code false}. */
public boolean isInProgress() {
return mState == STATE_RECORDING_IN_PROGRESS;
}
+ /** Returns {@code true} if the recording is finished, otherwise @{code false}. */
+ public boolean isFinished() {
+ return mState == STATE_RECORDING_FINISHED;
+ }
+
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ScheduledRecording)) {
@@ -862,20 +1007,34 @@ public final class ScheduledRecording implements Parcelable {
&& Objects.equals(mProgramPosterArtUri, r.getProgramPosterArtUri())
&& Objects.equals(mProgramThumbnailUri, r.getProgramThumbnailUri())
&& mState == r.mState
+ && Objects.equals(mFailedReason, r.mFailedReason)
&& mSeriesRecordingId == r.mSeriesRecordingId;
}
@Override
public int hashCode() {
- return Objects.hash(mId, mPriority, mChannelId, mProgramId, mProgramTitle, mType,
- mStartTimeMs, mEndTimeMs, mSeasonNumber, mEpisodeNumber, mEpisodeTitle,
- mProgramDescription, mProgramLongDescription, mProgramPosterArtUri,
- mProgramThumbnailUri, mState, mSeriesRecordingId);
+ return Objects.hash(
+ mId,
+ mPriority,
+ mChannelId,
+ mProgramId,
+ mProgramTitle,
+ mType,
+ mStartTimeMs,
+ mEndTimeMs,
+ mSeasonNumber,
+ mEpisodeNumber,
+ mEpisodeTitle,
+ mProgramDescription,
+ mProgramLongDescription,
+ mProgramPosterArtUri,
+ mProgramThumbnailUri,
+ mState,
+ mFailedReason,
+ mSeriesRecordingId);
}
- /**
- * Returns an array containing all of the elements in the list.
- */
+ /** Returns an array containing all of the elements in the list. */
public static ScheduledRecording[] toArray(Collection<ScheduledRecording> schedules) {
return schedules.toArray(new ScheduledRecording[schedules.size()]);
}
diff --git a/src/com/android/tv/dvr/data/SeasonEpisodeNumber.java b/src/com/android/tv/dvr/data/SeasonEpisodeNumber.java
index 89533dbb..c697451a 100644
--- a/src/com/android/tv/dvr/data/SeasonEpisodeNumber.java
+++ b/src/com/android/tv/dvr/data/SeasonEpisodeNumber.java
@@ -17,20 +17,15 @@
package com.android.tv.dvr.data;
import android.text.TextUtils;
-
import java.util.Objects;
-/**
- * A plain java object which includes the season/episode number for the series recording.
- */
+/** A plain java object which includes the season/episode number for the series recording. */
public class SeasonEpisodeNumber {
public final long seriesRecordingId;
public final String seasonNumber;
public final String episodeNumber;
- /**
- * Creates a new Builder with the values set from an existing {@link ScheduledRecording}.
- */
+ /** Creates a new Builder with the values set from an existing {@link ScheduledRecording}. */
public SeasonEpisodeNumber(ScheduledRecording r) {
this(r.getSeriesRecordingId(), r.getSeasonNumber(), r.getEpisodeNumber());
}
@@ -47,7 +42,8 @@ public class SeasonEpisodeNumber {
return true;
}
if (!(o instanceof SeasonEpisodeNumber)
- || TextUtils.isEmpty(seasonNumber) || TextUtils.isEmpty(episodeNumber)) {
+ || TextUtils.isEmpty(seasonNumber)
+ || TextUtils.isEmpty(episodeNumber)) {
return false;
}
SeasonEpisodeNumber that = (SeasonEpisodeNumber) o;
@@ -63,10 +59,13 @@ public class SeasonEpisodeNumber {
@Override
public String toString() {
- return "SeasonEpisodeNumber{" +
- "seriesRecordingId=" + seriesRecordingId +
- ", seasonNumber='" + seasonNumber +
- ", episodeNumber=" + episodeNumber +
- '}';
+ return "SeasonEpisodeNumber{"
+ + "seriesRecordingId="
+ + seriesRecordingId
+ + ", seasonNumber='"
+ + seasonNumber
+ + ", episodeNumber="
+ + episodeNumber
+ + '}';
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/data/SeriesInfo.java b/src/com/android/tv/dvr/data/SeriesInfo.java
index a0dec4a4..aa622c3d 100644
--- a/src/com/android/tv/dvr/data/SeriesInfo.java
+++ b/src/com/android/tv/dvr/data/SeriesInfo.java
@@ -16,9 +16,7 @@
package com.android.tv.dvr.data;
-/**
- * Series information.
- */
+/** Series information. */
public class SeriesInfo {
private final String mId;
private final String mTitle;
@@ -28,8 +26,14 @@ public class SeriesInfo {
private final String mPosterUri;
private final String mPhotoUri;
- public SeriesInfo(String id, String title, String description, String longDescription,
- int[] canonicalGenreIds, String posterUri, String photoUri) {
+ public SeriesInfo(
+ String id,
+ String title,
+ String description,
+ String longDescription,
+ int[] canonicalGenreIds,
+ String posterUri,
+ String photoUri) {
this.mId = id;
this.mTitle = title;
this.mDescription = description;
@@ -39,37 +43,37 @@ public class SeriesInfo {
this.mPhotoUri = photoUri;
}
- /** Returns the ID. **/
+ /** Returns the ID. * */
public String getId() {
return mId;
}
- /** Returns the title. **/
+ /** Returns the title. * */
public String getTitle() {
return mTitle;
}
- /** Returns the description. **/
+ /** Returns the description. * */
public String getDescription() {
return mDescription;
}
- /** Returns the description. **/
+ /** Returns the description. * */
public String getLongDescription() {
return mLongDescription;
}
- /** Returns the canonical genre IDs. **/
+ /** Returns the canonical genre IDs. * */
public int[] getCanonicalGenreIds() {
return mCanonicalGenreIds;
}
- /** Returns the poster URI. **/
+ /** Returns the poster URI. * */
public String getPosterUri() {
return mPosterUri;
}
- /** Returns the photo URI. **/
+ /** Returns the photo URI. * */
public String getPhotoUri() {
return mPhotoUri;
}
diff --git a/src/com/android/tv/dvr/data/SeriesRecording.java b/src/com/android/tv/dvr/data/SeriesRecording.java
index 822e7320..96b3425a 100644
--- a/src/com/android/tv/dvr/data/SeriesRecording.java
+++ b/src/com/android/tv/dvr/data/SeriesRecording.java
@@ -21,15 +21,12 @@ import android.database.Cursor;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.IntDef;
-import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
-
import com.android.tv.data.BaseProgram;
import com.android.tv.data.Program;
import com.android.tv.dvr.DvrScheduleManager;
import com.android.tv.dvr.provider.DvrContract.SeriesRecordings;
import com.android.tv.util.Utils;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
@@ -40,68 +37,55 @@ import java.util.Objects;
/**
* Schedules the recording of a Series of Programs.
*
- * <p>
- * Contains the data needed to create new ScheduleRecordings as the programs become available in
+ * <p>Contains the data needed to create new ScheduleRecordings as the programs become available in
* the EPG.
*/
public class SeriesRecording implements Parcelable {
- /**
- * Indicates that the ID is not assigned yet.
- */
+ /** Indicates that the ID is not assigned yet. */
public static final long ID_NOT_SET = 0;
- /**
- * The default priority of this recording.
- */
+ /** The default priority of this recording. */
public static final long DEFAULT_PRIORITY = Long.MAX_VALUE >> 1;
@Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true,
- value = {OPTION_CHANNEL_ONE, OPTION_CHANNEL_ALL})
+ @IntDef(
+ flag = true,
+ value = {OPTION_CHANNEL_ONE, OPTION_CHANNEL_ALL}
+ )
public @interface ChannelOption {}
- /**
- * An option which indicates that the episodes in one channel are recorded.
- */
+ /** An option which indicates that the episodes in one channel are recorded. */
public static final int OPTION_CHANNEL_ONE = 0;
- /**
- * An option which indicates that the episodes in all the channels are recorded.
- */
+ /** An option which indicates that the episodes in all the channels are recorded. */
public static final int OPTION_CHANNEL_ALL = 1;
@Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true,
- value = {STATE_SERIES_NORMAL, STATE_SERIES_STOPPED})
+ @IntDef(
+ flag = true,
+ value = {STATE_SERIES_NORMAL, STATE_SERIES_STOPPED}
+ )
public @interface SeriesState {}
- /**
- * The state indicates that the series recording is a normal one.
- */
+ /** The state indicates that the series recording is a normal one. */
public static final int STATE_SERIES_NORMAL = 0;
- /**
- * The state indicates that the series recording is stopped.
- */
+ /** The state indicates that the series recording is stopped. */
public static final int STATE_SERIES_STOPPED = 1;
- /**
- * Compare priority in descending order.
- */
+ /** Compare priority in descending order. */
public static final Comparator<SeriesRecording> PRIORITY_COMPARATOR =
new Comparator<SeriesRecording>() {
- @Override
- public int compare(SeriesRecording lhs, SeriesRecording rhs) {
- int value = Long.compare(rhs.mPriority, lhs.mPriority);
- if (value == 0) {
- // New recording has the higher priority.
- value = Long.compare(rhs.mId, lhs.mId);
- }
- return value;
- }
- };
+ @Override
+ public int compare(SeriesRecording lhs, SeriesRecording rhs) {
+ int value = Long.compare(rhs.mPriority, lhs.mPriority);
+ if (value == 0) {
+ // New recording has the higher priority.
+ value = Long.compare(rhs.mId, lhs.mId);
+ }
+ return value;
+ }
+ };
- /**
- * Compare ID in ascending order.
- */
+ /** Compare ID in ascending order. */
public static final Comparator<SeriesRecording> ID_COMPARATOR =
new Comparator<SeriesRecording>() {
@Override
@@ -126,9 +110,7 @@ public class SeriesRecording implements Parcelable {
.setPhotoUri(p.getThumbnailUri());
}
- /**
- * Creates a new Builder with the values set from an existing {@link SeriesRecording}.
- */
+ /** Creates a new Builder with the values set from an existing {@link SeriesRecording}. */
public static Builder buildFrom(SeriesRecording r) {
return new Builder()
.setId(r.mId)
@@ -149,30 +131,28 @@ public class SeriesRecording implements Parcelable {
}
/**
- * Use this projection if you want to create {@link SeriesRecording} object using
- * {@link #fromCursor}.
+ * Use this projection if you want to create {@link SeriesRecording} object using {@link
+ * #fromCursor}.
*/
public static final String[] PROJECTION = {
- // Columns must match what is read in fromCursor()
- SeriesRecordings._ID,
- SeriesRecordings.COLUMN_INPUT_ID,
- SeriesRecordings.COLUMN_CHANNEL_ID,
- SeriesRecordings.COLUMN_PRIORITY,
- SeriesRecordings.COLUMN_TITLE,
- SeriesRecordings.COLUMN_SHORT_DESCRIPTION,
- SeriesRecordings.COLUMN_LONG_DESCRIPTION,
- SeriesRecordings.COLUMN_SERIES_ID,
- SeriesRecordings.COLUMN_START_FROM_EPISODE,
- SeriesRecordings.COLUMN_START_FROM_SEASON,
- SeriesRecordings.COLUMN_CHANNEL_OPTION,
- SeriesRecordings.COLUMN_CANONICAL_GENRE,
- SeriesRecordings.COLUMN_POSTER_URI,
- SeriesRecordings.COLUMN_PHOTO_URI,
- SeriesRecordings.COLUMN_STATE
+ // Columns must match what is read in fromCursor()
+ SeriesRecordings._ID,
+ SeriesRecordings.COLUMN_INPUT_ID,
+ SeriesRecordings.COLUMN_CHANNEL_ID,
+ SeriesRecordings.COLUMN_PRIORITY,
+ SeriesRecordings.COLUMN_TITLE,
+ SeriesRecordings.COLUMN_SHORT_DESCRIPTION,
+ SeriesRecordings.COLUMN_LONG_DESCRIPTION,
+ SeriesRecordings.COLUMN_SERIES_ID,
+ SeriesRecordings.COLUMN_START_FROM_EPISODE,
+ SeriesRecordings.COLUMN_START_FROM_SEASON,
+ SeriesRecordings.COLUMN_CHANNEL_OPTION,
+ SeriesRecordings.COLUMN_CANONICAL_GENRE,
+ SeriesRecordings.COLUMN_POSTER_URI,
+ SeriesRecordings.COLUMN_PHOTO_URI,
+ SeriesRecordings.COLUMN_STATE
};
- /**
- * Creates {@link SeriesRecording} object from the given {@link Cursor}.
- */
+ /** Creates {@link SeriesRecording} object from the given {@link Cursor}. */
public static SeriesRecording fromCursor(Cursor c) {
int index = -1;
return new Builder()
@@ -195,8 +175,8 @@ public class SeriesRecording implements Parcelable {
}
/**
- * Returns the ContentValues with keys as the columns specified in {@link SeriesRecordings}
- * and the values from {@code r}.
+ * Returns the ContentValues with keys as the columns specified in {@link SeriesRecordings} and
+ * the values from {@code r}.
*/
public static ContentValues toContentValues(SeriesRecording r) {
ContentValues values = new ContentValues();
@@ -214,9 +194,9 @@ public class SeriesRecording implements Parcelable {
values.put(SeriesRecordings.COLUMN_SERIES_ID, r.getSeriesId());
values.put(SeriesRecordings.COLUMN_START_FROM_EPISODE, r.getStartFromEpisode());
values.put(SeriesRecordings.COLUMN_START_FROM_SEASON, r.getStartFromSeason());
- values.put(SeriesRecordings.COLUMN_CHANNEL_OPTION,
- channelOption(r.getChannelOption()));
- values.put(SeriesRecordings.COLUMN_CANONICAL_GENRE,
+ values.put(SeriesRecordings.COLUMN_CHANNEL_OPTION, channelOption(r.getChannelOption()));
+ values.put(
+ SeriesRecordings.COLUMN_CANONICAL_GENRE,
Utils.getCanonicalGenre(r.getCanonicalGenreIds()));
values.put(SeriesRecordings.COLUMN_POSTER_URI, r.getPosterUri());
values.put(SeriesRecordings.COLUMN_PHOTO_URI, r.getPhotoUri());
@@ -234,7 +214,8 @@ public class SeriesRecording implements Parcelable {
return SeriesRecordings.OPTION_CHANNEL_ONE;
}
- @ChannelOption private static int channelOption(String option) {
+ @ChannelOption
+ private static int channelOption(String option) {
switch (option) {
case SeriesRecordings.OPTION_CHANNEL_ONE:
return OPTION_CHANNEL_ONE;
@@ -254,7 +235,8 @@ public class SeriesRecording implements Parcelable {
return SeriesRecordings.STATE_SERIES_NORMAL;
}
- @SeriesState private static int seriesRecordingState(String state) {
+ @SeriesState
+ private static int seriesRecordingState(String state) {
switch (state) {
case SeriesRecordings.STATE_SERIES_NORMAL:
return STATE_SERIES_NORMAL;
@@ -264,9 +246,7 @@ public class SeriesRecording implements Parcelable {
return STATE_SERIES_NORMAL;
}
- /**
- * Builder for {@link SeriesRecording}.
- */
+ /** Builder for {@link SeriesRecording}. */
public static class Builder {
private long mId = ID_NOT_SET;
private long mPriority = DvrScheduleManager.DEFAULT_SERIES_PRIORITY;
@@ -284,141 +264,120 @@ public class SeriesRecording implements Parcelable {
private String mPhotoUri;
private int mState = SeriesRecording.STATE_SERIES_NORMAL;
- /**
- * @see #getId()
- */
+ /** @see #getId() */
public Builder setId(long id) {
mId = id;
return this;
}
- /**
- * @see #getPriority() ()
- */
+ /** @see #getPriority() () */
public Builder setPriority(long priority) {
mPriority = priority;
return this;
}
- /**
- * @see #getTitle()
- */
+ /** @see #getTitle() */
public Builder setTitle(String title) {
mTitle = title;
return this;
}
- /**
- * @see #getDescription()
- */
+ /** @see #getDescription() */
public Builder setDescription(String description) {
mDescription = description;
return this;
}
- /**
- * @see #getLongDescription()
- */
+ /** @see #getLongDescription() */
public Builder setLongDescription(String longDescription) {
mLongDescription = longDescription;
return this;
}
- /**
- * @see #getInputId()
- */
+ /** @see #getInputId() */
public Builder setInputId(String inputId) {
mInputId = inputId;
return this;
}
- /**
- * @see #getChannelId()
- */
+ /** @see #getChannelId() */
public Builder setChannelId(long channelId) {
mChannelId = channelId;
return this;
}
- /**
- * @see #getSeriesId()
- */
+ /** @see #getSeriesId() */
public Builder setSeriesId(String seriesId) {
mSeriesId = seriesId;
return this;
}
- /**
- * @see #getStartFromSeason()
- */
+ /** @see #getStartFromSeason() */
public Builder setStartFromSeason(int startFromSeason) {
mStartFromSeason = startFromSeason;
return this;
}
- /**
- * @see #getChannelOption()
- */
+ /** @see #getChannelOption() */
public Builder setChannelOption(@ChannelOption int option) {
mChannelOption = option;
return this;
}
- /**
- * @see #getStartFromEpisode()
- */
+ /** @see #getStartFromEpisode() */
public Builder setStartFromEpisode(int startFromEpisode) {
mStartFromEpisode = startFromEpisode;
return this;
}
- /**
- * @see #getCanonicalGenreIds()
- */
+ /** @see #getCanonicalGenreIds() */
public Builder setCanonicalGenreIds(String genres) {
mCanonicalGenreIds = Utils.getCanonicalGenreIds(genres);
return this;
}
- /**
- * @see #getCanonicalGenreIds()
- */
+ /** @see #getCanonicalGenreIds() */
public Builder setCanonicalGenreIds(int[] canonicalGenreIds) {
mCanonicalGenreIds = canonicalGenreIds;
return this;
}
- /**
- * @see #getPosterUri()
- */
+ /** @see #getPosterUri() */
public Builder setPosterUri(String posterUri) {
mPosterUri = posterUri;
return this;
}
- /**
- * @see #getPhotoUri()
- */
+ /** @see #getPhotoUri() */
public Builder setPhotoUri(String photoUri) {
mPhotoUri = photoUri;
return this;
}
- /**
- * @see #getState()
- */
+ /** @see #getState() */
public Builder setState(@SeriesState int state) {
mState = state;
return this;
}
- /**
- * Creates a new {@link SeriesRecording}.
- */
+ /** Creates a new {@link SeriesRecording}. */
public SeriesRecording build() {
- return new SeriesRecording(mId, mPriority, mTitle, mDescription, mLongDescription,
- mInputId, mChannelId, mSeriesId, mStartFromSeason, mStartFromEpisode,
- mChannelOption, mCanonicalGenreIds, mPosterUri, mPhotoUri, mState);
+ return new SeriesRecording(
+ mId,
+ mPriority,
+ mTitle,
+ mDescription,
+ mLongDescription,
+ mInputId,
+ mChannelId,
+ mSeriesId,
+ mStartFromSeason,
+ mStartFromEpisode,
+ mChannelOption,
+ mCanonicalGenreIds,
+ mPosterUri,
+ mPhotoUri,
+ mState);
}
}
@@ -444,16 +403,16 @@ public class SeriesRecording implements Parcelable {
public static final Parcelable.Creator<SeriesRecording> CREATOR =
new Parcelable.Creator<SeriesRecording>() {
- @Override
- public SeriesRecording createFromParcel(Parcel in) {
- return SeriesRecording.fromParcel(in);
- }
+ @Override
+ public SeriesRecording createFromParcel(Parcel in) {
+ return SeriesRecording.fromParcel(in);
+ }
- @Override
- public SeriesRecording[] newArray(int size) {
- return new SeriesRecording[size];
- }
- };
+ @Override
+ public SeriesRecording[] newArray(int size) {
+ return new SeriesRecording[size];
+ }
+ };
private long mId;
private final long mPriority;
@@ -471,9 +430,7 @@ public class SeriesRecording implements Parcelable {
private final String mPhotoUri;
@SeriesState private int mState;
- /**
- * The input id of this SeriesRecording.
- */
+ /** The input id of this SeriesRecording. */
public String getInputId() {
return mInputId;
}
@@ -485,16 +442,12 @@ public class SeriesRecording implements Parcelable {
return mChannelId;
}
- /**
- * The id of this SeriesRecording.
- */
+ /** The id of this SeriesRecording. */
public long getId() {
return mId;
}
- /**
- * Sets the ID.
- */
+ /** Sets the ID. */
public void setId(long id) {
mId = id;
}
@@ -502,30 +455,24 @@ public class SeriesRecording implements Parcelable {
/**
* The priority of this recording.
*
- * <p> The highest number is recorded first. If there is a tie in mPriority then the higher mId
+ * <p>The highest number is recorded first. If there is a tie in mPriority then the higher mId
* wins.
*/
public long getPriority() {
return mPriority;
}
- /**
- * The series title.
- */
+ /** The series title. */
public String getTitle() {
return mTitle;
}
- /**
- * The series description.
- */
+ /** The series description. */
public String getDescription() {
return mDescription;
}
- /**
- * The long series description.
- */
+ /** The long series description. */
public String getLongDescription() {
return mLongDescription;
}
@@ -555,44 +502,34 @@ public class SeriesRecording implements Parcelable {
return mStartFromSeason;
}
- /**
- * Returns the channel recording option.
- */
- @ChannelOption public int getChannelOption() {
+ /** Returns the channel recording option. */
+ @ChannelOption
+ public int getChannelOption() {
return mChannelOption;
}
- /**
- * Returns the canonical genre ID's.
- */
+ /** Returns the canonical genre ID's. */
public int[] getCanonicalGenreIds() {
return mCanonicalGenreIds;
}
- /**
- * Returns the poster URI.
- */
+ /** Returns the poster URI. */
public String getPosterUri() {
return mPosterUri;
}
- /**
- * Returns the photo URI.
- */
+ /** Returns the photo URI. */
public String getPhotoUri() {
return mPhotoUri;
}
- /**
- * Returns the state of series recording.
- */
- @SeriesState public int getState() {
+ /** Returns the state of series recording. */
+ @SeriesState
+ public int getState() {
return mState;
}
- /**
- * Checks whether the series recording is stopped or not.
- */
+ /** Checks whether the series recording is stopped or not. */
public boolean isStopped() {
return mState == STATE_SERIES_STOPPED;
}
@@ -620,35 +557,77 @@ public class SeriesRecording implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(mPriority, mChannelId, mStartFromSeason, mStartFromEpisode, mId,
- mTitle, mDescription, mLongDescription, mSeriesId, mChannelOption,
- mCanonicalGenreIds, mPosterUri, mPhotoUri, mState);
+ return Objects.hash(
+ mPriority,
+ mChannelId,
+ mStartFromSeason,
+ mStartFromEpisode,
+ mId,
+ mTitle,
+ mDescription,
+ mLongDescription,
+ mSeriesId,
+ mChannelOption,
+ Arrays.hashCode(mCanonicalGenreIds),
+ mPosterUri,
+ mPhotoUri,
+ mState);
}
@Override
public String toString() {
- return "SeriesRecording{" +
- "inputId=" + mInputId +
- ", channelId=" + mChannelId +
- ", id='" + mId + '\'' +
- ", priority=" + mPriority +
- ", title='" + mTitle + '\'' +
- ", description='" + mDescription + '\'' +
- ", longDescription='" + mLongDescription + '\'' +
- ", startFromSeason=" + mStartFromSeason +
- ", startFromEpisode=" + mStartFromEpisode +
- ", channelOption=" + mChannelOption +
- ", canonicalGenreIds=" + Arrays.toString(mCanonicalGenreIds) +
- ", posterUri=" + mPosterUri +
- ", photoUri=" + mPhotoUri +
- ", state=" + mState +
- '}';
- }
-
- private SeriesRecording(long id, long priority, String title, String description,
- String longDescription, String inputId, long channelId, String seriesId,
- int startFromSeason, int startFromEpisode, int channelOption, int[] canonicalGenreIds,
- String posterUri, String photoUri, int state) {
+ return "SeriesRecording{"
+ + "inputId="
+ + mInputId
+ + ", channelId="
+ + mChannelId
+ + ", id='"
+ + mId
+ + '\''
+ + ", priority="
+ + mPriority
+ + ", title='"
+ + mTitle
+ + '\''
+ + ", description='"
+ + mDescription
+ + '\''
+ + ", longDescription='"
+ + mLongDescription
+ + '\''
+ + ", startFromSeason="
+ + mStartFromSeason
+ + ", startFromEpisode="
+ + mStartFromEpisode
+ + ", channelOption="
+ + mChannelOption
+ + ", canonicalGenreIds="
+ + Arrays.toString(mCanonicalGenreIds)
+ + ", posterUri="
+ + mPosterUri
+ + ", photoUri="
+ + mPhotoUri
+ + ", state="
+ + mState
+ + '}';
+ }
+
+ private SeriesRecording(
+ long id,
+ long priority,
+ String title,
+ String description,
+ String longDescription,
+ String inputId,
+ long channelId,
+ String seriesId,
+ int startFromSeason,
+ int startFromEpisode,
+ int channelOption,
+ int[] canonicalGenreIds,
+ String posterUri,
+ String photoUri,
+ int state) {
this.mId = id;
this.mPriority = priority;
this.mTitle = title;
@@ -690,9 +669,7 @@ public class SeriesRecording implements Parcelable {
out.writeInt(mState);
}
- /**
- * Returns an array containing all of the elements in the list.
- */
+ /** Returns an array containing all of the elements in the list. */
public static SeriesRecording[] toArray(Collection<SeriesRecording> series) {
return series.toArray(new SeriesRecording[series.size()]);
}
@@ -715,16 +692,16 @@ public class SeriesRecording implements Parcelable {
long channelId = program.getChannelId();
String seasonNumber = program.getSeasonNumber();
String episodeNumber = program.getEpisodeNumber();
- if (!mSeriesId.equals(seriesId) || (channelOption == SeriesRecording.OPTION_CHANNEL_ONE
- && mChannelId != channelId)) {
+ if (!mSeriesId.equals(seriesId)
+ || (channelOption == SeriesRecording.OPTION_CHANNEL_ONE
+ && mChannelId != channelId)) {
return false;
}
// Season number and episode number matches if
// start_season_number < program_season_number
// || (start_season_number == program_season_number
// && start_episode_number <= program_episode_number).
- if (mStartFromSeason == SeriesRecordings.THE_BEGINNING
- || TextUtils.isEmpty(seasonNumber)) {
+ if (mStartFromSeason == SeriesRecordings.THE_BEGINNING || TextUtils.isEmpty(seasonNumber)) {
return true;
} else {
int intSeasonNumber;
diff --git a/src/com/android/tv/dvr/provider/AsyncDvrDbTask.java b/src/com/android/tv/dvr/provider/AsyncDvrDbTask.java
index c5383d02..7d2af9c3 100644
--- a/src/com/android/tv/dvr/provider/AsyncDvrDbTask.java
+++ b/src/com/android/tv/dvr/provider/AsyncDvrDbTask.java
@@ -20,27 +20,23 @@ import android.content.Context;
import android.database.Cursor;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
-
+import com.android.tv.common.concurrent.NamedThreadFactory;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.dvr.provider.DvrContract.Schedules;
import com.android.tv.dvr.provider.DvrContract.SeriesRecordings;
-import com.android.tv.util.NamedThreadFactory;
-
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-/**
- * {@link AsyncTask} that defaults to executing on its own single threaded Executor Service.
- */
+/** {@link AsyncTask} that defaults to executing on its own single threaded Executor Service. */
public abstract class AsyncDvrDbTask<Params, Progress, Result>
extends AsyncTask<Params, Progress, Result> {
- private static final NamedThreadFactory THREAD_FACTORY = new NamedThreadFactory(
- AsyncDvrDbTask.class.getSimpleName());
- private static final ExecutorService DB_EXECUTOR = Executors
- .newSingleThreadExecutor(THREAD_FACTORY);
+ private static final NamedThreadFactory THREAD_FACTORY =
+ new NamedThreadFactory(AsyncDvrDbTask.class.getSimpleName());
+ private static final ExecutorService DB_EXECUTOR =
+ Executors.newSingleThreadExecutor(THREAD_FACTORY);
private static DvrDatabaseHelper sDbHelper;
@@ -57,9 +53,7 @@ public abstract class AsyncDvrDbTask<Params, Progress, Result>
mContext = context;
}
- /**
- * Execute the task on the {@link #DB_EXECUTOR} thread.
- */
+ /** Execute the task on the {@link #DB_EXECUTOR} thread. */
@SafeVarargs
public final void executeOnDbThread(Params... params) {
executeOnExecutor(DB_EXECUTOR, params);
@@ -71,15 +65,11 @@ public abstract class AsyncDvrDbTask<Params, Progress, Result>
return doInDvrBackground(params);
}
- /**
- * Executes in the background after {@link #initializeDbHelper(Context)}
- */
+ /** Executes in the background after {@link #initializeDbHelper(Context)} */
@Nullable
protected abstract Result doInDvrBackground(Params... params);
- /**
- * Inserts schedules.
- */
+ /** Inserts schedules. */
public static class AsyncAddScheduleTask
extends AsyncDvrDbTask<ScheduledRecording, Void, Void> {
public AsyncAddScheduleTask(Context context) {
@@ -93,9 +83,7 @@ public abstract class AsyncDvrDbTask<Params, Progress, Result>
}
}
- /**
- * Update schedules.
- */
+ /** Update schedules. */
public static class AsyncUpdateScheduleTask
extends AsyncDvrDbTask<ScheduledRecording, Void, Void> {
public AsyncUpdateScheduleTask(Context context) {
@@ -109,9 +97,7 @@ public abstract class AsyncDvrDbTask<Params, Progress, Result>
}
}
- /**
- * Delete schedules.
- */
+ /** Delete schedules. */
public static class AsyncDeleteScheduleTask
extends AsyncDvrDbTask<ScheduledRecording, Void, Void> {
public AsyncDeleteScheduleTask(Context context) {
@@ -125,9 +111,7 @@ public abstract class AsyncDvrDbTask<Params, Progress, Result>
}
}
- /**
- * Returns all {@link ScheduledRecording}s.
- */
+ /** Returns all {@link ScheduledRecording}s. */
public abstract static class AsyncDvrQueryScheduleTask
extends AsyncDvrDbTask<Void, Void, List<ScheduledRecording>> {
public AsyncDvrQueryScheduleTask(Context context) {
@@ -150,9 +134,7 @@ public abstract class AsyncDvrDbTask<Params, Progress, Result>
}
}
- /**
- * Inserts series recordings.
- */
+ /** Inserts series recordings. */
public static class AsyncAddSeriesRecordingTask
extends AsyncDvrDbTask<SeriesRecording, Void, Void> {
public AsyncAddSeriesRecordingTask(Context context) {
@@ -166,9 +148,7 @@ public abstract class AsyncDvrDbTask<Params, Progress, Result>
}
}
- /**
- * Update series recordings.
- */
+ /** Update series recordings. */
public static class AsyncUpdateSeriesRecordingTask
extends AsyncDvrDbTask<SeriesRecording, Void, Void> {
public AsyncUpdateSeriesRecordingTask(Context context) {
@@ -182,9 +162,7 @@ public abstract class AsyncDvrDbTask<Params, Progress, Result>
}
}
- /**
- * Delete series recordings.
- */
+ /** Delete series recordings. */
public static class AsyncDeleteSeriesRecordingTask
extends AsyncDvrDbTask<SeriesRecording, Void, Void> {
public AsyncDeleteSeriesRecordingTask(Context context) {
@@ -198,9 +176,7 @@ public abstract class AsyncDvrDbTask<Params, Progress, Result>
}
}
- /**
- * Returns all {@link SeriesRecording}s.
- */
+ /** Returns all {@link SeriesRecording}s. */
public abstract static class AsyncDvrQuerySeriesRecordingTask
extends AsyncDvrDbTask<Void, Void, List<SeriesRecording>> {
public AsyncDvrQuerySeriesRecordingTask(Context context) {
@@ -214,8 +190,8 @@ public abstract class AsyncDvrDbTask<Params, Progress, Result>
return null;
}
List<SeriesRecording> scheduledRecordings = new ArrayList<>();
- try (Cursor c = sDbHelper.query(SeriesRecordings.TABLE_NAME,
- SeriesRecording.PROJECTION)) {
+ try (Cursor c =
+ sDbHelper.query(SeriesRecordings.TABLE_NAME, SeriesRecording.PROJECTION)) {
while (c.moveToNext() && !isCancelled()) {
scheduledRecordings.add(SeriesRecording.fromCursor(c));
}
diff --git a/src/com/android/tv/dvr/provider/DvrContract.java b/src/com/android/tv/dvr/provider/DvrContract.java
index f0aca18e..a5f2e2cd 100644
--- a/src/com/android/tv/dvr/provider/DvrContract.java
+++ b/src/com/android/tv/dvr/provider/DvrContract.java
@@ -55,11 +55,57 @@ public final class DvrContract {
/** The recording marked as canceled. */
public static final String STATE_RECORDING_CANCELED = "STATE_RECORDING_CANCELED";
+ /** The recording failed reason for other reasons */
+ public static final String FAILED_REASON_OTHER = "FAILED_REASON_OTHER";
+
+ /** The recording failed because the program ended before recording started. */
+ public static final String FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED =
+ "FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED";
+
+ /** The recording failed because it was not finished successfully */
+ public static final String FAILED_REASON_NOT_FINISHED = "FAILED_REASON_NOT_FINISHED";
+
+ /** The recording failed because the channel ID was invalid */
+ public static final String FAILED_REASON_INVALID_CHANNEL = "FAILED_REASON_INVALID_CHANNEL";
+
+ /** The recording failed because the scheduler was stopped */
+ public static final String FAILED_REASON_SCHEDULER_STOPPED
+ = "FAILED_REASON_SCHEDULER_STOPPED";
+
+ /** The recording failed because some messages were not sent to the message queue */
+ public static final String FAILED_REASON_MESSAGE_NOT_SENT =
+ "FAILED_REASON_MESSAGE_NOT_SENT";
+
+ /**
+ * The recording failed because it was failed to establish a connection to the recording
+ * session for the corresponding TV input.
+ */
+ public static final String FAILED_REASON_CONNECTION_FAILED =
+ "FAILED_REASON_CONNECTION_FAILED";
+
+ /**
+ * The recording failed because a required recording resource was not able to be
+ * allocated.
+ */
+ public static final String FAILED_REASON_RESOURCE_BUSY = "FAILED_REASON_RESOURCE_BUSY";
+
+ /** The recording failed because the input was not available */
+ public static final String FAILED_REASON_INPUT_UNAVAILABLE =
+ "FAILED_REASON_INPUT_UNAVAILABLE";
+
+ /** The recording failed because the input doesn't support recording */
+ public static final String FAILED_REASON_INPUT_DVR_UNSUPPORTED =
+ "FAILED_REASON_INPUT_DVR_UNSUPPORTED";
+
+ /** The recording failed because the space was not sufficient */
+ public static final String FAILED_REASON_INSUFFICIENT_SPACE =
+ "FAILED_REASON_INSUFFICIENT_SPACE";
+
/**
* The priority of this recording.
*
- * <p> The lowest number is recorded first. If there is a tie in priority then the lower id
- * wins. Defaults to {@value Long#MAX_VALUE}
+ * <p>The lowest number is recorded first. If there is a tie in priority then the lower id
+ * wins. Defaults to {@value Long#MAX_VALUE}
*
* <p>Type: INTEGER (long)
*/
@@ -68,8 +114,8 @@ public final class DvrContract {
/**
* The type of this recording.
*
- * <p>This value should be one of the followings: {@link #TYPE_PROGRAM} and
- * {@link #TYPE_TIMED}.
+ * <p>This value should be one of the followings: {@link #TYPE_PROGRAM} and {@link
+ * #TYPE_TIMED}.
*
* <p>This is a required field.
*
@@ -184,9 +230,9 @@ public final class DvrContract {
* The state of this recording.
*
* <p>This value should be one of the followings: {@link #STATE_RECORDING_NOT_STARTED},
- * {@link #STATE_RECORDING_IN_PROGRESS}, {@link #STATE_RECORDING_FINISHED},
- * {@link #STATE_RECORDING_FAILED}, {@link #STATE_RECORDING_CLIPPED} and
- * {@link #STATE_RECORDING_DELETED}.
+ * {@link #STATE_RECORDING_IN_PROGRESS}, {@link #STATE_RECORDING_FINISHED}, {@link
+ * #STATE_RECORDING_FAILED}, {@link #STATE_RECORDING_CLIPPED} and {@link
+ * #STATE_RECORDING_DELETED}.
*
* <p>This is a required field.
*
@@ -195,13 +241,20 @@ public final class DvrContract {
public static final String COLUMN_STATE = "state";
/**
+ * The reason of failure of this recording if it's failed.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_FAILED_REASON = "failed_reason";
+
+ /**
* The ID of the parent series recording.
*
* <p>Type: INTEGER (long)
*/
public static final String COLUMN_SERIES_RECORDING_ID = "series_recording_id";
- private Schedules() { }
+ private Schedules() {}
}
/** Column definition for Recording table. */
@@ -210,8 +263,8 @@ public final class DvrContract {
public static final String TABLE_NAME = "series_recording";
/**
- * This value is used for {@link #COLUMN_START_FROM_SEASON} and
- * {@link #COLUMN_START_FROM_EPISODE} to mean record all seasons or episodes.
+ * This value is used for {@link #COLUMN_START_FROM_SEASON} and {@link
+ * #COLUMN_START_FROM_EPISODE} to mean record all seasons or episodes.
*/
public static final int THE_BEGINNING = -1;
@@ -227,21 +280,17 @@ public final class DvrContract {
*/
public static final String OPTION_CHANNEL_ALL = "OPTION_CHANNEL_ALL";
- /**
- * The state indicates that it is a normal one.
- */
+ /** The state indicates that it is a normal one. */
public static final String STATE_SERIES_NORMAL = "STATE_SERIES_NORMAL";
- /**
- * The state indicates that it is stopped.
- */
+ /** The state indicates that it is stopped. */
public static final String STATE_SERIES_STOPPED = "STATE_SERIES_STOPPED";
/**
* The priority of this recording.
*
- * <p> The lowest number is recorded first. If there is a tie in priority then the lower id
- * wins. Defaults to {@value Long#MAX_VALUE}
+ * <p>The lowest number is recorded first. If there is a tie in priority then the lower id
+ * wins. Defaults to {@value Long#MAX_VALUE}
*
* <p>Type: INTEGER (long)
*/
@@ -266,7 +315,7 @@ public final class DvrContract {
public static final String COLUMN_CHANNEL_ID = "channel_id";
/**
- * The ID of the associated series to record.
+ * The ID of the associated series to record.
*
* <p>The id is an opaque but stable string.
*
@@ -300,8 +349,8 @@ public final class DvrContract {
public static final String COLUMN_LONG_DESCRIPTION = "long_description";
/**
- * The number of the earliest season to record. The
- * value {@link #THE_BEGINNING} means record all seasons.
+ * The number of the earliest season to record. The value {@link #THE_BEGINNING} means
+ * record all seasons.
*
* <p>Default value is {@value #THE_BEGINNING} {@link #THE_BEGINNING}.
*
@@ -310,7 +359,7 @@ public final class DvrContract {
public static final String COLUMN_START_FROM_SEASON = "start_from_season";
/**
- * The number of the earliest episode to record in {@link #COLUMN_START_FROM_SEASON}. The
+ * The number of the earliest episode to record in {@link #COLUMN_START_FROM_SEASON}. The
* value {@link #THE_BEGINNING} means record all episodes.
*
* <p>Default value is {@value #THE_BEGINNING} {@link #THE_BEGINNING}.
@@ -322,8 +371,8 @@ public final class DvrContract {
/**
* The series recording option which indicates the channels to record.
*
- * <p>This value should be one of the followings: {@link #OPTION_CHANNEL_ONE} and
- * {@link #OPTION_CHANNEL_ALL}. The default value is OPTION_CHANNEL_ONE.
+ * <p>This value should be one of the followings: {@link #OPTION_CHANNEL_ONE} and {@link
+ * #OPTION_CHANNEL_ALL}. The default value is OPTION_CHANNEL_ONE.
*
* <p>Type: TEXT
*/
@@ -338,6 +387,7 @@ public final class DvrContract {
* to get the canonical genre strings from the text stored in the column.
*
* <p>Type: TEXT
+ *
* @see android.media.tv.TvContract.Programs.Genres
* @see android.media.tv.TvContract.Programs.Genres#encode
* @see android.media.tv.TvContract.Programs.Genres#decode
@@ -350,10 +400,9 @@ public final class DvrContract {
* <p>The data in the column must be a URL, or a URI in one of the following formats:
*
* <ul>
- * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
- * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
- * </li>
- * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
+ * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})
+ * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
+ * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})
* </ul>
*
* <p>Type: TEXT
@@ -366,10 +415,9 @@ public final class DvrContract {
* <p>The data in the column must be a URL, or a URI in one of the following formats:
*
* <ul>
- * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
- * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
- * </li>
- * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
+ * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})
+ * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
+ * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})
* </ul>
*
* <p>Type: TEXT
@@ -379,15 +427,15 @@ public final class DvrContract {
/**
* The state of whether the series recording be canceled or not.
*
- * <p>This value should be one of the followings: {@link #STATE_SERIES_NORMAL} and
- * {@link #STATE_SERIES_STOPPED}. The default value is STATE_SERIES_NORMAL.
+ * <p>This value should be one of the followings: {@link #STATE_SERIES_NORMAL} and {@link
+ * #STATE_SERIES_STOPPED}. The default value is STATE_SERIES_NORMAL.
*
* <p>Type: TEXT
*/
public static final String COLUMN_STATE = "state";
- private SeriesRecordings() { }
+ private SeriesRecordings() {}
}
- private DvrContract() { }
+ private DvrContract() {}
}
diff --git a/src/com/android/tv/dvr/provider/DvrDatabaseHelper.java b/src/com/android/tv/dvr/provider/DvrDatabaseHelper.java
index 8b9481a9..41e5a66a 100644
--- a/src/com/android/tv/dvr/provider/DvrDatabaseHelper.java
+++ b/src/com/android/tv/dvr/provider/DvrDatabaseHelper.java
@@ -26,98 +26,145 @@ import android.database.sqlite.SQLiteStatement;
import android.provider.BaseColumns;
import android.text.TextUtils;
import android.util.Log;
-
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.dvr.provider.DvrContract.Schedules;
import com.android.tv.dvr.provider.DvrContract.SeriesRecordings;
-/**
- * A data class for one recorded contents.
- */
+/** A data class for one recorded contents. */
public class DvrDatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "DvrDatabaseHelper";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
- private static final int DATABASE_VERSION = 17;
+ private static final int DATABASE_VERSION = 18;
private static final String DB_NAME = "dvr.db";
private static final String SQL_CREATE_SCHEDULES =
- "CREATE TABLE " + Schedules.TABLE_NAME + "("
- + Schedules._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
- + Schedules.COLUMN_PRIORITY + " INTEGER DEFAULT "
- + ScheduledRecording.DEFAULT_PRIORITY + ","
- + Schedules.COLUMN_TYPE + " TEXT NOT NULL,"
- + Schedules.COLUMN_INPUT_ID + " TEXT NOT NULL,"
- + Schedules.COLUMN_CHANNEL_ID + " INTEGER NOT NULL,"
- + Schedules.COLUMN_PROGRAM_ID + " INTEGER,"
- + Schedules.COLUMN_PROGRAM_TITLE + " TEXT,"
- + Schedules.COLUMN_START_TIME_UTC_MILLIS + " INTEGER NOT NULL,"
- + Schedules.COLUMN_END_TIME_UTC_MILLIS + " INTEGER NOT NULL,"
- + Schedules.COLUMN_SEASON_NUMBER + " TEXT,"
- + Schedules.COLUMN_EPISODE_NUMBER + " TEXT,"
- + Schedules.COLUMN_EPISODE_TITLE + " TEXT,"
- + Schedules.COLUMN_PROGRAM_DESCRIPTION + " TEXT,"
- + Schedules.COLUMN_PROGRAM_LONG_DESCRIPTION + " TEXT,"
- + Schedules.COLUMN_PROGRAM_POST_ART_URI + " TEXT,"
- + Schedules.COLUMN_PROGRAM_THUMBNAIL_URI + " TEXT,"
- + Schedules.COLUMN_STATE + " TEXT NOT NULL,"
- + Schedules.COLUMN_SERIES_RECORDING_ID + " INTEGER,"
- + "FOREIGN KEY(" + Schedules.COLUMN_SERIES_RECORDING_ID + ") "
- + "REFERENCES " + SeriesRecordings.TABLE_NAME
- + "(" + SeriesRecordings._ID + ") "
+ "CREATE TABLE "
+ + Schedules.TABLE_NAME
+ + "("
+ + Schedules._ID
+ + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ + Schedules.COLUMN_PRIORITY
+ + " INTEGER DEFAULT "
+ + ScheduledRecording.DEFAULT_PRIORITY
+ + ","
+ + Schedules.COLUMN_TYPE
+ + " TEXT NOT NULL,"
+ + Schedules.COLUMN_INPUT_ID
+ + " TEXT NOT NULL,"
+ + Schedules.COLUMN_CHANNEL_ID
+ + " INTEGER NOT NULL,"
+ + Schedules.COLUMN_PROGRAM_ID
+ + " INTEGER,"
+ + Schedules.COLUMN_PROGRAM_TITLE
+ + " TEXT,"
+ + Schedules.COLUMN_START_TIME_UTC_MILLIS
+ + " INTEGER NOT NULL,"
+ + Schedules.COLUMN_END_TIME_UTC_MILLIS
+ + " INTEGER NOT NULL,"
+ + Schedules.COLUMN_SEASON_NUMBER
+ + " TEXT,"
+ + Schedules.COLUMN_EPISODE_NUMBER
+ + " TEXT,"
+ + Schedules.COLUMN_EPISODE_TITLE
+ + " TEXT,"
+ + Schedules.COLUMN_PROGRAM_DESCRIPTION
+ + " TEXT,"
+ + Schedules.COLUMN_PROGRAM_LONG_DESCRIPTION
+ + " TEXT,"
+ + Schedules.COLUMN_PROGRAM_POST_ART_URI
+ + " TEXT,"
+ + Schedules.COLUMN_PROGRAM_THUMBNAIL_URI
+ + " TEXT,"
+ + Schedules.COLUMN_STATE
+ + " TEXT NOT NULL,"
+ + Schedules.COLUMN_SERIES_RECORDING_ID
+ + " INTEGER,"
+ + "FOREIGN KEY("
+ + Schedules.COLUMN_SERIES_RECORDING_ID
+ + ") "
+ + "REFERENCES "
+ + SeriesRecordings.TABLE_NAME
+ + "("
+ + SeriesRecordings._ID
+ + ") "
+ "ON UPDATE CASCADE ON DELETE SET NULL);";
private static final String SQL_DROP_SCHEDULES = "DROP TABLE IF EXISTS " + Schedules.TABLE_NAME;
private static final String SQL_CREATE_SERIES_RECORDINGS =
- "CREATE TABLE " + SeriesRecordings.TABLE_NAME + "("
- + SeriesRecordings._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
- + SeriesRecordings.COLUMN_PRIORITY + " INTEGER DEFAULT "
- + SeriesRecording.DEFAULT_PRIORITY + ","
- + SeriesRecordings.COLUMN_TITLE + " TEXT NOT NULL,"
- + SeriesRecordings.COLUMN_SHORT_DESCRIPTION + " TEXT,"
- + SeriesRecordings.COLUMN_LONG_DESCRIPTION + " TEXT,"
- + SeriesRecordings.COLUMN_INPUT_ID + " TEXT NOT NULL,"
- + SeriesRecordings.COLUMN_CHANNEL_ID + " INTEGER NOT NULL,"
- + SeriesRecordings.COLUMN_SERIES_ID + " TEXT NOT NULL,"
- + SeriesRecordings.COLUMN_START_FROM_SEASON + " INTEGER DEFAULT "
- + SeriesRecordings.THE_BEGINNING + ","
- + SeriesRecordings.COLUMN_START_FROM_EPISODE + " INTEGER DEFAULT "
- + SeriesRecordings.THE_BEGINNING + ","
- + SeriesRecordings.COLUMN_CHANNEL_OPTION + " TEXT DEFAULT "
- + SeriesRecordings.OPTION_CHANNEL_ONE + ","
- + SeriesRecordings.COLUMN_CANONICAL_GENRE + " TEXT,"
- + SeriesRecordings.COLUMN_POSTER_URI + " TEXT,"
- + SeriesRecordings.COLUMN_PHOTO_URI + " TEXT,"
- + SeriesRecordings.COLUMN_STATE + " TEXT)";
+ "CREATE TABLE "
+ + SeriesRecordings.TABLE_NAME
+ + "("
+ + SeriesRecordings._ID
+ + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ + SeriesRecordings.COLUMN_PRIORITY
+ + " INTEGER DEFAULT "
+ + SeriesRecording.DEFAULT_PRIORITY
+ + ","
+ + SeriesRecordings.COLUMN_TITLE
+ + " TEXT NOT NULL,"
+ + SeriesRecordings.COLUMN_SHORT_DESCRIPTION
+ + " TEXT,"
+ + SeriesRecordings.COLUMN_LONG_DESCRIPTION
+ + " TEXT,"
+ + SeriesRecordings.COLUMN_INPUT_ID
+ + " TEXT NOT NULL,"
+ + SeriesRecordings.COLUMN_CHANNEL_ID
+ + " INTEGER NOT NULL,"
+ + SeriesRecordings.COLUMN_SERIES_ID
+ + " TEXT NOT NULL,"
+ + SeriesRecordings.COLUMN_START_FROM_SEASON
+ + " INTEGER DEFAULT "
+ + SeriesRecordings.THE_BEGINNING
+ + ","
+ + SeriesRecordings.COLUMN_START_FROM_EPISODE
+ + " INTEGER DEFAULT "
+ + SeriesRecordings.THE_BEGINNING
+ + ","
+ + SeriesRecordings.COLUMN_CHANNEL_OPTION
+ + " TEXT DEFAULT "
+ + SeriesRecordings.OPTION_CHANNEL_ONE
+ + ","
+ + SeriesRecordings.COLUMN_CANONICAL_GENRE
+ + " TEXT,"
+ + SeriesRecordings.COLUMN_POSTER_URI
+ + " TEXT,"
+ + SeriesRecordings.COLUMN_PHOTO_URI
+ + " TEXT,"
+ + SeriesRecordings.COLUMN_STATE
+ + " TEXT)";
- private static final String SQL_DROP_SERIES_RECORDINGS = "DROP TABLE IF EXISTS " +
- SeriesRecordings.TABLE_NAME;
+ private static final String SQL_DROP_SERIES_RECORDINGS =
+ "DROP TABLE IF EXISTS " + SeriesRecordings.TABLE_NAME;
private static final int SQL_DATA_TYPE_LONG = 0;
private static final int SQL_DATA_TYPE_INT = 1;
private static final int SQL_DATA_TYPE_STRING = 2;
- private static final ColumnInfo[] COLUMNS_SCHEDULES = new ColumnInfo[] {
- new ColumnInfo(Schedules._ID, SQL_DATA_TYPE_LONG),
- new ColumnInfo(Schedules.COLUMN_PRIORITY, SQL_DATA_TYPE_LONG),
- new ColumnInfo(Schedules.COLUMN_TYPE, SQL_DATA_TYPE_STRING),
- new ColumnInfo(Schedules.COLUMN_INPUT_ID, SQL_DATA_TYPE_STRING),
- new ColumnInfo(Schedules.COLUMN_CHANNEL_ID, SQL_DATA_TYPE_LONG),
- new ColumnInfo(Schedules.COLUMN_PROGRAM_ID, SQL_DATA_TYPE_LONG),
- new ColumnInfo(Schedules.COLUMN_PROGRAM_TITLE, SQL_DATA_TYPE_STRING),
- new ColumnInfo(Schedules.COLUMN_START_TIME_UTC_MILLIS, SQL_DATA_TYPE_LONG),
- new ColumnInfo(Schedules.COLUMN_END_TIME_UTC_MILLIS, SQL_DATA_TYPE_LONG),
- new ColumnInfo(Schedules.COLUMN_SEASON_NUMBER, SQL_DATA_TYPE_STRING),
- new ColumnInfo(Schedules.COLUMN_EPISODE_NUMBER, SQL_DATA_TYPE_STRING),
- new ColumnInfo(Schedules.COLUMN_EPISODE_TITLE, SQL_DATA_TYPE_STRING),
- new ColumnInfo(Schedules.COLUMN_PROGRAM_DESCRIPTION, SQL_DATA_TYPE_STRING),
- new ColumnInfo(Schedules.COLUMN_PROGRAM_LONG_DESCRIPTION, SQL_DATA_TYPE_STRING),
- new ColumnInfo(Schedules.COLUMN_PROGRAM_POST_ART_URI, SQL_DATA_TYPE_STRING),
- new ColumnInfo(Schedules.COLUMN_PROGRAM_THUMBNAIL_URI, SQL_DATA_TYPE_STRING),
- new ColumnInfo(Schedules.COLUMN_STATE, SQL_DATA_TYPE_STRING),
- new ColumnInfo(Schedules.COLUMN_SERIES_RECORDING_ID, SQL_DATA_TYPE_LONG)};
+ private static final ColumnInfo[] COLUMNS_SCHEDULES =
+ new ColumnInfo[] {
+ new ColumnInfo(Schedules._ID, SQL_DATA_TYPE_LONG),
+ new ColumnInfo(Schedules.COLUMN_PRIORITY, SQL_DATA_TYPE_LONG),
+ new ColumnInfo(Schedules.COLUMN_TYPE, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(Schedules.COLUMN_INPUT_ID, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(Schedules.COLUMN_CHANNEL_ID, SQL_DATA_TYPE_LONG),
+ new ColumnInfo(Schedules.COLUMN_PROGRAM_ID, SQL_DATA_TYPE_LONG),
+ new ColumnInfo(Schedules.COLUMN_PROGRAM_TITLE, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(Schedules.COLUMN_START_TIME_UTC_MILLIS, SQL_DATA_TYPE_LONG),
+ new ColumnInfo(Schedules.COLUMN_END_TIME_UTC_MILLIS, SQL_DATA_TYPE_LONG),
+ new ColumnInfo(Schedules.COLUMN_SEASON_NUMBER, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(Schedules.COLUMN_EPISODE_NUMBER, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(Schedules.COLUMN_EPISODE_TITLE, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(Schedules.COLUMN_PROGRAM_DESCRIPTION, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(Schedules.COLUMN_PROGRAM_LONG_DESCRIPTION, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(Schedules.COLUMN_PROGRAM_POST_ART_URI, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(Schedules.COLUMN_PROGRAM_THUMBNAIL_URI, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(Schedules.COLUMN_STATE, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(Schedules.COLUMN_FAILED_REASON, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(Schedules.COLUMN_SERIES_RECORDING_ID, SQL_DATA_TYPE_LONG)
+ };
private static final String SQL_INSERT_SCHEDULES =
buildInsertSql(Schedules.TABLE_NAME, COLUMNS_SCHEDULES);
@@ -125,22 +172,24 @@ public class DvrDatabaseHelper extends SQLiteOpenHelper {
buildUpdateSql(Schedules.TABLE_NAME, COLUMNS_SCHEDULES);
private static final String SQL_DELETE_SCHEDULES = buildDeleteSql(Schedules.TABLE_NAME);
- private static final ColumnInfo[] COLUMNS_SERIES_RECORDINGS = new ColumnInfo[] {
- new ColumnInfo(SeriesRecordings._ID, SQL_DATA_TYPE_LONG),
- new ColumnInfo(SeriesRecordings.COLUMN_PRIORITY, SQL_DATA_TYPE_LONG),
- new ColumnInfo(SeriesRecordings.COLUMN_INPUT_ID, SQL_DATA_TYPE_STRING),
- new ColumnInfo(SeriesRecordings.COLUMN_CHANNEL_ID, SQL_DATA_TYPE_LONG),
- new ColumnInfo(SeriesRecordings.COLUMN_SERIES_ID, SQL_DATA_TYPE_STRING),
- new ColumnInfo(SeriesRecordings.COLUMN_TITLE, SQL_DATA_TYPE_STRING),
- new ColumnInfo(SeriesRecordings.COLUMN_SHORT_DESCRIPTION, SQL_DATA_TYPE_STRING),
- new ColumnInfo(SeriesRecordings.COLUMN_LONG_DESCRIPTION, SQL_DATA_TYPE_STRING),
- new ColumnInfo(SeriesRecordings.COLUMN_START_FROM_SEASON, SQL_DATA_TYPE_INT),
- new ColumnInfo(SeriesRecordings.COLUMN_START_FROM_EPISODE, SQL_DATA_TYPE_INT),
- new ColumnInfo(SeriesRecordings.COLUMN_CHANNEL_OPTION, SQL_DATA_TYPE_STRING),
- new ColumnInfo(SeriesRecordings.COLUMN_CANONICAL_GENRE, SQL_DATA_TYPE_STRING),
- new ColumnInfo(SeriesRecordings.COLUMN_POSTER_URI, SQL_DATA_TYPE_STRING),
- new ColumnInfo(SeriesRecordings.COLUMN_PHOTO_URI, SQL_DATA_TYPE_STRING),
- new ColumnInfo(SeriesRecordings.COLUMN_STATE, SQL_DATA_TYPE_STRING)};
+ private static final ColumnInfo[] COLUMNS_SERIES_RECORDINGS =
+ new ColumnInfo[] {
+ new ColumnInfo(SeriesRecordings._ID, SQL_DATA_TYPE_LONG),
+ new ColumnInfo(SeriesRecordings.COLUMN_PRIORITY, SQL_DATA_TYPE_LONG),
+ new ColumnInfo(SeriesRecordings.COLUMN_INPUT_ID, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(SeriesRecordings.COLUMN_CHANNEL_ID, SQL_DATA_TYPE_LONG),
+ new ColumnInfo(SeriesRecordings.COLUMN_SERIES_ID, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(SeriesRecordings.COLUMN_TITLE, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(SeriesRecordings.COLUMN_SHORT_DESCRIPTION, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(SeriesRecordings.COLUMN_LONG_DESCRIPTION, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(SeriesRecordings.COLUMN_START_FROM_SEASON, SQL_DATA_TYPE_INT),
+ new ColumnInfo(SeriesRecordings.COLUMN_START_FROM_EPISODE, SQL_DATA_TYPE_INT),
+ new ColumnInfo(SeriesRecordings.COLUMN_CHANNEL_OPTION, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(SeriesRecordings.COLUMN_CANONICAL_GENRE, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(SeriesRecordings.COLUMN_POSTER_URI, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(SeriesRecordings.COLUMN_PHOTO_URI, SQL_DATA_TYPE_STRING),
+ new ColumnInfo(SeriesRecordings.COLUMN_STATE, SQL_DATA_TYPE_STRING)
+ };
private static final String SQL_INSERT_SERIES_RECORDINGS =
buildInsertSql(SeriesRecordings.TABLE_NAME, COLUMNS_SERIES_RECORDINGS);
@@ -186,6 +235,7 @@ public class DvrDatabaseHelper extends SQLiteOpenHelper {
private static String buildDeleteSql(String tableName) {
return "DELETE FROM " + tableName + " WHERE " + BaseColumns._ID + "=?";
}
+
public DvrDatabaseHelper(Context context) {
super(context.getApplicationContext(), DB_NAME, null, DATABASE_VERSION);
}
@@ -205,16 +255,20 @@ public class DvrDatabaseHelper extends SQLiteOpenHelper {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- if (DEBUG) Log.d(TAG, "Executing SQL: " + SQL_DROP_SCHEDULES);
- db.execSQL(SQL_DROP_SCHEDULES);
- if (DEBUG) Log.d(TAG, "Executing SQL: " + SQL_DROP_SERIES_RECORDINGS);
- db.execSQL(SQL_DROP_SERIES_RECORDINGS);
- onCreate(db);
+ if (oldVersion < 17) {
+ if (DEBUG) Log.d(TAG, "Executing SQL: " + SQL_DROP_SCHEDULES);
+ db.execSQL(SQL_DROP_SCHEDULES);
+ if (DEBUG) Log.d(TAG, "Executing SQL: " + SQL_DROP_SERIES_RECORDINGS);
+ db.execSQL(SQL_DROP_SERIES_RECORDINGS);
+ onCreate(db);
+ }
+ if (oldVersion < 18) {
+ db.execSQL("ALTER TABLE " + Schedules.TABLE_NAME + " ADD COLUMN "
+ + Schedules.COLUMN_FAILED_REASON + " TEXT DEFAULT null;");
+ }
}
- /**
- * Handles the query request and returns a {@link Cursor}.
- */
+ /** Handles the query request and returns a {@link Cursor}. */
public Cursor query(String tableName, String[] projections) {
SQLiteDatabase db = getReadableDatabase();
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
@@ -222,9 +276,7 @@ public class DvrDatabaseHelper extends SQLiteOpenHelper {
return builder.query(db, projections, null, null, null, null, null);
}
- /**
- * Inserts schedules.
- */
+ /** Inserts schedules. */
public void insertSchedules(ScheduledRecording... scheduledRecordings) {
SQLiteDatabase db = getWritableDatabase();
SQLiteStatement statement = db.compileStatement(SQL_INSERT_SCHEDULES);
@@ -242,9 +294,7 @@ public class DvrDatabaseHelper extends SQLiteOpenHelper {
}
}
- /**
- * Update schedules.
- */
+ /** Update schedules. */
public void updateSchedules(ScheduledRecording... scheduledRecordings) {
SQLiteDatabase db = getWritableDatabase();
SQLiteStatement statement = db.compileStatement(SQL_UPDATE_SCHEDULES);
@@ -263,9 +313,7 @@ public class DvrDatabaseHelper extends SQLiteOpenHelper {
}
}
- /**
- * Delete schedules.
- */
+ /** Delete schedules. */
public void deleteSchedules(ScheduledRecording... scheduledRecordings) {
SQLiteDatabase db = getWritableDatabase();
SQLiteStatement statement = db.compileStatement(SQL_DELETE_SCHEDULES);
@@ -282,9 +330,7 @@ public class DvrDatabaseHelper extends SQLiteOpenHelper {
}
}
- /**
- * Inserts series recordings.
- */
+ /** Inserts series recordings. */
public void insertSeriesRecordings(SeriesRecording... seriesRecordings) {
SQLiteDatabase db = getWritableDatabase();
SQLiteStatement statement = db.compileStatement(SQL_INSERT_SERIES_RECORDINGS);
@@ -302,9 +348,7 @@ public class DvrDatabaseHelper extends SQLiteOpenHelper {
}
}
- /**
- * Update series recordings.
- */
+ /** Update series recordings. */
public void updateSeriesRecordings(SeriesRecording... seriesRecordings) {
SQLiteDatabase db = getWritableDatabase();
SQLiteStatement statement = db.compileStatement(SQL_UPDATE_SERIES_RECORDINGS);
@@ -323,9 +367,7 @@ public class DvrDatabaseHelper extends SQLiteOpenHelper {
}
}
- /**
- * Delete series recordings.
- */
+ /** Delete series recordings. */
public void deleteSeriesRecordings(SeriesRecording... seriesRecordings) {
SQLiteDatabase db = getWritableDatabase();
SQLiteStatement statement = db.compileStatement(SQL_DELETE_SERIES_RECORDINGS);
@@ -342,8 +384,8 @@ public class DvrDatabaseHelper extends SQLiteOpenHelper {
}
}
- private void bindColumns(SQLiteStatement statement, ColumnInfo[] columns,
- ContentValues values) {
+ private void bindColumns(
+ SQLiteStatement statement, ColumnInfo[] columns, ContentValues values) {
for (int i = 0; i < columns.length; ++i) {
ColumnInfo columnInfo = columns[i];
Object value = values.get(columnInfo.name);
@@ -362,14 +404,15 @@ public class DvrDatabaseHelper extends SQLiteOpenHelper {
statement.bindLong(i + 1, (Integer) value);
}
break;
- case SQL_DATA_TYPE_STRING: {
- if (TextUtils.isEmpty((String) value)) {
- statement.bindNull(i + 1);
- } else {
- statement.bindString(i + 1, (String) value);
+ case SQL_DATA_TYPE_STRING:
+ {
+ if (TextUtils.isEmpty((String) value)) {
+ statement.bindNull(i + 1);
+ } else {
+ statement.bindString(i + 1, (String) value);
+ }
+ break;
}
- break;
- }
}
}
}
diff --git a/src/com/android/tv/dvr/provider/DvrDbSync.java b/src/com/android/tv/dvr/provider/DvrDbSync.java
index ff391959..42bc8bcc 100644
--- a/src/com/android/tv/dvr/provider/DvrDbSync.java
+++ b/src/com/android/tv/dvr/provider/DvrDbSync.java
@@ -29,8 +29,7 @@ import android.os.Looper;
import android.support.annotation.MainThread;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
-
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.data.ChannelDataManager;
import com.android.tv.data.Program;
import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
@@ -41,7 +40,6 @@ import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.dvr.recorder.SeriesRecordingScheduler;
import com.android.tv.util.AsyncDbTask.AsyncQueryProgramTask;
import com.android.tv.util.TvUriMatcher;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -50,6 +48,7 @@ import java.util.List;
import java.util.Objects;
import java.util.Queue;
import java.util.Set;
+import java.util.concurrent.Executor;
/**
* A class to synchronizes DVR DB with TvProvider.
@@ -70,28 +69,31 @@ public class DvrDbSync {
private final DvrManager mDvrManager;
private final DvrDataManagerImpl mDataManager;
private final ChannelDataManager mChannelDataManager;
+ private final Executor mDbExecutor;
private final Queue<Long> mProgramIdQueue = new LinkedList<>();
private QueryProgramTask mQueryProgramTask;
private final SeriesRecordingScheduler mSeriesRecordingScheduler;
- private final ContentObserver mContentObserver = new ContentObserver(new Handler(
- Looper.getMainLooper())) {
- @SuppressLint("SwitchIntDef")
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- switch (TvUriMatcher.match(uri)) {
- case TvUriMatcher.MATCH_PROGRAM:
- if (DEBUG) Log.d(TAG, "onProgramsUpdated");
- onProgramsUpdated();
- break;
- case TvUriMatcher.MATCH_PROGRAM_ID:
- if (DEBUG) {
- Log.d(TAG, "onProgramUpdated: programId=" + ContentUris.parseId(uri));
+ private final ContentObserver mContentObserver =
+ new ContentObserver(new Handler(Looper.getMainLooper())) {
+ @SuppressLint("SwitchIntDef")
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ switch (TvUriMatcher.match(uri)) {
+ case TvUriMatcher.MATCH_PROGRAM:
+ if (DEBUG) Log.d(TAG, "onProgramsUpdated");
+ onProgramsUpdated();
+ break;
+ case TvUriMatcher.MATCH_PROGRAM_ID:
+ if (DEBUG) {
+ Log.d(
+ TAG,
+ "onProgramUpdated: programId=" + ContentUris.parseId(uri));
+ }
+ onProgramUpdated(ContentUris.parseId(uri));
+ break;
}
- onProgramUpdated(ContentUris.parseId(uri));
- break;
- }
- }
- };
+ }
+ };
private final ChannelDataManager.Listener mChannelDataManagerListener =
new ChannelDataManager.Listener() {
@@ -106,70 +108,76 @@ public class DvrDbSync {
}
@Override
- public void onChannelBrowsableChanged() { }
+ public void onChannelBrowsableChanged() {}
};
- private final ScheduledRecordingListener mScheduleListener = new ScheduledRecordingListener() {
- @Override
- public void onScheduledRecordingAdded(ScheduledRecording... schedules) {
- for (ScheduledRecording schedule : schedules) {
- addProgramIdToCheckIfNeeded(schedule);
- }
- startNextUpdateIfNeeded();
- }
+ private final ScheduledRecordingListener mScheduleListener =
+ new ScheduledRecordingListener() {
+ @Override
+ public void onScheduledRecordingAdded(ScheduledRecording... schedules) {
+ for (ScheduledRecording schedule : schedules) {
+ addProgramIdToCheckIfNeeded(schedule);
+ }
+ startNextUpdateIfNeeded();
+ }
- @Override
- public void onScheduledRecordingRemoved(ScheduledRecording... schedules) {
- for (ScheduledRecording schedule : schedules) {
- mProgramIdQueue.remove(schedule.getProgramId());
- }
- }
+ @Override
+ public void onScheduledRecordingRemoved(ScheduledRecording... schedules) {
+ for (ScheduledRecording schedule : schedules) {
+ mProgramIdQueue.remove(schedule.getProgramId());
+ }
+ }
- @Override
- public void onScheduledRecordingStatusChanged(ScheduledRecording... schedules) {
- for (ScheduledRecording schedule : schedules) {
- mProgramIdQueue.remove(schedule.getProgramId());
- addProgramIdToCheckIfNeeded(schedule);
- }
- startNextUpdateIfNeeded();
- }
- };
+ @Override
+ public void onScheduledRecordingStatusChanged(ScheduledRecording... schedules) {
+ for (ScheduledRecording schedule : schedules) {
+ mProgramIdQueue.remove(schedule.getProgramId());
+ addProgramIdToCheckIfNeeded(schedule);
+ }
+ startNextUpdateIfNeeded();
+ }
+ };
public DvrDbSync(Context context, DvrDataManagerImpl dataManager) {
- this(context, dataManager, TvApplication.getSingletons(context).getChannelDataManager(),
- TvApplication.getSingletons(context).getDvrManager(),
- SeriesRecordingScheduler.getInstance(context));
+ this(
+ context,
+ dataManager,
+ TvSingletons.getSingletons(context).getChannelDataManager(),
+ TvSingletons.getSingletons(context).getDvrManager(),
+ SeriesRecordingScheduler.getInstance(context),
+ TvSingletons.getSingletons(context).getDbExecutor());
}
@VisibleForTesting
- DvrDbSync(Context context, DvrDataManagerImpl dataManager,
- ChannelDataManager channelDataManager, DvrManager dvrManager,
- SeriesRecordingScheduler seriesRecordingScheduler) {
+ DvrDbSync(
+ Context context,
+ DvrDataManagerImpl dataManager,
+ ChannelDataManager channelDataManager,
+ DvrManager dvrManager,
+ SeriesRecordingScheduler seriesRecordingScheduler,
+ Executor dbExecutor) {
mContext = context;
mDvrManager = dvrManager;
mDataManager = dataManager;
mChannelDataManager = channelDataManager;
mSeriesRecordingScheduler = seriesRecordingScheduler;
+ mDbExecutor = dbExecutor;
}
- /**
- * Starts the DB sync.
- */
+ /** Starts the DB sync. */
public void start() {
if (!mChannelDataManager.isDbLoadFinished()) {
mChannelDataManager.addListener(mChannelDataManagerListener);
return;
}
- mContext.getContentResolver().registerContentObserver(Programs.CONTENT_URI, true,
- mContentObserver);
+ mContext.getContentResolver()
+ .registerContentObserver(Programs.CONTENT_URI, true, mContentObserver);
mDataManager.addScheduledRecordingListener(mScheduleListener);
onChannelsUpdated();
onProgramsUpdated();
}
- /**
- * Stops the DB sync.
- */
+ /** Stops the DB sync. */
public void stop() {
mProgramIdQueue.clear();
if (mQueryProgramTask != null) {
@@ -185,14 +193,15 @@ public class DvrDbSync {
for (SeriesRecording r : mDataManager.getSeriesRecordings()) {
if (r.getChannelOption() == SeriesRecording.OPTION_CHANNEL_ONE
&& !mChannelDataManager.doesChannelExistInDb(r.getChannelId())) {
- seriesRecordingsToUpdate.add(SeriesRecording.buildFrom(r)
- .setChannelOption(SeriesRecording.OPTION_CHANNEL_ALL)
- .setState(SeriesRecording.STATE_SERIES_STOPPED).build());
+ seriesRecordingsToUpdate.add(
+ SeriesRecording.buildFrom(r)
+ .setChannelOption(SeriesRecording.OPTION_CHANNEL_ALL)
+ .setState(SeriesRecording.STATE_SERIES_STOPPED)
+ .build());
}
}
if (!seriesRecordingsToUpdate.isEmpty()) {
- mDataManager.updateSeriesRecording(
- SeriesRecording.toArray(seriesRecordingsToUpdate));
+ mDataManager.updateSeriesRecording(SeriesRecording.toArray(seriesRecordingsToUpdate));
}
List<ScheduledRecording> schedulesToRemove = new ArrayList<>();
for (ScheduledRecording r : mDataManager.getAvailableScheduledRecordings()) {
@@ -202,8 +211,7 @@ public class DvrDbSync {
}
}
if (!schedulesToRemove.isEmpty()) {
- mDataManager.removeScheduledRecording(
- ScheduledRecording.toArray(schedulesToRemove));
+ mDataManager.removeScheduledRecording(ScheduledRecording.toArray(schedulesToRemove));
}
}
@@ -227,7 +235,7 @@ public class DvrDbSync {
if (programId != ScheduledRecording.ID_NOT_SET
&& !mProgramIdQueue.contains(programId)
&& (schedule.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED
- || schedule.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS)) {
+ || schedule.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS)) {
if (DEBUG) Log.d(TAG, "Program ID enqueued: " + programId);
mProgramIdQueue.offer(programId);
// There are schedules to be updated. Pause the SeriesRecordingScheduler until all the
@@ -258,7 +266,7 @@ public class DvrDbSync {
ScheduledRecording schedule = mDataManager.getScheduledRecordingForProgramId(programId);
if (schedule != null
&& (schedule.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED
- || schedule.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS)) {
+ || schedule.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS)) {
if (program == null) {
mDataManager.removeScheduledRecording(schedule);
if (schedule.getSeriesRecordingId() != SeriesRecording.ID_NOT_SET) {
@@ -270,15 +278,16 @@ public class DvrDbSync {
}
} else {
long currentTimeMs = System.currentTimeMillis();
- ScheduledRecording.Builder builder = ScheduledRecording.buildFrom(schedule)
- .setEndTimeMs(program.getEndTimeUtcMillis())
- .setSeasonNumber(program.getSeasonNumber())
- .setEpisodeNumber(program.getEpisodeNumber())
- .setEpisodeTitle(program.getEpisodeTitle())
- .setProgramDescription(program.getDescription())
- .setProgramLongDescription(program.getLongDescription())
- .setProgramPosterArtUri(program.getPosterArtUri())
- .setProgramThumbnailUri(program.getThumbnailUri());
+ ScheduledRecording.Builder builder =
+ ScheduledRecording.buildFrom(schedule)
+ .setEndTimeMs(program.getEndTimeUtcMillis())
+ .setSeasonNumber(program.getSeasonNumber())
+ .setEpisodeNumber(program.getEpisodeNumber())
+ .setEpisodeTitle(program.getEpisodeTitle())
+ .setProgramDescription(program.getDescription())
+ .setProgramLongDescription(program.getLongDescription())
+ .setProgramPosterArtUri(program.getPosterArtUri())
+ .setProgramThumbnailUri(program.getThumbnailUri());
boolean needUpdate = false;
// Check the series recording.
SeriesRecording seriesRecordingForOldSchedule =
@@ -289,9 +298,11 @@ public class DvrDbSync {
mDataManager.getSeriesRecording(program.getSeriesId());
if (seriesRecording == null) {
// The new program is episodic while the previous one isn't.
- SeriesRecording newSeriesRecording = mDvrManager.addSeriesRecording(
- program, Collections.singletonList(program),
- SeriesRecording.STATE_SERIES_STOPPED);
+ SeriesRecording newSeriesRecording =
+ mDvrManager.addSeriesRecording(
+ program,
+ Collections.singletonList(program),
+ SeriesRecording.STATE_SERIES_STOPPED);
builder.setSeriesRecordingId(newSeriesRecording.getId());
needUpdate = true;
} else if (seriesRecording.getId() != schedule.getSeriesRecordingId()) {
@@ -302,10 +313,10 @@ public class DvrDbSync {
if (seriesRecordingForOldSchedule != null) {
seriesRecordingsToUpdate.add(seriesRecordingForOldSchedule);
}
- } else if (!Objects.equals(schedule.getSeasonNumber(),
- program.getSeasonNumber())
- || !Objects.equals(schedule.getEpisodeNumber(),
- program.getEpisodeNumber())) {
+ } else if (!Objects.equals(
+ schedule.getSeasonNumber(), program.getSeasonNumber())
+ || !Objects.equals(
+ schedule.getEpisodeNumber(), program.getEpisodeNumber())) {
// The episode number has been changed.
if (seriesRecordingForOldSchedule != null) {
seriesRecordingsToUpdate.add(seriesRecordingForOldSchedule);
@@ -318,23 +329,24 @@ public class DvrDbSync {
// Change start time only when the recording is not started yet.
boolean needToChangeStartTime =
schedule.getState() != ScheduledRecording.STATE_RECORDING_IN_PROGRESS
- && program.getStartTimeUtcMillis() != schedule.getStartTimeMs();
+ && program.getStartTimeUtcMillis() != schedule.getStartTimeMs();
if (needToChangeStartTime) {
builder.setStartTimeMs(program.getStartTimeUtcMillis());
needUpdate = true;
}
- if (needUpdate || schedule.getEndTimeMs() != program.getEndTimeUtcMillis()
+ if (needUpdate
+ || schedule.getEndTimeMs() != program.getEndTimeUtcMillis()
|| !Objects.equals(schedule.getSeasonNumber(), program.getSeasonNumber())
|| !Objects.equals(schedule.getEpisodeNumber(), program.getEpisodeNumber())
|| !Objects.equals(schedule.getEpisodeTitle(), program.getEpisodeTitle())
- || !Objects.equals(schedule.getProgramDescription(),
- program.getDescription())
- || !Objects.equals(schedule.getProgramLongDescription(),
- program.getLongDescription())
- || !Objects.equals(schedule.getProgramPosterArtUri(),
- program.getPosterArtUri())
- || !Objects.equals(schedule.getProgramThumbnailUri(),
- program.getThumbnailUri())) {
+ || !Objects.equals(
+ schedule.getProgramDescription(), program.getDescription())
+ || !Objects.equals(
+ schedule.getProgramLongDescription(), program.getLongDescription())
+ || !Objects.equals(
+ schedule.getProgramPosterArtUri(), program.getPosterArtUri())
+ || !Objects.equals(
+ schedule.getProgramThumbnailUri(), program.getThumbnailUri())) {
mDataManager.updateScheduledRecording(builder.build());
}
if (!seriesRecordingsToUpdate.isEmpty()) {
@@ -349,7 +361,7 @@ public class DvrDbSync {
private final long mProgramId;
QueryProgramTask(long programId) {
- super(mContext.getContentResolver(), programId);
+ super(mDbExecutor, mContext.getContentResolver(), programId);
mProgramId = programId;
}
diff --git a/src/com/android/tv/dvr/provider/EpisodicProgramLoadTask.java b/src/com/android/tv/dvr/provider/EpisodicProgramLoadTask.java
index ba0aca51..b7d9f3b3 100644
--- a/src/com/android/tv/dvr/provider/EpisodicProgramLoadTask.java
+++ b/src/com/android/tv/dvr/provider/EpisodicProgramLoadTask.java
@@ -25,18 +25,16 @@ import android.net.Uri;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;
-
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
+import com.android.tv.common.util.PermissionUtils;
import com.android.tv.data.Program;
import com.android.tv.dvr.DvrDataManager;
-import com.android.tv.dvr.data.SeasonEpisodeNumber;
import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeasonEpisodeNumber;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.util.AsyncDbTask.AsyncProgramQueryTask;
import com.android.tv.util.AsyncDbTask.CursorFilter;
-import com.android.tv.util.PermissionUtils;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -44,11 +42,9 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
-/**
- * A wrapper of AsyncProgramQueryTask to load the episodic programs for the series recordings.
- */
+/** A wrapper of AsyncProgramQueryTask to load the episodic programs for the series recordings. */
@TargetApi(Build.VERSION_CODES.N)
-abstract public class EpisodicProgramLoadTask {
+public abstract class EpisodicProgramLoadTask {
private static final String TAG = "EpisodicProgramLoadTask";
private static final int PROGRAM_ID_INDEX = Program.getColumnIndex(Programs._ID);
@@ -61,11 +57,15 @@ abstract public class EpisodicProgramLoadTask {
private static final String PARAM_END_TIME = "end_time";
private static final String PROGRAM_PREDICATE =
- Programs.COLUMN_START_TIME_UTC_MILLIS + ">? AND "
- + Programs.COLUMN_RECORDING_PROHIBITED + "=0";
+ Programs.COLUMN_START_TIME_UTC_MILLIS
+ + ">? AND "
+ + Programs.COLUMN_RECORDING_PROHIBITED
+ + "=0";
private static final String PROGRAM_PREDICATE_WITH_CURRENT_PROGRAM =
- Programs.COLUMN_END_TIME_UTC_MILLIS + ">? AND "
- + Programs.COLUMN_RECORDING_PROHIBITED + "=0";
+ Programs.COLUMN_END_TIME_UTC_MILLIS
+ + ">? AND "
+ + Programs.COLUMN_RECORDING_PROHIBITED
+ + "=0";
private static final String CHANNEL_ID_PREDICATE = Programs.COLUMN_CHANNEL_ID + "=?";
private static final String PROGRAM_TITLE_PREDICATE = Programs.COLUMN_TITLE + "=?";
@@ -80,10 +80,7 @@ abstract public class EpisodicProgramLoadTask {
private final ArrayList<SeriesRecording> mSeriesRecordings = new ArrayList<>();
private AsyncProgramQueryTask mProgramQueryTask;
- /**
- *
- * Constructor used to load programs for one series recording with the given channel option.
- */
+ /** Constructor used to load programs for one series recording with the given channel option. */
public EpisodicProgramLoadTask(Context context, SeriesRecording seriesRecording) {
this(context, Collections.singletonList(seriesRecording));
}
@@ -94,64 +91,56 @@ abstract public class EpisodicProgramLoadTask {
*/
public EpisodicProgramLoadTask(Context context, Collection<SeriesRecording> seriesRecordings) {
mContext = context.getApplicationContext();
- mDataManager = TvApplication.getSingletons(context).getDvrDataManager();
+ mDataManager = TvSingletons.getSingletons(context).getDvrDataManager();
mSeriesRecordings.addAll(seriesRecordings);
}
- /**
- * Returns the series recordings.
- */
+ /** Returns the series recordings. */
public List<SeriesRecording> getSeriesRecordings() {
return mSeriesRecordings;
}
- /**
- * Returns the program query task. It is {@code null} until it is executed.
- */
+ /** Returns the program query task. It is {@code null} until it is executed. */
@Nullable
public AsyncProgramQueryTask getTask() {
return mProgramQueryTask;
}
- /**
- * Enables loading current programs. The default value is {@code false}.
- */
+ /** Enables loading current programs. The default value is {@code false}. */
public EpisodicProgramLoadTask setLoadCurrentProgram(boolean loadCurrentProgram) {
- SoftPreconditions.checkState(mProgramQueryTask == null, TAG,
- "Can't change setting after execution.");
+ SoftPreconditions.checkState(
+ mProgramQueryTask == null, TAG, "Can't change setting after execution.");
mLoadCurrentProgram = loadCurrentProgram;
return this;
}
- /**
- * Enables already schedules episodes. The default value is {@code false}.
- */
+ /** Enables already schedules episodes. The default value is {@code false}. */
public EpisodicProgramLoadTask setLoadScheduledEpisode(boolean loadScheduledEpisode) {
- SoftPreconditions.checkState(mProgramQueryTask == null, TAG,
- "Can't change setting after execution.");
+ SoftPreconditions.checkState(
+ mProgramQueryTask == null, TAG, "Can't change setting after execution.");
mLoadScheduledEpisode = loadScheduledEpisode;
return this;
}
/**
- * Enables loading disallowed programs whose schedules were removed manually by the user.
- * The default value is {@code false}.
+ * Enables loading disallowed programs whose schedules were removed manually by the user. The
+ * default value is {@code false}.
*/
public EpisodicProgramLoadTask setLoadDisallowedProgram(boolean loadDisallowedProgram) {
- SoftPreconditions.checkState(mProgramQueryTask == null, TAG,
- "Can't change setting after execution.");
+ SoftPreconditions.checkState(
+ mProgramQueryTask == null, TAG, "Can't change setting after execution.");
mLoadDisallowedProgram = loadDisallowedProgram;
return this;
}
/**
- * Gives the option whether to ignore the channel option when matching programs.
- * If {@code ignoreChannelOption} is {@code true}, the program will be matched with
- * {@link SeriesRecording#OPTION_CHANNEL_ALL} option.
+ * Gives the option whether to ignore the channel option when matching programs. If {@code
+ * ignoreChannelOption} is {@code true}, the program will be matched with {@link
+ * SeriesRecording#OPTION_CHANNEL_ALL} option.
*/
public EpisodicProgramLoadTask setIgnoreChannelOption(boolean ignoreChannelOption) {
- SoftPreconditions.checkState(mProgramQueryTask == null, TAG,
- "Can't change setting after execution.");
+ SoftPreconditions.checkState(
+ mProgramQueryTask == null, TAG, "Can't change setting after execution.");
mIgnoreChannelOption = ignoreChannelOption;
return this;
}
@@ -162,12 +151,15 @@ abstract public class EpisodicProgramLoadTask {
* @see com.android.tv.util.AsyncDbTask#executeOnDbThread
*/
public void execute() {
- if (SoftPreconditions.checkState(mProgramQueryTask == null, TAG,
+ if (SoftPreconditions.checkState(
+ mProgramQueryTask == null,
+ TAG,
"Can't execute task: the task is already running.")) {
- mQueryAllChannels = mSeriesRecordings.size() > 1
- || mSeriesRecordings.get(0).getChannelOption()
- == SeriesRecording.OPTION_CHANNEL_ALL
- || mIgnoreChannelOption;
+ mQueryAllChannels =
+ mSeriesRecordings.size() > 1
+ || mSeriesRecordings.get(0).getChannelOption()
+ == SeriesRecording.OPTION_CHANNEL_ALL
+ || mIgnoreChannelOption;
mProgramQueryTask = createTask();
mProgramQueryTask.executeOnDbThread();
}
@@ -184,22 +176,22 @@ abstract public class EpisodicProgramLoadTask {
}
}
- /**
- * Runs on the UI thread after the program loading finishes successfully.
- */
- protected void onPostExecute(List<Program> programs) {
- }
+ /** Runs on the UI thread after the program loading finishes successfully. */
+ protected void onPostExecute(List<Program> programs) {}
- /**
- * Runs on the UI thread after the program loading was canceled.
- */
- protected void onCancelled(List<Program> programs) {
- }
+ /** Runs on the UI thread after the program loading was canceled. */
+ protected void onCancelled(List<Program> programs) {}
private AsyncProgramQueryTask createTask() {
SqlParams sqlParams = createSqlParams();
- return new AsyncProgramQueryTask(mContext.getContentResolver(), sqlParams.uri,
- sqlParams.selection, sqlParams.selectionArgs, null, sqlParams.filter) {
+ return new AsyncProgramQueryTask(
+ TvSingletons.getSingletons(mContext).getDbExecutor(),
+ mContext.getContentResolver(),
+ sqlParams.uri,
+ sqlParams.selection,
+ sqlParams.selectionArgs,
+ null,
+ sqlParams.filter) {
@Override
protected void onPostExecute(List<Program> programs) {
EpisodicProgramLoadTask.this.onPostExecute(programs);
@@ -217,8 +209,11 @@ abstract public class EpisodicProgramLoadTask {
if (PermissionUtils.hasAccessAllEpg(mContext)) {
sqlParams.uri = Programs.CONTENT_URI;
// Base
- StringBuilder selection = new StringBuilder(mLoadCurrentProgram
- ? PROGRAM_PREDICATE_WITH_CURRENT_PROGRAM : PROGRAM_PREDICATE);
+ StringBuilder selection =
+ new StringBuilder(
+ mLoadCurrentProgram
+ ? PROGRAM_PREDICATE_WITH_CURRENT_PROGRAM
+ : PROGRAM_PREDICATE);
List<String> args = new ArrayList<>();
args.add(Long.toString(System.currentTimeMillis()));
// Channel option
@@ -237,15 +232,21 @@ abstract public class EpisodicProgramLoadTask {
} else {
// The query includes the current program. Will be filtered if needed.
if (mQueryAllChannels) {
- sqlParams.uri = Programs.CONTENT_URI.buildUpon()
- .appendQueryParameter(PARAM_START_TIME,
- String.valueOf(System.currentTimeMillis()))
- .appendQueryParameter(PARAM_END_TIME, String.valueOf(Long.MAX_VALUE))
- .build();
+ sqlParams.uri =
+ Programs.CONTENT_URI
+ .buildUpon()
+ .appendQueryParameter(
+ PARAM_START_TIME,
+ String.valueOf(System.currentTimeMillis()))
+ .appendQueryParameter(
+ PARAM_END_TIME, String.valueOf(Long.MAX_VALUE))
+ .build();
} else {
- sqlParams.uri = TvContract.buildProgramsUriForChannel(
- mSeriesRecordings.get(0).getChannelId(),
- System.currentTimeMillis(), Long.MAX_VALUE);
+ sqlParams.uri =
+ TvContract.buildProgramsUriForChannel(
+ mSeriesRecordings.get(0).getChannelId(),
+ System.currentTimeMillis(),
+ Long.MAX_VALUE);
}
sqlParams.selection = null;
sqlParams.selectionArgs = null;
@@ -292,16 +293,19 @@ abstract public class EpisodicProgramLoadTask {
for (SeriesRecording seriesRecording : mSeriesRecordings) {
boolean programMatches;
if (mIgnoreChannelOption) {
- programMatches = seriesRecording.matchProgram(program,
- SeriesRecording.OPTION_CHANNEL_ALL);
+ programMatches =
+ seriesRecording.matchProgram(
+ program, SeriesRecording.OPTION_CHANNEL_ALL);
} else {
programMatches = seriesRecording.matchProgram(program);
}
if (programMatches) {
return mLoadScheduledEpisode
- || !mSeasonEpisodeNumbers.contains(new SeasonEpisodeNumber(
- seriesRecording.getId(), program.getSeasonNumber(),
- program.getEpisodeNumber()));
+ || !mSeasonEpisodeNumbers.contains(
+ new SeasonEpisodeNumber(
+ seriesRecording.getId(),
+ program.getSeasonNumber(),
+ program.getEpisodeNumber()));
}
}
return false;
@@ -316,7 +320,8 @@ abstract public class EpisodicProgramLoadTask {
@Override
public boolean filter(Cursor c) {
return (mLoadCurrentProgram || c.getLong(START_TIME_INDEX) > System.currentTimeMillis())
- && c.getInt(RECORDING_PROHIBITED_INDEX) != 0 && super.filter(c);
+ && c.getInt(RECORDING_PROHIBITED_INDEX) != 0
+ && super.filter(c);
}
}
diff --git a/src/com/android/tv/dvr/recorder/ConflictChecker.java b/src/com/android/tv/dvr/recorder/ConflictChecker.java
index 8aa90116..bfd315e9 100644
--- a/src/com/android/tv/dvr/recorder/ConflictChecker.java
+++ b/src/com/android/tv/dvr/recorder/ConflictChecker.java
@@ -27,21 +27,19 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.ArraySet;
import android.util.Log;
-
-import com.android.tv.ApplicationSingletons;
import com.android.tv.InputSessionManager;
import com.android.tv.InputSessionManager.OnTvViewChannelChangeListener;
import com.android.tv.MainActivity;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.WeakHandler;
-import com.android.tv.data.Channel;
import com.android.tv.data.ChannelDataManager;
+import com.android.tv.data.api.Channel;
import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
import com.android.tv.dvr.DvrScheduleManager;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.ui.DvrUiHelper;
-
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -50,8 +48,9 @@ import java.util.concurrent.TimeUnit;
/**
* Checking the runtime conflict of DVR recording.
- * <p>
- * This class runs only while the {@link MainActivity} is resumed and holds the upcoming conflicts.
+ *
+ * <p>This class runs only while the {@link MainActivity} is resumed and holds the upcoming
+ * conflicts.
*/
@TargetApi(Build.VERSION_CODES.N)
@MainThread
@@ -87,24 +86,40 @@ public class ConflictChecker {
private final ScheduledRecordingListener mScheduledRecordingListener =
new ScheduledRecordingListener() {
- @Override
- public void onScheduledRecordingAdded(ScheduledRecording... scheduledRecordings) {
- if (DEBUG) Log.d(TAG, "onScheduledRecordingAdded: " + scheduledRecordings);
- mHandler.sendEmptyMessage(MSG_CHECK_CONFLICT);
- }
+ @Override
+ public void onScheduledRecordingAdded(ScheduledRecording... scheduledRecordings) {
+ if (DEBUG) {
+ Log.d(
+ TAG,
+ "onScheduledRecordingAdded: "
+ + Arrays.toString(scheduledRecordings));
+ }
+ mHandler.sendEmptyMessage(MSG_CHECK_CONFLICT);
+ }
- @Override
- public void onScheduledRecordingRemoved(ScheduledRecording... scheduledRecordings) {
- if (DEBUG) Log.d(TAG, "onScheduledRecordingRemoved: " + scheduledRecordings);
- mHandler.sendEmptyMessage(MSG_CHECK_CONFLICT);
- }
+ @Override
+ public void onScheduledRecordingRemoved(ScheduledRecording... scheduledRecordings) {
+ if (DEBUG) {
+ Log.d(
+ TAG,
+ "onScheduledRecordingRemoved: "
+ + Arrays.toString(scheduledRecordings));
+ }
+ mHandler.sendEmptyMessage(MSG_CHECK_CONFLICT);
+ }
- @Override
- public void onScheduledRecordingStatusChanged(ScheduledRecording... scheduledRecordings) {
- if (DEBUG) Log.d(TAG, "onScheduledRecordingStatusChanged: " + scheduledRecordings);
- mHandler.sendEmptyMessage(MSG_CHECK_CONFLICT);
- }
- };
+ @Override
+ public void onScheduledRecordingStatusChanged(
+ ScheduledRecording... scheduledRecordings) {
+ if (DEBUG) {
+ Log.d(
+ TAG,
+ "onScheduledRecordingStatusChanged: "
+ + Arrays.toString(scheduledRecordings));
+ }
+ mHandler.sendEmptyMessage(MSG_CHECK_CONFLICT);
+ }
+ };
private final OnTvViewChannelChangeListener mOnTvViewChannelChangeListener =
new OnTvViewChannelChangeListener() {
@@ -118,15 +133,13 @@ public class ConflictChecker {
public ConflictChecker(MainActivity mainActivity) {
mMainActivity = mainActivity;
- ApplicationSingletons appSingletons = TvApplication.getSingletons(mainActivity);
- mChannelDataManager = appSingletons.getChannelDataManager();
- mScheduleManager = appSingletons.getDvrScheduleManager();
- mSessionManager = appSingletons.getInputSessionManager();
+ TvSingletons tvSingletons = TvSingletons.getSingletons(mainActivity);
+ mChannelDataManager = tvSingletons.getChannelDataManager();
+ mScheduleManager = tvSingletons.getDvrScheduleManager();
+ mSessionManager = tvSingletons.getInputSessionManager();
}
- /**
- * Starts checking the conflict.
- */
+ /** Starts checking the conflict. */
public void start() {
if (mStarted) {
return;
@@ -137,9 +150,7 @@ public class ConflictChecker {
mSessionManager.addOnTvViewChannelChangeListener(mOnTvViewChannelChangeListener);
}
- /**
- * Stops checking the conflict.
- */
+ /** Stops checking the conflict. */
public void stop() {
if (!mStarted) {
return;
@@ -150,23 +161,17 @@ public class ConflictChecker {
mHandler.removeCallbacksAndMessages(null);
}
- /**
- * Returns the upcoming conflicts.
- */
+ /** Returns the upcoming conflicts. */
public List<ScheduledRecording> getUpcomingConflicts() {
return new ArrayList<>(mUpcomingConflicts);
}
- /**
- * Adds a {@link OnUpcomingConflictChangeListener}.
- */
+ /** Adds a {@link OnUpcomingConflictChangeListener}. */
public void addOnUpcomingConflictChangeListener(OnUpcomingConflictChangeListener listener) {
mOnUpcomingConflictChangeListeners.add(listener);
}
- /**
- * Removes the {@link OnUpcomingConflictChangeListener}.
- */
+ /** Removes the {@link OnUpcomingConflictChangeListener}. */
public void removeOnUpcomingConflictChangeListener(OnUpcomingConflictChangeListener listener) {
mOnUpcomingConflictChangeListeners.remove(listener);
}
@@ -177,9 +182,7 @@ public class ConflictChecker {
}
}
- /**
- * Remembers the user's decision to record while watching the channel.
- */
+ /** Remembers the user's decision to record while watching the channel. */
public void setCheckedConflictsForChannel(long mChannelId, List<ScheduledRecording> conflicts) {
mCheckedConflictsMap.put(mChannelId, new ArrayList<>(conflicts));
}
@@ -190,8 +193,7 @@ public class ConflictChecker {
if (DEBUG) Log.d(TAG, "Handling MSG_CHECK_CONFLICT");
mHandler.removeMessages(MSG_CHECK_CONFLICT);
mUpcomingConflicts.clear();
- if (!mScheduleManager.isInitialized()
- || !mChannelDataManager.isDbLoadFinished()) {
+ if (!mScheduleManager.isInitialized() || !mChannelDataManager.isDbLoadFinished()) {
mHandler.sendEmptyMessageDelayed(MSG_CHECK_CONFLICT, CHECK_RETRY_PERIOD_MS);
notifyUpcomingConflictChanged();
return;
@@ -209,8 +211,8 @@ public class ConflictChecker {
long channelId = ContentUris.parseId(channelUri);
Channel channel = mChannelDataManager.getChannel(channelId);
// The conflicts caused by watching the channel.
- List<ScheduledRecording> conflicts = mScheduleManager
- .getConflictingSchedulesForWatching(channel.getId());
+ List<ScheduledRecording> conflicts =
+ mScheduleManager.getConflictingSchedulesForWatching(channel.getId());
long earliestToCheck = Long.MAX_VALUE;
long currentTimeMs = System.currentTimeMillis();
for (ScheduledRecording schedule : conflicts) {
@@ -239,18 +241,15 @@ public class ConflictChecker {
}
}
if (earliestToCheck != Long.MAX_VALUE) {
- mHandler.sendEmptyMessageDelayed(MSG_CHECK_CONFLICT,
- earliestToCheck - currentTimeMs);
+ mHandler.sendEmptyMessageDelayed(MSG_CHECK_CONFLICT, earliestToCheck - currentTimeMs);
}
if (DEBUG) Log.d(TAG, "upcoming conflicts: " + mUpcomingConflicts);
notifyUpcomingConflictChanged();
if (!mUpcomingConflicts.isEmpty()
&& !DvrUiHelper.isChannelWatchConflictDialogShown(mMainActivity)) {
// Don't show the conflict dialog if the user already knows.
- List<ScheduledRecording> checkedConflicts = mCheckedConflictsMap.get(
- channel.getId());
- if (checkedConflicts == null
- || !checkedConflicts.containsAll(mUpcomingConflicts)) {
+ List<ScheduledRecording> checkedConflicts = mCheckedConflictsMap.get(channel.getId());
+ if (checkedConflicts == null || !checkedConflicts.containsAll(mUpcomingConflicts)) {
DvrUiHelper.showChannelWatchConflictDialog(mMainActivity, channel);
}
}
@@ -271,9 +270,7 @@ public class ConflictChecker {
}
}
- /**
- * A listener for the change of upcoming conflicts.
- */
+ /** A listener for the change of upcoming conflicts. */
public interface OnUpcomingConflictChangeListener {
void onUpcomingConflictChange();
}
diff --git a/src/com/android/tv/dvr/recorder/DvrRecordingService.java b/src/com/android/tv/dvr/recorder/DvrRecordingService.java
index 5d324ca5..9fdbf062 100644
--- a/src/com/android/tv/dvr/recorder/DvrRecordingService.java
+++ b/src/com/android/tv/dvr/recorder/DvrRecordingService.java
@@ -29,21 +29,20 @@ import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
-
-import com.android.tv.ApplicationSingletons;
import com.android.tv.InputSessionManager;
import com.android.tv.InputSessionManager.OnRecordingSessionChangeListener;
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.Starter;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.common.util.Clock;
import com.android.tv.dvr.WritableDvrDataManager;
-import com.android.tv.util.Clock;
import com.android.tv.util.RecurringRunner;
/**
- * DVR recording service. This service should be a foreground service and send a notification
- * to users to do long-running recording task.
+ * DVR recording service. This service should be a foreground service and send a notification to
+ * users to do long-running recording task.
*
* <p>This service is waken up when there's a scheduled recording coming soon and at boot completed
* since schedules have to be loaded from databases in order to set new recording alarms, which
@@ -67,9 +66,9 @@ public class DvrRecordingService extends Service {
/**
* Starts the service in foreground.
*
- * @param startForRecording {@code true} if there are upcoming recordings in
- * {@link RecordingScheduler#SOON_DURATION_IN_MS} and the service is
- * started in foreground for those recordings.
+ * @param startForRecording {@code true} if there are upcoming recordings in {@link
+ * RecordingScheduler#SOON_DURATION_IN_MS} and the service is started in foreground for
+ * those recordings.
*/
@MainThread
static void startForegroundService(Context context, boolean startForRecording) {
@@ -99,7 +98,8 @@ public class DvrRecordingService extends Service {
@VisibleForTesting boolean mIsRecording;
private boolean mForeground;
- @VisibleForTesting final OnRecordingSessionChangeListener mOnRecordingSessionChangeListener =
+ @VisibleForTesting
+ final OnRecordingSessionChangeListener mOnRecordingSessionChangeListener =
new OnRecordingSessionChangeListener() {
@Override
public void onRecordingSessionChange(final boolean create, final int count) {
@@ -114,18 +114,22 @@ public class DvrRecordingService extends Service {
@Override
public void onCreate() {
- TvApplication.setCurrentRunningProcess(this, true);
+ Starter.start(this);
if (DEBUG) Log.d(TAG, "onCreate");
super.onCreate();
SoftPreconditions.checkFeatureEnabled(this, CommonFeatures.DVR, TAG);
sInstance = this;
- ApplicationSingletons singletons = TvApplication.getSingletons(this);
+ TvSingletons singletons = TvSingletons.getSingletons(this);
WritableDvrDataManager dataManager =
(WritableDvrDataManager) singletons.getDvrDataManager();
mSessionManager = singletons.getInputSessionManager();
mSessionManager.addOnRecordingSessionChangeListener(mOnRecordingSessionChangeListener);
- mReaperRunner = new RecurringRunner(this, java.util.concurrent.TimeUnit.DAYS.toMillis(1),
- new ScheduledProgramReaper(dataManager, Clock.SYSTEM), null);
+ mReaperRunner =
+ new RecurringRunner(
+ this,
+ java.util.concurrent.TimeUnit.DAYS.toMillis(1),
+ new ScheduledProgramReaper(dataManager, Clock.SYSTEM),
+ null);
mReaperRunner.start();
mContentTitle = getString(R.string.dvr_notification_content_title);
mContentTextRecording = getString(R.string.dvr_notification_content_text_recording);
@@ -179,13 +183,16 @@ public class DvrRecordingService extends Service {
@VisibleForTesting
protected void startForegroundInternal(boolean hasUpcomingRecording) {
- // STOPSHIP: Replace the content title with real UX strings
- Notification.Builder builder = new Notification.Builder(this)
- .setContentTitle(mContentTitle)
- .setContentText(hasUpcomingRecording ? mContentTextRecording : mContentTextLoading)
- .setSmallIcon(R.drawable.ic_dvr);
- Notification notification = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
- builder.setChannelId(DVR_NOTIFICATION_CHANNEL_ID).build() : builder.build();
+ Notification.Builder builder =
+ new Notification.Builder(this)
+ .setContentTitle(mContentTitle)
+ .setContentText(
+ hasUpcomingRecording ? mContentTextRecording : mContentTextLoading)
+ .setSmallIcon(R.drawable.ic_dvr);
+ Notification notification =
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
+ ? builder.setChannelId(DVR_NOTIFICATION_CHANNEL_ID).build()
+ : builder.build();
startForeground(ONGOING_NOTIFICATION_ID, notification);
}
@@ -196,10 +203,11 @@ public class DvrRecordingService extends Service {
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- // STOPSHIP: Replace the channel name with real UX strings
- mNotificationChannel = new NotificationChannel(DVR_NOTIFICATION_CHANNEL_ID,
- getString(R.string.dvr_notification_channel_name),
- NotificationManager.IMPORTANCE_LOW);
+ mNotificationChannel =
+ new NotificationChannel(
+ DVR_NOTIFICATION_CHANNEL_ID,
+ getString(R.string.dvr_notification_channel_name),
+ NotificationManager.IMPORTANCE_LOW);
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE))
.createNotificationChannel(mNotificationChannel);
}
diff --git a/src/com/android/tv/dvr/recorder/DvrStartRecordingReceiver.java b/src/com/android/tv/dvr/recorder/DvrStartRecordingReceiver.java
index f1c0020b..bb5ea99d 100644
--- a/src/com/android/tv/dvr/recorder/DvrStartRecordingReceiver.java
+++ b/src/com/android/tv/dvr/recorder/DvrStartRecordingReceiver.java
@@ -21,18 +21,16 @@ import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.support.annotation.RequiresApi;
+import com.android.tv.Starter;
+import com.android.tv.TvSingletons;
-import com.android.tv.TvApplication;
-
-/**
- * Signals the DVR to start recording shows <i>soon</i>.
- */
+/** Signals the DVR to start recording shows <i>soon</i>. */
@RequiresApi(Build.VERSION_CODES.N)
public class DvrStartRecordingReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- TvApplication.setCurrentRunningProcess(context, true);
- RecordingScheduler scheduler = TvApplication.getSingletons(context).getRecordingScheduler();
+ Starter.start(context);
+ RecordingScheduler scheduler = TvSingletons.getSingletons(context).getRecordingScheduler();
if (scheduler != null) {
scheduler.updateAndStartServiceIfNeeded();
}
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;
diff --git a/src/com/android/tv/dvr/recorder/RecordingScheduler.java b/src/com/android/tv/dvr/recorder/RecordingScheduler.java
index cbaf46b5..f309537d 100644
--- a/src/com/android/tv/dvr/recorder/RecordingScheduler.java
+++ b/src/com/android/tv/dvr/recorder/RecordingScheduler.java
@@ -31,11 +31,10 @@ import android.support.annotation.VisibleForTesting;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Range;
-
-import com.android.tv.ApplicationSingletons;
import com.android.tv.InputSessionManager;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
+import com.android.tv.common.util.Clock;
import com.android.tv.data.ChannelDataManager;
import com.android.tv.data.ChannelDataManager.Listener;
import com.android.tv.dvr.DvrDataManager;
@@ -44,22 +43,21 @@ import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
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.TvInputManagerHelper;
import com.android.tv.util.Utils;
-
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
- * The core class to manage DVR schedule and run recording task.
- **
- * <p> This class is responsible for:
+ * The core class to manage DVR schedule and run recording task. *
+ *
+ * <p>This class is responsible for:
+ *
* <ul>
- * <li>Sending record commands to TV inputs</li>
- * <li>Resolving conflicting schedules, handling overlapping recording time durations, etc.</li>
+ * <li>Sending record commands to TV inputs
+ * <li>Resolving conflicting schedules, handling overlapping recording time durations, etc.
* </ul>
*
* <p>This should be a singleton associated with application's main process.
@@ -71,8 +69,8 @@ public class RecordingScheduler extends TvInputCallback implements ScheduledReco
private static final boolean DEBUG = false;
private static final String HANDLER_THREAD_NAME = "RecordingScheduler";
- private final static long SOON_DURATION_IN_MS = TimeUnit.MINUTES.toMillis(1);
- @VisibleForTesting final static long MS_TO_WAKE_BEFORE_START = TimeUnit.SECONDS.toMillis(30);
+ private static final long SOON_DURATION_IN_MS = TimeUnit.MINUTES.toMillis(1);
+ @VisibleForTesting static final long MS_TO_WAKE_BEFORE_START = TimeUnit.SECONDS.toMillis(30);
private final Looper mLooper;
private final InputSessionManager mSessionManager;
@@ -98,21 +96,22 @@ public class RecordingScheduler extends TvInputCallback implements ScheduledReco
}
};
- private Listener mChannelDataLoadListener = new Listener() {
- @Override
- public void onLoadFinished() {
- mChannelDataManager.removeListener(this);
- if (isDbLoaded()) {
- updateInternal();
- }
- }
+ private Listener mChannelDataLoadListener =
+ new Listener() {
+ @Override
+ public void onLoadFinished() {
+ mChannelDataManager.removeListener(this);
+ if (isDbLoaded()) {
+ updateInternal();
+ }
+ }
- @Override
- public void onChannelListUpdated() { }
+ @Override
+ public void onChannelListUpdated() {}
- @Override
- public void onChannelBrowsableChanged() { }
- };
+ @Override
+ public void onChannelBrowsableChanged() {}
+ };
/**
* Creates a scheduler to schedule alarms for scheduled recordings and create recording tasks.
@@ -120,21 +119,32 @@ public class RecordingScheduler extends TvInputCallback implements ScheduledReco
*/
public static RecordingScheduler createScheduler(Context context) {
SoftPreconditions.checkState(
- TvApplication.getSingletons(context).getRecordingScheduler() == null);
+ TvSingletons.getSingletons(context).getRecordingScheduler() == null);
HandlerThread handlerThread = new HandlerThread(HANDLER_THREAD_NAME);
handlerThread.start();
- ApplicationSingletons singletons = TvApplication.getSingletons(context);
- return new RecordingScheduler(handlerThread.getLooper(),
- singletons.getDvrManager(), singletons.getInputSessionManager(),
+ TvSingletons singletons = TvSingletons.getSingletons(context);
+ return new RecordingScheduler(
+ handlerThread.getLooper(),
+ singletons.getDvrManager(),
+ singletons.getInputSessionManager(),
(WritableDvrDataManager) singletons.getDvrDataManager(),
- singletons.getChannelDataManager(), singletons.getTvInputManagerHelper(), context,
- Clock.SYSTEM, (AlarmManager) context.getSystemService(Context.ALARM_SERVICE));
+ singletons.getChannelDataManager(),
+ singletons.getTvInputManagerHelper(),
+ context,
+ Clock.SYSTEM,
+ (AlarmManager) context.getSystemService(Context.ALARM_SERVICE));
}
@VisibleForTesting
- RecordingScheduler(Looper looper, DvrManager dvrManager, InputSessionManager sessionManager,
- WritableDvrDataManager dataManager, ChannelDataManager channelDataManager,
- TvInputManagerHelper inputManager, Context context, Clock clock,
+ RecordingScheduler(
+ Looper looper,
+ DvrManager dvrManager,
+ InputSessionManager sessionManager,
+ WritableDvrDataManager dataManager,
+ ChannelDataManager channelDataManager,
+ TvInputManagerHelper inputManager,
+ Context context,
+ Clock clock,
AlarmManager alarmManager) {
mLooper = looper;
mDvrManager = dvrManager;
@@ -159,9 +169,7 @@ public class RecordingScheduler extends TvInputCallback implements ScheduledReco
}
}
- /**
- * Start recording that will happen soon, and set the next alarm time.
- */
+ /** Start recording that will happen soon, and set the next alarm time. */
public void updateAndStartServiceIfNeeded() {
if (DEBUG) Log.d(TAG, "update and start service if needed");
if (isDbLoaded()) {
@@ -185,8 +193,10 @@ public class RecordingScheduler extends TvInputCallback implements ScheduledReco
}
private boolean updatePendingRecordings() {
- List<ScheduledRecording> scheduledRecordings = mDataManager
- .getScheduledRecordings(new Range<>(mLastStartTimePendingMs,
+ List<ScheduledRecording> scheduledRecordings =
+ mDataManager.getScheduledRecordings(
+ new Range<>(
+ mLastStartTimePendingMs,
mClock.currentTimeMillis() + SOON_DURATION_IN_MS),
ScheduledRecording.STATE_RECORDING_NOT_STARTED);
for (ScheduledRecording r : scheduledRecordings) {
@@ -198,7 +208,8 @@ public class RecordingScheduler extends TvInputCallback implements ScheduledReco
// recording service being wrongly pushed back to background in updateInternal().
return scheduledRecordings.size() > 0
|| (mLastStartTimePendingMs > mClock.currentTimeMillis()
- && mLastStartTimePendingMs < mClock.currentTimeMillis() + SOON_DURATION_IN_MS);
+ && mLastStartTimePendingMs
+ < mClock.currentTimeMillis() + SOON_DURATION_IN_MS);
}
private boolean isDbLoaded() {
@@ -269,18 +280,32 @@ public class RecordingScheduler extends TvInputCallback implements ScheduledReco
TvInputInfo input = Utils.getTvInputInfoForInputId(mContext, schedule.getInputId());
if (input == null) {
Log.e(TAG, "Can't find input for " + schedule);
- mDataManager.changeState(schedule, ScheduledRecording.STATE_RECORDING_FAILED);
+ mDataManager.changeState(
+ schedule,
+ ScheduledRecording.STATE_RECORDING_FAILED,
+ ScheduledRecording.FAILED_REASON_INPUT_UNAVAILABLE);
return;
}
if (!input.canRecord() || input.getTunerCount() <= 0) {
Log.e(TAG, "TV input doesn't support recording: " + input);
- mDataManager.changeState(schedule, ScheduledRecording.STATE_RECORDING_FAILED);
+ mDataManager.changeState(
+ schedule,
+ ScheduledRecording.STATE_RECORDING_FAILED,
+ ScheduledRecording.FAILED_REASON_INPUT_DVR_UNSUPPORTED);
return;
}
InputTaskScheduler inputTaskScheduler = mInputSchedulerMap.get(input.getId());
if (inputTaskScheduler == null) {
- inputTaskScheduler = new InputTaskScheduler(mContext, input, mLooper,
- mChannelDataManager, mDvrManager, mDataManager, mSessionManager, mClock);
+ inputTaskScheduler =
+ new InputTaskScheduler(
+ mContext,
+ input,
+ mLooper,
+ mChannelDataManager,
+ mDvrManager,
+ mDataManager,
+ mSessionManager,
+ mClock);
mInputSchedulerMap.put(input.getId(), inputTaskScheduler);
}
inputTaskScheduler.addSchedule(schedule);
@@ -290,8 +315,9 @@ public class RecordingScheduler extends TvInputCallback implements ScheduledReco
}
private void updateNextAlarm() {
- long nextStartTime = mDataManager.getNextScheduledStartTimeAfter(
- Math.max(mLastStartTimePendingMs, mClock.currentTimeMillis()));
+ long nextStartTime =
+ mDataManager.getNextScheduledStartTimeAfter(
+ Math.max(mLastStartTimePendingMs, mClock.currentTimeMillis()));
if (nextStartTime != DvrDataManager.NEXT_START_TIME_NOT_FOUND) {
long wakeAt = nextStartTime - MS_TO_WAKE_BEFORE_START;
if (DEBUG) Log.d(TAG, "Set alarm to record at " + wakeAt);
diff --git a/src/com/android/tv/dvr/recorder/RecordingTask.java b/src/com/android/tv/dvr/recorder/RecordingTask.java
index 14888056..07a29e51 100644
--- a/src/com/android/tv/dvr/recorder/RecordingTask.java
+++ b/src/com/android/tv/dvr/recorder/RecordingTask.java
@@ -26,24 +26,24 @@ import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.support.annotation.WorkerThread;
import android.util.Log;
import android.widget.Toast;
-
import com.android.tv.InputSessionManager;
import com.android.tv.InputSessionManager.RecordingSession;
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
-import com.android.tv.data.Channel;
+import com.android.tv.common.util.Clock;
+import com.android.tv.common.util.CommonUtils;
+import com.android.tv.data.api.Channel;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.WritableDvrDataManager;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.recorder.InputTaskScheduler.HandlerWrapper;
-import com.android.tv.util.Clock;
import com.android.tv.util.Utils;
-
import java.util.Comparator;
import java.util.concurrent.TimeUnit;
@@ -55,58 +55,45 @@ import java.util.concurrent.TimeUnit;
*/
@WorkerThread
@TargetApi(Build.VERSION_CODES.N)
-public class RecordingTask extends RecordingCallback implements Handler.Callback,
- DvrManager.Listener {
+public class RecordingTask extends RecordingCallback
+ implements Handler.Callback, DvrManager.Listener {
private static final String TAG = "RecordingTask";
private static final boolean DEBUG = false;
- /**
- * Compares the end time in ascending order.
- */
- public static final Comparator<RecordingTask> END_TIME_COMPARATOR
- = new Comparator<RecordingTask>() {
- @Override
- public int compare(RecordingTask lhs, RecordingTask rhs) {
- return Long.compare(lhs.getEndTimeMs(), rhs.getEndTimeMs());
- }
- };
-
- /**
- * Compares ID in ascending order.
- */
- public static final Comparator<RecordingTask> ID_COMPARATOR
- = new Comparator<RecordingTask>() {
- @Override
- public int compare(RecordingTask lhs, RecordingTask rhs) {
- return Long.compare(lhs.getScheduleId(), rhs.getScheduleId());
- }
- };
-
- /**
- * Compares the priority in ascending order.
- */
- public static final Comparator<RecordingTask> PRIORITY_COMPARATOR
- = new Comparator<RecordingTask>() {
- @Override
- public int compare(RecordingTask lhs, RecordingTask rhs) {
- return Long.compare(lhs.getPriority(), rhs.getPriority());
- }
- };
+ /** Compares the end time in ascending order. */
+ public static final Comparator<RecordingTask> END_TIME_COMPARATOR =
+ new Comparator<RecordingTask>() {
+ @Override
+ public int compare(RecordingTask lhs, RecordingTask rhs) {
+ return Long.compare(lhs.getEndTimeMs(), rhs.getEndTimeMs());
+ }
+ };
+
+ /** Compares ID in ascending order. */
+ public static final Comparator<RecordingTask> ID_COMPARATOR =
+ new Comparator<RecordingTask>() {
+ @Override
+ public int compare(RecordingTask lhs, RecordingTask rhs) {
+ return Long.compare(lhs.getScheduleId(), rhs.getScheduleId());
+ }
+ };
+
+ /** Compares the priority in ascending order. */
+ public static final Comparator<RecordingTask> PRIORITY_COMPARATOR =
+ new Comparator<RecordingTask>() {
+ @Override
+ public int compare(RecordingTask lhs, RecordingTask rhs) {
+ return Long.compare(lhs.getPriority(), rhs.getPriority());
+ }
+ };
- @VisibleForTesting
- static final int MSG_INITIALIZE = 1;
- @VisibleForTesting
- static final int MSG_START_RECORDING = 2;
- @VisibleForTesting
- static final int MSG_STOP_RECORDING = 3;
- /**
- * Message to update schedule.
- */
+ @VisibleForTesting static final int MSG_INITIALIZE = 1;
+ @VisibleForTesting static final int MSG_START_RECORDING = 2;
+ @VisibleForTesting static final int MSG_STOP_RECORDING = 3;
+ /** Message to update schedule. */
public static final int MSG_UDPATE_SCHEDULE = 4;
- /**
- * The time when the start command will be sent before the recording starts.
- */
+ /** The time when the start command will be sent before the recording starts. */
public static final long RECORDING_EARLY_START_OFFSET_MS = TimeUnit.SECONDS.toMillis(3);
/**
* If the recording starts later than the scheduled start time or ends before the scheduled end
@@ -126,6 +113,7 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
ERROR,
RELEASED,
}
+
private final InputSessionManager mSessionManager;
private final DvrManager mDvrManager;
private final Context mContext;
@@ -142,9 +130,14 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
private Uri mRecordedProgramUri;
private boolean mCanceled;
- RecordingTask(Context context, ScheduledRecording scheduledRecording, Channel channel,
- DvrManager dvrManager, InputSessionManager sessionManager,
- WritableDvrDataManager dataManager, Clock clock) {
+ RecordingTask(
+ Context context,
+ ScheduledRecording scheduledRecording,
+ Channel channel,
+ DvrManager dvrManager,
+ InputSessionManager sessionManager,
+ WritableDvrDataManager dataManager,
+ Clock clock) {
mContext = context;
mScheduledRecording = scheduledRecording;
mChannel = channel;
@@ -163,8 +156,10 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
@Override
public boolean handleMessage(Message msg) {
if (DEBUG) Log.d(TAG, "handleMessage " + msg);
- SoftPreconditions.checkState(msg.what == HandlerWrapper.MESSAGE_REMOVE || mHandler != null,
- TAG, "Null handler trying to handle " + msg);
+ SoftPreconditions.checkState(
+ msg.what == HandlerWrapper.MESSAGE_REMOVE || mHandler != null,
+ TAG,
+ "Null handler trying to handle " + msg);
try {
switch (msg.what) {
case MSG_INITIALIZE:
@@ -185,7 +180,7 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
release();
return false;
default:
- SoftPreconditions.checkArgument(false, TAG, "unexpected message type " + msg);
+ SoftPreconditions.checkArgument(false, TAG, "unexpected message type %s", msg);
break;
}
return true;
@@ -200,7 +195,7 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
public void onDisconnected(String inputId) {
if (DEBUG) Log.d(TAG, "onDisconnected(" + inputId + ")");
if (mRecordingSession != null && mState != State.FINISHED) {
- failAndQuit();
+ failAndQuit(ScheduledRecording.FAILED_REASON_NOT_FINISHED);
}
}
@@ -208,7 +203,7 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
public void onConnectionFailed(String inputId) {
if (DEBUG) Log.d(TAG, "onConnectionFailed(" + inputId + ")");
if (mRecordingSession != null) {
- failAndQuit();
+ failAndQuit(ScheduledRecording.FAILED_REASON_CONNECTION_FAILED);
}
}
@@ -219,23 +214,27 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
return;
}
mState = State.CONNECTED;
- if (mHandler == null || !sendEmptyMessageAtAbsoluteTime(MSG_START_RECORDING,
- mScheduledRecording.getStartTimeMs() - RECORDING_EARLY_START_OFFSET_MS)) {
- failAndQuit();
+ if (mHandler == null
+ || !sendEmptyMessageAtAbsoluteTime(
+ MSG_START_RECORDING,
+ mScheduledRecording.getStartTimeMs() - RECORDING_EARLY_START_OFFSET_MS)) {
+ failAndQuit(ScheduledRecording.FAILED_REASON_MESSAGE_NOT_SENT);
}
}
@Override
public void onRecordingStopped(Uri recordedProgramUri) {
- if (DEBUG) Log.d(TAG, "onRecordingStopped");
+ Log.i(TAG, "Recording Stopped: " + mScheduledRecording);
+ Log.i(TAG, "Recording Stopped: stored as " + recordedProgramUri);
if (mRecordingSession == null) {
return;
}
mRecordedProgramUri = recordedProgramUri;
mState = State.FINISHED;
int state = ScheduledRecording.STATE_RECORDING_FINISHED;
- if (mStartedWithClipping || mScheduledRecording.getEndTimeMs() - CLIPPED_THRESHOLD_MS
- > mClock.currentTimeMillis()) {
+ if (mStartedWithClipping
+ || mScheduledRecording.getEndTimeMs() - CLIPPED_THRESHOLD_MS
+ > mClock.currentTimeMillis()) {
state = ScheduledRecording.STATE_RECORDING_CLIPPED;
}
updateRecordingState(state);
@@ -247,65 +246,89 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
@Override
public void onError(int reason) {
- if (DEBUG) Log.d(TAG, "onError reason " + reason);
+ Log.i(TAG, "Recording failed with code=" + reason + " for " + mScheduledRecording);
if (mRecordingSession == null) {
return;
}
+ int error;
switch (reason) {
case TvInputManager.RECORDING_ERROR_INSUFFICIENT_SPACE:
- mMainThreadHandler.post(new Runnable() {
- @Override
- public void run() {
- if (TvApplication.getSingletons(mContext).getMainActivityWrapper()
- .isResumed()) {
- ScheduledRecording scheduledRecording = mDataManager
- .getScheduledRecording(mScheduledRecording.getId());
- if (scheduledRecording != null) {
- Toast.makeText(mContext.getApplicationContext(),
- mContext.getString(R.string
- .dvr_error_insufficient_space_description_one_recording,
- scheduledRecording.getProgramDisplayTitle(mContext)),
- Toast.LENGTH_LONG)
- .show();
+ Log.i(TAG, "Insufficient space to record " + mScheduledRecording);
+ mMainThreadHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ if (TvSingletons.getSingletons(mContext)
+ .getMainActivityWrapper()
+ .isResumed()) {
+ ScheduledRecording scheduledRecording =
+ mDataManager.getScheduledRecording(
+ mScheduledRecording.getId());
+ if (scheduledRecording != null) {
+ Toast.makeText(
+ mContext.getApplicationContext(),
+ mContext.getString(
+ R.string
+ .dvr_error_insufficient_space_description_one_recording,
+ scheduledRecording
+ .getProgramDisplayTitle(
+ mContext)),
+ Toast.LENGTH_LONG)
+ .show();
+ }
+ } else {
+ Utils.setRecordingFailedReason(
+ mContext.getApplicationContext(),
+ TvInputManager.RECORDING_ERROR_INSUFFICIENT_SPACE);
+ Utils.addFailedScheduledRecordingInfo(
+ mContext.getApplicationContext(),
+ mScheduledRecording.getProgramDisplayTitle(mContext));
+ }
}
- } else {
- Utils.setRecordingFailedReason(mContext.getApplicationContext(),
- TvInputManager.RECORDING_ERROR_INSUFFICIENT_SPACE);
- Utils.addFailedScheduledRecordingInfo(mContext.getApplicationContext(),
- mScheduledRecording.getProgramDisplayTitle(mContext));
- }
- }
- });
- // Pass through
+ });
+ error = ScheduledRecording.FAILED_REASON_INSUFFICIENT_SPACE;
+ break;
+ case TvInputManager.RECORDING_ERROR_RESOURCE_BUSY:
+ error = ScheduledRecording.FAILED_REASON_RESOURCE_BUSY;
+ break;
default:
- failAndQuit();
+ error = ScheduledRecording.FAILED_REASON_OTHER;
break;
}
+ failAndQuit(error);
}
private void handleInit() {
if (DEBUG) Log.d(TAG, "handleInit " + mScheduledRecording);
if (mScheduledRecording.getEndTimeMs() < mClock.currentTimeMillis()) {
Log.w(TAG, "End time already past, not recording " + mScheduledRecording);
- failAndQuit();
+ failAndQuit(ScheduledRecording.FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED);
return;
}
if (mChannel == null) {
Log.w(TAG, "Null channel for " + mScheduledRecording);
- failAndQuit();
+ failAndQuit(ScheduledRecording.FAILED_REASON_INVALID_CHANNEL);
return;
}
if (mChannel.getId() != mScheduledRecording.getChannelId()) {
- Log.w(TAG, "Channel" + mChannel + " does not match scheduled recording "
- + mScheduledRecording);
- failAndQuit();
+ Log.w(
+ TAG,
+ "Channel"
+ + mChannel
+ + " does not match scheduled recording "
+ + mScheduledRecording);
+ failAndQuit(ScheduledRecording.FAILED_REASON_INVALID_CHANNEL);
return;
}
String inputId = mChannel.getInputId();
- mRecordingSession = mSessionManager.createRecordingSession(inputId,
- "recordingTask-" + mScheduledRecording.getId(), this,
- mHandler, mScheduledRecording.getEndTimeMs());
+ mRecordingSession =
+ mSessionManager.createRecordingSession(
+ inputId,
+ "recordingTask-" + mScheduledRecording.getId(),
+ this,
+ mHandler,
+ mScheduledRecording.getEndTimeMs());
mState = State.SESSION_ACQUIRED;
mDvrManager.addListener(this, mHandler);
mRecordingSession.tune(inputId, mChannel.getUri());
@@ -313,8 +336,14 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
}
private void failAndQuit() {
+ failAndQuit(ScheduledRecording.FAILED_REASON_OTHER);
+ }
+
+ private void failAndQuit(Integer reason) {
if (DEBUG) Log.d(TAG, "failAndQuit");
- updateRecordingState(ScheduledRecording.STATE_RECORDING_FAILED);
+ updateRecordingState(
+ ScheduledRecording.STATE_RECORDING_FAILED,
+ reason);
mState = State.ERROR;
sendRemove();
}
@@ -322,16 +351,18 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
private void sendRemove() {
if (DEBUG) Log.d(TAG, "sendRemove");
if (mHandler != null) {
- mHandler.sendMessageAtFrontOfQueue(mHandler.obtainMessage(
- HandlerWrapper.MESSAGE_REMOVE));
+ mHandler.sendMessageAtFrontOfQueue(
+ mHandler.obtainMessage(HandlerWrapper.MESSAGE_REMOVE));
}
}
private void handleStartRecording() {
- if (DEBUG) Log.d(TAG, "handleStartRecording " + mScheduledRecording);
+ Log.i(TAG, "Start Recording: " + mScheduledRecording);
long programId = mScheduledRecording.getProgramId();
- mRecordingSession.startRecording(programId == ScheduledRecording.ID_NOT_SET ? null
- : TvContract.buildProgramUri(programId));
+ mRecordingSession.startRecording(
+ programId == ScheduledRecording.ID_NOT_SET
+ ? null
+ : TvContract.buildProgramUri(programId));
updateRecordingState(ScheduledRecording.STATE_RECORDING_IN_PROGRESS);
// If it starts late, it's clipped.
if (mScheduledRecording.getStartTimeMs() + CLIPPED_THRESHOLD_MS
@@ -340,14 +371,14 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
}
mState = State.RECORDING_STARTED;
- if (!sendEmptyMessageAtAbsoluteTime(MSG_STOP_RECORDING,
- mScheduledRecording.getEndTimeMs())) {
- failAndQuit();
+ if (!sendEmptyMessageAtAbsoluteTime(
+ MSG_STOP_RECORDING, mScheduledRecording.getEndTimeMs())) {
+ failAndQuit(ScheduledRecording.FAILED_REASON_MESSAGE_NOT_SENT);
}
}
private void handleStopRecording() {
- if (DEBUG) Log.d(TAG, "handleStopRecording " + mScheduledRecording);
+ Log.i(TAG, "Stop Recording: " + mScheduledRecording);
mRecordingSession.stopRecording();
mState = State.RECORDING_STOP_REQUESTED;
}
@@ -362,7 +393,7 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
if (mState == State.RECORDING_STARTED) {
mHandler.removeMessages(MSG_STOP_RECORDING);
if (!sendEmptyMessageAtAbsoluteTime(MSG_STOP_RECORDING, schedule.getEndTimeMs())) {
- failAndQuit();
+ failAndQuit(ScheduledRecording.FAILED_REASON_MESSAGE_NOT_SENT);
}
}
}
@@ -377,23 +408,17 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
return mScheduledRecording.getId();
}
- /**
- * Returns the priority.
- */
+ /** Returns the priority. */
public long getPriority() {
return mScheduledRecording.getPriority();
}
- /**
- * Returns the start time of the recording.
- */
+ /** Returns the start time of the recording. */
public long getStartTimeMs() {
return mScheduledRecording.getStartTimeMs();
}
- /**
- * Returns the end time of the recording.
- */
+ /** Returns the end time of the recording. */
public long getEndTimeMs() {
return mScheduledRecording.getEndTimeMs();
}
@@ -410,33 +435,53 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
long now = mClock.currentTimeMillis();
long delay = Math.max(0L, when - now);
if (DEBUG) {
- Log.d(TAG, "Sending message " + what + " with a delay of " + delay / 1000
- + " seconds to arrive at " + Utils.toIsoDateTimeString(when));
+ Log.d(
+ TAG,
+ "Sending message "
+ + what
+ + " with a delay of "
+ + delay / 1000
+ + " seconds to arrive at "
+ + CommonUtils.toIsoDateTimeString(when));
}
return mHandler.sendEmptyMessageDelayed(what, delay);
}
private void updateRecordingState(@ScheduledRecording.RecordingState int state) {
- if (DEBUG) Log.d(TAG, "Updating the state of " + mScheduledRecording + " to " + state);
- mScheduledRecording = ScheduledRecording.buildFrom(mScheduledRecording).setState(state)
- .build();
- runOnMainThread(new Runnable() {
- @Override
- public void run() {
- ScheduledRecording schedule = mDataManager.getScheduledRecording(
- mScheduledRecording.getId());
- if (schedule == null) {
- // Schedule has been deleted. Delete the recorded program.
- removeRecordedProgram();
- } else {
- // Update the state based on the object in DataManager in case when it has been
- // updated. mScheduledRecording will be updated from
- // onScheduledRecordingStateChanged.
- mDataManager.updateScheduledRecording(ScheduledRecording.buildFrom(schedule)
- .setState(state).build());
- }
- }
- });
+ updateRecordingState(state, null);
+ }
+ private void updateRecordingState(
+ @ScheduledRecording.RecordingState int state, @Nullable Integer reason) {
+ if (DEBUG) {
+ Log.d(TAG, "Updating the state of " + mScheduledRecording + " to " + state);
+ }
+ mScheduledRecording =
+ ScheduledRecording.buildFrom(mScheduledRecording).setState(state).build();
+ runOnMainThread(
+ new Runnable() {
+ @Override
+ public void run() {
+ ScheduledRecording schedule =
+ mDataManager.getScheduledRecording(mScheduledRecording.getId());
+ if (schedule == null) {
+ // Schedule has been deleted. Delete the recorded program.
+ removeRecordedProgram();
+ } else {
+ // Update the state based on the object in DataManager in case when it
+ // has been updated. mScheduledRecording will be updated from
+ // onScheduledRecordingStateChanged.
+ ScheduledRecording.Builder builder =
+ ScheduledRecording
+ .buildFrom(schedule)
+ .setState(state);
+ if (state == ScheduledRecording.STATE_RECORDING_FAILED
+ && reason != null) {
+ builder.setFailedReason(reason);
+ }
+ mDataManager.updateScheduledRecording(builder.build());
+ }
+ }
+ });
}
@Override
@@ -447,16 +492,12 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
stop();
}
- /**
- * Starts the task.
- */
+ /** Starts the task. */
public void start() {
mHandler.sendEmptyMessage(MSG_INITIALIZE);
}
- /**
- * Stops the task.
- */
+ /** Stops the task. */
public void stop() {
if (DEBUG) Log.d(TAG, "stop");
switch (mState) {
@@ -480,9 +521,7 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
}
}
- /**
- * Cancels the task
- */
+ /** Cancels the task */
public void cancel() {
if (DEBUG) Log.d(TAG, "cancel");
mCanceled = true;
@@ -490,12 +529,12 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
removeRecordedProgram();
}
- /**
- * Clean up the task.
- */
+ /** Clean up the task. */
public void cleanUp() {
if (mState == State.RECORDING_STARTED || mState == State.RECORDING_STOP_REQUESTED) {
- updateRecordingState(ScheduledRecording.STATE_RECORDING_FAILED);
+ updateRecordingState(
+ ScheduledRecording.STATE_RECORDING_FAILED,
+ ScheduledRecording.FAILED_REASON_SCHEDULER_STOPPED);
}
release();
if (mHandler != null) {
@@ -509,14 +548,15 @@ public class RecordingTask extends RecordingCallback implements Handler.Callback
}
private void removeRecordedProgram() {
- runOnMainThread(new Runnable() {
- @Override
- public void run() {
- if (mRecordedProgramUri != null) {
- mDvrManager.removeRecordedProgram(mRecordedProgramUri);
- }
- }
- });
+ runOnMainThread(
+ new Runnable() {
+ @Override
+ public void run() {
+ if (mRecordedProgramUri != null) {
+ mDvrManager.removeRecordedProgram(mRecordedProgramUri);
+ }
+ }
+ });
}
private void runOnMainThread(Runnable runnable) {
diff --git a/src/com/android/tv/dvr/recorder/ScheduledProgramReaper.java b/src/com/android/tv/dvr/recorder/ScheduledProgramReaper.java
index d958c4a1..dd106e1c 100644
--- a/src/com/android/tv/dvr/recorder/ScheduledProgramReaper.java
+++ b/src/com/android/tv/dvr/recorder/ScheduledProgramReaper.java
@@ -17,24 +17,18 @@
package com.android.tv.dvr.recorder;
import android.support.annotation.MainThread;
-import android.support.annotation.VisibleForTesting;
-
+import com.android.tv.common.util.Clock;
import com.android.tv.dvr.WritableDvrDataManager;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.SeriesRecording;
-import com.android.tv.util.Clock;
-
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
-/**
- * Deletes {@link ScheduledRecording} older than {@value @DAYS} days.
- */
-class ScheduledProgramReaper implements Runnable {
+/** Deletes {@link ScheduledRecording} older than {@value @DAYS} days. */
+public class ScheduledProgramReaper implements Runnable {
- @VisibleForTesting
- static final int DAYS = 2;
+ public static final int DAYS = 7;
private final WritableDvrDataManager mDvrDataManager;
private final Clock mClock;
@@ -54,7 +48,7 @@ class ScheduledProgramReaper implements Runnable {
// series recording.
if (r.getEndTimeMs() < cutoff
&& (r.getSeriesRecordingId() == SeriesRecording.ID_NOT_SET
- || r.getState() != ScheduledRecording.STATE_RECORDING_FINISHED)) {
+ || r.getState() != ScheduledRecording.STATE_RECORDING_FINISHED)) {
toRemove.add(r);
}
}
diff --git a/src/com/android/tv/dvr/recorder/SeriesRecordingScheduler.java b/src/com/android/tv/dvr/recorder/SeriesRecordingScheduler.java
index 15508c24..4f7a789b 100644
--- a/src/com/android/tv/dvr/recorder/SeriesRecordingScheduler.java
+++ b/src/com/android/tv/dvr/recorder/SeriesRecordingScheduler.java
@@ -27,27 +27,23 @@ import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.LongSparseArray;
-
-import com.android.tv.ApplicationSingletons;
-import com.android.tv.TvApplication;
-import com.android.tv.common.CollectionUtils;
-import com.android.tv.common.SharedPreferencesUtils;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
+import com.android.tv.common.experiments.Experiments;
+import com.android.tv.common.util.CollectionUtils;
+import com.android.tv.common.util.SharedPreferencesUtils;
import com.android.tv.data.Program;
-import com.android.tv.data.epg.EpgFetcher;
+import com.android.tv.data.epg.EpgReader;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
import com.android.tv.dvr.DvrDataManager.SeriesRecordingListener;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.WritableDvrDataManager;
-import com.android.tv.dvr.data.SeasonEpisodeNumber;
import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeasonEpisodeNumber;
import com.android.tv.dvr.data.SeriesInfo;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.dvr.provider.EpisodicProgramLoadTask;
-import com.android.tv.experiments.Experiments;
-
-import com.android.tv.util.LocationUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -60,12 +56,14 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import javax.inject.Provider;
/**
- * Creates the {@link com.android.tv.dvr.data.ScheduledRecording}s for
- * the {@link com.android.tv.dvr.data.SeriesRecording}.
- * <p>
- * The current implementation assumes that the series recordings are scheduled only for one channel.
+ * Creates the {@link com.android.tv.dvr.data.ScheduledRecording}s for the {@link
+ * com.android.tv.dvr.data.SeriesRecording}.
+ *
+ * <p>The current implementation assumes that the series recordings are scheduled only for one
+ * channel.
*/
@TargetApi(Build.VERSION_CODES.N)
public class SeriesRecordingScheduler {
@@ -78,9 +76,7 @@ public class SeriesRecordingScheduler {
@SuppressLint("StaticFieldLeak")
private static SeriesRecordingScheduler sInstance;
- /**
- * Creates and returns the {@link SeriesRecordingScheduler}.
- */
+ /** Creates and returns the {@link SeriesRecordingScheduler}. */
public static synchronized SeriesRecordingScheduler getInstance(Context context) {
if (sInstance == null) {
sInstance = new SeriesRecordingScheduler(context);
@@ -100,54 +96,59 @@ public class SeriesRecordingScheduler {
private boolean mPaused;
private final Set<Long> mPendingSeriesRecordings = new ArraySet<>();
- private final SeriesRecordingListener mSeriesRecordingListener = new SeriesRecordingListener() {
- @Override
- public void onSeriesRecordingAdded(SeriesRecording... seriesRecordings) {
- for (SeriesRecording seriesRecording : seriesRecordings) {
- executeFetchSeriesInfoTask(seriesRecording);
- }
- }
-
- @Override
- public void onSeriesRecordingRemoved(SeriesRecording... seriesRecordings) {
- // Cancel the update.
- for (Iterator<SeriesRecordingUpdateTask> iter = mScheduleTasks.iterator();
- iter.hasNext(); ) {
- SeriesRecordingUpdateTask task = iter.next();
- if (CollectionUtils.subtract(task.getSeriesRecordings(), seriesRecordings,
- SeriesRecording.ID_COMPARATOR).isEmpty()) {
- task.cancel(true);
- iter.remove();
+ private final SeriesRecordingListener mSeriesRecordingListener =
+ new SeriesRecordingListener() {
+ @Override
+ public void onSeriesRecordingAdded(SeriesRecording... seriesRecordings) {
+ for (SeriesRecording seriesRecording : seriesRecordings) {
+ executeFetchSeriesInfoTask(seriesRecording);
+ }
}
- }
- for (SeriesRecording seriesRecording : seriesRecordings) {
- FetchSeriesInfoTask task = mFetchSeriesInfoTasks.get(seriesRecording.getId());
- if (task != null) {
- task.cancel(true);
- mFetchSeriesInfoTasks.remove(seriesRecording.getId());
+
+ @Override
+ public void onSeriesRecordingRemoved(SeriesRecording... seriesRecordings) {
+ // Cancel the update.
+ for (Iterator<SeriesRecordingUpdateTask> iter = mScheduleTasks.iterator();
+ iter.hasNext(); ) {
+ SeriesRecordingUpdateTask task = iter.next();
+ if (CollectionUtils.subtract(
+ task.getSeriesRecordings(),
+ seriesRecordings,
+ SeriesRecording.ID_COMPARATOR)
+ .isEmpty()) {
+ task.cancel(true);
+ iter.remove();
+ }
+ }
+ for (SeriesRecording seriesRecording : seriesRecordings) {
+ FetchSeriesInfoTask task =
+ mFetchSeriesInfoTasks.get(seriesRecording.getId());
+ if (task != null) {
+ task.cancel(true);
+ mFetchSeriesInfoTasks.remove(seriesRecording.getId());
+ }
+ }
}
- }
- }
- @Override
- public void onSeriesRecordingChanged(SeriesRecording... seriesRecordings) {
- List<SeriesRecording> stopped = new ArrayList<>();
- List<SeriesRecording> normal = new ArrayList<>();
- for (SeriesRecording r : seriesRecordings) {
- if (r.isStopped()) {
- stopped.add(r);
- } else {
- normal.add(r);
+ @Override
+ public void onSeriesRecordingChanged(SeriesRecording... seriesRecordings) {
+ List<SeriesRecording> stopped = new ArrayList<>();
+ List<SeriesRecording> normal = new ArrayList<>();
+ for (SeriesRecording r : seriesRecordings) {
+ if (r.isStopped()) {
+ stopped.add(r);
+ } else {
+ normal.add(r);
+ }
+ }
+ if (!stopped.isEmpty()) {
+ onSeriesRecordingRemoved(SeriesRecording.toArray(stopped));
+ }
+ if (!normal.isEmpty()) {
+ updateSchedules(normal);
+ }
}
- }
- if (!stopped.isEmpty()) {
- onSeriesRecordingRemoved(SeriesRecording.toArray(stopped));
- }
- if (!normal.isEmpty()) {
- updateSchedules(normal);
- }
- }
- };
+ };
private final ScheduledRecordingListener mScheduledRecordingListener =
new ScheduledRecordingListener() {
@@ -166,7 +167,8 @@ public class SeriesRecordingScheduler {
List<ScheduledRecording> schedulesForUpdate = new ArrayList<>();
for (ScheduledRecording r : schedules) {
if ((r.getState() == ScheduledRecording.STATE_RECORDING_FAILED
- || r.getState() == ScheduledRecording.STATE_RECORDING_CLIPPED)
+ || r.getState()
+ == ScheduledRecording.STATE_RECORDING_CLIPPED)
&& r.getSeriesRecordingId() != SeriesRecording.ID_NOT_SET
&& !TextUtils.isEmpty(r.getSeasonNumber())
&& !TextUtils.isEmpty(r.getEpisodeNumber())) {
@@ -205,18 +207,17 @@ public class SeriesRecordingScheduler {
private SeriesRecordingScheduler(Context context) {
mContext = context.getApplicationContext();
- ApplicationSingletons appSingletons = TvApplication.getSingletons(context);
- mDvrManager = appSingletons.getDvrManager();
- mDataManager = (WritableDvrDataManager) appSingletons.getDvrDataManager();
- mSharedPreferences = context.getSharedPreferences(
- SharedPreferencesUtils.SHARED_PREF_SERIES_RECORDINGS, Context.MODE_PRIVATE);
- mFetchedSeriesIds.addAll(mSharedPreferences.getStringSet(KEY_FETCHED_SERIES_IDS,
- Collections.emptySet()));
+ TvSingletons tvSingletons = TvSingletons.getSingletons(context);
+ mDvrManager = tvSingletons.getDvrManager();
+ mDataManager = (WritableDvrDataManager) tvSingletons.getDvrDataManager();
+ mSharedPreferences =
+ context.getSharedPreferences(
+ SharedPreferencesUtils.SHARED_PREF_SERIES_RECORDINGS, Context.MODE_PRIVATE);
+ mFetchedSeriesIds.addAll(
+ mSharedPreferences.getStringSet(KEY_FETCHED_SERIES_IDS, Collections.emptySet()));
}
- /**
- * Starts the scheduler.
- */
+ /** Starts the scheduler. */
@MainThread
public void start() {
SoftPreconditions.checkState(mDataManager.isInitialized());
@@ -261,15 +262,16 @@ public class SeriesRecordingScheduler {
private void executeFetchSeriesInfoTask(SeriesRecording seriesRecording) {
if (Experiments.CLOUD_EPG.get()) {
- FetchSeriesInfoTask task = new FetchSeriesInfoTask(seriesRecording);
+ FetchSeriesInfoTask task =
+ new FetchSeriesInfoTask(
+ seriesRecording,
+ TvSingletons.getSingletons(mContext).providesEpgReader());
task.execute();
mFetchSeriesInfoTasks.put(seriesRecording.getId(), task);
}
}
- /**
- * Pauses the updates of the series recordings.
- */
+ /** Pauses the updates of the series recordings. */
public void pauseUpdate() {
if (DEBUG) Log.d(TAG, "Schedule paused");
if (mPaused) {
@@ -287,9 +289,7 @@ public class SeriesRecordingScheduler {
}
}
- /**
- * Resumes the updates of the series recordings.
- */
+ /** Resumes the updates of the series recordings. */
public void resumeUpdate() {
if (DEBUG) Log.d(TAG, "Schedule resumed");
if (!mPaused) {
@@ -329,25 +329,28 @@ public class SeriesRecordingScheduler {
mPendingSeriesRecordings.add(r.getId());
}
if (DEBUG) {
- Log.d(TAG, "The scheduler has been paused. Adding to the pending list. size="
- + mPendingSeriesRecordings.size());
+ Log.d(
+ TAG,
+ "The scheduler has been paused. Adding to the pending list. size="
+ + mPendingSeriesRecordings.size());
}
return;
}
Set<SeriesRecording> previousSeriesRecordings = new HashSet<>();
for (Iterator<SeriesRecordingUpdateTask> iter = mScheduleTasks.iterator();
- iter.hasNext(); ) {
+ iter.hasNext(); ) {
SeriesRecordingUpdateTask task = iter.next();
- if (CollectionUtils.containsAny(task.getSeriesRecordings(), seriesRecordings,
- SeriesRecording.ID_COMPARATOR)) {
+ if (CollectionUtils.containsAny(
+ task.getSeriesRecordings(), seriesRecordings, SeriesRecording.ID_COMPARATOR)) {
// The task is affected by the seriesRecordings
task.cancel(true);
previousSeriesRecordings.addAll(task.getSeriesRecordings());
iter.remove();
}
}
- List<SeriesRecording> seriesRecordingsToUpdate = CollectionUtils.union(seriesRecordings,
- previousSeriesRecordings, SeriesRecording.ID_COMPARATOR);
+ List<SeriesRecording> seriesRecordingsToUpdate =
+ CollectionUtils.union(
+ seriesRecordings, previousSeriesRecordings, SeriesRecording.ID_COMPARATOR);
for (Iterator<SeriesRecording> iter = seriesRecordingsToUpdate.iterator();
iter.hasNext(); ) {
SeriesRecording seriesRecording = mDataManager.getSeriesRecording(iter.next().getId());
@@ -367,8 +370,8 @@ public class SeriesRecordingScheduler {
task.execute();
} else {
for (SeriesRecording seriesRecording : seriesRecordingsToUpdate) {
- SeriesRecordingUpdateTask task = new SeriesRecordingUpdateTask(
- Collections.singletonList(seriesRecording));
+ SeriesRecordingUpdateTask task =
+ new SeriesRecordingUpdateTask(Collections.singletonList(seriesRecording));
mScheduleTasks.add(task);
if (DEBUG) Log.d(TAG, "Added schedule task: " + task);
task.execute();
@@ -389,8 +392,9 @@ public class SeriesRecordingScheduler {
* Pick one program per an episode.
*
* <p>Note that the programs which has been already scheduled have the highest priority, and all
- * of them are added even though they are the same episodes. That's because the schedules
- * should be added to the series recording.
+ * of them are added even though they are the same episodes. That's because the schedules should
+ * be added to the series recording.
+ *
* <p>If there are no existing schedules for an episode, one program which starts earlier is
* picked.
*/
@@ -399,11 +403,10 @@ public class SeriesRecordingScheduler {
return pickOneProgramPerEpisode(mDataManager, seriesRecordings, programs);
}
- /**
- * @see #pickOneProgramPerEpisode(List, List)
- */
+ /** @see #pickOneProgramPerEpisode(List, List) */
public static LongSparseArray<List<Program>> pickOneProgramPerEpisode(
- DvrDataManager dataManager, List<SeriesRecording> seriesRecordings,
+ DvrDataManager dataManager,
+ List<SeriesRecording> seriesRecordings,
List<Program> programs) {
// Initialize.
LongSparseArray<List<Program>> result = new LongSparseArray<>();
@@ -422,8 +425,11 @@ public class SeriesRecordingScheduler {
result.get(seriesRecordingId).add(program);
continue;
}
- SeasonEpisodeNumber seasonEpisodeNumber = new SeasonEpisodeNumber(seriesRecordingId,
- program.getSeasonNumber(), program.getEpisodeNumber());
+ SeasonEpisodeNumber seasonEpisodeNumber =
+ new SeasonEpisodeNumber(
+ seriesRecordingId,
+ program.getSeasonNumber(),
+ program.getEpisodeNumber());
List<Program> programsForEpisode = programsForEpisodeMap.get(seasonEpisodeNumber);
if (programsForEpisode == null) {
programsForEpisode = new ArrayList<>();
@@ -434,22 +440,24 @@ public class SeriesRecordingScheduler {
// Pick one program.
for (Entry<SeasonEpisodeNumber, List<Program>> entry : programsForEpisodeMap.entrySet()) {
List<Program> programsForEpisode = entry.getValue();
- Collections.sort(programsForEpisode, new Comparator<Program>() {
- @Override
- public int compare(Program lhs, Program rhs) {
- // Place the existing schedule first.
- boolean lhsScheduled = isProgramScheduled(dataManager, lhs);
- boolean rhsScheduled = isProgramScheduled(dataManager, rhs);
- if (lhsScheduled && !rhsScheduled) {
- return -1;
- }
- if (!lhsScheduled && rhsScheduled) {
- return 1;
- }
- // Sort by the start time in ascending order.
- return lhs.compareTo(rhs);
- }
- });
+ Collections.sort(
+ programsForEpisode,
+ new Comparator<Program>() {
+ @Override
+ public int compare(Program lhs, Program rhs) {
+ // Place the existing schedule first.
+ boolean lhsScheduled = isProgramScheduled(dataManager, lhs);
+ boolean rhsScheduled = isProgramScheduled(dataManager, rhs);
+ if (lhsScheduled && !rhsScheduled) {
+ return -1;
+ }
+ if (!lhsScheduled && rhsScheduled) {
+ return 1;
+ }
+ // Sort by the start time in ascending order.
+ return lhs.compareTo(rhs);
+ }
+ });
boolean added = false;
// Add all the scheduled programs
List<Program> programsForSeries = result.get(entry.getKey().seriesRecordingId);
@@ -469,8 +477,8 @@ public class SeriesRecordingScheduler {
private static boolean isProgramScheduled(DvrDataManager dataManager, Program program) {
ScheduledRecording schedule =
dataManager.getScheduledRecordingForProgramId(program.getId());
- return schedule != null && schedule.getState()
- == ScheduledRecording.STATE_RECORDING_NOT_STARTED;
+ return schedule != null
+ && schedule.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED;
}
private void updateFetchedSeries() {
@@ -478,8 +486,8 @@ public class SeriesRecordingScheduler {
}
/**
- * This works only for the existing series recordings. Do not use this task for the
- * "adding series recording" UI.
+ * This works only for the existing series recordings. Do not use this task for the "adding
+ * series recording" UI.
*/
private class SeriesRecordingUpdateTask extends EpisodicProgramLoadTask {
SeriesRecordingUpdateTask(List<SeriesRecording> seriesRecordings) {
@@ -491,16 +499,17 @@ public class SeriesRecordingScheduler {
if (DEBUG) Log.d(TAG, "onPostExecute: updating schedules with programs:" + programs);
mScheduleTasks.remove(this);
if (programs == null) {
- Log.e(TAG, "Creating schedules for series recording failed: "
- + getSeriesRecordings());
+ Log.e(
+ TAG,
+ "Creating schedules for series recording failed: " + getSeriesRecordings());
return;
}
- LongSparseArray<List<Program>> seriesProgramMap = pickOneProgramPerEpisode(
- getSeriesRecordings(), programs);
+ LongSparseArray<List<Program>> seriesProgramMap =
+ pickOneProgramPerEpisode(getSeriesRecordings(), programs);
for (SeriesRecording seriesRecording : getSeriesRecordings()) {
// Check the series recording is still valid.
- SeriesRecording actualSeriesRecording = mDataManager.getSeriesRecording(
- seriesRecording.getId());
+ SeriesRecording actualSeriesRecording =
+ mDataManager.getSeriesRecording(seriesRecording.getId());
if (actualSeriesRecording == null || actualSeriesRecording.isStopped()) {
continue;
}
@@ -520,35 +529,39 @@ public class SeriesRecordingScheduler {
@Override
public String toString() {
return "SeriesRecordingUpdateTask:{"
- + "series_recordings=" + getSeriesRecordings()
+ + "series_recordings="
+ + getSeriesRecordings()
+ "}";
}
}
private class FetchSeriesInfoTask extends AsyncTask<Void, Void, SeriesInfo> {
- private SeriesRecording mSeriesRecording;
+ private final SeriesRecording mSeriesRecording;
+ private final Provider<EpgReader> mEpgReaderProvider;
- FetchSeriesInfoTask(SeriesRecording seriesRecording) {
+ FetchSeriesInfoTask(
+ SeriesRecording seriesRecording, Provider<EpgReader> epgReaderProvider) {
mSeriesRecording = seriesRecording;
+ mEpgReaderProvider = epgReaderProvider;
}
@Override
protected SeriesInfo doInBackground(Void... voids) {
- return EpgFetcher.createEpgReader(mContext, LocationUtils.getCurrentCountry(mContext))
- .getSeriesInfo(mSeriesRecording.getSeriesId());
+ return mEpgReaderProvider.get().getSeriesInfo(mSeriesRecording.getSeriesId());
}
@Override
protected void onPostExecute(SeriesInfo seriesInfo) {
if (seriesInfo != null) {
- mDataManager.updateSeriesRecording(SeriesRecording.buildFrom(mSeriesRecording)
- .setTitle(seriesInfo.getTitle())
- .setDescription(seriesInfo.getDescription())
- .setLongDescription(seriesInfo.getLongDescription())
- .setCanonicalGenreIds(seriesInfo.getCanonicalGenreIds())
- .setPosterUri(seriesInfo.getPosterUri())
- .setPhotoUri(seriesInfo.getPhotoUri())
- .build());
+ mDataManager.updateSeriesRecording(
+ SeriesRecording.buildFrom(mSeriesRecording)
+ .setTitle(seriesInfo.getTitle())
+ .setDescription(seriesInfo.getDescription())
+ .setLongDescription(seriesInfo.getLongDescription())
+ .setCanonicalGenreIds(seriesInfo.getCanonicalGenreIds())
+ .setPosterUri(seriesInfo.getPosterUri())
+ .setPhotoUri(seriesInfo.getPhotoUri())
+ .build());
mFetchedSeriesIds.add(seriesInfo.getId());
updateFetchedSeries();
}
diff --git a/src/com/android/tv/dvr/ui/BigArguments.java b/src/com/android/tv/dvr/ui/BigArguments.java
index ec3b5065..0d6ff8b1 100644
--- a/src/com/android/tv/dvr/ui/BigArguments.java
+++ b/src/com/android/tv/dvr/ui/BigArguments.java
@@ -17,37 +17,27 @@
package com.android.tv.dvr.ui;
import android.support.annotation.NonNull;
-
import com.android.tv.common.SoftPreconditions;
-
import java.util.HashMap;
import java.util.Map;
-/**
- * Stores the object to pass through activities/fragments.
- */
+/** Stores the object to pass through activities/fragments. */
public class BigArguments {
- private final static String TAG = "BigArguments";
+ private static final String TAG = "BigArguments";
private static Map<String, Object> sBigArgumentMap = new HashMap<>();
- /**
- * Sets the argument.
- */
+ /** Sets the argument. */
public static void setArgument(String name, @NonNull Object value) {
SoftPreconditions.checkState(value != null, TAG, "Set argument, but value is null");
sBigArgumentMap.put(name, value);
}
- /**
- * Returns the argument which is associated to the name.
- */
+ /** Returns the argument which is associated to the name. */
public static Object getArgument(String name) {
return sBigArgumentMap.get(name);
}
- /**
- * Resets the arguments.
- */
+ /** Resets the arguments. */
public static void reset() {
sBigArgumentMap.clear();
}
diff --git a/src/com/android/tv/dvr/ui/ChangeImageTransformWithScaledParent.java b/src/com/android/tv/dvr/ui/ChangeImageTransformWithScaledParent.java
index cddece73..32679421 100644
--- a/src/com/android/tv/dvr/ui/ChangeImageTransformWithScaledParent.java
+++ b/src/com/android/tv/dvr/ui/ChangeImageTransformWithScaledParent.java
@@ -26,16 +26,14 @@ import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
-
import com.android.tv.R;
-
import java.util.Map;
/**
- * TODO: Remove this class once b/32405620 is fixed.
- * This class is for the workaround of b/32405620 and only for the shared element transition between
- * {@link com.android.tv.dvr.ui.browse.RecordingCardView} and
- * {@link com.android.tv.dvr.ui.browse.DvrDetailsActivity}.
+ * TODO: Remove this class once b/32405620 is fixed. This class is for the workaround of b/32405620
+ * and only for the shared element transition between {@link
+ * com.android.tv.dvr.ui.browse.RecordingCardView} and {@link
+ * com.android.tv.dvr.ui.browse.DvrDetailsActivity}.
*/
public class ChangeImageTransformWithScaledParent extends ChangeImageTransform {
private static final String PROPNAME_MATRIX = "android:changeImageTransform:matrix";
@@ -60,7 +58,8 @@ public class ChangeImageTransformWithScaledParent extends ChangeImageTransform {
View view = transitionValues.view;
Map<String, Object> values = transitionValues.values;
Matrix matrix = (Matrix) values.get(PROPNAME_MATRIX);
- if (matrix != null && view.getId() == R.id.details_overview_image
+ if (matrix != null
+ && view.getId() == R.id.details_overview_image
&& view instanceof ImageView) {
ImageView imageView = (ImageView) view;
if (imageView.getScaleType() == ScaleType.CENTER_INSIDE
@@ -68,10 +67,13 @@ public class ChangeImageTransformWithScaledParent extends ChangeImageTransform {
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
if (bitmap.getWidth() < imageView.getWidth()
&& bitmap.getHeight() < imageView.getHeight()) {
- float scale = imageView.getContext().getResources().getFraction(
- R.fraction.lb_focus_zoom_factor_medium, 1, 1);
- matrix.postScale(scale, scale, imageView.getWidth() / 2,
- imageView.getHeight() / 2);
+ float scale =
+ imageView
+ .getContext()
+ .getResources()
+ .getFraction(R.fraction.lb_focus_zoom_factor_medium, 1, 1);
+ matrix.postScale(
+ scale, scale, imageView.getWidth() / 2, imageView.getHeight() / 2);
}
}
}
diff --git a/src/com/android/tv/dvr/ui/DvrAlreadyRecordedFragment.java b/src/com/android/tv/dvr/ui/DvrAlreadyRecordedFragment.java
index 62327870..fce94230 100644
--- a/src/com/android/tv/dvr/ui/DvrAlreadyRecordedFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrAlreadyRecordedFragment.java
@@ -24,13 +24,11 @@ import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
import android.support.v17.leanback.widget.GuidedAction;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.data.Program;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.data.RecordedProgram;
-
import java.util.List;
/**
@@ -51,13 +49,19 @@ public class DvrAlreadyRecordedFragment extends DvrGuidedStepFragment {
public void onAttach(Context context) {
super.onAttach(context);
mProgram = getArguments().getParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM);
- DvrManager dvrManager = TvApplication.getSingletons(context).getDvrManager();
- mDuplicate = dvrManager.getRecordedProgram(mProgram.getTitle(),
- mProgram.getSeasonNumber(), mProgram.getEpisodeNumber());
+ DvrManager dvrManager = TvSingletons.getSingletons(context).getDvrManager();
+ mDuplicate =
+ dvrManager.getRecordedProgram(
+ mProgram.getTitle(),
+ mProgram.getSeasonNumber(),
+ mProgram.getEpisodeNumber());
if (mDuplicate == null) {
dvrManager.addSchedule(mProgram);
- DvrUiHelper.showAddScheduleToast(context, mProgram.getTitle(),
- mProgram.getStartTimeUtcMillis(), mProgram.getEndTimeUtcMillis());
+ DvrUiHelper.showAddScheduleToast(
+ context,
+ mProgram.getTitle(),
+ mProgram.getStartTimeUtcMillis(),
+ mProgram.getEndTimeUtcMillis());
dismissDialog();
}
}
@@ -74,18 +78,21 @@ public class DvrAlreadyRecordedFragment extends DvrGuidedStepFragment {
@Override
public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
Context context = getContext();
- actions.add(new GuidedAction.Builder(context)
- .id(ACTION_RECORD_ANYWAY)
- .title(R.string.dvr_action_record_anyway)
- .build());
- actions.add(new GuidedAction.Builder(context)
- .id(ACTION_WATCH)
- .title(R.string.dvr_action_watch_now)
- .build());
- actions.add(new GuidedAction.Builder(context)
- .id(ACTION_CANCEL)
- .title(R.string.dvr_action_record_cancel)
- .build());
+ actions.add(
+ new GuidedAction.Builder(context)
+ .id(ACTION_RECORD_ANYWAY)
+ .title(R.string.dvr_action_record_anyway)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(context)
+ .id(ACTION_WATCH)
+ .title(R.string.dvr_action_watch_now)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(context)
+ .id(ACTION_CANCEL)
+ .title(R.string.dvr_action_record_cancel)
+ .build());
}
@Override
diff --git a/src/com/android/tv/dvr/ui/DvrAlreadyScheduledFragment.java b/src/com/android/tv/dvr/ui/DvrAlreadyScheduledFragment.java
index 6da75e55..456ad830 100644
--- a/src/com/android/tv/dvr/ui/DvrAlreadyScheduledFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrAlreadyScheduledFragment.java
@@ -25,13 +25,11 @@ import android.support.annotation.NonNull;
import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
import android.support.v17.leanback.widget.GuidedAction;
import android.text.format.DateUtils;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.data.Program;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.data.ScheduledRecording;
-
import java.util.List;
/**
@@ -52,13 +50,19 @@ public class DvrAlreadyScheduledFragment extends DvrGuidedStepFragment {
public void onAttach(Context context) {
super.onAttach(context);
mProgram = getArguments().getParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM);
- DvrManager dvrManager = TvApplication.getSingletons(context).getDvrManager();
- mDuplicate = dvrManager.getScheduledRecording(mProgram.getTitle(),
- mProgram.getSeasonNumber(), mProgram.getEpisodeNumber());
+ DvrManager dvrManager = TvSingletons.getSingletons(context).getDvrManager();
+ mDuplicate =
+ dvrManager.getScheduledRecording(
+ mProgram.getTitle(),
+ mProgram.getSeasonNumber(),
+ mProgram.getEpisodeNumber());
if (mDuplicate == null) {
dvrManager.addSchedule(mProgram);
- DvrUiHelper.showAddScheduleToast(context, mProgram.getTitle(),
- mProgram.getStartTimeUtcMillis(), mProgram.getEndTimeUtcMillis());
+ DvrUiHelper.showAddScheduleToast(
+ context,
+ mProgram.getTitle(),
+ mProgram.getStartTimeUtcMillis(),
+ mProgram.getEndTimeUtcMillis());
dismissDialog();
}
}
@@ -67,9 +71,13 @@ public class DvrAlreadyScheduledFragment extends DvrGuidedStepFragment {
@Override
public Guidance onCreateGuidance(Bundle savedInstanceState) {
String title = getString(R.string.dvr_already_scheduled_dialog_title);
- String description = getString(R.string.dvr_already_scheduled_dialog_description,
- DateUtils.formatDateTime(getContext(), mDuplicate.getStartTimeMs(),
- DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE));
+ String description =
+ getString(
+ R.string.dvr_already_scheduled_dialog_description,
+ DateUtils.formatDateTime(
+ getContext(),
+ mDuplicate.getStartTimeMs(),
+ DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE));
Drawable image = getResources().getDrawable(R.drawable.ic_warning_white_96dp, null);
return new Guidance(title, description, null, image);
}
@@ -77,18 +85,21 @@ public class DvrAlreadyScheduledFragment extends DvrGuidedStepFragment {
@Override
public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
Context context = getContext();
- actions.add(new GuidedAction.Builder(context)
- .id(ACTION_RECORD_ANYWAY)
- .title(R.string.dvr_action_record_anyway)
- .build());
- actions.add(new GuidedAction.Builder(context)
- .id(ACTION_RECORD_INSTEAD)
- .title(R.string.dvr_action_record_instead)
- .build());
- actions.add(new GuidedAction.Builder(context)
- .id(ACTION_CANCEL)
- .title(R.string.dvr_action_record_cancel)
- .build());
+ actions.add(
+ new GuidedAction.Builder(context)
+ .id(ACTION_RECORD_ANYWAY)
+ .title(R.string.dvr_action_record_anyway)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(context)
+ .id(ACTION_RECORD_INSTEAD)
+ .title(R.string.dvr_action_record_instead)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(context)
+ .id(ACTION_CANCEL)
+ .title(R.string.dvr_action_record_cancel)
+ .build());
}
@Override
diff --git a/src/com/android/tv/dvr/ui/DvrChannelRecordDurationOptionFragment.java b/src/com/android/tv/dvr/ui/DvrChannelRecordDurationOptionFragment.java
index 36659412..6be35cb2 100644
--- a/src/com/android/tv/dvr/ui/DvrChannelRecordDurationOptionFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrChannelRecordDurationOptionFragment.java
@@ -21,15 +21,13 @@ import android.os.Bundle;
import android.support.v17.leanback.app.GuidedStepFragment;
import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
import android.support.v17.leanback.widget.GuidedAction;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
-import com.android.tv.data.Channel;
+import com.android.tv.data.api.Channel;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.ui.DvrConflictFragment.DvrChannelRecordConflictFragment;
-
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -43,8 +41,10 @@ public class DvrChannelRecordDurationOptionFragment extends DvrGuidedStepFragmen
Bundle args = getArguments();
if (args != null) {
long channelId = args.getLong(DvrHalfSizedDialogFragment.KEY_CHANNEL_ID);
- mChannel = TvApplication.getSingletons(getContext()).getChannelDataManager()
- .getChannel(channelId);
+ mChannel =
+ TvSingletons.getSingletons(getContext())
+ .getChannelDataManager()
+ .getChannel(channelId);
}
SoftPreconditions.checkArgument(mChannel != null);
super.onCreate(savedInstanceState);
@@ -66,32 +66,36 @@ public class DvrChannelRecordDurationOptionFragment extends DvrGuidedStepFragmen
mDurations.add(TimeUnit.HOURS.toMillis(1));
mDurations.add(TimeUnit.HOURS.toMillis(3));
- actions.add(new GuidedAction.Builder(getContext())
- .id(++actionId)
- .title(R.string.recording_start_dialog_10_min_duration)
- .build());
- actions.add(new GuidedAction.Builder(getContext())
- .id(++actionId)
- .title(R.string.recording_start_dialog_30_min_duration)
- .build());
- actions.add(new GuidedAction.Builder(getContext())
- .id(++actionId)
- .title(R.string.recording_start_dialog_1_hour_duration)
- .build());
- actions.add(new GuidedAction.Builder(getContext())
- .id(++actionId)
- .title(R.string.recording_start_dialog_3_hours_duration)
- .build());
+ actions.add(
+ new GuidedAction.Builder(getContext())
+ .id(++actionId)
+ .title(R.string.recording_start_dialog_10_min_duration)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(getContext())
+ .id(++actionId)
+ .title(R.string.recording_start_dialog_30_min_duration)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(getContext())
+ .id(++actionId)
+ .title(R.string.recording_start_dialog_1_hour_duration)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(getContext())
+ .id(++actionId)
+ .title(R.string.recording_start_dialog_3_hours_duration)
+ .build());
}
@Override
public void onTrackedGuidedActionClicked(GuidedAction action) {
- DvrManager dvrManager = TvApplication.getSingletons(getContext()).getDvrManager();
+ DvrManager dvrManager = TvSingletons.getSingletons(getContext()).getDvrManager();
long duration = mDurations.get((int) action.getId());
long startTimeMs = System.currentTimeMillis();
long endTimeMs = System.currentTimeMillis() + duration;
- List<ScheduledRecording> conflicts = dvrManager.getConflictingSchedules(
- mChannel.getId(), startTimeMs, endTimeMs);
+ List<ScheduledRecording> conflicts =
+ dvrManager.getConflictingSchedules(mChannel.getId(), startTimeMs, endTimeMs);
dvrManager.addSchedule(mChannel, startTimeMs, endTimeMs);
if (conflicts.isEmpty()) {
dismissDialog();
@@ -102,8 +106,7 @@ public class DvrChannelRecordDurationOptionFragment extends DvrGuidedStepFragmen
args.putLong(DvrHalfSizedDialogFragment.KEY_START_TIME_MS, startTimeMs);
args.putLong(DvrHalfSizedDialogFragment.KEY_END_TIME_MS, endTimeMs);
fragment.setArguments(args);
- GuidedStepFragment.add(getFragmentManager(), fragment,
- R.id.halfsized_dialog_host);
+ GuidedStepFragment.add(getFragmentManager(), fragment, R.id.halfsized_dialog_host);
}
}
diff --git a/src/com/android/tv/dvr/ui/DvrConflictFragment.java b/src/com/android/tv/dvr/ui/DvrConflictFragment.java
index 6f362e68..65759555 100644
--- a/src/com/android/tv/dvr/ui/DvrConflictFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrConflictFragment.java
@@ -27,18 +27,16 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
import com.android.tv.MainActivity;
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
-import com.android.tv.data.Channel;
import com.android.tv.data.Program;
+import com.android.tv.data.api.Channel;
+import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.recorder.ConflictChecker;
import com.android.tv.dvr.recorder.ConflictChecker.OnUpcomingConflictChangeListener;
-import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.util.Utils;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -72,15 +70,16 @@ public abstract class DvrConflictFragment extends DvrGuidedStepFragment {
}
@Override
- public void onCreateActions(@NonNull List<GuidedAction> actions,
- Bundle savedInstanceState) {
- actions.add(new GuidedAction.Builder(getContext())
- .clickAction(GuidedAction.ACTION_ID_OK)
- .build());
- actions.add(new GuidedAction.Builder(getContext())
- .id(ACTION_VIEW_SCHEDULES)
- .title(R.string.dvr_action_view_schedules)
- .build());
+ public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
+ actions.add(
+ new GuidedAction.Builder(getContext())
+ .clickAction(GuidedAction.ACTION_ID_OK)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(getContext())
+ .id(ACTION_VIEW_SCHEDULES)
+ .title(R.string.dvr_action_view_schedules)
+ .build());
}
@Override
@@ -114,33 +113,45 @@ public abstract class DvrConflictFragment extends DvrGuidedStepFragment {
}
switch (titles.size()) {
case 0:
- Log.i(TAG, "Conflict has been resolved by any reason. Maybe input might have"
- + " been deleted.");
+ Log.i(
+ TAG,
+ "Conflict has been resolved by any reason. Maybe input might have"
+ + " been deleted.");
return null;
case 1:
- return getResources().getString(
- R.string.dvr_program_conflict_dialog_description_1, titles.get(0));
+ return getResources()
+ .getString(
+ R.string.dvr_program_conflict_dialog_description_1, titles.get(0));
case 2:
- return getResources().getString(
- R.string.dvr_program_conflict_dialog_description_2, titles.get(0),
- titles.get(1));
+ return getResources()
+ .getString(
+ R.string.dvr_program_conflict_dialog_description_2,
+ titles.get(0),
+ titles.get(1));
case 3:
- return getResources().getString(
- R.string.dvr_program_conflict_dialog_description_3, titles.get(0),
- titles.get(1));
+ return getResources()
+ .getString(
+ R.string.dvr_program_conflict_dialog_description_3,
+ titles.get(0),
+ titles.get(1));
default:
- return getResources().getQuantityString(
- R.plurals.dvr_program_conflict_dialog_description_many,
- titles.size() - LISTED_PROGRAM_COUNT, titles.get(0), titles.get(1),
- titles.size() - LISTED_PROGRAM_COUNT);
+ return getResources()
+ .getQuantityString(
+ R.plurals.dvr_program_conflict_dialog_description_many,
+ titles.size() - LISTED_PROGRAM_COUNT,
+ titles.get(0),
+ titles.get(1),
+ titles.size() - LISTED_PROGRAM_COUNT);
}
}
@Nullable
private String getScheduleTitle(ScheduledRecording schedule) {
if (schedule.getType() == ScheduledRecording.TYPE_TIMED) {
- Channel channel = TvApplication.getSingletons(getContext()).getChannelDataManager()
- .getChannel(schedule.getChannelId());
+ Channel channel =
+ TvSingletons.getSingletons(getContext())
+ .getChannelDataManager()
+ .getChannel(schedule.getChannelId());
if (channel != null) {
return channel.getDisplayName();
} else {
@@ -151,14 +162,13 @@ public abstract class DvrConflictFragment extends DvrGuidedStepFragment {
}
}
- /**
- * A fragment to show the program conflict.
- */
+ /** A fragment to show the program conflict. */
public static class DvrProgramConflictFragment extends DvrConflictFragment {
private Program mProgram;
+
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
+ public View onCreateView(
+ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle args = getArguments();
if (args != null) {
mProgram = args.getParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM);
@@ -168,8 +178,10 @@ public abstract class DvrConflictFragment extends DvrGuidedStepFragment {
SoftPreconditions.checkNotNull(input);
List<ScheduledRecording> conflicts = null;
if (input != null) {
- conflicts = TvApplication.getSingletons(getContext()).getDvrManager()
- .getConflictingSchedules(mProgram);
+ conflicts =
+ TvSingletons.getSingletons(getContext())
+ .getDvrManager()
+ .getConflictingSchedules(mProgram);
}
if (conflicts == null) {
conflicts = Collections.emptyList();
@@ -185,8 +197,10 @@ public abstract class DvrConflictFragment extends DvrGuidedStepFragment {
@Override
public Guidance onCreateGuidance(Bundle savedInstanceState) {
String title = getResources().getString(R.string.dvr_program_conflict_dialog_title);
- String descriptionPrefix = getString(
- R.string.dvr_program_conflict_dialog_description_prefix, mProgram.getTitle());
+ String descriptionPrefix =
+ getString(
+ R.string.dvr_program_conflict_dialog_description_prefix,
+ mProgram.getTitle());
String description = getConflictDescription();
if (description == null) {
dismissDialog();
@@ -201,21 +215,21 @@ public abstract class DvrConflictFragment extends DvrGuidedStepFragment {
}
}
- /**
- * A fragment to show the channel recording conflict.
- */
+ /** A fragment to show the channel recording conflict. */
public static class DvrChannelRecordConflictFragment extends DvrConflictFragment {
private Channel mChannel;
private long mStartTimeMs;
private long mEndTimeMs;
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
+ public View onCreateView(
+ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle args = getArguments();
long channelId = args.getLong(DvrHalfSizedDialogFragment.KEY_CHANNEL_ID);
- mChannel = TvApplication.getSingletons(getContext()).getChannelDataManager()
- .getChannel(channelId);
+ mChannel =
+ TvSingletons.getSingletons(getContext())
+ .getChannelDataManager()
+ .getChannel(channelId);
SoftPreconditions.checkArgument(mChannel != null);
TvInputInfo input = Utils.getTvInputInfoForChannelId(getContext(), mChannel.getId());
SoftPreconditions.checkNotNull(input);
@@ -223,8 +237,11 @@ public abstract class DvrConflictFragment extends DvrGuidedStepFragment {
if (input != null) {
mStartTimeMs = args.getLong(DvrHalfSizedDialogFragment.KEY_START_TIME_MS);
mEndTimeMs = args.getLong(DvrHalfSizedDialogFragment.KEY_END_TIME_MS);
- conflicts = TvApplication.getSingletons(getContext()).getDvrManager()
- .getConflictingSchedules(mChannel.getId(), mStartTimeMs, mEndTimeMs);
+ conflicts =
+ TvSingletons.getSingletons(getContext())
+ .getDvrManager()
+ .getConflictingSchedules(
+ mChannel.getId(), mStartTimeMs, mEndTimeMs);
}
if (conflicts == null) {
conflicts = Collections.emptyList();
@@ -240,9 +257,10 @@ public abstract class DvrConflictFragment extends DvrGuidedStepFragment {
@Override
public Guidance onCreateGuidance(Bundle savedInstanceState) {
String title = getResources().getString(R.string.dvr_channel_conflict_dialog_title);
- String descriptionPrefix = getString(
- R.string.dvr_channel_conflict_dialog_description_prefix,
- mChannel.getDisplayName());
+ String descriptionPrefix =
+ getString(
+ R.string.dvr_channel_conflict_dialog_description_prefix,
+ mChannel.getDisplayName());
String description = getConflictDescription();
if (description == null) {
dismissDialog();
@@ -259,16 +277,16 @@ public abstract class DvrConflictFragment extends DvrGuidedStepFragment {
/**
* A fragment to show the channel watching conflict.
- * <p>
- * This fragment is automatically closed when there are no upcoming conflicts.
+ *
+ * <p>This fragment is automatically closed when there are no upcoming conflicts.
*/
public static class DvrChannelWatchConflictFragment extends DvrConflictFragment
implements OnUpcomingConflictChangeListener {
private long mChannelId;
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
+ public View onCreateView(
+ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle args = getArguments();
if (args != null) {
mChannelId = args.getLong(DvrHalfSizedDialogFragment.KEY_CHANNEL_ID);
@@ -298,24 +316,27 @@ public abstract class DvrConflictFragment extends DvrGuidedStepFragment {
@NonNull
@Override
public Guidance onCreateGuidance(Bundle savedInstanceState) {
- String title = getResources().getString(
- R.string.dvr_epg_channel_watch_conflict_dialog_title);
- String description = getResources().getString(
- R.string.dvr_epg_channel_watch_conflict_dialog_description);
+ String title =
+ getResources().getString(R.string.dvr_epg_channel_watch_conflict_dialog_title);
+ String description =
+ getResources()
+ .getString(R.string.dvr_epg_channel_watch_conflict_dialog_description);
return new Guidance(title, description, null, null);
}
@Override
- public void onCreateActions(@NonNull List<GuidedAction> actions,
- Bundle savedInstanceState) {
- actions.add(new GuidedAction.Builder(getContext())
- .id(ACTION_DELETE_CONFLICT)
- .title(R.string.dvr_action_delete_schedule)
- .build());
- actions.add(new GuidedAction.Builder(getContext())
- .id(ACTION_CANCEL)
- .title(R.string.dvr_action_record_program)
- .build());
+ public void onCreateActions(
+ @NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
+ actions.add(
+ new GuidedAction.Builder(getContext())
+ .id(ACTION_DELETE_CONFLICT)
+ .title(R.string.dvr_action_delete_schedule)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(getContext())
+ .id(ACTION_CANCEL)
+ .title(R.string.dvr_action_record_program)
+ .build());
}
@Override
diff --git a/src/com/android/tv/dvr/ui/DvrFutureProgramInfoFragment.java b/src/com/android/tv/dvr/ui/DvrFutureProgramInfoFragment.java
new file mode 100644
index 00000000..677a6cbb
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/DvrFutureProgramInfoFragment.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 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.dvr.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v17.leanback.widget.GuidanceStylist;
+import android.support.v17.leanback.widget.GuidedAction;
+import com.android.tv.TvSingletons;
+import com.android.tv.data.Program;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.util.Utils;
+import java.util.List;
+
+/**
+ * A fragment which shows the formation of a program.
+ */
+public class DvrFutureProgramInfoFragment extends DvrGuidedStepFragment {
+ private static final long ACTION_ID_VIEW_SCHEDULE = 1;
+ private ScheduledRecording mScheduledRecording;
+ private Program mProgram;
+
+ @Override
+ public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
+ long startTime = mProgram.getStartTimeUtcMillis();
+ // TODO(b/71717923): use R.string when the strings are finalized
+ StringBuilder description = new StringBuilder()
+ .append("This program will start at ")
+ .append(Utils.getDurationString(getContext(), startTime, startTime, false));
+ if (mScheduledRecording != null) {
+ description.append("\nThis program has been scheduled for recording.");
+ }
+ return new GuidanceStylist.Guidance(
+ mProgram.getTitle(), description.toString(), null, null);
+ }
+
+ @Override
+ public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
+ Activity activity = getActivity();
+ mProgram = getArguments().getParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM);
+ mScheduledRecording =
+ TvSingletons.getSingletons(getContext())
+ .getDvrDataManager()
+ .getScheduledRecordingForProgramId(mProgram.getId());
+ actions.add(
+ new GuidedAction.Builder(activity)
+ .id(GuidedAction.ACTION_ID_OK)
+ .title(android.R.string.ok)
+ .build());
+ if (mScheduledRecording != null) {
+ actions.add(
+ new GuidedAction.Builder(activity)
+ .id(ACTION_ID_VIEW_SCHEDULE)
+ .title("View schedules")
+ .build());
+ }
+
+ }
+
+ @Override
+ public void onTrackedGuidedActionClicked(GuidedAction action) {
+ if (action.getId() == ACTION_ID_VIEW_SCHEDULE) {
+ DvrUiHelper.startSchedulesActivity(getContext(), mScheduledRecording);
+ return;
+ }
+ dismissDialog();
+ }
+
+ @Override
+ public String getTrackerPrefix() {
+ return "DvrFutureProgramInfoFragment";
+ }
+}
diff --git a/src/com/android/tv/dvr/ui/DvrGuidedActionsStylist.java b/src/com/android/tv/dvr/ui/DvrGuidedActionsStylist.java
index 6b0c22ff..611962d0 100644
--- a/src/com/android/tv/dvr/ui/DvrGuidedActionsStylist.java
+++ b/src/com/android/tv/dvr/ui/DvrGuidedActionsStylist.java
@@ -24,12 +24,9 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
-
import com.android.tv.R;
-/**
- * Stylist class used for DVR settings {@link GuidedStepFragment}.
- */
+/** Stylist class used for DVR settings {@link GuidedStepFragment}. */
public class DvrGuidedActionsStylist extends GuidedActionsStylist {
private static boolean sInitialized;
private static float sWidthWeight;
@@ -68,11 +65,13 @@ public class DvrGuidedActionsStylist extends GuidedActionsStylist {
return;
}
sInitialized = true;
- sItemHeight = context.getResources().getDimensionPixelSize(
- R.dimen.dvr_settings_one_line_action_container_height);
+ sItemHeight =
+ context.getResources()
+ .getDimensionPixelSize(
+ R.dimen.dvr_settings_one_line_action_container_height);
TypedValue outValue = new TypedValue();
- context.getResources().getValue(R.dimen.dvr_settings_button_actions_list_width_weight,
- outValue, true);
+ context.getResources()
+ .getValue(R.dimen.dvr_settings_button_actions_list_width_weight, outValue, true);
sWidthWeight = outValue.getFloat();
}
}
diff --git a/src/com/android/tv/dvr/ui/DvrGuidedStepFragment.java b/src/com/android/tv/dvr/ui/DvrGuidedStepFragment.java
index ab852e10..a900cc70 100644
--- a/src/com/android/tv/dvr/ui/DvrGuidedStepFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrGuidedStepFragment.java
@@ -26,31 +26,23 @@ import android.support.v17.leanback.widget.VerticalGridView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
-import com.android.tv.ApplicationSingletons;
import com.android.tv.MainActivity;
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
+import com.android.tv.common.recording.RecordingStorageStatusManager;
import com.android.tv.dialog.HalfSizedDialogFragment.OnActionClickListener;
import com.android.tv.dialog.SafeDismissDialogFragment;
import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.DvrStorageStatusManager;
-
import java.util.List;
public abstract class DvrGuidedStepFragment extends TrackedGuidedStepFragment {
- /**
- * Action ID for "recording/scheduling the program anyway".
- */
+ /** Action ID for "recording/scheduling the program anyway". */
public static final int ACTION_RECORD_ANYWAY = 1;
- /**
- * Action ID for "deleting existed recordings".
- */
+ /** Action ID for "deleting existed recordings". */
public static final int ACTION_DELETE_RECORDINGS = 2;
- /**
- * Action ID for "cancelling current recording request".
- */
+ /** Action ID for "cancelling current recording request". */
public static final int ACTION_CANCEL_RECORDING = 3;
+
public static final String UNKNOWN_DVR_ACTION = "Unknown DVR Action";
private DvrManager mDvrManager;
@@ -63,13 +55,13 @@ public abstract class DvrGuidedStepFragment extends TrackedGuidedStepFragment {
@Override
public void onAttach(Context context) {
super.onAttach(context);
- ApplicationSingletons singletons = TvApplication.getSingletons(context);
+ TvSingletons singletons = TvSingletons.getSingletons(context);
mDvrManager = singletons.getDvrManager();
}
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
+ public View onCreateView(
+ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
VerticalGridView actionsList = getGuidedActionsStylist().getActionsGridView();
actionsList.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE);
@@ -122,32 +114,37 @@ public abstract class DvrGuidedStepFragment extends TrackedGuidedStepFragment {
}
/**
- * The inner guided step fragment for
- * {@link com.android.tv.dvr.ui.DvrHalfSizedDialogFragment
+ * The inner guided step fragment for {@link com.android.tv.dvr.ui.DvrHalfSizedDialogFragment
* .DvrNoFreeSpaceErrorDialogFragment}.
*/
public static class DvrNoFreeSpaceErrorFragment extends DvrGuidedStepFragment {
@Override
public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
- return new GuidanceStylist.Guidance(getString(R.string.dvr_error_no_free_space_title),
- getString(R.string.dvr_error_no_free_space_description), null, null);
+ return new GuidanceStylist.Guidance(
+ getString(R.string.dvr_error_no_free_space_title),
+ getString(R.string.dvr_error_no_free_space_description),
+ null,
+ null);
}
@Override
public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
Activity activity = getActivity();
- actions.add(new GuidedAction.Builder(activity)
- .id(ACTION_RECORD_ANYWAY)
- .title(R.string.dvr_action_record_anyway)
- .build());
- actions.add(new GuidedAction.Builder(activity)
- .id(ACTION_DELETE_RECORDINGS)
- .title(R.string.dvr_action_delete_recordings)
- .build());
- actions.add(new GuidedAction.Builder(activity)
- .id(ACTION_CANCEL_RECORDING)
- .title(R.string.dvr_action_record_cancel)
- .build());
+ actions.add(
+ new GuidedAction.Builder(activity)
+ .id(ACTION_RECORD_ANYWAY)
+ .title(R.string.dvr_action_record_anyway)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(activity)
+ .id(ACTION_DELETE_RECORDINGS)
+ .title(R.string.dvr_action_delete_recordings)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(activity)
+ .id(ACTION_CANCEL_RECORDING)
+ .title(R.string.dvr_action_record_cancel)
+ .build());
}
@Override
@@ -157,29 +154,32 @@ public abstract class DvrGuidedStepFragment extends TrackedGuidedStepFragment {
}
/**
- * The inner guided step fragment for
- * {@link com.android.tv.dvr.ui.DvrHalfSizedDialogFragment
+ * The inner guided step fragment for {@link com.android.tv.dvr.ui.DvrHalfSizedDialogFragment
* .DvrSmallSizedStorageErrorDialogFragment}.
*/
public static class DvrSmallSizedStorageErrorFragment extends DvrGuidedStepFragment {
@Override
public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
- String title = getResources().getString(
- R.string.dvr_error_small_sized_storage_title);
- String description = getResources().getString(
- R.string.dvr_error_small_sized_storage_description,
- DvrStorageStatusManager.MIN_STORAGE_SIZE_FOR_DVR_IN_BYTES / 1024
- / 1024 / 1024);
+ String title = getResources().getString(R.string.dvr_error_small_sized_storage_title);
+ String description =
+ getResources()
+ .getString(
+ R.string.dvr_error_small_sized_storage_description,
+ RecordingStorageStatusManager.MIN_STORAGE_SIZE_FOR_DVR_IN_BYTES
+ / 1024
+ / 1024
+ / 1024);
return new GuidanceStylist.Guidance(title, description, null, null);
}
@Override
public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
Activity activity = getActivity();
- actions.add(new GuidedAction.Builder(activity)
- .id(GuidedAction.ACTION_ID_OK)
- .title(android.R.string.ok)
- .build());
+ actions.add(
+ new GuidedAction.Builder(activity)
+ .id(GuidedAction.ACTION_ID_OK)
+ .title(android.R.string.ok)
+ .build());
}
@Override
@@ -192,4 +192,4 @@ public abstract class DvrGuidedStepFragment extends TrackedGuidedStepFragment {
return "DvrSmallSizedStorageErrorFragment";
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/DvrHalfSizedDialogFragment.java b/src/com/android/tv/dvr/ui/DvrHalfSizedDialogFragment.java
index f8ef3850..4a713703 100644
--- a/src/com/android/tv/dvr/ui/DvrHalfSizedDialogFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrHalfSizedDialogFragment.java
@@ -20,47 +20,26 @@ import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v17.leanback.app.GuidedStepFragment;
-import android.support.v17.leanback.widget.GuidedAction;
-import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
import com.android.tv.MainActivity;
import com.android.tv.R;
-import com.android.tv.dvr.DvrStorageStatusManager;
import com.android.tv.dialog.HalfSizedDialogFragment;
import com.android.tv.dvr.ui.DvrConflictFragment.DvrChannelWatchConflictFragment;
import com.android.tv.dvr.ui.DvrConflictFragment.DvrProgramConflictFragment;
import com.android.tv.guide.ProgramGuide;
-import java.util.List;
-
public class DvrHalfSizedDialogFragment extends HalfSizedDialogFragment {
- /**
- * Key for input ID.
- * Type: String.
- */
+ /** Key for input ID. Type: String. */
public static final String KEY_INPUT_ID = "DvrHalfSizedDialogFragment.input_id";
- /**
- * Key for the program.
- * Type: {@link com.android.tv.data.Program}.
- */
+ /** Key for the program. Type: {@link com.android.tv.data.Program}. */
public static final String KEY_PROGRAM = "DvrHalfSizedDialogFragment.program";
- /**
- * Key for the channel ID.
- * Type: long.
- */
+ /** Key for the channel ID. Type: long. */
public static final String KEY_CHANNEL_ID = "DvrHalfSizedDialogFragment.channel_id";
- /**
- * Key for the recording start time in millisecond.
- * Type: long.
- */
+ /** Key for the recording start time in millisecond. Type: long. */
public static final String KEY_START_TIME_MS = "DvrHalfSizedDialogFragment.start_time_ms";
- /**
- * Key for the recording end time in millisecond.
- * Type: long.
- */
+ /** Key for the recording end time in millisecond. Type: long. */
public static final String KEY_END_TIME_MS = "DvrHalfSizedDialogFragment.end_time_ms";
@Override
@@ -93,14 +72,14 @@ public class DvrHalfSizedDialogFragment extends HalfSizedDialogFragment {
private DvrGuidedStepFragment mFragment;
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
+ public View onCreateView(
+ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
mFragment = onCreateGuidedStepFragment();
mFragment.setArguments(getArguments());
mFragment.setOnActionClickListener(getOnActionClickListener());
- GuidedStepFragment.add(getChildFragmentManager(),
- mFragment, R.id.halfsized_dialog_host);
+ GuidedStepFragment.add(
+ getChildFragmentManager(), mFragment, R.id.halfsized_dialog_host);
return view;
}
@@ -158,19 +137,15 @@ public class DvrHalfSizedDialogFragment extends HalfSizedDialogFragment {
}
/** A dialog fragment for {@link DvrMissingStorageErrorFragment}. */
- public static class DvrMissingStorageErrorDialogFragment
- extends DvrGuidedStepDialogFragment {
+ public static class DvrMissingStorageErrorDialogFragment extends DvrGuidedStepDialogFragment {
@Override
protected DvrGuidedStepFragment onCreateGuidedStepFragment() {
return new DvrMissingStorageErrorFragment();
}
}
- /**
- * A dialog fragment to show error message when there is no enough free space to record.
- */
- public static class DvrNoFreeSpaceErrorDialogFragment
- extends DvrGuidedStepDialogFragment {
+ /** A dialog fragment to show error message when there is no enough free space to record. */
+ public static class DvrNoFreeSpaceErrorDialogFragment extends DvrGuidedStepDialogFragment {
@Override
protected DvrGuidedStepFragment onCreateGuidedStepFragment() {
return new DvrGuidedStepFragment.DvrNoFreeSpaceErrorFragment();
@@ -178,8 +153,7 @@ public class DvrHalfSizedDialogFragment extends HalfSizedDialogFragment {
}
/**
- * A dialog fragment to show error message when the current storage is too small to
- * support DVR
+ * A dialog fragment to show error message when the current storage is too small to support DVR
*/
public static class DvrSmallSizedStorageErrorDialogFragment
extends DvrGuidedStepDialogFragment {
@@ -212,4 +186,12 @@ public class DvrHalfSizedDialogFragment extends HalfSizedDialogFragment {
return new DvrAlreadyRecordedFragment();
}
}
-} \ No newline at end of file
+
+ /** A dialog fragment for {@link DvrFutureProgramInfoFragment}. */
+ public static class DvrFutureProgramInfoDialogFragment extends DvrGuidedStepDialogFragment {
+ @Override
+ protected DvrGuidedStepFragment onCreateGuidedStepFragment() {
+ return new DvrFutureProgramInfoFragment();
+ }
+ }
+}
diff --git a/src/com/android/tv/dvr/ui/DvrInsufficientSpaceErrorFragment.java b/src/com/android/tv/dvr/ui/DvrInsufficientSpaceErrorFragment.java
index 182416b6..6fba4d98 100644
--- a/src/com/android/tv/dvr/ui/DvrInsufficientSpaceErrorFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrInsufficientSpaceErrorFragment.java
@@ -22,19 +22,15 @@ import android.content.Intent;
import android.os.Bundle;
import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
import android.support.v17.leanback.widget.GuidedAction;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
import com.android.tv.dvr.ui.browse.DvrBrowseActivity;
-
import java.util.ArrayList;
import java.util.List;
public class DvrInsufficientSpaceErrorFragment extends DvrGuidedStepFragment {
- /**
- * Key for the failed scheduled recordings information.
- */
+ /** Key for the failed scheduled recordings information. */
public static final String FAILED_SCHEDULED_RECORDING_INFOS =
"failed_scheduled_recording_infos";
@@ -54,7 +50,8 @@ public class DvrInsufficientSpaceErrorFragment extends DvrGuidedStepFragment {
}
SoftPreconditions.checkState(
mFailedScheduledRecordingInfos != null && !mFailedScheduledRecordingInfos.isEmpty(),
- TAG, "failed scheduled recording is null");
+ TAG,
+ "failed scheduled recording is null");
}
@Override
@@ -63,28 +60,39 @@ public class DvrInsufficientSpaceErrorFragment extends DvrGuidedStepFragment {
String description;
int failedScheduledRecordingSize = mFailedScheduledRecordingInfos.size();
if (failedScheduledRecordingSize == 1) {
- title = getString(
- R.string.dvr_error_insufficient_space_title_one_recording,
- mFailedScheduledRecordingInfos.get(0));
- description = getString(
- R.string.dvr_error_insufficient_space_description_one_recording,
- mFailedScheduledRecordingInfos.get(0));
+ title =
+ getString(
+ R.string.dvr_error_insufficient_space_title_one_recording,
+ mFailedScheduledRecordingInfos.get(0));
+ description =
+ getString(
+ R.string.dvr_error_insufficient_space_description_one_recording,
+ mFailedScheduledRecordingInfos.get(0));
} else if (failedScheduledRecordingSize == 2) {
- title = getString(
- R.string.dvr_error_insufficient_space_title_two_recordings,
- mFailedScheduledRecordingInfos.get(0), mFailedScheduledRecordingInfos.get(1));
- description = getString(
- R.string.dvr_error_insufficient_space_description_two_recordings,
- mFailedScheduledRecordingInfos.get(0), mFailedScheduledRecordingInfos.get(1));
+ title =
+ getString(
+ R.string.dvr_error_insufficient_space_title_two_recordings,
+ mFailedScheduledRecordingInfos.get(0),
+ mFailedScheduledRecordingInfos.get(1));
+ description =
+ getString(
+ R.string.dvr_error_insufficient_space_description_two_recordings,
+ mFailedScheduledRecordingInfos.get(0),
+ mFailedScheduledRecordingInfos.get(1));
} else {
- title = getString(
- R.string.dvr_error_insufficient_space_title_three_or_more_recordings,
- mFailedScheduledRecordingInfos.get(0), mFailedScheduledRecordingInfos.get(1),
- mFailedScheduledRecordingInfos.get(2));
- description = getString(
- R.string.dvr_error_insufficient_space_description_three_or_more_recordings,
- mFailedScheduledRecordingInfos.get(0), mFailedScheduledRecordingInfos.get(1),
- mFailedScheduledRecordingInfos.get(2));
+ title =
+ getString(
+ R.string.dvr_error_insufficient_space_title_three_or_more_recordings,
+ mFailedScheduledRecordingInfos.get(0),
+ mFailedScheduledRecordingInfos.get(1),
+ mFailedScheduledRecordingInfos.get(2));
+ description =
+ getString(
+ R.string
+ .dvr_error_insufficient_space_description_three_or_more_recordings,
+ mFailedScheduledRecordingInfos.get(0),
+ mFailedScheduledRecordingInfos.get(1),
+ mFailedScheduledRecordingInfos.get(2));
}
return new Guidance(title, description, null, null);
}
@@ -92,15 +100,18 @@ public class DvrInsufficientSpaceErrorFragment extends DvrGuidedStepFragment {
@Override
public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
Activity activity = getActivity();
- actions.add(new GuidedAction.Builder(activity)
- .clickAction(GuidedAction.ACTION_ID_OK)
- .build());
- if (TvApplication.getSingletons(getContext()).getDvrManager().hasValidItems()) {
- actions.add(new GuidedAction.Builder(activity)
- .id(ACTION_VIEW_RECENT_RECORDINGS)
- .title(getResources().getString(
- R.string.dvr_error_insufficient_space_action_view_recent_recordings))
- .build());
+ actions.add(
+ new GuidedAction.Builder(activity).clickAction(GuidedAction.ACTION_ID_OK).build());
+ if (TvSingletons.getSingletons(getContext()).getDvrManager().hasValidItems()) {
+ actions.add(
+ new GuidedAction.Builder(activity)
+ .id(ACTION_VIEW_RECENT_RECORDINGS)
+ .title(
+ getResources()
+ .getString(
+ R.string
+ .dvr_error_insufficient_space_action_view_recent_recordings))
+ .build());
}
}
diff --git a/src/com/android/tv/dvr/ui/DvrMissingStorageErrorFragment.java b/src/com/android/tv/dvr/ui/DvrMissingStorageErrorFragment.java
index e726995f..e5f40260 100644
--- a/src/com/android/tv/dvr/ui/DvrMissingStorageErrorFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrMissingStorageErrorFragment.java
@@ -24,10 +24,8 @@ import android.provider.Settings;
import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
import android.support.v17.leanback.widget.GuidedAction;
import android.util.Log;
-
import com.android.tv.R;
import com.android.tv.dvr.ui.browse.DvrDetailsActivity;
-
import java.util.List;
public class DvrMissingStorageErrorFragment extends DvrGuidedStepFragment {
@@ -44,22 +42,24 @@ public class DvrMissingStorageErrorFragment extends DvrGuidedStepFragment {
@Override
public Guidance onCreateGuidance(Bundle savedInstanceState) {
String title = getResources().getString(R.string.dvr_error_missing_storage_title);
- String description = getResources().getString(
- R.string.dvr_error_missing_storage_description);
+ String description =
+ getResources().getString(R.string.dvr_error_missing_storage_description);
return new Guidance(title, description, null, null);
}
@Override
public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
Activity activity = getActivity();
- actions.add(new GuidedAction.Builder(activity)
- .id(ACTION_OK)
- .title(android.R.string.ok)
- .build());
- actions.add(new GuidedAction.Builder(activity)
- .id(ACTION_OPEN_STORAGE_SETTINGS)
- .title(getResources().getString(R.string.dvr_action_error_storage_settings))
- .build());
+ actions.add(
+ new GuidedAction.Builder(activity)
+ .id(ACTION_OK)
+ .title(android.R.string.ok)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(activity)
+ .id(ACTION_OPEN_STORAGE_SETTINGS)
+ .title(getResources().getString(R.string.dvr_action_error_storage_settings))
+ .build());
}
@Override
diff --git a/src/com/android/tv/dvr/ui/DvrPrioritySettingsFragment.java b/src/com/android/tv/dvr/ui/DvrPrioritySettingsFragment.java
index e4cb7243..5bb97e90 100644
--- a/src/com/android/tv/dvr/ui/DvrPrioritySettingsFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrPrioritySettingsFragment.java
@@ -16,9 +16,11 @@
package com.android.tv.dvr.ui;
+import android.annotation.TargetApi;
import android.app.FragmentManager;
import android.content.Context;
import android.graphics.Typeface;
+import android.os.Build;
import android.os.Bundle;
import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
import android.support.v17.leanback.widget.GuidedAction;
@@ -26,23 +28,20 @@ import android.support.v17.leanback.widget.GuidedActionsStylist;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.DvrScheduleManager;
import com.android.tv.dvr.data.SeriesRecording;
-
import java.util.ArrayList;
import java.util.List;
/** Fragment for DVR series recording settings. */
+@TargetApi(Build.VERSION_CODES.N)
+@SuppressWarnings("AndroidApiChecker") // TODO(b/32513850) remove when error prone is updated
public class DvrPrioritySettingsFragment extends TrackedGuidedStepFragment {
- /**
- * Name of series recording id starting the fragment.
- * Type: Long
- */
+ /** Name of series recording id starting the fragment. Type: Long */
public static final String COME_FROM_SERIES_RECORDING_ID = "series_recording_id";
private static final int ONE_TIME_RECORDING_ID = 0;
@@ -61,14 +60,14 @@ public class DvrPrioritySettingsFragment extends TrackedGuidedStepFragment {
public void onAttach(Context context) {
super.onAttach(context);
mSeriesRecordings.clear();
- mSeriesRecordings.add(new SeriesRecording.Builder()
- .setTitle(getString(R.string.dvr_priority_action_one_time_recording))
- .setPriority(Long.MAX_VALUE)
- .setId(ONE_TIME_RECORDING_ID)
- .build());
- DvrDataManager dvrDataManager = TvApplication.getSingletons(context).getDvrDataManager();
- long comeFromSeriesRecordingId =
- getArguments().getLong(COME_FROM_SERIES_RECORDING_ID, -1);
+ mSeriesRecordings.add(
+ new SeriesRecording.Builder()
+ .setTitle(getString(R.string.dvr_priority_action_one_time_recording))
+ .setPriority(Long.MAX_VALUE)
+ .setId(ONE_TIME_RECORDING_ID)
+ .build());
+ DvrDataManager dvrDataManager = TvSingletons.getSingletons(context).getDvrDataManager();
+ long comeFromSeriesRecordingId = getArguments().getLong(COME_FROM_SERIES_RECORDING_ID, -1);
for (SeriesRecording series : dvrDataManager.getSeriesRecordings()) {
if (series.getState() == SeriesRecording.STATE_SERIES_NORMAL
|| series.getId() == comeFromSeriesRecordingId) {
@@ -86,52 +85,62 @@ public class DvrPrioritySettingsFragment extends TrackedGuidedStepFragment {
@Override
public void onResume() {
super.onResume();
- setSelectedActionPosition(mComeFromSeriesRecording == null ? 1
- : mSeriesRecordings.indexOf(mComeFromSeriesRecording));
+ setSelectedActionPosition(
+ mComeFromSeriesRecording == null
+ ? 1
+ : mSeriesRecordings.indexOf(mComeFromSeriesRecording));
}
@Override
public Guidance onCreateGuidance(Bundle savedInstanceState) {
- String breadcrumb = mComeFromSeriesRecording == null ? null
- : mComeFromSeriesRecording.getTitle();
- return new Guidance(getString(R.string.dvr_priority_title),
- getString(R.string.dvr_priority_description), breadcrumb, null);
+ String breadcrumb =
+ mComeFromSeriesRecording == null ? null : mComeFromSeriesRecording.getTitle();
+ return new Guidance(
+ getString(R.string.dvr_priority_title),
+ getString(R.string.dvr_priority_description),
+ breadcrumb,
+ null);
}
@Override
public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
int position = 0;
for (SeriesRecording seriesRecording : mSeriesRecordings) {
- actions.add(new GuidedAction.Builder(getActivity())
- .id(position++)
- .title(seriesRecording.getTitle())
- .build());
+ actions.add(
+ new GuidedAction.Builder(getActivity())
+ .id(position++)
+ .title(seriesRecording.getTitle())
+ .build());
}
}
@Override
public void onCreateButtonActions(List<GuidedAction> actions, Bundle savedInstanceState) {
- actions.add(new GuidedAction.Builder(getActivity())
- .id(ACTION_ID_SAVE)
- .title(getString(R.string.dvr_priority_button_action_save))
- .build());
- actions.add(new GuidedAction.Builder(getActivity())
- .clickAction(GuidedAction.ACTION_ID_CANCEL)
- .build());
+ actions.add(
+ new GuidedAction.Builder(getActivity())
+ .id(ACTION_ID_SAVE)
+ .title(getString(R.string.dvr_priority_button_action_save))
+ .build());
+ actions.add(
+ new GuidedAction.Builder(getActivity())
+ .clickAction(GuidedAction.ACTION_ID_CANCEL)
+ .build());
}
@Override
public void onTrackedGuidedActionClicked(GuidedAction action) {
long actionId = action.getId();
if (actionId == ACTION_ID_SAVE) {
- DvrManager dvrManager = TvApplication.getSingletons(getContext()).getDvrManager();
+ DvrManager dvrManager = TvSingletons.getSingletons(getContext()).getDvrManager();
int size = mSeriesRecordings.size();
for (int i = 1; i < size; ++i) {
long priority = DvrScheduleManager.suggestSeriesPriority(size - i);
SeriesRecording seriesRecording = mSeriesRecordings.get(i);
if (seriesRecording.getPriority() != priority) {
- dvrManager.updateSeriesRecording(SeriesRecording.buildFrom(seriesRecording)
- .setPriority(priority).build());
+ dvrManager.updateSeriesRecording(
+ SeriesRecording.buildFrom(seriesRecording)
+ .setPriority(priority)
+ .build());
}
}
FragmentManager fragmentManager = getFragmentManager();
@@ -222,8 +231,9 @@ public class DvrPrioritySettingsFragment extends TrackedGuidedStepFragment {
private void updateItem(View itemView, int position) {
GuidedAction action = getActions().get(position);
action.setTitle(mSeriesRecordings.get(position).getTitle());
- boolean selected = mSelectedRecording != null
- && mSeriesRecordings.indexOf(mSelectedRecording) == position;
+ boolean selected =
+ mSelectedRecording != null
+ && mSeriesRecordings.indexOf(mSelectedRecording) == position;
TextView titleView = (TextView) itemView.findViewById(R.id.guidedactions_item_title);
ImageView imageView = (ImageView) itemView.findViewById(R.id.guidedactions_item_tail_image);
if (position == 0) {
@@ -259,4 +269,4 @@ public class DvrPrioritySettingsFragment extends TrackedGuidedStepFragment {
titleView.setTypeface(titleView.getTypeface(), Typeface.NORMAL);
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/DvrScheduleFragment.java b/src/com/android/tv/dvr/ui/DvrScheduleFragment.java
index 390e0928..5251e140 100644
--- a/src/com/android/tv/dvr/ui/DvrScheduleFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrScheduleFragment.java
@@ -26,9 +26,8 @@ import android.support.v17.leanback.app.GuidedStepFragment;
import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
import android.support.v17.leanback.widget.GuidedAction;
import android.text.format.DateUtils;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
import com.android.tv.data.Program;
import com.android.tv.dvr.DvrManager;
@@ -36,21 +35,17 @@ import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.dvr.ui.DvrConflictFragment.DvrProgramConflictFragment;
import com.android.tv.util.Utils;
-
import java.util.Collections;
import java.util.List;
/**
* A fragment which asks the user the type of the recording.
- * <p>
- * The program should be episodic and the series recording should not had been created yet.
+ *
+ * <p>The program should be episodic and the series recording should not had been created yet.
*/
@TargetApi(Build.VERSION_CODES.N)
public class DvrScheduleFragment extends DvrGuidedStepFragment {
- /**
- * Key for the whether to add the current program to series.
- * Type: boolean
- */
+ /** Key for the whether to add the current program to series. Type: boolean */
public static final String KEY_ADD_CURRENT_PROGRAM_TO_SERIES = "add_current_program_to_series";
private static final String TAG = "DvrScheduleFragment";
@@ -68,13 +63,18 @@ public class DvrScheduleFragment extends DvrGuidedStepFragment {
mProgram = args.getParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM);
mAddCurrentProgramToSeries = args.getBoolean(KEY_ADD_CURRENT_PROGRAM_TO_SERIES, false);
}
- DvrManager dvrManager = TvApplication.getSingletons(getContext()).getDvrManager();
- SoftPreconditions.checkArgument(mProgram != null && mProgram.isEpisodic(), TAG,
- "The program should be episodic: " + mProgram);
+ DvrManager dvrManager = TvSingletons.getSingletons(getContext()).getDvrManager();
+ SoftPreconditions.checkArgument(
+ mProgram != null && mProgram.isEpisodic(),
+ TAG,
+ "The program should be episodic: %s ",
+ mProgram);
SeriesRecording seriesRecording = dvrManager.getSeriesRecording(mProgram);
- SoftPreconditions.checkArgument(seriesRecording == null
- || seriesRecording.isStopped(), TAG,
- "The series recording should be stopped or null: " + seriesRecording);
+ SoftPreconditions.checkArgument(
+ seriesRecording == null || seriesRecording.isStopped(),
+ TAG,
+ "The series recording should be stopped or null: %s",
+ seriesRecording);
super.onCreate(savedInstanceState);
}
@@ -96,23 +96,33 @@ public class DvrScheduleFragment extends DvrGuidedStepFragment {
Context context = getContext();
String description;
if (mProgram.getStartTimeUtcMillis() <= System.currentTimeMillis()) {
- description = getString(R.string.dvr_action_record_episode_from_now_description,
- DateUtils.formatDateTime(context, mProgram.getEndTimeUtcMillis(),
- DateUtils.FORMAT_SHOW_TIME));
+ description =
+ getString(
+ R.string.dvr_action_record_episode_from_now_description,
+ DateUtils.formatDateTime(
+ context,
+ mProgram.getEndTimeUtcMillis(),
+ DateUtils.FORMAT_SHOW_TIME));
} else {
- description = Utils.getDurationString(context, mProgram.getStartTimeUtcMillis(),
- mProgram.getEndTimeUtcMillis(), true);
+ description =
+ Utils.getDurationString(
+ context,
+ mProgram.getStartTimeUtcMillis(),
+ mProgram.getEndTimeUtcMillis(),
+ true);
}
- actions.add(new GuidedAction.Builder(context)
- .id(ACTION_RECORD_EPISODE)
- .title(R.string.dvr_action_record_episode)
- .description(description)
- .build());
- actions.add(new GuidedAction.Builder(context)
- .id(ACTION_RECORD_SERIES)
- .title(R.string.dvr_action_record_series)
- .description(mProgram.getTitle())
- .build());
+ actions.add(
+ new GuidedAction.Builder(context)
+ .id(ACTION_RECORD_EPISODE)
+ .title(R.string.dvr_action_record_episode)
+ .description(description)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(context)
+ .id(ACTION_RECORD_SERIES)
+ .title(R.string.dvr_action_record_series)
+ .description(mProgram.getTitle())
+ .build());
}
@Override
@@ -121,34 +131,50 @@ public class DvrScheduleFragment extends DvrGuidedStepFragment {
getDvrManager().addSchedule(mProgram);
List<ScheduledRecording> conflicts = getDvrManager().getConflictingSchedules(mProgram);
if (conflicts.isEmpty()) {
- DvrUiHelper.showAddScheduleToast(getContext(), mProgram.getTitle(),
- mProgram.getStartTimeUtcMillis(), mProgram.getEndTimeUtcMillis());
+ DvrUiHelper.showAddScheduleToast(
+ getContext(),
+ mProgram.getTitle(),
+ mProgram.getStartTimeUtcMillis(),
+ mProgram.getEndTimeUtcMillis());
dismissDialog();
} else {
GuidedStepFragment fragment = new DvrProgramConflictFragment();
Bundle args = new Bundle();
args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, mProgram);
fragment.setArguments(args);
- GuidedStepFragment.add(getFragmentManager(), fragment,
- R.id.halfsized_dialog_host);
+ GuidedStepFragment.add(getFragmentManager(), fragment, R.id.halfsized_dialog_host);
}
} else if (action.getId() == ACTION_RECORD_SERIES) {
- SeriesRecording seriesRecording = TvApplication.getSingletons(getContext())
- .getDvrDataManager().getSeriesRecording(mProgram.getSeriesId());
+ SeriesRecording seriesRecording =
+ TvSingletons.getSingletons(getContext())
+ .getDvrDataManager()
+ .getSeriesRecording(mProgram.getSeriesId());
if (seriesRecording == null) {
- seriesRecording = getDvrManager().addSeriesRecording(mProgram,
- Collections.emptyList(), SeriesRecording.STATE_SERIES_STOPPED);
+ seriesRecording =
+ getDvrManager()
+ .addSeriesRecording(
+ mProgram,
+ Collections.emptyList(),
+ SeriesRecording.STATE_SERIES_STOPPED);
} else {
// Reset priority to the highest.
- seriesRecording = SeriesRecording.buildFrom(seriesRecording)
- .setPriority(TvApplication.getSingletons(getContext())
- .getDvrScheduleManager().suggestNewSeriesPriority())
- .build();
+ seriesRecording =
+ SeriesRecording.buildFrom(seriesRecording)
+ .setPriority(
+ TvSingletons.getSingletons(getContext())
+ .getDvrScheduleManager()
+ .suggestNewSeriesPriority())
+ .build();
getDvrManager().updateSeriesRecording(seriesRecording);
}
- DvrUiHelper.startSeriesSettingsActivity(getContext(),
- seriesRecording.getId(), null, true, true, true,
+ DvrUiHelper.startSeriesSettingsActivity(
+ getContext(),
+ seriesRecording.getId(),
+ null,
+ true,
+ true,
+ true,
mAddCurrentProgramToSeries ? mProgram : null);
dismissDialog();
}
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesDeletionActivity.java b/src/com/android/tv/dvr/ui/DvrSeriesDeletionActivity.java
index 667af34a..a2ae1f97 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesDeletionActivity.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesDeletionActivity.java
@@ -19,22 +19,17 @@ package com.android.tv.dvr.ui;
import android.app.Activity;
import android.os.Bundle;
import android.support.v17.leanback.app.GuidedStepFragment;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.Starter;
-/**
- * Activity to show details view in DVR.
- */
+/** Activity to show details view in DVR. */
public class DvrSeriesDeletionActivity extends Activity {
- /**
- * Name of series id added to the Intent.
- */
+ /** Name of series id added to the Intent. */
public static final String SERIES_RECORDING_ID = "series_recording_id";
@Override
public void onCreate(Bundle savedInstanceState) {
- TvApplication.setCurrentRunningProcess(this, true);
+ Starter.start(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dvr_series_settings);
// Check savedInstanceState to prevent that activity is being showed with animation.
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesDeletionFragment.java b/src/com/android/tv/dvr/ui/DvrSeriesDeletionFragment.java
index 8bf8560f..685f0a58 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesDeletionFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesDeletionFragment.java
@@ -26,9 +26,8 @@ import android.support.v17.leanback.widget.GuidedActionsStylist;
import android.text.TextUtils;
import android.view.ViewGroup.LayoutParams;
import android.widget.Toast;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrManager;
@@ -37,7 +36,6 @@ import com.android.tv.dvr.data.RecordedProgram;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.ui.GuidedActionsStylistWithDivider;
import com.android.tv.util.Utils;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -45,9 +43,7 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
-/**
- * Fragment for DVR series recording settings.
- */
+/** Fragment for DVR series recording settings. */
public class DvrSeriesDeletionFragment extends GuidedStepFragment {
private static final long WATCHED_TIME_UNIT_THRESHOLD = TimeUnit.MINUTES.toMillis(2);
@@ -68,18 +64,23 @@ public class DvrSeriesDeletionFragment extends GuidedStepFragment {
@Override
public void onAttach(Context context) {
super.onAttach(context);
- mSeriesRecordingId = getArguments()
- .getLong(DvrSeriesDeletionActivity.SERIES_RECORDING_ID, -1);
+ mSeriesRecordingId =
+ getArguments().getLong(DvrSeriesDeletionActivity.SERIES_RECORDING_ID, -1);
SoftPreconditions.checkArgument(mSeriesRecordingId != -1);
- mDvrDataManager = TvApplication.getSingletons(context).getDvrDataManager();
+ mDvrDataManager = TvSingletons.getSingletons(context).getDvrDataManager();
mDvrWatchedPositionManager =
- TvApplication.getSingletons(context).getDvrWatchedPositionManager();
+ TvSingletons.getSingletons(context).getDvrWatchedPositionManager();
mRecordings = mDvrDataManager.getRecordedPrograms(mSeriesRecordingId);
- mOneLineActionHeight = getResources().getDimensionPixelSize(
- R.dimen.dvr_settings_one_line_action_container_height);
+ mOneLineActionHeight =
+ getResources()
+ .getDimensionPixelSize(
+ R.dimen.dvr_settings_one_line_action_container_height);
if (mRecordings.isEmpty()) {
- Toast.makeText(getActivity(), getString(R.string.dvr_series_deletion_no_recordings),
- Toast.LENGTH_LONG).show();
+ Toast.makeText(
+ getActivity(),
+ getString(R.string.dvr_series_deletion_no_recordings),
+ Toast.LENGTH_LONG)
+ .show();
finishGuidedStepFragments();
return;
}
@@ -93,28 +94,35 @@ public class DvrSeriesDeletionFragment extends GuidedStepFragment {
if (series != null) {
breadcrumb = series.getTitle();
}
- return new Guidance(getString(R.string.dvr_series_deletion_title),
- getString(R.string.dvr_series_deletion_description), breadcrumb, null);
+ return new Guidance(
+ getString(R.string.dvr_series_deletion_title),
+ getString(R.string.dvr_series_deletion_description),
+ breadcrumb,
+ null);
}
@Override
public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
- actions.add(new GuidedAction.Builder(getActivity())
- .id(ACTION_ID_SELECT_WATCHED)
- .title(getString(R.string.dvr_series_select_watched))
- .build());
- actions.add(new GuidedAction.Builder(getActivity())
- .id(ACTION_ID_SELECT_ALL)
- .title(getString(R.string.dvr_series_select_all))
- .build());
+ actions.add(
+ new GuidedAction.Builder(getActivity())
+ .id(ACTION_ID_SELECT_WATCHED)
+ .title(getString(R.string.dvr_series_select_watched))
+ .build());
+ actions.add(
+ new GuidedAction.Builder(getActivity())
+ .id(ACTION_ID_SELECT_ALL)
+ .title(getString(R.string.dvr_series_select_all))
+ .build());
actions.add(GuidedActionsStylistWithDivider.createDividerAction(getContext()));
for (RecordedProgram recording : mRecordings) {
long watchedPositionMs =
mDvrWatchedPositionManager.getWatchedPosition(recording.getId());
String title = recording.getEpisodeDisplayTitle(getContext());
if (TextUtils.isEmpty(title)) {
- title = TextUtils.isEmpty(recording.getTitle()) ?
- getString(R.string.channel_banner_no_title) : recording.getTitle();
+ title =
+ TextUtils.isEmpty(recording.getTitle())
+ ? getString(R.string.channel_banner_no_title)
+ : recording.getTitle();
}
String description;
if (watchedPositionMs != TvInputManager.TIME_SHIFT_INVALID_TIME) {
@@ -123,24 +131,27 @@ public class DvrSeriesDeletionFragment extends GuidedStepFragment {
} else {
description = getString(R.string.dvr_series_never_watched);
}
- actions.add(new GuidedAction.Builder(getActivity())
- .id(recording.getId())
- .title(title)
- .description(description)
- .checkSetId(GuidedAction.CHECKBOX_CHECK_SET_ID)
- .build());
+ actions.add(
+ new GuidedAction.Builder(getActivity())
+ .id(recording.getId())
+ .title(title)
+ .description(description)
+ .checkSetId(GuidedAction.CHECKBOX_CHECK_SET_ID)
+ .build());
}
}
@Override
public void onCreateButtonActions(List<GuidedAction> actions, Bundle savedInstanceState) {
- actions.add(new GuidedAction.Builder(getActivity())
- .id(ACTION_ID_DELETE)
- .title(getString(R.string.dvr_detail_delete))
- .build());
- actions.add(new GuidedAction.Builder(getActivity())
- .clickAction(GuidedAction.ACTION_ID_CANCEL)
- .build());
+ actions.add(
+ new GuidedAction.Builder(getActivity())
+ .id(ACTION_ID_DELETE)
+ .title(getString(R.string.dvr_detail_delete))
+ .build());
+ actions.add(
+ new GuidedAction.Builder(getActivity())
+ .clickAction(GuidedAction.ACTION_ID_CANCEL)
+ .build());
}
@Override
@@ -155,12 +166,19 @@ public class DvrSeriesDeletionFragment extends GuidedStepFragment {
}
}
if (!idsToDelete.isEmpty()) {
- DvrManager dvrManager = TvApplication.getSingletons(getActivity()).getDvrManager();
+ DvrManager dvrManager = TvSingletons.getSingletons(getActivity()).getDvrManager();
dvrManager.removeRecordedPrograms(idsToDelete);
}
- Toast.makeText(getContext(), getResources().getQuantityString(
- R.plurals.dvr_msg_episodes_deleted, idsToDelete.size(), idsToDelete.size(),
- mRecordings.size()), Toast.LENGTH_LONG).show();
+ Toast.makeText(
+ getContext(),
+ getResources()
+ .getQuantityString(
+ R.plurals.dvr_msg_episodes_deleted,
+ idsToDelete.size(),
+ idsToDelete.size(),
+ mRecordings.size()),
+ Toast.LENGTH_LONG)
+ .show();
finishGuidedStepFragments();
} else if (actionId == GuidedAction.ACTION_ID_CANCEL) {
finishGuidedStepFragments();
@@ -218,13 +236,17 @@ public class DvrSeriesDeletionFragment extends GuidedStepFragment {
private String getWatchedString(long watchedPositionMs, long durationMs) {
if (durationMs > WATCHED_TIME_UNIT_THRESHOLD) {
- return getResources().getString(R.string.dvr_series_watched_info_minutes,
- Math.max(1, Utils.getRoundOffMinsFromMs(watchedPositionMs)),
- Utils.getRoundOffMinsFromMs(durationMs));
+ return getResources()
+ .getString(
+ R.string.dvr_series_watched_info_minutes,
+ Math.max(1, Utils.getRoundOffMinsFromMs(watchedPositionMs)),
+ Utils.getRoundOffMinsFromMs(durationMs));
} else {
- return getResources().getString(R.string.dvr_series_watched_info_seconds,
- Math.max(1, TimeUnit.MILLISECONDS.toSeconds(watchedPositionMs)),
- TimeUnit.MILLISECONDS.toSeconds(durationMs));
+ return getResources()
+ .getString(
+ R.string.dvr_series_watched_info_seconds,
+ Math.max(1, TimeUnit.MILLISECONDS.toSeconds(watchedPositionMs)),
+ TimeUnit.MILLISECONDS.toSeconds(durationMs));
}
}
@@ -246,8 +268,10 @@ public class DvrSeriesDeletionFragment extends GuidedStepFragment {
}
private void updateSelectAllState(GuidedAction selectAll, boolean select) {
- selectAll.setTitle(select ? getString(R.string.dvr_series_deselect_all)
- : getString(R.string.dvr_series_select_all));
+ selectAll.setTitle(
+ select
+ ? getString(R.string.dvr_series_deselect_all)
+ : getString(R.string.dvr_series_select_all));
notifyActionChanged(findActionPositionById(ACTION_ID_SELECT_ALL));
}
}
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesScheduledDialogActivity.java b/src/com/android/tv/dvr/ui/DvrSeriesScheduledDialogActivity.java
index 1a0d13d3..9acb5b5e 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesScheduledDialogActivity.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesScheduledDialogActivity.java
@@ -19,18 +19,13 @@ package com.android.tv.dvr.ui;
import android.app.Activity;
import android.os.Bundle;
import android.support.v17.leanback.app.GuidedStepFragment;
-
import com.android.tv.R;
public class DvrSeriesScheduledDialogActivity extends Activity {
- /**
- * Name of series recording id added to the Intent.
- */
+ /** Name of series recording id added to the Intent. */
public static final String SERIES_RECORDING_ID = "series_recording_id";
- /**
- * Name of flag to check if the dialog should show view schedule option.
- */
+ /** Name of flag to check if the dialog should show view schedule option. */
public static final String SHOW_VIEW_SCHEDULE_OPTION = "show_view_schedule_option";
@Override
@@ -41,8 +36,8 @@ public class DvrSeriesScheduledDialogActivity extends Activity {
DvrSeriesScheduledFragment dvrSeriesScheduledFragment =
new DvrSeriesScheduledFragment();
dvrSeriesScheduledFragment.setArguments(getIntent().getExtras());
- GuidedStepFragment.addAsRoot(this, dvrSeriesScheduledFragment,
- R.id.halfsized_dialog_host);
+ GuidedStepFragment.addAsRoot(
+ this, dvrSeriesScheduledFragment, R.id.halfsized_dialog_host);
}
}
}
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesScheduledFragment.java b/src/com/android/tv/dvr/ui/DvrSeriesScheduledFragment.java
index 2c4bb3ea..edb62c96 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesScheduledFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesScheduledFragment.java
@@ -22,28 +22,26 @@ import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v17.leanback.widget.GuidanceStylist;
import android.support.v17.leanback.widget.GuidedAction;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.data.Program;
import com.android.tv.dvr.DvrScheduleManager;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.dvr.ui.list.DvrSchedulesActivity;
import com.android.tv.dvr.ui.list.DvrSeriesSchedulesFragment;
-
import java.util.List;
public class DvrSeriesScheduledFragment extends DvrGuidedStepFragment {
/**
- * The key for program list which will be passed to {@link DvrSeriesSchedulesFragment}.
- * Type: List<{@link Program}>
+ * The key for program list which will be passed to {@link DvrSeriesSchedulesFragment}. Type:
+ * List<{@link Program}>
*/
public static final String SERIES_SCHEDULED_KEY_PROGRAMS = "series_scheduled_key_programs";
- private final static long SERIES_RECORDING_ID_NOT_SET = -1;
+ private static final long SERIES_RECORDING_ID_NOT_SET = -1;
- private final static int ACTION_VIEW_SCHEDULES = 1;
+ private static final int ACTION_VIEW_SCHEDULES = 1;
private SeriesRecording mSeriesRecording;
private boolean mShowViewScheduleOption;
@@ -57,26 +55,35 @@ public class DvrSeriesScheduledFragment extends DvrGuidedStepFragment {
@Override
public void onAttach(Context context) {
super.onAttach(context);
- long seriesRecordingId = getArguments().getLong(
- DvrSeriesScheduledDialogActivity.SERIES_RECORDING_ID, SERIES_RECORDING_ID_NOT_SET);
+ long seriesRecordingId =
+ getArguments()
+ .getLong(
+ DvrSeriesScheduledDialogActivity.SERIES_RECORDING_ID,
+ SERIES_RECORDING_ID_NOT_SET);
if (seriesRecordingId == SERIES_RECORDING_ID_NOT_SET) {
getActivity().finish();
return;
}
- mShowViewScheduleOption = getArguments().getBoolean(
- DvrSeriesScheduledDialogActivity.SHOW_VIEW_SCHEDULE_OPTION);
- mSeriesRecording = TvApplication.getSingletons(context).getDvrDataManager()
- .getSeriesRecording(seriesRecordingId);
+ mShowViewScheduleOption =
+ getArguments()
+ .getBoolean(DvrSeriesScheduledDialogActivity.SHOW_VIEW_SCHEDULE_OPTION);
+ mSeriesRecording =
+ TvSingletons.getSingletons(context)
+ .getDvrDataManager()
+ .getSeriesRecording(seriesRecordingId);
if (mSeriesRecording == null) {
getActivity().finish();
return;
}
mPrograms = (List<Program>) BigArguments.getArgument(SERIES_SCHEDULED_KEY_PROGRAMS);
BigArguments.reset();
- mSchedulesAddedCount = TvApplication.getSingletons(getContext()).getDvrManager()
- .getAvailableScheduledRecording(mSeriesRecording.getId()).size();
+ mSchedulesAddedCount =
+ TvSingletons.getSingletons(getContext())
+ .getDvrManager()
+ .getAvailableScheduledRecording(mSeriesRecording.getId())
+ .size();
DvrScheduleManager dvrScheduleManager =
- TvApplication.getSingletons(context).getDvrScheduleManager();
+ TvSingletons.getSingletons(context).getDvrScheduleManager();
List<ScheduledRecording> conflictingRecordings =
dvrScheduleManager.getConflictingSchedules(mSeriesRecording);
mHasConflict = !conflictingRecordings.isEmpty();
@@ -87,7 +94,7 @@ public class DvrSeriesScheduledFragment extends DvrGuidedStepFragment {
++mOutThisSeriesConflictCount;
}
}
- }
+ }
@Override
public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
@@ -104,14 +111,14 @@ public class DvrSeriesScheduledFragment extends DvrGuidedStepFragment {
@Override
public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
Context context = getContext();
- actions.add(new GuidedAction.Builder(context)
- .clickAction(GuidedAction.ACTION_ID_OK)
- .build());
+ actions.add(
+ new GuidedAction.Builder(context).clickAction(GuidedAction.ACTION_ID_OK).build());
if (mShowViewScheduleOption) {
- actions.add(new GuidedAction.Builder(context)
- .id(ACTION_VIEW_SCHEDULES)
- .title(R.string.dvr_action_view_schedules)
- .build());
+ actions.add(
+ new GuidedAction.Builder(context)
+ .id(ACTION_VIEW_SCHEDULES)
+ .title(R.string.dvr_action_view_schedules)
+ .build());
}
}
@@ -119,13 +126,15 @@ public class DvrSeriesScheduledFragment extends DvrGuidedStepFragment {
public void onTrackedGuidedActionClicked(GuidedAction action) {
if (action.getId() == ACTION_VIEW_SCHEDULES) {
Intent intent = new Intent(getActivity(), DvrSchedulesActivity.class);
- intent.putExtra(DvrSchedulesActivity.KEY_SCHEDULES_TYPE, DvrSchedulesActivity
- .TYPE_SERIES_SCHEDULE);
- intent.putExtra(DvrSeriesSchedulesFragment.SERIES_SCHEDULES_KEY_SERIES_RECORDING,
+ intent.putExtra(
+ DvrSchedulesActivity.KEY_SCHEDULES_TYPE,
+ DvrSchedulesActivity.TYPE_SERIES_SCHEDULE);
+ intent.putExtra(
+ DvrSeriesSchedulesFragment.SERIES_SCHEDULES_KEY_SERIES_RECORDING,
mSeriesRecording);
BigArguments.reset();
- BigArguments.setArgument(DvrSeriesSchedulesFragment
- .SERIES_SCHEDULES_KEY_SERIES_PROGRAMS, mPrograms);
+ BigArguments.setArgument(
+ DvrSeriesSchedulesFragment.SERIES_SCHEDULES_KEY_SERIES_PROGRAMS, mPrograms);
startActivity(intent);
}
getActivity().finish();
@@ -148,33 +157,47 @@ public class DvrSeriesScheduledFragment extends DvrGuidedStepFragment {
private String getDescription() {
if (!mHasConflict) {
- return getResources().getQuantityString(
- R.plurals.dvr_series_scheduled_no_conflict, mSchedulesAddedCount,
- mSchedulesAddedCount, mSeriesRecording.getTitle());
+ return getResources()
+ .getQuantityString(
+ R.plurals.dvr_series_scheduled_no_conflict,
+ mSchedulesAddedCount,
+ mSchedulesAddedCount,
+ mSeriesRecording.getTitle());
} else {
// mInThisSeriesConflictCount equals 0 and mOutThisSeriesConflictCount equals 0 means
// mHasConflict is false. So we don't need to check that case.
if (mInThisSeriesConflictCount != 0 && mOutThisSeriesConflictCount != 0) {
- return getResources().getQuantityString(
- R.plurals.dvr_series_scheduled_this_and_other_series_conflict,
- mSchedulesAddedCount, mSchedulesAddedCount, mSeriesRecording.getTitle(),
- mInThisSeriesConflictCount + mOutThisSeriesConflictCount);
+ return getResources()
+ .getQuantityString(
+ R.plurals.dvr_series_scheduled_this_and_other_series_conflict,
+ mSchedulesAddedCount,
+ mSchedulesAddedCount,
+ mSeriesRecording.getTitle(),
+ mInThisSeriesConflictCount + mOutThisSeriesConflictCount);
} else if (mInThisSeriesConflictCount != 0) {
- return getResources().getQuantityString(
- R.plurals.dvr_series_recording_scheduled_only_this_series_conflict,
- mSchedulesAddedCount, mSchedulesAddedCount, mSeriesRecording.getTitle(),
- mInThisSeriesConflictCount);
+ return getResources()
+ .getQuantityString(
+ R.plurals.dvr_series_recording_scheduled_only_this_series_conflict,
+ mSchedulesAddedCount,
+ mSchedulesAddedCount,
+ mSeriesRecording.getTitle(),
+ mInThisSeriesConflictCount);
} else {
if (mOutThisSeriesConflictCount == 1) {
- return getResources().getQuantityString(
- R.plurals.dvr_series_scheduled_only_other_series_one_conflict,
- mSchedulesAddedCount, mSchedulesAddedCount,
- mSeriesRecording.getTitle());
+ return getResources()
+ .getQuantityString(
+ R.plurals.dvr_series_scheduled_only_other_series_one_conflict,
+ mSchedulesAddedCount,
+ mSchedulesAddedCount,
+ mSeriesRecording.getTitle());
} else {
- return getResources().getQuantityString(
- R.plurals.dvr_series_scheduled_only_other_series_many_conflicts,
- mSchedulesAddedCount, mSchedulesAddedCount, mSeriesRecording.getTitle(),
- mOutThisSeriesConflictCount);
+ return getResources()
+ .getQuantityString(
+ R.plurals.dvr_series_scheduled_only_other_series_many_conflicts,
+ mSchedulesAddedCount,
+ mSchedulesAddedCount,
+ mSeriesRecording.getTitle(),
+ mOutThisSeriesConflictCount);
}
}
}
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesSettingsActivity.java b/src/com/android/tv/dvr/ui/DvrSeriesSettingsActivity.java
index 6dd20b3a..1a51cf46 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesSettingsActivity.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesSettingsActivity.java
@@ -20,34 +20,27 @@ import android.app.Activity;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.v17.leanback.app.GuidedStepFragment;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.Starter;
import com.android.tv.common.SoftPreconditions;
-/**
- * Activity to show details view in DVR.
- */
+/** Activity to show details view in DVR. */
public class DvrSeriesSettingsActivity extends Activity {
- /**
- * Name of series id added to the Intent.
- * Type: Long
- */
+ /** Name of series id added to the Intent. Type: Long */
public static final String SERIES_RECORDING_ID = "series_recording_id";
/**
* Name of the boolean flag to decide if the series recording with empty schedule and recording
- * will be removed.
- * Type: boolean
+ * will be removed. Type: boolean
*/
public static final String REMOVE_EMPTY_SERIES_RECORDING = "remove_empty_series_recording";
/**
- * Name of the boolean flag to decide if the setting fragment should be translucent.
- * Type: boolean
+ * Name of the boolean flag to decide if the setting fragment should be translucent. Type:
+ * boolean
*/
public static final String IS_WINDOW_TRANSLUCENT = "windows_translucent";
/**
- * Name of the program list. The list contains the programs which belong to the series.
- * Type: List<{@link com.android.tv.data.Program}>
+ * Name of the program list. The list contains the programs which belong to the series. Type:
+ * List<{@link com.android.tv.data.Program}>
*/
public static final String PROGRAM_LIST = "program_list";
@@ -67,7 +60,7 @@ public class DvrSeriesSettingsActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
- TvApplication.setCurrentRunningProcess(this, true);
+ Starter.start(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dvr_series_settings);
long seriesRecordingId = getIntent().getLongExtra(SERIES_RECORDING_ID, -1);
@@ -83,8 +76,9 @@ public class DvrSeriesSettingsActivity extends Activity {
@Override
public void onAttachedToWindow() {
if (!getIntent().getExtras().getBoolean(IS_WINDOW_TRANSLUCENT, true)) {
- getWindow().setBackgroundDrawable(
- new ColorDrawable(getColor(R.color.common_tv_background)));
+ getWindow()
+ .setBackgroundDrawable(
+ new ColorDrawable(getColor(R.color.common_tv_background)));
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesSettingsFragment.java b/src/com/android/tv/dvr/ui/DvrSeriesSettingsFragment.java
index f28382da..eadb3b9e 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesSettingsFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesSettingsFragment.java
@@ -16,20 +16,22 @@
package com.android.tv.dvr.ui;
+import android.annotation.TargetApi;
import android.app.FragmentManager;
import android.content.Context;
+import android.os.Build;
import android.os.Bundle;
import android.support.v17.leanback.app.GuidedStepFragment;
import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
import android.support.v17.leanback.widget.GuidedAction;
import android.support.v17.leanback.widget.GuidedActionsStylist;
import android.util.LongSparseArray;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
-import com.android.tv.data.Channel;
+import com.android.tv.TvSingletons;
import com.android.tv.data.ChannelDataManager;
+import com.android.tv.data.ChannelImpl;
import com.android.tv.data.Program;
+import com.android.tv.data.api.Channel;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.data.ScheduledRecording;
@@ -37,20 +39,18 @@ import com.android.tv.dvr.data.SeasonEpisodeNumber;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.dvr.data.SeriesRecording.ChannelOption;
import com.android.tv.dvr.recorder.SeriesRecordingScheduler;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-/**
- * Fragment for DVR series recording settings.
- */
+/** Fragment for DVR series recording settings. */
+@TargetApi(Build.VERSION_CODES.N)
+@SuppressWarnings("AndroidApiChecker") // TODO(b/32513850) remove when error prone is updated
public class DvrSeriesSettingsFragment extends GuidedStepFragment
implements DvrDataManager.SeriesRecordingListener {
private static final String TAG = "SeriesSettingsFragment";
- private static final boolean DEBUG = false;
private static final long ACTION_ID_PRIORITY = 10;
private static final long ACTION_ID_CHANNEL = 11;
@@ -85,19 +85,20 @@ public class DvrSeriesSettingsFragment extends GuidedStepFragment
public void onAttach(Context context) {
super.onAttach(context);
mBackStackCount = getFragmentManager().getBackStackEntryCount();
- mDvrDataManager = TvApplication.getSingletons(context).getDvrDataManager();
+ mDvrDataManager = TvSingletons.getSingletons(context).getDvrDataManager();
mSeriesRecordingId = getArguments().getLong(DvrSeriesSettingsActivity.SERIES_RECORDING_ID);
mSeriesRecording = mDvrDataManager.getSeriesRecording(mSeriesRecordingId);
if (mSeriesRecording == null) {
getActivity().finish();
return;
}
- mShowViewScheduleOptionInDialog = getArguments().getBoolean(
- DvrSeriesSettingsActivity.SHOW_VIEW_SCHEDULE_OPTION_IN_DIALOG);
+ mShowViewScheduleOptionInDialog =
+ getArguments()
+ .getBoolean(DvrSeriesSettingsActivity.SHOW_VIEW_SCHEDULE_OPTION_IN_DIALOG);
mCurrentProgram = getArguments().getParcelable(DvrSeriesSettingsActivity.CURRENT_PROGRAM);
mDvrDataManager.addSeriesRecordingListener(this);
- mPrograms = (List<Program>) BigArguments.getArgument(
- DvrSeriesSettingsActivity.PROGRAM_LIST);
+ mPrograms =
+ (List<Program>) BigArguments.getArgument(DvrSeriesSettingsActivity.PROGRAM_LIST);
BigArguments.reset();
if (mPrograms == null) {
getActivity().finish();
@@ -105,7 +106,7 @@ public class DvrSeriesSettingsFragment extends GuidedStepFragment
}
Set<Long> channelIds = new HashSet<>();
ChannelDataManager channelDataManager =
- TvApplication.getSingletons(context).getChannelDataManager();
+ TvSingletons.getSingletons(context).getChannelDataManager();
for (Program program : mPrograms) {
long channelId = program.getChannelId();
if (channelIds.add(channelId)) {
@@ -126,7 +127,7 @@ public class DvrSeriesSettingsFragment extends GuidedStepFragment
mChannelOption = SeriesRecording.OPTION_CHANNEL_ALL;
}
}
- mChannels.sort(Channel.CHANNEL_NUMBER_COMPARATOR);
+ mChannels.sort(ChannelImpl.CHANNEL_NUMBER_COMPARATOR);
mFragmentTitle = getString(R.string.dvr_series_settings_title);
mProrityActionTitle = getString(R.string.dvr_series_settings_priority);
mProrityActionHighestText = getString(R.string.dvr_series_settings_priority_highest);
@@ -150,8 +151,9 @@ public class DvrSeriesSettingsFragment extends GuidedStepFragment
@Override
public void onDestroy() {
- if (getFragmentManager().getBackStackEntryCount() == mBackStackCount && getArguments()
- .getBoolean(DvrSeriesSettingsActivity.REMOVE_EMPTY_SERIES_RECORDING)) {
+ if (getFragmentManager().getBackStackEntryCount() == mBackStackCount
+ && getArguments()
+ .getBoolean(DvrSeriesSettingsActivity.REMOVE_EMPTY_SERIES_RECORDING)) {
mDvrDataManager.checkAndRemoveEmptySeriesRecording(mSeriesRecordingId);
}
super.onDestroy();
@@ -166,29 +168,33 @@ public class DvrSeriesSettingsFragment extends GuidedStepFragment
@Override
public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
- mPriorityGuidedAction = new GuidedAction.Builder(getActivity())
- .id(ACTION_ID_PRIORITY)
- .title(mProrityActionTitle)
- .build();
+ mPriorityGuidedAction =
+ new GuidedAction.Builder(getActivity())
+ .id(ACTION_ID_PRIORITY)
+ .title(mProrityActionTitle)
+ .build();
actions.add(mPriorityGuidedAction);
- mChannelsGuidedAction = new GuidedAction.Builder(getActivity())
- .id(ACTION_ID_CHANNEL)
- .title(mChannelsActionTitle)
- .subActions(buildChannelSubAction())
- .build();
+ mChannelsGuidedAction =
+ new GuidedAction.Builder(getActivity())
+ .id(ACTION_ID_CHANNEL)
+ .title(mChannelsActionTitle)
+ .subActions(buildChannelSubAction())
+ .build();
actions.add(mChannelsGuidedAction);
updateChannelsGuidedAction(false);
}
@Override
public void onCreateButtonActions(List<GuidedAction> actions, Bundle savedInstanceState) {
- actions.add(new GuidedAction.Builder(getActivity())
- .clickAction(GuidedAction.ACTION_ID_OK)
- .build());
- actions.add(new GuidedAction.Builder(getActivity())
- .clickAction(GuidedAction.ACTION_ID_CANCEL)
- .build());
+ actions.add(
+ new GuidedAction.Builder(getActivity())
+ .clickAction(GuidedAction.ACTION_ID_OK)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(getActivity())
+ .clickAction(GuidedAction.ACTION_ID_CANCEL)
+ .build());
}
@Override
@@ -199,16 +205,18 @@ public class DvrSeriesSettingsFragment extends GuidedStepFragment
|| mSeriesRecording.isStopped()
|| (mChannelOption == SeriesRecording.OPTION_CHANNEL_ONE
&& mSeriesRecording.getChannelId() != mSelectedChannelId)) {
- SeriesRecording.Builder builder = SeriesRecording.buildFrom(mSeriesRecording)
- .setChannelOption(mChannelOption)
- .setState(SeriesRecording.STATE_SERIES_NORMAL);
+ SeriesRecording.Builder builder =
+ SeriesRecording.buildFrom(mSeriesRecording)
+ .setChannelOption(mChannelOption)
+ .setState(SeriesRecording.STATE_SERIES_NORMAL);
if (mSelectedChannelId != Channel.INVALID_ID) {
builder.setChannelId(mSelectedChannelId);
}
- DvrManager dvrManager = TvApplication.getSingletons(getContext()).getDvrManager();
- dvrManager.updateSeriesRecording(builder.build());
- if (mCurrentProgram != null && (mChannelOption == SeriesRecording.OPTION_CHANNEL_ALL
- || mSelectedChannelId == mCurrentProgram.getChannelId())) {
+ DvrManager dvrManager = TvSingletons.getSingletons(getContext()).getDvrManager();
+ dvrManager.updateSeriesRecording(builder.build());
+ if (mCurrentProgram != null
+ && (mChannelOption == SeriesRecording.OPTION_CHANNEL_ALL
+ || mSelectedChannelId == mCurrentProgram.getChannelId())) {
dvrManager.addSchedule(mCurrentProgram);
}
updateSchedulesToSeries();
@@ -222,7 +230,8 @@ public class DvrSeriesSettingsFragment extends GuidedStepFragment
FragmentManager fragmentManager = getFragmentManager();
DvrPrioritySettingsFragment fragment = new DvrPrioritySettingsFragment();
Bundle args = new Bundle();
- args.putLong(DvrPrioritySettingsFragment.COME_FROM_SERIES_RECORDING_ID,
+ args.putLong(
+ DvrPrioritySettingsFragment.COME_FROM_SERIES_RECORDING_ID,
mSeriesRecording.getId());
fragment.setArguments(args);
GuidedStepFragment.add(fragmentManager, fragment, R.id.dvr_settings_view_frame);
@@ -254,9 +263,9 @@ public class DvrSeriesSettingsFragment extends GuidedStepFragment
private void updateChannelsGuidedAction(boolean notifyActionChanged) {
if (mChannelOption == SeriesRecording.OPTION_CHANNEL_ALL) {
mChannelsGuidedAction.setDescription(mChannelsActionAllText);
- } else if (mId2Channel.get(mSelectedChannelId) != null){
- mChannelsGuidedAction.setDescription(mId2Channel.get(mSelectedChannelId)
- .getDisplayText());
+ } else if (mId2Channel.get(mSelectedChannelId) != null) {
+ mChannelsGuidedAction.setDescription(
+ mId2Channel.get(mSelectedChannelId).getDisplayText());
}
if (notifyActionChanged) {
notifyActionChanged(findActionPositionById(ACTION_ID_CHANNEL));
@@ -282,8 +291,8 @@ public class DvrSeriesSettingsFragment extends GuidedStepFragment
} else if (priorityOrder >= totalSeriesCount - 1) {
mPriorityGuidedAction.setDescription(mProrityActionLowestText);
} else {
- mPriorityGuidedAction.setDescription(getString(
- R.string.dvr_series_settings_priority_rank, priorityOrder + 1));
+ mPriorityGuidedAction.setDescription(
+ getString(R.string.dvr_series_settings_priority_rank, priorityOrder + 1));
}
notifyActionChanged(findActionPositionById(ACTION_ID_PRIORITY));
}
@@ -294,54 +303,66 @@ public class DvrSeriesSettingsFragment extends GuidedStepFragment
for (ScheduledRecording r : mDvrDataManager.getScheduledRecordings(mSeriesRecordingId)) {
if (r.getState() != ScheduledRecording.STATE_RECORDING_FAILED
&& r.getState() != ScheduledRecording.STATE_RECORDING_CLIPPED) {
- scheduledEpisodes.add(new SeasonEpisodeNumber(
- r.getSeriesRecordingId(), r.getSeasonNumber(), r.getEpisodeNumber()));
+ scheduledEpisodes.add(
+ new SeasonEpisodeNumber(
+ r.getSeriesRecordingId(),
+ r.getSeasonNumber(),
+ r.getEpisodeNumber()));
}
}
for (Program program : mPrograms) {
// Removes current programs and scheduled episodes out, matches the channel option.
if (program.getStartTimeUtcMillis() >= System.currentTimeMillis()
&& mSeriesRecording.matchProgram(program)
- && !scheduledEpisodes.contains(new SeasonEpisodeNumber(
- mSeriesRecordingId, program.getSeasonNumber(), program.getEpisodeNumber()))) {
+ && !scheduledEpisodes.contains(
+ new SeasonEpisodeNumber(
+ mSeriesRecordingId,
+ program.getSeasonNumber(),
+ program.getEpisodeNumber()))) {
recordingCandidates.add(program);
}
}
if (recordingCandidates.isEmpty()) {
return;
}
- List<Program> programsToSchedule = SeriesRecordingScheduler.pickOneProgramPerEpisode(
- mDvrDataManager, Collections.singletonList(mSeriesRecording), recordingCandidates)
- .get(mSeriesRecordingId);
+ List<Program> programsToSchedule =
+ SeriesRecordingScheduler.pickOneProgramPerEpisode(
+ mDvrDataManager,
+ Collections.singletonList(mSeriesRecording),
+ recordingCandidates)
+ .get(mSeriesRecordingId);
if (!programsToSchedule.isEmpty()) {
- TvApplication.getSingletons(getContext()).getDvrManager()
+ TvSingletons.getSingletons(getContext())
+ .getDvrManager()
.addScheduleToSeriesRecording(mSeriesRecording, programsToSchedule);
}
}
private List<GuidedAction> buildChannelSubAction() {
List<GuidedAction> channelSubActions = new ArrayList<>();
- channelSubActions.add(new GuidedAction.Builder(getActivity())
- .id(SUB_ACTION_ID_CHANNEL_ALL)
- .title(mChannelsActionAllText)
- .build());
+ channelSubActions.add(
+ new GuidedAction.Builder(getActivity())
+ .id(SUB_ACTION_ID_CHANNEL_ALL)
+ .title(mChannelsActionAllText)
+ .build());
for (Channel channel : mChannels) {
- channelSubActions.add(new GuidedAction.Builder(getActivity())
- .id(SUB_ACTION_ID_CHANNEL_ONE_BASE + channel.getId())
- .title(channel.getDisplayText())
- .build());
+ channelSubActions.add(
+ new GuidedAction.Builder(getActivity())
+ .id(SUB_ACTION_ID_CHANNEL_ONE_BASE + channel.getId())
+ .title(channel.getDisplayText())
+ .build());
}
return channelSubActions;
}
private void showConfirmDialog() {
- DvrUiHelper.StartSeriesScheduledDialogActivity(getContext(), mSeriesRecording,
- mShowViewScheduleOptionInDialog, mPrograms);
+ DvrUiHelper.startSeriesScheduledDialogActivity(
+ getContext(), mSeriesRecording, mShowViewScheduleOptionInDialog, mPrograms);
finishGuidedStepFragments();
}
@Override
- public void onSeriesRecordingAdded(SeriesRecording... seriesRecordings) { }
+ public void onSeriesRecordingAdded(SeriesRecording... seriesRecordings) {}
@Override
public void onSeriesRecordingRemoved(SeriesRecording... seriesRecordings) {
@@ -363,4 +384,4 @@ public class DvrSeriesSettingsFragment extends GuidedStepFragment
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/DvrStopRecordingFragment.java b/src/com/android/tv/dvr/ui/DvrStopRecordingFragment.java
index baa45793..e93387ab 100644
--- a/src/com/android/tv/dvr/ui/DvrStopRecordingFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrStopRecordingFragment.java
@@ -25,45 +25,36 @@ import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
import android.support.v17.leanback.widget.GuidedAction;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
import com.android.tv.dvr.data.ScheduledRecording;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
* A fragment which asks the user to make a recording schedule for the program.
- * <p>
- * If the program belongs to a series and the series recording is not created yet, we will show the
- * option to record all the episodes of the series.
+ *
+ * <p>If the program belongs to a series and the series recording is not created yet, we will show
+ * the option to record all the episodes of the series.
*/
@TargetApi(Build.VERSION_CODES.N)
public class DvrStopRecordingFragment extends DvrGuidedStepFragment {
- /**
- * The action ID for the stop action.
- */
+ /** The action ID for the stop action. */
public static final int ACTION_STOP = 1;
- /**
- * Key for the program.
- * Type: {@link com.android.tv.data.Program}.
- */
+ /** Key for the program. Type: {@link com.android.tv.data.Program}. */
public static final String KEY_REASON = "DvrStopRecordingFragment.type";
@Retention(RetentionPolicy.SOURCE)
@IntDef({REASON_USER_STOP, REASON_ON_CONFLICT})
public @interface ReasonType {}
- /**
- * The dialog is shown because users want to stop some currently recording program.
- */
+ /** The dialog is shown because users want to stop some currently recording program. */
public static final int REASON_USER_STOP = 1;
/**
- * The dialog is shown because users want to record some program that is conflict to the
- * current recording program.
+ * The dialog is shown because users want to record some program that is conflict to the current
+ * recording program.
*/
public static final int REASON_ON_CONFLICT = 2;
@@ -74,7 +65,7 @@ public class DvrStopRecordingFragment extends DvrGuidedStepFragment {
private final ScheduledRecordingListener mScheduledRecordingListener =
new ScheduledRecordingListener() {
@Override
- public void onScheduledRecordingAdded(ScheduledRecording... schedules) { }
+ public void onScheduledRecordingAdded(ScheduledRecording... schedules) {}
@Override
public void onScheduledRecordingRemoved(ScheduledRecording... schedules) {
@@ -91,7 +82,7 @@ public class DvrStopRecordingFragment extends DvrGuidedStepFragment {
for (ScheduledRecording schedule : schedules) {
if (schedule.getId() == mSchedule.getId()
&& schedule.getState()
- != ScheduledRecording.STATE_RECORDING_IN_PROGRESS) {
+ != ScheduledRecording.STATE_RECORDING_IN_PROGRESS) {
dismissDialog();
return;
}
@@ -109,7 +100,7 @@ public class DvrStopRecordingFragment extends DvrGuidedStepFragment {
dismissDialog();
return;
}
- mDvrDataManager = TvApplication.getSingletons(context).getDvrDataManager();
+ mDvrDataManager = TvSingletons.getSingletons(context).getDvrDataManager();
mDvrDataManager.addScheduledRecordingListener(mScheduledRecordingListener);
mStopReason = args.getInt(KEY_REASON);
}
@@ -128,8 +119,10 @@ public class DvrStopRecordingFragment extends DvrGuidedStepFragment {
String title = getString(R.string.dvr_stop_recording_dialog_title);
String description;
if (mStopReason == REASON_ON_CONFLICT) {
- description = getString(R.string.dvr_stop_recording_dialog_description_on_conflict,
- mSchedule.getProgramDisplayTitle(getContext()));
+ description =
+ getString(
+ R.string.dvr_stop_recording_dialog_description_on_conflict,
+ mSchedule.getProgramDisplayTitle(getContext()));
} else {
description = getString(R.string.dvr_stop_recording_dialog_description);
}
@@ -140,13 +133,15 @@ public class DvrStopRecordingFragment extends DvrGuidedStepFragment {
@Override
public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
Context context = getContext();
- actions.add(new GuidedAction.Builder(context)
- .id(ACTION_STOP)
- .title(R.string.dvr_action_stop)
- .build());
- actions.add(new GuidedAction.Builder(context)
- .clickAction(GuidedAction.ACTION_ID_CANCEL)
- .build());
+ actions.add(
+ new GuidedAction.Builder(context)
+ .id(ACTION_STOP)
+ .title(R.string.dvr_action_stop)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(context)
+ .clickAction(GuidedAction.ACTION_ID_CANCEL)
+ .build());
}
@Override
@@ -163,4 +158,4 @@ public class DvrStopRecordingFragment extends DvrGuidedStepFragment {
return super.getTrackerLabelForGuidedAction(action);
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingDialogFragment.java b/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingDialogFragment.java
index 5b880bd6..15abf902 100644
--- a/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingDialogFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingDialogFragment.java
@@ -22,18 +22,15 @@ import android.support.v17.leanback.app.GuidedStepFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
import com.android.tv.R;
-/**
- * A dialog fragment which contains {@link DvrStopSeriesRecordingFragment}.
- */
+/** A dialog fragment which contains {@link DvrStopSeriesRecordingFragment}. */
public class DvrStopSeriesRecordingDialogFragment extends DialogFragment {
public static final String DIALOG_TAG = "dialog_tag";
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
+ public View onCreateView(
+ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.halfsized_dialog, container, false);
GuidedStepFragment fragment = new DvrStopSeriesRecordingFragment();
fragment.setArguments(getArguments());
diff --git a/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingFragment.java b/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingFragment.java
index 7b56cfc1..99211fdb 100644
--- a/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingFragment.java
@@ -25,25 +25,18 @@ import android.support.v17.leanback.widget.GuidedAction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
-import com.android.tv.ApplicationSingletons;
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.SeriesRecording;
-
import java.util.ArrayList;
import java.util.List;
-/**
- * A fragment which asks the user to stop series recording.
- */
+/** A fragment which asks the user to stop series recording. */
public class DvrStopSeriesRecordingFragment extends DvrGuidedStepFragment {
- /**
- * Key for the series recording to be stopped.
- */
+ /** Key for the series recording to be stopped. */
public static final String KEY_SERIES_RECORDING = "key_series_recoridng";
private static final int ACTION_STOP_SERIES_RECORDING = 1;
@@ -51,7 +44,8 @@ public class DvrStopSeriesRecordingFragment extends DvrGuidedStepFragment {
private SeriesRecording mSeriesRecording;
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ public View onCreateView(
+ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mSeriesRecording = getArguments().getParcelable(KEY_SERIES_RECORDING);
return super.onCreateView(inflater, container, savedInstanceState);
}
@@ -68,19 +62,21 @@ public class DvrStopSeriesRecordingFragment extends DvrGuidedStepFragment {
@Override
public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
Activity activity = getActivity();
- actions.add(new GuidedAction.Builder(activity)
- .id(ACTION_STOP_SERIES_RECORDING)
- .title(R.string.dvr_series_schedules_stop_dialog_action_stop)
- .build());
- actions.add(new GuidedAction.Builder(activity)
- .clickAction(GuidedAction.ACTION_ID_CANCEL)
- .build());
+ actions.add(
+ new GuidedAction.Builder(activity)
+ .id(ACTION_STOP_SERIES_RECORDING)
+ .title(R.string.dvr_series_schedules_stop_dialog_action_stop)
+ .build());
+ actions.add(
+ new GuidedAction.Builder(activity)
+ .clickAction(GuidedAction.ACTION_ID_CANCEL)
+ .build());
}
@Override
public void onTrackedGuidedActionClicked(GuidedAction action) {
if (action.getId() == ACTION_STOP_SERIES_RECORDING) {
- ApplicationSingletons singletons = TvApplication.getSingletons(getContext());
+ TvSingletons singletons = TvSingletons.getSingletons(getContext());
DvrManager dvrManager = singletons.getDvrManager();
DvrDataManager dataManager = singletons.getDvrDataManager();
List<ScheduledRecording> toDelete = new ArrayList<>();
@@ -96,8 +92,10 @@ public class DvrStopSeriesRecordingFragment extends DvrGuidedStepFragment {
if (!toDelete.isEmpty()) {
dvrManager.forceRemoveScheduledRecording(ScheduledRecording.toArray(toDelete));
}
- dvrManager.updateSeriesRecording(SeriesRecording.buildFrom(mSeriesRecording)
- .setState(SeriesRecording.STATE_SERIES_STOPPED).build());
+ dvrManager.updateSeriesRecording(
+ SeriesRecording.buildFrom(mSeriesRecording)
+ .setState(SeriesRecording.STATE_SERIES_STOPPED)
+ .build());
}
dismissDialog();
}
diff --git a/src/com/android/tv/dvr/ui/DvrUiHelper.java b/src/com/android/tv/dvr/ui/DvrUiHelper.java
index 302fd6cd..16afbdef 100644
--- a/src/com/android/tv/dvr/ui/DvrUiHelper.java
+++ b/src/com/android/tv/dvr/ui/DvrUiHelper.java
@@ -37,17 +37,18 @@ import android.text.TextUtils;
import android.text.style.TextAppearanceSpan;
import android.widget.ImageView;
import android.widget.Toast;
-
import com.android.tv.MainActivity;
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
+import com.android.tv.common.BuildConfig;
import com.android.tv.common.SoftPreconditions;
+import com.android.tv.common.recording.RecordingStorageStatusManager;
+import com.android.tv.common.util.CommonUtils;
import com.android.tv.data.BaseProgram;
-import com.android.tv.data.Channel;
import com.android.tv.data.Program;
+import com.android.tv.data.api.Channel;
import com.android.tv.dialog.HalfSizedDialogFragment;
import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.DvrStorageStatusManager;
import com.android.tv.dvr.data.RecordedProgram;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.SeriesRecording;
@@ -56,6 +57,7 @@ import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrAlreadyRecordedDialog
import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrAlreadyScheduledDialogFragment;
import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrChannelRecordDurationOptionDialogFragment;
import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrChannelWatchConflictDialogFragment;
+import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrFutureProgramInfoDialogFragment;
import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrInsufficientSpaceErrorDialogFragment;
import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrMissingStorageErrorDialogFragment;
import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrNoFreeSpaceErrorDialogFragment;
@@ -65,21 +67,19 @@ import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrSmallSizedStorageErro
import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrStopRecordingDialogFragment;
import com.android.tv.dvr.ui.browse.DvrBrowseActivity;
import com.android.tv.dvr.ui.browse.DvrDetailsActivity;
+import com.android.tv.dvr.ui.list.DvrHistoryActivity;
import com.android.tv.dvr.ui.list.DvrSchedulesActivity;
import com.android.tv.dvr.ui.list.DvrSchedulesFragment;
import com.android.tv.dvr.ui.list.DvrSeriesSchedulesFragment;
import com.android.tv.dvr.ui.playback.DvrPlaybackActivity;
import com.android.tv.util.ToastUtils;
import com.android.tv.util.Utils;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
-/**
- * A helper class for DVR UI.
- */
+/** A helper class for DVR UI. */
@MainThread
@TargetApi(Build.VERSION_CODES.N)
public class DvrUiHelper {
@@ -91,45 +91,43 @@ public class DvrUiHelper {
* Checks if the storage status is good for recording and shows error messages if needed.
*
* @param recordingRequestRunnable if the storage status is OK to record or users choose to
- * perform the operation anyway, this Runnable will run.
+ * perform the operation anyway, this Runnable will run.
*/
- public static void checkStorageStatusAndShowErrorMessage(Activity activity, String inputId,
- Runnable recordingRequestRunnable) {
- if (Utils.isBundledInput(inputId)) {
- switch (TvApplication.getSingletons(activity).getDvrStorageStatusManager()
+ public static void checkStorageStatusAndShowErrorMessage(
+ Activity activity, String inputId, Runnable recordingRequestRunnable) {
+ if (CommonUtils.isBundledInput(inputId)) {
+ switch (TvSingletons.getSingletons(activity)
+ .getRecordingStorageStatusManager()
.getDvrStorageStatus()) {
- case DvrStorageStatusManager.STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL:
+ case RecordingStorageStatusManager.STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL:
showDvrSmallSizedStorageErrorDialog(activity);
return;
- case DvrStorageStatusManager.STORAGE_STATUS_MISSING:
+ case RecordingStorageStatusManager.STORAGE_STATUS_MISSING:
showDvrMissingStorageErrorDialog(activity);
return;
- case DvrStorageStatusManager.STORAGE_STATUS_FREE_SPACE_INSUFFICIENT:
+ case RecordingStorageStatusManager.STORAGE_STATUS_FREE_SPACE_INSUFFICIENT:
showDvrNoFreeSpaceErrorDialog(activity, recordingRequestRunnable);
return;
+ default: // fall out
}
}
recordingRequestRunnable.run();
}
- /**
- * Shows the schedule dialog.
- */
- public static void showScheduleDialog(Activity activity, Program program,
- boolean addCurrentProgramToSeries) {
+ /** Shows the schedule dialog. */
+ public static void showScheduleDialog(
+ Activity activity, Program program, boolean addCurrentProgramToSeries) {
if (SoftPreconditions.checkNotNull(program) == null) {
return;
}
Bundle args = new Bundle();
args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program);
- args.putBoolean(DvrScheduleFragment.KEY_ADD_CURRENT_PROGRAM_TO_SERIES,
- addCurrentProgramToSeries);
+ args.putBoolean(
+ DvrScheduleFragment.KEY_ADD_CURRENT_PROGRAM_TO_SERIES, addCurrentProgramToSeries);
showDialogFragment(activity, new DvrScheduleDialogFragment(), args, true, true);
}
- /**
- * Shows the recording duration options dialog.
- */
+ /** Shows the recording duration options dialog. */
public static void showChannelRecordDurationOptions(Activity activity, Channel channel) {
if (SoftPreconditions.checkNotNull(channel) == null) {
return;
@@ -139,9 +137,7 @@ public class DvrUiHelper {
showDialogFragment(activity, new DvrChannelRecordDurationOptionDialogFragment(), args);
}
- /**
- * Shows the dialog which says that the new schedule conflicts with others.
- */
+ /** Shows the dialog which says that the new schedule conflicts with others. */
public static void showScheduleConflictDialog(Activity activity, Program program) {
if (program == null) {
return;
@@ -151,9 +147,7 @@ public class DvrUiHelper {
showDialogFragment(activity, new DvrProgramConflictDialogFragment(), args, false, true);
}
- /**
- * Shows the conflict dialog for the channel watching.
- */
+ /** Shows the conflict dialog for the channel watching. */
public static void showChannelWatchConflictDialog(MainActivity activity, Channel channel) {
if (channel == null) {
return;
@@ -163,63 +157,60 @@ public class DvrUiHelper {
showDialogFragment(activity, new DvrChannelWatchConflictDialogFragment(), args);
}
- /**
- * Shows DVR insufficient space error dialog.
- */
- public static void showDvrInsufficientSpaceErrorDialog(MainActivity activity,
- Set<String> failedScheduledRecordingInfoSet) {
+ /** Shows DVR insufficient space error dialog. */
+ public static void showDvrInsufficientSpaceErrorDialog(
+ MainActivity activity, Set<String> failedScheduledRecordingInfoSet) {
Bundle args = new Bundle();
ArrayList<String> failedScheduledRecordingInfoArray =
new ArrayList<>(failedScheduledRecordingInfoSet);
- args.putStringArrayList(DvrInsufficientSpaceErrorFragment.FAILED_SCHEDULED_RECORDING_INFOS,
+ args.putStringArrayList(
+ DvrInsufficientSpaceErrorFragment.FAILED_SCHEDULED_RECORDING_INFOS,
failedScheduledRecordingInfoArray);
showDialogFragment(activity, new DvrInsufficientSpaceErrorDialogFragment(), args);
- Utils.clearRecordingFailedReason(activity,
- TvInputManager.RECORDING_ERROR_INSUFFICIENT_SPACE);
+ Utils.clearRecordingFailedReason(
+ activity, TvInputManager.RECORDING_ERROR_INSUFFICIENT_SPACE);
Utils.clearFailedScheduledRecordingInfoSet(activity);
}
/**
* Shows DVR no free space error dialog.
*
- * @param recordingRequestRunnable the recording request to be executed when users choose
- * {@link DvrGuidedStepFragment#ACTION_RECORD_ANYWAY}.
+ * @param recordingRequestRunnable the recording request to be executed when users choose {@link
+ * DvrGuidedStepFragment#ACTION_RECORD_ANYWAY}.
*/
- public static void showDvrNoFreeSpaceErrorDialog(Activity activity,
- Runnable recordingRequestRunnable) {
+ public static void showDvrNoFreeSpaceErrorDialog(
+ Activity activity, Runnable recordingRequestRunnable) {
DvrHalfSizedDialogFragment fragment = new DvrNoFreeSpaceErrorDialogFragment();
- fragment.setOnActionClickListener(new HalfSizedDialogFragment.OnActionClickListener() {
- @Override
- public void onActionClick(long actionId) {
- if (actionId == DvrGuidedStepFragment.ACTION_RECORD_ANYWAY) {
- recordingRequestRunnable.run();
- } else if (actionId == DvrGuidedStepFragment.ACTION_DELETE_RECORDINGS) {
- Intent intent = new Intent(activity, DvrBrowseActivity.class);
- activity.startActivity(intent);
- }
- }
- });
+ fragment.setOnActionClickListener(
+ new HalfSizedDialogFragment.OnActionClickListener() {
+ @Override
+ public void onActionClick(long actionId) {
+ if (actionId == DvrGuidedStepFragment.ACTION_RECORD_ANYWAY) {
+ recordingRequestRunnable.run();
+ } else if (actionId == DvrGuidedStepFragment.ACTION_DELETE_RECORDINGS) {
+ Intent intent = new Intent(activity, DvrBrowseActivity.class);
+ activity.startActivity(intent);
+ }
+ }
+ });
showDialogFragment(activity, fragment, null);
}
- /**
- * Shows DVR missing storage error dialog.
- */
+ /** Shows DVR missing storage error dialog. */
private static void showDvrMissingStorageErrorDialog(Activity activity) {
showDialogFragment(activity, new DvrMissingStorageErrorDialogFragment(), null);
}
- /**
- * Shows DVR small sized storage error dialog.
- */
+ /** Shows DVR small sized storage error dialog. */
public static void showDvrSmallSizedStorageErrorDialog(Activity activity) {
showDialogFragment(activity, new DvrSmallSizedStorageErrorDialogFragment(), null);
}
- /**
- * Shows stop recording dialog.
- */
- public static void showStopRecordingDialog(Activity activity, long channelId, int reason,
+ /** Shows stop recording dialog. */
+ public static void showStopRecordingDialog(
+ Activity activity,
+ long channelId,
+ int reason,
HalfSizedDialogFragment.OnActionClickListener listener) {
Bundle args = new Bundle();
args.putLong(DvrHalfSizedDialogFragment.KEY_CHANNEL_ID, channelId);
@@ -229,9 +220,7 @@ public class DvrUiHelper {
showDialogFragment(activity, fragment, args);
}
- /**
- * Shows "already scheduled" dialog.
- */
+ /** Shows "already scheduled" dialog. */
public static void showAlreadyScheduleDialog(Activity activity, Program program) {
if (program == null) {
return;
@@ -241,9 +230,7 @@ public class DvrUiHelper {
showDialogFragment(activity, new DvrAlreadyScheduledDialogFragment(), args, false, true);
}
- /**
- * Shows "already recorded" dialog.
- */
+ /** Shows "already recorded" dialog. */
public static void showAlreadyRecordedDialog(Activity activity, Program program) {
if (program == null) {
return;
@@ -253,37 +240,49 @@ public class DvrUiHelper {
showDialogFragment(activity, new DvrAlreadyRecordedDialogFragment(), args, false, true);
}
+ /** Shows program information dialog. */
+ public static void showProgramInfoDialog(Activity activity, Program program) {
+ if (program == null || !BuildConfig.ENG) {
+ return;
+ }
+ Bundle args = new Bundle();
+ args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program);
+ showDialogFragment(activity, new DvrFutureProgramInfoDialogFragment(), args, false, true);
+ }
+
/**
* Handle the request of recording a current program. It will handle creating schedules and
* shows the proper dialog and toast message respectively for timed-recording and program
* recording cases.
*
- * @param addProgramToSeries denotes whether the program to be recorded should be added into
- * the series recording when users choose to record the entire series.
+ * @param addProgramToSeries denotes whether the program to be recorded should be added into the
+ * series recording when users choose to record the entire series.
*/
- public static void requestRecordingCurrentProgram(Activity activity,
- Channel channel, Program program, boolean addProgramToSeries) {
+ public static void requestRecordingCurrentProgram(
+ Activity activity, Channel channel, Program program, boolean addProgramToSeries) {
if (program == null) {
DvrUiHelper.showChannelRecordDurationOptions(activity, channel);
} else if (DvrUiHelper.handleCreateSchedule(activity, program, addProgramToSeries)) {
- String msg = activity.getString(R.string.dvr_msg_current_program_scheduled,
- program.getTitle(), Utils.toTimeString(program.getEndTimeUtcMillis(), false));
+ String msg =
+ activity.getString(
+ R.string.dvr_msg_current_program_scheduled,
+ program.getTitle(),
+ Utils.toTimeString(program.getEndTimeUtcMillis(), false));
Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show();
}
}
/**
- * Handle the request of recording a future program. It will handle creating schedules and
- * shows the proper toast message.
+ * Handle the request of recording a future program. It will handle creating schedules and shows
+ * the proper toast message.
*
- * @param addProgramToSeries denotes whether the program to be recorded should be added into
- * the series recording when users choose to record the entire series.
+ * @param addProgramToSeries denotes whether the program to be recorded should be added into the
+ * series recording when users choose to record the entire series.
*/
- public static void requestRecordingFutureProgram(Activity activity,
- Program program, boolean addProgramToSeries) {
+ public static void requestRecordingFutureProgram(
+ Activity activity, Program program, boolean addProgramToSeries) {
if (DvrUiHelper.handleCreateSchedule(activity, program, addProgramToSeries)) {
- String msg = activity.getString(
- R.string.dvr_msg_program_scheduled, program.getTitle());
+ String msg = activity.getString(R.string.dvr_msg_program_scheduled, program.getTitle());
ToastUtils.show(activity, msg, Toast.LENGTH_SHORT);
}
}
@@ -292,12 +291,12 @@ public class DvrUiHelper {
* Handles the action to create the new schedule. It returns {@code true} if the schedule is
* added and there's no additional UI, otherwise {@code false}.
*/
- private static boolean handleCreateSchedule(Activity activity, Program program,
- boolean addProgramToSeries) {
+ private static boolean handleCreateSchedule(
+ Activity activity, Program program, boolean addProgramToSeries) {
if (program == null) {
return false;
}
- DvrManager dvrManager = TvApplication.getSingletons(activity).getDvrManager();
+ DvrManager dvrManager = TvSingletons.getSingletons(activity).getDvrManager();
if (!program.isEpisodic()) {
// One time recording.
dvrManager.addSchedule(program);
@@ -307,18 +306,24 @@ public class DvrUiHelper {
}
} else {
// Show recorded program rather than the schedule.
- RecordedProgram recordedProgram = dvrManager.getRecordedProgram(program.getTitle(),
- program.getSeasonNumber(), program.getEpisodeNumber());
+ RecordedProgram recordedProgram =
+ dvrManager.getRecordedProgram(
+ program.getTitle(),
+ program.getSeasonNumber(),
+ program.getEpisodeNumber());
if (recordedProgram != null) {
DvrUiHelper.showAlreadyRecordedDialog(activity, program);
return false;
}
- ScheduledRecording duplicate = dvrManager.getScheduledRecording(program.getTitle(),
- program.getSeasonNumber(), program.getEpisodeNumber());
+ ScheduledRecording duplicate =
+ dvrManager.getScheduledRecording(
+ program.getTitle(),
+ program.getSeasonNumber(),
+ program.getEpisodeNumber());
if (duplicate != null
&& (duplicate.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED
- || duplicate.getState()
- == ScheduledRecording.STATE_RECORDING_IN_PROGRESS)) {
+ || duplicate.getState()
+ == ScheduledRecording.STATE_RECORDING_IN_PROGRESS)) {
DvrUiHelper.showAlreadyScheduleDialog(activity, program);
return false;
}
@@ -334,39 +339,44 @@ public class DvrUiHelper {
return true;
}
- private static void showDialogFragment(Activity activity,
- DvrHalfSizedDialogFragment dialogFragment, Bundle args) {
+ private static void showDialogFragment(
+ Activity activity, DvrHalfSizedDialogFragment dialogFragment, Bundle args) {
showDialogFragment(activity, dialogFragment, args, false, false);
}
- private static void showDialogFragment(Activity activity,
- DvrHalfSizedDialogFragment dialogFragment, Bundle args, boolean keepSidePanelHistory,
+ private static void showDialogFragment(
+ Activity activity,
+ DvrHalfSizedDialogFragment dialogFragment,
+ Bundle args,
+ boolean keepSidePanelHistory,
boolean keepProgramGuide) {
dialogFragment.setArguments(args);
if (activity instanceof MainActivity) {
- ((MainActivity) activity).getOverlayManager()
- .showDialogFragment(DvrHalfSizedDialogFragment.DIALOG_TAG, dialogFragment,
- keepSidePanelHistory, keepProgramGuide);
+ ((MainActivity) activity)
+ .getOverlayManager()
+ .showDialogFragment(
+ DvrHalfSizedDialogFragment.DIALOG_TAG,
+ dialogFragment,
+ keepSidePanelHistory,
+ keepProgramGuide);
} else {
- dialogFragment.show(activity.getFragmentManager(),
- DvrHalfSizedDialogFragment.DIALOG_TAG);
+ dialogFragment.show(
+ activity.getFragmentManager(), DvrHalfSizedDialogFragment.DIALOG_TAG);
}
}
- /**
- * Checks whether channel watch conflict dialog is open or not.
- */
+ /** Checks whether channel watch conflict dialog is open or not. */
public static boolean isChannelWatchConflictDialogShown(MainActivity activity) {
- return activity.getOverlayManager().getCurrentDialog() instanceof
- DvrChannelWatchConflictDialogFragment;
+ return activity.getOverlayManager().getCurrentDialog()
+ instanceof DvrChannelWatchConflictDialogFragment;
}
- private static ScheduledRecording getEarliestScheduledRecording(List<ScheduledRecording>
- recordings) {
+ private static ScheduledRecording getEarliestScheduledRecording(
+ List<ScheduledRecording> recordings) {
ScheduledRecording earlistScheduledRecording = null;
if (!recordings.isEmpty()) {
- Collections.sort(recordings,
- ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR);
+ Collections.sort(
+ recordings, ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR);
earlistScheduledRecording = recordings.get(0);
}
return earlistScheduledRecording;
@@ -378,10 +388,10 @@ public class DvrUiHelper {
* @param programId the ID of the recorded program going to be played.
* @param seekTimeMs the seek position to initial playback.
* @param pinChecked {@code true} if the pin code for parental controls has already been
- * verified, otherwise {@code false}.
+ * verified, otherwise {@code false}.
*/
- public static void startPlaybackActivity(Context context, long programId,
- long seekTimeMs, boolean pinChecked) {
+ public static void startPlaybackActivity(
+ Context context, long programId, long seekTimeMs, boolean pinChecked) {
Intent intent = new Intent(context, DvrPlaybackActivity.class);
intent.putExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_ID, programId);
if (seekTimeMs != TvInputManager.TIME_SHIFT_INVALID_TIME) {
@@ -391,51 +401,52 @@ public class DvrUiHelper {
context.startActivity(intent);
}
- /**
- * Shows the schedules activity to resolve the tune conflict.
- */
+ /** Shows the schedules activity to resolve the tune conflict. */
public static void startSchedulesActivityForTuneConflict(Context context, Channel channel) {
if (channel == null) {
return;
}
- List<ScheduledRecording> conflicts = TvApplication.getSingletons(context).getDvrManager()
- .getConflictingSchedulesForTune(channel.getId());
+ List<ScheduledRecording> conflicts =
+ TvSingletons.getSingletons(context)
+ .getDvrManager()
+ .getConflictingSchedulesForTune(channel.getId());
startSchedulesActivity(context, getEarliestScheduledRecording(conflicts));
}
- /**
- * Shows the schedules activity to resolve the one time recording conflict.
- */
- public static void startSchedulesActivityForOneTimeRecordingConflict(Context context,
- List<ScheduledRecording> conflicts) {
+ /** Shows the schedules activity to resolve the one time recording conflict. */
+ public static void startSchedulesActivityForOneTimeRecordingConflict(
+ Context context, List<ScheduledRecording> conflicts) {
startSchedulesActivity(context, getEarliestScheduledRecording(conflicts));
}
- /**
- * Shows the schedules activity with full schedule.
- */
- public static void startSchedulesActivity(Context context, ScheduledRecording
- focusedScheduledRecording) {
+ /** Shows the schedules activity with full schedule. */
+ public static void startDvrHistoryActivity(Context context) {
+ Intent intent = new Intent(context, DvrHistoryActivity.class);
+ context.startActivity(intent);
+ }
+
+ /** Shows the schedules activity with full schedule. */
+ public static void startSchedulesActivity(
+ Context context, ScheduledRecording focusedScheduledRecording) {
Intent intent = new Intent(context, DvrSchedulesActivity.class);
- intent.putExtra(DvrSchedulesActivity.KEY_SCHEDULES_TYPE,
- DvrSchedulesActivity.TYPE_FULL_SCHEDULE);
+ intent.putExtra(
+ DvrSchedulesActivity.KEY_SCHEDULES_TYPE, DvrSchedulesActivity.TYPE_FULL_SCHEDULE);
if (focusedScheduledRecording != null) {
- intent.putExtra(DvrSchedulesFragment.SCHEDULES_KEY_SCHEDULED_RECORDING,
+ intent.putExtra(
+ DvrSchedulesFragment.SCHEDULES_KEY_SCHEDULED_RECORDING,
focusedScheduledRecording);
}
context.startActivity(intent);
}
- /**
- * Shows the schedules activity for series recording.
- */
- public static void startSchedulesActivityForSeries(Context context,
- SeriesRecording seriesRecording) {
+ /** Shows the schedules activity for series recording. */
+ public static void startSchedulesActivityForSeries(
+ Context context, SeriesRecording seriesRecording) {
Intent intent = new Intent(context, DvrSchedulesActivity.class);
- intent.putExtra(DvrSchedulesActivity.KEY_SCHEDULES_TYPE,
- DvrSchedulesActivity.TYPE_SERIES_SCHEDULE);
- intent.putExtra(DvrSeriesSchedulesFragment.SERIES_SCHEDULES_KEY_SERIES_RECORDING,
- seriesRecording);
+ intent.putExtra(
+ DvrSchedulesActivity.KEY_SCHEDULES_TYPE, DvrSchedulesActivity.TYPE_SERIES_SCHEDULE);
+ intent.putExtra(
+ DvrSeriesSchedulesFragment.SERIES_SCHEDULES_KEY_SERIES_RECORDING, seriesRecording);
context.startActivity(intent);
}
@@ -444,93 +455,125 @@ public class DvrUiHelper {
*
* @param programs list of programs which belong to the series.
*/
- public static void startSeriesSettingsActivity(Context context, long seriesRecordingId,
- @Nullable List<Program> programs, boolean removeEmptySeriesSchedule,
- boolean isWindowTranslucent, boolean showViewScheduleOptionInDialog,
+ public static void startSeriesSettingsActivity(
+ Context context,
+ long seriesRecordingId,
+ @Nullable List<Program> programs,
+ boolean removeEmptySeriesSchedule,
+ boolean isWindowTranslucent,
+ boolean showViewScheduleOptionInDialog,
Program currentProgram) {
- SeriesRecording series = TvApplication.getSingletons(context).getDvrDataManager()
- .getSeriesRecording(seriesRecordingId);
+ SeriesRecording series =
+ TvSingletons.getSingletons(context)
+ .getDvrDataManager()
+ .getSeriesRecording(seriesRecordingId);
if (series == null) {
return;
}
if (programs != null) {
- startSeriesSettingsActivityInternal(context, seriesRecordingId, programs,
- removeEmptySeriesSchedule, isWindowTranslucent,
- showViewScheduleOptionInDialog, currentProgram);
+ startSeriesSettingsActivityInternal(
+ context,
+ seriesRecordingId,
+ programs,
+ removeEmptySeriesSchedule,
+ isWindowTranslucent,
+ showViewScheduleOptionInDialog,
+ currentProgram);
} else {
EpisodicProgramLoadTask episodicProgramLoadTask =
new EpisodicProgramLoadTask(context, series) {
- @Override
- protected void onPostExecute(List<Program> loadedPrograms) {
- sProgressDialog.dismiss();
- sProgressDialog = null;
- startSeriesSettingsActivityInternal(context, seriesRecordingId,
- loadedPrograms == null ? Collections.EMPTY_LIST : loadedPrograms,
- removeEmptySeriesSchedule, isWindowTranslucent,
- showViewScheduleOptionInDialog, currentProgram);
- }
- }.setLoadCurrentProgram(true)
- .setLoadDisallowedProgram(true)
- .setLoadScheduledEpisode(true)
- .setIgnoreChannelOption(true);
- sProgressDialog = ProgressDialog.show(context, null, context.getString(
- R.string.dvr_series_progress_message_reading_programs), true, true,
- new DialogInterface.OnCancelListener() {
@Override
- public void onCancel(DialogInterface dialogInterface) {
- episodicProgramLoadTask.cancel(true);
+ protected void onPostExecute(List<Program> loadedPrograms) {
+ sProgressDialog.dismiss();
sProgressDialog = null;
+ startSeriesSettingsActivityInternal(
+ context,
+ seriesRecordingId,
+ loadedPrograms == null
+ ? Collections.EMPTY_LIST
+ : loadedPrograms,
+ removeEmptySeriesSchedule,
+ isWindowTranslucent,
+ showViewScheduleOptionInDialog,
+ currentProgram);
}
- });
+ }.setLoadCurrentProgram(true)
+ .setLoadDisallowedProgram(true)
+ .setLoadScheduledEpisode(true)
+ .setIgnoreChannelOption(true);
+ sProgressDialog =
+ ProgressDialog.show(
+ context,
+ null,
+ context.getString(
+ R.string.dvr_series_progress_message_reading_programs),
+ true,
+ true,
+ new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialogInterface) {
+ episodicProgramLoadTask.cancel(true);
+ sProgressDialog = null;
+ }
+ });
episodicProgramLoadTask.execute();
}
}
- private static void startSeriesSettingsActivityInternal(Context context, long seriesRecordingId,
- @NonNull List<Program> programs, boolean removeEmptySeriesSchedule,
- boolean isWindowTranslucent, boolean showViewScheduleOptionInDialog,
+ private static void startSeriesSettingsActivityInternal(
+ Context context,
+ long seriesRecordingId,
+ @NonNull List<Program> programs,
+ boolean removeEmptySeriesSchedule,
+ boolean isWindowTranslucent,
+ boolean showViewScheduleOptionInDialog,
Program currentProgram) {
- SoftPreconditions.checkState(programs != null,
- TAG, "Start series settings activity but programs is null");
+ SoftPreconditions.checkState(
+ programs != null, TAG, "Start series settings activity but programs is null");
Intent intent = new Intent(context, DvrSeriesSettingsActivity.class);
intent.putExtra(DvrSeriesSettingsActivity.SERIES_RECORDING_ID, seriesRecordingId);
BigArguments.reset();
BigArguments.setArgument(DvrSeriesSettingsActivity.PROGRAM_LIST, programs);
- intent.putExtra(DvrSeriesSettingsActivity.REMOVE_EMPTY_SERIES_RECORDING,
- removeEmptySeriesSchedule);
+ intent.putExtra(
+ DvrSeriesSettingsActivity.REMOVE_EMPTY_SERIES_RECORDING, removeEmptySeriesSchedule);
intent.putExtra(DvrSeriesSettingsActivity.IS_WINDOW_TRANSLUCENT, isWindowTranslucent);
- intent.putExtra(DvrSeriesSettingsActivity.SHOW_VIEW_SCHEDULE_OPTION_IN_DIALOG,
+ intent.putExtra(
+ DvrSeriesSettingsActivity.SHOW_VIEW_SCHEDULE_OPTION_IN_DIALOG,
showViewScheduleOptionInDialog);
intent.putExtra(DvrSeriesSettingsActivity.CURRENT_PROGRAM, currentProgram);
context.startActivity(intent);
}
- /**
- * Shows "series recording scheduled" dialog activity.
- */
- public static void StartSeriesScheduledDialogActivity(Context context,
- SeriesRecording seriesRecording, boolean showViewScheduleOptionInDialog,
+ /** Shows "series recording scheduled" dialog activity. */
+ public static void startSeriesScheduledDialogActivity(
+ Context context,
+ SeriesRecording seriesRecording,
+ boolean showViewScheduleOptionInDialog,
List<Program> programs) {
if (seriesRecording == null) {
return;
}
Intent intent = new Intent(context, DvrSeriesScheduledDialogActivity.class);
- intent.putExtra(DvrSeriesScheduledDialogActivity.SERIES_RECORDING_ID,
- seriesRecording.getId());
- intent.putExtra(DvrSeriesScheduledDialogActivity.SHOW_VIEW_SCHEDULE_OPTION,
+ intent.putExtra(
+ DvrSeriesScheduledDialogActivity.SERIES_RECORDING_ID, seriesRecording.getId());
+ intent.putExtra(
+ DvrSeriesScheduledDialogActivity.SHOW_VIEW_SCHEDULE_OPTION,
showViewScheduleOptionInDialog);
BigArguments.reset();
- BigArguments.setArgument(DvrSeriesScheduledFragment.SERIES_SCHEDULED_KEY_PROGRAMS,
- programs);
+ BigArguments.setArgument(
+ DvrSeriesScheduledFragment.SERIES_SCHEDULED_KEY_PROGRAMS, programs);
context.startActivity(intent);
}
/**
- * Shows the details activity for the DVR items. The type of DVR items may be
- * {@link ScheduledRecording}, {@link RecordedProgram}, or {@link SeriesRecording}.
+ * Shows the details activity for the DVR items. The type of DVR items may be {@link
+ * ScheduledRecording}, {@link RecordedProgram}, or {@link SeriesRecording}.
*/
- public static void startDetailsActivity(Activity activity, Object dvrItem,
- @Nullable ImageView imageView, boolean hideViewSchedule) {
+ public static void startDetailsActivity(
+ Activity activity,
+ Object dvrItem,
+ @Nullable ImageView imageView,
+ boolean hideViewSchedule) {
if (dvrItem == null) {
return;
}
@@ -544,6 +587,17 @@ public class DvrUiHelper {
viewType = DvrDetailsActivity.SCHEDULED_RECORDING_VIEW;
} else if (schedule.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS) {
viewType = DvrDetailsActivity.CURRENT_RECORDING_VIEW;
+ } else if (schedule.getState() == ScheduledRecording.STATE_RECORDING_FINISHED
+ && schedule.getRecordedProgramId() != null) {
+ recordingId = schedule.getRecordedProgramId();
+ viewType = DvrDetailsActivity.RECORDED_PROGRAM_VIEW;
+ } else if (schedule.getState() == ScheduledRecording.STATE_RECORDING_FAILED) {
+ viewType = DvrDetailsActivity.SCHEDULED_RECORDING_VIEW;
+ hideViewSchedule = true;
+ // TODO(b/72638385): pass detailed error message
+ intent.putExtra(
+ DvrDetailsActivity.EXTRA_FAILED_MESSAGE,
+ activity.getString(R.string.dvr_recording_failed));
} else {
return;
}
@@ -561,89 +615,108 @@ public class DvrUiHelper {
intent.putExtra(DvrDetailsActivity.HIDE_VIEW_SCHEDULE, hideViewSchedule);
Bundle bundle = null;
if (imageView != null) {
- bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, imageView,
- DvrDetailsActivity.SHARED_ELEMENT_NAME).toBundle();
+ bundle =
+ ActivityOptionsCompat.makeSceneTransitionAnimation(
+ activity, imageView, DvrDetailsActivity.SHARED_ELEMENT_NAME)
+ .toBundle();
}
activity.startActivity(intent, bundle);
}
- /**
- * Shows the cancel all dialog for series schedules list.
- */
- public static void showCancelAllSeriesRecordingDialog(DvrSchedulesActivity activity,
- SeriesRecording seriesRecording) {
+ /** Shows the cancel all dialog for series schedules list. */
+ public static void showCancelAllSeriesRecordingDialog(
+ DvrSchedulesActivity activity, SeriesRecording seriesRecording) {
DvrStopSeriesRecordingDialogFragment dvrStopSeriesRecordingDialogFragment =
new DvrStopSeriesRecordingDialogFragment();
Bundle arguments = new Bundle();
- arguments.putParcelable(DvrStopSeriesRecordingFragment.KEY_SERIES_RECORDING,
- seriesRecording);
+ arguments.putParcelable(
+ DvrStopSeriesRecordingFragment.KEY_SERIES_RECORDING, seriesRecording);
dvrStopSeriesRecordingDialogFragment.setArguments(arguments);
- dvrStopSeriesRecordingDialogFragment.show(activity.getFragmentManager(),
- DvrStopSeriesRecordingDialogFragment.DIALOG_TAG);
+ dvrStopSeriesRecordingDialogFragment.show(
+ activity.getFragmentManager(), DvrStopSeriesRecordingDialogFragment.DIALOG_TAG);
}
- /**
- * Shows the series deletion activity.
- */
+ /** Shows the series deletion activity. */
public static void startSeriesDeletionActivity(Context context, long seriesRecordingId) {
Intent intent = new Intent(context, DvrSeriesDeletionActivity.class);
intent.putExtra(DvrSeriesDeletionActivity.SERIES_RECORDING_ID, seriesRecordingId);
context.startActivity(intent);
}
- public static void showAddScheduleToast(Context context,
- String title, long startTimeMs, long endTimeMs) {
- String msg = (startTimeMs > System.currentTimeMillis()) ?
- context.getString(R.string.dvr_msg_program_scheduled, title)
- : context.getString(R.string.dvr_msg_current_program_scheduled, title,
- Utils.toTimeString(endTimeMs, false));
+ public static void showAddScheduleToast(
+ Context context, String title, long startTimeMs, long endTimeMs) {
+ String msg =
+ (startTimeMs > System.currentTimeMillis())
+ ? context.getString(R.string.dvr_msg_program_scheduled, title)
+ : context.getString(
+ R.string.dvr_msg_current_program_scheduled,
+ title,
+ Utils.toTimeString(endTimeMs, false));
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
}
- /**
- * Returns the styled schedule's title with its season and episode number.
- */
- public static CharSequence getStyledTitleWithEpisodeNumber(Context context,
- ScheduledRecording schedule, int episodeNumberStyleResId) {
- return getStyledTitleWithEpisodeNumber(context, schedule.getProgramTitle(),
- schedule.getSeasonNumber(), schedule.getEpisodeNumber(), episodeNumberStyleResId);
+ /** Returns the styled schedule's title with its season and episode number. */
+ public static CharSequence getStyledTitleWithEpisodeNumber(
+ Context context, ScheduledRecording schedule, int episodeNumberStyleResId) {
+ return getStyledTitleWithEpisodeNumber(
+ context,
+ schedule.getProgramTitle(),
+ schedule.getSeasonNumber(),
+ schedule.getEpisodeNumber(),
+ episodeNumberStyleResId);
}
- /**
- * Returns the styled program's title with its season and episode number.
- */
- public static CharSequence getStyledTitleWithEpisodeNumber(Context context,
- BaseProgram program, int episodeNumberStyleResId) {
- return getStyledTitleWithEpisodeNumber(context, program.getTitle(),
- program.getSeasonNumber(), program.getEpisodeNumber(), episodeNumberStyleResId);
+ /** Returns the styled program's title with its season and episode number. */
+ public static CharSequence getStyledTitleWithEpisodeNumber(
+ Context context, BaseProgram program, int episodeNumberStyleResId) {
+ return getStyledTitleWithEpisodeNumber(
+ context,
+ program.getTitle(),
+ program.getSeasonNumber(),
+ program.getEpisodeNumber(),
+ episodeNumberStyleResId);
}
@NonNull
- public static CharSequence getStyledTitleWithEpisodeNumber(Context context, String title,
- String seasonNumber, String episodeNumber, int episodeNumberStyleResId) {
+ public static CharSequence getStyledTitleWithEpisodeNumber(
+ Context context,
+ String title,
+ String seasonNumber,
+ String episodeNumber,
+ int episodeNumberStyleResId) {
if (TextUtils.isEmpty(title)) {
return "";
}
SpannableStringBuilder builder;
if (TextUtils.isEmpty(seasonNumber) || seasonNumber.equals("0")) {
- builder = TextUtils.isEmpty(episodeNumber) ? new SpannableStringBuilder(title) :
- new SpannableStringBuilder(Html.fromHtml(
- context.getString(R.string.program_title_with_episode_number_no_season,
- title, episodeNumber)));
+ builder =
+ TextUtils.isEmpty(episodeNumber)
+ ? new SpannableStringBuilder(title)
+ : new SpannableStringBuilder(Html.fromHtml(context.getString(
+ R.string.program_title_with_episode_number_no_season,
+ title,
+ episodeNumber)));
} else {
- builder = new SpannableStringBuilder(Html.fromHtml(
- context.getString(R.string.program_title_with_episode_number,
- title, seasonNumber, episodeNumber)));
+ builder =
+ new SpannableStringBuilder(
+ Html.fromHtml(
+ context.getString(
+ R.string.program_title_with_episode_number,
+ title,
+ seasonNumber,
+ episodeNumber)));
}
Object[] spans = builder.getSpans(0, builder.length(), Object.class);
if (spans.length > 0) {
if (episodeNumberStyleResId != 0) {
- builder.setSpan(new TextAppearanceSpan(context, episodeNumberStyleResId),
- builder.getSpanStart(spans[0]), builder.getSpanEnd(spans[0]),
+ builder.setSpan(
+ new TextAppearanceSpan(context, episodeNumberStyleResId),
+ builder.getSpanStart(spans[0]),
+ builder.getSpanEnd(spans[0]),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
builder.removeSpan(spans[0]);
}
return new SpannableString(builder);
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/FadeBackground.java b/src/com/android/tv/dvr/ui/FadeBackground.java
index 4f06ebcf..373daaaf 100644
--- a/src/com/android/tv/dvr/ui/FadeBackground.java
+++ b/src/com/android/tv/dvr/ui/FadeBackground.java
@@ -28,12 +28,9 @@ import android.transition.TransitionValues;
import android.transition.Visibility;
import android.util.AttributeSet;
import android.view.ViewGroup;
-
import com.android.tv.R;
-/**
- * This transition fades in/out of the background of the view by changing the background color.
- */
+/** This transition fades in/out of the background of the view by changing the background color. */
public class FadeBackground extends Transition {
private final int mMode;
@@ -45,22 +42,22 @@ public class FadeBackground extends Transition {
}
@Override
- public void captureStartValues(TransitionValues transitionValues) { }
+ public void captureStartValues(TransitionValues transitionValues) {}
@Override
- public void captureEndValues(TransitionValues transitionValues) { }
+ public void captureEndValues(TransitionValues transitionValues) {}
@Override
- public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
- TransitionValues endValues) {
+ public Animator createAnimator(
+ ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) {
if (startValues == null || endValues == null) {
return null;
}
Drawable background = endValues.view.getBackground();
if (background instanceof ColorDrawable) {
int color = ((ColorDrawable) background).getColor();
- int transparentColor = Color.argb(0, Color.red(color), Color.green(color),
- Color.blue(color));
+ int transparentColor =
+ Color.argb(0, Color.red(color), Color.green(color), Color.blue(color));
return mMode == Visibility.MODE_OUT
? ObjectAnimator.ofArgb(background, "color", transparentColor)
: ObjectAnimator.ofArgb(background, "color", transparentColor, color);
diff --git a/src/com/android/tv/dvr/ui/SortedArrayAdapter.java b/src/com/android/tv/dvr/ui/SortedArrayAdapter.java
index 8c0af9ed..1eb8080a 100644
--- a/src/com/android/tv/dvr/ui/SortedArrayAdapter.java
+++ b/src/com/android/tv/dvr/ui/SortedArrayAdapter.java
@@ -19,9 +19,7 @@ package com.android.tv.dvr.ui;
import android.support.annotation.VisibleForTesting;
import android.support.v17.leanback.widget.ArrayObjectAdapter;
import android.support.v17.leanback.widget.PresenterSelector;
-
import com.android.tv.common.SoftPreconditions;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -45,8 +43,8 @@ public abstract class SortedArrayAdapter<T> extends ArrayObjectAdapter {
this(presenterSelector, comparator, Integer.MAX_VALUE);
}
- public SortedArrayAdapter(PresenterSelector presenterSelector, Comparator<T> comparator,
- int maxItemCount) {
+ public SortedArrayAdapter(
+ PresenterSelector presenterSelector, Comparator<T> comparator, int maxItemCount) {
super(presenterSelector);
mComparator = comparator;
mMaxItemCount = maxItemCount;
@@ -88,9 +86,8 @@ public abstract class SortedArrayAdapter<T> extends ArrayObjectAdapter {
* Adds an item in sorted order to the adapter.
*
* @param item The item to add in sorted order to the adapter.
- * @param insertToEnd If items are inserted in a more or less sorted fashion,
- * sets this parameter to {@code true} to search insertion position from
- * the end to save search time.
+ * @param insertToEnd If items are inserted in a more or less sorted fashion, sets this
+ * parameter to {@code true} to search insertion position from the end to save search time.
*/
public final void add(T item, boolean insertToEnd) {
long newItemId = getId(item);
@@ -127,9 +124,7 @@ public abstract class SortedArrayAdapter<T> extends ArrayObjectAdapter {
return removeWithId((T) item);
}
- /**
- * Removes an item which has the same ID as {@code item}.
- */
+ /** Removes an item which has the same ID as {@code item}. */
public boolean removeWithId(T item) {
int index = indexWithId(item);
return index >= 0 && index < size() && removeItems(index, 1) == 1;
@@ -166,6 +161,7 @@ public abstract class SortedArrayAdapter<T> extends ArrayObjectAdapter {
/**
* Changes an item in the list.
+ *
* @param item The item to change.
*/
public final void change(T item) {
@@ -181,9 +177,7 @@ public abstract class SortedArrayAdapter<T> extends ArrayObjectAdapter {
add(item);
}
- /**
- * Checks whether the item is in the list.
- */
+ /** Checks whether the item is in the list. */
public final boolean contains(T item) {
return indexWithId(item) != -1;
}
@@ -194,10 +188,10 @@ public abstract class SortedArrayAdapter<T> extends ArrayObjectAdapter {
}
/**
- * Returns the id of the the given {@code item}, which will be used in {@link #change} to
- * decide if the given item is already existed in the adapter.
+ * Returns the id of the the given {@code item}, which will be used in {@link #change} to decide
+ * if the given item is already existed in the adapter.
*
- * The id must be stable.
+ * <p>The id must be stable.
*/
protected abstract long getId(T item);
@@ -212,11 +206,9 @@ public abstract class SortedArrayAdapter<T> extends ArrayObjectAdapter {
return -1;
}
- /**
- * Finds the position that the given item should be inserted to keep the sorted order.
- */
+ /** Finds the position that the given item should be inserted to keep the sorted order. */
public int findInsertPosition(T item) {
- for (int i = size() - mExtraItemCount - 1; i >=0; i--) {
+ for (int i = size() - mExtraItemCount - 1; i >= 0; i--) {
T r = (T) get(i);
if (mComparator.compare(r, item) <= 0) {
return i + 1;
@@ -242,4 +234,4 @@ public abstract class SortedArrayAdapter<T> extends ArrayObjectAdapter {
}
return lb;
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/TrackedGuidedStepFragment.java b/src/com/android/tv/dvr/ui/TrackedGuidedStepFragment.java
index 5fe9c478..0172f76f 100644
--- a/src/com/android/tv/dvr/ui/TrackedGuidedStepFragment.java
+++ b/src/com/android/tv/dvr/ui/TrackedGuidedStepFragment.java
@@ -19,8 +19,7 @@ package com.android.tv.dvr.ui;
import android.content.Context;
import android.support.v17.leanback.app.GuidedStepFragment;
import android.support.v17.leanback.widget.GuidedAction;
-
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.analytics.Tracker;
/** A {@link GuidedStepFragment} with {@link Tracker} for analytics. */
@@ -30,7 +29,7 @@ public abstract class TrackedGuidedStepFragment extends GuidedStepFragment {
@Override
public void onAttach(Context context) {
super.onAttach(context);
- mTracker = TvApplication.getSingletons(context).getAnalytics().getDefaultTracker();
+ mTracker = TvSingletons.getSingletons(context).getAnalytics().getDefaultTracker();
}
@Override
diff --git a/src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java b/src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java
index 38a78f5d..f3a6fea4 100644
--- a/src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java
+++ b/src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java
@@ -32,8 +32,8 @@ import android.widget.Button;
class ActionPresenterSelector extends PresenterSelector {
private final Presenter mOneLineActionPresenter = new OneLineActionPresenter();
private final Presenter mTwoLineActionPresenter = new TwoLineActionPresenter();
- private final Presenter[] mPresenters = new Presenter[] {
- mOneLineActionPresenter, mTwoLineActionPresenter};
+ private final Presenter[] mPresenters =
+ new Presenter[] {mOneLineActionPresenter, mTwoLineActionPresenter};
@Override
public Presenter getPresenter(Object item) {
@@ -65,8 +65,9 @@ class ActionPresenterSelector extends PresenterSelector {
class OneLineActionPresenter extends Presenter {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent) {
- View v = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.lb_action_1_line, parent, false);
+ View v =
+ LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.lb_action_1_line, parent, false);
return new ActionViewHolder(v, parent.getLayoutDirection());
}
@@ -87,8 +88,9 @@ class ActionPresenterSelector extends PresenterSelector {
class TwoLineActionPresenter extends Presenter {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent) {
- View v = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.lb_action_2_lines, parent, false);
+ View v =
+ LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.lb_action_2_lines, parent, false);
return new ActionViewHolder(v, parent.getLayoutDirection());
}
@@ -100,14 +102,20 @@ class ActionPresenterSelector extends PresenterSelector {
vh.mAction = action;
if (icon != null) {
- final int startPadding = vh.view.getResources()
- .getDimensionPixelSize(R.dimen.lb_action_with_icon_padding_start);
- final int endPadding = vh.view.getResources()
- .getDimensionPixelSize(R.dimen.lb_action_with_icon_padding_end);
+ final int startPadding =
+ vh.view
+ .getResources()
+ .getDimensionPixelSize(R.dimen.lb_action_with_icon_padding_start);
+ final int endPadding =
+ vh.view
+ .getResources()
+ .getDimensionPixelSize(R.dimen.lb_action_with_icon_padding_end);
vh.view.setPaddingRelative(startPadding, 0, endPadding, 0);
} else {
- final int padding = vh.view.getResources()
- .getDimensionPixelSize(R.dimen.lb_action_padding_horizontal);
+ final int padding =
+ vh.view
+ .getResources()
+ .getDimensionPixelSize(R.dimen.lb_action_padding_horizontal);
vh.view.setPaddingRelative(padding, 0, padding, 0);
}
vh.mButton.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null);
@@ -131,4 +139,4 @@ class ActionPresenterSelector extends PresenterSelector {
vh.mAction = null;
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java
index bf18ddc0..7e7e1f75 100644
--- a/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java
@@ -21,9 +21,8 @@ import android.content.res.Resources;
import android.support.v17.leanback.widget.Action;
import android.support.v17.leanback.widget.OnActionClickedListener;
import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.dialog.HalfSizedDialogFragment;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrManager;
@@ -31,9 +30,7 @@ import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.ui.DvrStopRecordingFragment;
import com.android.tv.dvr.ui.DvrUiHelper;
-/**
- * {@link RecordingDetailsFragment} for current recording in DVR.
- */
+/** {@link RecordingDetailsFragment} for current recording in DVR. */
public class CurrentRecordingDetailsFragment extends RecordingDetailsFragment {
private static final int ACTION_STOP_RECORDING = 1;
@@ -41,7 +38,7 @@ public class CurrentRecordingDetailsFragment extends RecordingDetailsFragment {
private final DvrDataManager.ScheduledRecordingListener mScheduledRecordingListener =
new DvrDataManager.ScheduledRecordingListener() {
@Override
- public void onScheduledRecordingAdded(ScheduledRecording... schedules) { }
+ public void onScheduledRecordingAdded(ScheduledRecording... schedules) {}
@Override
public void onScheduledRecordingRemoved(ScheduledRecording... schedules) {
@@ -58,7 +55,7 @@ public class CurrentRecordingDetailsFragment extends RecordingDetailsFragment {
for (ScheduledRecording schedule : schedules) {
if (schedule.getId() == getRecording().getId()
&& schedule.getState()
- != ScheduledRecording.STATE_RECORDING_IN_PROGRESS) {
+ != ScheduledRecording.STATE_RECORDING_IN_PROGRESS) {
getActivity().finish();
return;
}
@@ -69,7 +66,7 @@ public class CurrentRecordingDetailsFragment extends RecordingDetailsFragment {
@Override
public void onAttach(Context context) {
super.onAttach(context);
- mDvrDataManger = TvApplication.getSingletons(context).getDvrDataManager();
+ mDvrDataManger = TvSingletons.getSingletons(context).getDvrDataManager();
mDvrDataManger.addScheduledRecordingListener(mScheduledRecordingListener);
}
@@ -78,9 +75,13 @@ public class CurrentRecordingDetailsFragment extends RecordingDetailsFragment {
SparseArrayObjectAdapter adapter =
new SparseArrayObjectAdapter(new ActionPresenterSelector());
Resources res = getResources();
- adapter.set(ACTION_STOP_RECORDING, new Action(ACTION_STOP_RECORDING,
- res.getString(R.string.dvr_detail_stop_recording), null,
- res.getDrawable(R.drawable.lb_ic_stop)));
+ adapter.set(
+ ACTION_STOP_RECORDING,
+ new Action(
+ ACTION_STOP_RECORDING,
+ res.getString(R.string.dvr_detail_stop_recording),
+ null,
+ res.getDrawable(R.drawable.lb_ic_stop)));
return adapter;
}
@@ -90,7 +91,8 @@ public class CurrentRecordingDetailsFragment extends RecordingDetailsFragment {
@Override
public void onActionClicked(Action action) {
if (action.getId() == ACTION_STOP_RECORDING) {
- DvrUiHelper.showStopRecordingDialog(getActivity(),
+ DvrUiHelper.showStopRecordingDialog(
+ getActivity(),
getRecording().getChannelId(),
DvrStopRecordingFragment.REASON_USER_STOP,
new HalfSizedDialogFragment.OnActionClickListener() {
@@ -98,7 +100,7 @@ public class CurrentRecordingDetailsFragment extends RecordingDetailsFragment {
public void onActionClick(long actionId) {
if (actionId == DvrStopRecordingFragment.ACTION_STOP) {
DvrManager dvrManager =
- TvApplication.getSingletons(getContext())
+ TvSingletons.getSingletons(getContext())
.getDvrManager();
dvrManager.stopRecording(getRecording());
getActivity().finish();
diff --git a/src/com/android/tv/dvr/ui/browse/DetailsContent.java b/src/com/android/tv/dvr/ui/browse/DetailsContent.java
index c1fa05d7..cba6293b 100644
--- a/src/com/android/tv/dvr/ui/browse/DetailsContent.java
+++ b/src/com/android/tv/dvr/ui/browse/DetailsContent.java
@@ -20,18 +20,15 @@ import android.content.Context;
import android.media.tv.TvContract;
import android.support.annotation.Nullable;
import android.text.TextUtils;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
-import com.android.tv.data.Channel;
+import com.android.tv.TvSingletons;
+import com.android.tv.data.api.Channel;
import com.android.tv.dvr.data.RecordedProgram;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.dvr.ui.DvrUiHelper;
-/**
- * A class for details content.
- */
+/** A class for details content. */
class DetailsContent {
/** Constant for invalid time. */
public static final long INVALID_TIME = -1;
@@ -44,8 +41,8 @@ class DetailsContent {
private String mBackgroundImageUri;
private boolean mUsingChannelLogo;
- static DetailsContent createFromRecordedProgram(Context context,
- RecordedProgram recordedProgram) {
+ static DetailsContent createFromRecordedProgram(
+ Context context, RecordedProgram recordedProgram) {
return new DetailsContent.Builder()
.setChannelId(recordedProgram.getChannelId())
.setProgramTitle(recordedProgram.getTitle())
@@ -53,32 +50,72 @@ class DetailsContent {
.setEpisodeNumber(recordedProgram.getEpisodeNumber())
.setStartTimeUtcMillis(recordedProgram.getStartTimeUtcMillis())
.setEndTimeUtcMillis(recordedProgram.getEndTimeUtcMillis())
- .setDescription(TextUtils.isEmpty(recordedProgram.getLongDescription())
- ? recordedProgram.getDescription() : recordedProgram.getLongDescription())
+ .setDescription(
+ TextUtils.isEmpty(recordedProgram.getLongDescription())
+ ? recordedProgram.getDescription()
+ : recordedProgram.getLongDescription())
.setPosterArtUri(recordedProgram.getPosterArtUri())
.setThumbnailUri(recordedProgram.getThumbnailUri())
.build(context);
}
- static DetailsContent createFromSeriesRecording(Context context,
- SeriesRecording seriesRecording) {
+ static DetailsContent createFromSeriesRecording(
+ Context context, SeriesRecording seriesRecording) {
return new DetailsContent.Builder()
.setChannelId(seriesRecording.getChannelId())
.setTitle(seriesRecording.getTitle())
- .setDescription(TextUtils.isEmpty(seriesRecording.getLongDescription())
- ? seriesRecording.getDescription() : seriesRecording.getLongDescription())
+ .setDescription(
+ TextUtils.isEmpty(seriesRecording.getLongDescription())
+ ? seriesRecording.getDescription()
+ : seriesRecording.getLongDescription())
.setPosterArtUri(seriesRecording.getPosterUri())
.setThumbnailUri(seriesRecording.getPhotoUri())
.build(context);
}
- static DetailsContent createFromScheduledRecording(Context context,
- ScheduledRecording scheduledRecording) {
- Channel channel = TvApplication.getSingletons(context).getChannelDataManager()
- .getChannel(scheduledRecording.getChannelId());
- String description = !TextUtils.isEmpty(scheduledRecording.getProgramDescription()) ?
- scheduledRecording.getProgramDescription()
- : scheduledRecording.getProgramLongDescription();
+ static DetailsContent createFromScheduledRecording(
+ Context context, ScheduledRecording scheduledRecording) {
+ Channel channel =
+ TvSingletons.getSingletons(context)
+ .getChannelDataManager()
+ .getChannel(scheduledRecording.getChannelId());
+ String description =
+ !TextUtils.isEmpty(scheduledRecording.getProgramDescription())
+ ? scheduledRecording.getProgramDescription()
+ : scheduledRecording.getProgramLongDescription();
+ if (TextUtils.isEmpty(description)) {
+ description = channel != null ? channel.getDescription() : null;
+ }
+ return new DetailsContent.Builder()
+ .setChannelId(scheduledRecording.getChannelId())
+ .setProgramTitle(scheduledRecording.getProgramTitle())
+ .setSeasonNumber(scheduledRecording.getSeasonNumber())
+ .setEpisodeNumber(scheduledRecording.getEpisodeNumber())
+ .setStartTimeUtcMillis(scheduledRecording.getStartTimeMs())
+ .setEndTimeUtcMillis(scheduledRecording.getEndTimeMs())
+ .setDescription(description)
+ .setPosterArtUri(scheduledRecording.getProgramPosterArtUri())
+ .setThumbnailUri(scheduledRecording.getProgramThumbnailUri())
+ .build(context);
+ }
+
+ static DetailsContent createFromFailedScheduledRecording(
+ Context context, ScheduledRecording scheduledRecording, String errMsg) {
+ Channel channel =
+ TvSingletons.getSingletons(context)
+ .getChannelDataManager()
+ .getChannel(scheduledRecording.getChannelId());
+ String description;
+ if (scheduledRecording.getState() == ScheduledRecording.STATE_RECORDING_FAILED
+ && errMsg != null) {
+ description = errMsg
+ + " (Error code: " + scheduledRecording.getFailedReason() + ")";
+ } else {
+ description =
+ !TextUtils.isEmpty(scheduledRecording.getProgramDescription())
+ ? scheduledRecording.getProgramDescription()
+ : scheduledRecording.getProgramLongDescription();
+ }
if (TextUtils.isEmpty(description)) {
description = channel != null ? channel.getDescription() : null;
}
@@ -95,60 +132,44 @@ class DetailsContent {
.build(context);
}
- private DetailsContent() { }
+ private DetailsContent() {}
- /**
- * Returns title.
- */
+ /** Returns title. */
public CharSequence getTitle() {
return mTitle;
}
- /**
- * Returns start time.
- */
+ /** Returns start time. */
public long getStartTimeUtcMillis() {
return mStartTimeUtcMillis;
}
- /**
- * Returns end time.
- */
+ /** Returns end time. */
public long getEndTimeUtcMillis() {
return mEndTimeUtcMillis;
}
- /**
- * Returns description.
- */
+ /** Returns description. */
public String getDescription() {
return mDescription;
}
- /**
- * Returns Logo image URI as a String.
- */
+ /** Returns Logo image URI as a String. */
public String getLogoImageUri() {
return mLogoImageUri;
}
- /**
- * Returns background image URI as a String.
- */
+ /** Returns background image URI as a String. */
public String getBackgroundImageUri() {
return mBackgroundImageUri;
}
- /**
- * Returns if image URIs are from its channels' logo.
- */
+ /** Returns if image URIs are from its channels' logo. */
public boolean isUsingChannelLogo() {
return mUsingChannelLogo;
}
- /**
- * Copies other details content.
- */
+ /** Copies other details content. */
public void copyFrom(DetailsContent other) {
if (this == other) {
return;
@@ -162,9 +183,7 @@ class DetailsContent {
mUsingChannelLogo = other.mUsingChannelLogo;
}
- /**
- * A class for building details content.
- */
+ /** A class for building details content. */
public static final class Builder {
private final DetailsContent mDetailsContent;
@@ -181,49 +200,37 @@ class DetailsContent {
mDetailsContent.mEndTimeUtcMillis = INVALID_TIME;
}
- /**
- * Sets title.
- */
+ /** Sets title. */
public Builder setTitle(CharSequence title) {
mDetailsContent.mTitle = title;
return this;
}
- /**
- * Sets start time.
- */
+ /** Sets start time. */
public Builder setStartTimeUtcMillis(long startTimeUtcMillis) {
mDetailsContent.mStartTimeUtcMillis = startTimeUtcMillis;
return this;
}
- /**
- * Sets end time.
- */
+ /** Sets end time. */
public Builder setEndTimeUtcMillis(long endTimeUtcMillis) {
mDetailsContent.mEndTimeUtcMillis = endTimeUtcMillis;
return this;
}
- /**
- * Sets description.
- */
+ /** Sets description. */
public Builder setDescription(String description) {
mDetailsContent.mDescription = description;
return this;
}
- /**
- * Sets logo image URI as a String.
- */
+ /** Sets logo image URI as a String. */
public Builder setLogoImageUri(String logoImageUri) {
mDetailsContent.mLogoImageUri = logoImageUri;
return this;
}
- /**
- * Sets background image URI as a String.
- */
+ /** Sets background image URI as a String. */
public Builder setBackgroundImageUri(String backgroundImageUri) {
mDetailsContent.mBackgroundImageUri = backgroundImageUri;
return this;
@@ -260,12 +267,18 @@ class DetailsContent {
}
private void createStyledTitle(Context context, Channel channel) {
- CharSequence title = DvrUiHelper.getStyledTitleWithEpisodeNumber(context,
- mProgramTitle, mSeasonNumber, mEpisodeNumber,
- R.style.text_appearance_card_view_episode_number);
+ CharSequence title =
+ DvrUiHelper.getStyledTitleWithEpisodeNumber(
+ context,
+ mProgramTitle,
+ mSeasonNumber,
+ mEpisodeNumber,
+ R.style.text_appearance_card_view_episode_number);
if (TextUtils.isEmpty(title)) {
- mDetailsContent.mTitle = channel != null ? channel.getDisplayName()
- : context.getResources().getString(R.string.no_program_information);
+ mDetailsContent.mTitle =
+ channel != null
+ ? channel.getDisplayName()
+ : context.getResources().getString(R.string.no_program_information);
} else {
mDetailsContent.mTitle = title;
}
@@ -288,20 +301,19 @@ class DetailsContent {
mDetailsContent.mBackgroundImageUri = mThumbnailUri;
}
if (TextUtils.isEmpty(mDetailsContent.mLogoImageUri) && channel != null) {
- String channelLogoUri = TvContract.buildChannelLogoUri(channel.getId())
- .toString();
+ String channelLogoUri = TvContract.buildChannelLogoUri(channel.getId()).toString();
mDetailsContent.mLogoImageUri = channelLogoUri;
mDetailsContent.mBackgroundImageUri = channelLogoUri;
mDetailsContent.mUsingChannelLogo = true;
}
}
- /**
- * Builds details content.
- */
+ /** Builds details content. */
public DetailsContent build(Context context) {
- Channel channel = TvApplication.getSingletons(context).getChannelDataManager()
- .getChannel(mChannelId);
+ Channel channel =
+ TvSingletons.getSingletons(context)
+ .getChannelDataManager()
+ .getChannel(mChannelId);
if (mDetailsContent.mTitle == null) {
createStyledTitle(context, channel);
}
@@ -314,4 +326,4 @@ class DetailsContent {
return detailsContent;
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java b/src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java
index 09b57887..aec8c411 100644
--- a/src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java
+++ b/src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java
@@ -16,11 +16,11 @@
package com.android.tv.dvr.ui.browse;
-import android.app.Activity;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
+import android.app.Activity;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
@@ -33,24 +33,20 @@ import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityManager;
import android.widget.LinearLayout;
import android.widget.TextView;
-
import com.android.tv.R;
import com.android.tv.ui.ViewUtils;
import com.android.tv.util.Utils;
/**
- * An {@link Presenter} for rendering a detailed description of an DVR item.
- * Typically this Presenter will be used in a
- * {@link android.support.v17.leanback.widget.DetailsOverviewRowPresenter}.
- * Most codes of this class is originated from
- * {@link android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter}.
- * The latter class are re-used to provide a customized version of
- * {@link android.support.v17.leanback.widget.DetailsOverviewRow}.
+ * An {@link Presenter} for rendering a detailed description of an DVR item. Typically this
+ * Presenter will be used in a {@link
+ * android.support.v17.leanback.widget.DetailsOverviewRowPresenter}. Most codes of this class is
+ * originated from {@link android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter}.
+ * The latter class are re-used to provide a customized version of {@link
+ * android.support.v17.leanback.widget.DetailsOverviewRow}.
*/
class DetailsContentPresenter extends Presenter {
- /**
- * The ViewHolder for the {@link DetailsContentPresenter}.
- */
+ /** The ViewHolder for the {@link DetailsContentPresenter}. */
public static class ViewHolder extends Presenter.ViewHolder {
final TextView mTitle;
final TextView mSubtitle;
@@ -85,31 +81,40 @@ class DetailsContentPresenter extends Presenter {
return false;
}
final int bodyLines = mBody.getLineCount();
- int maxLines = mFullTextMode ? bodyLines :
- (mTitle.getLineCount() > 1 ? mBodyMinLines : mBodyMaxLines);
+ int maxLines =
+ mFullTextMode
+ ? bodyLines
+ : (mTitle.getLineCount() > 1
+ ? mBodyMinLines
+ : mBodyMaxLines);
if (bodyLines > maxLines) {
mReadMoreView.setVisibility(View.VISIBLE);
mDescriptionContainer.setFocusable(true);
mDescriptionContainer.setClickable(true);
- mDescriptionContainer.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- mFullTextMode = true;
- mReadMoreView.setVisibility(View.GONE);
- mDescriptionContainer.setFocusable((
- (AccessibilityManager) view.getContext()
- .getSystemService(
- Context.ACCESSIBILITY_SERVICE))
- .isEnabled());
- mDescriptionContainer.setClickable(false);
- mDescriptionContainer.setOnClickListener(null);
- int oldMaxLines = mBody.getMaxLines();
- mBody.setMaxLines(bodyLines);
- // Minus 1 from line difference to eliminate the space
- // originally occupied by "READ MORE"
- showFullText((bodyLines - oldMaxLines - 1) * mBodyLineSpacing);
- }
- });
+ mDescriptionContainer.setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ mFullTextMode = true;
+ mReadMoreView.setVisibility(View.GONE);
+ mDescriptionContainer.setFocusable(
+ ((AccessibilityManager)
+ view.getContext()
+ .getSystemService(
+ Context
+ .ACCESSIBILITY_SERVICE))
+ .isEnabled());
+ mDescriptionContainer.setClickable(false);
+ mDescriptionContainer.setOnClickListener(null);
+ int oldMaxLines = mBody.getMaxLines();
+ mBody.setMaxLines(bodyLines);
+ // Minus 1 from line difference to eliminate the space
+ // originally occupied by "READ MORE"
+ showFullText(
+ (bodyLines - oldMaxLines - 1)
+ * mBodyLineSpacing);
+ }
+ });
}
if (mReadMoreView.getVisibility() == View.VISIBLE
&& mSubtitle.getVisibility() == View.VISIBLE) {
@@ -151,30 +156,42 @@ class DetailsContentPresenter extends Presenter {
// We have to explicitly set focusable to true here for accessibility, since we might
// set the view's focusable state when we need to show "READ MORE", which would remove
// the default focusable state for accessibility.
- mDescriptionContainer.setFocusable(((AccessibilityManager) view.getContext()
- .getSystemService(Context.ACCESSIBILITY_SERVICE)).isEnabled());
+ mDescriptionContainer.setFocusable(
+ ((AccessibilityManager)
+ view.getContext()
+ .getSystemService(Context.ACCESSIBILITY_SERVICE))
+ .isEnabled());
mReadMoreView = (TextView) view.findViewById(R.id.dvr_details_description_read_more);
FontMetricsInt titleFontMetricsInt = getFontMetricsInt(mTitle);
- final int titleAscent = view.getResources().getDimensionPixelSize(
- R.dimen.lb_details_description_title_baseline);
+ final int titleAscent =
+ view.getResources()
+ .getDimensionPixelSize(R.dimen.lb_details_description_title_baseline);
// Ascent is negative
mTitleMargin = titleAscent + titleFontMetricsInt.ascent;
- mUnderTitleBaselineMargin = view.getResources().getDimensionPixelSize(
- R.dimen.lb_details_description_under_title_baseline_margin);
- mUnderSubtitleBaselineMargin = view.getResources().getDimensionPixelSize(
- R.dimen.dvr_details_description_under_subtitle_baseline_margin);
+ mUnderTitleBaselineMargin =
+ view.getResources()
+ .getDimensionPixelSize(
+ R.dimen.lb_details_description_under_title_baseline_margin);
+ mUnderSubtitleBaselineMargin =
+ view.getResources()
+ .getDimensionPixelSize(
+ R.dimen.dvr_details_description_under_subtitle_baseline_margin);
- mTitleLineSpacing = view.getResources().getDimensionPixelSize(
- R.dimen.lb_details_description_title_line_spacing);
- mBodyLineSpacing = view.getResources().getDimensionPixelSize(
- R.dimen.lb_details_description_body_line_spacing);
+ mTitleLineSpacing =
+ view.getResources()
+ .getDimensionPixelSize(
+ R.dimen.lb_details_description_title_line_spacing);
+ mBodyLineSpacing =
+ view.getResources()
+ .getDimensionPixelSize(
+ R.dimen.lb_details_description_body_line_spacing);
- mBodyMaxLines = view.getResources().getInteger(
- R.integer.lb_details_description_body_max_lines);
- mBodyMinLines = view.getResources().getInteger(
- R.integer.lb_details_description_body_min_lines);
+ mBodyMaxLines =
+ view.getResources().getInteger(R.integer.lb_details_description_body_max_lines);
+ mBodyMinLines =
+ view.getResources().getInteger(R.integer.lb_details_description_body_min_lines);
mTitleMaxLines = mTitle.getMaxLines();
mTitleFontMetricsInt = getFontMetricsInt(mTitle);
@@ -218,12 +235,14 @@ class DetailsContentPresenter extends Presenter {
private void showFullText(int heightDiff) {
final ViewGroup detailsFrame = (ViewGroup) mActivity.findViewById(R.id.details_frame);
int nowHeight = ViewUtils.getLayoutHeight(detailsFrame);
- Animator expandAnimator = ViewUtils.createHeightAnimator(
- detailsFrame, nowHeight, nowHeight + heightDiff);
+ Animator expandAnimator =
+ ViewUtils.createHeightAnimator(detailsFrame, nowHeight, nowHeight + heightDiff);
expandAnimator.setDuration(mFullTextAnimationDuration);
- Animator shiftAnimator = ObjectAnimator.ofPropertyValuesHolder(detailsFrame,
- PropertyValuesHolder.ofFloat(View.TRANSLATION_Y,
- 0f, -(heightDiff / 2)));
+ Animator shiftAnimator =
+ ObjectAnimator.ofPropertyValuesHolder(
+ detailsFrame,
+ PropertyValuesHolder.ofFloat(
+ View.TRANSLATION_Y, 0f, -(heightDiff / 2)));
shiftAnimator.setDuration(mFullTextAnimationDuration);
AnimatorSet fullTextAnimator = new AnimatorSet();
fullTextAnimator.playTogether(expandAnimator, shiftAnimator);
@@ -237,14 +256,17 @@ class DetailsContentPresenter extends Presenter {
public DetailsContentPresenter(Activity activity) {
super();
mActivity = activity;
- mFullTextAnimationDuration = mActivity.getResources()
- .getInteger(R.integer.dvr_details_full_text_animation_duration);
+ mFullTextAnimationDuration =
+ mActivity
+ .getResources()
+ .getInteger(R.integer.dvr_details_full_text_animation_duration);
}
@Override
public final ViewHolder onCreateViewHolder(ViewGroup parent) {
- View v = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.dvr_details_description, parent, false);
+ View v =
+ LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.dvr_details_description, parent, false);
return new ViewHolder(v);
}
@@ -263,8 +285,11 @@ class DetailsContentPresenter extends Presenter {
} else {
vh.mTitle.setText(detailsContent.getTitle());
vh.mTitle.setVisibility(View.VISIBLE);
- vh.mTitle.setLineSpacing(vh.mTitleLineSpacing - vh.mTitle.getLineHeight()
- + vh.mTitle.getLineSpacingExtra(), vh.mTitle.getLineSpacingMultiplier());
+ vh.mTitle.setLineSpacing(
+ vh.mTitleLineSpacing
+ - vh.mTitle.getLineHeight()
+ + vh.mTitle.getLineSpacingExtra(),
+ vh.mTitle.getLineSpacingMultiplier());
vh.mTitle.setMaxLines(vh.mTitleMaxLines);
}
setTopMargin(vh.mTitle, vh.mTitleMargin);
@@ -272,13 +297,19 @@ class DetailsContentPresenter extends Presenter {
boolean hasSubtitle = true;
if (detailsContent.getStartTimeUtcMillis() != DetailsContent.INVALID_TIME
&& detailsContent.getEndTimeUtcMillis() != DetailsContent.INVALID_TIME) {
- vh.mSubtitle.setText(Utils.getDurationString(viewHolder.view.getContext(),
- detailsContent.getStartTimeUtcMillis(),
- detailsContent.getEndTimeUtcMillis(), false));
+ vh.mSubtitle.setText(
+ Utils.getDurationString(
+ viewHolder.view.getContext(),
+ detailsContent.getStartTimeUtcMillis(),
+ detailsContent.getEndTimeUtcMillis(),
+ false));
vh.mSubtitle.setVisibility(View.VISIBLE);
if (hasTitle) {
- setTopMargin(vh.mSubtitle, vh.mUnderTitleBaselineMargin
- + vh.mSubtitleFontMetricsInt.ascent - vh.mTitleFontMetricsInt.descent);
+ setTopMargin(
+ vh.mSubtitle,
+ vh.mUnderTitleBaselineMargin
+ + vh.mSubtitleFontMetricsInt.ascent
+ - vh.mTitleFontMetricsInt.descent);
} else {
setTopMargin(vh.mSubtitle, 0);
}
@@ -292,16 +323,23 @@ class DetailsContentPresenter extends Presenter {
} else {
vh.mBody.setText(detailsContent.getDescription());
vh.mBody.setVisibility(View.VISIBLE);
- vh.mBody.setLineSpacing(vh.mBodyLineSpacing - vh.mBody.getLineHeight()
- + vh.mBody.getLineSpacingExtra(), vh.mBody.getLineSpacingMultiplier());
+ vh.mBody.setLineSpacing(
+ vh.mBodyLineSpacing - vh.mBody.getLineHeight() + vh.mBody.getLineSpacingExtra(),
+ vh.mBody.getLineSpacingMultiplier());
if (hasSubtitle) {
- setTopMargin(vh.mDescriptionContainer, vh.mUnderSubtitleBaselineMargin
- + vh.mBodyFontMetricsInt.ascent - vh.mSubtitleFontMetricsInt.descent
- - vh.mBody.getPaddingTop());
+ setTopMargin(
+ vh.mDescriptionContainer,
+ vh.mUnderSubtitleBaselineMargin
+ + vh.mBodyFontMetricsInt.ascent
+ - vh.mSubtitleFontMetricsInt.descent
+ - vh.mBody.getPaddingTop());
} else if (hasTitle) {
- setTopMargin(vh.mDescriptionContainer, vh.mUnderTitleBaselineMargin
- + vh.mBodyFontMetricsInt.ascent - vh.mTitleFontMetricsInt.descent
- - vh.mBody.getPaddingTop());
+ setTopMargin(
+ vh.mDescriptionContainer,
+ vh.mUnderTitleBaselineMargin
+ + vh.mBodyFontMetricsInt.ascent
+ - vh.mTitleFontMetricsInt.descent
+ - vh.mBody.getPaddingTop());
} else {
setTopMargin(vh.mDescriptionContainer, 0);
}
@@ -309,11 +347,11 @@ class DetailsContentPresenter extends Presenter {
}
@Override
- public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) { }
+ public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {}
private void setTopMargin(View view, int topMargin) {
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
lp.topMargin = topMargin;
view.setLayoutParams(lp);
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java b/src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java
index 82fe9ce3..849360b8 100644
--- a/src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java
+++ b/src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java
@@ -23,9 +23,7 @@ import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.support.v17.leanback.app.BackgroundManager;
-/**
- * The Background Helper.
- */
+/** The Background Helper. */
class DetailsViewBackgroundHelper {
// Background delay serves to avoid kicking off expensive bitmap loading
// in case multiple backgrounds are set in quick succession.
@@ -59,11 +57,10 @@ class DetailsViewBackgroundHelper {
public DetailsViewBackgroundHelper(Activity activity) {
mBackgroundManager = BackgroundManager.getInstance(activity);
mBackgroundManager.attach(activity.getWindow());
+ mBackgroundManager.setAutoReleaseOnStop(false);
}
- /**
- * Sets the given image to background.
- */
+ /** Sets the given image to background. */
public void setBackground(Drawable background) {
if (mRunnable != null) {
mHandler.removeCallbacks(mRunnable);
@@ -72,18 +69,14 @@ class DetailsViewBackgroundHelper {
mHandler.postDelayed(mRunnable, SET_BACKGROUND_DELAY_MS);
}
- /**
- * Sets the background color.
- */
+ /** Sets the background color. */
public void setBackgroundColor(int color) {
if (mBackgroundManager.isAttached()) {
mBackgroundManager.setColor(color);
}
}
- /**
- * Sets the background scrim.
- */
+ /** Sets the background scrim. */
public void setScrim(int color) {
if (mBackgroundManager.isAttached()) {
mBackgroundManager.setDimLayer(new ColorDrawable(color));
diff --git a/src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java b/src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java
index 07eec107..6cc1c7a1 100644
--- a/src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java
@@ -20,19 +20,16 @@ import android.app.Activity;
import android.content.Intent;
import android.media.tv.TvInputManager;
import android.os.Bundle;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.Starter;
-/**
- * {@link android.app.Activity} for DVR UI.
- */
+/** {@link android.app.Activity} for DVR UI. */
public class DvrBrowseActivity extends Activity {
private DvrBrowseFragment mFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
- TvApplication.setCurrentRunningProcess(this, true);
+ Starter.start(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.dvr_main);
mFragment = (DvrBrowseFragment) getFragmentManager().findFragmentById(R.id.dvr_frame);
@@ -49,4 +46,4 @@ public class DvrBrowseActivity extends Activity {
mFragment.showScheduledRow();
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java b/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java
index cb3a5745..40b3a1f0 100644
--- a/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java
@@ -16,7 +16,9 @@
package com.android.tv.dvr.ui.browse;
+import android.annotation.TargetApi;
import android.content.Context;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v17.leanback.app.BrowseFragment;
@@ -30,9 +32,9 @@ import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalFocusChangeListener;
-import com.android.tv.ApplicationSingletons;
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvFeatures;
+import com.android.tv.TvSingletons;
import com.android.tv.data.GenreItems;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrDataManager.OnDvrScheduleLoadFinishedListener;
@@ -52,12 +54,15 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
-/**
- * {@link BrowseFragment} for DVR functions.
- */
-public class DvrBrowseFragment extends BrowseFragment implements
- RecordedProgramListener, ScheduledRecordingListener, SeriesRecordingListener,
- OnDvrScheduleLoadFinishedListener, OnRecordedProgramLoadFinishedListener {
+/** {@link BrowseFragment} for DVR functions. */
+@TargetApi(Build.VERSION_CODES.N)
+@SuppressWarnings("AndroidApiChecker") // TODO(b/32513850) remove when error prone is updated
+public class DvrBrowseFragment extends BrowseFragment
+ implements RecordedProgramListener,
+ ScheduledRecordingListener,
+ SeriesRecordingListener,
+ OnDvrScheduleLoadFinishedListener,
+ OnRecordedProgramLoadFinishedListener {
private static final String TAG = "DvrBrowseFragment";
private static final boolean DEBUG = false;
@@ -67,7 +72,7 @@ public class DvrBrowseFragment extends BrowseFragment implements
private boolean mShouldShowScheduleRow;
private boolean mEntranceTransitionEnded;
- private RecordedProgramAdapter mRecentAdapter;
+ private RecentRowAdapter mRecentAdapter;
private ScheduleAdapter mScheduleAdapter;
private SeriesAdapter mSeriesAdapter;
private RecordedProgramAdapter[] mGenreAdapters =
@@ -98,82 +103,143 @@ public class DvrBrowseFragment extends BrowseFragment implements
}
};
- private final Comparator<Object> RECORDED_PROGRAM_COMPARATOR = new Comparator<Object>() {
- @Override
- public int compare(Object lhs, Object rhs) {
- if (lhs instanceof SeriesRecording) {
- lhs = mSeriesId2LatestProgram.get(((SeriesRecording) lhs).getSeriesId());
- }
- if (rhs instanceof SeriesRecording) {
- rhs = mSeriesId2LatestProgram.get(((SeriesRecording) rhs).getSeriesId());
- }
- if (lhs instanceof RecordedProgram) {
- if (rhs instanceof RecordedProgram) {
- return RecordedProgram.START_TIME_THEN_ID_COMPARATOR.reversed()
- .compare((RecordedProgram) lhs, (RecordedProgram) rhs);
- } else {
- return -1;
+ private final Comparator<Object> RECORDED_PROGRAM_COMPARATOR =
+ new Comparator<Object>() {
+ @Override
+ public int compare(Object lhs, Object rhs) {
+ if (lhs instanceof SeriesRecording) {
+ lhs = mSeriesId2LatestProgram.get(((SeriesRecording) lhs).getSeriesId());
+ }
+ if (rhs instanceof SeriesRecording) {
+ rhs = mSeriesId2LatestProgram.get(((SeriesRecording) rhs).getSeriesId());
+ }
+ if (lhs instanceof RecordedProgram) {
+ if (rhs instanceof RecordedProgram) {
+ return RecordedProgram.START_TIME_THEN_ID_COMPARATOR
+ .reversed()
+ .compare((RecordedProgram) lhs, (RecordedProgram) rhs);
+ } else {
+ return -1;
+ }
+ } else if (rhs instanceof RecordedProgram) {
+ return 1;
+ } else {
+ return 0;
+ }
}
- } else if (rhs instanceof RecordedProgram) {
- return 1;
- } else {
- return 0;
- }
- }
- };
+ };
- private static final Comparator<Object> SCHEDULE_COMPARATOR = new Comparator<Object>() {
- @Override
- public int compare(Object lhs, Object rhs) {
- if (lhs instanceof ScheduledRecording) {
- if (rhs instanceof ScheduledRecording) {
- return ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR
- .compare((ScheduledRecording) lhs, (ScheduledRecording) rhs);
- } else {
- return -1;
+ private static final Comparator<Object> SCHEDULE_COMPARATOR =
+ new Comparator<Object>() {
+ @Override
+ public int compare(Object lhs, Object rhs) {
+ if (lhs instanceof ScheduledRecording) {
+ if (rhs instanceof ScheduledRecording) {
+ return ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR
+ .compare((ScheduledRecording) lhs, (ScheduledRecording) rhs);
+ } else {
+ return -1;
+ }
+ } else if (rhs instanceof ScheduledRecording) {
+ return 1;
+ } else {
+ return 0;
+ }
}
- } else if (rhs instanceof ScheduledRecording) {
- return 1;
- } else {
- return 0;
- }
- }
- };
+ };
+
+ static final Comparator<Object> RECENT_ROW_COMPARATOR =
+ new Comparator<Object>() {
+ @Override
+ public int compare(Object lhs, Object rhs) {
+ if (lhs instanceof ScheduledRecording) {
+ if (rhs instanceof ScheduledRecording) {
+ return ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR
+ .reversed()
+ .compare((ScheduledRecording) lhs, (ScheduledRecording) rhs);
+ } else if (rhs instanceof RecordedProgram) {
+ ScheduledRecording scheduled = (ScheduledRecording) lhs;
+ RecordedProgram recorded = (RecordedProgram) rhs;
+ int compare =
+ Long.compare(
+ recorded.getStartTimeUtcMillis(),
+ scheduled.getStartTimeMs());
+ // recorded program first when the start times are the same
+ return compare == 0 ? 1 : compare;
+ } else {
+ return -1;
+ }
+ } else if (lhs instanceof RecordedProgram) {
+ if (rhs instanceof RecordedProgram) {
+ return RecordedProgram.START_TIME_THEN_ID_COMPARATOR
+ .reversed()
+ .compare((RecordedProgram) lhs, (RecordedProgram) rhs);
+ } else if (rhs instanceof ScheduledRecording) {
+ RecordedProgram recorded = (RecordedProgram) lhs;
+ ScheduledRecording scheduled = (ScheduledRecording) rhs;
+ int compare =
+ Long.compare(
+ scheduled.getStartTimeMs(),
+ recorded.getStartTimeUtcMillis());
+ // recorded program first when the start times are the same
+ return compare == 0 ? -1 : compare;
+ } else {
+ return -1;
+ }
+ } else {
+ return !(rhs instanceof RecordedProgram)
+ && !(rhs instanceof ScheduledRecording)
+ ? 0 : 1;
+ }
+ }
+ };
private final DvrScheduleManager.OnConflictStateChangeListener mOnConflictStateChangeListener =
new DvrScheduleManager.OnConflictStateChangeListener() {
- @Override
- public void onConflictStateChange(boolean conflict, ScheduledRecording... schedules) {
- if (mScheduleAdapter != null) {
- for (ScheduledRecording schedule : schedules) {
- onScheduledRecordingConflictStatusChanged(schedule);
+ @Override
+ public void onConflictStateChange(
+ boolean conflict, ScheduledRecording... schedules) {
+ if (mScheduleAdapter != null) {
+ for (ScheduledRecording schedule : schedules) {
+ onScheduledRecordingConflictStatusChanged(schedule);
+ }
+ }
}
- }
- }
- };
+ };
- private final Runnable mUpdateRowsRunnable = new Runnable() {
- @Override
- public void run() {
- updateRows();
- }
- };
+ private final Runnable mUpdateRowsRunnable =
+ new Runnable() {
+ @Override
+ public void run() {
+ updateRows();
+ }
+ };
@Override
public void onCreate(Bundle savedInstanceState) {
if (DEBUG) Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
Context context = getContext();
- ApplicationSingletons singletons = TvApplication.getSingletons(context);
+ TvSingletons singletons = TvSingletons.getSingletons(context);
mDvrDataManager = singletons.getDvrDataManager();
mDvrScheudleManager = singletons.getDvrScheduleManager();
- mPresenterSelector = new ClassPresenterSelector()
- .addClassPresenter(ScheduledRecording.class,
- new ScheduledRecordingPresenter(context))
- .addClassPresenter(RecordedProgram.class, new RecordedProgramPresenter(context))
- .addClassPresenter(SeriesRecording.class, new SeriesRecordingPresenter(context))
- .addClassPresenter(FullScheduleCardHolder.class,
- new FullSchedulesCardPresenter(context));
+ mPresenterSelector =
+ new ClassPresenterSelector()
+ .addClassPresenter(
+ ScheduledRecording.class, new ScheduledRecordingPresenter(context))
+ .addClassPresenter(
+ RecordedProgram.class, new RecordedProgramPresenter(context))
+ .addClassPresenter(
+ SeriesRecording.class, new SeriesRecordingPresenter(context))
+ .addClassPresenter(
+ FullScheduleCardHolder.class,
+ new FullSchedulesCardPresenter(context));
+
+ if (TvFeatures.DVR_FAILED_LIST.isEnabled(context)) {
+ mPresenterSelector.addClassPresenter(
+ DvrHistoryCardHolder.class,
+ new DvrHistoryCardPresenter(context));
+ }
mGenreLabels = new ArrayList<>(Arrays.asList(GenreItems.getLabels(context)));
mGenreLabels.add(getString(R.string.dvr_main_others));
prepareUiElements();
@@ -195,7 +261,8 @@ public class DvrBrowseFragment extends BrowseFragment implements
@Override
public void onDestroyView() {
- getView().getViewTreeObserver()
+ getView()
+ .getViewTreeObserver()
.removeOnGlobalFocusChangeListener(mOnGlobalFocusChangeListener);
super.onDestroyView();
}
@@ -263,6 +330,8 @@ public class DvrBrowseFragment extends BrowseFragment implements
for (ScheduledRecording scheduleRecording : scheduledRecordings) {
if (needToShowScheduledRecording(scheduleRecording)) {
mScheduleAdapter.add(scheduleRecording);
+ } else if (scheduleRecording.getState() == ScheduledRecording.STATE_RECORDING_FAILED) {
+ mRecentAdapter.add(scheduleRecording);
}
}
}
@@ -361,30 +430,44 @@ public class DvrBrowseFragment extends BrowseFragment implements
private boolean startBrowseIfDvrInitialized() {
if (mDvrDataManager.isInitialized()) {
// Setup rows
- mRecentAdapter = new RecordedProgramAdapter(MAX_RECENT_ITEM_COUNT);
+ mRecentAdapter = new RecentRowAdapter(MAX_RECENT_ITEM_COUNT);
mScheduleAdapter = new ScheduleAdapter(MAX_SCHEDULED_ITEM_COUNT);
mSeriesAdapter = new SeriesAdapter();
for (int i = 0; i < mGenreAdapters.length; i++) {
mGenreAdapters[i] = new RecordedProgramAdapter();
}
// Schedule Recordings.
- List<ScheduledRecording> schedules = mDvrDataManager.getAllScheduledRecordings();
+ // only get not started or in progress recordings
+ List<ScheduledRecording> schedules = mDvrDataManager.getAvailableScheduledRecordings();
onScheduledRecordingAdded(ScheduledRecording.toArray(schedules));
mScheduleAdapter.addExtraItem(FullScheduleCardHolder.FULL_SCHEDULE_CARD_HOLDER);
// Recorded Programs.
for (RecordedProgram recordedProgram : mDvrDataManager.getRecordedPrograms()) {
handleRecordedProgramAdded(recordedProgram, false);
}
+ if (TvFeatures.DVR_FAILED_LIST.isEnabled(getContext())) {
+ // only get failed recordings
+ for (ScheduledRecording scheduledRecording
+ : mDvrDataManager.getFailedScheduledRecordings()) {
+ onScheduledRecordingAdded(scheduledRecording);
+ }
+ mRecentAdapter.addExtraItem(DvrHistoryCardHolder.DVR_HISTORY_CARD_HOLDER);
+ }
// Series Recordings. Series recordings should be added after recorded programs, because
- // we build series recordings' latest program information while adding recorded programs.
+ // we build series recordings' latest program information while adding recorded
+ // programs.
List<SeriesRecording> recordings = mDvrDataManager.getSeriesRecordings();
handleSeriesRecordingsAdded(recordings);
- mRecentRow = new ListRow(new HeaderItem(
- getString(R.string.dvr_main_recent)), mRecentAdapter);
- mScheduledRow = new ListRow(new HeaderItem(
- getString(R.string.dvr_main_scheduled)), mScheduleAdapter);
- mSeriesRow = new ListRow(new HeaderItem(
- getString(R.string.dvr_main_series)), mSeriesAdapter);
+ mRecentRow =
+ new ListRow(
+ new HeaderItem(getString(R.string.dvr_main_recent)), mRecentAdapter);
+ mScheduledRow =
+ new ListRow(
+ new HeaderItem(getString(R.string.dvr_main_scheduled)),
+ mScheduleAdapter);
+ mSeriesRow =
+ new ListRow(
+ new HeaderItem(getString(R.string.dvr_main_series)), mSeriesAdapter);
mRowsAdapter.add(mScheduledRow);
updateRows();
// Initialize listeners
@@ -398,16 +481,18 @@ public class DvrBrowseFragment extends BrowseFragment implements
return false;
}
- private void handleRecordedProgramAdded(RecordedProgram recordedProgram,
- boolean updateSeriesRecording) {
+ private void handleRecordedProgramAdded(
+ RecordedProgram recordedProgram, boolean updateSeriesRecording) {
mRecentAdapter.add(recordedProgram);
String seriesId = recordedProgram.getSeriesId();
SeriesRecording seriesRecording = null;
if (seriesId != null) {
seriesRecording = mDvrDataManager.getSeriesRecording(seriesId);
RecordedProgram latestProgram = mSeriesId2LatestProgram.get(seriesId);
- if (latestProgram == null || RecordedProgram.START_TIME_THEN_ID_COMPARATOR
- .compare(latestProgram, recordedProgram) < 0) {
+ if (latestProgram == null
+ || RecordedProgram.START_TIME_THEN_ID_COMPARATOR.compare(
+ latestProgram, recordedProgram)
+ < 0) {
mSeriesId2LatestProgram.put(seriesId, recordedProgram);
if (updateSeriesRecording && seriesRecording != null) {
onSeriesRecordingChanged(seriesRecording);
@@ -415,8 +500,8 @@ public class DvrBrowseFragment extends BrowseFragment implements
}
}
if (seriesRecording == null) {
- for (RecordedProgramAdapter adapter
- : getGenreAdapters(recordedProgram.getCanonicalGenres())) {
+ for (RecordedProgramAdapter adapter :
+ getGenreAdapters(recordedProgram.getCanonicalGenres())) {
adapter.add(recordedProgram);
}
}
@@ -436,8 +521,8 @@ public class DvrBrowseFragment extends BrowseFragment implements
}
}
}
- for (RecordedProgramAdapter adapter
- : getGenreAdapters(recordedProgram.getCanonicalGenres())) {
+ for (RecordedProgramAdapter adapter :
+ getGenreAdapters(recordedProgram.getCanonicalGenres())) {
adapter.remove(recordedProgram);
}
}
@@ -449,8 +534,10 @@ public class DvrBrowseFragment extends BrowseFragment implements
if (seriesId != null) {
seriesRecording = mDvrDataManager.getSeriesRecording(seriesId);
RecordedProgram latestProgram = mSeriesId2LatestProgram.get(seriesId);
- if (latestProgram == null || RecordedProgram.START_TIME_THEN_ID_COMPARATOR
- .compare(latestProgram, recordedProgram) <= 0) {
+ if (latestProgram == null
+ || RecordedProgram.START_TIME_THEN_ID_COMPARATOR.compare(
+ latestProgram, recordedProgram)
+ <= 0) {
mSeriesId2LatestProgram.put(seriesId, recordedProgram);
if (seriesRecording != null) {
onSeriesRecordingChanged(seriesRecording);
@@ -463,8 +550,8 @@ public class DvrBrowseFragment extends BrowseFragment implements
}
}
if (seriesRecording == null) {
- updateGenreAdapters(getGenreAdapters(
- recordedProgram.getCanonicalGenres()), recordedProgram);
+ updateGenreAdapters(
+ getGenreAdapters(recordedProgram.getCanonicalGenres()), recordedProgram);
} else {
updateGenreAdapters(new ArrayList<>(), recordedProgram);
}
@@ -474,8 +561,8 @@ public class DvrBrowseFragment extends BrowseFragment implements
for (SeriesRecording seriesRecording : seriesRecordings) {
mSeriesAdapter.add(seriesRecording);
if (mSeriesId2LatestProgram.get(seriesRecording.getSeriesId()) != null) {
- for (RecordedProgramAdapter adapter
- : getGenreAdapters(seriesRecording.getCanonicalGenreIds())) {
+ for (RecordedProgramAdapter adapter :
+ getGenreAdapters(seriesRecording.getCanonicalGenreIds())) {
adapter.add(seriesRecording);
}
}
@@ -485,8 +572,8 @@ public class DvrBrowseFragment extends BrowseFragment implements
private void handleSeriesRecordingsRemoved(List<SeriesRecording> seriesRecordings) {
for (SeriesRecording seriesRecording : seriesRecordings) {
mSeriesAdapter.remove(seriesRecording);
- for (RecordedProgramAdapter adapter
- : getGenreAdapters(seriesRecording.getCanonicalGenreIds())) {
+ for (RecordedProgramAdapter adapter :
+ getGenreAdapters(seriesRecording.getCanonicalGenreIds())) {
adapter.remove(seriesRecording);
}
}
@@ -496,8 +583,8 @@ public class DvrBrowseFragment extends BrowseFragment implements
for (SeriesRecording seriesRecording : seriesRecordings) {
mSeriesAdapter.change(seriesRecording);
if (mSeriesId2LatestProgram.get(seriesRecording.getSeriesId()) != null) {
- updateGenreAdapters(getGenreAdapters(
- seriesRecording.getCanonicalGenreIds()), seriesRecording);
+ updateGenreAdapters(
+ getGenreAdapters(seriesRecording.getCanonicalGenreIds()), seriesRecording);
} else {
// Remove series recording from all genre rows if it has no recorded program
updateGenreAdapters(new ArrayList<>(), seriesRecording);
@@ -512,7 +599,7 @@ public class DvrBrowseFragment extends BrowseFragment implements
} else {
for (String genre : genres) {
int genreId = GenreItems.getId(genre);
- if(genreId >= mGenreAdapters.length) {
+ if (genreId >= mGenreAdapters.length) {
Log.d(TAG, "Wrong Genre ID: " + genreId);
} else {
result.add(mGenreAdapters[genreId]);
@@ -528,7 +615,7 @@ public class DvrBrowseFragment extends BrowseFragment implements
result.add(mGenreAdapters[mGenreAdapters.length - 1]);
} else {
for (int genreId : genreIds) {
- if(genreId >= mGenreAdapters.length) {
+ if (genreId >= mGenreAdapters.length) {
Log.d(TAG, "Wrong Genre ID: " + genreId);
} else {
result.add(mGenreAdapters[genreId]);
@@ -554,8 +641,9 @@ public class DvrBrowseFragment extends BrowseFragment implements
}
private void updateRows() {
- int visibleRowsCount = 1; // Schedule's Row will never be empty
- if (mRecentAdapter.isEmpty()) {
+ int visibleRowsCount = 1; // Schedule's Row will never be empty
+ int recentRowMinSize = TvFeatures.DVR_FAILED_LIST.isEnabled(getContext()) ? 1 : 0;
+ if (mRecentAdapter.size() <= recentRowMinSize) {
mRowsAdapter.remove(mRecentRow);
} else {
if (mRowsAdapter.indexOf(mRecentRow) < 0) {
@@ -597,8 +685,9 @@ public class DvrBrowseFragment extends BrowseFragment implements
RecordedProgram latestProgram = null;
for (RecordedProgram program :
mDvrDataManager.getRecordedPrograms(seriesRecording.getId())) {
- if (latestProgram == null || RecordedProgram
- .START_TIME_THEN_ID_COMPARATOR.compare(latestProgram, program) < 0) {
+ if (latestProgram == null
+ || RecordedProgram.START_TIME_THEN_ID_COMPARATOR.compare(latestProgram, program)
+ < 0) {
latestProgram = program;
}
}
@@ -622,17 +711,19 @@ public class DvrBrowseFragment extends BrowseFragment implements
private class SeriesAdapter extends SortedArrayAdapter<SeriesRecording> {
SeriesAdapter() {
- super(mPresenterSelector, new Comparator<SeriesRecording>() {
- @Override
- public int compare(SeriesRecording lhs, SeriesRecording rhs) {
- if (lhs.isStopped() && !rhs.isStopped()) {
- return 1;
- } else if (!lhs.isStopped() && rhs.isStopped()) {
- return -1;
- }
- return SeriesRecording.PRIORITY_COMPARATOR.compare(lhs, rhs);
- }
- });
+ super(
+ mPresenterSelector,
+ new Comparator<SeriesRecording>() {
+ @Override
+ public int compare(SeriesRecording lhs, SeriesRecording rhs) {
+ if (lhs.isStopped() && !rhs.isStopped()) {
+ return 1;
+ } else if (!lhs.isStopped() && rhs.isStopped()) {
+ return -1;
+ }
+ return SeriesRecording.PRIORITY_COMPARATOR.compare(lhs, rhs);
+ }
+ });
}
@Override
@@ -662,4 +753,22 @@ public class DvrBrowseFragment extends BrowseFragment implements
}
}
}
-} \ No newline at end of file
+
+ private class RecentRowAdapter extends SortedArrayAdapter<Object> {
+ RecentRowAdapter(int maxItemCount) {
+ super(mPresenterSelector, RECENT_ROW_COMPARATOR, maxItemCount);
+ }
+
+ @Override
+ public long getId(Object item) {
+ // We takes the inverse number for the ID of scheduled recordings to make the ID stable.
+ if (item instanceof ScheduledRecording) {
+ return -((ScheduledRecording) item).getId() - 1;
+ } else if (item instanceof RecordedProgram) {
+ return ((RecordedProgram) item).getId();
+ } else {
+ return -1;
+ }
+ }
+ }
+}
diff --git a/src/com/android/tv/dvr/ui/browse/DvrDetailsActivity.java b/src/com/android/tv/dvr/ui/browse/DvrDetailsActivity.java
index 35d21db8..0336b319 100644
--- a/src/com/android/tv/dvr/ui/browse/DvrDetailsActivity.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrDetailsActivity.java
@@ -19,21 +19,16 @@ package com.android.tv.dvr.ui.browse;
import android.app.Activity;
import android.os.Bundle;
import android.support.v17.leanback.app.DetailsFragment;
-
import android.transition.Transition;
import android.transition.Transition.TransitionListener;
import android.view.View;
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.Starter;
import com.android.tv.dialog.PinDialogFragment;
-/**
- * Activity to show details view in DVR.
- */
+/** Activity to show details view in DVR. */
public class DvrDetailsActivity extends Activity implements PinDialogFragment.OnPinCheckedListener {
- /**
- * Name of record id added to the Intent.
- */
+ /** Name of record id added to the Intent. */
public static final String RECORDING_ID = "record_id";
/**
@@ -42,46 +37,38 @@ public class DvrDetailsActivity extends Activity implements PinDialogFragment.On
*/
public static final String HIDE_VIEW_SCHEDULE = "hide_view_schedule";
- /**
- * Name of details view's type added to the intent.
- */
+ /** Name of details view's type added to the intent. */
public static final String DETAILS_VIEW_TYPE = "details_view_type";
- /**
- * Name of shared element between activities.
- */
+ /** Name of shared element between activities. */
public static final String SHARED_ELEMENT_NAME = "shared_element";
- /**
- * CURRENT_RECORDING_VIEW refers to Current Recordings in DVR.
- */
+ /** Name of error message of a failed recording */
+ public static final String EXTRA_FAILED_MESSAGE = "failed_message";
+
+ /** CURRENT_RECORDING_VIEW refers to Current Recordings in DVR. */
public static final int CURRENT_RECORDING_VIEW = 1;
- /**
- * SCHEDULED_RECORDING_VIEW refers to Scheduled Recordings in DVR.
- */
+ /** SCHEDULED_RECORDING_VIEW refers to Scheduled Recordings in DVR. */
public static final int SCHEDULED_RECORDING_VIEW = 2;
- /**
- * RECORDED_PROGRAM_VIEW refers to Recorded programs in DVR.
- */
+ /** RECORDED_PROGRAM_VIEW refers to Recorded programs in DVR. */
public static final int RECORDED_PROGRAM_VIEW = 3;
- /**
- * SERIES_RECORDING_VIEW refers to series recording in DVR.
- */
+ /** SERIES_RECORDING_VIEW refers to series recording in DVR. */
public static final int SERIES_RECORDING_VIEW = 4;
private PinDialogFragment.OnPinCheckedListener mOnPinCheckedListener;
@Override
public void onCreate(Bundle savedInstanceState) {
- TvApplication.setCurrentRunningProcess(this, true);
+ Starter.start(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dvr_details);
long recordId = getIntent().getLongExtra(RECORDING_ID, -1);
int detailsViewType = getIntent().getIntExtra(DETAILS_VIEW_TYPE, -1);
boolean hideViewSchedule = getIntent().getBooleanExtra(HIDE_VIEW_SCHEDULE, false);
+ String failedMsg = getIntent().getStringExtra(EXTRA_FAILED_MESSAGE);
if (recordId != -1 && detailsViewType != -1 && savedInstanceState == null) {
Bundle args = new Bundle();
args.putLong(RECORDING_ID, recordId);
@@ -90,6 +77,7 @@ public class DvrDetailsActivity extends Activity implements PinDialogFragment.On
detailsFragment = new CurrentRecordingDetailsFragment();
} else if (detailsViewType == SCHEDULED_RECORDING_VIEW) {
args.putBoolean(HIDE_VIEW_SCHEDULE, hideViewSchedule);
+ args.putString(EXTRA_FAILED_MESSAGE, failedMsg);
detailsFragment = new ScheduledRecordingDetailsFragment();
} else if (detailsViewType == RECORDED_PROGRAM_VIEW) {
detailsFragment = new RecordedProgramDetailsFragment();
@@ -97,8 +85,10 @@ public class DvrDetailsActivity extends Activity implements PinDialogFragment.On
detailsFragment = new SeriesRecordingDetailsFragment();
}
detailsFragment.setArguments(args);
- getFragmentManager().beginTransaction()
- .replace(R.id.dvr_details_view_frame, detailsFragment).commit();
+ getFragmentManager()
+ .beginTransaction()
+ .replace(R.id.dvr_details_view_frame, detailsFragment)
+ .commit();
}
// This is a workaround for the focus on O device
diff --git a/src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java
index 19fb7117..8f4e4dab 100644
--- a/src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java
@@ -36,21 +36,19 @@ import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
import android.support.v17.leanback.widget.VerticalGridView;
import android.text.TextUtils;
import android.widget.Toast;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
-import com.android.tv.data.Channel;
+import com.android.tv.common.util.CommonUtils;
import com.android.tv.data.ChannelDataManager;
+import com.android.tv.data.api.Channel;
import com.android.tv.dialog.PinDialogFragment;
import com.android.tv.dialog.PinDialogFragment.OnPinCheckedListener;
import com.android.tv.dvr.data.RecordedProgram;
import com.android.tv.dvr.ui.DvrUiHelper;
import com.android.tv.parental.ParentalControlSettings;
-import com.android.tv.util.ImageLoader;
import com.android.tv.util.ToastUtils;
-import com.android.tv.util.Utils;
-
+import com.android.tv.util.images.ImageLoader;
import java.io.File;
abstract class DvrDetailsFragment extends DetailsFragment {
@@ -77,8 +75,8 @@ abstract class DvrDetailsFragment extends DetailsFragment {
public void onStart() {
super.onStart();
// TODO: remove the workaround of b/30401180.
- VerticalGridView container = (VerticalGridView) getActivity()
- .findViewById(R.id.container_list);
+ VerticalGridView container =
+ (VerticalGridView) getActivity().findViewById(R.id.container_list);
// Need to manually modify offset. Please refer DetailsFragment.setVerticalGridViewLayout.
container.setItemAlignmentOffset(0);
container.setWindowAlignmentOffset(
@@ -86,27 +84,23 @@ abstract class DvrDetailsFragment extends DetailsFragment {
}
private void setupAdapter() {
- DetailsOverviewRowPresenter rowPresenter = new DetailsOverviewRowPresenter(
- new DetailsContentPresenter(getActivity()));
- rowPresenter.setBackgroundColor(getResources().getColor(R.color.common_tv_background,
- null));
- rowPresenter.setSharedElementEnterTransition(getActivity(),
- DvrDetailsActivity.SHARED_ELEMENT_NAME);
+ DetailsOverviewRowPresenter rowPresenter =
+ new DetailsOverviewRowPresenter(new DetailsContentPresenter(getActivity()));
+ rowPresenter.setBackgroundColor(
+ getResources().getColor(R.color.common_tv_background, null));
+ rowPresenter.setSharedElementEnterTransition(
+ getActivity(), DvrDetailsActivity.SHARED_ELEMENT_NAME);
rowPresenter.setOnActionClickedListener(onCreateOnActionClickedListener());
mRowsAdapter = new ArrayObjectAdapter(onCreatePresenterSelector(rowPresenter));
setAdapter(mRowsAdapter);
}
- /**
- * Returns details views' rows adapter.
- */
+ /** Returns details views' rows adapter. */
protected ArrayObjectAdapter getRowsAdapter() {
- return mRowsAdapter;
+ return mRowsAdapter;
}
- /**
- * Sets details overview.
- */
+ /** Sets details overview. */
protected void setDetailsOverviewRow(DetailsContent detailsContent) {
mDetailsOverview = new DetailsOverviewRow(detailsContent);
mDetailsOverview.setActionsAdapter(onCreateActionsAdapter());
@@ -114,9 +108,7 @@ abstract class DvrDetailsFragment extends DetailsFragment {
onLoadLogoAndBackgroundImages(detailsContent);
}
- /**
- * Creates and returns presenter selector will be used by rows adaptor.
- */
+ /** Creates and returns presenter selector will be used by rows adaptor. */
protected PresenterSelector onCreatePresenterSelector(
DetailsOverviewRowPresenter rowPresenter) {
ClassPresenterSelector presenterSelector = new ClassPresenterSelector();
@@ -130,11 +122,9 @@ abstract class DvrDetailsFragment extends DetailsFragment {
* do anything after calling {@link #onCreate(Bundle)}. If there's something subclasses have to
* do after the super class did onCreate, it should override this method and put the codes here.
*/
- protected void onCreateInternal() { }
+ protected void onCreateInternal() {}
- /**
- * Updates actions of details overview.
- */
+ /** Updates actions of details overview. */
protected void updateActions() {
mDetailsOverview.setActionsAdapter(onCreateActionsAdapter());
}
@@ -142,14 +132,12 @@ abstract class DvrDetailsFragment extends DetailsFragment {
/**
* Loads recording details according to the arguments the fragment got.
*
- * @return false if cannot find valid recordings, else return true. If the return value
- * is false, the detail activity and fragment will be ended.
+ * @return false if cannot find valid recordings, else return true. If the return value is
+ * false, the detail activity and fragment will be ended.
*/
abstract boolean onLoadRecordingDetails(Bundle args);
- /**
- * Creates actions users can interact with and their adaptor for this fragment.
- */
+ /** Creates actions users can interact with and their adaptor for this fragment. */
abstract SparseArrayObjectAdapter onCreateActionsAdapter();
/**
@@ -158,66 +146,76 @@ abstract class DvrDetailsFragment extends DetailsFragment {
*/
abstract OnActionClickedListener onCreateOnActionClickedListener();
- /**
- * Loads logo and background images for detail fragments.
- */
+ /** Loads logo and background images for detail fragments. */
protected void onLoadLogoAndBackgroundImages(DetailsContent detailsContent) {
Drawable logoDrawable = null;
Drawable backgroundDrawable = null;
if (TextUtils.isEmpty(detailsContent.getLogoImageUri())) {
- logoDrawable = getContext().getResources()
- .getDrawable(R.drawable.dvr_default_poster, null);
+ logoDrawable =
+ getContext().getResources().getDrawable(R.drawable.dvr_default_poster, null);
mDetailsOverview.setImageDrawable(logoDrawable);
}
if (TextUtils.isEmpty(detailsContent.getBackgroundImageUri())) {
- backgroundDrawable = getContext().getResources()
- .getDrawable(R.drawable.dvr_default_poster, null);
+ backgroundDrawable =
+ getContext().getResources().getDrawable(R.drawable.dvr_default_poster, null);
mBackgroundHelper.setBackground(backgroundDrawable);
}
if (logoDrawable != null && backgroundDrawable != null) {
return;
}
- if (logoDrawable == null && backgroundDrawable == null
- && detailsContent.getLogoImageUri().equals(
- detailsContent.getBackgroundImageUri())) {
- ImageLoader.loadBitmap(getContext(), detailsContent.getLogoImageUri(),
- new MyImageLoaderCallback(this, LOAD_LOGO_IMAGE | LOAD_BACKGROUND_IMAGE,
- getContext()));
+ if (logoDrawable == null
+ && backgroundDrawable == null
+ && detailsContent
+ .getLogoImageUri()
+ .equals(detailsContent.getBackgroundImageUri())) {
+ ImageLoader.loadBitmap(
+ getContext(),
+ detailsContent.getLogoImageUri(),
+ new MyImageLoaderCallback(
+ this, LOAD_LOGO_IMAGE | LOAD_BACKGROUND_IMAGE, getContext()));
return;
}
if (logoDrawable == null) {
int imageWidth = getResources().getDimensionPixelSize(R.dimen.dvr_details_poster_width);
- int imageHeight = getResources()
- .getDimensionPixelSize(R.dimen.dvr_details_poster_height);
- ImageLoader.loadBitmap(getContext(), detailsContent.getLogoImageUri(),
- imageWidth, imageHeight,
+ int imageHeight =
+ getResources().getDimensionPixelSize(R.dimen.dvr_details_poster_height);
+ ImageLoader.loadBitmap(
+ getContext(),
+ detailsContent.getLogoImageUri(),
+ imageWidth,
+ imageHeight,
new MyImageLoaderCallback(this, LOAD_LOGO_IMAGE, getContext()));
}
if (backgroundDrawable == null) {
- ImageLoader.loadBitmap(getContext(), detailsContent.getBackgroundImageUri(),
+ ImageLoader.loadBitmap(
+ getContext(),
+ detailsContent.getBackgroundImageUri(),
new MyImageLoaderCallback(this, LOAD_BACKGROUND_IMAGE, getContext()));
}
}
protected void startPlayback(RecordedProgram recordedProgram, long seekTimeMs) {
- if (Utils.isInBundledPackageSet(recordedProgram.getPackageName()) &&
- !isDataUriAccessible(recordedProgram.getDataUri())) {
+ if (CommonUtils.isInBundledPackageSet(recordedProgram.getPackageName())
+ && !isDataUriAccessible(recordedProgram.getDataUri())) {
// Since cleaning RecordedProgram from forgotten storage will take some time,
// ignore playback until cleaning is finished.
- ToastUtils.show(getContext(),
+ ToastUtils.show(
+ getContext(),
getContext().getResources().getString(R.string.dvr_toast_recording_deleted),
Toast.LENGTH_SHORT);
return;
}
long programId = recordedProgram.getId();
- ParentalControlSettings parental = TvApplication.getSingletons(getActivity())
- .getTvInputManagerHelper().getParentalControlSettings();
+ ParentalControlSettings parental =
+ TvSingletons.getSingletons(getActivity())
+ .getTvInputManagerHelper()
+ .getParentalControlSettings();
if (!parental.isParentalControlsEnabled()) {
DvrUiHelper.startPlaybackActivity(getContext(), programId, seekTimeMs, false);
return;
}
ChannelDataManager channelDataManager =
- TvApplication.getSingletons(getActivity()).getChannelDataManager();
+ TvSingletons.getSingletons(getActivity()).getChannelDataManager();
Channel channel = channelDataManager.getChannel(recordedProgram.getChannelId());
if (channel != null && channel.isLocked()) {
checkPinToPlay(recordedProgram, seekTimeMs);
@@ -249,36 +247,43 @@ abstract class DvrDetailsFragment extends DetailsFragment {
private void checkPinToPlay(RecordedProgram recordedProgram, long seekTimeMs) {
SoftPreconditions.checkState(getActivity() instanceof DvrDetailsActivity);
if (getActivity() instanceof DvrDetailsActivity) {
- ((DvrDetailsActivity) getActivity()).setOnPinCheckListener(new OnPinCheckedListener() {
- @Override
- public void onPinChecked(boolean checked, int type, String rating) {
- ((DvrDetailsActivity) getActivity()).setOnPinCheckListener(null);
- if (checked && type == PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_PROGRAM) {
- DvrUiHelper.startPlaybackActivity(getContext(), recordedProgram.getId(),
- seekTimeMs, true);
- }
- }
- });
+ ((DvrDetailsActivity) getActivity())
+ .setOnPinCheckListener(
+ new OnPinCheckedListener() {
+ @Override
+ public void onPinChecked(boolean checked, int type, String rating) {
+ ((DvrDetailsActivity) getActivity())
+ .setOnPinCheckListener(null);
+ if (checked
+ && type
+ == PinDialogFragment
+ .PIN_DIALOG_TYPE_UNLOCK_PROGRAM) {
+ DvrUiHelper.startPlaybackActivity(
+ getContext(),
+ recordedProgram.getId(),
+ seekTimeMs,
+ true);
+ }
+ }
+ });
PinDialogFragment.create(PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_PROGRAM)
.show(getActivity().getFragmentManager(), PinDialogFragment.DIALOG_TAG);
}
}
- private static class MyImageLoaderCallback extends
- ImageLoader.ImageLoaderCallback<DvrDetailsFragment> {
+ private static class MyImageLoaderCallback
+ extends ImageLoader.ImageLoaderCallback<DvrDetailsFragment> {
private final Context mContext;
private final int mLoadType;
- public MyImageLoaderCallback(DvrDetailsFragment fragment,
- int loadType, Context context) {
+ public MyImageLoaderCallback(DvrDetailsFragment fragment, int loadType, Context context) {
super(fragment);
mLoadType = loadType;
mContext = context;
}
@Override
- public void onBitmapLoaded(DvrDetailsFragment fragment,
- @Nullable Bitmap bitmap) {
+ public void onBitmapLoaded(DvrDetailsFragment fragment, @Nullable Bitmap bitmap) {
Drawable drawable;
int loadType = mLoadType;
if (bitmap == null) {
diff --git a/src/com/android/tv/dvr/ui/browse/DvrHistoryCardHolder.java b/src/com/android/tv/dvr/ui/browse/DvrHistoryCardHolder.java
new file mode 100644
index 00000000..c6288ef0
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/browse/DvrHistoryCardHolder.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2018 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.dvr.ui.browse;
+
+/** Special object for schedule preview; */
+final class DvrHistoryCardHolder {
+ /** Full schedule card holder. */
+ static final DvrHistoryCardHolder DVR_HISTORY_CARD_HOLDER = new DvrHistoryCardHolder();
+
+ private DvrHistoryCardHolder() {}
+}
diff --git a/src/com/android/tv/dvr/ui/browse/DvrHistoryCardPresenter.java b/src/com/android/tv/dvr/ui/browse/DvrHistoryCardPresenter.java
new file mode 100644
index 00000000..62c050c9
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/browse/DvrHistoryCardPresenter.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 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.dvr.ui.browse;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import com.android.tv.R;
+import com.android.tv.dvr.ui.DvrUiHelper;
+
+/** Presents a DVR history card view in the {@link DvrBrowseFragment}. */
+class DvrHistoryCardPresenter extends DvrItemPresenter<Object> {
+ private final Drawable mIconDrawable;
+ private final String mCardTitleText;
+
+ DvrHistoryCardPresenter(Context context) {
+ super(context);
+ mIconDrawable = mContext.getDrawable(R.drawable.dvr_full_schedule);
+ mCardTitleText = mContext.getString(R.string.dvr_history_card_view_title);
+ }
+
+ @Override
+ public DvrItemViewHolder onCreateDvrItemViewHolder() {
+ return new DvrItemViewHolder(new RecordingCardView(mContext));
+ }
+
+ @Override
+ public void onBindDvrItemViewHolder(DvrItemViewHolder vh, Object o) {
+ final RecordingCardView cardView = (RecordingCardView) vh.view;
+
+ cardView.setTitle(mCardTitleText);
+ cardView.setImage(mIconDrawable);
+ }
+
+ @Override
+ public void onUnbindViewHolder(ViewHolder vh) {
+ ((RecordingCardView) vh.view).reset();
+ super.onUnbindViewHolder(vh);
+ }
+
+ @Override
+ protected View.OnClickListener onCreateOnClickListener() {
+ return new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ DvrUiHelper.startDvrHistoryActivity(mContext);
+ }
+ };
+ }
+}
diff --git a/src/com/android/tv/dvr/ui/browse/DvrItemPresenter.java b/src/com/android/tv/dvr/ui/browse/DvrItemPresenter.java
index df0e61c1..4298d86a 100644
--- a/src/com/android/tv/dvr/ui/browse/DvrItemPresenter.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrItemPresenter.java
@@ -23,18 +23,15 @@ import android.support.v17.leanback.widget.Presenter;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-
import com.android.tv.common.SoftPreconditions;
import com.android.tv.dvr.ui.DvrUiHelper;
-
import java.util.HashSet;
import java.util.Set;
/**
* An abstract class to present DVR items in {@link RecordingCardView}, which is mainly used in
- * {@link DvrBrowseFragment}. DVR items might include:
- * {@link com.android.tv.dvr.data.ScheduledRecording},
- * {@link com.android.tv.dvr.data.RecordedProgram}, and
+ * {@link DvrBrowseFragment}. DVR items might include: {@link
+ * com.android.tv.dvr.data.ScheduledRecording}, {@link com.android.tv.dvr.data.RecordedProgram}, and
* {@link com.android.tv.dvr.data.SeriesRecording}.
*/
public abstract class DvrItemPresenter<T> extends Presenter {
@@ -51,9 +48,9 @@ public abstract class DvrItemPresenter<T> extends Presenter {
return (RecordingCardView) view;
}
- protected void onBound(T item) { }
+ protected void onBound(T item) {}
- protected void onUnbound() { }
+ protected void onUnbound() {}
}
DvrItemPresenter(Context context) {
@@ -94,9 +91,7 @@ public abstract class DvrItemPresenter<T> extends Presenter {
viewHolder.view.setOnClickListener(null);
}
- /**
- * Unbinds all bound view holders.
- */
+ /** Unbinds all bound view holders. */
public void unbindAllViewHolders() {
// When browse fragments are destroyed, RecyclerView would not call presenters'
// onUnbindViewHolder(). We should handle it by ourselves to prevent resources leaks.
@@ -105,36 +100,28 @@ public abstract class DvrItemPresenter<T> extends Presenter {
}
}
- /**
- * This method will be called when a {@link DvrItemViewHolder} is needed to be created.
- */
- abstract protected DvrItemViewHolder onCreateDvrItemViewHolder();
+ /** This method will be called when a {@link DvrItemViewHolder} is needed to be created. */
+ protected abstract DvrItemViewHolder onCreateDvrItemViewHolder();
- /**
- * This method will be called when a {@link DvrItemViewHolder} is bound to a DVR item.
- */
- abstract protected void onBindDvrItemViewHolder(DvrItemViewHolder viewHolder, T item);
+ /** This method will be called when a {@link DvrItemViewHolder} is bound to a DVR item. */
+ protected abstract void onBindDvrItemViewHolder(DvrItemViewHolder viewHolder, T item);
- /**
- * Returns context.
- */
+ /** Returns context. */
protected Context getContext() {
return mContext;
}
- /**
- * Creates {@link OnClickListener} for DVR library's card views.
- */
+ /** Creates {@link OnClickListener} for DVR library's card views. */
protected OnClickListener onCreateOnClickListener() {
return new OnClickListener() {
@Override
public void onClick(View view) {
if (view instanceof RecordingCardView) {
RecordingCardView v = (RecordingCardView) view;
- DvrUiHelper.startDetailsActivity((Activity) v.getContext(),
- v.getTag(), v.getImageView(), false);
+ DvrUiHelper.startDetailsActivity(
+ (Activity) v.getContext(), v.getTag(), v.getImageView(), false);
}
}
};
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/browse/DvrListRowPresenter.java b/src/com/android/tv/dvr/ui/browse/DvrListRowPresenter.java
index 37a72eaf..a2d1cb28 100644
--- a/src/com/android/tv/dvr/ui/browse/DvrListRowPresenter.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrListRowPresenter.java
@@ -19,7 +19,6 @@ package com.android.tv.dvr.ui.browse;
import android.content.Context;
import android.support.v17.leanback.widget.ListRowPresenter;
import android.view.ViewGroup;
-
import com.android.tv.R;
/** A list row presenter to display expand/fold card views list. */
diff --git a/src/com/android/tv/dvr/ui/browse/FullScheduleCardHolder.java b/src/com/android/tv/dvr/ui/browse/FullScheduleCardHolder.java
index 311137a9..6def818f 100644
--- a/src/com/android/tv/dvr/ui/browse/FullScheduleCardHolder.java
+++ b/src/com/android/tv/dvr/ui/browse/FullScheduleCardHolder.java
@@ -16,14 +16,10 @@
package com.android.tv.dvr.ui.browse;
-/**
- * Special object for schedule preview;
- */
+/** Special object for schedule preview; */
final class FullScheduleCardHolder {
- /**
- * Full schedule card holder.
- */
+ /** Full schedule card holder. */
static final FullScheduleCardHolder FULL_SCHEDULE_CARD_HOLDER = new FullScheduleCardHolder();
- private FullScheduleCardHolder() { }
+ private FullScheduleCardHolder() {}
}
diff --git a/src/com/android/tv/dvr/ui/browse/FullSchedulesCardPresenter.java b/src/com/android/tv/dvr/ui/browse/FullSchedulesCardPresenter.java
index 94c67eec..af0f24c0 100644
--- a/src/com/android/tv/dvr/ui/browse/FullSchedulesCardPresenter.java
+++ b/src/com/android/tv/dvr/ui/browse/FullSchedulesCardPresenter.java
@@ -19,20 +19,15 @@ package com.android.tv.dvr.ui.browse;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.View;
-import android.view.ViewGroup;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.ui.DvrUiHelper;
import com.android.tv.util.Utils;
-
import java.util.Collections;
import java.util.List;
-/**
- * Presents a {@link ScheduledRecording} in the {@link DvrBrowseFragment}.
- */
+/** Presents a {@link ScheduledRecording} in the {@link DvrBrowseFragment}. */
class FullSchedulesCardPresenter extends DvrItemPresenter<Object> {
private final Drawable mIconDrawable;
private final String mCardTitleText;
@@ -54,16 +49,26 @@ class FullSchedulesCardPresenter extends DvrItemPresenter<Object> {
cardView.setTitle(mCardTitleText);
cardView.setImage(mIconDrawable);
- List<ScheduledRecording> scheduledRecordings = TvApplication.getSingletons(mContext)
- .getDvrDataManager().getAvailableScheduledRecordings();
+ List<ScheduledRecording> scheduledRecordings =
+ TvSingletons.getSingletons(mContext)
+ .getDvrDataManager()
+ .getAvailableScheduledRecordings();
int fullDays = 0;
if (!scheduledRecordings.isEmpty()) {
- fullDays = Utils.computeDateDifference(System.currentTimeMillis(),
- Collections.max(scheduledRecordings, ScheduledRecording.START_TIME_COMPARATOR)
- .getStartTimeMs()) + 1;
+ fullDays =
+ Utils.computeDateDifference(
+ System.currentTimeMillis(),
+ Collections.max(
+ scheduledRecordings,
+ ScheduledRecording.START_TIME_COMPARATOR)
+ .getStartTimeMs())
+ + 1;
}
- cardView.setContent(mContext.getResources().getQuantityString(
- R.plurals.dvr_full_schedule_card_view_content, fullDays, fullDays), null);
+ cardView.setContent(
+ mContext.getResources()
+ .getQuantityString(
+ R.plurals.dvr_full_schedule_card_view_content, fullDays, fullDays),
+ null);
}
@Override
@@ -81,4 +86,4 @@ class FullSchedulesCardPresenter extends DvrItemPresenter<Object> {
}
};
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java
index eb9cb26c..47b1a198 100644
--- a/src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java
@@ -22,17 +22,14 @@ import android.os.Bundle;
import android.support.v17.leanback.widget.Action;
import android.support.v17.leanback.widget.OnActionClickedListener;
import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.DvrWatchedPositionManager;
import com.android.tv.dvr.data.RecordedProgram;
-/**
- * {@link android.support.v17.leanback.app.DetailsFragment} for recorded program in DVR.
- */
+/** {@link android.support.v17.leanback.app.DetailsFragment} for recorded program in DVR. */
public class RecordedProgramDetailsFragment extends DvrDetailsFragment
implements DvrDataManager.RecordedProgramListener {
private static final int ACTION_RESUME_PLAYING = 1;
@@ -47,17 +44,17 @@ public class RecordedProgramDetailsFragment extends DvrDetailsFragment
@Override
public void onCreate(Bundle savedInstanceState) {
- mDvrDataManager = TvApplication.getSingletons(getContext()).getDvrDataManager();
+ mDvrDataManager = TvSingletons.getSingletons(getContext()).getDvrDataManager();
mDvrDataManager.addRecordedProgramListener(this);
super.onCreate(savedInstanceState);
}
@Override
public void onCreateInternal() {
- mDvrWatchedPositionManager = TvApplication.getSingletons(getActivity())
- .getDvrWatchedPositionManager();
- setDetailsOverviewRow(DetailsContent
- .createFromRecordedProgram(getContext(), mRecordedProgram));
+ mDvrWatchedPositionManager =
+ TvSingletons.getSingletons(getActivity()).getDvrWatchedPositionManager();
+ setDetailsOverviewRow(
+ DetailsContent.createFromRecordedProgram(getContext(), mRecordedProgram));
}
@Override
@@ -95,20 +92,36 @@ public class RecordedProgramDetailsFragment extends DvrDetailsFragment
Resources res = getResources();
if (mDvrWatchedPositionManager.getWatchedStatus(mRecordedProgram)
== DvrWatchedPositionManager.DVR_WATCHED_STATUS_WATCHING) {
- adapter.set(ACTION_RESUME_PLAYING, new Action(ACTION_RESUME_PLAYING,
- res.getString(R.string.dvr_detail_resume_play), null,
- res.getDrawable(R.drawable.lb_ic_play)));
- adapter.set(ACTION_PLAY_FROM_BEGINNING, new Action(ACTION_PLAY_FROM_BEGINNING,
- res.getString(R.string.dvr_detail_play_from_beginning), null,
- res.getDrawable(R.drawable.lb_ic_replay)));
+ adapter.set(
+ ACTION_RESUME_PLAYING,
+ new Action(
+ ACTION_RESUME_PLAYING,
+ res.getString(R.string.dvr_detail_resume_play),
+ null,
+ res.getDrawable(R.drawable.lb_ic_play)));
+ adapter.set(
+ ACTION_PLAY_FROM_BEGINNING,
+ new Action(
+ ACTION_PLAY_FROM_BEGINNING,
+ res.getString(R.string.dvr_detail_play_from_beginning),
+ null,
+ res.getDrawable(R.drawable.lb_ic_replay)));
} else {
- adapter.set(ACTION_PLAY_FROM_BEGINNING, new Action(ACTION_PLAY_FROM_BEGINNING,
- res.getString(R.string.dvr_detail_watch), null,
- res.getDrawable(R.drawable.lb_ic_play)));
+ adapter.set(
+ ACTION_PLAY_FROM_BEGINNING,
+ new Action(
+ ACTION_PLAY_FROM_BEGINNING,
+ res.getString(R.string.dvr_detail_watch),
+ null,
+ res.getDrawable(R.drawable.lb_ic_play)));
}
- adapter.set(ACTION_DELETE_RECORDING, new Action(ACTION_DELETE_RECORDING,
- res.getString(R.string.dvr_detail_delete), null,
- res.getDrawable(R.drawable.ic_delete_32dp)));
+ adapter.set(
+ ACTION_DELETE_RECORDING,
+ new Action(
+ ACTION_DELETE_RECORDING,
+ res.getString(R.string.dvr_detail_delete),
+ null,
+ res.getDrawable(R.drawable.ic_delete_32dp)));
return adapter;
}
@@ -120,11 +133,13 @@ public class RecordedProgramDetailsFragment extends DvrDetailsFragment
if (action.getId() == ACTION_PLAY_FROM_BEGINNING) {
startPlayback(mRecordedProgram, TvInputManager.TIME_SHIFT_INVALID_TIME);
} else if (action.getId() == ACTION_RESUME_PLAYING) {
- startPlayback(mRecordedProgram, mDvrWatchedPositionManager
- .getWatchedPosition(mRecordedProgram.getId()));
+ startPlayback(
+ mRecordedProgram,
+ mDvrWatchedPositionManager.getWatchedPosition(
+ mRecordedProgram.getId()));
} else if (action.getId() == ACTION_DELETE_RECORDING) {
- DvrManager dvrManager = TvApplication
- .getSingletons(getActivity()).getDvrManager();
+ DvrManager dvrManager =
+ TvSingletons.getSingletons(getActivity()).getDvrManager();
dvrManager.removeRecordedProgram(mRecordedProgram);
getActivity().finish();
}
@@ -133,10 +148,10 @@ public class RecordedProgramDetailsFragment extends DvrDetailsFragment
}
@Override
- public void onRecordedProgramsAdded(RecordedProgram... recordedPrograms) { }
+ public void onRecordedProgramsAdded(RecordedProgram... recordedPrograms) {}
@Override
- public void onRecordedProgramsChanged(RecordedProgram... recordedPrograms) { }
+ public void onRecordedProgramsChanged(RecordedProgram... recordedPrograms) {}
@Override
public void onRecordedProgramsRemoved(RecordedProgram... recordedPrograms) {
diff --git a/src/com/android/tv/dvr/ui/browse/RecordedProgramPresenter.java b/src/com/android/tv/dvr/ui/browse/RecordedProgramPresenter.java
index 5fe162b6..e2db3ac4 100644
--- a/src/com/android/tv/dvr/ui/browse/RecordedProgramPresenter.java
+++ b/src/com/android/tv/dvr/ui/browse/RecordedProgramPresenter.java
@@ -18,17 +18,14 @@ package com.android.tv.dvr.ui.browse;
import android.content.Context;
import android.media.tv.TvInputManager;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.dvr.DvrWatchedPositionManager;
import com.android.tv.dvr.DvrWatchedPositionManager.WatchedPositionChangedListener;
import com.android.tv.dvr.data.RecordedProgram;
import com.android.tv.util.Utils;
-/**
- * Presents a {@link RecordedProgram} in the {@link DvrBrowseFragment}.
- */
+/** Presents a {@link RecordedProgram} in the {@link DvrBrowseFragment}. */
public class RecordedProgramPresenter extends DvrItemPresenter<RecordedProgram> {
private final DvrWatchedPositionManager mDvrWatchedPositionManager;
private String mTodayString;
@@ -53,10 +50,16 @@ public class RecordedProgramPresenter extends DvrItemPresenter<RecordedProgram>
}
private void setProgressBar(long watchedPositionMs) {
- ((RecordingCardView) view).setProgressBar(
- (watchedPositionMs == TvInputManager.TIME_SHIFT_INVALID_TIME) ? null
- : Math.min(100, (int) (100.0f * watchedPositionMs
- / mProgram.getDurationMillis())));
+ ((RecordingCardView) view)
+ .setProgressBar(
+ (watchedPositionMs == TvInputManager.TIME_SHIFT_INVALID_TIME)
+ ? null
+ : Math.min(
+ 100,
+ (int)
+ (100.0f
+ * watchedPositionMs
+ / mProgram.getDurationMillis())));
}
@Override
@@ -86,15 +89,15 @@ public class RecordedProgramPresenter extends DvrItemPresenter<RecordedProgram>
}
}
- RecordedProgramPresenter(Context context, boolean showEpisodeTitle,
- boolean expandTitleWhenFocused) {
+ RecordedProgramPresenter(
+ Context context, boolean showEpisodeTitle, boolean expandTitleWhenFocused) {
super(context);
mTodayString = mContext.getString(R.string.dvr_date_today);
mYesterdayString = mContext.getString(R.string.dvr_date_yesterday);
mDvrWatchedPositionManager =
- TvApplication.getSingletons(mContext).getDvrWatchedPositionManager();
- mProgressBarColor = mContext.getResources()
- .getColor(R.color.play_controls_progress_bar_watched);
+ TvSingletons.getSingletons(mContext).getDvrWatchedPositionManager();
+ mProgressBarColor =
+ mContext.getResources().getColor(R.color.play_controls_progress_bar_watched);
mShowEpisodeTitle = showEpisodeTitle;
mExpandTitleWhenFocused = expandTitleWhenFocused;
}
@@ -114,29 +117,37 @@ public class RecordedProgramPresenter extends DvrItemPresenter<RecordedProgram>
final RecordedProgramViewHolder viewHolder = (RecordedProgramViewHolder) baseHolder;
final RecordingCardView cardView = viewHolder.getView();
DetailsContent details = DetailsContent.createFromRecordedProgram(mContext, program);
- cardView.setTitle(mShowEpisodeTitle ?
- program.getEpisodeDisplayTitle(mContext) : details.getTitle());
+ cardView.setTitle(
+ mShowEpisodeTitle ? program.getEpisodeDisplayTitle(mContext) : details.getTitle());
cardView.setImageUri(details.getLogoImageUri(), details.isUsingChannelLogo());
cardView.setContent(generateMajorContent(program), generateMinorContent(program));
cardView.setDetailBackgroundImageUri(details.getBackgroundImageUri());
}
private String generateMajorContent(RecordedProgram program) {
- int dateDifference = Utils.computeDateDifference(program.getStartTimeUtcMillis(),
- System.currentTimeMillis());
+ int dateDifference =
+ Utils.computeDateDifference(
+ program.getStartTimeUtcMillis(), System.currentTimeMillis());
if (dateDifference == 0) {
return mTodayString;
} else if (dateDifference == 1) {
return mYesterdayString;
} else {
- return Utils.getDurationString(mContext, program.getStartTimeUtcMillis(),
- program.getStartTimeUtcMillis(), false, true, false, 0);
+ return Utils.getDurationString(
+ mContext,
+ program.getStartTimeUtcMillis(),
+ program.getStartTimeUtcMillis(),
+ false,
+ true,
+ false,
+ 0);
}
}
private String generateMinorContent(RecordedProgram program) {
int durationMinutes = Math.max(1, Utils.getRoundOffMinsFromMs(program.getDurationMillis()));
- return mContext.getResources().getQuantityString(
- R.plurals.dvr_program_duration, durationMinutes, durationMinutes);
+ return mContext.getResources()
+ .getQuantityString(
+ R.plurals.dvr_program_duration, durationMinutes, durationMinutes);
}
}
diff --git a/src/com/android/tv/dvr/ui/browse/RecordingCardView.java b/src/com/android/tv/dvr/ui/browse/RecordingCardView.java
index 767addc8..fe3c52d9 100644
--- a/src/com/android/tv/dvr/ui/browse/RecordingCardView.java
+++ b/src/com/android/tv/dvr/ui/browse/RecordingCardView.java
@@ -31,20 +31,19 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
-
import com.android.tv.R;
import com.android.tv.dvr.data.RecordedProgram;
import com.android.tv.ui.ViewUtils;
-import com.android.tv.util.ImageLoader;
+import com.android.tv.util.images.ImageLoader;
/**
- * A CardView for displaying info about a {@link com.android.tv.dvr.data.ScheduledRecording}
- * or {@link RecordedProgram} or {@link com.android.tv.dvr.data.SeriesRecording}.
+ * A CardView for displaying info about a {@link com.android.tv.dvr.data.ScheduledRecording} or
+ * {@link RecordedProgram} or {@link com.android.tv.dvr.data.SeriesRecording}.
*/
public class RecordingCardView extends BaseCardView {
// This value should be the same with
// android.support.v17.leanback.widget.FocusHighlightHelper.BrowseItemFocusHighlight.DURATION_MS
- private final static int ANIMATION_DURATION = 150;
+ private static final int ANIMATION_DURATION = 150;
private final ImageView mImageView;
private final int mImageWidth;
private final int mImageHeight;
@@ -70,16 +69,19 @@ public class RecordingCardView extends BaseCardView {
}
public RecordingCardView(Context context, boolean expandTitleWhenFocused) {
- this(context, context.getResources().getDimensionPixelSize(
- R.dimen.dvr_library_card_image_layout_width), context.getResources()
- .getDimensionPixelSize(R.dimen.dvr_library_card_image_layout_height),
+ this(
+ context,
+ context.getResources()
+ .getDimensionPixelSize(R.dimen.dvr_library_card_image_layout_width),
+ context.getResources()
+ .getDimensionPixelSize(R.dimen.dvr_library_card_image_layout_height),
expandTitleWhenFocused);
}
- public RecordingCardView(Context context, int imageWidth, int imageHeight,
- boolean expandTitleWhenFocused) {
+ public RecordingCardView(
+ Context context, int imageWidth, int imageHeight, boolean expandTitleWhenFocused) {
super(context);
- //TODO(dvr): move these to the layout XML.
+ // TODO(dvr): move these to the layout XML.
setCardType(BaseCardView.CARD_TYPE_INFO_UNDER_WITH_EXTRA);
setInfoVisibility(BaseCardView.CARD_REGION_VISIBLE_ALWAYS);
setFocusable(true);
@@ -99,21 +101,27 @@ public class RecordingCardView extends BaseCardView {
mTitleArea = (FrameLayout) findViewById(R.id.title_area);
mFoldedTitleView = (TextView) findViewById(R.id.title_one_line);
mExpandedTitleView = (TextView) findViewById(R.id.title_two_lines);
- mFoldedTitleHeight = getResources()
- .getDimensionPixelSize(R.dimen.dvr_library_card_folded_title_height);
- mExpandedTitleHeight = getResources()
- .getDimensionPixelSize(R.dimen.dvr_library_card_expanded_title_height);
+ mFoldedTitleHeight =
+ getResources().getDimensionPixelSize(R.dimen.dvr_library_card_folded_title_height);
+ mExpandedTitleHeight =
+ getResources()
+ .getDimensionPixelSize(R.dimen.dvr_library_card_expanded_title_height);
mExpandTitleAnimator = ValueAnimator.ofFloat(0.0f, 1.0f).setDuration(ANIMATION_DURATION);
- mExpandTitleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator valueAnimator) {
- float value = (Float) valueAnimator.getAnimatedValue();
- mExpandedTitleView.setAlpha(value);
- mFoldedTitleView.setAlpha(1.0f - value);
- ViewUtils.setLayoutHeight(mTitleArea, (int) (mFoldedTitleHeight
- + (mExpandedTitleHeight - mFoldedTitleHeight) * value));
- }
- });
+ mExpandTitleAnimator.addUpdateListener(
+ new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ float value = (Float) valueAnimator.getAnimatedValue();
+ mExpandedTitleView.setAlpha(value);
+ mFoldedTitleView.setAlpha(1.0f - value);
+ ViewUtils.setLayoutHeight(
+ mTitleArea,
+ (int)
+ (mFoldedTitleHeight
+ + (mExpandedTitleHeight - mFoldedTitleHeight)
+ * value));
+ }
+ });
mExpandTitleWhenFocused = expandTitleWhenFocused;
}
@@ -124,8 +132,12 @@ public class RecordingCardView extends BaseCardView {
// loading and drawing background images during activity transitions.
if (gainFocus) {
if (!TextUtils.isEmpty(mDetailBackgroundImageUri)) {
- ImageLoader.loadBitmap(getContext(), mDetailBackgroundImageUri,
- Integer.MAX_VALUE, Integer.MAX_VALUE, null);
+ ImageLoader.loadBitmap(
+ getContext(),
+ mDetailBackgroundImageUri,
+ Integer.MAX_VALUE,
+ Integer.MAX_VALUE,
+ null);
}
}
if (mExpandTitleWhenFocused) {
@@ -186,9 +198,7 @@ public class RecordingCardView extends BaseCardView {
}
}
- /**
- * Sets progress bar. If progress is {@code null}, hides progress bar.
- */
+ /** Sets progress bar. If progress is {@code null}, hides progress bar. */
void setProgressBar(Integer progress) {
if (progress == null) {
mProgressBar.setVisibility(View.GONE);
@@ -198,16 +208,14 @@ public class RecordingCardView extends BaseCardView {
}
}
- /**
- * Sets the color of progress bar.
- */
+ /** Sets the color of progress bar. */
void setProgressBarColor(int color) {
mProgressBar.getProgressDrawable().setTint(color);
}
/**
* Sets the image URI of the poster should be shown on the card view.
-
+ *
* @param isChannelLogo {@code true} if the image is from channels' logo.
*/
void setImageUri(String uri, boolean isChannelLogo) {
@@ -220,14 +228,16 @@ public class RecordingCardView extends BaseCardView {
if (TextUtils.isEmpty(uri)) {
mImageView.setImageDrawable(mDefaultImage);
} else {
- ImageLoader.loadBitmap(getContext(), uri, mImageWidth, mImageHeight,
+ ImageLoader.loadBitmap(
+ getContext(),
+ uri,
+ mImageWidth,
+ mImageHeight,
new RecordingCardImageLoaderCallback(this, uri));
}
}
- /**
- * Sets the {@link Drawable} of the poster should be shown on the card view.
- */
+ /** Sets the {@link Drawable} of the poster should be shown on the card view. */
public void setImage(Drawable image) {
if (image != null) {
mImageView.setImageDrawable(image);
@@ -255,9 +265,7 @@ public class RecordingCardView extends BaseCardView {
mDetailBackgroundImageUri = uri;
}
- /**
- * Returns image view.
- */
+ /** Returns image view. */
public ImageView getImageView() {
return mImageView;
}
@@ -287,4 +295,4 @@ public class RecordingCardView extends BaseCardView {
setContent(null, null);
mImageView.setImageDrawable(mDefaultImage);
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java
index 56ec357f..aa2ccf75 100644
--- a/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java
@@ -18,34 +18,35 @@ package com.android.tv.dvr.ui.browse;
import android.os.Bundle;
import android.support.v17.leanback.app.DetailsFragment;
-
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.dvr.data.ScheduledRecording;
-/**
- * {@link DetailsFragment} for recordings in DVR.
- */
+/** {@link DetailsFragment} for recordings in DVR. */
abstract class RecordingDetailsFragment extends DvrDetailsFragment {
private ScheduledRecording mRecording;
@Override
protected void onCreateInternal() {
- setDetailsOverviewRow(DetailsContent
- .createFromScheduledRecording(getContext(), mRecording));
+ setDetailsOverviewRow(
+ DetailsContent.createFromScheduledRecording(getContext(), mRecording));
}
@Override
protected boolean onLoadRecordingDetails(Bundle args) {
long scheduledRecordingId = args.getLong(DvrDetailsActivity.RECORDING_ID);
- mRecording = TvApplication.getSingletons(getContext()).getDvrDataManager()
- .getScheduledRecording(scheduledRecordingId);
+ mRecording =
+ TvSingletons.getSingletons(getContext())
+ .getDvrDataManager()
+ .getScheduledRecording(scheduledRecordingId);
return mRecording != null;
}
- /**
- * Returns {@link ScheduledRecording} for the current fragment.
- */
+ protected ScheduledRecording getScheduledRecording() {
+ return mRecording;
+ }
+
+ /** Returns {@link ScheduledRecording} for the current fragment. */
public ScheduledRecording getRecording() {
return mRecording;
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java
index 958f8bf8..302b8318 100644
--- a/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java
@@ -21,16 +21,12 @@ import android.os.Bundle;
import android.support.v17.leanback.widget.Action;
import android.support.v17.leanback.widget.OnActionClickedListener;
import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
-import android.text.TextUtils;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.ui.DvrUiHelper;
-/**
- * {@link RecordingDetailsFragment} for scheduled recording in DVR.
- */
+/** {@link RecordingDetailsFragment} for scheduled recording in DVR. */
public class ScheduledRecordingDetailsFragment extends RecordingDetailsFragment {
private static final int ACTION_VIEW_SCHEDULE = 1;
private static final int ACTION_CANCEL = 2;
@@ -38,11 +34,14 @@ public class ScheduledRecordingDetailsFragment extends RecordingDetailsFragment
private DvrManager mDvrManager;
private Action mScheduleAction;
private boolean mHideViewSchedule;
+ private String mFailedMessage;
@Override
public void onCreate(Bundle savedInstance) {
- mDvrManager = TvApplication.getSingletons(getContext()).getDvrManager();
- mHideViewSchedule = getArguments().getBoolean(DvrDetailsActivity.HIDE_VIEW_SCHEDULE);
+ Bundle args = getArguments();
+ mDvrManager = TvSingletons.getSingletons(getContext()).getDvrManager();
+ mHideViewSchedule = args.getBoolean(DvrDetailsActivity.HIDE_VIEW_SCHEDULE);
+ mFailedMessage = args.getString(DvrDetailsActivity.EXTRA_FAILED_MESSAGE);
super.onCreate(savedInstance);
}
@@ -55,19 +54,37 @@ public class ScheduledRecordingDetailsFragment extends RecordingDetailsFragment
}
@Override
+ protected void onCreateInternal() {
+ if (mFailedMessage == null) {
+ super.onCreateInternal();
+ return;
+ }
+ setDetailsOverviewRow(
+ DetailsContent.createFromFailedScheduledRecording(
+ getContext(), getScheduledRecording(), mFailedMessage));
+ }
+
+ @Override
protected SparseArrayObjectAdapter onCreateActionsAdapter() {
SparseArrayObjectAdapter adapter =
new SparseArrayObjectAdapter(new ActionPresenterSelector());
Resources res = getResources();
if (!mHideViewSchedule) {
- mScheduleAction = new Action(ACTION_VIEW_SCHEDULE,
- res.getString(R.string.dvr_detail_view_schedule), null,
- res.getDrawable(getScheduleIconId()));
+ mScheduleAction =
+ new Action(
+ ACTION_VIEW_SCHEDULE,
+ res.getString(R.string.dvr_detail_view_schedule),
+ null,
+ res.getDrawable(getScheduleIconId()));
adapter.set(ACTION_VIEW_SCHEDULE, mScheduleAction);
}
- adapter.set(ACTION_CANCEL, new Action(ACTION_CANCEL,
- res.getString(R.string.dvr_detail_cancel_recording), null,
- res.getDrawable(R.drawable.ic_dvr_cancel_32dp)));
+ adapter.set(
+ ACTION_CANCEL,
+ new Action(
+ ACTION_CANCEL,
+ res.getString(R.string.dvr_detail_cancel_recording),
+ null,
+ res.getDrawable(R.drawable.ic_dvr_cancel_32dp)));
return adapter;
}
diff --git a/src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java
index 273d3d19..8e028689 100644
--- a/src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java
+++ b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java
@@ -18,18 +18,14 @@ package com.android.tv.dvr.ui.browse;
import android.content.Context;
import android.os.Handler;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.util.Utils;
-
import java.util.concurrent.TimeUnit;
-/**
- * Presents a {@link ScheduledRecording} in the {@link DvrBrowseFragment}.
- */
+/** Presents a {@link ScheduledRecording} in the {@link DvrBrowseFragment}. */
class ScheduledRecordingPresenter extends DvrItemPresenter<ScheduledRecording> {
private static final long PROGRESS_UPDATE_INTERVAL_MS = TimeUnit.SECONDS.toMillis(5);
@@ -39,13 +35,14 @@ class ScheduledRecordingPresenter extends DvrItemPresenter<ScheduledRecording> {
private final class ScheduledRecordingViewHolder extends DvrItemViewHolder {
private final Handler mHandler = new Handler();
private ScheduledRecording mScheduledRecording;
- private final Runnable mProgressBarUpdater = new Runnable() {
- @Override
- public void run() {
- updateProgressBar();
- mHandler.postDelayed(this, PROGRESS_UPDATE_INTERVAL_MS);
- }
- };
+ private final Runnable mProgressBarUpdater =
+ new Runnable() {
+ @Override
+ public void run() {
+ updateProgressBar();
+ mHandler.postDelayed(this, PROGRESS_UPDATE_INTERVAL_MS);
+ }
+ };
ScheduledRecordingViewHolder(RecordingCardView view, int progressBarColor) {
super(view);
@@ -73,9 +70,17 @@ class ScheduledRecordingPresenter extends DvrItemPresenter<ScheduledRecording> {
int recordingState = mScheduledRecording.getState();
RecordingCardView cardView = (RecordingCardView) view;
if (recordingState == ScheduledRecording.STATE_RECORDING_IN_PROGRESS) {
- cardView.setProgressBar(Math.max(0, Math.min((int) (100 *
- (System.currentTimeMillis() - mScheduledRecording.getStartTimeMs())
- / mScheduledRecording.getDuration()), 100)));
+ cardView.setProgressBar(
+ Math.max(
+ 0,
+ Math.min(
+ (int)
+ (100
+ * (System.currentTimeMillis()
+ - mScheduledRecording
+ .getStartTimeMs())
+ / mScheduledRecording.getDuration()),
+ 100)));
} else if (recordingState == ScheduledRecording.STATE_RECORDING_FINISHED) {
cardView.setProgressBar(100);
} else {
@@ -95,9 +100,10 @@ class ScheduledRecordingPresenter extends DvrItemPresenter<ScheduledRecording> {
public ScheduledRecordingPresenter(Context context) {
super(context);
- mDvrManager = TvApplication.getSingletons(mContext).getDvrManager();
- mProgressBarColor = mContext.getResources()
- .getColor(R.color.play_controls_recording_icon_color_on_focus);
+ mDvrManager = TvSingletons.getSingletons(mContext).getDvrManager();
+ mProgressBarColor =
+ mContext.getResources()
+ .getColor(R.color.play_controls_recording_icon_color_on_focus);
}
@Override
@@ -106,33 +112,61 @@ class ScheduledRecordingPresenter extends DvrItemPresenter<ScheduledRecording> {
}
@Override
- public void onBindDvrItemViewHolder(DvrItemViewHolder baseHolder,
- ScheduledRecording recording) {
+ public void onBindDvrItemViewHolder(
+ DvrItemViewHolder baseHolder, ScheduledRecording recording) {
final ScheduledRecordingViewHolder viewHolder = (ScheduledRecordingViewHolder) baseHolder;
final RecordingCardView cardView = viewHolder.getView();
DetailsContent details = DetailsContent.createFromScheduledRecording(mContext, recording);
cardView.setTitle(details.getTitle());
cardView.setImageUri(details.getLogoImageUri(), details.isUsingChannelLogo());
- cardView.setAffiliatedIcon(mDvrManager.isConflicting(recording) ?
- R.drawable.ic_warning_white_32dp : 0);
+ if (mDvrManager.isConflicting(recording)) {
+ cardView.setAffiliatedIcon(R.drawable.ic_warning_white_32dp);
+ } else if (recording.getState() == ScheduledRecording.STATE_RECORDING_FAILED) {
+ cardView.setAffiliatedIcon(R.drawable.ic_error_white_48dp);
+ } else {
+ cardView.setAffiliatedIcon(0);
+ }
cardView.setContent(generateMajorContent(recording), null);
cardView.setDetailBackgroundImageUri(details.getBackgroundImageUri());
}
private String generateMajorContent(ScheduledRecording recording) {
- int dateDifference = Utils.computeDateDifference(System.currentTimeMillis(),
- recording.getStartTimeMs());
+ if (recording.getState() == ScheduledRecording.STATE_RECORDING_FAILED) {
+ return mContext.getString(R.string.dvr_recording_failed);
+ }
+ int dateDifference =
+ Utils.computeDateDifference(System.currentTimeMillis(), recording.getStartTimeMs());
if (dateDifference <= 0) {
- return mContext.getString(R.string.dvr_date_today_time,
- Utils.getDurationString(mContext, recording.getStartTimeMs(),
- recording.getEndTimeMs(), false, false, true, 0));
+ return mContext.getString(
+ R.string.dvr_date_today_time,
+ Utils.getDurationString(
+ mContext,
+ recording.getStartTimeMs(),
+ recording.getEndTimeMs(),
+ false,
+ false,
+ true,
+ 0));
} else if (dateDifference == 1) {
- return mContext.getString(R.string.dvr_date_tomorrow_time,
- Utils.getDurationString(mContext, recording.getStartTimeMs(),
- recording.getEndTimeMs(), false, false, true, 0));
+ return mContext.getString(
+ R.string.dvr_date_tomorrow_time,
+ Utils.getDurationString(
+ mContext,
+ recording.getStartTimeMs(),
+ recording.getEndTimeMs(),
+ false,
+ false,
+ true,
+ 0));
} else {
- return Utils.getDurationString(mContext, recording.getStartTimeMs(),
- recording.getStartTimeMs(), false, true, false, 0);
+ return Utils.getDurationString(
+ mContext,
+ recording.getStartTimeMs(),
+ recording.getStartTimeMs(),
+ false,
+ true,
+ false,
+ 0);
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java
index c2aa8e98..2cd191a7 100644
--- a/src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java
@@ -32,9 +32,8 @@ import android.support.v17.leanback.widget.OnActionClickedListener;
import android.support.v17.leanback.widget.PresenterSelector;
import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
import android.text.TextUtils;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.data.BaseProgram;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrWatchedPositionManager;
@@ -42,16 +41,13 @@ import com.android.tv.dvr.data.RecordedProgram;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.dvr.ui.DvrUiHelper;
import com.android.tv.dvr.ui.SortedArrayAdapter;
-
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-/**
- * {@link DetailsFragment} for series recording in DVR.
- */
-public class SeriesRecordingDetailsFragment extends DvrDetailsFragment implements
- DvrDataManager.SeriesRecordingListener, DvrDataManager.RecordedProgramListener {
+/** {@link DetailsFragment} for series recording in DVR. */
+public class SeriesRecordingDetailsFragment extends DvrDetailsFragment
+ implements DvrDataManager.SeriesRecordingListener, DvrDataManager.RecordedProgramListener {
private static final int ACTION_WATCH = 1;
private static final int ACTION_SERIES_SCHEDULES = 2;
private static final int ACTION_DELETE = 3;
@@ -77,7 +73,7 @@ public class SeriesRecordingDetailsFragment extends DvrDetailsFragment implement
@Override
public void onCreate(Bundle savedInstanceState) {
- mDvrDataManager = TvApplication.getSingletons(getActivity()).getDvrDataManager();
+ mDvrDataManager = TvSingletons.getSingletons(getActivity()).getDvrDataManager();
mWatchLabel = getString(R.string.dvr_detail_watch);
mResumeLabel = getString(R.string.dvr_detail_series_resume);
mWatchDrawable = getResources().getDrawable(R.drawable.lb_ic_play, null);
@@ -87,8 +83,8 @@ public class SeriesRecordingDetailsFragment extends DvrDetailsFragment implement
@Override
protected void onCreateInternal() {
- mDvrWatchedPositionManager = TvApplication.getSingletons(getActivity())
- .getDvrWatchedPositionManager();
+ mDvrWatchedPositionManager =
+ TvSingletons.getSingletons(getActivity()).getDvrWatchedPositionManager();
setDetailsOverviewRow(DetailsContent.createFromSeriesRecording(getContext(), mSeries));
setupRecordedProgramsRow();
mDvrDataManager.addSeriesRecordingListener(this);
@@ -119,27 +115,31 @@ public class SeriesRecordingDetailsFragment extends DvrDetailsFragment implement
mActionsAdapter.clear(ACTION_WATCH);
} else {
String episodeStatus;
- if(mDvrWatchedPositionManager.getWatchedStatus(mRecommendRecordedProgram)
+ if (mDvrWatchedPositionManager.getWatchedStatus(mRecommendRecordedProgram)
== DvrWatchedPositionManager.DVR_WATCHED_STATUS_WATCHING) {
episodeStatus = mResumeLabel;
- mInitialPlaybackPositionMs = mDvrWatchedPositionManager
- .getWatchedPosition(mRecommendRecordedProgram.getId());
+ mInitialPlaybackPositionMs =
+ mDvrWatchedPositionManager.getWatchedPosition(
+ mRecommendRecordedProgram.getId());
} else {
episodeStatus = mWatchLabel;
mInitialPlaybackPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
}
- String episodeDisplayNumber = mRecommendRecordedProgram.getEpisodeDisplayNumber(
- getContext());
- mActionsAdapter.set(ACTION_WATCH, new Action(ACTION_WATCH,
- episodeStatus, episodeDisplayNumber, mWatchDrawable));
+ String episodeDisplayNumber =
+ mRecommendRecordedProgram.getEpisodeDisplayNumber(getContext());
+ mActionsAdapter.set(
+ ACTION_WATCH,
+ new Action(ACTION_WATCH, episodeStatus, episodeDisplayNumber, mWatchDrawable));
}
}
@Override
protected boolean onLoadRecordingDetails(Bundle args) {
long recordId = args.getLong(DvrDetailsActivity.RECORDING_ID);
- mSeries = TvApplication.getSingletons(getActivity()).getDvrDataManager()
- .getSeriesRecording(recordId);
+ mSeries =
+ TvSingletons.getSingletons(getActivity())
+ .getDvrDataManager()
+ .getSeriesRecording(recordId);
if (mSeries == null) {
return false;
}
@@ -162,12 +162,19 @@ public class SeriesRecordingDetailsFragment extends DvrDetailsFragment implement
mActionsAdapter = new SparseArrayObjectAdapter(new ActionPresenterSelector());
Resources res = getResources();
updateWatchAction();
- mActionsAdapter.set(ACTION_SERIES_SCHEDULES, new Action(ACTION_SERIES_SCHEDULES,
- getString(R.string.dvr_detail_view_schedule), null,
- res.getDrawable(R.drawable.ic_schedule_32dp, null)));
- mDeleteAction = new Action(ACTION_DELETE,
- getString(R.string.dvr_detail_series_delete), null,
- res.getDrawable(R.drawable.ic_delete_32dp, null));
+ mActionsAdapter.set(
+ ACTION_SERIES_SCHEDULES,
+ new Action(
+ ACTION_SERIES_SCHEDULES,
+ getString(R.string.dvr_detail_view_schedule),
+ null,
+ res.getDrawable(R.drawable.ic_schedule_32dp, null)));
+ mDeleteAction =
+ new Action(
+ ACTION_DELETE,
+ getString(R.string.dvr_detail_series_delete),
+ null,
+ res.getDrawable(R.drawable.ic_delete_32dp, null));
if (!mRecordedPrograms.isEmpty()) {
mActionsAdapter.set(ACTION_DELETE, mDeleteAction);
}
@@ -207,11 +214,9 @@ public class SeriesRecordingDetailsFragment extends DvrDetailsFragment implement
};
}
- /**
- * The programs are sorted by season number and episode number.
- */
+ /** The programs are sorted by season number and episode number. */
private RecordedProgram getRecommendProgram(List<RecordedProgram> programs) {
- for (int i = programs.size() - 1 ; i >= 0 ; i--) {
+ for (int i = programs.size() - 1; i >= 0; i--) {
RecordedProgram program = programs.get(i);
int watchedStatus = mDvrWatchedPositionManager.getWatchedStatus(program);
if (watchedStatus == DvrWatchedPositionManager.DVR_WATCHED_STATUS_NEW) {
@@ -230,7 +235,7 @@ public class SeriesRecordingDetailsFragment extends DvrDetailsFragment implement
}
@Override
- public void onSeriesRecordingAdded(SeriesRecording... seriesRecordings) { }
+ public void onSeriesRecordingAdded(SeriesRecording... seriesRecordings) {}
@Override
public void onSeriesRecordingChanged(SeriesRecording... seriesRecordings) {
@@ -308,8 +313,10 @@ public class SeriesRecordingDetailsFragment extends DvrDetailsFragment implement
for (int i = rowsAdaptor.size() - 1; i >= 0; i--) {
Object row = rowsAdaptor.get(i);
if (row instanceof ListRow) {
- int compareResult = BaseProgram.numberCompare(seasonNumber,
- ((SeasonRowAdapter) ((ListRow) row).getAdapter()).mSeasonNumber);
+ int compareResult =
+ BaseProgram.numberCompare(
+ seasonNumber,
+ ((SeasonRowAdapter) ((ListRow) row).getAdapter()).mSeasonNumber);
if (compareResult == 0) {
return (ListRow) row;
} else if (compareResult < 0) {
@@ -321,18 +328,25 @@ public class SeriesRecordingDetailsFragment extends DvrDetailsFragment implement
}
private ListRow createNewSeasonRow(String seasonNumber, int position) {
- String seasonTitle = seasonNumber.isEmpty() ? mSeries.getTitle()
- : getString(R.string.dvr_detail_series_season_title, seasonNumber);
+ String seasonTitle =
+ seasonNumber.isEmpty()
+ ? mSeries.getTitle()
+ : getString(R.string.dvr_detail_series_season_title, seasonNumber);
HeaderItem header = new HeaderItem(mSeasonRowCount++, seasonTitle);
ClassPresenterSelector selector = new ClassPresenterSelector();
selector.addClassPresenter(RecordedProgram.class, mRecordedProgramPresenter);
- ListRow row = new ListRow(header, new SeasonRowAdapter(selector,
- new Comparator<RecordedProgram>() {
- @Override
- public int compare(RecordedProgram lhs, RecordedProgram rhs) {
- return BaseProgram.EPISODE_COMPARATOR.compare(lhs, rhs);
- }
- }, seasonNumber));
+ ListRow row =
+ new ListRow(
+ header,
+ new SeasonRowAdapter(
+ selector,
+ new Comparator<RecordedProgram>() {
+ @Override
+ public int compare(RecordedProgram lhs, RecordedProgram rhs) {
+ return BaseProgram.EPISODE_COMPARATOR.compare(lhs, rhs);
+ }
+ },
+ seasonNumber));
getRowsAdapter().add(position, row);
return row;
}
@@ -340,7 +354,9 @@ public class SeriesRecordingDetailsFragment extends DvrDetailsFragment implement
private class SeasonRowAdapter extends SortedArrayAdapter<RecordedProgram> {
private String mSeasonNumber;
- SeasonRowAdapter(PresenterSelector selector, Comparator<RecordedProgram> comparator,
+ SeasonRowAdapter(
+ PresenterSelector selector,
+ Comparator<RecordedProgram> comparator,
String seasonNumber) {
super(selector, comparator);
mSeasonNumber = seasonNumber;
@@ -351,4 +367,4 @@ public class SeriesRecordingDetailsFragment extends DvrDetailsFragment implement
return program.getId();
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/browse/SeriesRecordingPresenter.java b/src/com/android/tv/dvr/ui/browse/SeriesRecordingPresenter.java
index e508259d..14f9dceb 100644
--- a/src/com/android/tv/dvr/ui/browse/SeriesRecordingPresenter.java
+++ b/src/com/android/tv/dvr/ui/browse/SeriesRecordingPresenter.java
@@ -19,10 +19,8 @@ package com.android.tv.dvr.ui.browse;
import android.content.Context;
import android.media.tv.TvInputManager;
import android.text.TextUtils;
-
-import com.android.tv.ApplicationSingletons;
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrDataManager.RecordedProgramListener;
import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
@@ -32,27 +30,29 @@ import com.android.tv.dvr.DvrWatchedPositionManager.WatchedPositionChangedListen
import com.android.tv.dvr.data.RecordedProgram;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.SeriesRecording;
-
import java.util.List;
-/**
- * Presents a {@link SeriesRecording} in {@link DvrBrowseFragment}.
- */
+/** Presents a {@link SeriesRecording} in {@link DvrBrowseFragment}. */
class SeriesRecordingPresenter extends DvrItemPresenter<SeriesRecording> {
private final DvrDataManager mDvrDataManager;
private final DvrManager mDvrManager;
private final DvrWatchedPositionManager mWatchedPositionManager;
- private final class SeriesRecordingViewHolder extends DvrItemViewHolder implements
- WatchedPositionChangedListener, ScheduledRecordingListener, RecordedProgramListener {
+ private final class SeriesRecordingViewHolder extends DvrItemViewHolder
+ implements WatchedPositionChangedListener,
+ ScheduledRecordingListener,
+ RecordedProgramListener {
private SeriesRecording mSeriesRecording;
private RecordingCardView mCardView;
private DvrDataManager mDvrDataManager;
private DvrManager mDvrManager;
private DvrWatchedPositionManager mWatchedPositionManager;
- SeriesRecordingViewHolder(RecordingCardView view, DvrDataManager dvrDataManager,
- DvrManager dvrManager, DvrWatchedPositionManager watchedPositionManager) {
+ SeriesRecordingViewHolder(
+ RecordingCardView view,
+ DvrDataManager dvrDataManager,
+ DvrManager dvrManager,
+ DvrWatchedPositionManager watchedPositionManager) {
super(view);
mCardView = view;
mDvrDataManager = dvrDataManager;
@@ -92,8 +92,8 @@ class SeriesRecordingPresenter extends DvrItemPresenter<SeriesRecording> {
public void onRecordedProgramsAdded(RecordedProgram... recordedPrograms) {
boolean needToUpdateCardView = false;
for (RecordedProgram recordedProgram : recordedPrograms) {
- if (TextUtils.equals(recordedProgram.getSeriesId(),
- mSeriesRecording.getSeriesId())) {
+ if (TextUtils.equals(
+ recordedProgram.getSeriesId(), mSeriesRecording.getSeriesId())) {
mDvrDataManager.removeScheduledRecordingListener(this);
mWatchedPositionManager.addListener(this, recordedProgram.getId());
needToUpdateCardView = true;
@@ -108,8 +108,8 @@ class SeriesRecordingPresenter extends DvrItemPresenter<SeriesRecording> {
public void onRecordedProgramsRemoved(RecordedProgram... recordedPrograms) {
boolean needToUpdateCardView = false;
for (RecordedProgram recordedProgram : recordedPrograms) {
- if (TextUtils.equals(recordedProgram.getSeriesId(),
- mSeriesRecording.getSeriesId())) {
+ if (TextUtils.equals(
+ recordedProgram.getSeriesId(), mSeriesRecording.getSeriesId())) {
if (mWatchedPositionManager.getWatchedPosition(recordedProgram.getId())
== TvInputManager.TIME_SHIFT_INVALID_TIME) {
mWatchedPositionManager.removeListener(this, recordedProgram.getId());
@@ -177,14 +177,15 @@ class SeriesRecordingPresenter extends DvrItemPresenter<SeriesRecording> {
quantityStringID = R.plurals.dvr_count_new_recordings;
}
}
- mCardView.setContent(mCardView.getResources()
- .getQuantityString(quantityStringID, count, count), null);
+ mCardView.setContent(
+ mCardView.getResources().getQuantityString(quantityStringID, count, count),
+ null);
}
}
public SeriesRecordingPresenter(Context context) {
super(context);
- ApplicationSingletons singletons = TvApplication.getSingletons(context);
+ TvSingletons singletons = TvSingletons.getSingletons(context);
mDvrDataManager = singletons.getDvrDataManager();
mDvrManager = singletons.getDvrManager();
mWatchedPositionManager = singletons.getDvrWatchedPositionManager();
@@ -192,8 +193,11 @@ class SeriesRecordingPresenter extends DvrItemPresenter<SeriesRecording> {
@Override
public DvrItemViewHolder onCreateDvrItemViewHolder() {
- return new SeriesRecordingViewHolder(new RecordingCardView(mContext), mDvrDataManager,
- mDvrManager, mWatchedPositionManager);
+ return new SeriesRecordingViewHolder(
+ new RecordingCardView(mContext),
+ mDvrDataManager,
+ mDvrManager,
+ mWatchedPositionManager);
}
@Override
diff --git a/src/com/android/tv/dvr/ui/list/BaseDvrSchedulesFragment.java b/src/com/android/tv/dvr/ui/list/BaseDvrSchedulesFragment.java
index b9407b15..77a63508 100644
--- a/src/com/android/tv/dvr/ui/list/BaseDvrSchedulesFragment.java
+++ b/src/com/android/tv/dvr/ui/list/BaseDvrSchedulesFragment.java
@@ -1,18 +1,18 @@
/*
-* Copyright (C) 2016 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
-*/
+ * Copyright (C) 2016 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.dvr.ui.list;
@@ -23,23 +23,17 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
-
-import com.android.tv.ApplicationSingletons;
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrScheduleManager;
import com.android.tv.dvr.data.ScheduledRecording;
-/**
- * A base fragment to show the list of schedule recordings.
- */
+/** A base fragment to show the list of schedule recordings. */
public abstract class BaseDvrSchedulesFragment extends DetailsFragment
implements DvrDataManager.ScheduledRecordingListener,
- DvrScheduleManager.OnConflictStateChangeListener {
- /**
- * The key for scheduled recording which has be selected in the list.
- */
+ DvrScheduleManager.OnConflictStateChangeListener {
+ /** The key for scheduled recording which has be selected in the list. */
public static final String SCHEDULES_KEY_SCHEDULED_RECORDING =
"schedules_key_scheduled_recording";
@@ -55,15 +49,15 @@ public abstract class BaseDvrSchedulesFragment extends DetailsFragment
mRowsAdapter = onCreateRowsAdapter(presenterSelector);
setAdapter(mRowsAdapter);
mRowsAdapter.start();
- ApplicationSingletons singletons = TvApplication.getSingletons(getContext());
+ TvSingletons singletons = TvSingletons.getSingletons(getContext());
singletons.getDvrDataManager().addScheduledRecordingListener(this);
singletons.getDvrScheduleManager().addOnConflictStateChangeListener(this);
mEmptyInfoScreenView = (TextView) getActivity().findViewById(R.id.empty_info_screen);
}
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
+ public View onCreateView(
+ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
int firstItemPosition = getFirstItemPosition();
if (firstItemPosition != -1) {
@@ -72,16 +66,12 @@ public abstract class BaseDvrSchedulesFragment extends DetailsFragment
return view;
}
- /**
- * Returns rows adapter.
- */
+ /** Returns rows adapter. */
protected ScheduleRowAdapter getRowsAdapter() {
return mRowsAdapter;
}
- /**
- * Shows the empty message.
- */
+ /** Shows the empty message. */
void showEmptyMessage(int messageId) {
mEmptyInfoScreenView.setText(messageId);
if (mEmptyInfoScreenView.getVisibility() != View.VISIBLE) {
@@ -89,9 +79,7 @@ public abstract class BaseDvrSchedulesFragment extends DetailsFragment
}
}
- /**
- * Hides the empty message.
- */
+ /** Hides the empty message. */
void hideEmptyMessage() {
if (mEmptyInfoScreenView.getVisibility() == View.VISIBLE) {
mEmptyInfoScreenView.setVisibility(View.GONE);
@@ -99,39 +87,32 @@ public abstract class BaseDvrSchedulesFragment extends DetailsFragment
}
@Override
- public View onInflateTitleView(LayoutInflater inflater, ViewGroup parent,
- Bundle savedInstanceState) {
+ public View onInflateTitleView(
+ LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
// Workaround of b/31046014
return null;
}
@Override
public void onDestroy() {
- ApplicationSingletons singletons = TvApplication.getSingletons(getContext());
+ TvSingletons singletons = TvSingletons.getSingletons(getContext());
singletons.getDvrScheduleManager().removeOnConflictStateChangeListener(this);
singletons.getDvrDataManager().removeScheduledRecordingListener(this);
mRowsAdapter.stop();
super.onDestroy();
}
- /**
- * Creates header row presenter.
- */
+ /** Creates header row presenter. */
public abstract SchedulesHeaderRowPresenter onCreateHeaderRowPresenter();
- /**
- * Creates rows presenter.
- */
+ /** Creates rows presenter. */
public abstract ScheduleRowPresenter onCreateRowPresenter();
- /**
- * Creates rows adapter.
- */
- public abstract ScheduleRowAdapter onCreateRowsAdapter(ClassPresenterSelector presenterSelecor);
+ /** Creates rows adapter. */
+ public abstract ScheduleRowAdapter onCreateRowsAdapter(
+ ClassPresenterSelector presenterSelector);
- /**
- * Gets the first focus position in schedules list.
- */
+ /** Gets the first focus position in schedules list. */
protected int getFirstItemPosition() {
for (int i = 0; i < mRowsAdapter.size(); i++) {
if (mRowsAdapter.get(i) instanceof ScheduleRow) {
@@ -176,4 +157,4 @@ public abstract class BaseDvrSchedulesFragment extends DetailsFragment
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/list/DvrHistoryActivity.java b/src/com/android/tv/dvr/ui/list/DvrHistoryActivity.java
new file mode 100644
index 00000000..623975e1
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/list/DvrHistoryActivity.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 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.dvr.ui.list;
+
+import android.app.Activity;
+import android.os.Bundle;
+import com.android.tv.R;
+import com.android.tv.Starter;
+
+/** Activity to show the recording history. */
+public class DvrHistoryActivity extends Activity {
+
+ @Override
+ public void onCreate(final Bundle savedInstanceState) {
+ Starter.start(this);
+ // Pass null to prevent automatically re-creating fragments
+ super.onCreate(null);
+ setContentView(R.layout.activity_dvr_history);
+ DvrHistoryFragment dvrHistoryFragment = new DvrHistoryFragment();
+ getFragmentManager()
+ .beginTransaction()
+ .add(R.id.fragment_container, dvrHistoryFragment)
+ .commit();
+ }
+}
diff --git a/src/com/android/tv/dvr/ui/list/DvrHistoryFragment.java b/src/com/android/tv/dvr/ui/list/DvrHistoryFragment.java
new file mode 100644
index 00000000..0ca05fac
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/list/DvrHistoryFragment.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2018 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.dvr.ui.list;
+
+import android.os.Bundle;
+import android.support.v17.leanback.app.DetailsFragment;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import com.android.tv.R;
+import com.android.tv.TvSingletons;
+import com.android.tv.dvr.DvrDataManager;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.ui.list.SchedulesHeaderRowPresenter.DateHeaderRowPresenter;
+
+/** A fragment to show the DVR history. */
+public class DvrHistoryFragment extends DetailsFragment
+ implements DvrDataManager.ScheduledRecordingListener,
+ DvrDataManager.RecordedProgramListener {
+
+ private DvrHistoryRowAdapter mRowsAdapter;
+ private TextView mEmptyInfoScreenView;
+ private DvrDataManager mDvrDataManager;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ClassPresenterSelector presenterSelector = new ClassPresenterSelector();
+ presenterSelector.addClassPresenter(
+ SchedulesHeaderRow.class, new DateHeaderRowPresenter(getContext()));
+ presenterSelector.addClassPresenter(
+ ScheduleRow.class, new ScheduleRowPresenter(getContext()));
+ TvSingletons singletons = TvSingletons.getSingletons(getContext());
+ mRowsAdapter = new DvrHistoryRowAdapter(
+ getContext(), presenterSelector, singletons.getClock());
+ setAdapter(mRowsAdapter);
+ mRowsAdapter.start();
+ mDvrDataManager = singletons.getDvrDataManager();
+ mDvrDataManager.addScheduledRecordingListener(this);
+ mDvrDataManager.addRecordedProgramListener(this);
+ mEmptyInfoScreenView = (TextView) getActivity().findViewById(R.id.empty_info_screen);
+ }
+
+ @Override
+ public void onDestroy() {
+ mDvrDataManager.removeScheduledRecordingListener(this);
+ mDvrDataManager.removeRecordedProgramListener(this);
+ super.onDestroy();
+ }
+
+ /** Shows the empty message. */
+ void showEmptyMessage() {
+ mEmptyInfoScreenView.setText(R.string.dvr_history_empty_state);
+ if (mEmptyInfoScreenView.getVisibility() != View.VISIBLE) {
+ mEmptyInfoScreenView.setVisibility(View.VISIBLE);
+ }
+ }
+
+ /** Hides the empty message. */
+ void hideEmptyMessage() {
+ if (mEmptyInfoScreenView.getVisibility() == View.VISIBLE) {
+ mEmptyInfoScreenView.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public View onInflateTitleView(
+ LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
+ // Workaround of b/31046014
+ return null;
+ }
+
+ @Override
+ public void onScheduledRecordingAdded(ScheduledRecording... scheduledRecordings) {
+ if (mRowsAdapter != null) {
+ for (ScheduledRecording recording : scheduledRecordings) {
+ mRowsAdapter.onScheduledRecordingAdded(recording);
+ }
+ if (mRowsAdapter.size() > 0) {
+ hideEmptyMessage();
+ }
+ }
+ }
+
+ @Override
+ public void onScheduledRecordingRemoved(ScheduledRecording... scheduledRecordings) {
+ if (mRowsAdapter != null) {
+ for (ScheduledRecording recording : scheduledRecordings) {
+ mRowsAdapter.onScheduledRecordingRemoved(recording);
+ }
+ if (mRowsAdapter.size() == 0) {
+ showEmptyMessage();
+ }
+ }
+ }
+
+ @Override
+ public void onScheduledRecordingStatusChanged(ScheduledRecording... scheduledRecordings) {
+ if (mRowsAdapter != null) {
+ for (ScheduledRecording recording : scheduledRecordings) {
+ mRowsAdapter.onScheduledRecordingUpdated(recording);
+ }
+ if (mRowsAdapter.size() == 0) {
+ showEmptyMessage();
+ } else {
+ hideEmptyMessage();
+ }
+ }
+ }
+
+ @Override
+ public void onRecordedProgramsAdded(RecordedProgram... recordedPrograms) {
+ if (mRowsAdapter != null) {
+ for (RecordedProgram p : recordedPrograms) {
+ mRowsAdapter.onScheduledRecordingAdded(p);
+ }
+ if (mRowsAdapter.size() > 0) {
+ hideEmptyMessage();
+ }
+ }
+
+ }
+
+ @Override
+ public void onRecordedProgramsChanged(RecordedProgram... recordedPrograms) {
+ if (mRowsAdapter != null) {
+ for (RecordedProgram program : recordedPrograms) {
+ mRowsAdapter.onScheduledRecordingUpdated(program);
+ }
+ if (mRowsAdapter.size() == 0) {
+ showEmptyMessage();
+ } else {
+ hideEmptyMessage();
+ }
+ }
+ }
+
+ @Override
+ public void onRecordedProgramsRemoved(RecordedProgram... recordedPrograms) {
+ if (mRowsAdapter != null) {
+ for (RecordedProgram p : recordedPrograms) {
+ mRowsAdapter.onScheduledRecordingRemoved(p);
+ }
+ if (mRowsAdapter.size() == 0) {
+ showEmptyMessage();
+ }
+ }
+ }
+}
diff --git a/src/com/android/tv/dvr/ui/list/DvrHistoryRowAdapter.java b/src/com/android/tv/dvr/ui/list/DvrHistoryRowAdapter.java
new file mode 100644
index 00000000..156d1a7e
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/list/DvrHistoryRowAdapter.java
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2018 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.dvr.ui.list;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.os.Build.VERSION_CODES;
+import android.support.annotation.Nullable;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
+import android.text.format.DateUtils;
+import android.util.Log;
+import com.android.tv.R;
+import com.android.tv.TvSingletons;
+import com.android.tv.common.SoftPreconditions;
+import com.android.tv.common.util.Clock;
+import com.android.tv.dvr.DvrDataManager;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.recorder.ScheduledProgramReaper;
+import com.android.tv.dvr.ui.list.SchedulesHeaderRow.DateHeaderRow;
+import com.android.tv.util.Utils;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/** An adapter for DVR history. */
+@TargetApi(VERSION_CODES.N)
+@SuppressWarnings("AndroidApiChecker") // TODO(b/32513850) remove when error prone is updated
+class DvrHistoryRowAdapter extends ArrayObjectAdapter {
+ private static final String TAG = "DvrHistoryRowAdapter";
+ private static final boolean DEBUG = false;
+
+ private static final long ONE_DAY_MS = TimeUnit.DAYS.toMillis(1);
+ private static final int MAX_HISTORY_DAYS = ScheduledProgramReaper.DAYS;
+
+ private final Context mContext;
+ private final Clock mClock;
+ private final DvrDataManager mDvrDataManager;
+ private final List<String> mTitles = new ArrayList<>();
+ private final Map<Long, ScheduledRecording> mRecordedProgramScheduleMap = new HashMap<>();
+
+ public DvrHistoryRowAdapter(
+ Context context, ClassPresenterSelector classPresenterSelector, Clock clock) {
+ super(classPresenterSelector);
+ mContext = context;
+ mClock = clock;
+ mDvrDataManager = TvSingletons.getSingletons(mContext).getDvrDataManager();
+ mTitles.add(mContext.getString(R.string.dvr_date_today));
+ mTitles.add(mContext.getString(R.string.dvr_date_yesterday));
+ }
+
+ /** Returns context. */
+ protected Context getContext() {
+ return mContext;
+ }
+
+ /** Starts row adapter. */
+ public void start() {
+ clear();
+ List<ScheduledRecording> recordingList = mDvrDataManager.getFailedScheduledRecordings();
+ List<RecordedProgram> recordedProgramList = mDvrDataManager.getRecordedPrograms();
+
+ recordingList.addAll(
+ recordedProgramsToScheduledRecordings(recordedProgramList, MAX_HISTORY_DAYS));
+ recordingList
+ .sort(ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR.reversed());
+ long deadLine = Utils.getFirstMillisecondOfDay(mClock.currentTimeMillis());
+ for (int i = 0; i < recordingList.size(); ) {
+ ArrayList<ScheduledRecording> section = new ArrayList<>();
+ while (i < recordingList.size() && recordingList.get(i).getStartTimeMs() >= deadLine) {
+ section.add(recordingList.get(i++));
+ }
+ if (!section.isEmpty()) {
+ SchedulesHeaderRow headerRow =
+ new DateHeaderRow(
+ calculateHeaderDate(deadLine),
+ mContext.getResources()
+ .getQuantityString(
+ R.plurals.dvr_schedules_section_subtitle,
+ section.size(),
+ section.size()),
+ section.size(),
+ deadLine);
+ add(headerRow);
+ for (ScheduledRecording recording : section) {
+ add(new ScheduleRow(recording, headerRow));
+ }
+ }
+ deadLine -= ONE_DAY_MS;
+ }
+ }
+
+ private String calculateHeaderDate(long timeMs) {
+ int titleIndex =
+ (int)
+ ((Utils.getFirstMillisecondOfDay(mClock.currentTimeMillis()) - timeMs)
+ / ONE_DAY_MS);
+ String headerDate;
+ if (titleIndex < mTitles.size()) {
+ headerDate = mTitles.get(titleIndex);
+ } else {
+ headerDate =
+ DateUtils.formatDateTime(
+ getContext(),
+ timeMs,
+ DateUtils.FORMAT_SHOW_WEEKDAY
+ | DateUtils.FORMAT_SHOW_DATE
+ | DateUtils.FORMAT_ABBREV_MONTH);
+ }
+ return headerDate;
+ }
+
+ private List<ScheduledRecording> recordedProgramsToScheduledRecordings(
+ List<RecordedProgram> programs, int maxDays) {
+ List<ScheduledRecording> result = new ArrayList<>();
+ for (RecordedProgram recordedProgram : programs) {
+ ScheduledRecording scheduledRecording =
+ recordedProgramsToScheduledRecordings(recordedProgram, maxDays);
+ if (scheduledRecording != null) {
+ result.add(scheduledRecording);
+ }
+ }
+ return result;
+ }
+
+ @Nullable
+ private ScheduledRecording recordedProgramsToScheduledRecordings(
+ RecordedProgram program, int maxDays) {
+ long firstMillisecondToday = Utils.getFirstMillisecondOfDay(mClock.currentTimeMillis());
+ if (maxDays
+ < Utils.computeDateDifference(
+ program.getStartTimeUtcMillis(),
+ firstMillisecondToday)) {
+ return null;
+ }
+ ScheduledRecording scheduledRecording = ScheduledRecording.builder(program).build();
+ mRecordedProgramScheduleMap.put(program.getId(), scheduledRecording);
+ return scheduledRecording;
+ }
+
+ public void onScheduledRecordingAdded(ScheduledRecording schedule) {
+ if (DEBUG) {
+ Log.d(TAG, "onScheduledRecordingAdded: " + schedule);
+ }
+ if (findRowByScheduledRecording(schedule) == null
+ && (schedule.getState() == ScheduledRecording.STATE_RECORDING_FINISHED
+ || schedule.getState() == ScheduledRecording.STATE_RECORDING_CLIPPED
+ || schedule.getState() == ScheduledRecording.STATE_RECORDING_FAILED)) {
+ addScheduleRow(schedule);
+ }
+ }
+
+ public void onScheduledRecordingAdded(RecordedProgram program) {
+ if (DEBUG) {
+ Log.d(TAG, "onScheduledRecordingAdded: " + program);
+ }
+ if (mRecordedProgramScheduleMap.get(program.getId()) != null) {
+ return;
+ }
+ ScheduledRecording schedule =
+ recordedProgramsToScheduledRecordings(program, MAX_HISTORY_DAYS);
+ if (schedule == null) {
+ return;
+ }
+ addScheduleRow(schedule);
+ }
+
+ public void onScheduledRecordingRemoved(ScheduledRecording schedule) {
+ if (DEBUG) {
+ Log.d(TAG, "onScheduledRecordingRemoved: " + schedule);
+ }
+ ScheduleRow row = findRowByScheduledRecording(schedule);
+ if (row != null) {
+ removeScheduleRow(row);
+ notifyArrayItemRangeChanged(indexOf(row), 1);
+ }
+ }
+
+ public void onScheduledRecordingRemoved(RecordedProgram program) {
+ if (DEBUG) {
+ Log.d(TAG, "onScheduledRecordingRemoved: " + program);
+ }
+ ScheduledRecording scheduledRecording = mRecordedProgramScheduleMap.get(program.getId());
+ if (scheduledRecording != null) {
+ mRecordedProgramScheduleMap.remove(program.getId());
+ ScheduleRow row = findRowByRecordedProgram(program);
+ if (row != null) {
+ removeScheduleRow(row);
+ notifyArrayItemRangeChanged(indexOf(row), 1);
+ }
+ }
+ }
+
+ public void onScheduledRecordingUpdated(ScheduledRecording schedule) {
+ if (DEBUG) {
+ Log.d(TAG, "onScheduledRecordingUpdated: " + schedule);
+ }
+ ScheduleRow row = findRowByScheduledRecording(schedule);
+ if (row != null) {
+ row.setSchedule(schedule);
+ if (schedule.getState() != ScheduledRecording.STATE_RECORDING_FAILED) {
+ // Only handle failed schedules. Finished schedules are handled as recorded programs
+ removeScheduleRow(row);
+ }
+ notifyArrayItemRangeChanged(indexOf(row), 1);
+ }
+ }
+
+ public void onScheduledRecordingUpdated(RecordedProgram program) {
+ if (DEBUG) {
+ Log.d(TAG, "onScheduledRecordingUpdated: " + program);
+ }
+ ScheduleRow row = findRowByRecordedProgram(program);
+ if (row != null) {
+ removeScheduleRow(row);
+ notifyArrayItemRangeChanged(indexOf(row), 1);
+ ScheduledRecording schedule = mRecordedProgramScheduleMap.get(program.getId());
+ if (schedule != null) {
+ mRecordedProgramScheduleMap.remove(program.getId());
+ }
+ }
+ onScheduledRecordingAdded(program);
+ }
+
+ private void addScheduleRow(ScheduledRecording recording) {
+ // This method must not be called from inherited class.
+ SoftPreconditions.checkState(getClass().equals(DvrHistoryRowAdapter.class));
+ if (recording != null) {
+ int pre = -1;
+ int index = 0;
+ for (; index < size(); index++) {
+ if (get(index) instanceof ScheduleRow) {
+ ScheduleRow scheduleRow = (ScheduleRow) get(index);
+ if (ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR.reversed()
+ .compare(scheduleRow.getSchedule(), recording) > 0) {
+ break;
+ }
+ pre = index;
+ }
+ }
+ long deadLine = Utils.getFirstMillisecondOfDay(recording.getStartTimeMs());
+ if (pre >= 0 && getHeaderRow(pre).getDeadLineMs() == deadLine) {
+ SchedulesHeaderRow headerRow = ((ScheduleRow) get(pre)).getHeaderRow();
+ headerRow.setItemCount(headerRow.getItemCount() + 1);
+ ScheduleRow addedRow = new ScheduleRow(recording, headerRow);
+ add(++pre, addedRow);
+ updateHeaderDescription(headerRow);
+ } else if (index < size() && getHeaderRow(index).getDeadLineMs() == deadLine) {
+ SchedulesHeaderRow headerRow = ((ScheduleRow) get(index)).getHeaderRow();
+ headerRow.setItemCount(headerRow.getItemCount() + 1);
+ ScheduleRow addedRow = new ScheduleRow(recording, headerRow);
+ add(index, addedRow);
+ updateHeaderDescription(headerRow);
+ } else {
+ SchedulesHeaderRow headerRow =
+ new DateHeaderRow(
+ calculateHeaderDate(deadLine),
+ mContext.getResources()
+ .getQuantityString(
+ R.plurals.dvr_schedules_section_subtitle, 1, 1),
+ 1,
+ deadLine);
+ add(++pre, headerRow);
+ ScheduleRow addedRow = new ScheduleRow(recording, headerRow);
+ add(pre, addedRow);
+ }
+ }
+ }
+
+ private DateHeaderRow getHeaderRow(int index) {
+ return ((DateHeaderRow) ((ScheduleRow) get(index)).getHeaderRow());
+ }
+
+ /** Gets which {@link ScheduleRow} the {@link ScheduledRecording} belongs to. */
+ private ScheduleRow findRowByScheduledRecording(ScheduledRecording recording) {
+ if (recording == null) {
+ return null;
+ }
+ for (int i = 0; i < size(); i++) {
+ Object item = get(i);
+ if (item instanceof ScheduleRow && ((ScheduleRow) item).getSchedule() != null) {
+ if (((ScheduleRow) item).getSchedule().getId() == recording.getId()) {
+ return (ScheduleRow) item;
+ }
+ }
+ }
+ return null;
+ }
+
+ private ScheduleRow findRowByRecordedProgram(RecordedProgram program) {
+ if (program == null) {
+ return null;
+ }
+ for (int i = 0; i < size(); i++) {
+ Object item = get(i);
+ if (item instanceof ScheduleRow) {
+ ScheduleRow row = (ScheduleRow) item;
+ if (row.hasRecordedProgram()
+ && row.getSchedule().getRecordedProgramId() == program.getId()) {
+ return (ScheduleRow) item;
+ }
+ }
+ }
+ return null;
+ }
+
+ private void removeScheduleRow(ScheduleRow scheduleRow) {
+ // This method must not be called from inherited class.
+ SoftPreconditions.checkState(getClass().equals(DvrHistoryRowAdapter.class));
+ if (scheduleRow != null) {
+ scheduleRow.setSchedule(null);
+ SchedulesHeaderRow headerRow = scheduleRow.getHeaderRow();
+ remove(scheduleRow);
+ // Changes the count information of header which the removed row belongs to.
+ if (headerRow != null) {
+ int currentCount = headerRow.getItemCount();
+ headerRow.setItemCount(--currentCount);
+ if (headerRow.getItemCount() == 0) {
+ remove(headerRow);
+ } else {
+ replace(indexOf(headerRow), headerRow);
+ updateHeaderDescription(headerRow);
+ }
+ }
+ }
+ }
+
+ private void updateHeaderDescription(SchedulesHeaderRow headerRow) {
+ headerRow.setDescription(
+ mContext.getResources()
+ .getQuantityString(
+ R.plurals.dvr_schedules_section_subtitle,
+ headerRow.getItemCount(),
+ headerRow.getItemCount()));
+ }
+}
diff --git a/src/com/android/tv/dvr/ui/list/DvrSchedulesActivity.java b/src/com/android/tv/dvr/ui/list/DvrSchedulesActivity.java
index a0410bb3..82b85630 100644
--- a/src/com/android/tv/dvr/ui/list/DvrSchedulesActivity.java
+++ b/src/com/android/tv/dvr/ui/list/DvrSchedulesActivity.java
@@ -20,23 +20,19 @@ import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.annotation.IntDef;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.Starter;
import com.android.tv.data.Program;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.dvr.provider.EpisodicProgramLoadTask;
import com.android.tv.dvr.recorder.SeriesRecordingScheduler;
import com.android.tv.dvr.ui.BigArguments;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.List;
-/**
- * Activity to show the list of recording schedules.
- */
+/** Activity to show the list of recording schedules. */
public class DvrSchedulesActivity extends Activity {
/**
* The key for the type of the schedules which will be listed in the list. The type of the value
@@ -47,9 +43,7 @@ public class DvrSchedulesActivity extends Activity {
@Retention(RetentionPolicy.SOURCE)
@IntDef({TYPE_FULL_SCHEDULE, TYPE_SERIES_SCHEDULE})
public @interface ScheduleListType {}
- /**
- * A type which means the activity will display the full scheduled recordings.
- */
+ /** A type which means the activity will display the full scheduled recordings. */
public static final int TYPE_FULL_SCHEDULE = 0;
/**
* A type which means the activity will display a scheduled recording list of a series
@@ -59,7 +53,7 @@ public class DvrSchedulesActivity extends Activity {
@Override
public void onCreate(final Bundle savedInstanceState) {
- TvApplication.setCurrentRunningProcess(this, true);
+ Starter.start(this);
// Pass null to prevent automatically re-creating fragments
super.onCreate(null);
setContentView(R.layout.activity_dvr_schedules);
@@ -67,20 +61,29 @@ public class DvrSchedulesActivity extends Activity {
if (scheduleType == TYPE_FULL_SCHEDULE) {
DvrSchedulesFragment schedulesFragment = new DvrSchedulesFragment();
schedulesFragment.setArguments(getIntent().getExtras());
- getFragmentManager().beginTransaction().add(
- R.id.fragment_container, schedulesFragment).commit();
+ getFragmentManager()
+ .beginTransaction()
+ .add(R.id.fragment_container, schedulesFragment)
+ .commit();
} else if (scheduleType == TYPE_SERIES_SCHEDULE) {
- if (BigArguments.getArgument(DvrSeriesSchedulesFragment
- .SERIES_SCHEDULES_KEY_SERIES_PROGRAMS) != null) {
+ if (BigArguments.getArgument(
+ DvrSeriesSchedulesFragment.SERIES_SCHEDULES_KEY_SERIES_PROGRAMS)
+ != null) {
// The programs will be passed to the DvrSeriesSchedulesFragment, so don't need
// to reset the BigArguments.
showDvrSeriesSchedulesFragment(getIntent().getExtras());
} else {
- final ProgressDialog dialog = ProgressDialog.show(this, null, getString(
- R.string.dvr_series_progress_message_reading_programs));
- SeriesRecording seriesRecording = getIntent().getExtras()
- .getParcelable(DvrSeriesSchedulesFragment
- .SERIES_SCHEDULES_KEY_SERIES_RECORDING);
+ final ProgressDialog dialog =
+ ProgressDialog.show(
+ this,
+ null,
+ getString(R.string.dvr_series_progress_message_reading_programs));
+ SeriesRecording seriesRecording =
+ getIntent()
+ .getExtras()
+ .getParcelable(
+ DvrSeriesSchedulesFragment
+ .SERIES_SCHEDULES_KEY_SERIES_RECORDING);
// To get programs faster, hold the update of the series schedules.
SeriesRecordingScheduler.getInstance(this).pauseUpdate();
new EpisodicProgramLoadTask(this, Collections.singletonList(seriesRecording)) {
@@ -110,7 +113,9 @@ public class DvrSchedulesActivity extends Activity {
private void showDvrSeriesSchedulesFragment(Bundle args) {
DvrSeriesSchedulesFragment schedulesFragment = new DvrSeriesSchedulesFragment();
schedulesFragment.setArguments(args);
- getFragmentManager().beginTransaction().add(
- R.id.fragment_container, schedulesFragment).commit();
+ getFragmentManager()
+ .beginTransaction()
+ .add(R.id.fragment_container, schedulesFragment)
+ .commit();
}
}
diff --git a/src/com/android/tv/dvr/ui/list/DvrSchedulesFocusView.java b/src/com/android/tv/dvr/ui/list/DvrSchedulesFocusView.java
index c906c62a..c86721e8 100644
--- a/src/com/android/tv/dvr/ui/list/DvrSchedulesFocusView.java
+++ b/src/com/android/tv/dvr/ui/list/DvrSchedulesFocusView.java
@@ -23,12 +23,9 @@ import android.graphics.RectF;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
-
import com.android.tv.R;
-/**
- * A view used for focus in schedules list.
- */
+/** A view used for focus in schedules list. */
public class DvrSchedulesFocusView extends View {
private final Paint mPaint;
private final RectF mRoundRectF = new RectF();
@@ -76,13 +73,11 @@ public class DvrSchedulesFocusView extends View {
private int getRoundRectRadius() {
if (TextUtils.equals(mViewTag, mHeaderFocusViewTag)) {
- return getResources().getDimensionPixelSize(
- R.dimen.dvr_schedules_header_selector_radius);
+ return getResources()
+ .getDimensionPixelSize(R.dimen.dvr_schedules_header_selector_radius);
} else if (TextUtils.equals(mViewTag, mItemFocusViewTag)) {
return getResources().getDimensionPixelSize(R.dimen.dvr_schedules_selector_radius);
}
return 0;
}
}
-
-
diff --git a/src/com/android/tv/dvr/ui/list/DvrSchedulesFragment.java b/src/com/android/tv/dvr/ui/list/DvrSchedulesFragment.java
index 3cbb500a..d97b61f4 100644
--- a/src/com/android/tv/dvr/ui/list/DvrSchedulesFragment.java
+++ b/src/com/android/tv/dvr/ui/list/DvrSchedulesFragment.java
@@ -18,14 +18,11 @@ package com.android.tv.dvr.ui.list;
import android.os.Bundle;
import android.support.v17.leanback.widget.ClassPresenterSelector;
-
import com.android.tv.R;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.ui.list.SchedulesHeaderRowPresenter.DateHeaderRowPresenter;
-/**
- * A fragment to show the list of schedule recordings.
- */
+/** A fragment to show the list of schedule recordings. */
public class DvrSchedulesFragment extends BaseDvrSchedulesFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -46,8 +43,8 @@ public class DvrSchedulesFragment extends BaseDvrSchedulesFragment {
}
@Override
- public ScheduleRowAdapter onCreateRowsAdapter(ClassPresenterSelector presenterSelecor) {
- return new ScheduleRowAdapter(getContext(), presenterSelecor);
+ public ScheduleRowAdapter onCreateRowsAdapter(ClassPresenterSelector presenterSelector) {
+ return new ScheduleRowAdapter(getContext(), presenterSelector);
}
@Override
@@ -73,11 +70,11 @@ public class DvrSchedulesFragment extends BaseDvrSchedulesFragment {
if (args != null) {
recording = args.getParcelable(SCHEDULES_KEY_SCHEDULED_RECORDING);
}
- final int selectedPostion = getRowsAdapter().indexOf(
- getRowsAdapter().findRowByScheduledRecording(recording));
+ final int selectedPostion =
+ getRowsAdapter().indexOf(getRowsAdapter().findRowByScheduledRecording(recording));
if (selectedPostion != -1) {
return selectedPostion;
}
return super.getFirstItemPosition();
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/list/DvrSeriesSchedulesFragment.java b/src/com/android/tv/dvr/ui/list/DvrSeriesSchedulesFragment.java
index 57e7a88f..d376e358 100644
--- a/src/com/android/tv/dvr/ui/list/DvrSeriesSchedulesFragment.java
+++ b/src/com/android/tv/dvr/ui/list/DvrSeriesSchedulesFragment.java
@@ -1,18 +1,18 @@
/*
-* Copyright (C) 2016 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
-*/
+ * Copyright (C) 2016 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.dvr.ui.list;
@@ -30,10 +30,8 @@ import android.transition.Fade;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
-import com.android.tv.ApplicationSingletons;
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.data.ChannelDataManager;
import com.android.tv.data.Program;
import com.android.tv.dvr.DvrDataManager;
@@ -41,25 +39,21 @@ import com.android.tv.dvr.DvrDataManager.SeriesRecordingListener;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.dvr.provider.EpisodicProgramLoadTask;
import com.android.tv.dvr.ui.BigArguments;
-
import java.util.Collections;
import java.util.List;
-/**
- * A fragment to show the list of series schedule recordings.
- */
+/** A fragment to show the list of series schedule recordings. */
@TargetApi(Build.VERSION_CODES.N)
public class DvrSeriesSchedulesFragment extends BaseDvrSchedulesFragment {
/**
- * The key for series recording whose scheduled recording list will be displayed.
- * Type: {@link SeriesRecording}
+ * The key for series recording whose scheduled recording list will be displayed. Type: {@link
+ * SeriesRecording}
*/
public static final String SERIES_SCHEDULES_KEY_SERIES_RECORDING =
"series_schedules_key_series_recording";
/**
- * The key for programs which belong to the series recording whose scheduled recording list
- * will be displayed.
- * Type: List<{@link Program}>
+ * The key for programs which belong to the series recording whose scheduled recording list will
+ * be displayed. Type: List<{@link Program}>
*/
public static final String SERIES_SCHEDULES_KEY_SERIES_PROGRAMS =
"series_schedules_key_series_programs";
@@ -73,7 +67,7 @@ public class DvrSeriesSchedulesFragment extends BaseDvrSchedulesFragment {
private final SeriesRecordingListener mSeriesRecordingListener =
new SeriesRecordingListener() {
@Override
- public void onSeriesRecordingAdded(SeriesRecording... seriesRecordings) { }
+ public void onSeriesRecordingAdded(SeriesRecording... seriesRecordings) {}
@Override
public void onSeriesRecordingRemoved(SeriesRecording... seriesRecordings) {
@@ -101,26 +95,28 @@ public class DvrSeriesSchedulesFragment extends BaseDvrSchedulesFragment {
};
private final Handler mHandler = new Handler(Looper.getMainLooper());
- private final ContentObserver mContentObserver = new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- super.onChange(selfChange, uri);
- executeProgramLoadingTask();
- }
- };
+ private final ContentObserver mContentObserver =
+ new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ executeProgramLoadingTask();
+ }
+ };
- private final ChannelDataManager.Listener mChannelListener = new ChannelDataManager.Listener() {
- @Override
- public void onLoadFinished() { }
+ private final ChannelDataManager.Listener mChannelListener =
+ new ChannelDataManager.Listener() {
+ @Override
+ public void onLoadFinished() {}
- @Override
- public void onChannelListUpdated() {
- executeProgramLoadingTask();
- }
+ @Override
+ public void onChannelListUpdated() {
+ executeProgramLoadingTask();
+ }
- @Override
- public void onChannelBrowsableChanged() { }
- };
+ @Override
+ public void onChannelBrowsableChanged() {}
+ };
public DvrSeriesSchedulesFragment() {
setEnterTransition(new Fade(Fade.IN));
@@ -132,8 +128,8 @@ public class DvrSeriesSchedulesFragment extends BaseDvrSchedulesFragment {
Bundle args = getArguments();
if (args != null) {
mSeriesRecording = args.getParcelable(SERIES_SCHEDULES_KEY_SERIES_RECORDING);
- mPrograms = (List<Program>) BigArguments.getArgument(
- SERIES_SCHEDULES_KEY_SERIES_PROGRAMS);
+ mPrograms =
+ (List<Program>) BigArguments.getArgument(SERIES_SCHEDULES_KEY_SERIES_PROGRAMS);
BigArguments.reset();
}
if (args == null || mPrograms == null) {
@@ -144,18 +140,19 @@ public class DvrSeriesSchedulesFragment extends BaseDvrSchedulesFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ApplicationSingletons singletons = TvApplication.getSingletons(getContext());
+ TvSingletons singletons = TvSingletons.getSingletons(getContext());
mChannelDataManager = singletons.getChannelDataManager();
mChannelDataManager.addListener(mChannelListener);
mDvrDataManager = singletons.getDvrDataManager();
mDvrDataManager.addSeriesRecordingListener(mSeriesRecordingListener);
- getContext().getContentResolver().registerContentObserver(Programs.CONTENT_URI, true,
- mContentObserver);
+ getContext()
+ .getContentResolver()
+ .registerContentObserver(Programs.CONTENT_URI, true, mContentObserver);
}
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
+ public View onCreateView(
+ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
onProgramsUpdated();
return super.onCreateView(inflater, container, savedInstanceState);
}
@@ -218,14 +215,16 @@ public class DvrSeriesSchedulesFragment extends BaseDvrSchedulesFragment {
if (mProgramLoadTask != null) {
mProgramLoadTask.cancel(true);
}
- mProgramLoadTask = new EpisodicProgramLoadTask(getContext(), mSeriesRecording) {
- @Override
- protected void onPostExecute(List<Program> programs) {
- mPrograms = programs == null ? Collections.EMPTY_LIST : programs;
- onProgramsUpdated();
- }
- };
- mProgramLoadTask.setLoadCurrentProgram(true)
+ mProgramLoadTask =
+ new EpisodicProgramLoadTask(getContext(), mSeriesRecording) {
+ @Override
+ protected void onPostExecute(List<Program> programs) {
+ mPrograms = programs == null ? Collections.EMPTY_LIST : programs;
+ onProgramsUpdated();
+ }
+ };
+ mProgramLoadTask
+ .setLoadCurrentProgram(true)
.setLoadDisallowedProgram(true)
.setLoadScheduledEpisode(true)
.setIgnoreChannelOption(true)
diff --git a/src/com/android/tv/dvr/ui/list/EpisodicProgramRow.java b/src/com/android/tv/dvr/ui/list/EpisodicProgramRow.java
index 2af832ec..d5808412 100644
--- a/src/com/android/tv/dvr/ui/list/EpisodicProgramRow.java
+++ b/src/com/android/tv/dvr/ui/list/EpisodicProgramRow.java
@@ -17,29 +17,27 @@
package com.android.tv.dvr.ui.list;
import android.content.Context;
-
import com.android.tv.data.Program;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.ScheduledRecording.Builder;
import com.android.tv.dvr.ui.DvrUiHelper;
-/**
- * A class for the episodic program.
- */
+/** A class for the episodic program. */
class EpisodicProgramRow extends ScheduleRow {
private final String mInputId;
private final Program mProgram;
- public EpisodicProgramRow(String inputId, Program program, ScheduledRecording recording,
+ public EpisodicProgramRow(
+ String inputId,
+ Program program,
+ ScheduledRecording recording,
SchedulesHeaderRow headerRow) {
super(recording, headerRow);
mInputId = inputId;
mProgram = program;
}
- /**
- * Returns the program.
- */
+ /** Returns the program. */
public Program getProgram() {
return mProgram;
}
@@ -82,9 +80,6 @@ class EpisodicProgramRow extends ScheduleRow {
@Override
public String toString() {
- return super.toString()
- + "(inputId=" + mInputId
- + ",program=" + mProgram
- + ")";
+ return super.toString() + "(inputId=" + mInputId + ",program=" + mProgram + ")";
}
}
diff --git a/src/com/android/tv/dvr/ui/list/ScheduleRow.java b/src/com/android/tv/dvr/ui/list/ScheduleRow.java
index 91ba393a..b739c18f 100644
--- a/src/com/android/tv/dvr/ui/list/ScheduleRow.java
+++ b/src/com/android/tv/dvr/ui/list/ScheduleRow.java
@@ -18,14 +18,11 @@ package com.android.tv.dvr.ui.list;
import android.content.Context;
import android.support.annotation.Nullable;
-
import com.android.tv.common.SoftPreconditions;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.ui.DvrUiHelper;
-/**
- * A class for schedule recording row.
- */
+/** A class for schedule recording row. */
class ScheduleRow {
private final SchedulesHeaderRow mHeaderRow;
@Nullable private ScheduledRecording mSchedule;
@@ -37,113 +34,89 @@ class ScheduleRow {
mHeaderRow = headerRow;
}
- /**
- * Gets which {@link SchedulesHeaderRow} this schedule row belongs to.
- */
+ /** Gets which {@link SchedulesHeaderRow} this schedule row belongs to. */
public SchedulesHeaderRow getHeaderRow() {
return mHeaderRow;
}
- /**
- * Returns the recording schedule.
- */
+ /** Returns the recording schedule. */
@Nullable
public ScheduledRecording getSchedule() {
return mSchedule;
}
- /**
- * Checks if the stop recording has been requested or not.
- */
+ /** Checks if the stop recording has been requested or not. */
public boolean isStopRecordingRequested() {
return mStopRecordingRequested;
}
- /**
- * Sets the flag of stop recording request.
- */
+ /** Sets the flag of stop recording request. */
public void setStopRecordingRequested(boolean stopRecordingRequested) {
SoftPreconditions.checkState(!mStartRecordingRequested);
mStopRecordingRequested = stopRecordingRequested;
}
- /**
- * Checks if the start recording has been requested or not.
- */
+ /** Checks if the start recording has been requested or not. */
public boolean isStartRecordingRequested() {
return mStartRecordingRequested;
}
- /**
- * Sets the flag of start recording request.
- */
+ /** Sets the flag of start recording request. */
public void setStartRecordingRequested(boolean startRecordingRequested) {
SoftPreconditions.checkState(!mStopRecordingRequested);
mStartRecordingRequested = startRecordingRequested;
}
- /**
- * Sets the recording schedule.
- */
+ /** Sets the recording schedule. */
public void setSchedule(@Nullable ScheduledRecording schedule) {
mSchedule = schedule;
}
- /**
- * Returns the channel ID.
- */
+ /** Returns the channel ID. */
public long getChannelId() {
return mSchedule != null ? mSchedule.getChannelId() : -1;
}
- /**
- * Returns the start time.
- */
+ /** Returns the start time. */
public long getStartTimeMs() {
return mSchedule != null ? mSchedule.getStartTimeMs() : -1;
}
- /**
- * Returns the end time.
- */
+ /** Returns the end time. */
public long getEndTimeMs() {
return mSchedule != null ? mSchedule.getEndTimeMs() : -1;
}
- /**
- * Returns the duration.
- */
+ /** Returns the duration. */
public final long getDuration() {
return getEndTimeMs() - getStartTimeMs();
}
- /**
- * Checks if the program is on air.
- */
+ /** Checks if the program is on air. */
public final boolean isOnAir() {
long currentTimeMs = System.currentTimeMillis();
return getStartTimeMs() <= currentTimeMs && getEndTimeMs() > currentTimeMs;
}
- /**
- * Checks if the schedule is not started.
- */
+ /** Checks if the schedule is not started. */
public final boolean isRecordingNotStarted() {
return mSchedule != null
&& mSchedule.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED;
}
- /**
- * Checks if the schedule is in progress.
- */
+ /** Checks if the schedule is in progress. */
public final boolean isRecordingInProgress() {
return mSchedule != null
&& mSchedule.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS;
}
- /**
- * Checks if the schedule has been canceled or not.
- */
+ /** Checks if the schedule is failed. */
+ public final boolean isRecordingFailed() {
+ return mSchedule != null
+ && mSchedule.getState() == ScheduledRecording.STATE_RECORDING_FAILED;
+ }
+
+ /** Checks if the schedule has been canceled or not. */
public final boolean isScheduleCanceled() {
return mSchedule != null
&& mSchedule.getState() == ScheduledRecording.STATE_RECORDING_CANCELED;
@@ -152,28 +125,29 @@ class ScheduleRow {
public boolean isRecordingFinished() {
return mSchedule != null
&& (mSchedule.getState() == ScheduledRecording.STATE_RECORDING_FAILED
- || mSchedule.getState() == ScheduledRecording.STATE_RECORDING_CLIPPED
- || mSchedule.getState() == ScheduledRecording.STATE_RECORDING_FINISHED);
+ || mSchedule.getState() == ScheduledRecording.STATE_RECORDING_CLIPPED
+ || mSchedule.getState() == ScheduledRecording.STATE_RECORDING_FINISHED);
}
- /**
- * Creates and returns the new schedule with the existing information.
- */
+ public boolean hasRecordedProgram() {
+ return mSchedule != null
+ && mSchedule.getRecordedProgramId() != null
+ && mSchedule.getState() == ScheduledRecording.STATE_RECORDING_FINISHED;
+ }
+
+ /** Creates and returns the new schedule with the existing information. */
public ScheduledRecording.Builder createNewScheduleBuilder() {
return mSchedule != null ? ScheduledRecording.buildFrom(mSchedule) : null;
}
- /**
- * Returns the program title with episode number.
- */
+ /** Returns the program title with episode number. */
public String getProgramTitleWithEpisodeNumber(Context context) {
- return mSchedule != null ? DvrUiHelper.getStyledTitleWithEpisodeNumber(context,
- mSchedule, 0).toString() : null;
+ return mSchedule != null
+ ? DvrUiHelper.getStyledTitleWithEpisodeNumber(context, mSchedule, 0).toString()
+ : null;
}
- /**
- * Returns the program title including the season/episode number.
- */
+ /** Returns the program title including the season/episode number. */
public String getEpisodeDisplayTitle(Context context) {
return mSchedule != null ? mSchedule.getEpisodeDisplayTitle(context) : null;
}
@@ -181,15 +155,16 @@ class ScheduleRow {
@Override
public String toString() {
return getClass().getSimpleName()
- + "(schedule=" + mSchedule
- + ",stopRecordingRequested=" + mStopRecordingRequested
- + ",startRecordingRequested=" + mStartRecordingRequested
+ + "(schedule="
+ + mSchedule
+ + ",stopRecordingRequested="
+ + mStopRecordingRequested
+ + ",startRecordingRequested="
+ + mStartRecordingRequested
+ ")";
}
- /**
- * Checks if the {@code schedule} is for the program or channel.
- */
+ /** Checks if the {@code schedule} is for the program or channel. */
public boolean matchSchedule(ScheduledRecording schedule) {
if (mSchedule == null) {
return false;
diff --git a/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java b/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java
index 97d60473..ef4a4337 100644
--- a/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java
+++ b/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java
@@ -16,7 +16,9 @@
package com.android.tv.dvr.ui.list;
+import android.annotation.TargetApi;
import android.content.Context;
+import android.os.Build.VERSION_CODES;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -27,11 +29,11 @@ import android.util.ArraySet;
import android.util.Log;
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.ui.list.SchedulesHeaderRow.DateHeaderRow;
import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.ui.list.SchedulesHeaderRow.DateHeaderRow;
import com.android.tv.util.Utils;
import java.util.ArrayList;
@@ -40,14 +42,14 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
-/**
- * An adapter for {@link ScheduleRow}.
- */
+/** An adapter for {@link ScheduleRow}. */
+@TargetApi(VERSION_CODES.N)
+@SuppressWarnings("AndroidApiChecker") // TODO(b/32513850) remove when error prone is updated
class ScheduleRowAdapter extends ArrayObjectAdapter {
private static final String TAG = "ScheduleRowAdapter";
private static final boolean DEBUG = false;
- private final static long ONE_DAY_MS = TimeUnit.DAYS.toMillis(1);
+ private static final long ONE_DAY_MS = TimeUnit.DAYS.toMillis(1);
private static final int MSG_UPDATE_ROW = 1;
@@ -55,16 +57,17 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
private final List<String> mTitles = new ArrayList<>();
private final Set<ScheduleRow> mPendingUpdate = new ArraySet<>();
- private final Handler mHandler = new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == MSG_UPDATE_ROW) {
- long currentTimeMs = System.currentTimeMillis();
- handleUpdateRow(currentTimeMs);
- sendNextUpdateMessage(currentTimeMs);
- }
- }
- };
+ private final Handler mHandler =
+ new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_UPDATE_ROW) {
+ long currentTimeMs = System.currentTimeMillis();
+ handleUpdateRow(currentTimeMs);
+ sendNextUpdateMessage(currentTimeMs);
+ }
+ }
+ };
public ScheduleRowAdapter(Context context, ClassPresenterSelector classPresenterSelector) {
super(classPresenterSelector);
@@ -73,37 +76,41 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
mTitles.add(mContext.getString(R.string.dvr_date_tomorrow));
}
- /**
- * Returns context.
- */
+ /** Returns context. */
protected Context getContext() {
return mContext;
}
- /**
- * Starts schedule row adapter.
- */
+ /** Starts schedule row adapter. */
public void start() {
clear();
- List<ScheduledRecording> recordingList = TvApplication.getSingletons(mContext)
- .getDvrDataManager().getNonStartedScheduledRecordings();
- recordingList.addAll(TvApplication.getSingletons(mContext).getDvrDataManager()
- .getStartedRecordings());
- Collections.sort(recordingList,
- ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR);
+ List<ScheduledRecording> recordingList =
+ TvSingletons.getSingletons(mContext)
+ .getDvrDataManager()
+ .getNonStartedScheduledRecordings();
+ recordingList.addAll(
+ TvSingletons.getSingletons(mContext).getDvrDataManager().getStartedRecordings());
+ Collections.sort(
+ recordingList, ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR);
long deadLine = Utils.getLastMillisecondOfDay(System.currentTimeMillis());
- for (int i = 0; i < recordingList.size();) {
+ for (int i = 0; i < recordingList.size(); ) {
ArrayList<ScheduledRecording> section = new ArrayList<>();
while (i < recordingList.size() && recordingList.get(i).getStartTimeMs() < deadLine) {
section.add(recordingList.get(i++));
}
if (!section.isEmpty()) {
- SchedulesHeaderRow headerRow = new DateHeaderRow(calculateHeaderDate(deadLine),
- mContext.getResources().getQuantityString(
- R.plurals.dvr_schedules_section_subtitle, section.size(), section.size()),
- section.size(), deadLine);
+ SchedulesHeaderRow headerRow =
+ new DateHeaderRow(
+ calculateHeaderDate(deadLine),
+ mContext.getResources()
+ .getQuantityString(
+ R.plurals.dvr_schedules_section_subtitle,
+ section.size(),
+ section.size()),
+ section.size(),
+ deadLine);
add(headerRow);
- for(ScheduledRecording recording : section){
+ for (ScheduledRecording recording : section) {
add(new ScheduleRow(recording, headerRow));
}
}
@@ -113,25 +120,29 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
}
private String calculateHeaderDate(long deadLine) {
- int titleIndex = (int) ((deadLine -
- Utils.getLastMillisecondOfDay(System.currentTimeMillis())) / ONE_DAY_MS);
+ int titleIndex =
+ (int)
+ ((deadLine - Utils.getLastMillisecondOfDay(System.currentTimeMillis()))
+ / ONE_DAY_MS);
String headerDate;
if (titleIndex < mTitles.size()) {
headerDate = mTitles.get(titleIndex);
} else {
- headerDate = DateUtils.formatDateTime(getContext(), deadLine,
- DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_SHOW_DATE
- | DateUtils.FORMAT_ABBREV_MONTH);
+ headerDate =
+ DateUtils.formatDateTime(
+ getContext(),
+ deadLine,
+ DateUtils.FORMAT_SHOW_WEEKDAY
+ | DateUtils.FORMAT_SHOW_DATE
+ | DateUtils.FORMAT_ABBREV_MONTH);
}
return headerDate;
}
- /**
- * Stops schedules row adapter.
- */
+ /** Stops schedules row adapter. */
public void stop() {
mHandler.removeCallbacksAndMessages(null);
- DvrManager dvrManager = TvApplication.getSingletons(getContext()).getDvrManager();
+ DvrManager dvrManager = TvSingletons.getSingletons(getContext()).getDvrManager();
for (int i = 0; i < size(); i++) {
if (get(i) instanceof ScheduleRow) {
ScheduleRow row = (ScheduleRow) get(i);
@@ -142,9 +153,7 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
}
}
- /**
- * Gets which {@link ScheduleRow} the {@link ScheduledRecording} belongs to.
- */
+ /** Gets which {@link ScheduleRow} the {@link ScheduledRecording} belongs to. */
public ScheduleRow findRowByScheduledRecording(ScheduledRecording recording) {
if (recording == null) {
return null;
@@ -167,7 +176,8 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
continue;
}
ScheduleRow row = (ScheduleRow) item;
- if (row.getSchedule() != null && row.isStartRecordingRequested()
+ if (row.getSchedule() != null
+ && row.isStartRecordingRequested()
&& row.matchSchedule(schedule)) {
return row;
}
@@ -185,7 +195,8 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
if (get(index) instanceof ScheduleRow) {
ScheduleRow scheduleRow = (ScheduleRow) get(index);
if (ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR.compare(
- scheduleRow.getSchedule(), recording) > 0) {
+ scheduleRow.getSchedule(), recording)
+ > 0) {
break;
}
pre = index;
@@ -205,9 +216,14 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
add(index, addedRow);
updateHeaderDescription(headerRow);
} else {
- SchedulesHeaderRow headerRow = new DateHeaderRow(calculateHeaderDate(deadLine),
- mContext.getResources().getQuantityString(
- R.plurals.dvr_schedules_section_subtitle, 1, 1), 1, deadLine);
+ SchedulesHeaderRow headerRow =
+ new DateHeaderRow(
+ calculateHeaderDate(deadLine),
+ mContext.getResources()
+ .getQuantityString(
+ R.plurals.dvr_schedules_section_subtitle, 1, 1),
+ 1,
+ deadLine);
add(++pre, headerRow);
ScheduleRow addedRow = new ScheduleRow(recording, headerRow);
add(pre, addedRow);
@@ -241,14 +257,15 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
}
private void updateHeaderDescription(SchedulesHeaderRow headerRow) {
- headerRow.setDescription(mContext.getResources().getQuantityString(
- R.plurals.dvr_schedules_section_subtitle,
- headerRow.getItemCount(), headerRow.getItemCount()));
+ headerRow.setDescription(
+ mContext.getResources()
+ .getQuantityString(
+ R.plurals.dvr_schedules_section_subtitle,
+ headerRow.getItemCount(),
+ headerRow.getItemCount()));
}
- /**
- * Called when a schedule recording is added to dvr date manager.
- */
+ /** Called when a schedule recording is added to dvr date manager. */
public void onScheduledRecordingAdded(ScheduledRecording schedule) {
if (DEBUG) Log.d(TAG, "onScheduledRecordingAdded: " + schedule);
ScheduleRow row = findRowWithStartRequest(schedule);
@@ -263,9 +280,7 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
}
}
- /**
- * Called when a schedule recording is removed from dvr date manager.
- */
+ /** Called when a schedule recording is removed from dvr date manager. */
public void onScheduledRecordingRemoved(ScheduledRecording schedule) {
if (DEBUG) Log.d(TAG, "onScheduledRecordingRemoved: " + schedule);
ScheduleRow row = findRowByScheduledRecording(schedule);
@@ -276,9 +291,7 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
}
}
- /**
- * Called when a schedule recording is updated in dvr date manager.
- */
+ /** Called when a schedule recording is updated in dvr date manager. */
public void onScheduledRecordingUpdated(ScheduledRecording schedule, boolean conflictChange) {
if (DEBUG) Log.d(TAG, "onScheduledRecordingUpdated: " + schedule);
ScheduleRow row = findRowByScheduledRecording(schedule);
@@ -329,9 +342,7 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
}
}
- /**
- * Checks if there is a row which requested start/stop recording.
- */
+ /** Checks if there is a row which requested start/stop recording. */
protected boolean isStartOrStopRequested() {
for (int i = 0; i < size(); i++) {
Object item = get(i);
@@ -345,16 +356,12 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
return false;
}
- /**
- * Delays update of the row.
- */
+ /** Delays update of the row. */
protected void addPendingUpdate(ScheduleRow row) {
mPendingUpdate.add(row);
}
- /**
- * Executes the pending updates.
- */
+ /** Executes the pending updates. */
protected void executePendingUpdate() {
for (ScheduleRow row : mPendingUpdate) {
int index = indexOf(row);
@@ -365,21 +372,17 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
mPendingUpdate.clear();
}
- /**
- * To check whether the recording should be kept or not.
- */
+ /** To check whether the recording should be kept or not. */
protected boolean willBeKept(ScheduledRecording schedule) {
// CANCELED state means that the schedule was removed temporarily, which should be shown
// in the list so that the user can reschedule it.
return schedule.getEndTimeMs() > System.currentTimeMillis()
&& (schedule.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS
- || schedule.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED
- || schedule.getState() == ScheduledRecording.STATE_RECORDING_CANCELED);
+ || schedule.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED
+ || schedule.getState() == ScheduledRecording.STATE_RECORDING_CANCELED);
}
- /**
- * Handle the message to update/remove rows.
- */
+ /** Handle the message to update/remove rows. */
protected void handleUpdateRow(long currentTimeMs) {
for (int i = 0; i < size(); i++) {
Object item = get(i);
@@ -392,9 +395,7 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
}
}
- /**
- * Returns the next update time. Return {@link Long#MAX_VALUE} if no timer is necessary.
- */
+ /** Returns the next update time. Return {@link Long#MAX_VALUE} if no timer is necessary. */
protected long getNextTimerMs(long currentTimeMs) {
long earliest = Long.MAX_VALUE;
for (int i = 0; i < size(); i++) {
@@ -411,15 +412,12 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
return earliest;
}
- /**
- * Send update message at the time returned by {@link #getNextTimerMs}.
- */
+ /** Send update message at the time returned by {@link #getNextTimerMs}. */
protected final void sendNextUpdateMessage(long currentTimeMs) {
mHandler.removeMessages(MSG_UPDATE_ROW);
long nextTime = getNextTimerMs(currentTimeMs);
if (nextTime != Long.MAX_VALUE) {
- mHandler.sendEmptyMessageDelayed(MSG_UPDATE_ROW,
- nextTime - System.currentTimeMillis());
+ mHandler.sendEmptyMessageDelayed(MSG_UPDATE_ROW, nextTime - System.currentTimeMillis());
}
}
}
diff --git a/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java b/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java
index dc4e3c41..38d3d582 100644
--- a/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java
+++ b/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java
@@ -18,7 +18,6 @@ package com.android.tv.dvr.ui.list;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
@@ -37,11 +36,11 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvFeatures;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
-import com.android.tv.data.Channel;
+import com.android.tv.data.api.Channel;
import com.android.tv.dialog.HalfSizedDialogFragment;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.DvrScheduleManager;
@@ -50,21 +49,22 @@ import com.android.tv.dvr.ui.DvrStopRecordingFragment;
import com.android.tv.dvr.ui.DvrUiHelper;
import com.android.tv.util.ToastUtils;
import com.android.tv.util.Utils;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
-/**
- * A RowPresenter for {@link ScheduleRow}.
- */
+/** A RowPresenter for {@link ScheduleRow}. */
@TargetApi(Build.VERSION_CODES.N)
class ScheduleRowPresenter extends RowPresenter {
private static final String TAG = "ScheduleRowPresenter";
@Retention(RetentionPolicy.SOURCE)
- @IntDef({ACTION_START_RECORDING, ACTION_STOP_RECORDING, ACTION_CREATE_SCHEDULE,
- ACTION_REMOVE_SCHEDULE})
+ @IntDef({
+ ACTION_START_RECORDING,
+ ACTION_STOP_RECORDING,
+ ACTION_CREATE_SCHEDULE,
+ ACTION_REMOVE_SCHEDULE
+ })
public @interface ScheduleRowAction {}
/** An action to start recording. */
public static final int ACTION_START_RECORDING = 1;
@@ -85,9 +85,7 @@ class ScheduleRowPresenter extends RowPresenter {
private int mLastFocusedViewId;
- /**
- * A ViewHolder for {@link ScheduleRow}
- */
+ /** A ViewHolder for {@link ScheduleRow} */
public static class ScheduleRowViewHolder extends RowPresenter.ViewHolder {
private ScheduleRowPresenter mPresenter;
@ScheduleRowAction private int[] mActions;
@@ -118,29 +116,30 @@ class ScheduleRowPresenter extends RowPresenter {
new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean focused) {
- view.post(new Runnable() {
- @Override
- public void run() {
- if (view.isFocused()) {
- mPresenter.mLastFocusedViewId = view.getId();
- }
- updateSelector();
- }
- });
+ view.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ if (view.isFocused()) {
+ mPresenter.mLastFocusedViewId = view.getId();
+ }
+ updateSelector();
+ }
+ });
}
};
public ScheduleRowViewHolder(View view, ScheduleRowPresenter presenter) {
super(view);
mPresenter = presenter;
- mLtr = view.getContext().getResources().getConfiguration().getLayoutDirection()
- == View.LAYOUT_DIRECTION_LTR;
+ mLtr =
+ view.getContext().getResources().getConfiguration().getLayoutDirection()
+ == View.LAYOUT_DIRECTION_LTR;
mInfoContainer = (LinearLayout) view.findViewById(R.id.info_container);
- mSecondActionContainer = (RelativeLayout) view.findViewById(
- R.id.action_second_container);
+ mSecondActionContainer =
+ (RelativeLayout) view.findViewById(R.id.action_second_container);
mSecondActionView = (ImageView) view.findViewById(R.id.action_second);
- mFirstActionContainer = (RelativeLayout) view.findViewById(
- R.id.action_first_container);
+ mFirstActionContainer = (RelativeLayout) view.findViewById(R.id.action_first_container);
mFirstActionView = (ImageView) view.findViewById(R.id.action_first);
mSelectorView = view.findViewById(R.id.selector);
mTimeView = (TextView) view.findViewById(R.id.time);
@@ -151,47 +150,48 @@ class ScheduleRowPresenter extends RowPresenter {
Resources res = view.getResources();
mSelectorTranslationDelta =
res.getDimensionPixelSize(R.dimen.dvr_schedules_item_section_margin)
- - res.getDimensionPixelSize(R.dimen.dvr_schedules_item_focus_translation_delta);
- mSelectorWidthDelta = res.getDimensionPixelSize(
- R.dimen.dvr_schedules_item_focus_width_delta);
+ - res.getDimensionPixelSize(
+ R.dimen.dvr_schedules_item_focus_translation_delta);
+ mSelectorWidthDelta =
+ res.getDimensionPixelSize(R.dimen.dvr_schedules_item_focus_width_delta);
mRoundRectRadius = res.getDimensionPixelSize(R.dimen.dvr_schedules_selector_radius);
- int fullWidth = res.getDimensionPixelSize(
- R.dimen.dvr_schedules_item_width)
- - 2 * res.getDimensionPixelSize(R.dimen.dvr_schedules_layout_padding);
+ int fullWidth =
+ res.getDimensionPixelSize(R.dimen.dvr_schedules_item_width)
+ - 2 * res.getDimensionPixelSize(R.dimen.dvr_schedules_layout_padding);
mInfoContainerTargetWidthWithNoAction = fullWidth + 2 * mRoundRectRadius;
- mInfoContainerTargetWidthWithOneAction = fullWidth
- - res.getDimensionPixelSize(R.dimen.dvr_schedules_item_section_margin)
- - res.getDimensionPixelSize(R.dimen.dvr_schedules_item_delete_width)
- + mRoundRectRadius + mSelectorWidthDelta;
- mInfoContainerTargetWidthWithTwoAction = mInfoContainerTargetWidthWithOneAction
- - res.getDimensionPixelSize(R.dimen.dvr_schedules_item_section_margin)
- - res.getDimensionPixelSize(R.dimen.dvr_schedules_item_icon_size);
+ mInfoContainerTargetWidthWithOneAction =
+ fullWidth
+ - res.getDimensionPixelSize(R.dimen.dvr_schedules_item_section_margin)
+ - res.getDimensionPixelSize(R.dimen.dvr_schedules_item_delete_width)
+ + mRoundRectRadius
+ + mSelectorWidthDelta;
+ mInfoContainerTargetWidthWithTwoAction =
+ mInfoContainerTargetWidthWithOneAction
+ - res.getDimensionPixelSize(R.dimen.dvr_schedules_item_section_margin)
+ - res.getDimensionPixelSize(R.dimen.dvr_schedules_item_icon_size);
mInfoContainer.setOnFocusChangeListener(mOnFocusChangeListener);
mFirstActionContainer.setOnFocusChangeListener(mOnFocusChangeListener);
mSecondActionContainer.setOnFocusChangeListener(mOnFocusChangeListener);
}
- /**
- * Returns time view.
- */
+ /** Returns time view. */
public TextView getTimeView() {
return mTimeView;
}
- /**
- * Returns title view.
- */
+ /** Returns title view. */
public TextView getProgramTitleView() {
return mProgramTitleView;
}
private void updateSelector() {
- int animationDuration = mSelectorView.getResources().getInteger(
- android.R.integer.config_shortAnimTime);
+ int animationDuration =
+ mSelectorView.getResources().getInteger(android.R.integer.config_shortAnimTime);
DecelerateInterpolator interpolator = new DecelerateInterpolator();
- if (mInfoContainer.isFocused() || mSecondActionContainer.isFocused()
+ if (mInfoContainer.isFocused()
+ || mSecondActionContainer.isFocused()
|| mFirstActionContainer.isFocused()) {
final ViewGroup.LayoutParams lp = mSelectorView.getLayoutParams();
final int targetWidth;
@@ -208,33 +208,50 @@ class ScheduleRowPresenter extends RowPresenter {
} else if (mSecondActionContainer.isFocused()) {
targetWidth = Math.max(mSecondActionContainer.getWidth(), 2 * mRoundRectRadius);
} else {
- targetWidth = mFirstActionContainer.getWidth() + mRoundRectRadius
- + mSelectorTranslationDelta;
+ targetWidth =
+ mFirstActionContainer.getWidth()
+ + mRoundRectRadius
+ + mSelectorTranslationDelta;
}
float targetTranslationX;
if (mInfoContainer.isFocused()) {
- targetTranslationX = mLtr ? mInfoContainer.getLeft() - mRoundRectRadius
- - mSelectorView.getLeft() :
- mInfoContainer.getRight() + mRoundRectRadius - mSelectorView.getRight();
+ targetTranslationX =
+ mLtr
+ ? mInfoContainer.getLeft()
+ - mRoundRectRadius
+ - mSelectorView.getLeft()
+ : mInfoContainer.getRight()
+ + mRoundRectRadius
+ - mSelectorView.getRight();
} else if (mSecondActionContainer.isFocused()) {
if (mSecondActionContainer.getWidth() > 2 * mRoundRectRadius) {
- targetTranslationX = mLtr ? mSecondActionContainer.getLeft() -
- mSelectorView.getLeft()
- : mSecondActionContainer.getRight() - mSelectorView.getRight();
+ targetTranslationX =
+ mLtr
+ ? mSecondActionContainer.getLeft() - mSelectorView.getLeft()
+ : mSecondActionContainer.getRight()
+ - mSelectorView.getRight();
} else {
- targetTranslationX = mLtr ? mSecondActionContainer.getLeft() -
- (mRoundRectRadius - mSecondActionContainer.getWidth() / 2) -
- mSelectorView.getLeft()
- : mSecondActionContainer.getRight() +
- (mRoundRectRadius - mSecondActionContainer.getWidth() / 2) -
- mSelectorView.getRight();
+ targetTranslationX =
+ mLtr
+ ? mSecondActionContainer.getLeft()
+ - (mRoundRectRadius
+ - mSecondActionContainer.getWidth() / 2)
+ - mSelectorView.getLeft()
+ : mSecondActionContainer.getRight()
+ + (mRoundRectRadius
+ - mSecondActionContainer.getWidth() / 2)
+ - mSelectorView.getRight();
}
} else {
- targetTranslationX = mLtr ? mFirstActionContainer.getLeft()
- - mSelectorTranslationDelta - mSelectorView.getLeft()
- : mFirstActionContainer.getRight() + mSelectorTranslationDelta
- - mSelectorView.getRight();
+ targetTranslationX =
+ mLtr
+ ? mFirstActionContainer.getLeft()
+ - mSelectorTranslationDelta
+ - mSelectorView.getLeft()
+ : mFirstActionContainer.getRight()
+ + mSelectorTranslationDelta
+ - mSelectorView.getRight();
}
if (mSelectorView.getAlpha() == 0) {
@@ -246,57 +263,72 @@ class ScheduleRowPresenter extends RowPresenter {
// animate the selector in and to the proper width and translation X.
final float deltaWidth = lp.width - targetWidth;
mSelectorView.animate().cancel();
- mSelectorView.animate().translationX(targetTranslationX).alpha(1f)
- .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- // Set width to the proper width for this animation step.
- lp.width = targetWidth + Math.round(
- deltaWidth * (1f - animation.getAnimatedFraction()));
- mSelectorView.requestLayout();
- }
- }).setDuration(animationDuration).setInterpolator(interpolator).start();
+ mSelectorView
+ .animate()
+ .translationX(targetTranslationX)
+ .alpha(1f)
+ .setUpdateListener(
+ animation -> {
+ // Set width to the proper width for this animation step.
+ float fraction = 1f - animation.getAnimatedFraction();
+ lp.width = targetWidth + Math.round(deltaWidth * fraction);
+ mSelectorView.requestLayout();
+ })
+ .setDuration(animationDuration)
+ .setInterpolator(interpolator)
+ .start();
if (mPendingAnimationRunnable != null) {
mPendingAnimationRunnable.run();
mPendingAnimationRunnable = null;
}
} else {
mSelectorView.animate().cancel();
- mSelectorView.animate().alpha(0f).setDuration(animationDuration)
- .setInterpolator(interpolator).setUpdateListener(null).start();
+ mSelectorView
+ .animate()
+ .alpha(0f)
+ .setDuration(animationDuration)
+ .setInterpolator(interpolator)
+ .setUpdateListener(null)
+ .start();
}
}
- /**
- * Grey out the information body.
- */
+ /** Grey out the information body. */
public void greyOutInfo() {
- mTimeView.setTextColor(mInfoContainer.getResources().getColor(R.color
- .dvr_schedules_item_info_grey, null));
- mProgramTitleView.setTextColor(mInfoContainer.getResources().getColor(R.color
- .dvr_schedules_item_info_grey, null));
- mInfoSeparatorView.setTextColor(mInfoContainer.getResources().getColor(R.color
- .dvr_schedules_item_info_grey, null));
- mChannelNameView.setTextColor(mInfoContainer.getResources().getColor(R.color
- .dvr_schedules_item_info_grey, null));
- mConflictInfoView.setTextColor(mInfoContainer.getResources().getColor(R.color
- .dvr_schedules_item_info_grey, null));
+ mTimeView.setTextColor(
+ mInfoContainer
+ .getResources()
+ .getColor(R.color.dvr_schedules_item_info_grey, null));
+ mProgramTitleView.setTextColor(
+ mInfoContainer
+ .getResources()
+ .getColor(R.color.dvr_schedules_item_info_grey, null));
+ mInfoSeparatorView.setTextColor(
+ mInfoContainer
+ .getResources()
+ .getColor(R.color.dvr_schedules_item_info_grey, null));
+ mChannelNameView.setTextColor(
+ mInfoContainer
+ .getResources()
+ .getColor(R.color.dvr_schedules_item_info_grey, null));
+ mConflictInfoView.setTextColor(
+ mInfoContainer
+ .getResources()
+ .getColor(R.color.dvr_schedules_item_info_grey, null));
}
- /**
- * Reverse grey out operation.
- */
+ /** Reverse grey out operation. */
public void whiteBackInfo() {
- mTimeView.setTextColor(mInfoContainer.getResources().getColor(R.color
- .dvr_schedules_item_info, null));
- mProgramTitleView.setTextColor(mInfoContainer.getResources().getColor(R.color
- .dvr_schedules_item_main, null));
- mInfoSeparatorView.setTextColor(mInfoContainer.getResources().getColor(R.color
- .dvr_schedules_item_info, null));
- mChannelNameView.setTextColor(mInfoContainer.getResources().getColor(R.color
- .dvr_schedules_item_info, null));
- mConflictInfoView.setTextColor(mInfoContainer.getResources().getColor(R.color
- .dvr_schedules_item_info, null));
+ mTimeView.setTextColor(
+ mInfoContainer.getResources().getColor(R.color.dvr_schedules_item_info, null));
+ mProgramTitleView.setTextColor(
+ mInfoContainer.getResources().getColor(R.color.dvr_schedules_item_main, null));
+ mInfoSeparatorView.setTextColor(
+ mInfoContainer.getResources().getColor(R.color.dvr_schedules_item_info, null));
+ mChannelNameView.setTextColor(
+ mInfoContainer.getResources().getColor(R.color.dvr_schedules_item_info, null));
+ mConflictInfoView.setTextColor(
+ mInfoContainer.getResources().getColor(R.color.dvr_schedules_item_info, null));
}
}
@@ -304,32 +336,29 @@ class ScheduleRowPresenter extends RowPresenter {
setHeaderPresenter(null);
setSelectEffectEnabled(false);
mContext = context;
- mDvrManager = TvApplication.getSingletons(context).getDvrManager();
- mDvrScheduleManager = TvApplication.getSingletons(context).getDvrScheduleManager();
- mTunerConflictWillNotBeRecordedInfo = mContext.getString(
- R.string.dvr_schedules_tuner_conflict_will_not_be_recorded_info);
- mTunerConflictWillBePartiallyRecordedInfo = mContext.getString(
- R.string.dvr_schedules_tuner_conflict_will_be_partially_recorded);
- mAnimationDuration = mContext.getResources().getInteger(
- android.R.integer.config_shortAnimTime);
+ mDvrManager = TvSingletons.getSingletons(context).getDvrManager();
+ mDvrScheduleManager = TvSingletons.getSingletons(context).getDvrScheduleManager();
+ mTunerConflictWillNotBeRecordedInfo =
+ mContext.getString(R.string.dvr_schedules_tuner_conflict_will_not_be_recorded_info);
+ mTunerConflictWillBePartiallyRecordedInfo =
+ mContext.getString(
+ R.string.dvr_schedules_tuner_conflict_will_be_partially_recorded);
+ mAnimationDuration =
+ mContext.getResources().getInteger(android.R.integer.config_shortAnimTime);
}
@Override
public ViewHolder createRowViewHolder(ViewGroup parent) {
- return onGetScheduleRowViewHolder(LayoutInflater.from(mContext)
- .inflate(R.layout.dvr_schedules_item, parent, false));
+ return onGetScheduleRowViewHolder(
+ LayoutInflater.from(mContext).inflate(R.layout.dvr_schedules_item, parent, false));
}
- /**
- * Returns context.
- */
+ /** Returns context. */
protected Context getContext() {
return mContext;
}
- /**
- * Returns DVR manager.
- */
+ /** Returns DVR manager. */
protected DvrManager getDvrManager() {
return mDvrManager;
}
@@ -341,54 +370,77 @@ class ScheduleRowPresenter extends RowPresenter {
ScheduleRow row = (ScheduleRow) item;
@ScheduleRowAction int[] actions = getAvailableActions(row);
viewHolder.mActions = actions;
- viewHolder.mInfoContainer.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (isInfoClickable(row)) {
- onInfoClicked(row);
- }
- }
- });
+ viewHolder.mInfoContainer.setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (isInfoClickable(row)) {
+ onInfoClicked(row);
+ }
+ }
+ });
- viewHolder.mFirstActionContainer.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- onActionClicked(actions[0], row);
- }
- });
+ viewHolder.mFirstActionContainer.setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ onActionClicked(actions[0], row);
+ }
+ });
- viewHolder.mSecondActionContainer.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- onActionClicked(actions[1], row);
- }
- });
+ viewHolder.mSecondActionContainer.setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ onActionClicked(actions[1], row);
+ }
+ });
viewHolder.mTimeView.setText(onGetRecordingTimeText(row));
String programInfoText = onGetProgramInfoText(row);
if (TextUtils.isEmpty(programInfoText)) {
int durationMins = Math.max(1, Utils.getRoundOffMinsFromMs(row.getDuration()));
- programInfoText = mContext.getResources().getQuantityString(
- R.plurals.dvr_schedules_recording_duration, durationMins, durationMins);
+ programInfoText =
+ mContext.getResources()
+ .getQuantityString(
+ R.plurals.dvr_schedules_recording_duration,
+ durationMins,
+ durationMins);
}
String channelName = getChannelNameText(row);
viewHolder.mProgramTitleView.setText(programInfoText);
- viewHolder.mInfoSeparatorView.setVisibility((!TextUtils.isEmpty(programInfoText)
- && !TextUtils.isEmpty(channelName)) ? View.VISIBLE : View.GONE);
+ viewHolder.mInfoSeparatorView.setVisibility(
+ (!TextUtils.isEmpty(programInfoText) && !TextUtils.isEmpty(channelName))
+ ? View.VISIBLE
+ : View.GONE);
viewHolder.mChannelNameView.setText(channelName);
if (actions != null) {
switch (actions.length) {
case 2:
viewHolder.mSecondActionView.setImageResource(getImageForAction(actions[1]));
- // pass through
+ // fall through
case 1:
viewHolder.mFirstActionView.setImageResource(getImageForAction(actions[0]));
break;
+ default: // fall out
}
}
- if (mDvrManager.isConflicting(row.getSchedule())) {
+ ScheduledRecording schedule = row.getSchedule();
+ if (mDvrManager.isConflicting(schedule)
+ || (TvFeatures.DVR_FAILED_LIST.isEnabled(getContext())
+ && schedule != null
+ && schedule.getState() == ScheduledRecording.STATE_RECORDING_FAILED)) {
String conflictInfo;
- if (mDvrScheduleManager.isPartiallyConflicting(row.getSchedule())) {
+ if (TvFeatures.DVR_FAILED_LIST.isEnabled(getContext())
+ && schedule != null
+ && schedule.getState() == ScheduledRecording.STATE_RECORDING_FAILED) {
+ // TODO(b/72638385): show real error messages
+ // TODO(b/72638385): use a better name for ConflictInfoXXX
+ conflictInfo = "Failed";
+ if (schedule.getFailedReason() != null) {
+ conflictInfo += " (Error code: " + schedule.getFailedReason() + ")";
+ }
+ } else if (mDvrScheduleManager.isPartiallyConflicting(row.getSchedule())) {
conflictInfo = mTunerConflictWillBePartiallyRecordedInfo;
} else {
conflictInfo = mTunerConflictWillNotBeRecordedInfo;
@@ -422,51 +474,48 @@ class ScheduleRowPresenter extends RowPresenter {
}
}
- /**
- * Returns view holder for schedule row.
- */
+ /** Returns view holder for schedule row. */
protected ScheduleRowViewHolder onGetScheduleRowViewHolder(View view) {
return new ScheduleRowViewHolder(view, this);
}
- /**
- * Returns time text for time view from scheduled recording.
- */
+ /** Returns time text for time view from scheduled recording. */
protected String onGetRecordingTimeText(ScheduleRow row) {
- return Utils.getDurationString(mContext, row.getStartTimeMs(), row.getEndTimeMs(), true,
- false, true, 0);
+ return Utils.getDurationString(
+ mContext, row.getStartTimeMs(), row.getEndTimeMs(), true, false, true, 0);
}
- /**
- * Returns program info text for program title view.
- */
+ /** Returns program info text for program title view. */
protected String onGetProgramInfoText(ScheduleRow row) {
return row.getProgramTitleWithEpisodeNumber(mContext);
}
private String getChannelNameText(ScheduleRow row) {
- Channel channel = TvApplication.getSingletons(mContext).getChannelDataManager()
- .getChannel(row.getChannelId());
- return channel == null ? null :
- TextUtils.isEmpty(channel.getDisplayName()) ? channel.getDisplayNumber() :
- channel.getDisplayName().trim() + " " + channel.getDisplayNumber();
+ Channel channel =
+ TvSingletons.getSingletons(mContext)
+ .getChannelDataManager()
+ .getChannel(row.getChannelId());
+ return channel == null
+ ? null
+ : TextUtils.isEmpty(channel.getDisplayName())
+ ? channel.getDisplayNumber()
+ : channel.getDisplayName().trim() + " " + channel.getDisplayNumber();
}
- /**
- * Called when user click Info in {@link ScheduleRow}.
- */
+ /** Called when user click Info in {@link ScheduleRow}. */
protected void onInfoClicked(ScheduleRow row) {
DvrUiHelper.startDetailsActivity((Activity) mContext, row.getSchedule(), null, true);
}
private boolean isInfoClickable(ScheduleRow row) {
- return row.getSchedule() != null
- && (row.getSchedule().isNotStarted() || row.getSchedule().isInProgress());
+ ScheduledRecording schedule = row.getSchedule();
+ return schedule != null
+ && (schedule.isNotStarted()
+ || schedule.isInProgress()
+ || schedule.isFinished());
}
- /**
- * Called when the button in a row is clicked.
- */
+ /** Called when the button in a row is clicked. */
protected void onActionClicked(@ScheduleRowAction final int action, ScheduleRow row) {
switch (action) {
case ACTION_START_RECORDING:
@@ -481,12 +530,11 @@ class ScheduleRowPresenter extends RowPresenter {
case ACTION_REMOVE_SCHEDULE:
onRemoveSchedule(row);
break;
+ default: // fall out
}
}
- /**
- * Action handler for {@link #ACTION_START_RECORDING}.
- */
+ /** Action handler for {@link #ACTION_START_RECORDING}. */
protected void onStartRecording(ScheduleRow row) {
ScheduledRecording schedule = row.getSchedule();
if (schedule == null) {
@@ -495,12 +543,16 @@ class ScheduleRowPresenter extends RowPresenter {
}
// Checks if there are current recordings that will be stopped by schedule this program.
// If so, shows confirmation dialog to users.
- List<ScheduledRecording> conflictSchedules = mDvrScheduleManager.getConflictingSchedules(
- schedule.getChannelId(), System.currentTimeMillis(), schedule.getEndTimeMs());
+ List<ScheduledRecording> conflictSchedules =
+ mDvrScheduleManager.getConflictingSchedules(
+ schedule.getChannelId(),
+ System.currentTimeMillis(),
+ schedule.getEndTimeMs());
for (int i = conflictSchedules.size() - 1; i >= 0; i--) {
ScheduledRecording conflictSchedule = conflictSchedules.get(i);
if (conflictSchedule.isInProgress()) {
- DvrUiHelper.showStopRecordingDialog((Activity) mContext,
+ DvrUiHelper.showStopRecordingDialog(
+ (Activity) mContext,
conflictSchedule.getChannelId(),
DvrStopRecordingFragment.REASON_ON_CONFLICT,
new HalfSizedDialogFragment.OnActionClickListener() {
@@ -523,26 +575,27 @@ class ScheduleRowPresenter extends RowPresenter {
if (row.isRecordingNotStarted()) {
mDvrManager.setHighestPriority(row.getSchedule());
} else if (row.isRecordingFinished()) {
- mDvrManager.addSchedule(ScheduledRecording.buildFrom(row.getSchedule())
- .setId(ScheduledRecording.ID_NOT_SET)
- .setState(ScheduledRecording.STATE_RECORDING_NOT_STARTED)
- .setPriority(mDvrManager.suggestHighestPriority(row.getSchedule()))
- .build());
+ mDvrManager.addSchedule(
+ ScheduledRecording.buildFrom(row.getSchedule())
+ .setId(ScheduledRecording.ID_NOT_SET)
+ .setState(ScheduledRecording.STATE_RECORDING_NOT_STARTED)
+ .setPriority(mDvrManager.suggestHighestPriority(row.getSchedule()))
+ .build());
} else {
- SoftPreconditions.checkState(false, TAG, "Invalid row state to start recording: "
- + row);
+ SoftPreconditions.checkState(
+ false, TAG, "Invalid row state to start recording: " + row);
return;
}
- String msg = mContext.getString(R.string.dvr_msg_current_program_scheduled,
- row.getSchedule().getProgramTitle(),
- Utils.toTimeString(row.getEndTimeMs(), false));
+ String msg =
+ mContext.getString(
+ R.string.dvr_msg_current_program_scheduled,
+ row.getSchedule().getProgramTitle(),
+ Utils.toTimeString(row.getEndTimeMs(), false));
ToastUtils.show(mContext, msg, Toast.LENGTH_SHORT);
}
}
- /**
- * Action handler for {@link #ACTION_STOP_RECORDING}.
- */
+ /** Action handler for {@link #ACTION_STOP_RECORDING}. */
protected void onStopRecording(ScheduleRow row) {
if (row.getSchedule() == null) {
// This row has been deleted.
@@ -555,15 +608,15 @@ class ScheduleRowPresenter extends RowPresenter {
if (TextUtils.isEmpty(deletedInfo)) {
deletedInfo = getChannelNameText(row);
}
- ToastUtils.show(mContext, mContext.getResources()
- .getString(R.string.dvr_schedules_deletion_info, deletedInfo),
+ ToastUtils.show(
+ mContext,
+ mContext.getResources()
+ .getString(R.string.dvr_schedules_deletion_info, deletedInfo),
Toast.LENGTH_SHORT);
}
}
- /**
- * Action handler for {@link #ACTION_CREATE_SCHEDULE}.
- */
+ /** Action handler for {@link #ACTION_CREATE_SCHEDULE}. */
protected void onCreateSchedule(ScheduleRow row) {
if (row.getSchedule() == null) {
// This row has been deleted.
@@ -571,12 +624,15 @@ class ScheduleRowPresenter extends RowPresenter {
}
if (!row.isOnAir()) {
if (row.isScheduleCanceled()) {
- mDvrManager.updateScheduledRecording(ScheduledRecording.buildFrom(row.getSchedule())
- .setState(ScheduledRecording.STATE_RECORDING_NOT_STARTED)
- .setPriority(mDvrManager.suggestHighestPriority(row.getSchedule()))
- .build());
- String msg = mContext.getString(R.string.dvr_msg_program_scheduled,
- row.getSchedule().getProgramTitle());
+ mDvrManager.updateScheduledRecording(
+ ScheduledRecording.buildFrom(row.getSchedule())
+ .setState(ScheduledRecording.STATE_RECORDING_NOT_STARTED)
+ .setPriority(mDvrManager.suggestHighestPriority(row.getSchedule()))
+ .build());
+ String msg =
+ mContext.getString(
+ R.string.dvr_msg_program_scheduled,
+ row.getSchedule().getProgramTitle());
ToastUtils.show(mContext, msg, Toast.LENGTH_SHORT);
} else if (mDvrManager.isConflicting(row.getSchedule())) {
mDvrManager.setHighestPriority(row.getSchedule());
@@ -584,9 +640,7 @@ class ScheduleRowPresenter extends RowPresenter {
}
}
- /**
- * Action handler for {@link #ACTION_REMOVE_SCHEDULE}.
- */
+ /** Action handler for {@link #ACTION_REMOVE_SCHEDULE}. */
protected void onRemoveSchedule(ScheduleRow row) {
if (row.getSchedule() == null) {
// This row has been deleted.
@@ -605,13 +659,19 @@ class ScheduleRowPresenter extends RowPresenter {
mDvrManager.removeScheduledRecording(row.getSchedule());
} else if (row.isRecordingNotStarted()) {
deletedInfo = getDeletedInfo(row);
- mDvrManager.updateScheduledRecording(ScheduledRecording.buildFrom(row.getSchedule())
- .setState(ScheduledRecording.STATE_RECORDING_CANCELED)
- .build());
+ mDvrManager.updateScheduledRecording(
+ ScheduledRecording.buildFrom(row.getSchedule())
+ .setState(ScheduledRecording.STATE_RECORDING_CANCELED)
+ .build());
+ } else if (row.isRecordingFailed()) {
+ deletedInfo = getDeletedInfo(row);
+ mDvrManager.removeScheduledRecording(row.getSchedule());
}
}
if (deletedInfo != null) {
- ToastUtils.show(mContext, mContext.getResources()
+ ToastUtils.show(
+ mContext,
+ mContext.getResources()
.getString(R.string.dvr_schedules_deletion_info, deletedInfo),
Toast.LENGTH_SHORT);
}
@@ -631,9 +691,7 @@ class ScheduleRowPresenter extends RowPresenter {
updateActionContainer(vh, selected);
}
- /**
- * Internal method for onRowViewSelected, can be customized by subclass.
- */
+ /** Internal method for onRowViewSelected, can be customized by subclass. */
private void updateActionContainer(ViewHolder vh, boolean selected) {
ScheduleRowViewHolder viewHolder = (ScheduleRowViewHolder) vh;
viewHolder.mSecondActionContainer.animate().setListener(null).cancel();
@@ -643,38 +701,43 @@ class ScheduleRowPresenter extends RowPresenter {
case 2:
prepareShowActionView(viewHolder.mSecondActionContainer);
prepareShowActionView(viewHolder.mFirstActionContainer);
- viewHolder.mPendingAnimationRunnable = new Runnable() {
- @Override
- public void run() {
- showActionView(viewHolder.mSecondActionContainer);
- showActionView(viewHolder.mFirstActionContainer);
- }
- };
+ viewHolder.mPendingAnimationRunnable =
+ new Runnable() {
+ @Override
+ public void run() {
+ showActionView(viewHolder.mSecondActionContainer);
+ showActionView(viewHolder.mFirstActionContainer);
+ }
+ };
break;
case 1:
prepareShowActionView(viewHolder.mFirstActionContainer);
- viewHolder.mPendingAnimationRunnable = new Runnable() {
- @Override
- public void run() {
- hideActionView(viewHolder.mSecondActionContainer, View.GONE);
- showActionView(viewHolder.mFirstActionContainer);
- }
- };
+ viewHolder.mPendingAnimationRunnable =
+ new Runnable() {
+ @Override
+ public void run() {
+ hideActionView(viewHolder.mSecondActionContainer, View.GONE);
+ showActionView(viewHolder.mFirstActionContainer);
+ }
+ };
if (mLastFocusedViewId == R.id.action_second_container) {
mLastFocusedViewId = R.id.info_container;
}
break;
case 0:
default:
- viewHolder.mPendingAnimationRunnable = new Runnable() {
- @Override
- public void run() {
- hideActionView(viewHolder.mSecondActionContainer, View.GONE);
- hideActionView(viewHolder.mFirstActionContainer, View.GONE);
- }
- };
+ viewHolder.mPendingAnimationRunnable =
+ new Runnable() {
+ @Override
+ public void run() {
+ hideActionView(viewHolder.mSecondActionContainer, View.GONE);
+ hideActionView(viewHolder.mFirstActionContainer, View.GONE);
+ }
+ };
mLastFocusedViewId = R.id.info_container;
- SoftPreconditions.checkState(viewHolder.mInfoContainer.isFocusable(), TAG,
+ SoftPreconditions.checkState(
+ viewHolder.mInfoContainer.isFocusable(),
+ TAG,
"No focusable view in this row: " + viewHolder);
break;
}
@@ -685,7 +748,7 @@ class ScheduleRowPresenter extends RowPresenter {
// requestFocus() explicitly.
if (view.hasFocus()) {
viewHolder.mPendingAnimationRunnable.run();
- } else if (view.isFocusable()){
+ } else if (view.isFocusable()) {
view.requestFocus();
} else {
viewHolder.view.requestFocus();
@@ -705,17 +768,16 @@ class ScheduleRowPresenter extends RowPresenter {
view.setVisibility(View.VISIBLE);
}
- /**
- * Add animation when view is visible.
- */
+ /** Add animation when view is visible. */
private void showActionView(View view) {
- view.animate().alpha(1.0f).setInterpolator(new DecelerateInterpolator())
- .setDuration(mAnimationDuration).start();
+ view.animate()
+ .alpha(1.0f)
+ .setInterpolator(new DecelerateInterpolator())
+ .setDuration(mAnimationDuration)
+ .start();
}
- /**
- * Add animation when view change to invisible.
- */
+ /** Add animation when view change to invisible. */
private void hideActionView(View view, int visibility) {
if (view.getVisibility() != View.VISIBLE) {
if (view.getVisibility() != visibility) {
@@ -723,15 +785,19 @@ class ScheduleRowPresenter extends RowPresenter {
}
return;
}
- view.animate().alpha(0.0f).setInterpolator(new DecelerateInterpolator())
+ view.animate()
+ .alpha(0.0f)
+ .setInterpolator(new DecelerateInterpolator())
.setDuration(mAnimationDuration)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- view.setVisibility(visibility);
- view.animate().setListener(null);
- }
- }).start();
+ .setListener(
+ new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ view.setVisibility(visibility);
+ view.animate().setListener(null);
+ }
+ })
+ .start();
}
/**
@@ -742,8 +808,8 @@ class ScheduleRowPresenter extends RowPresenter {
protected int[] getAvailableActions(ScheduleRow row) {
if (row.getSchedule() != null) {
if (row.isRecordingInProgress()) {
- return new int[]{ACTION_STOP_RECORDING};
- } else if (row.isOnAir()) {
+ return new int[] {ACTION_STOP_RECORDING};
+ } else if (row.isOnAir() && !row.hasRecordedProgram()) {
if (row.isRecordingNotStarted()) {
if (canResolveConflict()) {
// The "START" action can change the conflict states.
@@ -754,8 +820,12 @@ class ScheduleRowPresenter extends RowPresenter {
} else if (row.isRecordingFinished()) {
return new int[] {ACTION_START_RECORDING};
} else {
- SoftPreconditions.checkState(false, TAG, "Invalid row state in checking the"
- + " available actions(on air): " + row);
+ SoftPreconditions.checkState(
+ false,
+ TAG,
+ "Invalid row state in checking the"
+ + " available actions(on air): "
+ + row);
}
} else {
if (row.isScheduleCanceled()) {
@@ -764,36 +834,39 @@ class ScheduleRowPresenter extends RowPresenter {
return new int[] {ACTION_REMOVE_SCHEDULE, ACTION_CREATE_SCHEDULE};
} else if (row.isRecordingNotStarted()) {
return new int[] {ACTION_REMOVE_SCHEDULE};
+ } else if (row.isRecordingFailed()) {
+ return new int[] {ACTION_REMOVE_SCHEDULE};
+ } else if (row.isRecordingFinished()) {
+ return new int[] {};
} else {
- SoftPreconditions.checkState(false, TAG, "Invalid row state in checking the"
- + " available actions(future schedule): " + row);
+ SoftPreconditions.checkState(
+ false,
+ TAG,
+ "Invalid row state in checking the"
+ + " available actions(future schedule): "
+ + row);
}
}
}
return null;
}
- /**
- * Check if the conflict can be resolved in this screen.
- */
+ /** Check if the conflict can be resolved in this screen. */
protected boolean canResolveConflict() {
return true;
}
- /**
- * Check if the schedule should be kept after removing it.
- */
+ /** Check if the schedule should be kept after removing it. */
protected boolean shouldKeepScheduleAfterRemoving() {
return false;
}
- /**
- * Checks if the row should be grayed out.
- */
+ /** Checks if the row should be grayed out. */
protected boolean shouldBeGrayedOut(ScheduleRow row) {
return row.getSchedule() == null
- || (row.isOnAir() && !row.isRecordingInProgress())
+ || (row.isOnAir() && !row.isRecordingInProgress() && !row.hasRecordedProgram())
|| mDvrManager.isConflicting(row.getSchedule())
- || row.isScheduleCanceled();
+ || row.isScheduleCanceled()
+ || row.isRecordingFailed();
}
}
diff --git a/src/com/android/tv/dvr/ui/list/SchedulesHeaderRow.java b/src/com/android/tv/dvr/ui/list/SchedulesHeaderRow.java
index 715ecb8c..bbddc07f 100644
--- a/src/com/android/tv/dvr/ui/list/SchedulesHeaderRow.java
+++ b/src/com/android/tv/dvr/ui/list/SchedulesHeaderRow.java
@@ -18,12 +18,9 @@ package com.android.tv.dvr.ui.list;
import com.android.tv.data.Program;
import com.android.tv.dvr.data.SeriesRecording;
-
import java.util.List;
-/**
- * A base class for the rows for schedules' header.
- */
+/** A base class for the rows for schedules' header. */
abstract class SchedulesHeaderRow {
private String mTitle;
private String mDescription;
@@ -35,51 +32,37 @@ abstract class SchedulesHeaderRow {
mDescription = description;
}
- /**
- * Sets title.
- */
+ /** Sets title. */
public void setTitle(String title) {
mTitle = title;
}
- /**
- * Sets description.
- */
+ /** Sets description. */
public void setDescription(String description) {
mDescription = description;
}
- /**
- * Sets count of items.
- */
+ /** Sets count of items. */
public void setItemCount(int itemCount) {
mItemCount = itemCount;
}
- /**
- * Returns title.
- */
+ /** Returns title. */
public String getTitle() {
return mTitle;
}
- /**
- * Returns description.
- */
+ /** Returns description. */
public String getDescription() {
return mDescription;
}
- /**
- * Returns count of items.
- */
+ /** Returns count of items. */
public int getItemCount() {
return mItemCount;
}
- /**
- * The header row which represent the date.
- */
+ /** The header row which represent the date. */
public static class DateHeaderRow extends SchedulesHeaderRow {
private long mDeadLineMs;
@@ -88,47 +71,41 @@ abstract class SchedulesHeaderRow {
mDeadLineMs = deadLineMs;
}
- /**
- * Returns the latest time of the list which belongs to the header row.
- */
+ /** Returns the latest time of the list which belongs to the header row. */
public long getDeadLineMs() {
return mDeadLineMs;
}
}
- /**
- * The header row which represent the series recording.
- */
+ /** The header row which represent the series recording. */
public static class SeriesRecordingHeaderRow extends SchedulesHeaderRow {
private SeriesRecording mSeriesRecording;
private List<Program> mPrograms;
- public SeriesRecordingHeaderRow(String title, String description, int itemCount,
- SeriesRecording series, List<Program> programs) {
+ public SeriesRecordingHeaderRow(
+ String title,
+ String description,
+ int itemCount,
+ SeriesRecording series,
+ List<Program> programs) {
super(title, description, itemCount);
mSeriesRecording = series;
mPrograms = programs;
}
- /**
- * Returns the list of programs which belong to the series.
- */
+ /** Returns the list of programs which belong to the series. */
public List<Program> getPrograms() {
return mPrograms;
}
- /**
- * Returns the series recording, it is for series schedules list.
- */
+ /** Returns the series recording, it is for series schedules list. */
public SeriesRecording getSeriesRecording() {
return mSeriesRecording;
}
- /**
- * Sets the series recording.
- */
+ /** Sets the series recording. */
public void setSeriesRecording(SeriesRecording seriesRecording) {
mSeriesRecording = seriesRecording;
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/list/SchedulesHeaderRowPresenter.java b/src/com/android/tv/dvr/ui/list/SchedulesHeaderRowPresenter.java
index fe2033ba..eb01aba2 100644
--- a/src/com/android/tv/dvr/ui/list/SchedulesHeaderRowPresenter.java
+++ b/src/com/android/tv/dvr/ui/list/SchedulesHeaderRowPresenter.java
@@ -27,16 +27,13 @@ import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.TextView;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.dvr.ui.DvrUiHelper;
import com.android.tv.dvr.ui.list.SchedulesHeaderRow.SeriesRecordingHeaderRow;
-/**
- * A base class for RowPresenter for {@link SchedulesHeaderRow}
- */
+/** A base class for RowPresenter for {@link SchedulesHeaderRow} */
abstract class SchedulesHeaderRowPresenter extends RowPresenter {
private Context mContext;
@@ -46,23 +43,20 @@ abstract class SchedulesHeaderRowPresenter extends RowPresenter {
mContext = context;
}
- /**
- * Returns the context.
- */
+ /** Returns the context. */
Context getContext() {
return mContext;
}
- /**
- * A ViewHolder for {@link SchedulesHeaderRow}.
- */
+ /** A ViewHolder for {@link SchedulesHeaderRow}. */
public static class SchedulesHeaderRowViewHolder extends RowPresenter.ViewHolder {
private TextView mTitle;
private TextView mDescription;
public SchedulesHeaderRowViewHolder(Context context, ViewGroup parent) {
- super(LayoutInflater.from(context).inflate(R.layout.dvr_schedules_header, parent,
- false));
+ super(
+ LayoutInflater.from(context)
+ .inflate(R.layout.dvr_schedules_header, parent, false));
mTitle = (TextView) view.findViewById(R.id.header_title);
mDescription = (TextView) view.findViewById(R.id.header_description);
}
@@ -77,9 +71,7 @@ abstract class SchedulesHeaderRowPresenter extends RowPresenter {
headerViewHolder.mDescription.setText(header.getDescription());
}
- /**
- * A presenter for {@link SchedulesHeaderRow.DateHeaderRow}.
- */
+ /** A presenter for {@link SchedulesHeaderRow.DateHeaderRow}. */
public static class DateHeaderRowPresenter extends SchedulesHeaderRowPresenter {
public DateHeaderRowPresenter(Context context) {
super(context);
@@ -90,10 +82,7 @@ abstract class SchedulesHeaderRowPresenter extends RowPresenter {
return new DateHeaderRowViewHolder(getContext(), parent);
}
- /**
- * A ViewHolder for
- * {@link SchedulesHeaderRow.DateHeaderRow}.
- */
+ /** A ViewHolder for {@link SchedulesHeaderRow.DateHeaderRow}. */
public static class DateHeaderRowViewHolder extends SchedulesHeaderRowViewHolder {
public DateHeaderRowViewHolder(Context context, ViewGroup parent) {
super(context, parent);
@@ -101,9 +90,7 @@ abstract class SchedulesHeaderRowPresenter extends RowPresenter {
}
}
- /**
- * A presenter for {@link SeriesRecordingHeaderRow}.
- */
+ /** A presenter for {@link SeriesRecordingHeaderRow}. */
public static class SeriesRecordingHeaderRowPresenter extends SchedulesHeaderRowPresenter {
private final boolean mLtr;
private final Drawable mSettingsDrawable;
@@ -116,8 +103,9 @@ abstract class SchedulesHeaderRowPresenter extends RowPresenter {
public SeriesRecordingHeaderRowPresenter(Context context) {
super(context);
- mLtr = context.getResources().getConfiguration().getLayoutDirection()
- == View.LAYOUT_DIRECTION_LTR;
+ mLtr =
+ context.getResources().getConfiguration().getLayoutDirection()
+ == View.LAYOUT_DIRECTION_LTR;
mSettingsDrawable = context.getDrawable(R.drawable.ic_settings);
mCancelDrawable = context.getDrawable(R.drawable.ic_dvr_cancel_large);
mResumeDrawable = context.getDrawable(R.drawable.ic_record_start);
@@ -134,8 +122,7 @@ abstract class SchedulesHeaderRowPresenter extends RowPresenter {
@Override
protected void onBindRowViewHolder(RowPresenter.ViewHolder viewHolder, Object item) {
super.onBindRowViewHolder(viewHolder, item);
- SeriesHeaderRowViewHolder headerViewHolder =
- (SeriesHeaderRowViewHolder) viewHolder;
+ SeriesHeaderRowViewHolder headerViewHolder = (SeriesHeaderRowViewHolder) viewHolder;
SeriesRecordingHeaderRow header = (SeriesRecordingHeaderRow) item;
headerViewHolder.mSeriesSettingsButton.setVisibility(
header.getSeriesRecording().isStopped() ? View.INVISIBLE : View.VISIBLE);
@@ -148,46 +135,59 @@ abstract class SchedulesHeaderRowPresenter extends RowPresenter {
headerViewHolder.mToggleStartStopButton.setText(mCancelAllInfo);
setTextDrawable(headerViewHolder.mToggleStartStopButton, mCancelDrawable);
}
- headerViewHolder.mSeriesSettingsButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- DvrUiHelper.startSeriesSettingsActivity(getContext(),
- header.getSeriesRecording().getId(),
- header.getPrograms(), false, false, false, null);
- }
- });
- headerViewHolder.mToggleStartStopButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- if (header.getSeriesRecording().isStopped()) {
- // Reset priority to the highest.
- SeriesRecording seriesRecording = SeriesRecording
- .buildFrom(header.getSeriesRecording())
- .setPriority(TvApplication.getSingletons(getContext())
- .getDvrScheduleManager().suggestNewSeriesPriority())
- .build();
- TvApplication.getSingletons(getContext()).getDvrManager()
- .updateSeriesRecording(seriesRecording);
- DvrUiHelper.startSeriesSettingsActivity(getContext(),
- header.getSeriesRecording().getId(),
- header.getPrograms(), false, false, false, null);
- } else {
- DvrUiHelper.showCancelAllSeriesRecordingDialog(
- (DvrSchedulesActivity) view.getContext(),
- header.getSeriesRecording());
- }
- }
- });
+ headerViewHolder.mSeriesSettingsButton.setOnClickListener(
+ new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ DvrUiHelper.startSeriesSettingsActivity(
+ getContext(),
+ header.getSeriesRecording().getId(),
+ header.getPrograms(),
+ false,
+ false,
+ false,
+ null);
+ }
+ });
+ headerViewHolder.mToggleStartStopButton.setOnClickListener(
+ new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (header.getSeriesRecording().isStopped()) {
+ // Reset priority to the highest.
+ SeriesRecording seriesRecording =
+ SeriesRecording.buildFrom(header.getSeriesRecording())
+ .setPriority(
+ TvSingletons.getSingletons(getContext())
+ .getDvrScheduleManager()
+ .suggestNewSeriesPriority())
+ .build();
+ TvSingletons.getSingletons(getContext())
+ .getDvrManager()
+ .updateSeriesRecording(seriesRecording);
+ DvrUiHelper.startSeriesSettingsActivity(
+ getContext(),
+ header.getSeriesRecording().getId(),
+ header.getPrograms(),
+ false,
+ false,
+ false,
+ null);
+ } else {
+ DvrUiHelper.showCancelAllSeriesRecordingDialog(
+ (DvrSchedulesActivity) view.getContext(),
+ header.getSeriesRecording());
+ }
+ }
+ });
}
private void setTextDrawable(TextView textView, Drawable drawableStart) {
- textView.setCompoundDrawablesRelativeWithIntrinsicBounds(drawableStart, null, null,
- null);
+ textView.setCompoundDrawablesRelativeWithIntrinsicBounds(
+ drawableStart, null, null, null);
}
- /**
- * A ViewHolder for {@link SeriesRecordingHeaderRow}.
- */
+ /** A ViewHolder for {@link SeriesRecordingHeaderRow}. */
public static class SeriesHeaderRowViewHolder extends SchedulesHeaderRowViewHolder {
private final TextView mSeriesSettingsButton;
private final TextView mToggleStartStopButton;
@@ -196,33 +196,40 @@ abstract class SchedulesHeaderRowPresenter extends RowPresenter {
private final View mSelector;
private View mLastFocusedView;
+
public SeriesHeaderRowViewHolder(Context context, ViewGroup parent) {
super(context, parent);
- mLtr = context.getResources().getConfiguration().getLayoutDirection()
- == View.LAYOUT_DIRECTION_LTR;
+ mLtr =
+ context.getResources().getConfiguration().getLayoutDirection()
+ == View.LAYOUT_DIRECTION_LTR;
view.findViewById(R.id.button_container).setVisibility(View.VISIBLE);
mSeriesSettingsButton = (TextView) view.findViewById(R.id.series_settings);
mToggleStartStopButton =
(TextView) view.findViewById(R.id.series_toggle_start_stop);
mSelector = view.findViewById(R.id.selector);
- OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View view, boolean focused) {
- view.post(new Runnable() {
+ OnFocusChangeListener onFocusChangeListener =
+ new View.OnFocusChangeListener() {
@Override
- public void run() {
- updateSelector(view);
+ public void onFocusChange(View view, boolean focused) {
+ view.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ updateSelector(view);
+ }
+ });
}
- });
- }
- };
+ };
mSeriesSettingsButton.setOnFocusChangeListener(onFocusChangeListener);
mToggleStartStopButton.setOnFocusChangeListener(onFocusChangeListener);
}
private void updateSelector(View focusedView) {
- int animationDuration = mSelector.getContext().getResources()
- .getInteger(android.R.integer.config_shortAnimTime);
+ int animationDuration =
+ mSelector
+ .getContext()
+ .getResources()
+ .getInteger(android.R.integer.config_shortAnimTime);
DecelerateInterpolator interpolator = new DecelerateInterpolator();
if (focusedView.hasFocus()) {
@@ -246,21 +253,38 @@ abstract class SchedulesHeaderRowPresenter extends RowPresenter {
// animate the selector in and to the proper width and translation X.
final float deltaWidth = lp.width - targetWidth;
mSelector.animate().cancel();
- mSelector.animate().translationX(targetTranslationX).alpha(1f)
- .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- // Set width to the proper width for this animation step.
- lp.width = targetWidth + Math.round(
- deltaWidth * (1f - animation.getAnimatedFraction()));
- mSelector.requestLayout();
- }
- }).setDuration(animationDuration).setInterpolator(interpolator).start();
+ mSelector
+ .animate()
+ .translationX(targetTranslationX)
+ .alpha(1f)
+ .setUpdateListener(
+ new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ // Set width to the proper width for this animation
+ // step.
+ lp.width =
+ targetWidth
+ + Math.round(
+ deltaWidth
+ * (1f
+ - animation
+ .getAnimatedFraction()));
+ mSelector.requestLayout();
+ }
+ })
+ .setDuration(animationDuration)
+ .setInterpolator(interpolator)
+ .start();
mLastFocusedView = focusedView;
} else if (mLastFocusedView == focusedView) {
mSelector.animate().setUpdateListener(null).cancel();
- mSelector.animate().alpha(0f).setDuration(animationDuration)
- .setInterpolator(interpolator).start();
+ mSelector
+ .animate()
+ .alpha(0f)
+ .setDuration(animationDuration)
+ .setInterpolator(interpolator)
+ .start();
mLastFocusedView = null;
}
}
diff --git a/src/com/android/tv/dvr/ui/list/SeriesScheduleRowAdapter.java b/src/com/android/tv/dvr/ui/list/SeriesScheduleRowAdapter.java
index 6b6de8b8..9a9c94ea 100644
--- a/src/com/android/tv/dvr/ui/list/SeriesScheduleRowAdapter.java
+++ b/src/com/android/tv/dvr/ui/list/SeriesScheduleRowAdapter.java
@@ -1,18 +1,18 @@
/*
-* Copyright (C) 2016 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
-*/
+ * Copyright (C) 2016 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.dvr.ui.list;
@@ -23,10 +23,8 @@ import android.os.Build;
import android.support.v17.leanback.widget.ClassPresenterSelector;
import android.util.ArrayMap;
import android.util.Log;
-
-import com.android.tv.ApplicationSingletons;
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
import com.android.tv.data.Program;
import com.android.tv.dvr.DvrDataManager;
@@ -35,16 +33,13 @@ import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.dvr.ui.list.SchedulesHeaderRow.SeriesRecordingHeaderRow;
import com.android.tv.util.Utils;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-/**
- * An adapter for series schedule row.
- */
+/** An adapter for series schedule row. */
@TargetApi(Build.VERSION_CODES.N)
class SeriesScheduleRowAdapter extends ScheduleRowAdapter {
private static final String TAG = "SeriesRowAdapter";
@@ -57,7 +52,9 @@ class SeriesScheduleRowAdapter extends ScheduleRowAdapter {
private final Map<Long, Program> mPrograms = new ArrayMap<>();
private SeriesRecordingHeaderRow mHeaderRow;
- public SeriesScheduleRowAdapter(Context context, ClassPresenterSelector classPresenterSelector,
+ public SeriesScheduleRowAdapter(
+ Context context,
+ ClassPresenterSelector classPresenterSelector,
SeriesRecording seriesRecording) {
super(context, classPresenterSelector);
mSeriesRecording = seriesRecording;
@@ -67,7 +64,7 @@ class SeriesScheduleRowAdapter extends ScheduleRowAdapter {
} else {
mInputId = null;
}
- ApplicationSingletons singletons = TvApplication.getSingletons(context);
+ TvSingletons singletons = TvSingletons.getSingletons(context);
mDvrManager = singletons.getDvrManager();
mDataManager = singletons.getDvrDataManager();
setHasStableIds(true);
@@ -83,9 +80,7 @@ class SeriesScheduleRowAdapter extends ScheduleRowAdapter {
super.stop();
}
- /**
- * Sets the programs to show.
- */
+ /** Sets the programs to show. */
public void setPrograms(List<Program> programs) {
if (programs == null) {
programs = Collections.emptyList();
@@ -95,8 +90,13 @@ class SeriesScheduleRowAdapter extends ScheduleRowAdapter {
List<Program> sortedPrograms = new ArrayList<>(programs);
Collections.sort(sortedPrograms);
List<EpisodicProgramRow> rows = new ArrayList<>();
- mHeaderRow = new SeriesRecordingHeaderRow(mSeriesRecording.getTitle(),
- null, sortedPrograms.size(), mSeriesRecording, programs);
+ mHeaderRow =
+ new SeriesRecordingHeaderRow(
+ mSeriesRecording.getTitle(),
+ null,
+ sortedPrograms.size(),
+ mSeriesRecording,
+ programs);
for (Program program : sortedPrograms) {
ScheduledRecording schedule =
mDataManager.getScheduledRecordingForProgramId(program.getId());
@@ -122,8 +122,14 @@ class SeriesScheduleRowAdapter extends ScheduleRowAdapter {
++conflicts;
}
}
- return conflicts == 0 ? null : getContext().getResources().getQuantityString(
- R.plurals.dvr_series_schedules_header_description, conflicts, conflicts);
+ return conflicts == 0
+ ? null
+ : getContext()
+ .getResources()
+ .getQuantityString(
+ R.plurals.dvr_series_schedules_header_description,
+ conflicts,
+ conflicts);
}
@Override
diff --git a/src/com/android/tv/dvr/ui/list/SeriesScheduleRowPresenter.java b/src/com/android/tv/dvr/ui/list/SeriesScheduleRowPresenter.java
index c8503e0d..263c579e 100644
--- a/src/com/android/tv/dvr/ui/list/SeriesScheduleRowPresenter.java
+++ b/src/com/android/tv/dvr/ui/list/SeriesScheduleRowPresenter.java
@@ -1,33 +1,30 @@
/*
-* Copyright (C) 2016 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
-*/
+ * Copyright (C) 2016 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.dvr.ui.list;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
-
import com.android.tv.R;
import com.android.tv.common.SoftPreconditions;
import com.android.tv.dvr.ui.DvrUiHelper;
import com.android.tv.util.Utils;
-/**
- * A RowPresenter for series schedule row.
- */
+/** A RowPresenter for series schedule row. */
class SeriesScheduleRowPresenter extends ScheduleRowPresenter {
private static final String TAG = "SeriesRowPresenter";
@@ -35,16 +32,18 @@ class SeriesScheduleRowPresenter extends ScheduleRowPresenter {
public SeriesScheduleRowPresenter(Context context) {
super(context);
- mLtr = context.getResources().getConfiguration().getLayoutDirection()
- == View.LAYOUT_DIRECTION_LTR;
+ mLtr =
+ context.getResources().getConfiguration().getLayoutDirection()
+ == View.LAYOUT_DIRECTION_LTR;
}
public static class SeriesScheduleRowViewHolder extends ScheduleRowViewHolder {
public SeriesScheduleRowViewHolder(View view, ScheduleRowPresenter presenter) {
super(view, presenter);
ViewGroup.LayoutParams lp = getTimeView().getLayoutParams();
- lp.width = view.getResources().getDimensionPixelSize(
- R.dimen.dvr_series_schedules_item_time_width);
+ lp.width =
+ view.getResources()
+ .getDimensionPixelSize(R.dimen.dvr_series_schedules_item_time_width);
getTimeView().setLayoutParams(lp);
}
}
@@ -56,8 +55,8 @@ class SeriesScheduleRowPresenter extends ScheduleRowPresenter {
@Override
protected String onGetRecordingTimeText(ScheduleRow row) {
- return Utils.getDurationString(getContext(), row.getStartTimeMs(), row.getEndTimeMs(),
- false, true, true, 0);
+ return Utils.getDurationString(
+ getContext(), row.getStartTimeMs(), row.getEndTimeMs(), false, true, true, 0);
}
@Override
@@ -71,11 +70,17 @@ class SeriesScheduleRowPresenter extends ScheduleRowPresenter {
SeriesScheduleRowViewHolder viewHolder = (SeriesScheduleRowViewHolder) vh;
EpisodicProgramRow row = (EpisodicProgramRow) item;
if (getDvrManager().isConflicting(row.getSchedule())) {
- viewHolder.getProgramTitleView().setCompoundDrawablePadding(getContext()
- .getResources().getDimensionPixelOffset(
- R.dimen.dvr_schedules_warning_icon_padding));
- viewHolder.getProgramTitleView().setCompoundDrawablesRelativeWithIntrinsicBounds(
- R.drawable.ic_warning_gray600_36dp, 0, 0, 0);
+ viewHolder
+ .getProgramTitleView()
+ .setCompoundDrawablePadding(
+ getContext()
+ .getResources()
+ .getDimensionPixelOffset(
+ R.dimen.dvr_schedules_warning_icon_padding));
+ viewHolder
+ .getProgramTitleView()
+ .setCompoundDrawablesRelativeWithIntrinsicBounds(
+ R.drawable.ic_warning_gray600_36dp, 0, 0, 0);
} else {
viewHolder.getProgramTitleView().setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}
@@ -88,16 +93,16 @@ class SeriesScheduleRowPresenter extends ScheduleRowPresenter {
@Override
protected void onStartRecording(ScheduleRow row) {
- SoftPreconditions.checkState(row.getSchedule() == null, TAG,
- "Start request with the existing schedule: " + row);
+ SoftPreconditions.checkState(
+ row.getSchedule() == null, TAG, "Start request with the existing schedule: " + row);
row.setStartRecordingRequested(true);
getDvrManager().addScheduleWithHighestPriority(((EpisodicProgramRow) row).getProgram());
}
@Override
protected void onStopRecording(ScheduleRow row) {
- SoftPreconditions.checkState(row.getSchedule() != null, TAG,
- "Stop request with the null schedule: " + row);
+ SoftPreconditions.checkState(
+ row.getSchedule() != null, TAG, "Stop request with the null schedule: " + row);
row.setStopRecordingRequested(true);
getDvrManager().stopRecording(row.getSchedule());
}
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlaybackActivity.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackActivity.java
index 6824cfe2..b8b19adc 100644
--- a/src/com/android/tv/dvr/ui/playback/DvrPlaybackActivity.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackActivity.java
@@ -23,16 +23,13 @@ import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.Starter;
import com.android.tv.dialog.PinDialogFragment.OnPinCheckedListener;
import com.android.tv.dvr.data.RecordedProgram;
import com.android.tv.util.Utils;
-/**
- * Activity to play a {@link RecordedProgram}.
- */
+/** Activity to play a {@link RecordedProgram}. */
public class DvrPlaybackActivity extends Activity implements OnPinCheckedListener {
private static final String TAG = "DvrPlaybackActivity";
private static final boolean DEBUG = false;
@@ -42,13 +39,14 @@ public class DvrPlaybackActivity extends Activity implements OnPinCheckedListene
@Override
public void onCreate(Bundle savedInstanceState) {
- TvApplication.setCurrentRunningProcess(this, true);
+ Starter.start(this);
if (DEBUG) Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
setIntent(createProgramIntent(getIntent()));
setContentView(R.layout.activity_dvr_playback);
- mOverlayFragment = (DvrPlaybackOverlayFragment) getFragmentManager()
- .findFragmentById(R.id.dvr_playback_controls_fragment);
+ mOverlayFragment =
+ (DvrPlaybackOverlayFragment)
+ getFragmentManager().findFragmentById(R.id.dvr_playback_controls_fragment);
}
@Override
@@ -68,7 +66,8 @@ public class DvrPlaybackActivity extends Activity implements OnPinCheckedListene
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
float density = getResources().getDisplayMetrics().density;
- mOverlayFragment.onWindowSizeChanged((int) (newConfig.screenWidthDp * density),
+ mOverlayFragment.onWindowSizeChanged(
+ (int) (newConfig.screenWidthDp * density),
(int) (newConfig.screenHeightDp * density));
}
@@ -91,4 +90,4 @@ public class DvrPlaybackActivity extends Activity implements OnPinCheckedListene
void setOnPinCheckListener(OnPinCheckedListener listener) {
mOnPinCheckedListener = listener;
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlaybackCardPresenter.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackCardPresenter.java
index 8ef0041d..a6352d95 100644
--- a/src/com/android/tv/dvr/ui/playback/DvrPlaybackCardPresenter.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackCardPresenter.java
@@ -17,14 +17,11 @@
package com.android.tv.dvr.ui.playback;
import android.content.Context;
-
import com.android.tv.R;
import com.android.tv.dvr.ui.browse.RecordedProgramPresenter;
import com.android.tv.dvr.ui.browse.RecordingCardView;
-/**
- * This class is used to generate Views and bind Objects for related recordings in DVR playback.
- */
+/** This class is used to generate Views and bind Objects for related recordings in DVR playback. */
class DvrPlaybackCardPresenter extends RecordedProgramPresenter {
private final int mRelatedRecordingCardWidth;
private final int mRelatedRecordingCardHeight;
@@ -39,7 +36,12 @@ class DvrPlaybackCardPresenter extends RecordedProgramPresenter {
@Override
public DvrItemViewHolder onCreateDvrItemViewHolder() {
- return new RecordedProgramViewHolder(new RecordingCardView(
- getContext(), mRelatedRecordingCardWidth, mRelatedRecordingCardHeight, true), null);
+ return new RecordedProgramViewHolder(
+ new RecordingCardView(
+ getContext(),
+ mRelatedRecordingCardWidth,
+ mRelatedRecordingCardHeight,
+ true),
+ null);
}
}
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlaybackControlHelper.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackControlHelper.java
index 1a6ae187..59c90d11 100644
--- a/src/com/android/tv/dvr/ui/playback/DvrPlaybackControlHelper.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackControlHelper.java
@@ -44,8 +44,8 @@ import com.android.tv.util.TimeShiftUtils;
import java.util.ArrayList;
/**
- * A helper class to assist {@link DvrPlaybackOverlayFragment} to manage its controls row and
- * send command to the media controller. It also helps to update playback states displayed in the
+ * A helper class to assist {@link DvrPlaybackOverlayFragment} to manage its controls row and send
+ * command to the media controller. It also helps to update playback states displayed in the
* fragment according to information the media session provides.
*/
class DvrPlaybackControlHelper extends PlaybackControlGlue {
@@ -74,8 +74,9 @@ class DvrPlaybackControlHelper extends PlaybackControlGlue {
mMediaController = activity.getMediaController();
mMediaController.registerCallback(mMediaControllerCallback);
mTransportControls = mMediaController.getTransportControls();
- mExtraPaddingTopForNoDescription = activity.getResources()
- .getDimensionPixelOffset(R.dimen.dvr_playback_controls_extra_padding_top);
+ mExtraPaddingTopForNoDescription =
+ activity.getResources()
+ .getDimensionPixelOffset(R.dimen.dvr_playback_controls_extra_padding_top);
mClosedCaptioningAction = new ClosedCaptioningAction(activity);
mMultiAudioAction = new MultiAudioAction(activity);
createControlsRowPresenter();
@@ -90,42 +91,47 @@ class DvrPlaybackControlHelper extends PlaybackControlGlue {
private void createControlsRowPresenter() {
AbstractDetailsDescriptionPresenter detailsPresenter =
new AbstractDetailsDescriptionPresenter() {
- @Override
- protected void onBindDescription(
- AbstractDetailsDescriptionPresenter.ViewHolder viewHolder, Object object) {
- PlaybackControlGlue glue = (PlaybackControlGlue) object;
- if (glue.hasValidMedia()) {
- viewHolder.getTitle().setText(glue.getMediaTitle());
- viewHolder.getSubtitle().setText(glue.getMediaSubtitle());
- } else {
- viewHolder.getTitle().setText("");
- viewHolder.getSubtitle().setText("");
- }
- if (TextUtils.isEmpty(viewHolder.getSubtitle().getText())) {
- viewHolder.view.setPadding(viewHolder.view.getPaddingLeft(),
- mExtraPaddingTopForNoDescription,
- viewHolder.view.getPaddingRight(), viewHolder.view.getPaddingBottom());
- }
- }
- };
+ @Override
+ protected void onBindDescription(
+ AbstractDetailsDescriptionPresenter.ViewHolder viewHolder,
+ Object object) {
+ PlaybackControlGlue glue = (PlaybackControlGlue) object;
+ if (glue.hasValidMedia()) {
+ viewHolder.getTitle().setText(glue.getMediaTitle());
+ viewHolder.getSubtitle().setText(glue.getMediaSubtitle());
+ } else {
+ viewHolder.getTitle().setText("");
+ viewHolder.getSubtitle().setText("");
+ }
+ if (TextUtils.isEmpty(viewHolder.getSubtitle().getText())) {
+ viewHolder.view.setPadding(
+ viewHolder.view.getPaddingLeft(),
+ mExtraPaddingTopForNoDescription,
+ viewHolder.view.getPaddingRight(),
+ viewHolder.view.getPaddingBottom());
+ }
+ }
+ };
PlaybackControlsRowPresenter presenter =
new PlaybackControlsRowPresenter(detailsPresenter) {
- @Override
- protected void onBindRowViewHolder(RowPresenter.ViewHolder vh, Object item) {
- super.onBindRowViewHolder(vh, item);
- vh.setOnKeyListener(DvrPlaybackControlHelper.this);
- }
-
- @Override
- protected void onUnbindRowViewHolder(RowPresenter.ViewHolder vh) {
- super.onUnbindRowViewHolder(vh);
- vh.setOnKeyListener(null);
- }
- };
- presenter.setProgressColor(getContext().getResources()
- .getColor(R.color.play_controls_progress_bar_watched));
- presenter.setBackgroundColor(getContext().getResources()
- .getColor(R.color.play_controls_body_background_enabled));
+ @Override
+ protected void onBindRowViewHolder(RowPresenter.ViewHolder vh, Object item) {
+ super.onBindRowViewHolder(vh, item);
+ vh.setOnKeyListener(DvrPlaybackControlHelper.this);
+ }
+
+ @Override
+ protected void onUnbindRowViewHolder(RowPresenter.ViewHolder vh) {
+ super.onUnbindRowViewHolder(vh);
+ vh.setOnKeyListener(null);
+ }
+ };
+ presenter.setProgressColor(
+ getContext().getResources().getColor(R.color.play_controls_progress_bar_watched));
+ presenter.setBackgroundColor(
+ getContext()
+ .getResources()
+ .getColor(R.color.play_controls_body_background_enabled));
setControlsRowPresenter(presenter);
}
@@ -166,37 +172,40 @@ class DvrPlaybackControlHelper extends PlaybackControlGlue {
return false;
}
int state = playbackState.getState();
- return state != PlaybackState.STATE_NONE && state != PlaybackState.STATE_CONNECTING
+ return state != PlaybackState.STATE_NONE
+ && state != PlaybackState.STATE_CONNECTING
&& state != PlaybackState.STATE_PAUSED;
}
- /**
- * Returns the ID of the media under playback.
- */
+ /** Returns the ID of the media under playback. */
public String getMediaId() {
MediaMetadata mediaMetadata = mMediaController.getMetadata();
- return mediaMetadata == null ? null
+ return mediaMetadata == null
+ ? null
: mediaMetadata.getString(MediaMetadata.METADATA_KEY_MEDIA_ID);
}
@Override
public CharSequence getMediaTitle() {
MediaMetadata mediaMetadata = mMediaController.getMetadata();
- return mediaMetadata == null ? ""
+ return mediaMetadata == null
+ ? ""
: mediaMetadata.getString(MediaMetadata.METADATA_KEY_TITLE);
}
@Override
public CharSequence getMediaSubtitle() {
MediaMetadata mediaMetadata = mMediaController.getMetadata();
- return mediaMetadata == null ? ""
+ return mediaMetadata == null
+ ? ""
: mediaMetadata.getString(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE);
}
@Override
public int getMediaDuration() {
MediaMetadata mediaMetadata = mMediaController.getMetadata();
- return mediaMetadata == null ? 0
+ return mediaMetadata == null
+ ? 0
: (int) mediaMetadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
}
@@ -225,19 +234,18 @@ class DvrPlaybackControlHelper extends PlaybackControlGlue {
return (int) playbackState.getPosition();
}
- /**
- * Unregister media controller's callback.
- */
+ /** Unregister media controller's callback. */
void unregisterCallback() {
mMediaController.unregisterCallback(mMediaControllerCallback);
}
/**
* Update the secondary controls row.
- * @param hasClosedCaption {@code true} to show the closed caption selection button,
- * {@code false} to hide it.
- * @param hasMultiAudio {@code true} to show the audio track selection button,
- * {@code false} to hide it.
+ *
+ * @param hasClosedCaption {@code true} to show the closed caption selection button, {@code
+ * false} to hide it.
+ * @param hasMultiAudio {@code true} to show the audio track selection button, {@code false} to
+ * hide it.
*/
void updateSecondaryRow(boolean hasClosedCaption, boolean hasMultiAudio) {
if (hasClosedCaption) {
@@ -274,7 +282,7 @@ class DvrPlaybackControlHelper extends PlaybackControlGlue {
mTransportControls.play();
} else if (speedId <= -PLAYBACK_SPEED_FAST_L0) {
mTransportControls.rewind();
- } else if (speedId >= PLAYBACK_SPEED_FAST_L0){
+ } else if (speedId >= PLAYBACK_SPEED_FAST_L0) {
mTransportControls.fastForward();
}
}
@@ -284,12 +292,10 @@ class DvrPlaybackControlHelper extends PlaybackControlGlue {
mTransportControls.pause();
}
- /**
- * Notifies closed caption being enabled/disabled to update related UI.
- */
+ /** Notifies closed caption being enabled/disabled to update related UI. */
void onSubtitleTrackStateChanged(boolean enabled) {
- mClosedCaptioningAction.setIndex(enabled ?
- ClosedCaptioningAction.ON : ClosedCaptioningAction.OFF);
+ mClosedCaptioningAction.setIndex(
+ enabled ? ClosedCaptioningAction.ON : ClosedCaptioningAction.OFF);
}
private void onStateChanged(int state, long positionMs, int speedLevel) {
@@ -344,7 +350,9 @@ class DvrPlaybackControlHelper extends PlaybackControlGlue {
args.putString(DvrPlaybackSideFragment.SELECTED_TRACK_ID, selectedTrackId);
DvrPlaybackSideFragment sideFragment = new DvrPlaybackSideFragment();
sideFragment.setArguments(args);
- mFragment.getFragmentManager().beginTransaction()
+ mFragment
+ .getFragmentManager()
+ .beginTransaction()
.hide(mFragment)
.replace(R.id.dvr_playback_side_fragment, sideFragment)
.addToBackStack(null)
@@ -367,7 +375,7 @@ class DvrPlaybackControlHelper extends PlaybackControlGlue {
private static class MultiAudioAction extends MultiAction {
MultiAudioAction(Context context) {
super(AUDIO_ACTION_ID);
- setDrawables(new Drawable[]{context.getDrawable(R.drawable.ic_tvoption_multi_track)});
+ setDrawables(new Drawable[] {context.getDrawable(R.drawable.ic_tvoption_multi_track)});
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlaybackMediaSessionHelper.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackMediaSessionHelper.java
index 843d2dbe..bef036eb 100644
--- a/src/com/android/tv/dvr/ui/playback/DvrPlaybackMediaSessionHelper.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackMediaSessionHelper.java
@@ -28,17 +28,15 @@ import android.media.tv.TvContract;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import android.text.TextUtils;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
-import com.android.tv.common.SoftPreconditions;
-import com.android.tv.data.Channel;
+import com.android.tv.TvSingletons;
import com.android.tv.data.ChannelDataManager;
+import com.android.tv.data.api.Channel;
import com.android.tv.dvr.DvrWatchedPositionManager;
import com.android.tv.dvr.data.RecordedProgram;
-import com.android.tv.util.ImageLoader;
import com.android.tv.util.TimeShiftUtils;
import com.android.tv.util.Utils;
+import com.android.tv.util.images.ImageLoader;
class DvrPlaybackMediaSessionHelper {
private static final String TAG = "DvrPlaybackMediaSessionHelper";
@@ -55,49 +53,52 @@ class DvrPlaybackMediaSessionHelper {
private final DvrWatchedPositionManager mDvrWatchedPositionManager;
private final ChannelDataManager mChannelDataManager;
- public DvrPlaybackMediaSessionHelper(Activity activity, String mediaSessionTag,
- DvrPlayer dvrPlayer, DvrPlaybackOverlayFragment overlayFragment) {
+ public DvrPlaybackMediaSessionHelper(
+ Activity activity,
+ String mediaSessionTag,
+ DvrPlayer dvrPlayer,
+ DvrPlaybackOverlayFragment overlayFragment) {
mActivity = activity;
mDvrPlayer = dvrPlayer;
mDvrWatchedPositionManager =
- TvApplication.getSingletons(activity).getDvrWatchedPositionManager();
- mChannelDataManager = TvApplication.getSingletons(activity).getChannelDataManager();
- mDvrPlayer.setCallback(new DvrPlayer.DvrPlayerCallback() {
- @Override
- public void onPlaybackStateChanged(int playbackState, int playbackSpeed) {
- updateMediaSessionPlaybackState();
- }
+ TvSingletons.getSingletons(activity).getDvrWatchedPositionManager();
+ mChannelDataManager = TvSingletons.getSingletons(activity).getChannelDataManager();
+ mDvrPlayer.setCallback(
+ new DvrPlayer.DvrPlayerCallback() {
+ @Override
+ public void onPlaybackStateChanged(int playbackState, int playbackSpeed) {
+ updateMediaSessionPlaybackState();
+ }
- @Override
- public void onPlaybackPositionChanged(long positionMs) {
- updateMediaSessionPlaybackState();
- if (mDvrPlayer.isPlaybackPrepared()) {
- mDvrWatchedPositionManager
- .setWatchedPosition(mDvrPlayer.getProgram().getId(), positionMs);
- }
- }
+ @Override
+ public void onPlaybackPositionChanged(long positionMs) {
+ updateMediaSessionPlaybackState();
+ if (mDvrPlayer.isPlaybackPrepared()) {
+ mDvrWatchedPositionManager.setWatchedPosition(
+ mDvrPlayer.getProgram().getId(), positionMs);
+ }
+ }
- @Override
- public void onPlaybackEnded() {
- // TODO: Deal with watched over recordings in DVR library
- RecordedProgram nextEpisode =
- overlayFragment.getNextEpisode(mDvrPlayer.getProgram());
- if (nextEpisode == null) {
- mDvrPlayer.reset();
- mActivity.finish();
- } else {
- Intent intent = new Intent(activity, DvrPlaybackActivity.class);
- intent.putExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_ID, nextEpisode.getId());
- mActivity.startActivity(intent);
- }
- }
- });
+ @Override
+ public void onPlaybackEnded() {
+ // TODO: Deal with watched over recordings in DVR library
+ RecordedProgram nextEpisode =
+ overlayFragment.getNextEpisode(mDvrPlayer.getProgram());
+ if (nextEpisode == null) {
+ mDvrPlayer.reset();
+ mActivity.finish();
+ } else {
+ Intent intent = new Intent(activity, DvrPlaybackActivity.class);
+ intent.putExtra(
+ Utils.EXTRA_KEY_RECORDED_PROGRAM_ID, nextEpisode.getId());
+ mActivity.startActivity(intent);
+ }
+ }
+ });
initializeMediaSession(mediaSessionTag);
}
- /**
- * Stops DVR player and release media session.
- */
+ /** Stops DVR player and release media session. */
public void release() {
if (mDvrPlayer != null) {
mDvrPlayer.reset();
@@ -108,13 +109,15 @@ class DvrPlaybackMediaSessionHelper {
}
}
- /**
- * Updates media session's playback state and speed.
- */
+ /** Updates media session's playback state and speed. */
public void updateMediaSessionPlaybackState() {
- mMediaSession.setPlaybackState(new PlaybackState.Builder()
- .setState(mDvrPlayer.getPlaybackState(), mDvrPlayer.getPlaybackPosition(),
- mSpeedLevel).build());
+ mMediaSession.setPlaybackState(
+ new PlaybackState.Builder()
+ .setState(
+ mDvrPlayer.getPlaybackState(),
+ mDvrPlayer.getPlaybackPosition(),
+ mSpeedLevel)
+ .build());
}
/**
@@ -132,42 +135,35 @@ class DvrPlaybackMediaSessionHelper {
}
}
- /**
- * Returns the recorded program now playing.
- */
+ /** Returns the recorded program now playing. */
public RecordedProgram getProgram() {
return mDvrPlayer.getProgram();
}
- /**
- * Checks if the recorded program is the same as now playing one.
- */
+ /** Checks if the recorded program is the same as now playing one. */
public boolean isCurrentProgram(RecordedProgram program) {
return program != null && program.equals(getProgram());
}
- /**
- * Returns playback state.
- */
+ /** Returns playback state. */
public int getPlaybackState() {
return mDvrPlayer.getPlaybackState();
}
- /**
- * Returns the underlying DVR player.
- */
+ /** Returns the underlying DVR player. */
public DvrPlayer getDvrPlayer() {
return mDvrPlayer;
}
private void initializeMediaSession(String mediaSessionTag) {
mMediaSession = new MediaSession(mActivity, mediaSessionTag);
- mMediaSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS
- | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
- mNowPlayingCardWidth = mActivity.getResources()
- .getDimensionPixelSize(R.dimen.notif_card_img_max_width);
- mNowPlayingCardHeight = mActivity.getResources()
- .getDimensionPixelSize(R.dimen.notif_card_img_height);
+ mMediaSession.setFlags(
+ MediaSession.FLAG_HANDLES_MEDIA_BUTTONS
+ | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
+ mNowPlayingCardWidth =
+ mActivity.getResources().getDimensionPixelSize(R.dimen.notif_card_img_max_width);
+ mNowPlayingCardHeight =
+ mActivity.getResources().getDimensionPixelSize(R.dimen.notif_card_img_height);
mMediaSession.setCallback(new MediaSessionCallback());
mActivity.setMediaController(
new MediaController(mActivity, mMediaSession.getSessionToken()));
@@ -179,11 +175,17 @@ class DvrPlaybackMediaSessionHelper {
String cardTitleText = program.getTitle();
if (TextUtils.isEmpty(cardTitleText)) {
Channel channel = mChannelDataManager.getChannel(program.getChannelId());
- cardTitleText = (channel != null) ? channel.getDisplayName()
- : mActivity.getString(R.string.no_program_information);
+ cardTitleText =
+ (channel != null)
+ ? channel.getDisplayName()
+ : mActivity.getString(R.string.no_program_information);
}
- final MediaMetadata currentMetadata = updateMetadataTextInfo(program.getId(), cardTitleText,
- program.getDescription(), mProgramDurationMs);
+ final MediaMetadata currentMetadata =
+ updateMetadataTextInfo(
+ program.getId(),
+ cardTitleText,
+ program.getDescription(),
+ mProgramDurationMs);
String posterArtUri = program.getPosterArtUri();
if (posterArtUri == null) {
posterArtUri = TvContract.buildChannelLogoUri(program.getChannelId()).toString();
@@ -192,12 +194,18 @@ class DvrPlaybackMediaSessionHelper {
mMediaSession.setActive(true);
}
- private void updatePosterArt(RecordedProgram program, MediaMetadata currentMetadata,
- @Nullable Bitmap posterArt, @Nullable String posterArtUri) {
+ private void updatePosterArt(
+ RecordedProgram program,
+ MediaMetadata currentMetadata,
+ @Nullable Bitmap posterArt,
+ @Nullable String posterArtUri) {
if (posterArt != null) {
updateMetadataImageInfo(program, currentMetadata, posterArt, 0);
} else if (posterArtUri != null) {
- ImageLoader.loadBitmap(mActivity, posterArtUri, mNowPlayingCardWidth,
+ ImageLoader.loadBitmap(
+ mActivity,
+ posterArtUri,
+ mNowPlayingCardWidth,
mNowPlayingCardHeight,
new ProgramPosterArtCallback(mActivity, program, currentMetadata));
} else {
@@ -205,13 +213,12 @@ class DvrPlaybackMediaSessionHelper {
}
}
- private class ProgramPosterArtCallback extends
- ImageLoader.ImageLoaderCallback<Activity> {
+ private class ProgramPosterArtCallback extends ImageLoader.ImageLoaderCallback<Activity> {
private final RecordedProgram mRecordedProgram;
private final MediaMetadata mCurrentMetadata;
- public ProgramPosterArtCallback(Activity activity, RecordedProgram program,
- MediaMetadata metadata) {
+ public ProgramPosterArtCallback(
+ Activity activity, RecordedProgram program, MediaMetadata metadata) {
super(activity);
mRecordedProgram = program;
mCurrentMetadata = metadata;
@@ -225,8 +232,8 @@ class DvrPlaybackMediaSessionHelper {
}
}
- private MediaMetadata updateMetadataTextInfo(final long programId, final String title,
- final String subtitle, final long duration) {
+ private MediaMetadata updateMetadataTextInfo(
+ final long programId, final String title, final String subtitle, final long duration) {
MediaMetadata.Builder builder = new MediaMetadata.Builder();
builder.putString(MediaMetadata.METADATA_KEY_MEDIA_ID, Long.toString(programId))
.putString(MediaMetadata.METADATA_KEY_TITLE, title)
@@ -239,8 +246,11 @@ class DvrPlaybackMediaSessionHelper {
return metadata;
}
- private void updateMetadataImageInfo(final RecordedProgram program,
- final MediaMetadata currentMetadata, final Bitmap posterArt, final int imageResId) {
+ private void updateMetadataImageInfo(
+ final RecordedProgram program,
+ final MediaMetadata currentMetadata,
+ final Bitmap posterArt,
+ final int imageResId) {
if (mMediaSession != null && (posterArt != null || imageResId != 0)) {
MediaMetadata.Builder builder = new MediaMetadata.Builder(currentMetadata);
if (posterArt != null) {
@@ -255,7 +265,8 @@ class DvrPlaybackMediaSessionHelper {
@Override
protected void onPostExecute(Bitmap programPosterArt) {
- if (mMediaSession != null && programPosterArt != null
+ if (mMediaSession != null
+ && programPosterArt != null
&& isCurrentProgram(program)) {
builder.putBitmap(MediaMetadata.METADATA_KEY_ART, programPosterArt);
mMediaSession.setMetadata(builder.build());
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlaybackOverlayFragment.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackOverlayFragment.java
index 783ae682..d3374cfa 100644
--- a/src/com/android/tv/dvr/ui/playback/DvrPlaybackOverlayFragment.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackOverlayFragment.java
@@ -21,12 +21,12 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.hardware.display.DisplayManager;
-import android.media.tv.TvContentRating;
-import android.media.tv.TvTrackInfo;
-import android.os.Bundle;
import android.media.session.PlaybackState;
+import android.media.tv.TvContentRating;
import android.media.tv.TvInputManager;
+import android.media.tv.TvTrackInfo;
import android.media.tv.TvView;
+import android.os.Bundle;
import android.support.v17.leanback.app.PlaybackFragment;
import android.support.v17.leanback.app.PlaybackFragmentGlueHost;
import android.support.v17.leanback.widget.ArrayObjectAdapter;
@@ -37,14 +37,13 @@ import android.support.v17.leanback.widget.ListRow;
import android.support.v17.leanback.widget.Presenter;
import android.support.v17.leanback.widget.RowPresenter;
import android.support.v17.leanback.widget.SinglePresenterSelector;
+import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
-import android.util.Log;
-
import com.android.tv.R;
-import com.android.tv.TvApplication;
+import com.android.tv.TvSingletons;
import com.android.tv.data.BaseProgram;
import com.android.tv.dialog.PinDialogFragment;
import com.android.tv.dvr.DvrDataManager;
@@ -57,9 +56,8 @@ import com.android.tv.parental.ContentRatingsManager;
import com.android.tv.util.TvSettings;
import com.android.tv.util.TvTrackInfoUtils;
import com.android.tv.util.Utils;
-
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
public class DvrPlaybackOverlayFragment extends PlaybackFragment {
// TODO: Handles audio focus. Deals with block and ratings.
@@ -104,15 +102,25 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
public void onCreate(Bundle savedInstanceState) {
if (DEBUG) Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
- mVerticalPaddingBase = getActivity().getResources()
- .getDimensionPixelOffset(R.dimen.dvr_playback_overlay_padding_top_base);
- mPaddingWithoutRelatedRow = getActivity().getResources()
- .getDimensionPixelOffset(R.dimen.dvr_playback_overlay_padding_top_no_related_row);
- mPaddingWithoutSecondaryRow = getActivity().getResources()
- .getDimensionPixelOffset(R.dimen.dvr_playback_overlay_padding_top_no_secondary_row);
- mDvrDataManager = TvApplication.getSingletons(getActivity()).getDvrDataManager();
- mContentRatingsManager = TvApplication.getSingletons(getContext())
- .getTvInputManagerHelper().getContentRatingsManager();
+ mVerticalPaddingBase =
+ getActivity()
+ .getResources()
+ .getDimensionPixelOffset(R.dimen.dvr_playback_overlay_padding_top_base);
+ mPaddingWithoutRelatedRow =
+ getActivity()
+ .getResources()
+ .getDimensionPixelOffset(
+ R.dimen.dvr_playback_overlay_padding_top_no_related_row);
+ mPaddingWithoutSecondaryRow =
+ getActivity()
+ .getResources()
+ .getDimensionPixelOffset(
+ R.dimen.dvr_playback_overlay_padding_top_no_secondary_row);
+ mDvrDataManager = TvSingletons.getSingletons(getActivity()).getDvrDataManager();
+ mContentRatingsManager =
+ TvSingletons.getSingletons(getContext())
+ .getTvInputManagerHelper()
+ .getContentRatingsManager();
if (!mDvrDataManager.isRecordedProgramLoadFinished()) {
mDvrDataManager.addRecordedProgramLoadFinishedListener(
new DvrDataManager.OnRecordedProgramLoadFinishedListener() {
@@ -124,14 +132,14 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
preparePlayback(getActivity().getIntent());
}
}
- }
- );
+ });
} else if (!handleIntent(getActivity().getIntent(), true)) {
return;
}
Point size = new Point();
((DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE))
- .getDisplay(Display.DEFAULT_DISPLAY).getSize(size);
+ .getDisplay(Display.DEFAULT_DISPLAY)
+ .getSize(size);
mWindowWidth = size.x;
mWindowHeight = size.y;
mWindowAspectRatio = mAppliedAspectRatio = (float) mWindowWidth / mWindowHeight;
@@ -152,19 +160,20 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
mTvView = (TvView) getActivity().findViewById(R.id.dvr_tv_view);
mBlockScreenView = getActivity().findViewById(R.id.block_screen);
mDvrPlayer = new DvrPlayer(mTvView);
- mMediaSessionHelper = new DvrPlaybackMediaSessionHelper(
- getActivity(), MEDIA_SESSION_TAG, mDvrPlayer, this);
+ mMediaSessionHelper =
+ new DvrPlaybackMediaSessionHelper(
+ getActivity(), MEDIA_SESSION_TAG, mDvrPlayer, this);
mPlaybackControlHelper = new DvrPlaybackControlHelper(getActivity(), this);
mRelatedRecordingsRow = getRelatedRecordingsRow();
mDvrPlayer.setOnTracksAvailabilityChangedListener(
new DvrPlayer.OnTracksAvailabilityChangedListener() {
@Override
- public void onTracksAvailabilityChanged(boolean hasClosedCaption,
- boolean hasMultiAudio) {
+ public void onTracksAvailabilityChanged(
+ boolean hasClosedCaption, boolean hasMultiAudio) {
mPlaybackControlHelper.updateSecondaryRow(hasClosedCaption, hasMultiAudio);
if (hasClosedCaption) {
- mDvrPlayer.setOnTrackSelectedListener(TvTrackInfo.TYPE_SUBTITLE,
- mOnSubtitleTrackSelectedListener);
+ mDvrPlayer.setOnTrackSelectedListener(
+ TvTrackInfo.TYPE_SUBTITLE, mOnSubtitleTrackSelectedListener);
selectBestMatchedTrack(TvTrackInfo.TYPE_SUBTITLE);
} else {
mDvrPlayer.setOnTrackSelectedListener(TvTrackInfo.TYPE_SUBTITLE, null);
@@ -175,15 +184,18 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
updateVerticalPosition();
mPlaybackControlHelper.getHost().notifyPlaybackRowChanged();
}
- });
- mDvrPlayer.setOnAspectRatioChangedListener(new DvrPlayer.OnAspectRatioChangedListener() {
- @Override
- public void onAspectRatioChanged(float videoAspectRatio) {
- updateAspectRatio(videoAspectRatio);
- }
- });
- mPinChecked = getActivity().getIntent()
- .getBooleanExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_PIN_CHECKED, false);
+ });
+ mDvrPlayer.setOnAspectRatioChangedListener(
+ new DvrPlayer.OnAspectRatioChangedListener() {
+ @Override
+ public void onAspectRatioChanged(float videoAspectRatio) {
+ updateAspectRatio(videoAspectRatio);
+ }
+ });
+ mPinChecked =
+ getActivity()
+ .getIntent()
+ .getBooleanExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_PIN_CHECKED, false);
mDvrPlayer.setOnContentBlockedListener(
new DvrPlayer.OnContentBlockedListener() {
@Override
@@ -221,20 +233,25 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
PinDialogFragment.DIALOG_TAG);
}
});
- setOnItemViewClickedListener(new BaseOnItemViewClickedListener() {
- @Override
- public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
- RowPresenter.ViewHolder rowViewHolder, Object row) {
- if (itemViewHolder.view instanceof RecordingCardView) {
- setFadingEnabled(false);
- long programId = ((RecordedProgram) itemViewHolder.view.getTag()).getId();
- if (DEBUG) Log.d(TAG, "Play Related Recording:" + programId);
- Intent intent = new Intent(getContext(), DvrPlaybackActivity.class);
- intent.putExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_ID, programId);
- getContext().startActivity(intent);
- }
- }
- });
+ setOnItemViewClickedListener(
+ new BaseOnItemViewClickedListener() {
+ @Override
+ public void onItemClicked(
+ Presenter.ViewHolder itemViewHolder,
+ Object item,
+ RowPresenter.ViewHolder rowViewHolder,
+ Object row) {
+ if (itemViewHolder.view instanceof RecordingCardView) {
+ setFadingEnabled(false);
+ long programId =
+ ((RecordedProgram) itemViewHolder.view.getTag()).getId();
+ if (DEBUG) Log.d(TAG, "Play Related Recording:" + programId);
+ Intent intent = new Intent(getContext(), DvrPlaybackActivity.class);
+ intent.putExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_ID, programId);
+ getContext().startActivity(intent);
+ }
+ }
+ });
if (mProgram != null) {
setUpRows();
preparePlayback(getActivity().getIntent());
@@ -265,9 +282,7 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
super.onDestroy();
}
- /**
- * Passes the intent to the fragment.
- */
+ /** Passes the intent to the fragment. */
public void onNewIntent(Intent intent) {
if (mDvrDataManager.isRecordedProgramLoadFinished() && handleIntent(intent, false)) {
preparePlayback(intent);
@@ -275,8 +290,8 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
}
/**
- * Should be called when windows' size is changed in order to notify DVR player
- * to update it's view width/height and position.
+ * Should be called when windows' size is changed in order to notify DVR player to update it's
+ * view width/height and position.
*/
public void onWindowSizeChanged(final int windowWidth, final int windowHeight) {
mWindowWidth = windowWidth;
@@ -285,9 +300,7 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
updateAspectRatio(mAppliedAspectRatio);
}
- /**
- * Returns next recorded episode in the same series as now playing program.
- */
+ /** Returns next recorded episode in the same series as now playing program. */
public RecordedProgram getNextEpisode(RecordedProgram program) {
int position = mRelatedRecordingsRowAdapter.findInsertPosition(program);
if (position == mRelatedRecordingsRowAdapter.size()) {
@@ -299,9 +312,9 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
/**
* Returns the tracks of the give type of the current playback.
-
- * @param trackType Should be {@link TvTrackInfo#TYPE_SUBTITLE}
- * or {@link TvTrackInfo#TYPE_AUDIO}. Or returns {@code null}.
+ *
+ * @param trackType Should be {@link TvTrackInfo#TYPE_SUBTITLE} or {@link
+ * TvTrackInfo#TYPE_AUDIO}. Or returns {@code null}.
*/
public ArrayList<TvTrackInfo> getTracks(int trackType) {
if (trackType == TvTrackInfo.TYPE_AUDIO) {
@@ -312,18 +325,16 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
return null;
}
- /**
- * Returns the ID of the selected track of the given type.
- */
+ /** Returns the ID of the selected track of the given type. */
public String getSelectedTrackId(int trackType) {
return mDvrPlayer.getSelectedTrackId(trackType);
}
/**
* Returns the language setting of the given track type.
-
- * @param trackType Should be {@link TvTrackInfo#TYPE_SUBTITLE}
- * or {@link TvTrackInfo#TYPE_AUDIO}.
+ *
+ * @param trackType Should be {@link TvTrackInfo#TYPE_SUBTITLE} or {@link
+ * TvTrackInfo#TYPE_AUDIO}.
* @return {@code null} if no language has been set for the given track type.
*/
TvTrackInfo getTrackSetting(int trackType) {
@@ -332,10 +343,11 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
/**
* Selects the given audio or subtitle track for DVR playback.
- * @param trackType Should be {@link TvTrackInfo#TYPE_SUBTITLE}
- * or {@link TvTrackInfo#TYPE_AUDIO}.
+ *
+ * @param trackType Should be {@link TvTrackInfo#TYPE_SUBTITLE} or {@link
+ * TvTrackInfo#TYPE_AUDIO}.
* @param selectedTrack {@code null} to disable the audio or subtitle track according to
- * trackType.
+ * trackType.
*/
void selectTrack(int trackType, TvTrackInfo selectedTrack) {
if (mDvrPlayer.isPlaybackPrepared()) {
@@ -346,8 +358,11 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
private boolean handleIntent(Intent intent, boolean finishActivity) {
mProgram = getProgramFromIntent(intent);
if (mProgram == null) {
- Toast.makeText(getActivity(), getString(R.string.dvr_program_not_found),
- Toast.LENGTH_SHORT).show();
+ Toast.makeText(
+ getActivity(),
+ getString(R.string.dvr_program_not_found),
+ Toast.LENGTH_SHORT)
+ .show();
if (finishActivity) {
getActivity().finish();
}
@@ -359,12 +374,18 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
private void selectBestMatchedTrack(int trackType) {
TvTrackInfo selectedTrack = getTrackSetting(trackType);
if (selectedTrack != null) {
- TvTrackInfo bestMatchedTrack = TvTrackInfoUtils.getBestTrackInfo(getTracks(trackType),
- selectedTrack.getId(), selectedTrack.getLanguage(),
- trackType == TvTrackInfo.TYPE_AUDIO ? selectedTrack.getAudioChannelCount() : 0);
- if (bestMatchedTrack != null && (trackType == TvTrackInfo.TYPE_AUDIO || Utils
- .isEqualLanguage(bestMatchedTrack.getLanguage(),
- selectedTrack.getLanguage()))) {
+ TvTrackInfo bestMatchedTrack =
+ TvTrackInfoUtils.getBestTrackInfo(
+ getTracks(trackType),
+ selectedTrack.getId(),
+ selectedTrack.getLanguage(),
+ trackType == TvTrackInfo.TYPE_AUDIO
+ ? selectedTrack.getAudioChannelCount()
+ : 0);
+ if (bestMatchedTrack != null
+ && (trackType == TvTrackInfo.TYPE_AUDIO
+ || Utils.isEqualLanguage(
+ bestMatchedTrack.getLanguage(), selectedTrack.getLanguage()))) {
selectTrack(trackType, bestMatchedTrack);
return;
}
@@ -421,7 +442,7 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
}
if (mRelatedRecordingsRowAdapter.size() == 0) {
mRowsAdapter.remove(mRelatedRecordingsRow);
- } else if (wasEmpty){
+ } else if (wasEmpty) {
mRowsAdapter.add(mRelatedRecordingsRow);
}
updateVerticalPosition();
@@ -446,8 +467,9 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
private ListRow getRelatedRecordingsRow() {
mRelatedRecordingCardPresenter = new DvrPlaybackCardPresenter(getActivity());
mRelatedRecordingsRowAdapter = new RelatedRecordingsAdapter(mRelatedRecordingCardPresenter);
- HeaderItem header = new HeaderItem(0,
- getActivity().getString(R.string.dvr_playback_related_recordings));
+ HeaderItem header =
+ new HeaderItem(
+ 0, getActivity().getString(R.string.dvr_playback_related_recordings));
return new ListRow(header, mRelatedRecordingsRowAdapter);
}
@@ -457,8 +479,8 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
}
private long getSeekTimeFromIntent(Intent intent) {
- return intent.getLongExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_SEEK_TIME,
- TvInputManager.TIME_SHIFT_INVALID_TIME);
+ return intent.getLongExtra(
+ Utils.EXTRA_KEY_RECORDED_PROGRAM_SEEK_TIME, TvInputManager.TIME_SHIFT_INVALID_TIME);
}
private void updateVerticalPosition() {
@@ -491,4 +513,4 @@ public class DvrPlaybackOverlayFragment extends PlaybackFragment {
return item.getId();
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlaybackSideFragment.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackSideFragment.java
index e49870f1..b4481df8 100644
--- a/src/com/android/tv/dvr/ui/playback/DvrPlaybackSideFragment.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackSideFragment.java
@@ -26,24 +26,16 @@ import android.transition.Transition;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
import com.android.tv.R;
import com.android.tv.util.TvSettings;
-
import java.util.List;
import java.util.Locale;
-/**
- * Fragment for DVR playback closed-caption/multi-audio settings.
- */
+/** Fragment for DVR playback closed-caption/multi-audio settings. */
public class DvrPlaybackSideFragment extends GuidedStepFragment {
- /**
- * The tag for passing track infos to side fragments.
- */
+ /** The tag for passing track infos to side fragments. */
public static final String TRACK_INFOS = "dvr_key_track_infos";
- /**
- * The tag for passing selected track's ID to side fragments.
- */
+ /** The tag for passing selected track's ID to side fragments. */
public static final String SELECTED_TRACK_ID = "dvr_key_selected_track_id";
private static final int ACTION_ID_NO_SUBTITLE = -1;
@@ -60,39 +52,42 @@ public class DvrPlaybackSideFragment extends GuidedStepFragment {
mTrackInfos = getArguments().getParcelableArrayList(TRACK_INFOS);
mTrackType = mTrackInfos.get(0).getType();
mSelectedTrackId = getArguments().getString(SELECTED_TRACK_ID);
- mOverlayFragment = ((DvrPlaybackOverlayFragment) getFragmentManager()
- .findFragmentById(R.id.dvr_playback_controls_fragment));
+ mOverlayFragment =
+ ((DvrPlaybackOverlayFragment)
+ getFragmentManager().findFragmentById(R.id.dvr_playback_controls_fragment));
super.onCreate(savedInstanceState);
}
@Override
- public View onCreateBackgroundView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
+ public View onCreateBackgroundView(
+ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View backgroundView = super.onCreateBackgroundView(inflater, container, savedInstanceState);
- backgroundView.setBackgroundColor(getResources()
- .getColor(R.color.lb_playback_controls_background_light));
+ backgroundView.setBackgroundColor(
+ getResources().getColor(R.color.lb_playback_controls_background_light));
return backgroundView;
}
@Override
public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
if (mTrackType == TvTrackInfo.TYPE_SUBTITLE) {
- actions.add(new GuidedAction.Builder(getActivity())
- .id(ACTION_ID_NO_SUBTITLE)
- .title(getString(R.string.closed_caption_option_item_off))
- .checkSetId(CHECK_SET_ID)
- .checked(mSelectedTrackId == null)
- .build());
+ actions.add(
+ new GuidedAction.Builder(getActivity())
+ .id(ACTION_ID_NO_SUBTITLE)
+ .title(getString(R.string.closed_caption_option_item_off))
+ .checkSetId(CHECK_SET_ID)
+ .checked(mSelectedTrackId == null)
+ .build());
}
for (int i = 0; i < mTrackInfos.size(); i++) {
TvTrackInfo info = mTrackInfos.get(i);
boolean checked = TextUtils.equals(info.getId(), mSelectedTrackId);
- GuidedAction action = new GuidedAction.Builder(getActivity())
- .id(i)
- .title(getTrackLabel(info, i))
- .checkSetId(CHECK_SET_ID)
- .checked(checked)
- .build();
+ GuidedAction action =
+ new GuidedAction.Builder(getActivity())
+ .id(i)
+ .title(getTrackLabel(info, i))
+ .checkSetId(CHECK_SET_ID)
+ .checked(checked)
+ .build();
actions.add(action);
if (checked) {
mSelectedTrack = info;
@@ -136,8 +131,8 @@ public class DvrPlaybackSideFragment extends GuidedStepFragment {
if (track.getLanguage() != null) {
return new Locale(track.getLanguage()).getDisplayName();
}
- return track.getType() == TvTrackInfo.TYPE_SUBTITLE ?
- getString(R.string.closed_caption_unknown_language, trackIndex + 1)
+ return track.getType() == TvTrackInfo.TYPE_SUBTITLE
+ ? getString(R.string.closed_caption_unknown_language, trackIndex + 1)
: getString(R.string.multi_audio_unknown_language);
}
@@ -151,4 +146,4 @@ public class DvrPlaybackSideFragment extends GuidedStepFragment {
t.excludeTarget(R.id.guidedstep_background, true);
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlayer.java b/src/com/android/tv/dvr/ui/playback/DvrPlayer.java
index 7226c666..85bb31b2 100644
--- a/src/com/android/tv/dvr/ui/playback/DvrPlayer.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlayer.java
@@ -24,9 +24,7 @@ import android.media.tv.TvTrackInfo;
import android.media.tv.TvView;
import android.text.TextUtils;
import android.util.Log;
-
import com.android.tv.dvr.data.RecordedProgram;
-
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -35,17 +33,13 @@ class DvrPlayer {
private static final String TAG = "DvrPlayer";
private static final boolean DEBUG = false;
- /**
- * The max rewinding speed supported by DVR player.
- */
+ /** The max rewinding speed supported by DVR player. */
public static final int MAX_REWIND_SPEED = 256;
- /**
- * The max fast-forwarding speed supported by DVR player.
- */
+ /** The max fast-forwarding speed supported by DVR player. */
public static final int MAX_FAST_FORWARD_SPEED = 256;
private static final long SEEK_POSITION_MARGIN_MS = TimeUnit.SECONDS.toMillis(2);
- private static final long REWIND_POSITION_MARGIN_MS = 32; // Workaround value. b/29994826
+ private static final long REWIND_POSITION_MARGIN_MS = 32; // Workaround value. b/29994826
private RecordedProgram mProgram;
private long mInitialSeekPositionMs;
@@ -71,49 +65,39 @@ class DvrPlayer {
public static class DvrPlayerCallback {
/**
- * Called when the playback position is changed. The normal updating frequency is
- * around 1 sec., which is restricted to the implementation of
- * {@link android.media.tv.TvInputService}.
+ * Called when the playback position is changed. The normal updating frequency is around 1
+ * sec., which is restricted to the implementation of {@link
+ * android.media.tv.TvInputService}.
*/
- public void onPlaybackPositionChanged(long positionMs) { }
- /**
- * Called when the playback state or the playback speed is changed.
- */
- public void onPlaybackStateChanged(int playbackState, int playbackSpeed) { }
- /**
- * Called when the playback toward the end.
- */
- public void onPlaybackEnded() { }
+ public void onPlaybackPositionChanged(long positionMs) {}
+ /** Called when the playback state or the playback speed is changed. */
+ public void onPlaybackStateChanged(int playbackState, int playbackSpeed) {}
+ /** Called when the playback toward the end. */
+ public void onPlaybackEnded() {}
}
public interface OnAspectRatioChangedListener {
/**
* Called when the Video's aspect ratio is changed.
*
- * @param videoAspectRatio The aspect ratio of video. 0 stands for unknown ratios.
- * Listeners should handle it carefully.
+ * @param videoAspectRatio The aspect ratio of video. 0 stands for unknown ratios. Listeners
+ * should handle it carefully.
*/
void onAspectRatioChanged(float videoAspectRatio);
}
public interface OnContentBlockedListener {
- /**
- * Called when the Video's aspect ratio is changed.
- */
+ /** Called when the Video's aspect ratio is changed. */
void onContentBlocked(TvContentRating rating);
}
public interface OnTracksAvailabilityChangedListener {
- /**
- * Called when the Video's subtitle or audio tracks are changed.
- */
+ /** Called when the Video's subtitle or audio tracks are changed. */
void onTracksAvailabilityChanged(boolean hasClosedCaption, boolean hasMultiAudio);
}
public interface OnTrackSelectedListener {
- /**
- * Called when certain subtitle or audio track is selected.
- */
+ /** Called when certain subtitle or audio track is selected. */
void onTrackSelected(String selectedTrackId);
}
@@ -143,9 +127,7 @@ class DvrPlayer {
mCallback.onPlaybackStateChanged(mPlaybackState, 1);
}
- /**
- * Resumes playback.
- */
+ /** Resumes playback. */
public void play() throws IllegalStateException {
if (DEBUG) Log.d(TAG, "play()");
if (!isPlaybackPrepared()) {
@@ -163,9 +145,7 @@ class DvrPlayer {
mCallback.onPlaybackStateChanged(mPlaybackState, 1);
}
- /**
- * Pauses playback.
- */
+ /** Pauses playback. */
public void pause() throws IllegalStateException {
if (DEBUG) Log.d(TAG, "pause()");
if (!isPlaybackPrepared()) {
@@ -187,8 +167,8 @@ class DvrPlayer {
}
/**
- * Fast-forwards playback with the given speed. If the given speed is larger than
- * {@value #MAX_FAST_FORWARD_SPEED}, uses {@value #MAX_FAST_FORWARD_SPEED}.
+ * Fast-forwards playback with the given speed. If the given speed is larger than {@value
+ * #MAX_FAST_FORWARD_SPEED}, uses {@value #MAX_FAST_FORWARD_SPEED}.
*/
public void fastForward(int speed) throws IllegalStateException {
if (DEBUG) Log.d(TAG, "fastForward()");
@@ -209,8 +189,8 @@ class DvrPlayer {
}
/**
- * Rewinds playback with the given speed. If the given speed is larger than
- * {@value #MAX_REWIND_SPEED}, uses {@value #MAX_REWIND_SPEED}.
+ * Rewinds playback with the given speed. If the given speed is larger than {@value
+ * #MAX_REWIND_SPEED}, uses {@value #MAX_REWIND_SPEED}.
*/
public void rewind(int speed) throws IllegalStateException {
if (DEBUG) Log.d(TAG, "rewind()");
@@ -230,9 +210,7 @@ class DvrPlayer {
mCallback.onPlaybackStateChanged(mPlaybackState, speed);
}
- /**
- * Seeks playback to the specified position.
- */
+ /** Seeks playback to the specified position. */
public void seekTo(long positionMs) throws IllegalStateException {
if (DEBUG) Log.d(TAG, "seekTo()");
if (!isPlaybackPrepared()) {
@@ -244,17 +222,15 @@ class DvrPlayer {
positionMs = getRealSeekPosition(positionMs, SEEK_POSITION_MARGIN_MS);
if (DEBUG) Log.d(TAG, "Now: " + getPlaybackPosition() + ", shift to: " + positionMs);
mTvView.timeShiftSeekTo(positionMs + mStartPositionMs);
- if (mPlaybackState == PlaybackState.STATE_FAST_FORWARDING ||
- mPlaybackState == PlaybackState.STATE_REWINDING) {
+ if (mPlaybackState == PlaybackState.STATE_FAST_FORWARDING
+ || mPlaybackState == PlaybackState.STATE_REWINDING) {
mPlaybackState = PlaybackState.STATE_PLAYING;
mTvView.timeShiftResume();
mCallback.onPlaybackStateChanged(mPlaybackState, 1);
}
}
- /**
- * Resets playback.
- */
+ /** Resets playback. */
public void reset() {
if (DEBUG) Log.d(TAG, "reset()");
mCallback.onPlaybackStateChanged(PlaybackState.STATE_NONE, 1);
@@ -269,9 +245,7 @@ class DvrPlayer {
mSelectedSubtitleTrackId = null;
}
- /**
- * Sets callbacks for playback.
- */
+ /** Sets callbacks for playback. */
public void setCallback(DvrPlayerCallback callback) {
if (callback != null) {
mCallback = callback;
@@ -280,23 +254,17 @@ class DvrPlayer {
}
}
- /**
- * Sets the listener to aspect ratio changing.
- */
+ /** Sets the listener to aspect ratio changing. */
public void setOnAspectRatioChangedListener(OnAspectRatioChangedListener listener) {
mOnAspectRatioChangedListener = listener;
}
- /**
- * Sets the listener to content blocking.
- */
+ /** Sets the listener to content blocking. */
public void setOnContentBlockedListener(OnContentBlockedListener listener) {
mOnContentBlockedListener = listener;
}
- /**
- * Sets the listener to tracks changing.
- */
+ /** Sets the listener to tracks changing. */
public void setOnTracksAvailabilityChangedListener(
OnTracksAvailabilityChangedListener listener) {
mOnTracksAvailabilityChangedListener = listener;
@@ -305,8 +273,8 @@ class DvrPlayer {
/**
* Sets the listener to tracks of the given type being selected.
*
- * @param trackType should be either {@link TvTrackInfo#TYPE_AUDIO}
- * or {@link TvTrackInfo#TYPE_SUBTITLE}.
+ * @param trackType should be either {@link TvTrackInfo#TYPE_AUDIO} or {@link
+ * TvTrackInfo#TYPE_SUBTITLE}.
*/
public void setOnTrackSelectedListener(int trackType, OnTrackSelectedListener listener) {
if (trackType == TvTrackInfo.TYPE_AUDIO) {
@@ -316,9 +284,7 @@ class DvrPlayer {
}
}
- /**
- * Gets the listener to tracks of the given type being selected.
- */
+ /** Gets the listener to tracks of the given type being selected. */
public OnTrackSelectedListener getOnTrackSelectedListener(int trackType) {
if (trackType == TvTrackInfo.TYPE_AUDIO) {
return mOnAudioTrackSelectedListener;
@@ -328,9 +294,7 @@ class DvrPlayer {
return null;
}
- /**
- * Sets recorded programs for playback. If the player is playing another program, stops it.
- */
+ /** Sets recorded programs for playback. If the player is playing another program, stops it. */
public void setProgram(RecordedProgram program, long initialSeekPositionMs) {
if (mProgram != null && mProgram.equals(program)) {
return;
@@ -342,51 +306,37 @@ class DvrPlayer {
mProgram = program;
}
- /**
- * Returns the recorded program now playing.
- */
+ /** Returns the recorded program now playing. */
public RecordedProgram getProgram() {
return mProgram;
}
- /**
- * Returns the currrent playback posistion in msecs.
- */
+ /** Returns the currrent playback posistion in msecs. */
public long getPlaybackPosition() {
return mTimeShiftCurrentPositionMs;
}
- /**
- * Returns the playback speed currently used.
- */
+ /** Returns the playback speed currently used. */
public int getPlaybackSpeed() {
return (int) mPlaybackParams.getSpeed();
}
- /**
- * Returns the playback state defined in {@link android.media.session.PlaybackState}.
- */
+ /** Returns the playback state defined in {@link android.media.session.PlaybackState}. */
public int getPlaybackState() {
return mPlaybackState;
}
- /**
- * Returns the subtitle tracks of the current playback.
- */
+ /** Returns the subtitle tracks of the current playback. */
public ArrayList<TvTrackInfo> getSubtitleTracks() {
return new ArrayList<>(mTvView.getTracks(TvTrackInfo.TYPE_SUBTITLE));
}
- /**
- * Returns the audio tracks of the current playback.
- */
+ /** Returns the audio tracks of the current playback. */
public ArrayList<TvTrackInfo> getAudioTracks() {
return new ArrayList<>(mTvView.getTracks(TvTrackInfo.TYPE_AUDIO));
}
- /**
- * Returns the ID of the selected track of the given type.
- */
+ /** Returns the ID of the selected track of the given type. */
public String getSelectedTrackId(int trackType) {
if (trackType == TvTrackInfo.TYPE_AUDIO) {
return mSelectedAudioTrackId;
@@ -396,9 +346,7 @@ class DvrPlayer {
return null;
}
- /**
- * Returns if playback of the recorded program is started.
- */
+ /** Returns if playback of the recorded program is started. */
public boolean isPlaybackPrepared() {
return mPlaybackState != PlaybackState.STATE_NONE
&& mPlaybackState != PlaybackState.STATE_CONNECTING;
@@ -449,125 +397,138 @@ class DvrPlayer {
}
private void setTvViewCallbacks() {
- mTvView.setTimeShiftPositionCallback(new TvView.TimeShiftPositionCallback() {
- @Override
- public void onTimeShiftStartPositionChanged(String inputId, long timeMs) {
- if (DEBUG) Log.d(TAG, "onTimeShiftStartPositionChanged:" + timeMs);
- mStartPositionMs = timeMs;
- if (mTimeShiftPlayAvailable) {
- resumeToWatchedPositionIfNeeded();
- }
- }
+ mTvView.setTimeShiftPositionCallback(
+ new TvView.TimeShiftPositionCallback() {
+ @Override
+ public void onTimeShiftStartPositionChanged(String inputId, long timeMs) {
+ if (DEBUG) Log.d(TAG, "onTimeShiftStartPositionChanged:" + timeMs);
+ mStartPositionMs = timeMs;
+ if (mTimeShiftPlayAvailable) {
+ resumeToWatchedPositionIfNeeded();
+ }
+ }
- @Override
- public void onTimeShiftCurrentPositionChanged(String inputId, long timeMs) {
- if (DEBUG) Log.d(TAG, "onTimeShiftCurrentPositionChanged: " + timeMs);
- if (!mTimeShiftPlayAvailable) {
- // Workaround of b/31436263
- return;
- }
- // Workaround of b/32211561, TIF won't report start position when TIS report
- // its start position as 0. In that case, we have to do the prework of playback
- // on the first time we get current position, and the start position should be 0
- // at that time.
- if (mStartPositionMs == TvInputManager.TIME_SHIFT_INVALID_TIME) {
- mStartPositionMs = 0;
- resumeToWatchedPositionIfNeeded();
- }
- timeMs -= mStartPositionMs;
- if (mPlaybackState == PlaybackState.STATE_REWINDING
- && timeMs <= REWIND_POSITION_MARGIN_MS) {
- play();
- } else {
- mTimeShiftCurrentPositionMs = getRealSeekPosition(timeMs, 0);
- mCallback.onPlaybackPositionChanged(mTimeShiftCurrentPositionMs);
- if (timeMs >= mProgram.getDurationMillis()) {
- pause();
- mCallback.onPlaybackEnded();
+ @Override
+ public void onTimeShiftCurrentPositionChanged(String inputId, long timeMs) {
+ if (DEBUG) Log.d(TAG, "onTimeShiftCurrentPositionChanged: " + timeMs);
+ if (!mTimeShiftPlayAvailable) {
+ // Workaround of b/31436263
+ return;
+ }
+ // Workaround of b/32211561, TIF won't report start position when TIS report
+ // its start position as 0. In that case, we have to do the prework of
+ // playback
+ // on the first time we get current position, and the start position should
+ // be 0
+ // at that time.
+ if (mStartPositionMs == TvInputManager.TIME_SHIFT_INVALID_TIME) {
+ mStartPositionMs = 0;
+ resumeToWatchedPositionIfNeeded();
+ }
+ timeMs -= mStartPositionMs;
+ if (mPlaybackState == PlaybackState.STATE_REWINDING
+ && timeMs <= REWIND_POSITION_MARGIN_MS) {
+ play();
+ } else {
+ mTimeShiftCurrentPositionMs = getRealSeekPosition(timeMs, 0);
+ mCallback.onPlaybackPositionChanged(mTimeShiftCurrentPositionMs);
+ if (timeMs >= mProgram.getDurationMillis()) {
+ pause();
+ mCallback.onPlaybackEnded();
+ }
+ }
}
- }
- }
- });
- mTvView.setCallback(new TvView.TvInputCallback() {
- @Override
- public void onTimeShiftStatusChanged(String inputId, int status) {
- if (DEBUG) Log.d(TAG, "onTimeShiftStatusChanged:" + status);
- if (status == TvInputManager.TIME_SHIFT_STATUS_AVAILABLE
- && mPlaybackState == PlaybackState.STATE_CONNECTING) {
- mTimeShiftPlayAvailable = true;
- if (mStartPositionMs != TvInputManager.TIME_SHIFT_INVALID_TIME) {
- // onTimeShiftStatusChanged is sometimes called after
- // onTimeShiftStartPositionChanged is called. In this case,
- // resumeToWatchedPositionIfNeeded needs to be called here.
- resumeToWatchedPositionIfNeeded();
+ });
+ mTvView.setCallback(
+ new TvView.TvInputCallback() {
+ @Override
+ public void onTimeShiftStatusChanged(String inputId, int status) {
+ if (DEBUG) Log.d(TAG, "onTimeShiftStatusChanged:" + status);
+ if (status == TvInputManager.TIME_SHIFT_STATUS_AVAILABLE
+ && mPlaybackState == PlaybackState.STATE_CONNECTING) {
+ mTimeShiftPlayAvailable = true;
+ if (mStartPositionMs != TvInputManager.TIME_SHIFT_INVALID_TIME) {
+ // onTimeShiftStatusChanged is sometimes called after
+ // onTimeShiftStartPositionChanged is called. In this case,
+ // resumeToWatchedPositionIfNeeded needs to be called here.
+ resumeToWatchedPositionIfNeeded();
+ }
+ }
}
- }
- }
-
- @Override
- public void onTracksChanged(String inputId, List<TvTrackInfo> tracks) {
- boolean hasClosedCaption =
- !mTvView.getTracks(TvTrackInfo.TYPE_SUBTITLE).isEmpty();
- boolean hasMultiAudio = mTvView.getTracks(TvTrackInfo.TYPE_AUDIO).size() > 1;
- if ((hasClosedCaption != mHasClosedCaption || hasMultiAudio != mHasMultiAudio)
- && mOnTracksAvailabilityChangedListener != null) {
- mOnTracksAvailabilityChangedListener
- .onTracksAvailabilityChanged(hasClosedCaption, hasMultiAudio);
- }
- mHasClosedCaption = hasClosedCaption;
- mHasMultiAudio = hasMultiAudio;
- }
- @Override
- public void onTrackSelected(String inputId, int type, String trackId) {
- if (type == TvTrackInfo.TYPE_AUDIO || type == TvTrackInfo.TYPE_SUBTITLE) {
- setSelectedTrackId(type, trackId);
- OnTrackSelectedListener listener = getOnTrackSelectedListener(type);
- if (listener != null) {
- listener.onTrackSelected(trackId);
+ @Override
+ public void onTracksChanged(String inputId, List<TvTrackInfo> tracks) {
+ boolean hasClosedCaption =
+ !mTvView.getTracks(TvTrackInfo.TYPE_SUBTITLE).isEmpty();
+ boolean hasMultiAudio =
+ mTvView.getTracks(TvTrackInfo.TYPE_AUDIO).size() > 1;
+ if ((hasClosedCaption != mHasClosedCaption
+ || hasMultiAudio != mHasMultiAudio)
+ && mOnTracksAvailabilityChangedListener != null) {
+ mOnTracksAvailabilityChangedListener.onTracksAvailabilityChanged(
+ hasClosedCaption, hasMultiAudio);
+ }
+ mHasClosedCaption = hasClosedCaption;
+ mHasMultiAudio = hasMultiAudio;
}
- } else if (type == TvTrackInfo.TYPE_VIDEO && trackId != null
- && mOnAspectRatioChangedListener != null) {
- List<TvTrackInfo> trackInfos = mTvView.getTracks(TvTrackInfo.TYPE_VIDEO);
- if (trackInfos != null) {
- for (TvTrackInfo trackInfo : trackInfos) {
- if (trackInfo.getId().equals(trackId)) {
- float videoAspectRatio;
- int videoWidth = trackInfo.getVideoWidth();
- int videoHeight = trackInfo.getVideoHeight();
- if (videoWidth > 0 && videoHeight > 0) {
- videoAspectRatio = trackInfo.getVideoPixelAspectRatio()
- * trackInfo.getVideoWidth() / trackInfo.getVideoHeight();
- } else {
- // Aspect ratio is unknown. Pass the message to listeners.
- videoAspectRatio = 0;
- }
- if (DEBUG) Log.d(TAG, "Aspect Ratio: " + videoAspectRatio);
- if (mAspectRatio != videoAspectRatio || videoAspectRatio == 0) {
- mOnAspectRatioChangedListener
- .onAspectRatioChanged(videoAspectRatio);
- mAspectRatio = videoAspectRatio;
- return;
+
+ @Override
+ public void onTrackSelected(String inputId, int type, String trackId) {
+ if (type == TvTrackInfo.TYPE_AUDIO || type == TvTrackInfo.TYPE_SUBTITLE) {
+ setSelectedTrackId(type, trackId);
+ OnTrackSelectedListener listener = getOnTrackSelectedListener(type);
+ if (listener != null) {
+ listener.onTrackSelected(trackId);
+ }
+ } else if (type == TvTrackInfo.TYPE_VIDEO
+ && trackId != null
+ && mOnAspectRatioChangedListener != null) {
+ List<TvTrackInfo> trackInfos =
+ mTvView.getTracks(TvTrackInfo.TYPE_VIDEO);
+ if (trackInfos != null) {
+ for (TvTrackInfo trackInfo : trackInfos) {
+ if (trackInfo.getId().equals(trackId)) {
+ float videoAspectRatio;
+ int videoWidth = trackInfo.getVideoWidth();
+ int videoHeight = trackInfo.getVideoHeight();
+ if (videoWidth > 0 && videoHeight > 0) {
+ videoAspectRatio =
+ trackInfo.getVideoPixelAspectRatio()
+ * trackInfo.getVideoWidth()
+ / trackInfo.getVideoHeight();
+ } else {
+ // Aspect ratio is unknown. Pass the message to
+ // listeners.
+ videoAspectRatio = 0;
+ }
+ if (DEBUG) Log.d(TAG, "Aspect Ratio: " + videoAspectRatio);
+ if (mAspectRatio != videoAspectRatio
+ || videoAspectRatio == 0) {
+ mOnAspectRatioChangedListener.onAspectRatioChanged(
+ videoAspectRatio);
+ mAspectRatio = videoAspectRatio;
+ return;
+ }
+ }
}
}
}
}
- }
- }
- @Override
- public void onContentBlocked(String inputId, TvContentRating rating) {
- if (mOnContentBlockedListener != null) {
- mOnContentBlockedListener.onContentBlocked(rating);
- }
- }
- });
+ @Override
+ public void onContentBlocked(String inputId, TvContentRating rating) {
+ if (mOnContentBlockedListener != null) {
+ mOnContentBlockedListener.onContentBlocked(rating);
+ }
+ }
+ });
}
private void resumeToWatchedPositionIfNeeded() {
if (mInitialSeekPositionMs != TvInputManager.TIME_SHIFT_INVALID_TIME) {
- mTvView.timeShiftSeekTo(getRealSeekPosition(mInitialSeekPositionMs,
- SEEK_POSITION_MARGIN_MS) + mStartPositionMs);
+ mTvView.timeShiftSeekTo(
+ getRealSeekPosition(mInitialSeekPositionMs, SEEK_POSITION_MARGIN_MS)
+ + mStartPositionMs);
mInitialSeekPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
}
if (mPauseOnPrepared) {
@@ -580,4 +541,4 @@ class DvrPlayer {
}
mCallback.onPlaybackStateChanged(mPlaybackState, 1);
}
-} \ No newline at end of file
+}