1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.tv.dvr;
18 
19 import android.annotation.TargetApi;
20 import android.content.Context;
21 import android.os.Build;
22 import android.support.annotation.MainThread;
23 import android.util.ArraySet;
24 import android.util.Log;
25 
26 import com.android.tv.common.SoftPreconditions;
27 import com.android.tv.common.feature.CommonFeatures;
28 import com.android.tv.common.recording.RecordedProgram;
29 import com.android.tv.util.Clock;
30 
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.Set;
34 
35 /**
36  * Base implementation of @{link DataManagerInternal}.
37  */
38 @MainThread
39 @TargetApi(Build.VERSION_CODES.N)
40 public abstract class BaseDvrDataManager implements WritableDvrDataManager {
41     private final static String TAG = "BaseDvrDataManager";
42     private final static boolean DEBUG = false;
43     protected final Clock mClock;
44 
45     private final Set<ScheduledRecordingListener> mScheduledRecordingListeners = new ArraySet<>();
46     private final Set<RecordedProgramListener> mRecordedProgramListeners = new ArraySet<>();
47 
BaseDvrDataManager(Context context, Clock clock)48     BaseDvrDataManager(Context context, Clock clock) {
49         SoftPreconditions.checkFeatureEnabled(context, CommonFeatures.DVR, TAG);
50         mClock = clock;
51     }
52 
53     @Override
addScheduledRecordingListener(ScheduledRecordingListener listener)54     public final void addScheduledRecordingListener(ScheduledRecordingListener listener) {
55         mScheduledRecordingListeners.add(listener);
56     }
57 
58     @Override
removeScheduledRecordingListener(ScheduledRecordingListener listener)59     public final void removeScheduledRecordingListener(ScheduledRecordingListener listener) {
60         mScheduledRecordingListeners.remove(listener);
61     }
62 
63     @Override
addRecordedProgramListener(RecordedProgramListener listener)64     public final void addRecordedProgramListener(RecordedProgramListener listener) {
65         mRecordedProgramListeners.add(listener);
66     }
67 
68     @Override
removeRecordedProgramListener(RecordedProgramListener listener)69     public final void removeRecordedProgramListener(RecordedProgramListener listener) {
70         mRecordedProgramListeners.remove(listener);
71     }
72 
73     /**
74      * Calls {@link RecordedProgramListener#onRecordedProgramAdded(RecordedProgram)}
75      * for each listener.
76      */
notifyRecordedProgramAdded(RecordedProgram recordedProgram)77     protected final void notifyRecordedProgramAdded(RecordedProgram recordedProgram) {
78         for (RecordedProgramListener l : mRecordedProgramListeners) {
79             if (DEBUG) Log.d(TAG, "notify " + l + "added " + recordedProgram);
80             l.onRecordedProgramAdded(recordedProgram);
81         }
82     }
83 
84     /**
85      * Calls {@link RecordedProgramListener#onRecordedProgramChanged(RecordedProgram)}
86      * for each listener.
87      */
notifyRecordedProgramChanged(RecordedProgram recordedProgram)88     protected final void notifyRecordedProgramChanged(RecordedProgram recordedProgram) {
89         for (RecordedProgramListener l : mRecordedProgramListeners) {
90             if (DEBUG) Log.d(TAG, "notify " + l + "changed " + recordedProgram);
91             l.onRecordedProgramChanged(recordedProgram);
92         }
93     }
94 
95     /**
96      * Calls {@link RecordedProgramListener#onRecordedProgramRemoved(RecordedProgram)}
97      * for each  listener.
98      */
notifyRecordedProgramRemoved(RecordedProgram recordedProgram)99     protected final void notifyRecordedProgramRemoved(RecordedProgram recordedProgram) {
100         for (RecordedProgramListener l : mRecordedProgramListeners) {
101             if (DEBUG) Log.d(TAG, "notify " + l + "removed " + recordedProgram);
102             l.onRecordedProgramRemoved(recordedProgram);
103         }
104     }
105 
106     /**
107      * Calls {@link ScheduledRecordingListener#onScheduledRecordingAdded(ScheduledRecording)}
108      * for each listener.
109      */
notifyScheduledRecordingAdded(ScheduledRecording scheduledRecording)110     protected final void notifyScheduledRecordingAdded(ScheduledRecording scheduledRecording) {
111         for (ScheduledRecordingListener l : mScheduledRecordingListeners) {
112             if (DEBUG) Log.d(TAG, "notify " + l + "added  " + scheduledRecording);
113             l.onScheduledRecordingAdded(scheduledRecording);
114         }
115     }
116 
117     /**
118      * Calls {@link ScheduledRecordingListener#onScheduledRecordingRemoved(ScheduledRecording)}
119      * for each listener.
120      */
notifyScheduledRecordingRemoved(ScheduledRecording scheduledRecording)121     protected final void notifyScheduledRecordingRemoved(ScheduledRecording scheduledRecording) {
122         for (ScheduledRecordingListener l : mScheduledRecordingListeners) {
123             if (DEBUG) {
124                 Log.d(TAG, "notify " + l + "removed " + scheduledRecording);
125             }
126             l.onScheduledRecordingRemoved(scheduledRecording);
127         }
128     }
129 
130     /**
131      * Calls
132      * {@link ScheduledRecordingListener#onScheduledRecordingStatusChanged(ScheduledRecording)}
133      * for each listener.
134      */
notifyScheduledRecordingStatusChanged( ScheduledRecording scheduledRecording)135     protected final void notifyScheduledRecordingStatusChanged(
136             ScheduledRecording scheduledRecording) {
137         for (ScheduledRecordingListener l : mScheduledRecordingListeners) {
138             if (DEBUG) Log.d(TAG, "notify " + l + "changed " + scheduledRecording);
139             l.onScheduledRecordingStatusChanged(scheduledRecording);
140         }
141     }
142 
143     /**
144      * Returns a new list with only {@link ScheduledRecording} with a {@link
145      * ScheduledRecording#getEndTimeMs() endTime} after now.
146      */
filterEndTimeIsPast(List<ScheduledRecording> originals)147     private List<ScheduledRecording> filterEndTimeIsPast(List<ScheduledRecording> originals) {
148         List<ScheduledRecording> results = new ArrayList<>(originals.size());
149         for (ScheduledRecording r : originals) {
150             if (r.getEndTimeMs() > mClock.currentTimeMillis()) {
151                 results.add(r);
152             }
153         }
154         return results;
155     }
156 
157     @Override
getStartedRecordings()158     public List<ScheduledRecording> getStartedRecordings() {
159         return filterEndTimeIsPast(
160                 getRecordingsWithState(ScheduledRecording.STATE_RECORDING_IN_PROGRESS));
161     }
162 
163     @Override
getNonStartedScheduledRecordings()164     public List<ScheduledRecording> getNonStartedScheduledRecordings() {
165         return filterEndTimeIsPast(
166                 getRecordingsWithState(ScheduledRecording.STATE_RECORDING_NOT_STARTED));
167     }
168 
getRecordingsWithState(int state)169     protected abstract List<ScheduledRecording> getRecordingsWithState(int state);
170 }
171