aboutsummaryrefslogtreecommitdiff
path: root/src/com/android/tv/data/ProgramDataManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/tv/data/ProgramDataManager.java')
-rw-r--r--src/com/android/tv/data/ProgramDataManager.java358
1 files changed, 206 insertions, 152 deletions
diff --git a/src/com/android/tv/data/ProgramDataManager.java b/src/com/android/tv/data/ProgramDataManager.java
index 8cb5e74a..4631806c 100644
--- a/src/com/android/tv/data/ProgramDataManager.java
+++ b/src/com/android/tv/data/ProgramDataManager.java
@@ -33,14 +33,16 @@ import android.util.ArraySet;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.LruCache;
-
-import com.android.tv.common.MemoryManageable;
+import com.android.tv.TvSingletons;
import com.android.tv.common.SoftPreconditions;
+import com.android.tv.common.config.api.RemoteConfig;
+import com.android.tv.common.config.api.RemoteConfigValue;
+import com.android.tv.common.memory.MemoryManageable;
+import com.android.tv.common.util.Clock;
+import com.android.tv.data.api.Channel;
import com.android.tv.util.AsyncDbTask;
-import com.android.tv.util.Clock;
import com.android.tv.util.MultiLongSparseArray;
import com.android.tv.util.Utils;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -51,6 +53,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@MainThread
@@ -60,23 +63,28 @@ public class ProgramDataManager implements MemoryManageable {
// To prevent from too many program update operations at the same time, we give random interval
// between PERIODIC_PROGRAM_UPDATE_MIN_MS and PERIODIC_PROGRAM_UPDATE_MAX_MS.
- private static final long PERIODIC_PROGRAM_UPDATE_MIN_MS = TimeUnit.MINUTES.toMillis(5);
+ @VisibleForTesting
+ static final long PERIODIC_PROGRAM_UPDATE_MIN_MS = TimeUnit.MINUTES.toMillis(5);
+
private static final long PERIODIC_PROGRAM_UPDATE_MAX_MS = TimeUnit.MINUTES.toMillis(10);
private static final long PROGRAM_PREFETCH_UPDATE_WAIT_MS = TimeUnit.SECONDS.toMillis(5);
// TODO: need to optimize consecutive DB updates.
private static final long CURRENT_PROGRAM_UPDATE_WAIT_MS = TimeUnit.SECONDS.toMillis(5);
- @VisibleForTesting
- static final long PROGRAM_GUIDE_SNAP_TIME_MS = TimeUnit.MINUTES.toMillis(30);
- @VisibleForTesting
- static final long PROGRAM_GUIDE_MAX_TIME_RANGE = TimeUnit.DAYS.toMillis(2);
+ @VisibleForTesting static final long PROGRAM_GUIDE_SNAP_TIME_MS = TimeUnit.MINUTES.toMillis(30);
+ private static final RemoteConfigValue<Long> PROGRAM_GUIDE_MAX_HOURS =
+ RemoteConfigValue.create("live_channels_program_guide_max_hours", 48);
// TODO: Use TvContract constants, once they become public.
private static final String PARAM_START_TIME = "start_time";
private static final String PARAM_END_TIME = "end_time";
// COLUMN_CHANNEL_ID, COLUMN_END_TIME_UTC_MILLIS are added to detect duplicated programs.
// Duplicated programs are always consecutive by the sorting order.
- private static final String SORT_BY_TIME = Programs.COLUMN_START_TIME_UTC_MILLIS + ", "
- + Programs.COLUMN_CHANNEL_ID + ", " + Programs.COLUMN_END_TIME_UTC_MILLIS;
+ private static final String SORT_BY_TIME =
+ Programs.COLUMN_START_TIME_UTC_MILLIS
+ + ", "
+ + Programs.COLUMN_CHANNEL_ID
+ + ", "
+ + Programs.COLUMN_END_TIME_UTC_MILLIS;
private static final int MSG_UPDATE_CURRENT_PROGRAMS = 1000;
private static final int MSG_UPDATE_ONE_CURRENT_PROGRAM = 1001;
@@ -84,6 +92,8 @@ public class ProgramDataManager implements MemoryManageable {
private final Clock mClock;
private final ContentResolver mContentResolver;
+ private final Executor mDbExecutor;
+ private final RemoteConfig mRemoteConfig;
private boolean mStarted;
// Updated only on the main thread.
private volatile boolean mCurrentProgramsLoadFinished;
@@ -114,32 +124,47 @@ public class ProgramDataManager implements MemoryManageable {
@MainThread
public ProgramDataManager(Context context) {
- this(context.getContentResolver(), Clock.SYSTEM, Looper.myLooper());
+ this(
+ TvSingletons.getSingletons(context).getDbExecutor(),
+ context.getContentResolver(),
+ Clock.SYSTEM,
+ Looper.myLooper(),
+ TvSingletons.getSingletons(context).getRemoteConfig());
}
@VisibleForTesting
- ProgramDataManager(ContentResolver contentResolver, Clock time, Looper looper) {
+ ProgramDataManager(
+ Executor executor,
+ ContentResolver contentResolver,
+ Clock time,
+ Looper looper,
+ RemoteConfig remoteConfig) {
+ mDbExecutor = executor;
mClock = time;
mContentResolver = contentResolver;
mHandler = new MyHandler(looper);
- mProgramObserver = new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- if (!mHandler.hasMessages(MSG_UPDATE_CURRENT_PROGRAMS)) {
- mHandler.sendEmptyMessage(MSG_UPDATE_CURRENT_PROGRAMS);
- }
- if (isProgramUpdatePaused()) {
- return;
- }
- if (mPrefetchEnabled) {
- // The delay time of an existing MSG_UPDATE_PREFETCH_PROGRAM could be quite long
- // up to PROGRAM_GUIDE_SNAP_TIME_MS. So we need to remove the existing message
- // and send MSG_UPDATE_PREFETCH_PROGRAM again.
- mHandler.removeMessages(MSG_UPDATE_PREFETCH_PROGRAM);
- mHandler.sendEmptyMessage(MSG_UPDATE_PREFETCH_PROGRAM);
- }
- }
- };
+ mRemoteConfig = remoteConfig;
+ mProgramObserver =
+ new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ if (!mHandler.hasMessages(MSG_UPDATE_CURRENT_PROGRAMS)) {
+ mHandler.sendEmptyMessage(MSG_UPDATE_CURRENT_PROGRAMS);
+ }
+ if (isProgramUpdatePaused()) {
+ return;
+ }
+ if (mPrefetchEnabled) {
+ // The delay time of an existing MSG_UPDATE_PREFETCH_PROGRAM could be
+ // quite long
+ // up to PROGRAM_GUIDE_SNAP_TIME_MS. So we need to remove the existing
+ // message
+ // and send MSG_UPDATE_PREFETCH_PROGRAM again.
+ mHandler.removeMessages(MSG_UPDATE_PREFETCH_PROGRAM);
+ mHandler.sendEmptyMessage(MSG_UPDATE_PREFETCH_PROGRAM);
+ }
+ }
+ };
mProgramPrefetchUpdateWaitMs = PROGRAM_PREFETCH_UPDATE_WAIT_MS;
}
@@ -149,18 +174,16 @@ public class ProgramDataManager implements MemoryManageable {
}
/**
- * Set the program prefetch update wait which gives the delay to query all programs from DB
- * to prevent from too frequent DB queries.
- * Default value is {@link #PROGRAM_PREFETCH_UPDATE_WAIT_MS}
+ * Set the program prefetch update wait which gives the delay to query all programs from DB to
+ * prevent from too frequent DB queries. Default value is {@link
+ * #PROGRAM_PREFETCH_UPDATE_WAIT_MS}
*/
@VisibleForTesting
void setProgramPrefetchUpdateWait(long programPrefetchUpdateWaitMs) {
mProgramPrefetchUpdateWaitMs = programPrefetchUpdateWaitMs;
}
- /**
- * Starts the manager.
- */
+ /** Starts the manager. */
public void start() {
if (mStarted) {
return;
@@ -172,8 +195,7 @@ public class ProgramDataManager implements MemoryManageable {
if (mPrefetchEnabled) {
mHandler.sendEmptyMessage(MSG_UPDATE_PREFETCH_PROGRAM);
}
- mContentResolver.registerContentObserver(Programs.CONTENT_URI,
- true, mProgramObserver);
+ mContentResolver.registerContentObserver(Programs.CONTENT_URI, true, mProgramObserver);
}
/**
@@ -214,9 +236,7 @@ public class ProgramDataManager implements MemoryManageable {
return new ArrayList<>(mChannelIdCurrentProgramMap.values());
}
- /**
- * Reloads program data.
- */
+ /** Reloads program data. */
public void reload() {
if (!mHandler.hasMessages(MSG_UPDATE_CURRENT_PROGRAMS)) {
mHandler.sendEmptyMessage(MSG_UPDATE_CURRENT_PROGRAMS);
@@ -226,35 +246,27 @@ public class ProgramDataManager implements MemoryManageable {
}
}
- /**
- * A listener interface to receive notification on program data retrieval from DB.
- */
+ /** A listener interface to receive notification on program data retrieval from DB. */
public interface Listener {
/**
- * Called when a Program data is now available through getProgram()
- * after the DB operation is done which wasn't before.
- * This would be called only if fetched data is around the selected program.
- **/
+ * Called when a Program data is now available through getProgram() after the DB operation
+ * is done which wasn't before. This would be called only if fetched data is around the
+ * selected program.
+ */
void onProgramUpdated();
}
- /**
- * Adds the {@link Listener}.
- */
+ /** Adds the {@link Listener}. */
public void addListener(Listener listener) {
mListeners.add(listener);
}
- /**
- * Removes the {@link Listener}.
- */
+ /** Removes the {@link Listener}. */
public void removeListener(Listener listener) {
mListeners.remove(listener);
}
- /**
- * Enables or Disables program prefetch.
- */
+ /** Enables or Disables program prefetch. */
public void setPrefetchEnabled(boolean enable) {
if (mPrefetchEnabled == enable) {
return;
@@ -276,10 +288,10 @@ public class ProgramDataManager implements MemoryManageable {
/**
* Returns the programs for the given channel which ends after the given start time.
*
- * <p> Prefetch should be enabled to call it.
+ * <p>Prefetch should be enabled to call it.
*
* @return {@link List} with Programs. It may includes dummy program if the entry needs DB
- * operations to get.
+ * operations to get.
*/
public List<Program> getPrograms(long channelId, long startTime) {
SoftPreconditions.checkState(mPrefetchEnabled, TAG, "Prefetch is disabled.");
@@ -292,9 +304,12 @@ public class ProgramDataManager implements MemoryManageable {
cachedPrograms.subList(startIndex, cachedPrograms.size()));
}
- // Returns the index of program that is played at the specified time.
- // If there isn't, return the first program among programs that starts after the given time
- // if returnNextProgram is {@code true}.
+ /**
+ * Returns the index of program that is played at the specified time.
+ *
+ * <p>If there isn't, return the first program among programs that starts after the given time
+ * if returnNextProgram is {@code true}.
+ */
private int getProgramIndexAt(List<Program> programs, long time) {
Program key = mZeroLengthProgramCache.get(time);
if (key == null) {
@@ -321,38 +336,38 @@ public class ProgramDataManager implements MemoryManageable {
* Adds the listener to be notified if current program is updated for a channel.
*
* @param channelId A channel ID to get notified. If it's {@link Channel#INVALID_ID}, the
- * listener would be called whenever a current program is updated.
+ * listener would be called whenever a current program is updated.
*/
public void addOnCurrentProgramUpdatedListener(
long channelId, OnCurrentProgramUpdatedListener listener) {
- mChannelId2ProgramUpdatedListeners
- .put(channelId, listener);
+ mChannelId2ProgramUpdatedListeners.put(channelId, listener);
}
/**
- * Removes the listener previously added by
- * {@link #addOnCurrentProgramUpdatedListener(long, OnCurrentProgramUpdatedListener)}.
+ * Removes the listener previously added by {@link #addOnCurrentProgramUpdatedListener(long,
+ * OnCurrentProgramUpdatedListener)}.
*/
public void removeOnCurrentProgramUpdatedListener(
long channelId, OnCurrentProgramUpdatedListener listener) {
- mChannelId2ProgramUpdatedListeners
- .remove(channelId, listener);
+ mChannelId2ProgramUpdatedListeners.remove(channelId, listener);
}
private void notifyCurrentProgramUpdate(long channelId, Program program) {
- for (OnCurrentProgramUpdatedListener listener : mChannelId2ProgramUpdatedListeners
- .get(channelId)) {
+ for (OnCurrentProgramUpdatedListener listener :
+ mChannelId2ProgramUpdatedListeners.get(channelId)) {
listener.onCurrentProgramUpdated(channelId, program);
}
- for (OnCurrentProgramUpdatedListener listener : mChannelId2ProgramUpdatedListeners
- .get(Channel.INVALID_ID)) {
+ for (OnCurrentProgramUpdatedListener listener :
+ mChannelId2ProgramUpdatedListeners.get(Channel.INVALID_ID)) {
listener.onCurrentProgramUpdated(channelId, program);
}
}
private void updateCurrentProgram(long channelId, Program program) {
- Program previousProgram = program == null ? mChannelIdCurrentProgramMap.remove(channelId)
- : mChannelIdCurrentProgramMap.put(channelId, program);
+ Program previousProgram =
+ program == null
+ ? mChannelIdCurrentProgramMap.remove(channelId)
+ : mChannelIdCurrentProgramMap.put(channelId, program);
if (!Objects.equals(program, previousProgram)) {
if (mPrefetchEnabled) {
removePreviousProgramsAndUpdateCurrentProgramInCache(channelId, program);
@@ -362,20 +377,23 @@ public class ProgramDataManager implements MemoryManageable {
long delayedTime;
if (program == null) {
- delayedTime = PERIODIC_PROGRAM_UPDATE_MIN_MS
- + (long) (Math.random() * (PERIODIC_PROGRAM_UPDATE_MAX_MS
- - PERIODIC_PROGRAM_UPDATE_MIN_MS));
+ delayedTime =
+ PERIODIC_PROGRAM_UPDATE_MIN_MS
+ + (long)
+ (Math.random()
+ * (PERIODIC_PROGRAM_UPDATE_MAX_MS
+ - PERIODIC_PROGRAM_UPDATE_MIN_MS));
} else {
delayedTime = program.getEndTimeUtcMillis() - mClock.currentTimeMillis();
}
- mHandler.sendMessageDelayed(mHandler.obtainMessage(
- MSG_UPDATE_ONE_CURRENT_PROGRAM, channelId), delayedTime);
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(MSG_UPDATE_ONE_CURRENT_PROGRAM, channelId), delayedTime);
}
private void removePreviousProgramsAndUpdateCurrentProgramInCache(
long channelId, Program currentProgram) {
SoftPreconditions.checkState(mPrefetchEnabled, TAG, "Prefetch is disabled.");
- if (!Program.isValid(currentProgram)) {
+ if (!Program.isProgramValid(currentProgram)) {
return;
}
ArrayList<Program> cachedPrograms = mChannelIdProgramCache.remove(channelId);
@@ -391,27 +409,29 @@ public class ProgramDataManager implements MemoryManageable {
continue;
}
- if (cachedProgram.getEndTimeUtcMillis() <= currentProgram
- .getStartTimeUtcMillis()) {
+ if (cachedProgram.getEndTimeUtcMillis() <= currentProgram.getStartTimeUtcMillis()) {
// Keep the programs that ends earlier than current program
// but later than mPrefetchTimeRangeStartMs.
continue;
}
// Update dummy program around current program if any.
- if (cachedProgram.getStartTimeUtcMillis() < currentProgram
- .getStartTimeUtcMillis()) {
+ if (cachedProgram.getStartTimeUtcMillis() < currentProgram.getStartTimeUtcMillis()) {
// The dummy program starts earlier than the current program. Adjust its end time.
- i.set(createDummyProgram(cachedProgram.getStartTimeUtcMillis(),
- currentProgram.getStartTimeUtcMillis()));
+ i.set(
+ createDummyProgram(
+ cachedProgram.getStartTimeUtcMillis(),
+ currentProgram.getStartTimeUtcMillis()));
i.add(currentProgram);
} else {
i.set(currentProgram);
}
if (currentProgram.getEndTimeUtcMillis() < cachedProgram.getEndTimeUtcMillis()) {
// The dummy program ends later than the current program. Adjust its start time.
- i.add(createDummyProgram(currentProgram.getEndTimeUtcMillis(),
- cachedProgram.getEndTimeUtcMillis()));
+ i.add(
+ createDummyProgram(
+ currentProgram.getEndTimeUtcMillis(),
+ cachedProgram.getEndTimeUtcMillis()));
}
break;
}
@@ -425,8 +445,8 @@ public class ProgramDataManager implements MemoryManageable {
private void handleUpdateCurrentPrograms() {
if (mProgramsUpdateTask != null) {
- mHandler.sendEmptyMessageDelayed(MSG_UPDATE_CURRENT_PROGRAMS,
- CURRENT_PROGRAM_UPDATE_WAIT_MS);
+ mHandler.sendEmptyMessageDelayed(
+ MSG_UPDATE_CURRENT_PROGRAMS, CURRENT_PROGRAM_UPDATE_WAIT_MS);
return;
}
clearTask(mProgramUpdateTaskMap);
@@ -443,10 +463,13 @@ public class ProgramDataManager implements MemoryManageable {
private boolean mSuccess;
public ProgramsPrefetchTask() {
+ super(mDbExecutor);
long time = mClock.currentTimeMillis();
- mStartTimeMs = Utils
- .floorTime(time - PROGRAM_GUIDE_SNAP_TIME_MS, PROGRAM_GUIDE_SNAP_TIME_MS);
- mEndTimeMs = mStartTimeMs + PROGRAM_GUIDE_MAX_TIME_RANGE;
+ mStartTimeMs =
+ Utils.floorTime(time - PROGRAM_GUIDE_SNAP_TIME_MS, PROGRAM_GUIDE_SNAP_TIME_MS);
+ mEndTimeMs =
+ mStartTimeMs
+ + TimeUnit.HOURS.toMillis(PROGRAM_GUIDE_MAX_HOURS.get(mRemoteConfig));
mSuccess = false;
}
@@ -454,12 +477,19 @@ public class ProgramDataManager implements MemoryManageable {
protected Map<Long, ArrayList<Program>> doInBackground(Void... params) {
Map<Long, ArrayList<Program>> programMap = new HashMap<>();
if (DEBUG) {
- Log.d(TAG, "Starts programs prefetch. " + Utils.toTimeString(mStartTimeMs) + "-"
- + Utils.toTimeString(mEndTimeMs));
+ Log.d(
+ TAG,
+ "Starts programs prefetch. "
+ + Utils.toTimeString(mStartTimeMs)
+ + "-"
+ + Utils.toTimeString(mEndTimeMs));
}
- Uri uri = Programs.CONTENT_URI.buildUpon()
- .appendQueryParameter(PARAM_START_TIME, String.valueOf(mStartTimeMs))
- .appendQueryParameter(PARAM_END_TIME, String.valueOf(mEndTimeMs)).build();
+ Uri uri =
+ Programs.CONTENT_URI
+ .buildUpon()
+ .appendQueryParameter(PARAM_START_TIME, String.valueOf(mStartTimeMs))
+ .appendQueryParameter(PARAM_END_TIME, String.valueOf(mEndTimeMs))
+ .build();
final int RETRY_COUNT = 3;
Program lastReadProgram = null;
for (int retryCount = RETRY_COUNT; retryCount > 0; retryCount--) {
@@ -467,8 +497,8 @@ public class ProgramDataManager implements MemoryManageable {
return null;
}
programMap.clear();
- try (Cursor c = mContentResolver.query(uri, Program.PROJECTION, null, null,
- SORT_BY_TIME)) {
+ try (Cursor c =
+ mContentResolver.query(uri, Program.PROJECTION, null, null, SORT_BY_TIME)) {
if (c == null) {
continue;
}
@@ -527,14 +557,16 @@ public class ProgramDataManager implements MemoryManageable {
long currentTime = mClock.currentTimeMillis();
mLastPrefetchTaskRunMs = currentTime;
nextMessageDelayedTime =
- Utils.floorTime(mLastPrefetchTaskRunMs + PROGRAM_GUIDE_SNAP_TIME_MS,
- PROGRAM_GUIDE_SNAP_TIME_MS) - currentTime;
+ Utils.floorTime(
+ mLastPrefetchTaskRunMs + PROGRAM_GUIDE_SNAP_TIME_MS,
+ PROGRAM_GUIDE_SNAP_TIME_MS)
+ - currentTime;
} else {
nextMessageDelayedTime = PERIODIC_PROGRAM_UPDATE_MIN_MS;
}
if (!mHandler.hasMessages(MSG_UPDATE_PREFETCH_PROGRAM)) {
- mHandler.sendEmptyMessageDelayed(MSG_UPDATE_PREFETCH_PROGRAM,
- nextMessageDelayedTime);
+ mHandler.sendEmptyMessageDelayed(
+ MSG_UPDATE_PREFETCH_PROGRAM, nextMessageDelayedTime);
}
}
}
@@ -547,10 +579,18 @@ public class ProgramDataManager implements MemoryManageable {
private class ProgramsUpdateTask extends AsyncDbTask.AsyncQueryTask<List<Program>> {
public ProgramsUpdateTask(ContentResolver contentResolver, long time) {
- super(contentResolver, Programs.CONTENT_URI.buildUpon()
+ super(
+ mDbExecutor,
+ contentResolver,
+ Programs.CONTENT_URI
+ .buildUpon()
.appendQueryParameter(PARAM_START_TIME, String.valueOf(time))
- .appendQueryParameter(PARAM_END_TIME, String.valueOf(time)).build(),
- Program.PROJECTION, null, null, SORT_BY_TIME);
+ .appendQueryParameter(PARAM_END_TIME, String.valueOf(time))
+ .build(),
+ Program.PROJECTION,
+ null,
+ null,
+ SORT_BY_TIME);
}
@Override
@@ -604,10 +644,17 @@ public class ProgramDataManager implements MemoryManageable {
private class UpdateCurrentProgramForChannelTask extends AsyncDbTask.AsyncQueryTask<Program> {
private final long mChannelId;
- private UpdateCurrentProgramForChannelTask(ContentResolver contentResolver, long channelId,
- long time) {
- super(contentResolver, TvContract.buildProgramsUriForChannel(channelId, time, time),
- Program.PROJECTION, null, null, SORT_BY_TIME);
+
+ private UpdateCurrentProgramForChannelTask(
+ ContentResolver contentResolver, long channelId, long time) {
+ super(
+ mDbExecutor,
+ contentResolver,
+ TvContract.buildProgramsUriForChannel(channelId, time, time),
+ Program.PROJECTION,
+ null,
+ null,
+ SORT_BY_TIME);
mChannelId = channelId;
}
@@ -638,48 +685,55 @@ public class ProgramDataManager implements MemoryManageable {
case MSG_UPDATE_CURRENT_PROGRAMS:
handleUpdateCurrentPrograms();
break;
- case MSG_UPDATE_ONE_CURRENT_PROGRAM: {
- long channelId = (Long) msg.obj;
- UpdateCurrentProgramForChannelTask oldTask = mProgramUpdateTaskMap
- .get(channelId);
- if (oldTask != null) {
- oldTask.cancel(true);
- }
- UpdateCurrentProgramForChannelTask
- task = new UpdateCurrentProgramForChannelTask(
- mContentResolver, channelId, mClock.currentTimeMillis());
- mProgramUpdateTaskMap.put(channelId, task);
- task.executeOnDbThread();
- break;
- }
- case MSG_UPDATE_PREFETCH_PROGRAM: {
- if (isProgramUpdatePaused()) {
- return;
- }
- if (mProgramsPrefetchTask != null) {
- mHandler.sendEmptyMessageDelayed(msg.what, mProgramPrefetchUpdateWaitMs);
- return;
+ case MSG_UPDATE_ONE_CURRENT_PROGRAM:
+ {
+ long channelId = (Long) msg.obj;
+ UpdateCurrentProgramForChannelTask oldTask =
+ mProgramUpdateTaskMap.get(channelId);
+ if (oldTask != null) {
+ oldTask.cancel(true);
+ }
+ UpdateCurrentProgramForChannelTask task =
+ new UpdateCurrentProgramForChannelTask(
+ mContentResolver, channelId, mClock.currentTimeMillis());
+ mProgramUpdateTaskMap.put(channelId, task);
+ task.executeOnDbThread();
+ break;
}
- long delayMillis = mLastPrefetchTaskRunMs + mProgramPrefetchUpdateWaitMs
- - mClock.currentTimeMillis();
- if (delayMillis > 0) {
- mHandler.sendEmptyMessageDelayed(MSG_UPDATE_PREFETCH_PROGRAM, delayMillis);
- } else {
- mProgramsPrefetchTask = new ProgramsPrefetchTask();
- mProgramsPrefetchTask.executeOnDbThread();
+ case MSG_UPDATE_PREFETCH_PROGRAM:
+ {
+ if (isProgramUpdatePaused()) {
+ return;
+ }
+ if (mProgramsPrefetchTask != null) {
+ mHandler.sendEmptyMessageDelayed(
+ msg.what, mProgramPrefetchUpdateWaitMs);
+ return;
+ }
+ long delayMillis =
+ mLastPrefetchTaskRunMs
+ + mProgramPrefetchUpdateWaitMs
+ - mClock.currentTimeMillis();
+ if (delayMillis > 0) {
+ mHandler.sendEmptyMessageDelayed(
+ MSG_UPDATE_PREFETCH_PROGRAM, delayMillis);
+ } else {
+ mProgramsPrefetchTask = new ProgramsPrefetchTask();
+ mProgramsPrefetchTask.executeOnDbThread();
+ }
+ break;
}
- break;
- }
+ default:
+ // Do nothing
}
}
}
/**
- * Pause program update.
- * Updating program data will result in UI refresh,
- * but UI is fragile to handle it so we'd better disable it for a while.
+ * Pause program update. Updating program data will result in UI refresh, but UI is fragile to
+ * handle it so we'd better disable it for a while.
*
- * <p> Prefetch should be enabled to call it.
+ * <p>Prefetch should be enabled to call it.
*/
public void setPauseProgramUpdate(boolean pauseProgramUpdate) {
SoftPreconditions.checkState(mPrefetchEnabled, TAG, "Prefetch is disabled.");
@@ -700,11 +754,10 @@ public class ProgramDataManager implements MemoryManageable {
}
/**
- * Sets program data prefetch time range.
- * Any program data that ends before the start time will be removed from the cache later.
- * Note that there's no limit for end time.
+ * Sets program data prefetch time range. Any program data that ends before the start time will
+ * be removed from the cache later. Note that there's no limit for end time.
*
- * <p> Prefetch should be enabled to call it.
+ * <p>Prefetch should be enabled to call it.
*/
public void setPrefetchTimeRange(long startTimeMs) {
SoftPreconditions.checkState(mPrefetchEnabled, TAG, "Prefetch is disabled.");
@@ -736,7 +789,8 @@ public class ProgramDataManager implements MemoryManageable {
return new Program.Builder()
.setChannelId(Channel.INVALID_ID)
.setStartTimeUtcMillis(startTimeMs)
- .setEndTimeUtcMillis(endTimeMs).build();
+ .setEndTimeUtcMillis(endTimeMs)
+ .build();
}
@Override