diff options
Diffstat (limited to 'src/com/android/tv/dvr/ui/browse')
15 files changed, 315 insertions, 355 deletions
diff --git a/src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java b/src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java index f3a6fea4..41ace9a4 100644 --- a/src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java +++ b/src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java @@ -27,9 +27,11 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Button; -// This class is adapted from Leanback's library, which does not support action icon with one-line -// label. This class modified its getPresenter method to support the above situation. -class ActionPresenterSelector extends PresenterSelector { +/** + * This class is adapted from Leanback's library, which does not support action icon with one-line + * label. This class modified its getPresenter method to support the above situation. + */ +public class ActionPresenterSelector extends PresenterSelector { private final Presenter mOneLineActionPresenter = new OneLineActionPresenter(); private final Presenter mTwoLineActionPresenter = new TwoLineActionPresenter(); private final Presenter[] mPresenters = diff --git a/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java index 7e7e1f75..8c311d68 100644 --- a/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java +++ b/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java @@ -18,23 +18,34 @@ package com.android.tv.dvr.ui.browse; import android.content.Context; import android.content.res.Resources; +import android.media.tv.TvInputManager; 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.TvSingletons; +import com.android.tv.common.flags.has.HasConcurrentDvrPlaybackFlags; import com.android.tv.dialog.HalfSizedDialogFragment; 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; import com.android.tv.dvr.data.ScheduledRecording; import com.android.tv.dvr.ui.DvrStopRecordingFragment; import com.android.tv.dvr.ui.DvrUiHelper; +import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags; /** {@link RecordingDetailsFragment} for current recording in DVR. */ public class CurrentRecordingDetailsFragment extends RecordingDetailsFragment { private static final int ACTION_STOP_RECORDING = 1; + private static final int ACTION_RESUME_PLAYING = 2; + private static final int ACTION_PLAY_FROM_BEGINNING = 3; private DvrDataManager mDvrDataManger; + private RecordedProgram mRecordedProgram; + private DvrWatchedPositionManager mDvrWatchedPositionManager; + private ConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags; + private boolean mPaused; private final DvrDataManager.ScheduledRecordingListener mScheduledRecordingListener = new DvrDataManager.ScheduledRecordingListener() { @Override @@ -68,10 +79,32 @@ public class CurrentRecordingDetailsFragment extends RecordingDetailsFragment { super.onAttach(context); mDvrDataManger = TvSingletons.getSingletons(context).getDvrDataManager(); mDvrDataManger.addScheduledRecordingListener(mScheduledRecordingListener); + mDvrWatchedPositionManager = + TvSingletons.getSingletons(getActivity()).getDvrWatchedPositionManager(); + mConcurrentDvrPlaybackFlags = HasConcurrentDvrPlaybackFlags.fromContext(context); + } + + @Override + public void onResume() { + super.onResume(); + if (mPaused) { + updateActions(); + mPaused = false; + } + } + + @Override + public void onPause() { + super.onPause(); + mPaused = true; } @Override protected SparseArrayObjectAdapter onCreateActionsAdapter() { + Long recordedProgramId = getRecording().getRecordedProgramId(); + if (recordedProgramId != null) { + mRecordedProgram = mDvrDataManger.getRecordedProgram(recordedProgramId); + } SparseArrayObjectAdapter adapter = new SparseArrayObjectAdapter(new ActionPresenterSelector()); Resources res = getResources(); @@ -82,6 +115,35 @@ public class CurrentRecordingDetailsFragment extends RecordingDetailsFragment { res.getString(R.string.dvr_detail_stop_recording), null, res.getDrawable(R.drawable.lb_ic_stop))); + if (mConcurrentDvrPlaybackFlags.enabled() + && mRecordedProgram != null + && mRecordedProgram.isPartial()) { + 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))); + } 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))); + } + } return adapter; } @@ -107,6 +169,13 @@ public class CurrentRecordingDetailsFragment extends RecordingDetailsFragment { } } }); + } else if (action.getId() == ACTION_RESUME_PLAYING) { + startPlayback( + mRecordedProgram, + mDvrWatchedPositionManager.getWatchedPosition( + mRecordedProgram.getId())); + } else if (action.getId() == ACTION_PLAY_FROM_BEGINNING) { + startPlayback(mRecordedProgram, TvInputManager.TIME_SHIFT_INVALID_TIME); } } }; diff --git a/src/com/android/tv/dvr/ui/browse/DetailsContent.java b/src/com/android/tv/dvr/ui/browse/DetailsContent.java index cba6293b..e179743c 100644 --- a/src/com/android/tv/dvr/ui/browse/DetailsContent.java +++ b/src/com/android/tv/dvr/ui/browse/DetailsContent.java @@ -22,6 +22,7 @@ import android.support.annotation.Nullable; import android.text.TextUtils; import com.android.tv.R; import com.android.tv.TvSingletons; +import com.android.tv.data.Program; import com.android.tv.data.api.Channel; import com.android.tv.dvr.data.RecordedProgram; import com.android.tv.dvr.data.ScheduledRecording; @@ -29,7 +30,7 @@ import com.android.tv.dvr.data.SeriesRecording; import com.android.tv.dvr.ui.DvrUiHelper; /** A class for details content. */ -class DetailsContent { +public class DetailsContent { /** Constant for invalid time. */ public static final long INVALID_TIME = -1; @@ -40,6 +41,7 @@ class DetailsContent { private String mLogoImageUri; private String mBackgroundImageUri; private boolean mUsingChannelLogo; + private boolean mShowErrorMessage; static DetailsContent createFromRecordedProgram( Context context, RecordedProgram recordedProgram) { @@ -59,6 +61,23 @@ class DetailsContent { .build(context); } + public static DetailsContent createFromProgram(Context context, Program program) { + return new DetailsContent.Builder() + .setChannelId(program.getChannelId()) + .setProgramTitle(program.getTitle()) + .setSeasonNumber(program.getSeasonNumber()) + .setEpisodeNumber(program.getEpisodeNumber()) + .setStartTimeUtcMillis(program.getStartTimeUtcMillis()) + .setEndTimeUtcMillis(program.getEndTimeUtcMillis()) + .setDescription( + TextUtils.isEmpty(program.getLongDescription()) + ? program.getDescription() + : program.getLongDescription()) + .setPosterArtUri(program.getPosterArtUri()) + .setThumbnailUri(program.getThumbnailUri()) + .build(context); + } + static DetailsContent createFromSeriesRecording( Context context, SeriesRecording seriesRecording) { return new DetailsContent.Builder() @@ -79,37 +98,9 @@ class DetailsContent { 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() + ")"; + if (scheduledRecording.getState() == ScheduledRecording.STATE_RECORDING_FAILED) { + description = getErrorMessage(context, scheduledRecording); } else { description = !TextUtils.isEmpty(scheduledRecording.getProgramDescription()) @@ -129,9 +120,39 @@ class DetailsContent { .setDescription(description) .setPosterArtUri(scheduledRecording.getProgramPosterArtUri()) .setThumbnailUri(scheduledRecording.getProgramThumbnailUri()) + .setShowErrorMessage( + scheduledRecording.getState() == ScheduledRecording.STATE_RECORDING_FAILED) .build(context); } + private static String getErrorMessage(Context context, ScheduledRecording recording) { + int reason = recording.getFailedReason() == null + ? ScheduledRecording.FAILED_REASON_OTHER + : recording.getFailedReason(); + switch (reason) { + case ScheduledRecording.FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED: + return context.getString(R.string.dvr_recording_failed_not_started); + case ScheduledRecording.FAILED_REASON_RESOURCE_BUSY: + return context.getString(R.string.dvr_recording_failed_resource_busy); + case ScheduledRecording.FAILED_REASON_INPUT_UNAVAILABLE: + return context.getString( + R.string.dvr_recording_failed_input_unavailable, + recording.getInputId()); + case ScheduledRecording.FAILED_REASON_INPUT_DVR_UNSUPPORTED: + return context.getString(R.string.dvr_recording_failed_input_dvr_unsupported); + case ScheduledRecording.FAILED_REASON_INSUFFICIENT_SPACE: + return context.getString(R.string.dvr_recording_failed_insufficient_space); + case ScheduledRecording.FAILED_REASON_OTHER: // fall through + case ScheduledRecording.FAILED_REASON_NOT_FINISHED: // fall through + case ScheduledRecording.FAILED_REASON_SCHEDULER_STOPPED: // fall through + case ScheduledRecording.FAILED_REASON_INVALID_CHANNEL: // fall through + case ScheduledRecording.FAILED_REASON_MESSAGE_NOT_SENT: // fall through + case ScheduledRecording.FAILED_REASON_CONNECTION_FAILED: // fall through + default: + return context.getString(R.string.dvr_recording_failed_system_failure, reason); + } + } + private DetailsContent() {} /** Returns title. */ @@ -169,6 +190,11 @@ class DetailsContent { return mUsingChannelLogo; } + /** Returns if the error message should be shown. */ + public boolean shouldShowErrorMessage() { + return mShowErrorMessage; + } + /** Copies other details content. */ public void copyFrom(DetailsContent other) { if (this == other) { @@ -181,6 +207,7 @@ class DetailsContent { mLogoImageUri = other.mLogoImageUri; mBackgroundImageUri = other.mBackgroundImageUri; mUsingChannelLogo = other.mUsingChannelLogo; + mShowErrorMessage = other.mShowErrorMessage; } /** A class for building details content. */ @@ -266,6 +293,11 @@ class DetailsContent { return this; } + private Builder setShowErrorMessage(boolean showErrorMessage) { + mDetailsContent.mShowErrorMessage = showErrorMessage; + return this; + } + private void createStyledTitle(Context context, Channel channel) { CharSequence title = DvrUiHelper.getStyledTitleWithEpisodeNumber( diff --git a/src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java b/src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java index aec8c411..6b5fd1fd 100644 --- a/src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java +++ b/src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java @@ -45,12 +45,13 @@ import com.android.tv.util.Utils; * The latter class are re-used to provide a customized version of {@link * android.support.v17.leanback.widget.DetailsOverviewRow}. */ -class DetailsContentPresenter extends Presenter { +public class DetailsContentPresenter extends Presenter { /** The ViewHolder for the {@link DetailsContentPresenter}. */ public static class ViewHolder extends Presenter.ViewHolder { final TextView mTitle; final TextView mSubtitle; final LinearLayout mDescriptionContainer; + final LinearLayout mErrorMessage; final TextView mBody; final TextView mReadMoreView; final int mTitleMargin; @@ -150,6 +151,8 @@ class DetailsContentPresenter extends Presenter { }); mTitle = (TextView) view.findViewById(R.id.dvr_details_description_title); mSubtitle = (TextView) view.findViewById(R.id.dvr_details_description_subtitle); + mErrorMessage = + (LinearLayout) view.findViewById(R.id.dvr_details_description_error_message); mBody = (TextView) view.findViewById(R.id.dvr_details_description_body); mDescriptionContainer = (LinearLayout) view.findViewById(R.id.dvr_details_description_container); @@ -321,6 +324,9 @@ class DetailsContentPresenter extends Presenter { if (TextUtils.isEmpty(detailsContent.getDescription())) { vh.mBody.setVisibility(View.GONE); } else { + if (detailsContent.shouldShowErrorMessage()) { + vh.mErrorMessage.setVisibility(View.VISIBLE); + } vh.mBody.setText(detailsContent.getDescription()); vh.mBody.setVisibility(View.VISIBLE); vh.mBody.setLineSpacing( diff --git a/src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java b/src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java index 849360b8..4e41daee 100644 --- a/src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java +++ b/src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java @@ -24,7 +24,7 @@ import android.os.Handler; import android.support.v17.leanback.app.BackgroundManager; /** The Background Helper. */ -class DetailsViewBackgroundHelper { +public class DetailsViewBackgroundHelper { // Background delay serves to avoid kicking off expensive bitmap loading // in case multiple backgrounds are set in quick succession. private static final int SET_BACKGROUND_DELAY_MS = 100; diff --git a/src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java b/src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java index 6cc1c7a1..5743ea5c 100644 --- a/src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java +++ b/src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java @@ -22,9 +22,15 @@ import android.media.tv.TvInputManager; import android.os.Bundle; import com.android.tv.R; import com.android.tv.Starter; +import com.android.tv.perf.PerformanceMonitorManagerFactory; /** {@link android.app.Activity} for DVR UI. */ public class DvrBrowseActivity extends Activity { + + { + PerformanceMonitorManagerFactory.create().getStartupMeasure().onActivityInit(); + } + private DvrBrowseFragment mFragment; @Override diff --git a/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java b/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java index 40b3a1f0..17ba1939 100644 --- a/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java +++ b/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java @@ -31,9 +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; import com.android.tv.data.GenreItems; import com.android.tv.dvr.DvrDataManager; @@ -47,7 +45,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 com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -66,7 +64,7 @@ public class DvrBrowseFragment extends BrowseFragment private static final String TAG = "DvrBrowseFragment"; private static final boolean DEBUG = false; - private static final int MAX_RECENT_ITEM_COUNT = 10; + private static final int MAX_RECENT_ITEM_COUNT = 4; private static final int MAX_SCHEDULED_ITEM_COUNT = 4; private boolean mShouldShowScheduleRow; @@ -104,93 +102,84 @@ public class DvrBrowseFragment extends BrowseFragment }; 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; + (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 0; + return -1; } + } 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; - } - } else if (rhs instanceof ScheduledRecording) { - return 1; + (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 0; + return -1; } + } 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; - } + (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 !(rhs instanceof RecordedProgram) - && !(rhs instanceof ScheduledRecording) - ? 0 : 1; + return -1; } + } else { + return !(rhs instanceof RecordedProgram) && !(rhs instanceof ScheduledRecording) + ? 0 + : 1; } }; @@ -207,13 +196,7 @@ public class DvrBrowseFragment extends BrowseFragment } }; - private final Runnable mUpdateRowsRunnable = - new Runnable() { - @Override - public void run() { - updateRows(); - } - }; + private final Runnable mUpdateRowsRunnable = this::updateRows; @Override public void onCreate(Bundle savedInstanceState) { @@ -233,13 +216,10 @@ public class DvrBrowseFragment extends BrowseFragment SeriesRecording.class, new SeriesRecordingPresenter(context)) .addClassPresenter( FullScheduleCardHolder.class, - new FullSchedulesCardPresenter(context)); + new FullSchedulesCardPresenter(context)) + .addClassPresenter( + DvrHistoryCardHolder.class, new DvrHistoryCardPresenter(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(); @@ -310,7 +290,9 @@ public class DvrBrowseFragment extends BrowseFragment @Override public void onRecordedProgramsChanged(RecordedProgram... recordedPrograms) { for (RecordedProgram recordedProgram : recordedPrograms) { - handleRecordedProgramChanged(recordedProgram); + if (recordedProgram.isVisible()) { + handleRecordedProgramChanged(recordedProgram); + } } postUpdateRows(); } @@ -340,6 +322,9 @@ public class DvrBrowseFragment extends BrowseFragment public void onScheduledRecordingRemoved(ScheduledRecording... scheduledRecordings) { for (ScheduledRecording scheduleRecording : scheduledRecordings) { mScheduleAdapter.remove(scheduleRecording); + if (scheduleRecording.getState() == ScheduledRecording.STATE_RECORDING_FAILED) { + mRecentAdapter.remove(scheduleRecording); + } } } @@ -351,6 +336,9 @@ public class DvrBrowseFragment extends BrowseFragment } else { mScheduleAdapter.removeWithId(scheduleRecording); } + if (scheduleRecording.getState() == ScheduledRecording.STATE_RECORDING_FAILED) { + mRecentAdapter.change(scheduleRecording); + } } } @@ -443,16 +431,17 @@ public class DvrBrowseFragment extends BrowseFragment 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); + if (recordedProgram.isVisible()) { + handleRecordedProgramAdded(recordedProgram, false); } - mRecentAdapter.addExtraItem(DvrHistoryCardHolder.DVR_HISTORY_CARD_HOLDER); } + // 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. @@ -592,9 +581,9 @@ public class DvrBrowseFragment extends BrowseFragment } } - private List<RecordedProgramAdapter> getGenreAdapters(String[] genres) { + private List<RecordedProgramAdapter> getGenreAdapters(ImmutableList<String> genres) { List<RecordedProgramAdapter> result = new ArrayList<>(); - if (genres == null || genres.length == 0) { + if (genres == null || genres.isEmpty()) { result.add(mGenreAdapters[mGenreAdapters.length - 1]); } else { for (String genre : genres) { @@ -642,8 +631,8 @@ public class DvrBrowseFragment extends BrowseFragment private void updateRows() { int visibleRowsCount = 1; // Schedule's Row will never be empty - int recentRowMinSize = TvFeatures.DVR_FAILED_LIST.isEnabled(getContext()) ? 1 : 0; - if (mRecentAdapter.size() <= recentRowMinSize) { + if (mRecentAdapter.size() <= 1) { + // remove the row if there is only the DVR history card mRowsAdapter.remove(mRecentRow); } else { if (mRowsAdapter.indexOf(mRecentRow) < 0) { @@ -673,6 +662,9 @@ public class DvrBrowseFragment extends BrowseFragment } } } + if (getSelectedPosition() >= mRowsAdapter.size()) { + setSelectedPosition(mRecentAdapter.size() - 1); + } } private boolean needToShowScheduledRecording(ScheduledRecording recording) { @@ -713,16 +705,13 @@ public class DvrBrowseFragment extends BrowseFragment 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); + (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); }); } diff --git a/src/com/android/tv/dvr/ui/browse/DvrDetailsActivity.java b/src/com/android/tv/dvr/ui/browse/DvrDetailsActivity.java deleted file mode 100644 index 0336b319..00000000 --- a/src/com/android/tv/dvr/ui/browse/DvrDetailsActivity.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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.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.Starter; -import com.android.tv.dialog.PinDialogFragment; - -/** Activity to show details view in DVR. */ -public class DvrDetailsActivity extends Activity implements PinDialogFragment.OnPinCheckedListener { - /** Name of record id added to the Intent. */ - public static final String RECORDING_ID = "record_id"; - - /** - * Name of flag added to the Intent to determine if details view should hide "View schedule" - * button. - */ - public static final String HIDE_VIEW_SCHEDULE = "hide_view_schedule"; - - /** 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. */ - 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; - - /** 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. */ - public static final int RECORDED_PROGRAM_VIEW = 3; - - /** 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) { - 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); - DetailsFragment detailsFragment = null; - if (detailsViewType == CURRENT_RECORDING_VIEW) { - 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(); - } else if (detailsViewType == SERIES_RECORDING_VIEW) { - detailsFragment = new SeriesRecordingDetailsFragment(); - } - detailsFragment.setArguments(args); - getFragmentManager() - .beginTransaction() - .replace(R.id.dvr_details_view_frame, detailsFragment) - .commit(); - } - - // This is a workaround for the focus on O device - addTransitionListener(); - } - - @Override - public void onPinChecked(boolean checked, int type, String rating) { - if (mOnPinCheckedListener != null) { - mOnPinCheckedListener.onPinChecked(checked, type, rating); - } - } - - void setOnPinCheckListener(PinDialogFragment.OnPinCheckedListener listener) { - mOnPinCheckedListener = listener; - } - - private void addTransitionListener() { - getWindow() - .getSharedElementEnterTransition() - .addListener( - new TransitionListener() { - @Override - public void onTransitionStart(Transition transition) { - // Do nothing - } - - @Override - public void onTransitionEnd(Transition transition) { - View actions = findViewById(R.id.details_overview_actions); - if (actions != null) { - actions.requestFocus(); - } - } - - @Override - public void onTransitionCancel(Transition transition) { - // Do nothing - - } - - @Override - public void onTransitionPause(Transition transition) { - // Do nothing - } - - @Override - public void onTransitionResume(Transition transition) { - // Do nothing - } - }); - } -} diff --git a/src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java index 8f4e4dab..f90981f0 100644 --- a/src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java +++ b/src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java @@ -47,8 +47,10 @@ 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.ui.DetailsActivity; import com.android.tv.util.ToastUtils; import com.android.tv.util.images.ImageLoader; +import com.google.common.collect.ImmutableList; import java.io.File; abstract class DvrDetailsFragment extends DetailsFragment { @@ -89,7 +91,7 @@ abstract class DvrDetailsFragment extends DetailsFragment { rowPresenter.setBackgroundColor( getResources().getColor(R.color.common_tv_background, null)); rowPresenter.setSharedElementEnterTransition( - getActivity(), DvrDetailsActivity.SHARED_ELEMENT_NAME); + getActivity(), DetailsActivity.SHARED_ELEMENT_NAME); rowPresenter.setOnActionClickedListener(onCreateOnActionClickedListener()); mRowsAdapter = new ArrayObjectAdapter(onCreatePresenterSelector(rowPresenter)); setAdapter(mRowsAdapter); @@ -221,7 +223,7 @@ abstract class DvrDetailsFragment extends DetailsFragment { checkPinToPlay(recordedProgram, seekTimeMs); return; } - TvContentRating[] ratings = recordedProgram.getContentRatings(); + ImmutableList<TvContentRating> ratings = recordedProgram.getContentRatings(); TvContentRating blockRatings = parental.getBlockedRating(ratings); if (blockRatings != null) { checkPinToPlay(recordedProgram, seekTimeMs); @@ -245,15 +247,14 @@ abstract class DvrDetailsFragment extends DetailsFragment { } private void checkPinToPlay(RecordedProgram recordedProgram, long seekTimeMs) { - SoftPreconditions.checkState(getActivity() instanceof DvrDetailsActivity); - if (getActivity() instanceof DvrDetailsActivity) { - ((DvrDetailsActivity) getActivity()) + SoftPreconditions.checkState(getActivity() instanceof DetailsActivity); + if (getActivity() instanceof DetailsActivity) { + ((DetailsActivity) getActivity()) .setOnPinCheckListener( new OnPinCheckedListener() { @Override public void onPinChecked(boolean checked, int type, String rating) { - ((DvrDetailsActivity) getActivity()) - .setOnPinCheckListener(null); + ((DetailsActivity) getActivity()).setOnPinCheckListener(null); if (checked && type == PinDialogFragment diff --git a/src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java index 47b1a198..bf963547 100644 --- a/src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java +++ b/src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java @@ -24,10 +24,13 @@ import android.support.v17.leanback.widget.OnActionClickedListener; import android.support.v17.leanback.widget.SparseArrayObjectAdapter; import com.android.tv.R; import com.android.tv.TvSingletons; +import com.android.tv.common.util.PermissionUtils; 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; +import com.android.tv.dvr.ui.DvrUiHelper; +import com.android.tv.ui.DetailsActivity; /** {@link android.support.v17.leanback.app.DetailsFragment} for recorded program in DVR. */ public class RecordedProgramDetailsFragment extends DvrDetailsFragment @@ -80,7 +83,7 @@ public class RecordedProgramDetailsFragment extends DvrDetailsFragment @Override protected boolean onLoadRecordingDetails(Bundle args) { - long recordedProgramId = args.getLong(DvrDetailsActivity.RECORDING_ID); + long recordedProgramId = args.getLong(DetailsActivity.RECORDING_ID); mRecordedProgram = mDvrDataManager.getRecordedProgram(recordedProgramId); return mRecordedProgram != null; } @@ -138,15 +141,24 @@ public class RecordedProgramDetailsFragment extends DvrDetailsFragment mDvrWatchedPositionManager.getWatchedPosition( mRecordedProgram.getId())); } else if (action.getId() == ACTION_DELETE_RECORDING) { - DvrManager dvrManager = - TvSingletons.getSingletons(getActivity()).getDvrManager(); - dvrManager.removeRecordedProgram(mRecordedProgram); - getActivity().finish(); + delete(); } } }; } + private void delete() { + if (!PermissionUtils.hasWriteExternalStorage(getContext()) + && DvrManager.isFile(mRecordedProgram.getDataUri()) + && !DvrManager.isFromBundledInput(mRecordedProgram)) { + DvrUiHelper.showWriteStoragePermissionRationaleDialog(getActivity()); + } else { + DvrManager dvrManager = TvSingletons.getSingletons(getActivity()).getDvrManager(); + dvrManager.removeRecordedProgram(mRecordedProgram, true); + getActivity().finish(); + } + } + @Override public void onRecordedProgramsAdded(RecordedProgram... recordedPrograms) {} diff --git a/src/com/android/tv/dvr/ui/browse/RecordingCardView.java b/src/com/android/tv/dvr/ui/browse/RecordingCardView.java index fe3c52d9..c83ceaf0 100644 --- a/src/com/android/tv/dvr/ui/browse/RecordingCardView.java +++ b/src/com/android/tv/dvr/ui/browse/RecordingCardView.java @@ -48,11 +48,10 @@ public class RecordingCardView extends BaseCardView { private final int mImageWidth; private final int mImageHeight; private String mImageUri; + private final ImageView mContentIconView; private final TextView mMajorContentView; private final TextView mMinorContentView; private final ProgressBar mProgressBar; - private final View mAffiliatedIconContainer; - private final ImageView mAffiliatedIcon; private final Drawable mDefaultImage; private final FrameLayout mTitleArea; private final TextView mFoldedTitleView; @@ -94,8 +93,7 @@ public class RecordingCardView extends BaseCardView { mImageWidth = imageWidth; mImageHeight = imageHeight; mProgressBar = (ProgressBar) findViewById(R.id.recording_progress); - mAffiliatedIconContainer = findViewById(R.id.affiliated_icon_container); - mAffiliatedIcon = (ImageView) findViewById(R.id.affiliated_icon); + mContentIconView = (ImageView) findViewById(R.id.content_icon); mMajorContentView = (TextView) findViewById(R.id.content_major); mMinorContentView = (TextView) findViewById(R.id.content_minor); mTitleArea = (FrameLayout) findViewById(R.id.title_area); @@ -184,6 +182,7 @@ public class RecordingCardView extends BaseCardView { } void setContent(CharSequence majorContent, CharSequence minorContent) { + mContentIconView.setVisibility(View.GONE); if (!TextUtils.isEmpty(majorContent)) { mMajorContentView.setText(majorContent); mMajorContentView.setVisibility(View.VISIBLE); @@ -198,6 +197,24 @@ public class RecordingCardView extends BaseCardView { } } + void setRecordingFailedContent(Context context) { + mContentIconView.setVisibility(View.VISIBLE); + mContentIconView.setImageResource(R.drawable.ic_error_outline_pink_24dp); + mMajorContentView.setText(context.getString(R.string.dvr_recording_failed_no_period)); + mMajorContentView.setVisibility(View.VISIBLE); + mMajorContentView.setTextColor( + getResources().getColor(R.color.dvr_recording_failed_text_color, null)); + } + + void setRecordingConflictContent(Context context) { + mContentIconView.setVisibility(View.VISIBLE); + mContentIconView.setImageResource(R.drawable.ic_warning_yellow_24dp); + mMajorContentView.setText(context.getString(R.string.dvr_recording_conflict)); + mMajorContentView.setVisibility(View.VISIBLE); + mMajorContentView.setTextColor( + getResources().getColor(R.color.dvr_recording_conflict_text_color, null)); + } + /** Sets progress bar. If progress is {@code null}, hides progress bar. */ void setProgressBar(Integer progress) { if (progress == null) { @@ -245,19 +262,6 @@ public class RecordingCardView extends BaseCardView { } /** - * Sets the affiliated icon of the card view, which will be displayed at the lower-right corner - * of the poster. - */ - public void setAffiliatedIcon(int imageResId) { - if (imageResId > 0) { - mAffiliatedIconContainer.setVisibility(View.VISIBLE); - mAffiliatedIcon.setImageResource(imageResId); - } else { - mAffiliatedIconContainer.setVisibility(View.INVISIBLE); - } - } - - /** * Sets the background image URI of the card view, which will be displayed as background when * the view is clicked and shows its details fragment. */ diff --git a/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java index aa2ccf75..243681c6 100644 --- a/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java +++ b/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java @@ -20,6 +20,7 @@ import android.os.Bundle; import android.support.v17.leanback.app.DetailsFragment; import com.android.tv.TvSingletons; import com.android.tv.dvr.data.ScheduledRecording; +import com.android.tv.ui.DetailsActivity; /** {@link DetailsFragment} for recordings in DVR. */ abstract class RecordingDetailsFragment extends DvrDetailsFragment { @@ -33,7 +34,7 @@ abstract class RecordingDetailsFragment extends DvrDetailsFragment { @Override protected boolean onLoadRecordingDetails(Bundle args) { - long scheduledRecordingId = args.getLong(DvrDetailsActivity.RECORDING_ID); + long scheduledRecordingId = args.getLong(DetailsActivity.RECORDING_ID); mRecording = TvSingletons.getSingletons(getContext()) .getDvrDataManager() diff --git a/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java index 302b8318..f08bb12b 100644 --- a/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java +++ b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java @@ -21,10 +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 com.android.tv.R; import com.android.tv.TvSingletons; import com.android.tv.dvr.DvrManager; import com.android.tv.dvr.ui.DvrUiHelper; +import com.android.tv.ui.DetailsActivity; /** {@link RecordingDetailsFragment} for scheduled recording in DVR. */ public class ScheduledRecordingDetailsFragment extends RecordingDetailsFragment { @@ -34,14 +36,12 @@ 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 = args.getBoolean(DvrDetailsActivity.HIDE_VIEW_SCHEDULE); - mFailedMessage = args.getString(DvrDetailsActivity.EXTRA_FAILED_MESSAGE); + mHideViewSchedule = args.getBoolean(DetailsActivity.HIDE_VIEW_SCHEDULE); super.onCreate(savedInstance); } @@ -54,17 +54,6 @@ 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 8e028689..3d279354 100644 --- a/src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java +++ b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java @@ -119,21 +119,17 @@ class ScheduledRecordingPresenter extends DvrItemPresenter<ScheduledRecording> { DetailsContent details = DetailsContent.createFromScheduledRecording(mContext, recording); cardView.setTitle(details.getTitle()); cardView.setImageUri(details.getLogoImageUri(), details.isUsingChannelLogo()); - 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); + if (recording.getState() == ScheduledRecording.STATE_RECORDING_FAILED) { + cardView.setRecordingFailedContent(mContext); + } else if (mDvrManager.isConflicting(recording)) { + cardView.setRecordingConflictContent(mContext); } else { - cardView.setAffiliatedIcon(0); + cardView.setContent(generateMajorContent(recording), null); } - 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/browse/SeriesRecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java index 2cd191a7..9104ef10 100644 --- a/src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java +++ b/src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java @@ -20,6 +20,7 @@ import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.media.tv.TvInputManager; import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.v17.leanback.app.DetailsFragment; import android.support.v17.leanback.widget.Action; import android.support.v17.leanback.widget.ArrayObjectAdapter; @@ -41,6 +42,7 @@ 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 com.android.tv.ui.DetailsActivity; import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -135,7 +137,7 @@ public class SeriesRecordingDetailsFragment extends DvrDetailsFragment @Override protected boolean onLoadRecordingDetails(Bundle args) { - long recordId = args.getLong(DvrDetailsActivity.RECORDING_ID); + long recordId = args.getLong(DetailsActivity.RECORDING_ID); mSeries = TvSingletons.getSingletons(getActivity()) .getDvrDataManager() @@ -215,6 +217,7 @@ public class SeriesRecordingDetailsFragment extends DvrDetailsFragment } /** The programs are sorted by season number and episode number. */ + @Nullable private RecordedProgram getRecommendProgram(List<RecordedProgram> programs) { for (int i = programs.size() - 1; i >= 0; i--) { RecordedProgram program = programs.get(i); @@ -289,7 +292,8 @@ public class SeriesRecordingDetailsFragment extends DvrDetailsFragment } } } - if (recordedProgram.getId() == mRecommendRecordedProgram.getId()) { + if (mRecommendRecordedProgram != null + && recordedProgram.getId() == mRecommendRecordedProgram.getId()) { updateWatchAction(); } } @@ -339,14 +343,7 @@ public class SeriesRecordingDetailsFragment extends DvrDetailsFragment 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)); + selector, BaseProgram.EPISODE_COMPARATOR::compare, seasonNumber)); getRowsAdapter().add(position, row); return row; } |