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.content.Context; 20 import android.support.annotation.MainThread; 21 import android.support.annotation.NonNull; 22 import android.support.annotation.Nullable; 23 import android.support.annotation.VisibleForTesting; 24 import android.util.Range; 25 26 import com.android.tv.common.SoftPreconditions; 27 import com.android.tv.common.recording.RecordedProgram; 28 import com.android.tv.util.Clock; 29 30 import java.util.ArrayList; 31 import java.util.Collections; 32 import java.util.HashMap; 33 import java.util.List; 34 import java.util.Map; 35 import java.util.concurrent.atomic.AtomicLong; 36 37 /** 38 * A DVR Data manager that stores values in memory suitable for testing. 39 */ 40 @VisibleForTesting // TODO(DVR): move to testing dir. 41 @MainThread 42 public final class DvrDataManagerInMemoryImpl extends BaseDvrDataManager { 43 private final static String TAG = "DvrDataManagerInMemory"; 44 private final AtomicLong mNextId = new AtomicLong(1); 45 private final Map<Long, ScheduledRecording> mScheduledRecordings = new HashMap<>(); 46 private final Map<Long, RecordedProgram> mRecordedPrograms = new HashMap<>(); 47 private final List<SeasonRecording> mSeasonSchedule = new ArrayList<>(); 48 DvrDataManagerInMemoryImpl(Context context, Clock clock)49 public DvrDataManagerInMemoryImpl(Context context, Clock clock) { 50 super(context, clock); 51 } 52 53 @Override isInitialized()54 public boolean isInitialized() { 55 return true; 56 } 57 getScheduledRecordingsPrograms()58 private List<ScheduledRecording> getScheduledRecordingsPrograms() { 59 return new ArrayList(mScheduledRecordings.values()); 60 } 61 62 @Override getRecordedPrograms()63 public List<RecordedProgram> getRecordedPrograms() { 64 return new ArrayList<>(mRecordedPrograms.values()); 65 } 66 67 @Override getAllScheduledRecordings()68 public List<ScheduledRecording> getAllScheduledRecordings() { 69 return new ArrayList<>(mScheduledRecordings.values()); 70 } 71 getSeasonRecordings()72 public List<SeasonRecording> getSeasonRecordings() { 73 return mSeasonSchedule; 74 } 75 76 @Override getNextScheduledStartTimeAfter(long startTime)77 public long getNextScheduledStartTimeAfter(long startTime) { 78 79 List<ScheduledRecording> temp = getNonStartedScheduledRecordings(); 80 Collections.sort(temp, ScheduledRecording.START_TIME_COMPARATOR); 81 for (ScheduledRecording r : temp) { 82 if (r.getStartTimeMs() > startTime) { 83 return r.getStartTimeMs(); 84 } 85 } 86 return DvrDataManager.NEXT_START_TIME_NOT_FOUND; 87 } 88 89 @Override getRecordingsThatOverlapWith(Range<Long> period)90 public List<ScheduledRecording> getRecordingsThatOverlapWith(Range<Long> period) { 91 List<ScheduledRecording> temp = getScheduledRecordingsPrograms(); 92 List<ScheduledRecording> result = new ArrayList<>(); 93 for (ScheduledRecording r : temp) { 94 if (r.isOverLapping(period)) { 95 result.add(r); 96 } 97 } 98 return result; 99 } 100 101 /** 102 * Add a new scheduled recording. 103 */ 104 @Override addScheduledRecording(ScheduledRecording scheduledRecording)105 public void addScheduledRecording(ScheduledRecording scheduledRecording) { 106 addScheduledRecordingInternal(scheduledRecording); 107 } 108 109 addRecordedProgram(RecordedProgram recordedProgram)110 public void addRecordedProgram(RecordedProgram recordedProgram) { 111 addRecordedProgramInternal(recordedProgram); 112 } 113 updateRecordedProgram(RecordedProgram r)114 public void updateRecordedProgram(RecordedProgram r) { 115 long id = r.getId(); 116 if (mRecordedPrograms.containsKey(id)) { 117 mRecordedPrograms.put(id, r); 118 notifyRecordedProgramChanged(r); 119 } else { 120 throw new IllegalArgumentException("Recording not found:" + r); 121 } 122 } 123 removeRecordedProgram(RecordedProgram scheduledRecording)124 public void removeRecordedProgram(RecordedProgram scheduledRecording) { 125 mRecordedPrograms.remove(scheduledRecording.getId()); 126 notifyRecordedProgramRemoved(scheduledRecording); 127 } 128 129 addScheduledRecordingInternal(ScheduledRecording scheduledRecording)130 public ScheduledRecording addScheduledRecordingInternal(ScheduledRecording scheduledRecording) { 131 SoftPreconditions 132 .checkState(scheduledRecording.getId() == ScheduledRecording.ID_NOT_SET, TAG, 133 "expected id of " + ScheduledRecording.ID_NOT_SET + " but was " 134 + scheduledRecording); 135 scheduledRecording = ScheduledRecording.buildFrom(scheduledRecording) 136 .setId(mNextId.incrementAndGet()) 137 .build(); 138 mScheduledRecordings.put(scheduledRecording.getId(), scheduledRecording); 139 notifyScheduledRecordingAdded(scheduledRecording); 140 return scheduledRecording; 141 } 142 addRecordedProgramInternal(RecordedProgram recordedProgram)143 public RecordedProgram addRecordedProgramInternal(RecordedProgram recordedProgram) { 144 SoftPreconditions.checkState(recordedProgram.getId() == RecordedProgram.ID_NOT_SET, TAG, 145 "expected id of " + RecordedProgram.ID_NOT_SET + " but was " + recordedProgram); 146 recordedProgram = RecordedProgram.buildFrom(recordedProgram) 147 .setId(mNextId.incrementAndGet()) 148 .build(); 149 mRecordedPrograms.put(recordedProgram.getId(), recordedProgram); 150 notifyRecordedProgramAdded(recordedProgram); 151 return recordedProgram; 152 } 153 154 @Override addSeasonRecording(SeasonRecording seasonRecording)155 public void addSeasonRecording(SeasonRecording seasonRecording) { 156 mSeasonSchedule.add(seasonRecording); 157 } 158 159 @Override removeScheduledRecording(ScheduledRecording scheduledRecording)160 public void removeScheduledRecording(ScheduledRecording scheduledRecording) { 161 mScheduledRecordings.remove(scheduledRecording.getId()); 162 notifyScheduledRecordingRemoved(scheduledRecording); 163 } 164 165 @Override removeSeasonSchedule(SeasonRecording seasonSchedule)166 public void removeSeasonSchedule(SeasonRecording seasonSchedule) { 167 mSeasonSchedule.remove(seasonSchedule); 168 } 169 170 @Override updateScheduledRecording(ScheduledRecording r)171 public void updateScheduledRecording(ScheduledRecording r) { 172 long id = r.getId(); 173 if (mScheduledRecordings.containsKey(id)) { 174 mScheduledRecordings.put(id, r); 175 notifyScheduledRecordingStatusChanged(r); 176 } else { 177 throw new IllegalArgumentException("Recording not found:" + r); 178 } 179 } 180 181 @Nullable 182 @Override getScheduledRecording(long id)183 public ScheduledRecording getScheduledRecording(long id) { 184 return mScheduledRecordings.get(id); 185 } 186 187 @Nullable 188 @Override getScheduledRecordingForProgramId(long programId)189 public ScheduledRecording getScheduledRecordingForProgramId(long programId) { 190 for (ScheduledRecording r : mScheduledRecordings.values()) { 191 if (r.getProgramId() == programId) { 192 return r; 193 } 194 } 195 return null; 196 } 197 198 @Nullable 199 @Override getRecordedProgram(long recordingId)200 public RecordedProgram getRecordedProgram(long recordingId) { 201 return mRecordedPrograms.get(recordingId); 202 } 203 204 @Override 205 @NonNull getRecordingsWithState(int state)206 protected List<ScheduledRecording> getRecordingsWithState(int state) { 207 ArrayList<ScheduledRecording> result = new ArrayList<>(); 208 for (ScheduledRecording r : mScheduledRecordings.values()) { 209 if(r.getState() == state){ 210 result.add(r); 211 } 212 } 213 return result; 214 } 215 } 216