diff options
Diffstat (limited to 'src/com/android/tv/dvr/ui/DvrConflictFragment.java')
-rw-r--r-- | src/com/android/tv/dvr/ui/DvrConflictFragment.java | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/src/com/android/tv/dvr/ui/DvrConflictFragment.java b/src/com/android/tv/dvr/ui/DvrConflictFragment.java new file mode 100644 index 00000000..e7be4d0a --- /dev/null +++ b/src/com/android/tv/dvr/ui/DvrConflictFragment.java @@ -0,0 +1,339 @@ +/* + * 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; + +import android.graphics.drawable.Drawable; +import android.media.tv.TvInputInfo; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v17.leanback.widget.GuidanceStylist.Guidance; +import android.support.v17.leanback.widget.GuidedAction; +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.common.SoftPreconditions; +import com.android.tv.data.Channel; +import com.android.tv.data.Program; +import com.android.tv.dvr.ConflictChecker; +import com.android.tv.dvr.ConflictChecker.OnUpcomingConflictChangeListener; +import com.android.tv.dvr.DvrUiHelper; +import com.android.tv.dvr.ScheduledRecording; +import com.android.tv.util.Utils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; + +public abstract class DvrConflictFragment extends DvrGuidedStepFragment { + private static final String TAG = "DvrConflictFragment"; + private static final boolean DEBUG = false; + + private static final int ACTION_DELETE_CONFLICT = 1; + private static final int ACTION_CANCEL = 2; + private static final int ACTION_VIEW_SCHEDULES = 3; + + // The program count which will be listed in the description. This is the number of the + // program strings in R.plurals.dvr_program_conflict_dialog_description_many. + private static final int LISTED_PROGRAM_COUNT = 2; + + protected List<ScheduledRecording> mConflicts; + + void setConflicts(List<ScheduledRecording> conflicts) { + mConflicts = conflicts; + } + + List<ScheduledRecording> getConflicts() { + return mConflicts; + } + + @Override + public int onProvideTheme() { + return R.style.Theme_TV_Dvr_Conflict_GuidedStep; + } + + @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()); + } + + @Override + public void onGuidedActionClicked(GuidedAction action) { + if (action.getId() == ACTION_VIEW_SCHEDULES) { + DvrUiHelper.startSchedulesActivityForOneTimeRecordingConflict( + getContext(), getConflicts()); + } + dismissDialog(); + } + + String getConflictDescription() { + List<String> titles = new ArrayList<>(); + HashSet<String> titleSet = new HashSet<>(); + for (ScheduledRecording schedule : getConflicts()) { + String scheduleTitle = getScheduleTitle(schedule); + if (scheduleTitle != null && !titleSet.contains(scheduleTitle)) { + titles.add(scheduleTitle); + titleSet.add(scheduleTitle); + } + } + switch (titles.size()) { + case 0: + 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)); + case 2: + 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)); + 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); + } + } + + @Nullable + private String getScheduleTitle(ScheduledRecording schedule) { + if (schedule.getType() == ScheduledRecording.TYPE_TIMED) { + Channel channel = TvApplication.getSingletons(getContext()).getChannelDataManager() + .getChannel(schedule.getChannelId()); + if (channel != null) { + return channel.getDisplayName(); + } else { + return null; + } + } else { + return schedule.getProgramTitle(); + } + } + + /** + * 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) { + Bundle args = getArguments(); + if (args != null) { + mProgram = args.getParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM); + } + SoftPreconditions.checkArgument(mProgram != null); + TvInputInfo input = Utils.getTvInputInfoForProgram(getContext(), mProgram); + SoftPreconditions.checkNotNull(input); + List<ScheduledRecording> conflicts = null; + if (input != null) { + conflicts = TvApplication.getSingletons(getContext()).getDvrManager() + .getConflictingSchedules(mProgram); + } + if (conflicts == null) { + conflicts = Collections.emptyList(); + } + if (conflicts.isEmpty()) { + dismissDialog(); + } + setConflicts(conflicts); + return super.onCreateView(inflater, container, savedInstanceState); + } + + @NonNull + @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 description = getConflictDescription(); + if (description == null) { + dismissDialog(); + } + Drawable icon = getResources().getDrawable(R.drawable.ic_error_white_48dp, null); + return new Guidance(title, descriptionPrefix + " " + description, null, icon); + } + } + + /** + * 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) { + Bundle args = getArguments(); + long channelId = args.getLong(DvrHalfSizedDialogFragment.KEY_CHANNEL_ID); + mChannel = TvApplication.getSingletons(getContext()).getChannelDataManager() + .getChannel(channelId); + SoftPreconditions.checkArgument(mChannel != null); + TvInputInfo input = Utils.getTvInputInfoForChannelId(getContext(), mChannel.getId()); + SoftPreconditions.checkNotNull(input); + List<ScheduledRecording> conflicts = null; + 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); + } + if (conflicts == null) { + conflicts = Collections.emptyList(); + } + if (conflicts.isEmpty()) { + dismissDialog(); + } + setConflicts(conflicts); + return super.onCreateView(inflater, container, savedInstanceState); + } + + @NonNull + @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 description = getConflictDescription(); + if (description == null) { + dismissDialog(); + } + Drawable icon = getResources().getDrawable(R.drawable.ic_error_white_48dp, null); + return new Guidance(title, descriptionPrefix + " " + description, null, icon); + } + } + + /** + * A fragment to show the channel watching conflict. + * <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) { + Bundle args = getArguments(); + if (args != null) { + mChannelId = args.getLong(DvrHalfSizedDialogFragment.KEY_CHANNEL_ID); + } + SoftPreconditions.checkArgument(mChannelId != Channel.INVALID_ID); + ConflictChecker checker = ((MainActivity) getContext()).getDvrConflictChecker(); + List<ScheduledRecording> conflicts = null; + if (checker != null) { + checker.addOnUpcomingConflictChangeListener(this); + conflicts = checker.getUpcomingConflicts(); + if (DEBUG) Log.d(TAG, "onCreateView: upcoming conflicts: " + conflicts); + if (conflicts.isEmpty()) { + dismissDialog(); + } + } + if (conflicts == null) { + if (DEBUG) Log.d(TAG, "onCreateView: There's no conflict."); + conflicts = Collections.emptyList(); + } + if (conflicts.isEmpty()) { + dismissDialog(); + } + setConflicts(conflicts); + return super.onCreateView(inflater, container, savedInstanceState); + } + + @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); + 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()); + } + + @Override + public void onGuidedActionClicked(GuidedAction action) { + if (action.getId() == ACTION_CANCEL) { + ConflictChecker checker = ((MainActivity) getContext()).getDvrConflictChecker(); + if (checker != null) { + checker.setCheckedConflictsForChannel(mChannelId, getConflicts()); + } + } else if (action.getId() == ACTION_DELETE_CONFLICT) { + for (ScheduledRecording schedule : mConflicts) { + if (schedule.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS) { + getDvrManager().stopRecording(schedule); + } else { + getDvrManager().removeScheduledRecording(schedule); + } + } + } + super.onGuidedActionClicked(action); + } + + @Override + public void onDetach() { + ConflictChecker checker = ((MainActivity) getContext()).getDvrConflictChecker(); + if (checker != null) { + checker.removeOnUpcomingConflictChangeListener(this); + } + super.onDetach(); + } + + @Override + public void onUpcomingConflictChange() { + ConflictChecker checker = ((MainActivity) getContext()).getDvrConflictChecker(); + if (checker == null || checker.getUpcomingConflicts().isEmpty()) { + if (DEBUG) Log.d(TAG, "onUpcomingConflictChange: There's no conflict."); + dismissDialog(); + } + } + } +} |