aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshubang <shubang@google.com>2018-02-21 19:30:58 -0800
committerNick Chalko <nchalko@google.com>2018-02-26 15:40:17 -0800
commit4fa6d98a418cba109cd550f5808bd86d01b131cf (patch)
tree925402e83be618c379f00c56c95ea612a45c3fa1
parent6a2a9219b9ea3a2a9b56acd7038c9819f8959c35 (diff)
downloadTV-4fa6d98a418cba109cd550f5808bd86d01b131cf.tar.gz
Show failed recordings in DVR recent row
PiperOrigin-RevId: 186556969 Change-Id: I3410d9ea1db451d2e4711631ccd530f9179b428d
-rw-r--r--res/values/strings.xml2
-rw-r--r--src/com/android/tv/dvr/ui/DvrUiHelper.java18
-rw-r--r--src/com/android/tv/dvr/ui/browse/DetailsContent.java32
-rw-r--r--src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java80
-rw-r--r--src/com/android/tv/dvr/ui/browse/DvrDetailsActivity.java5
-rw-r--r--src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java4
-rw-r--r--src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java16
-rw-r--r--src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java12
-rw-r--r--src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java34
-rw-r--r--src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java7
10 files changed, 160 insertions, 50 deletions
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0aec0b30..cea4ee6c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -576,6 +576,8 @@
<string name="dvr_history_card_view_title">Recording History</string>
<!-- Description of a card view to show full list of scheduled recordings. [CHAR LIMIT=25] -->
<string name="dvr_full_schedule_card_view_title">Full schedule</string>
+ <!-- Description of failed recordings. [CHAR LIMIT=25] -->
+ <string name="dvr_recording_failed">Recording Failed</string>
<!-- Description of how many following days the schedule list will show. [CHAR LIMIT=25] -->
<plurals name="dvr_full_schedule_card_view_content">
<item quantity="one">Next %1$d day</item>
diff --git a/src/com/android/tv/dvr/ui/DvrUiHelper.java b/src/com/android/tv/dvr/ui/DvrUiHelper.java
index bb23793f..34ab62b6 100644
--- a/src/com/android/tv/dvr/ui/DvrUiHelper.java
+++ b/src/com/android/tv/dvr/ui/DvrUiHelper.java
@@ -591,6 +591,13 @@ public class DvrUiHelper {
&& 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;
}
@@ -685,13 +692,10 @@ public class DvrUiHelper {
builder =
TextUtils.isEmpty(episodeNumber)
? new SpannableStringBuilder(title)
- : new SpannableStringBuilder(
- Html.fromHtml(
- context.getString(
- R.string
- .program_title_with_episode_number_no_season,
- title,
- episodeNumber)));
+ : new SpannableStringBuilder(Html.fromHtml(context.getString(
+ R.string.program_title_with_episode_number_no_season,
+ title,
+ episodeNumber)));
} else {
builder =
new SpannableStringBuilder(
diff --git a/src/com/android/tv/dvr/ui/browse/DetailsContent.java b/src/com/android/tv/dvr/ui/browse/DetailsContent.java
index 56bbdb46..35713666 100644
--- a/src/com/android/tv/dvr/ui/browse/DetailsContent.java
+++ b/src/com/android/tv/dvr/ui/browse/DetailsContent.java
@@ -99,6 +99,38 @@ class DetailsContent {
.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;
+ } else {
+ 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);
+ }
+
private DetailsContent() {}
/** Returns title. */
diff --git a/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java b/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java
index 6d66eea1..51019c08 100644
--- a/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java
@@ -31,6 +31,7 @@ import android.support.v17.leanback.widget.TitleViewAdapter;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalFocusChangeListener;
+
import com.android.tv.R;
import com.android.tv.TvFeatures;
import com.android.tv.TvSingletons;
@@ -46,6 +47,7 @@ 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.SortedArrayAdapter;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@@ -70,7 +72,7 @@ public class DvrBrowseFragment extends BrowseFragment
private boolean mShouldShowScheduleRow;
private boolean mEntranceTransitionEnded;
- private RecordedProgramAdapter mRecentAdapter;
+ private RecentRowAdapter mRecentAdapter;
private ScheduleAdapter mScheduleAdapter;
private SeriesAdapter mSeriesAdapter;
private RecordedProgramAdapter[] mGenreAdapters =
@@ -146,6 +148,52 @@ public class DvrBrowseFragment extends BrowseFragment
}
};
+ private 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
@@ -282,6 +330,8 @@ public class DvrBrowseFragment extends BrowseFragment
for (ScheduledRecording scheduleRecording : scheduledRecordings) {
if (needToShowScheduledRecording(scheduleRecording)) {
mScheduleAdapter.add(scheduleRecording);
+ } else if (scheduleRecording.getState() == ScheduledRecording.STATE_RECORDING_FAILED) {
+ mRecentAdapter.add(scheduleRecording);
}
}
}
@@ -380,14 +430,15 @@ public class DvrBrowseFragment extends BrowseFragment
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.
@@ -395,6 +446,11 @@ public class DvrBrowseFragment extends BrowseFragment
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
@@ -697,4 +753,22 @@ public class DvrBrowseFragment extends BrowseFragment
}
}
}
+
+ 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 2659c3f3..0336b319 100644
--- a/src/com/android/tv/dvr/ui/browse/DvrDetailsActivity.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrDetailsActivity.java
@@ -43,6 +43,9 @@ public class DvrDetailsActivity extends Activity implements PinDialogFragment.On
/** Name of shared element between activities. */
public static final String SHARED_ELEMENT_NAME = "shared_element";
+ /** 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;
@@ -65,6 +68,7 @@ public class DvrDetailsActivity extends Activity implements PinDialogFragment.On
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);
@@ -73,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();
diff --git a/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java
index e4d95630..aa2ccf75 100644
--- a/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java
@@ -41,6 +41,10 @@ abstract class RecordingDetailsFragment extends DvrDetailsFragment {
return mRecording != null;
}
+ protected ScheduledRecording getScheduledRecording() {
+ return mRecording;
+ }
+
/** Returns {@link ScheduledRecording} for the current fragment. */
public ScheduledRecording getRecording() {
return mRecording;
diff --git a/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java
index 0765117d..302b8318 100644
--- a/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java
@@ -34,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) {
+ Bundle args = getArguments();
mDvrManager = TvSingletons.getSingletons(getContext()).getDvrManager();
- mHideViewSchedule = getArguments().getBoolean(DvrDetailsActivity.HIDE_VIEW_SCHEDULE);
+ mHideViewSchedule = args.getBoolean(DvrDetailsActivity.HIDE_VIEW_SCHEDULE);
+ mFailedMessage = args.getString(DvrDetailsActivity.EXTRA_FAILED_MESSAGE);
super.onCreate(savedInstance);
}
@@ -51,6 +54,17 @@ 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());
diff --git a/src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java
index f1ed52c8..8e028689 100644
--- a/src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java
+++ b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java
@@ -119,13 +119,21 @@ class ScheduledRecordingPresenter extends DvrItemPresenter<ScheduledRecording> {
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) {
+ 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) {
diff --git a/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java b/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java
index bbccdb15..ef4a4337 100644
--- a/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java
+++ b/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java
@@ -27,14 +27,15 @@ import android.support.v17.leanback.widget.ClassPresenterSelector;
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.Log;
+
import com.android.tv.R;
-import com.android.tv.TvFeatures;
import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
import com.android.tv.dvr.DvrManager;
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;
import java.util.Collections;
import java.util.List;
@@ -115,33 +116,6 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
}
deadLine += ONE_DAY_MS;
}
- if (TvFeatures.DVR_FAILED_LIST.isEnabled(getContext())) {
- List<ScheduledRecording> failedRecordingList =
- TvSingletons.getSingletons(mContext)
- .getDvrDataManager()
- .getFailedScheduledRecordings();
- Collections.sort(
- failedRecordingList,
- ScheduledRecording.START_TIME_COMPARATOR.reversed());
- if (!failedRecordingList.isEmpty()) {
- SchedulesHeaderRow headerRow =
- // TODO(b/72638385): use R.string
- // TODO(b/72638385): define another HeaderRow class
- new DateHeaderRow(
- "Failed recordings",
- mContext.getResources()
- .getQuantityString(
- R.plurals.dvr_schedules_section_subtitle,
- failedRecordingList.size(),
- failedRecordingList.size()),
- failedRecordingList.size(),
- Long.MAX_VALUE);
- add(headerRow);
- for (ScheduledRecording recording : failedRecordingList) {
- add(new ScheduleRow(recording, headerRow));
- }
- }
- }
sendNextUpdateMessage(System.currentTimeMillis());
}
@@ -414,9 +388,7 @@ class ScheduleRowAdapter extends ArrayObjectAdapter {
Object item = get(i);
if (item instanceof ScheduleRow) {
ScheduleRow row = (ScheduleRow) item;
- ScheduledRecording recording = row.getSchedule();
- if (row.getEndTimeMs() <= currentTimeMs && (recording == null
- || recording.getState() != ScheduledRecording.STATE_RECORDING_FAILED)) {
+ if (row.getEndTimeMs() <= currentTimeMs) {
removeScheduleRow(row);
}
}
diff --git a/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java b/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java
index 19fd913c..65c58ce8 100644
--- a/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java
+++ b/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java
@@ -478,13 +478,8 @@ class ScheduleRowPresenter extends RowPresenter {
/** Returns time text for time view from scheduled recording. */
protected String onGetRecordingTimeText(ScheduleRow row) {
- boolean showDate =
- TvFeatures.DVR_FAILED_LIST.isEnabled(getContext())
- && row.getSchedule() != null
- && row.getSchedule().getState()
- == ScheduledRecording.STATE_RECORDING_FAILED;
return Utils.getDurationString(
- mContext, row.getStartTimeMs(), row.getEndTimeMs(), true, showDate, true, 0);
+ mContext, row.getStartTimeMs(), row.getEndTimeMs(), true, false, true, 0);
}
/** Returns program info text for program title view. */