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.text.format.DateUtils; 26 27 import androidx.leanback.app.GuidedStepFragment; 28 import androidx.leanback.widget.GuidanceStylist.Guidance; 29 import androidx.leanback.widget.GuidedAction; 30 31 import com.android.tv.R; 32 import com.android.tv.TvSingletons; 33 import com.android.tv.common.SoftPreconditions; 34 import com.android.tv.common.flags.DvrFlags; 35 import com.android.tv.data.ProgramImpl; 36 import com.android.tv.dvr.DvrManager; 37 import com.android.tv.dvr.data.ScheduledRecording; 38 import com.android.tv.dvr.data.SeriesRecording; 39 import com.android.tv.dvr.ui.DvrConflictFragment.DvrProgramConflictFragment; 40 41 import java.util.Collections; 42 import java.util.List; 43 44 import javax.inject.Inject; 45 import dagger.android.AndroidInjection; 46 47 /** 48 * A fragment which asks the user the type of the recording. 49 * 50 * <p>The program should be episodic and the series recording should not had been created yet. 51 */ 52 @TargetApi(Build.VERSION_CODES.N) 53 public class DvrScheduleFragment extends DvrGuidedStepFragment { 54 /** Key for the whether to add the current program to series. Type: boolean */ 55 public static final String KEY_ADD_CURRENT_PROGRAM_TO_SERIES = "add_current_program_to_series"; 56 57 private static final String TAG = "DvrScheduleFragment"; 58 59 private static final int ACTION_RECORD_EPISODE = 1; 60 private static final int ACTION_RECORD_SERIES = 2; 61 62 private ProgramImpl mProgram; 63 private boolean mAddCurrentProgramToSeries; 64 @Inject DvrFlags mDvrFlags; 65 66 @Override onCreate(Bundle savedInstanceState)67 public void onCreate(Bundle savedInstanceState) { 68 Bundle args = getArguments(); 69 if (args != null) { 70 mProgram = args.getParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM); 71 mAddCurrentProgramToSeries = args.getBoolean(KEY_ADD_CURRENT_PROGRAM_TO_SERIES, false); 72 } 73 DvrManager dvrManager = TvSingletons.getSingletons(getContext()).getDvrManager(); 74 SoftPreconditions.checkArgument( 75 mProgram != null && mProgram.isEpisodic(), 76 TAG, 77 "The program should be episodic: %s ", 78 mProgram); 79 SeriesRecording seriesRecording = dvrManager.getSeriesRecording(mProgram); 80 SoftPreconditions.checkArgument( 81 seriesRecording == null || seriesRecording.isStopped(), 82 TAG, 83 "The series recording should be stopped or null: %s", 84 seriesRecording); 85 super.onCreate(savedInstanceState); 86 } 87 88 @Override onAttach(Context context)89 public void onAttach(Context context) { 90 AndroidInjection.inject(this); 91 super.onAttach(context); 92 } 93 94 @Override onProvideTheme()95 public int onProvideTheme() { 96 return R.style.Theme_TV_Dvr_GuidedStep_Twoline_Action; 97 } 98 99 @NonNull 100 @Override onCreateGuidance(Bundle savedInstanceState)101 public Guidance onCreateGuidance(Bundle savedInstanceState) { 102 String title = getString(R.string.dvr_schedule_dialog_title); 103 Drawable icon = getResources().getDrawable(R.drawable.ic_dvr, null); 104 return new Guidance(title, null, null, icon); 105 } 106 107 @Override onCreateActions(@onNull List<GuidedAction> actions, Bundle savedInstanceState)108 public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) { 109 Context context = getContext(); 110 String description; 111 if (mProgram.getStartTimeUtcMillis() <= System.currentTimeMillis()) { 112 description = 113 getString( 114 R.string.dvr_action_record_episode_from_now_description, 115 DateUtils.formatDateTime( 116 context, 117 mProgram.getEndTimeUtcMillis(), 118 DateUtils.FORMAT_SHOW_TIME)); 119 } else { 120 description = mProgram.getDurationString(context); 121 } 122 actions.add( 123 new GuidedAction.Builder(context) 124 .id(ACTION_RECORD_EPISODE) 125 .title(R.string.dvr_action_record_episode) 126 .description(description) 127 .build()); 128 actions.add( 129 new GuidedAction.Builder(context) 130 .id(ACTION_RECORD_SERIES) 131 .title(R.string.dvr_action_record_series) 132 .description(mProgram.getTitle()) 133 .build()); 134 } 135 136 @Override onTrackedGuidedActionClicked(GuidedAction action)137 public void onTrackedGuidedActionClicked(GuidedAction action) { 138 if (action.getId() == ACTION_RECORD_EPISODE) { 139 if (mDvrFlags.startEarlyEndLateEnabled()) { 140 DvrUiHelper.startRecordingSettingsActivity(getContext(), mProgram); 141 } else { 142 getDvrManager().addSchedule(mProgram); 143 List<ScheduledRecording> conflicts = getDvrManager().getConflictingSchedules 144 (mProgram); 145 146 if (conflicts.isEmpty()) { 147 DvrUiHelper.showAddScheduleToast( 148 getContext(), 149 mProgram.getTitle(), 150 mProgram.getStartTimeUtcMillis(), 151 mProgram.getEndTimeUtcMillis()); 152 dismissDialog(); 153 } else { 154 GuidedStepFragment fragment = new DvrProgramConflictFragment(); 155 Bundle args = new Bundle(); 156 args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, mProgram); 157 fragment.setArguments(args); 158 GuidedStepFragment.add(getFragmentManager(), fragment, R.id 159 .halfsized_dialog_host); 160 } 161 } 162 } else if (action.getId() == ACTION_RECORD_SERIES) { 163 SeriesRecording seriesRecording = 164 TvSingletons.getSingletons(getContext()) 165 .getDvrDataManager() 166 .getSeriesRecording(mProgram.getSeriesId()); 167 if (seriesRecording == null) { 168 seriesRecording = 169 getDvrManager() 170 .addSeriesRecording( 171 mProgram, 172 Collections.emptyList(), 173 SeriesRecording.STATE_SERIES_STOPPED); 174 } else { 175 // Reset priority to the highest. 176 seriesRecording = 177 SeriesRecording.buildFrom(seriesRecording) 178 .setPriority( 179 TvSingletons.getSingletons(getContext()) 180 .getDvrScheduleManager() 181 .suggestNewSeriesPriority()) 182 .build(); 183 getDvrManager().updateSeriesRecording(seriesRecording); 184 } 185 186 DvrUiHelper.startSeriesSettingsActivity( 187 getContext(), 188 seriesRecording.getId(), 189 null, 190 true, 191 true, 192 true, 193 mAddCurrentProgramToSeries ? mProgram : null); 194 dismissDialog(); 195 } 196 } 197 198 @Override getTrackerPrefix()199 public String getTrackerPrefix() { 200 return "DvrSmallSizedStorageErrorFragment"; 201 } 202 203 @Override getTrackerLabelForGuidedAction(GuidedAction action)204 public String getTrackerLabelForGuidedAction(GuidedAction action) { 205 long actionId = action.getId(); 206 if (actionId == ACTION_RECORD_EPISODE) { 207 return "record-episode"; 208 } else if (actionId == ACTION_RECORD_SERIES) { 209 return "record-series"; 210 } else { 211 return super.getTrackerLabelForGuidedAction(action); 212 } 213 } 214 } 215