1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tv.dvr.ui; 18 19 import android.annotation.TargetApi; 20 import android.content.Context; 21 import android.graphics.drawable.Drawable; 22 import android.os.Build; 23 import android.os.Bundle; 24 import android.support.annotation.NonNull; 25 import android.support.v17.leanback.app.GuidedStepFragment; 26 import android.support.v17.leanback.widget.GuidanceStylist.Guidance; 27 import android.support.v17.leanback.widget.GuidedAction; 28 import android.text.format.DateUtils; 29 import com.android.tv.R; 30 import com.android.tv.TvSingletons; 31 import com.android.tv.common.SoftPreconditions; 32 import com.android.tv.data.Program; 33 import com.android.tv.dvr.DvrManager; 34 import com.android.tv.dvr.data.ScheduledRecording; 35 import com.android.tv.dvr.data.SeriesRecording; 36 import com.android.tv.dvr.ui.DvrConflictFragment.DvrProgramConflictFragment; 37 import com.android.tv.util.Utils; 38 import java.util.Collections; 39 import java.util.List; 40 41 /** 42 * A fragment which asks the user the type of the recording. 43 * 44 * <p>The program should be episodic and the series recording should not had been created yet. 45 */ 46 @TargetApi(Build.VERSION_CODES.N) 47 public class DvrScheduleFragment extends DvrGuidedStepFragment { 48 /** Key for the whether to add the current program to series. Type: boolean */ 49 public static final String KEY_ADD_CURRENT_PROGRAM_TO_SERIES = "add_current_program_to_series"; 50 51 private static final String TAG = "DvrScheduleFragment"; 52 53 private static final int ACTION_RECORD_EPISODE = 1; 54 private static final int ACTION_RECORD_SERIES = 2; 55 56 private Program mProgram; 57 private boolean mAddCurrentProgramToSeries; 58 59 @Override 60 public void onCreate(Bundle savedInstanceState) { 61 Bundle args = getArguments(); 62 if (args != null) { 63 mProgram = args.getParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM); 64 mAddCurrentProgramToSeries = args.getBoolean(KEY_ADD_CURRENT_PROGRAM_TO_SERIES, false); 65 } 66 DvrManager dvrManager = TvSingletons.getSingletons(getContext()).getDvrManager(); 67 SoftPreconditions.checkArgument( 68 mProgram != null && mProgram.isEpisodic(), 69 TAG, 70 "The program should be episodic: %s ", 71 mProgram); 72 SeriesRecording seriesRecording = dvrManager.getSeriesRecording(mProgram); 73 SoftPreconditions.checkArgument( 74 seriesRecording == null || seriesRecording.isStopped(), 75 TAG, 76 "The series recording should be stopped or null: %s", 77 seriesRecording); 78 super.onCreate(savedInstanceState); 79 } 80 81 @Override 82 public int onProvideTheme() { 83 return R.style.Theme_TV_Dvr_GuidedStep_Twoline_Action; 84 } 85 86 @NonNull 87 @Override 88 public Guidance onCreateGuidance(Bundle savedInstanceState) { 89 String title = getString(R.string.dvr_schedule_dialog_title); 90 Drawable icon = getResources().getDrawable(R.drawable.ic_dvr, null); 91 return new Guidance(title, null, null, icon); 92 } 93 94 @Override 95 public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) { 96 Context context = getContext(); 97 String description; 98 if (mProgram.getStartTimeUtcMillis() <= System.currentTimeMillis()) { 99 description = 100 getString( 101 R.string.dvr_action_record_episode_from_now_description, 102 DateUtils.formatDateTime( 103 context, 104 mProgram.getEndTimeUtcMillis(), 105 DateUtils.FORMAT_SHOW_TIME)); 106 } else { 107 description = 108 Utils.getDurationString( 109 context, 110 mProgram.getStartTimeUtcMillis(), 111 mProgram.getEndTimeUtcMillis(), 112 true); 113 } 114 actions.add( 115 new GuidedAction.Builder(context) 116 .id(ACTION_RECORD_EPISODE) 117 .title(R.string.dvr_action_record_episode) 118 .description(description) 119 .build()); 120 actions.add( 121 new GuidedAction.Builder(context) 122 .id(ACTION_RECORD_SERIES) 123 .title(R.string.dvr_action_record_series) 124 .description(mProgram.getTitle()) 125 .build()); 126 } 127 128 @Override 129 public void onTrackedGuidedActionClicked(GuidedAction action) { 130 if (action.getId() == ACTION_RECORD_EPISODE) { 131 getDvrManager().addSchedule(mProgram); 132 List<ScheduledRecording> conflicts = getDvrManager().getConflictingSchedules(mProgram); 133 if (conflicts.isEmpty()) { 134 DvrUiHelper.showAddScheduleToast( 135 getContext(), 136 mProgram.getTitle(), 137 mProgram.getStartTimeUtcMillis(), 138 mProgram.getEndTimeUtcMillis()); 139 dismissDialog(); 140 } else { 141 GuidedStepFragment fragment = new DvrProgramConflictFragment(); 142 Bundle args = new Bundle(); 143 args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, mProgram); 144 fragment.setArguments(args); 145 GuidedStepFragment.add(getFragmentManager(), fragment, R.id.halfsized_dialog_host); 146 } 147 } else if (action.getId() == ACTION_RECORD_SERIES) { 148 SeriesRecording seriesRecording = 149 TvSingletons.getSingletons(getContext()) 150 .getDvrDataManager() 151 .getSeriesRecording(mProgram.getSeriesId()); 152 if (seriesRecording == null) { 153 seriesRecording = 154 getDvrManager() 155 .addSeriesRecording( 156 mProgram, 157 Collections.emptyList(), 158 SeriesRecording.STATE_SERIES_STOPPED); 159 } else { 160 // Reset priority to the highest. 161 seriesRecording = 162 SeriesRecording.buildFrom(seriesRecording) 163 .setPriority( 164 TvSingletons.getSingletons(getContext()) 165 .getDvrScheduleManager() 166 .suggestNewSeriesPriority()) 167 .build(); 168 getDvrManager().updateSeriesRecording(seriesRecording); 169 } 170 171 DvrUiHelper.startSeriesSettingsActivity( 172 getContext(), 173 seriesRecording.getId(), 174 null, 175 true, 176 true, 177 true, 178 mAddCurrentProgramToSeries ? mProgram : null); 179 dismissDialog(); 180 } 181 } 182 183 @Override 184 public String getTrackerPrefix() { 185 return "DvrSmallSizedStorageErrorFragment"; 186 } 187 188 @Override 189 public String getTrackerLabelForGuidedAction(GuidedAction action) { 190 long actionId = action.getId(); 191 if (actionId == ACTION_RECORD_EPISODE) { 192 return "record-episode"; 193 } else if (actionId == ACTION_RECORD_SERIES) { 194 return "record-series"; 195 } else { 196 return super.getTrackerLabelForGuidedAction(action); 197 } 198 } 199 } 200