DvrWatchedPositionManager.java revision 633eb826b8c97731dfc5ef12c7bf78a63734275d
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package com.android.tv.dvr; 18 19import android.content.Context; 20import android.content.SharedPreferences; 21import android.media.tv.TvInputManager; 22import android.support.annotation.IntDef; 23 24import com.android.tv.common.SharedPreferencesUtils; 25import com.android.tv.dvr.data.RecordedProgram; 26 27import java.lang.annotation.Retention; 28import java.lang.annotation.RetentionPolicy; 29import java.util.ArrayList; 30import java.util.HashMap; 31import java.util.Map; 32import java.util.Set; 33import java.util.concurrent.CopyOnWriteArraySet; 34 35/** 36 * A class to manage DVR watched state. 37 * It will remember and provides previous watched position of DVR playback. 38 */ 39public class DvrWatchedPositionManager { 40 private SharedPreferences mWatchedPositions; 41 private final Map<Long, Set> mListeners = new HashMap<>(); 42 43 /** 44 * The minimum percentage of recorded program being watched that will be considered as being 45 * completely watched. 46 */ 47 public static final float DVR_WATCHED_THRESHOLD_RATE = 0.98f; 48 49 @Retention(RetentionPolicy.SOURCE) 50 @IntDef({DVR_WATCHED_STATUS_NEW, DVR_WATCHED_STATUS_WATCHING, DVR_WATCHED_STATUS_WATCHED}) 51 public @interface DvrWatchedStatus {} 52 /** 53 * The status indicates the recorded program has not been watched at all. 54 */ 55 public static final int DVR_WATCHED_STATUS_NEW = 0; 56 /** 57 * The status indicates the recorded program is being watched. 58 */ 59 public static final int DVR_WATCHED_STATUS_WATCHING = 1; 60 /** 61 * The status indicates the recorded program was completely watched. 62 */ 63 public static final int DVR_WATCHED_STATUS_WATCHED = 2; 64 65 public DvrWatchedPositionManager(Context context) { 66 mWatchedPositions = context.getSharedPreferences( 67 SharedPreferencesUtils.SHARED_PREF_DVR_WATCHED_POSITION, Context.MODE_PRIVATE); 68 } 69 70 /** 71 * Sets the watched position of the give program. 72 */ 73 public void setWatchedPosition(long recordedProgramId, long positionMs) { 74 mWatchedPositions.edit().putLong(Long.toString(recordedProgramId), positionMs).apply(); 75 notifyWatchedPositionChanged(recordedProgramId, positionMs); 76 } 77 78 /** 79 * Gets the watched position of the give program. 80 */ 81 public long getWatchedPosition(long recordedProgramId) { 82 return mWatchedPositions.getLong(Long.toString(recordedProgramId), 83 TvInputManager.TIME_SHIFT_INVALID_TIME); 84 } 85 86 @DvrWatchedStatus public int getWatchedStatus(RecordedProgram recordedProgram) { 87 long watchedPosition = getWatchedPosition(recordedProgram.getId()); 88 if (watchedPosition == TvInputManager.TIME_SHIFT_INVALID_TIME) { 89 return DVR_WATCHED_STATUS_NEW; 90 } else if (watchedPosition > recordedProgram 91 .getDurationMillis() * DVR_WATCHED_THRESHOLD_RATE) { 92 return DVR_WATCHED_STATUS_WATCHED; 93 } else { 94 return DVR_WATCHED_STATUS_WATCHING; 95 } 96 } 97 98 /** 99 * Adds {@link WatchedPositionChangedListener}. 100 */ 101 public void addListener(WatchedPositionChangedListener listener, long recordedProgramId) { 102 if (recordedProgramId == RecordedProgram.ID_NOT_SET) { 103 return; 104 } 105 Set<WatchedPositionChangedListener> listenerSet = mListeners.get(recordedProgramId); 106 if (listenerSet == null) { 107 listenerSet = new CopyOnWriteArraySet<>(); 108 mListeners.put(recordedProgramId, listenerSet); 109 } 110 listenerSet.add(listener); 111 } 112 113 /** 114 * Removes {@link WatchedPositionChangedListener}. 115 */ 116 public void removeListener(WatchedPositionChangedListener listener) { 117 for (long recordedProgramId : new ArrayList<>(mListeners.keySet())) { 118 removeListener(listener, recordedProgramId); 119 } 120 } 121 122 /** 123 * Removes {@link WatchedPositionChangedListener}. 124 */ 125 public void removeListener(WatchedPositionChangedListener listener, long recordedProgramId) { 126 Set<WatchedPositionChangedListener> listenerSet = mListeners.get(recordedProgramId); 127 if (listenerSet == null) { 128 return; 129 } 130 listenerSet.remove(listener); 131 if (listenerSet.isEmpty()) { 132 mListeners.remove(recordedProgramId); 133 } 134 } 135 136 private void notifyWatchedPositionChanged(long recordedProgramId, long positionMs) { 137 Set<WatchedPositionChangedListener> listenerSet = mListeners.get(recordedProgramId); 138 if (listenerSet == null) { 139 return; 140 } 141 for (WatchedPositionChangedListener listener : listenerSet) { 142 listener.onWatchedPositionChanged(recordedProgramId, positionMs); 143 } 144 } 145 146 public interface WatchedPositionChangedListener { 147 /** 148 * Called when the watched position of some program is changed. 149 */ 150 void onWatchedPositionChanged(long recordedProgramId, long positionMs); 151 } 152} 153