aboutsummaryrefslogtreecommitdiff
path: root/src/com/android/tv/dvr/ui/DvrConflictFragment.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/tv/dvr/ui/DvrConflictFragment.java')
-rw-r--r--src/com/android/tv/dvr/ui/DvrConflictFragment.java339
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();
+ }
+ }
+ }
+}