diff options
author | Xin Li <delphij@google.com> | 2018-08-06 16:51:26 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2018-08-06 16:51:26 -0700 |
commit | aca265722281fe082995a71fd35401f766afac3e (patch) | |
tree | 28eac0d8752df3b094f50103a9ebb6d6340f4cc8 /src/com/android/tv/dvr/ui | |
parent | 5fdc24aa6cc0acfd6a2d5939862e6edbe14f1ef6 (diff) | |
parent | c56e1892201e0b31f3043e37a32d779b4055cb34 (diff) | |
download | TV-aca265722281fe082995a71fd35401f766afac3e.tar.gz |
Merge Android Pie into masterandroid-o-mr1-iot-release-smart-display-r3android-o-mr1-iot-release-1.0.5android-o-mr1-iot-release-1.0.4android-o-mr1-iot-release-1.0.3oreo-mr1-1.2-iot-releasemaster-cuttlefish-testing-release
Bug: 112104996
Change-Id: Iec32f622f0bb1bc1583aefcbf6d115ad05baa693
Diffstat (limited to 'src/com/android/tv/dvr/ui')
73 files changed, 4030 insertions, 2856 deletions
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 +} |