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 192e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport android.annotation.TargetApi; 201abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.content.Context; 212e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport android.os.Build; 22ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.support.annotation.MainThread; 2365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.annotation.NonNull; 242e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport android.util.ArraySet; 251abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.util.Log; 261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 272e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport com.android.tv.common.SoftPreconditions; 28ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport com.android.tv.common.feature.CommonFeatures; 296ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.RecordedProgram; 306ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.ScheduledRecording; 316ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.ScheduledRecording.RecordingState; 326ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.SeriesRecording; 332e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport com.android.tv.util.Clock; 341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 352e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport java.util.ArrayList; 36d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport java.util.Arrays; 3765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.Collection; 38d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport java.util.Collections; 3965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.HashMap; 402e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport java.util.List; 4165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.Map; 421abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.util.Set; 4365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.concurrent.CopyOnWriteArraySet; 441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko/** 461abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Base implementation of @{link DataManagerInternal}. 471abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 48ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko@MainThread 492e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko@TargetApi(Build.VERSION_CODES.N) 501abddd9f6225298066094e20a6c29061b6af4590Nick Chalkopublic abstract class BaseDvrDataManager implements WritableDvrDataManager { 511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private final static String TAG = "BaseDvrDataManager"; 521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private final static boolean DEBUG = false; 532e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko protected final Clock mClock; 541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 5565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private final Set<OnDvrScheduleLoadFinishedListener> mOnDvrScheduleLoadFinishedListeners = 5665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko new CopyOnWriteArraySet<>(); 5765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private final Set<OnRecordedProgramLoadFinishedListener> 5865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mOnRecordedProgramLoadFinishedListeners = new CopyOnWriteArraySet<>(); 592e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko private final Set<ScheduledRecordingListener> mScheduledRecordingListeners = new ArraySet<>(); 6065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private final Set<SeriesRecordingListener> mSeriesRecordingListeners = new ArraySet<>(); 612e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko private final Set<RecordedProgramListener> mRecordedProgramListeners = new ArraySet<>(); 6265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private final HashMap<Long, ScheduledRecording> mDeletedScheduleMap = new HashMap<>(); 631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 642e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko BaseDvrDataManager(Context context, Clock clock) { 65ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko SoftPreconditions.checkFeatureEnabled(context, CommonFeatures.DVR, TAG); 662e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mClock = clock; 671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 7065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void addDvrScheduleLoadFinishedListener(OnDvrScheduleLoadFinishedListener listener) { 7165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mOnDvrScheduleLoadFinishedListeners.add(listener); 7265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 7365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 7465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @Override 7565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void removeDvrScheduleLoadFinishedListener(OnDvrScheduleLoadFinishedListener listener) { 7665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mOnDvrScheduleLoadFinishedListeners.remove(listener); 7765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 7865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 7965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @Override 8065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void addRecordedProgramLoadFinishedListener( 8165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko OnRecordedProgramLoadFinishedListener listener) { 8265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mOnRecordedProgramLoadFinishedListeners.add(listener); 8365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 8465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 8565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @Override 8665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void removeRecordedProgramLoadFinishedListener( 8765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko OnRecordedProgramLoadFinishedListener listener) { 8865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mOnRecordedProgramLoadFinishedListeners.remove(listener); 8965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 9065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 9165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @Override 922e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko public final void addScheduledRecordingListener(ScheduledRecordingListener listener) { 932e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mScheduledRecordingListeners.add(listener); 941abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 972e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko public final void removeScheduledRecordingListener(ScheduledRecordingListener listener) { 982e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mScheduledRecordingListeners.remove(listener); 992e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 1002e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 1012e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko @Override 10265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public final void addSeriesRecordingListener(SeriesRecordingListener listener) { 10365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mSeriesRecordingListeners.add(listener); 10465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 10565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 10665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @Override 10765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public final void removeSeriesRecordingListener(SeriesRecordingListener listener) { 10865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mSeriesRecordingListeners.remove(listener); 10965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 11065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 11165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @Override 1122e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko public final void addRecordedProgramListener(RecordedProgramListener listener) { 1132e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mRecordedProgramListeners.add(listener); 1142e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 1152e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 1162e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko @Override 1172e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko public final void removeRecordedProgramListener(RecordedProgramListener listener) { 1182e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mRecordedProgramListeners.remove(listener); 1191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 1211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko /** 12265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Calls {@link OnDvrScheduleLoadFinishedListener#onDvrScheduleLoadFinished} for each listener. 12365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 12465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko protected final void notifyDvrScheduleLoadFinished() { 12565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko for (OnDvrScheduleLoadFinishedListener l : mOnDvrScheduleLoadFinishedListeners) { 12665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (DEBUG) Log.d(TAG, "notify DVR schedule load finished"); 12765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko l.onDvrScheduleLoadFinished(); 12865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 12965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 13065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 13165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 13265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Calls {@link OnRecordedProgramLoadFinishedListener#onRecordedProgramLoadFinished()} 13365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * for each listener. 13465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 13565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko protected final void notifyRecordedProgramLoadFinished() { 13665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko for (OnRecordedProgramLoadFinishedListener l : mOnRecordedProgramLoadFinishedListeners) { 13765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (DEBUG) Log.d(TAG, "notify recorded programs load finished"); 13865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko l.onRecordedProgramLoadFinished(); 13965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 14065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 14165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 14265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 143d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * Calls {@link RecordedProgramListener#onRecordedProgramsAdded} 1442e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko * for each listener. 1451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 146d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko protected final void notifyRecordedProgramsAdded(RecordedProgram... recordedPrograms) { 1472e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko for (RecordedProgramListener l : mRecordedProgramListeners) { 148d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (DEBUG) Log.d(TAG, "notify " + l + " added " + Arrays.asList(recordedPrograms)); 149d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko l.onRecordedProgramsAdded(recordedPrograms); 1501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 1531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko /** 154d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * Calls {@link RecordedProgramListener#onRecordedProgramsChanged} 1552e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko * for each listener. 1561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 157d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko protected final void notifyRecordedProgramsChanged(RecordedProgram... recordedPrograms) { 1582e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko for (RecordedProgramListener l : mRecordedProgramListeners) { 159d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (DEBUG) Log.d(TAG, "notify " + l + " changed " + Arrays.asList(recordedPrograms)); 160d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko l.onRecordedProgramsChanged(recordedPrograms); 1611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 1641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko /** 165d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko * Calls {@link RecordedProgramListener#onRecordedProgramsRemoved} 1662e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko * for each listener. 1671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 168d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko protected final void notifyRecordedProgramsRemoved(RecordedProgram... recordedPrograms) { 1692e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko for (RecordedProgramListener l : mRecordedProgramListeners) { 170d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (DEBUG) Log.d(TAG, "notify " + l + " removed " + Arrays.asList(recordedPrograms)); 171d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko l.onRecordedProgramsRemoved(recordedPrograms); 1721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1742e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 1752e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko /** 17665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Calls {@link SeriesRecordingListener#onSeriesRecordingAdded} 17765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * for each listener. 17865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 17965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko protected final void notifySeriesRecordingAdded(SeriesRecording... seriesRecordings) { 18065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko for (SeriesRecordingListener l : mSeriesRecordingListeners) { 181d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (DEBUG) Log.d(TAG, "notify " + l + " added " + Arrays.asList(seriesRecordings)); 18265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko l.onSeriesRecordingAdded(seriesRecordings); 18365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 18465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 18565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 18665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 18765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Calls {@link SeriesRecordingListener#onSeriesRecordingRemoved} 18865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * for each listener. 18965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 19065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko protected final void notifySeriesRecordingRemoved(SeriesRecording... seriesRecordings) { 19165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko for (SeriesRecordingListener l : mSeriesRecordingListeners) { 192d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (DEBUG) Log.d(TAG, "notify " + l + " removed " + Arrays.asList(seriesRecordings)); 19365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko l.onSeriesRecordingRemoved(seriesRecordings); 19465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 19565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 19665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 19765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 19865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Calls 19965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * {@link SeriesRecordingListener#onSeriesRecordingChanged} 20065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * for each listener. 20165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 20265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko protected final void notifySeriesRecordingChanged(SeriesRecording... seriesRecordings) { 20365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko for (SeriesRecordingListener l : mSeriesRecordingListeners) { 204d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (DEBUG) Log.d(TAG, "notify " + l + " changed " + Arrays.asList(seriesRecordings)); 20565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko l.onSeriesRecordingChanged(seriesRecordings); 20665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 20765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 20865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 20965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 21065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Calls {@link ScheduledRecordingListener#onScheduledRecordingAdded} 2112e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko * for each listener. 2122e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko */ 21365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko protected final void notifyScheduledRecordingAdded(ScheduledRecording... scheduledRecording) { 2142e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko for (ScheduledRecordingListener l : mScheduledRecordingListeners) { 215d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (DEBUG) Log.d(TAG, "notify " + l + " added " + Arrays.asList(scheduledRecording)); 2162e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko l.onScheduledRecordingAdded(scheduledRecording); 2172e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 2182e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 2192e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 2202e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko /** 22165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Calls {@link ScheduledRecordingListener#onScheduledRecordingRemoved} 2222e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko * for each listener. 2232e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko */ 22465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko protected final void notifyScheduledRecordingRemoved(ScheduledRecording... scheduledRecording) { 2252e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko for (ScheduledRecordingListener l : mScheduledRecordingListeners) { 226d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (DEBUG) Log.d(TAG, "notify " + l + " removed " + Arrays.asList(scheduledRecording)); 2272e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko l.onScheduledRecordingRemoved(scheduledRecording); 2282e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 2292e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 2302e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 2312e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko /** 2322e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko * Calls 23365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * {@link ScheduledRecordingListener#onScheduledRecordingStatusChanged} 2342e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko * for each listener. 2352e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko */ 2362e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko protected final void notifyScheduledRecordingStatusChanged( 23765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ScheduledRecording... scheduledRecording) { 2382e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko for (ScheduledRecordingListener l : mScheduledRecordingListeners) { 239d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (DEBUG) Log.d(TAG, "notify " + l + " changed " + Arrays.asList(scheduledRecording)); 2402e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko l.onScheduledRecordingStatusChanged(scheduledRecording); 2412e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 2422e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 2432e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 2442e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko /** 2452e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko * Returns a new list with only {@link ScheduledRecording} with a {@link 2462e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko * ScheduledRecording#getEndTimeMs() endTime} after now. 2472e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko */ 2482e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko private List<ScheduledRecording> filterEndTimeIsPast(List<ScheduledRecording> originals) { 2492e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko List<ScheduledRecording> results = new ArrayList<>(originals.size()); 2502e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko for (ScheduledRecording r : originals) { 2512e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko if (r.getEndTimeMs() > mClock.currentTimeMillis()) { 2522e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko results.add(r); 2532e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 2542e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 2552e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko return results; 2562e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 2572e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 2582e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko @Override 25965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public List<ScheduledRecording> getAvailableScheduledRecordings() { 26065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return filterEndTimeIsPast(getRecordingsWithState( 26165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ScheduledRecording.STATE_RECORDING_IN_PROGRESS, 26265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ScheduledRecording.STATE_RECORDING_NOT_STARTED)); 26365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 26465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 26565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @Override 2662e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko public List<ScheduledRecording> getStartedRecordings() { 26765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return filterEndTimeIsPast(getRecordingsWithState( 26865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ScheduledRecording.STATE_RECORDING_IN_PROGRESS)); 2692e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 2702e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 2712e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko @Override 2722e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko public List<ScheduledRecording> getNonStartedScheduledRecordings() { 27365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return filterEndTimeIsPast(getRecordingsWithState( 27465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ScheduledRecording.STATE_RECORDING_NOT_STARTED)); 27565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 27665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 27765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @Override 27865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void changeState(ScheduledRecording scheduledRecording, @RecordingState int newState) { 27965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (scheduledRecording.getState() != newState) { 28065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko updateScheduledRecording(ScheduledRecording.buildFrom(scheduledRecording) 28165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko .setState(newState).build()); 28265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 28365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 28465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 28565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @Override 28665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public Collection<ScheduledRecording> getDeletedSchedules() { 28765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mDeletedScheduleMap.values(); 2882e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 2892e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 29065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @NonNull 29165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @Override 29265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public Collection<Long> getDisallowedProgramIds() { 29365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mDeletedScheduleMap.keySet(); 29465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 29565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 29665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 29765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns the map which contains the deleted schedules which are mapped from the program ID. 29865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 29965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko protected Map<Long, ScheduledRecording> getDeletedScheduleMap() { 30065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mDeletedScheduleMap; 30165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 30265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 30365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 30465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns the schedules whose state is contained by states. 30565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 30665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko protected abstract List<ScheduledRecording> getRecordingsWithState(int... states); 30765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 30865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @Override 30965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public List<RecordedProgram> getRecordedPrograms(long seriesRecordingId) { 31065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko SeriesRecording seriesRecording = getSeriesRecording(seriesRecordingId); 311d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko if (seriesRecording == null) { 312d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko return Collections.emptyList(); 313d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko } 31465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko List<RecordedProgram> result = new ArrayList<>(); 31565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko for (RecordedProgram r : getRecordedPrograms()) { 31665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (seriesRecording.getSeriesId().equals(r.getSeriesId())) { 31765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko result.add(r); 31865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 31965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 32065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return result; 32165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 322d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko 323d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko @Override 3246ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void checkAndRemoveEmptySeriesRecording(long... seriesRecordingIds) { 3256ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko List<SeriesRecording> toRemove = new ArrayList<>(); 3266ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko for (long rId : seriesRecordingIds) { 3276ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko SeriesRecording seriesRecording = getSeriesRecording(rId); 3286ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (seriesRecording != null && isEmptySeriesRecording(seriesRecording)) { 3296ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko toRemove.add(seriesRecording); 3306ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 3316ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 3326ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko removeSeriesRecording(SeriesRecording.toArray(toRemove)); 3336ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 3346ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 3356ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko /** 3366ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * Returns {@code true}, if the series recording is empty and can be removed. If a series 3376ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * recording is in NORMAL state or has recordings or schedules, it is not empty and cannot be 3386ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * removed. 3396ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko */ 3406ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko protected final boolean isEmptySeriesRecording(@NonNull SeriesRecording seriesRecording) { 3416ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (!seriesRecording.isStopped()) { 3426ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return false; 3436ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 3446ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko long seriesRecordingId = seriesRecording.getId(); 3456ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko for (ScheduledRecording r : getAvailableScheduledRecordings()) { 3466ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (r.getSeriesRecordingId() == seriesRecordingId) { 3476ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return false; 3486ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 3496ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 3506ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko String seriesId = seriesRecording.getSeriesId(); 3516ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko for (RecordedProgram r : getRecordedPrograms()) { 3526ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (seriesId.equals(r.getSeriesId())) { 3536ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return false; 3546ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 3556ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 3566ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return true; 3576ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 3586ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 3596ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 360d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko public void forgetStorage(String inputId) { } 3611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko} 362