11abddd9f6225298066094e20a6c29061b6af4590Nick Chalko/* 21abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Copyright (C) 2015 The Android Open Source Project 31abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * 41abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License"); 51abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * you may not use this file except in compliance with the License. 61abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * You may obtain a copy of the License at 71abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * 81abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * http://www.apache.org/licenses/LICENSE-2.0 91abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * 101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Unless required by applicable law or agreed to in writing, software 111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS, 121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * See the License for the specific language governing permissions and 141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * limitations under the License. 151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 171abddd9f6225298066094e20a6c29061b6af4590Nick Chalkopackage com.android.tv.dvr; 181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 1965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.annotation.TargetApi; 20d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport android.content.ContentProviderOperation; 212e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport android.content.ContentResolver; 2265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.content.ContentUris; 231abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.content.Context; 24d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport android.content.OperationApplicationException; 2565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.media.tv.TvContract; 262e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport android.media.tv.TvInputInfo; 2765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.net.Uri; 28d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport android.os.AsyncTask; 2965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.os.Build; 302e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport android.os.Handler; 31d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport android.os.RemoteException; 32ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.support.annotation.MainThread; 33ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.support.annotation.NonNull; 3465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.annotation.Nullable; 3565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.annotation.VisibleForTesting; 362e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport android.support.annotation.WorkerThread; 371abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.util.Log; 38d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport android.util.Range; 391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 401abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.ApplicationSingletons; 411abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.TvApplication; 422e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport com.android.tv.common.SoftPreconditions; 43ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport com.android.tv.common.feature.CommonFeatures; 441abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.data.Channel; 451abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.data.Program; 46d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.dvr.DvrDataManager.OnRecordedProgramLoadFinishedListener; 47d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.dvr.DvrDataManager.RecordedProgramListener; 48d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.dvr.DvrScheduleManager.OnInitializeListener; 496ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.RecordedProgram; 506ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.ScheduledRecording; 516ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.SeriesRecording; 522e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport com.android.tv.util.AsyncDbTask; 531abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.util.Utils; 541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 5565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.io.File; 5665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.ArrayList; 5765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.Arrays; 58ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport java.util.Collections; 592e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport java.util.HashMap; 601abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.util.List; 612e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport java.util.Map; 622e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport java.util.Map.Entry; 631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko/** 651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * DVR manager class to add and remove recordings. UI can modify recording list through this class, 661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * instead of modifying them directly through {@link DvrDataManager}. 671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 68ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko@MainThread 6965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko@TargetApi(Build.VERSION_CODES.N) 701abddd9f6225298066094e20a6c29061b6af4590Nick Chalkopublic class DvrManager { 7165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private static final String TAG = "DvrManager"; 7265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private static final boolean DEBUG = false; 7365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private final WritableDvrDataManager mDataManager; 7565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private final DvrScheduleManager mScheduleManager; 762e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko // @GuardedBy("mListener") 772e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko private final Map<Listener, Handler> mListener = new HashMap<>(); 782e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko private final Context mAppContext; 791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 801abddd9f6225298066094e20a6c29061b6af4590Nick Chalko public DvrManager(Context context) { 81ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko SoftPreconditions.checkFeatureEnabled(context, CommonFeatures.DVR, TAG); 82d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mAppContext = context.getApplicationContext(); 831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko ApplicationSingletons appSingletons = TvApplication.getSingletons(context); 841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mDataManager = (WritableDvrDataManager) appSingletons.getDvrDataManager(); 8565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mScheduleManager = appSingletons.getDvrScheduleManager(); 86d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (mDataManager.isInitialized() && mScheduleManager.isInitialized()) { 87d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko createSeriesRecordingsForRecordedProgramsIfNeeded(mDataManager.getRecordedPrograms()); 88d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } else { 89d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko // No need to handle DVR schedule load finished because schedule manager is initialized 90d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko // after the all the schedules are loaded. 91d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (!mDataManager.isRecordedProgramLoadFinished()) { 92d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mDataManager.addRecordedProgramLoadFinishedListener( 93d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko new OnRecordedProgramLoadFinishedListener() { 94d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko @Override 95d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public void onRecordedProgramLoadFinished() { 96d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mDataManager.removeRecordedProgramLoadFinishedListener(this); 97d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (mDataManager.isInitialized() 98d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko && mScheduleManager.isInitialized()) { 99d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko createSeriesRecordingsForRecordedProgramsIfNeeded( 100d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mDataManager.getRecordedPrograms()); 101d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 102d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 103d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko }); 104d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 105d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (!mScheduleManager.isInitialized()) { 106d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mScheduleManager.addOnInitializeListener(new OnInitializeListener() { 107d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko @Override 108d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public void onInitialize() { 109d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mScheduleManager.removeOnInitializeListener(this); 110d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (mDataManager.isInitialized() && mScheduleManager.isInitialized()) { 111d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko createSeriesRecordingsForRecordedProgramsIfNeeded( 112d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mDataManager.getRecordedPrograms()); 113d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 114d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 115d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko }); 116d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 117d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 118d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mDataManager.addRecordedProgramListener(new RecordedProgramListener() { 119d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko @Override 120d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public void onRecordedProgramsAdded(RecordedProgram... recordedPrograms) { 121d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (!mDataManager.isInitialized() || !mScheduleManager.isInitialized()) { 122d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return; 123d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 124d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko for (RecordedProgram recordedProgram : recordedPrograms) { 125d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko createSeriesRecordingForRecordedProgramIfNeeded(recordedProgram); 126d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 127d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 128d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko 129d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko @Override 130d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public void onRecordedProgramsChanged(RecordedProgram... recordedPrograms) { } 131d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko 132d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko @Override 133d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public void onRecordedProgramsRemoved(RecordedProgram... recordedPrograms) { 134d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko // Removing series recording is handled in the SeriesRecordingDetailsFragment. 135d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 136d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko }); 137d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 138d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko 139d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko private void createSeriesRecordingsForRecordedProgramsIfNeeded( 140d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko List<RecordedProgram> recordedPrograms) { 141d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko for (RecordedProgram recordedProgram : recordedPrograms) { 142d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko createSeriesRecordingForRecordedProgramIfNeeded(recordedProgram); 143d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 144d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 145d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko 146d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko private void createSeriesRecordingForRecordedProgramIfNeeded(RecordedProgram recordedProgram) { 1476ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (recordedProgram.isEpisodic()) { 148d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko SeriesRecording seriesRecording = 149d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mDataManager.getSeriesRecording(recordedProgram.getSeriesId()); 150d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (seriesRecording == null) { 151d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko addSeriesRecording(recordedProgram); 152d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 153d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 15465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 15565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 15665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 15765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Schedules a recording for {@code program}. 15865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 159d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public ScheduledRecording addSchedule(Program program) { 16065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 161d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return null; 16265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 16365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko SeriesRecording seriesRecording = getSeriesRecording(program); 164d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return addSchedule(program, seriesRecording == null 165d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko ? mScheduleManager.suggestNewPriority() 166d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko : seriesRecording.getPriority()); 1671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 1691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko /** 170d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * Schedules a recording for {@code program} with the highest priority so that the schedule 171d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * can be recorded. 1721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 173d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public ScheduledRecording addScheduleWithHighestPriority(Program program) { 17465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 175d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return null; 17665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 177d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko SeriesRecording seriesRecording = getSeriesRecording(program); 178d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return addSchedule(program, seriesRecording == null 179d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko ? mScheduleManager.suggestNewPriority() 180d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko : mScheduleManager.suggestHighestPriority(seriesRecording.getInputId(), 181d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko new Range(program.getStartTimeUtcMillis(), program.getEndTimeUtcMillis()), 182d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko seriesRecording.getPriority())); 183d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 184d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko 185d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko private ScheduledRecording addSchedule(Program program, long priority) { 18665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko TvInputInfo input = Utils.getTvInputInfoForProgram(mAppContext, program); 18765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (input == null) { 18865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko Log.e(TAG, "Can't find input for program: " + program); 189d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return null; 19065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 191d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko ScheduledRecording schedule; 192d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko SeriesRecording seriesRecording = getSeriesRecording(program); 193d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko schedule = createScheduledRecordingBuilder(input.getId(), program) 194ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko .setPriority(priority) 195d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko .setSeriesRecordingId(seriesRecording == null ? SeriesRecording.ID_NOT_SET 196d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko : seriesRecording.getId()) 197ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko .build(); 198d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mDataManager.addScheduledRecording(schedule); 199d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return schedule; 2001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 2021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko /** 2031abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Adds a recording schedule with a time range. 2041abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 2051abddd9f6225298066094e20a6c29061b6af4590Nick Chalko public void addSchedule(Channel channel, long startTime, long endTime) { 20665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko Log.i(TAG, "Adding scheduled recording of channel " + channel + " starting at " + 2071abddd9f6225298066094e20a6c29061b6af4590Nick Chalko Utils.toTimeString(startTime) + " and ending at " + Utils.toTimeString(endTime)); 20865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 20965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return; 21065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 21165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko TvInputInfo input = Utils.getTvInputInfoForChannelId(mAppContext, channel.getId()); 21265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (input == null) { 21365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko Log.e(TAG, "Can't find input for channel: " + channel); 21465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return; 21565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 21665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko addScheduleInternal(input.getId(), channel.getId(), startTime, endTime); 21765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 21865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 219d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko /** 220d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * Adds the schedule. 221d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko */ 222d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public void addSchedule(ScheduledRecording schedule) { 223d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (mDataManager.isDvrScheduleLoadFinished()) { 224d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mDataManager.addScheduledRecording(schedule); 225d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 226d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 227d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko 22865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private void addScheduleInternal(String inputId, long channelId, long startTime, long endTime) { 22965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mDataManager.addScheduledRecording(ScheduledRecording 23065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko .builder(inputId, channelId, startTime, endTime) 23165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko .setPriority(mScheduleManager.suggestNewPriority()) 23265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko .build()); 23365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 23465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 23565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 236d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * Adds a new series recording and schedules for the programs with the initial state. 23765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 23865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public SeriesRecording addSeriesRecording(Program selectedProgram, 2396ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko List<Program> programsToSchedule, @SeriesRecording.SeriesState int initialState) { 24065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko Log.i(TAG, "Adding series recording for program " + selectedProgram + ", and schedules: " 24165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko + programsToSchedule); 24265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isInitialized())) { 24365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return null; 24465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 24565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko TvInputInfo input = Utils.getTvInputInfoForProgram(mAppContext, selectedProgram); 24665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (input == null) { 24765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko Log.e(TAG, "Can't find input for program: " + selectedProgram); 24865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return null; 24965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 25065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko SeriesRecording seriesRecording = SeriesRecording.builder(input.getId(), selectedProgram) 25165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko .setPriority(mScheduleManager.suggestNewSeriesPriority()) 252d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko .setState(initialState) 2532e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko .build(); 25465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mDataManager.addSeriesRecording(seriesRecording); 25565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko // The schedules for the recorded programs should be added not to create the schedule the 25665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko // duplicate episodes. 25765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko addRecordedProgramToSeriesRecording(seriesRecording); 25865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko addScheduleToSeriesRecording(seriesRecording, programsToSchedule); 25965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return seriesRecording; 26065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 26165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 262d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko private void addSeriesRecording(RecordedProgram recordedProgram) { 263d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko SeriesRecording seriesRecording = 264d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko SeriesRecording.builder(recordedProgram.getInputId(), recordedProgram) 265d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko .setPriority(mScheduleManager.suggestNewSeriesPriority()) 266d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko .setState(SeriesRecording.STATE_SERIES_STOPPED) 267d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko .build(); 268d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mDataManager.addSeriesRecording(seriesRecording); 269d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko // The schedules for the recorded programs should be added not to create the schedule the 270d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko // duplicate episodes. 271d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko addRecordedProgramToSeriesRecording(seriesRecording); 272d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 273d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko 27465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private void addRecordedProgramToSeriesRecording(SeriesRecording series) { 27565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko List<ScheduledRecording> toAdd = new ArrayList<>(); 27665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko for (RecordedProgram recordedProgram : mDataManager.getRecordedPrograms()) { 27765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (series.getSeriesId().equals(recordedProgram.getSeriesId()) 27865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko && !recordedProgram.isClipped()) { 27965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko // Duplicate schedules can exist, but they will be deleted in a few days. And it's 28065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko // also guaranteed that the schedules don't belong to any series recordings because 28165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko // there are no more than one series recordings which have the same program title. 28265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko toAdd.add(ScheduledRecording.builder(recordedProgram) 28365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko .setPriority(series.getPriority()) 28465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko .setSeriesRecordingId(series.getId()).build()); 28565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 28665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 28765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!toAdd.isEmpty()) { 28865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mDataManager.addScheduledRecording(ScheduledRecording.toArray(toAdd)); 28965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 29065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 29165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 29265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 29365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Adds {@link ScheduledRecording}s for the series recording. 29465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * <p> 29565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * This method doesn't add the series recording. 29665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 29765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void addScheduleToSeriesRecording(SeriesRecording series, 29865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko List<Program> programsToSchedule) { 29965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 30065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return; 30165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 30265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko TvInputInfo input = Utils.getTvInputInfoForInputId(mAppContext, series.getInputId()); 30365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (input == null) { 30465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko Log.e(TAG, "Can't find input with ID: " + series.getInputId()); 30565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return; 30665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 30765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko List<ScheduledRecording> toAdd = new ArrayList<>(); 30865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko List<ScheduledRecording> toUpdate = new ArrayList<>(); 30965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko for (Program program : programsToSchedule) { 31065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ScheduledRecording scheduleWithSameProgram = 31165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mDataManager.getScheduledRecordingForProgramId(program.getId()); 31265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (scheduleWithSameProgram != null) { 3136ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (scheduleWithSameProgram.isNotStarted()) { 31465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ScheduledRecording r = ScheduledRecording.buildFrom(scheduleWithSameProgram) 31565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko .setSeriesRecordingId(series.getId()) 31665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko .build(); 31765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!r.equals(scheduleWithSameProgram)) { 31865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko toUpdate.add(r); 31965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 32065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 32165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } else { 322d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko toAdd.add(createScheduledRecordingBuilder(input.getId(), program) 32365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko .setPriority(series.getPriority()) 324d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko .setSeriesRecordingId(series.getId()) 325d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko .build()); 32665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 32765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 32865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!toAdd.isEmpty()) { 32965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mDataManager.addScheduledRecording(ScheduledRecording.toArray(toAdd)); 33065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 33165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!toUpdate.isEmpty()) { 33265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mDataManager.updateScheduledRecording(ScheduledRecording.toArray(toUpdate)); 33365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 33465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 33565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 33665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 33765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Updates the series recording. 33865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 33965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void updateSeriesRecording(SeriesRecording series) { 34065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 34165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko SeriesRecording previousSeries = mDataManager.getSeriesRecording(series.getId()); 34265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (previousSeries != null) { 3436ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko // If the channel option of series changed, remove the existing schedules. The new 3446ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko // schedules will be added by SeriesRecordingScheduler or by SeriesSettingsFragment. 345d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (previousSeries.getChannelOption() != series.getChannelOption() 346d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko || (previousSeries.getChannelOption() == SeriesRecording.OPTION_CHANNEL_ONE 347d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko && previousSeries.getChannelId() != series.getChannelId())) { 348d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko List<ScheduledRecording> schedules = 349d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mDataManager.getScheduledRecordings(series.getId()); 350d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko List<ScheduledRecording> schedulesToRemove = new ArrayList<>(); 351d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko for (ScheduledRecording schedule : schedules) { 352d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (schedule.isNotStarted()) { 353d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko schedulesToRemove.add(schedule); 3546ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } else if (schedule.isInProgress() 3556ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko && series.getChannelOption() == SeriesRecording.OPTION_CHANNEL_ONE 3566ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko && schedule.getChannelId() != series.getChannelId()) { 3576ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko stopRecording(schedule); 3586ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 3596ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 3606ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko List<ScheduledRecording> deletedSchedules = 3616ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko new ArrayList<>(mDataManager.getDeletedSchedules()); 3626ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko for (ScheduledRecording deletedSchedule : deletedSchedules) { 3636ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (deletedSchedule.getSeriesRecordingId() == series.getId() 3646ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko && deletedSchedule.getEndTimeMs() > System.currentTimeMillis()) { 3656ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko schedulesToRemove.add(deletedSchedule); 366d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 367d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 368d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mDataManager.removeScheduledRecording(true, 369d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko ScheduledRecording.toArray(schedulesToRemove)); 370d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 37165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 37265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mDataManager.updateSeriesRecording(series); 373d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (previousSeries == null 374d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko || previousSeries.getPriority() != series.getPriority()) { 37565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko long priority = series.getPriority(); 37665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko List<ScheduledRecording> schedulesToUpdate = new ArrayList<>(); 37765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko for (ScheduledRecording schedule 37865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko : mDataManager.getScheduledRecordings(series.getId())) { 3796ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (schedule.isNotStarted() || schedule.isInProgress()) { 38065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko schedulesToUpdate.add(ScheduledRecording.buildFrom(schedule) 38165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko .setPriority(priority).build()); 38265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 38365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 38465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!schedulesToUpdate.isEmpty()) { 38565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mDataManager.updateScheduledRecording( 38665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ScheduledRecording.toArray(schedulesToUpdate)); 38765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 38865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 38965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 39065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 39165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 39265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 39365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Removes the series recording and all the corresponding schedules which are not started yet. 39465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 39565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void removeSeriesRecording(long seriesRecordingId) { 39665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 39765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return; 39865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 39965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko SeriesRecording series = mDataManager.getSeriesRecording(seriesRecordingId); 40065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (series == null) { 40165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return; 40265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 40365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko for (ScheduledRecording schedule : mDataManager.getAllScheduledRecordings()) { 40465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (schedule.getSeriesRecordingId() == seriesRecordingId) { 40565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (schedule.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS) { 40665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko stopRecording(schedule); 40765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko break; 40865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 40965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 41065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 41165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mDataManager.removeSeriesRecording(series); 4121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 4131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 4141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko /** 4152e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko * Stops the currently recorded program 4162e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko */ 4172e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko public void stopRecording(final ScheduledRecording recording) { 41865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 41965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return; 42065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 4212e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko synchronized (mListener) { 4222e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko for (final Entry<Listener, Handler> entry : mListener.entrySet()) { 4232e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko entry.getValue().post(new Runnable() { 4242e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko @Override 4252e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko public void run() { 4262e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko entry.getKey().onStopRecordingRequested(recording); 4272e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 4282e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko }); 4292e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 4302e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 4312e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 4322e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 4332e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko /** 43465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Removes scheduled recordings or an existing recordings. 4351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 43665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void removeScheduledRecording(ScheduledRecording... schedules) { 43765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko Log.i(TAG, "Removing " + Arrays.asList(schedules)); 43865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 43965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return; 44065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 44165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko for (ScheduledRecording r : schedules) { 44265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (r.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS) { 44365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko stopRecording(r); 44465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } else { 44565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mDataManager.removeScheduledRecording(r); 44665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 44765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 44865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 44965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 45065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 451d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * Removes scheduled recordings without changing to the DELETED state. 452d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko */ 453d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public void forceRemoveScheduledRecording(ScheduledRecording... schedules) { 454d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko Log.i(TAG, "Force removing " + Arrays.asList(schedules)); 455d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 456d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return; 457d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 458d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko for (ScheduledRecording r : schedules) { 459d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (r.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS) { 460d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko stopRecording(r); 461d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } else { 462d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mDataManager.removeScheduledRecording(true, r); 463d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 464d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 465d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 466d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko 467d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko /** 46865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Removes the recorded program. It deletes the file if possible. 46965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 47065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void removeRecordedProgram(Uri recordedProgramUri) { 47165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isInitialized())) { 47265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return; 47365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 47465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko removeRecordedProgram(ContentUris.parseId(recordedProgramUri)); 47565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 47665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 47765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 47865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Removes the recorded program. It deletes the file if possible. 47965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 48065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void removeRecordedProgram(long recordedProgramId) { 48165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isInitialized())) { 48265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return; 48365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 48465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko RecordedProgram recordedProgram = mDataManager.getRecordedProgram(recordedProgramId); 48565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (recordedProgram != null) { 48665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko removeRecordedProgram(recordedProgram); 48765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 4882e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 4892e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 49065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 49165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Removes the recorded program. It deletes the file if possible. 49265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 4932e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko public void removeRecordedProgram(final RecordedProgram recordedProgram) { 49465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isInitialized())) { 49565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return; 49665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 4976ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko new AsyncDbTask<Void, Void, Integer>() { 4982e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko @Override 4996ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko protected Integer doInBackground(Void... params) { 5002e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko ContentResolver resolver = mAppContext.getContentResolver(); 5016ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return resolver.delete(recordedProgram.getUri(), null, null); 5026ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 5036ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 5046ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 5056ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko protected void onPostExecute(Integer deletedCounts) { 506d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (deletedCounts > 0) { 507d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko new AsyncTask<Void, Void, Void>() { 508d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko @Override 509d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko protected Void doInBackground(Void... params) { 510d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko removeRecordedData(recordedProgram.getDataUri()); 511d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return null; 51265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 513d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 51465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 5152e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 51665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko }.executeOnDbThread(); 5171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 5181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 519d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public void removeRecordedPrograms(List<Long> recordedProgramIds) { 520d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko final ArrayList<ContentProviderOperation> dbOperations = new ArrayList<>(); 521d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko final List<Uri> dataUris = new ArrayList<>(); 522d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko for (Long rId : recordedProgramIds) { 523d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko RecordedProgram r = mDataManager.getRecordedProgram(rId); 524d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (r != null) { 525d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko dataUris.add(r.getDataUri()); 526d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko dbOperations.add(ContentProviderOperation.newDelete(r.getUri()).build()); 527d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 52865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 5296ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko new AsyncDbTask<Void, Void, Boolean>() { 53065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @Override 5316ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko protected Boolean doInBackground(Void... params) { 53265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ContentResolver resolver = mAppContext.getContentResolver(); 533d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko try { 534d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko resolver.applyBatch(TvContract.AUTHORITY, dbOperations); 5356ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } catch (RemoteException | OperationApplicationException e) { 5366ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko Log.w(TAG, "Remove recorded programs from DB failed.", e); 5376ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return false; 5386ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 5396ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return true; 5406ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 5416ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 5426ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 5436ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko protected void onPostExecute(Boolean success) { 5446ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (success) { 545d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko new AsyncTask<Void, Void, Void>() { 546d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko @Override 547d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko protected Void doInBackground(Void... params) { 548d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko for (Uri dataUri : dataUris) { 549d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko removeRecordedData(dataUri); 550d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 551d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return null; 552d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 553d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 554d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 55565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 55665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko }.executeOnDbThread(); 55765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 55865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 55965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 56065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Updates the scheduled recording. 56165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 56265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void updateScheduledRecording(ScheduledRecording recording) { 56365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 56465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mDataManager.updateScheduledRecording(recording); 56565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 56665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 56765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 56865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 56965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns priority ordered list of all scheduled recordings that will not be recorded if 570ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * this program is. 571ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * 57265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @see DvrScheduleManager#getConflictingSchedules(Program) 57365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 57465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public List<ScheduledRecording> getConflictingSchedules(Program program) { 57565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 57665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return Collections.emptyList(); 57765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 57865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mScheduleManager.getConflictingSchedules(program); 57965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 58065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 58165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 58265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns priority ordered list of all scheduled recordings that will not be recorded if 58365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * this channel is. 58465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 58565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @see DvrScheduleManager#getConflictingSchedules(long, long, long) 58665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 58765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public List<ScheduledRecording> getConflictingSchedules(long channelId, long startTimeMs, 58865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko long endTimeMs) { 58965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 59065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return Collections.emptyList(); 59165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 59265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mScheduleManager.getConflictingSchedules(channelId, startTimeMs, endTimeMs); 59365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 59465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 59565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 59665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Checks if the schedule is conflicting. 59765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 59865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * <p>Note that the {@code schedule} should be the existing one. If not, this returns 59965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * {@code false}. 60065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 60165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public boolean isConflicting(ScheduledRecording schedule) { 602d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return schedule != null 603d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko && SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished()) 604d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko && mScheduleManager.isConflicting(schedule); 60565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 60665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 60765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 60865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns priority ordered list of all scheduled recording that will not be recorded if 60965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * this channel is tuned to. 61065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 61165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @see DvrScheduleManager#getConflictingSchedulesForTune 61265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 61365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public List<ScheduledRecording> getConflictingSchedulesForTune(long channelId) { 61465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 61565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return Collections.emptyList(); 61665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 61765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mScheduleManager.getConflictingSchedulesForTune(channelId); 61865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 61965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 62065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 621d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * Sets the highest priority to the schedule. 62265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 623d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public void setHighestPriority(ScheduledRecording schedule) { 624d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 625d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko long newPriority = mScheduleManager.suggestHighestPriority(schedule); 626d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (newPriority != schedule.getPriority()) { 627d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mDataManager.updateScheduledRecording(ScheduledRecording.buildFrom(schedule) 628d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko .setPriority(newPriority).build()); 629ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 630ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 631d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 632d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko 633d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko /** 634d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * Suggests the higher priority than the schedules which overlap with {@code schedule}. 635d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko */ 636d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public long suggestHighestPriority(ScheduledRecording schedule) { 637d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 638d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return mScheduleManager.suggestHighestPriority(schedule); 639d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 640d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return DvrScheduleManager.DEFAULT_PRIORITY; 641ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 642ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko 64365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 64465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns {@code true} if the channel can be recorded. 64565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * <p> 64665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Note that this method doesn't check the conflict of the schedule or available tuners. 64765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * This can be called from the UI before the schedules are loaded. 64865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 64965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public boolean isChannelRecordable(Channel channel) { 65065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!mDataManager.isDvrScheduleLoadFinished() || channel == null) { 65165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return false; 65265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 6536ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (channel.isRecordingProhibited()) { 6546ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return false; 6556ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 65665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko TvInputInfo info = Utils.getTvInputInfoForChannelId(mAppContext, channel.getId()); 65765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (info == null) { 65865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko Log.w(TAG, "Could not find TvInputInfo for " + channel); 65965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return false; 66065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 66165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!info.canRecord()) { 66265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return false; 66365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 66465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko Program program = TvApplication.getSingletons(mAppContext).getProgramDataManager() 66565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko .getCurrentProgram(channel.getId()); 66665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return program == null || !program.isRecordingProhibited(); 6671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 6681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 6691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko /** 67065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns {@code true} if the program can be recorded. 67165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * <p> 67265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Note that this method doesn't check the conflict of the schedule or available tuners. 67365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * This can be called from the UI before the schedules are loaded. 6741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 67565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public boolean isProgramRecordable(Program program) { 67665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!mDataManager.isInitialized()) { 67765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return false; 67865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 6796ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko Channel channel = TvApplication.getSingletons(mAppContext).getChannelDataManager() 6806ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko .getChannel(program.getChannelId()); 6816ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (channel == null || channel.isRecordingProhibited()) { 6826ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return false; 6836ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 6846ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko TvInputInfo info = Utils.getTvInputInfoForChannelId(mAppContext, channel.getId()); 68565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (info == null) { 68665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko Log.w(TAG, "Could not find TvInputInfo for " + program); 68765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return false; 68865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 68965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return info.canRecord() && !program.isRecordingProhibited(); 6901abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 691ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko 692ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko /** 69365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns the current recording for the channel. 69465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * <p> 69565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * This can be called from the UI before the schedules are loaded. 696ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko */ 69765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public ScheduledRecording getCurrentRecording(long channelId) { 69865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!mDataManager.isDvrScheduleLoadFinished()) { 69965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return null; 70065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 70165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko for (ScheduledRecording recording : mDataManager.getStartedRecordings()) { 70265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (recording.getChannelId() == channelId) { 70365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return recording; 70465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 70565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 70665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return null; 70765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 70865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 70965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 710d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * Returns schedules which is available (i.e., isNotStarted or isInProgress) and belongs to 711d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * the series recording {@code seriesRecordingId}. 712d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko */ 713d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public List<ScheduledRecording> getAvailableScheduledRecording(long seriesRecordingId) { 714d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (!mDataManager.isDvrScheduleLoadFinished()) { 715d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return Collections.emptyList(); 716d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 717d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko List<ScheduledRecording> schedules = new ArrayList<>(); 718d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko for (ScheduledRecording schedule : mDataManager.getScheduledRecordings(seriesRecordingId)) { 719d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (schedule.isInProgress() || schedule.isNotStarted()) { 720d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko schedules.add(schedule); 721d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 722d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 723d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return schedules; 724d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 725d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko 726d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko /** 72765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns the series recording related to the program. 72865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 72965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @Nullable 73065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public SeriesRecording getSeriesRecording(Program program) { 73165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) { 73265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return null; 73365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 73465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mDataManager.getSeriesRecording(program.getSeriesId()); 7352e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 7362e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 7376ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko /** 7386ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * Returns if there are valid items. Valid item contains {@link RecordedProgram}, 7396ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * available {@link ScheduledRecording} and {@link SeriesRecording}. 7406ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko */ 7416ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public boolean hasValidItems() { 7426ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return !(mDataManager.getRecordedPrograms().isEmpty() 7436ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko && mDataManager.getStartedRecordings().isEmpty() 7446ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko && mDataManager.getNonStartedScheduledRecordings().isEmpty() 7456ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko && mDataManager.getSeriesRecordings().isEmpty()); 7466ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 7476ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 7482e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko @WorkerThread 74965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @VisibleForTesting 75065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko // Should be public to use mock DvrManager object. 75165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void addListener(Listener listener, @NonNull Handler handler) { 7522e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko SoftPreconditions.checkNotNull(handler); 7532e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko synchronized (mListener) { 7542e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mListener.put(listener, handler); 7552e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 7562e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 7572e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 7582e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko @WorkerThread 75965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @VisibleForTesting 76065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko // Should be public to use mock DvrManager object. 76165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void removeListener(Listener listener) { 7622e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko synchronized (mListener) { 7632e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mListener.remove(listener); 7642e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 7652e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 7662e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 7672e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko /** 76865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns ScheduledRecording.builder based on {@code program}. If program is already started, 76965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * recording started time is clipped to the current time. 77065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 77165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private ScheduledRecording.Builder createScheduledRecordingBuilder(String inputId, 77265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko Program program) { 77365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ScheduledRecording.Builder builder = ScheduledRecording.builder(inputId, program); 77465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko long time = System.currentTimeMillis(); 77565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (program.getStartTimeUtcMillis() < time && time < program.getEndTimeUtcMillis()) { 77665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko builder.setStartTimeMs(time); 77765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 77865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return builder; 77965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 78065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 78165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 78265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns a schedule which matches to the given episode. 78365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 78465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public ScheduledRecording getScheduledRecording(String title, String seasonNumber, 78565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko String episodeNumber) { 78665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isInitialized()) || title == null 78765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko || seasonNumber == null || episodeNumber == null) { 78865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return null; 78965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 79065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko for (ScheduledRecording r : mDataManager.getAllScheduledRecordings()) { 79165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (title.equals(r.getProgramTitle()) 79265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko && seasonNumber.equals(r.getSeasonNumber()) 79365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko && episodeNumber.equals(r.getEpisodeNumber())) { 79465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return r; 79565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 79665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 79765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return null; 79865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 79965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 80065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 80165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns a recorded program which is the same episode as the given {@code program}. 80265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 80365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public RecordedProgram getRecordedProgram(String title, String seasonNumber, 80465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko String episodeNumber) { 80565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!SoftPreconditions.checkState(mDataManager.isInitialized()) || title == null 80665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko || seasonNumber == null || episodeNumber == null) { 80765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return null; 80865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 80965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko for (RecordedProgram r : mDataManager.getRecordedPrograms()) { 81065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (title.equals(r.getTitle()) 81165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko && seasonNumber.equals(r.getSeasonNumber()) 81265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko && episodeNumber.equals(r.getEpisodeNumber()) 81365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko && !r.isClipped()) { 81465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return r; 81565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 81665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 81765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return null; 81865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 81965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 820d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko @WorkerThread 821d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko private void removeRecordedData(Uri dataUri) { 822d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko try { 823d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (dataUri != null && ContentResolver.SCHEME_FILE.equals(dataUri.getScheme()) 824d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko && dataUri.getPath() != null) { 825d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko File recordedProgramPath = new File(dataUri.getPath()); 826d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (!recordedProgramPath.exists()) { 827d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (DEBUG) Log.d(TAG, "File to delete not exist: " + recordedProgramPath); 828d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } else { 829d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko Utils.deleteDirOrFile(recordedProgramPath); 830d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (DEBUG) { 831d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko Log.d(TAG, "Sucessfully deleted files of the recorded program: " + dataUri); 832d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 833d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 834d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 835d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } catch (SecurityException e) { 836d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (DEBUG) { 837d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko Log.d(TAG, "To delete this recorded program, please manually delete video data at" 838d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko + "\nadb shell rm -rf " + dataUri); 839d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 840d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 841d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 842d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko 843d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko /** 844d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * Remove all the records related to the input. 845d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * <p> 846d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * Note that this should be called after the input was removed. 847d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko */ 848d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public void forgetStorage(String inputId) { 849d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (mDataManager.isInitialized()) { 850d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko mDataManager.forgetStorage(inputId); 851d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 852d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 853d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko 85465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 8556ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * Listener to stop recording request. Should only be internally used inside dvr and its 8566ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * sub-package. 8572e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko */ 8586ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public interface Listener { 8592e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko void onStopRecordingRequested(ScheduledRecording scheduledRecording); 860ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 8611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko} 862