Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1134)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java

Issue 2833493002: [Media>UI] Apply throttling if the notification is updated too frequently (Closed)
Patch Set: rebased and fixed tests Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | chrome/android/java_sources.gni » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
index 815761f11efc5f6a21b487996a14f94597b8335c..40b60ab945e5666bb4b24ce5f2ebd74dc7449e50 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
@@ -21,7 +21,9 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.os.Build;
+import android.os.Handler;
import android.os.IBinder;
+import android.support.annotation.NonNull;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaSessionCompat;
@@ -33,6 +35,7 @@ import android.util.SparseArray;
import android.view.KeyEvent;
import org.chromium.base.ContextUtils;
+import org.chromium.base.Log;
import org.chromium.base.SysUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.blink.mojom.MediaSessionAction;
@@ -129,6 +132,98 @@ public class MediaNotificationManager {
@VisibleForTesting
MediaSessionCompat mMediaSession;
+ @VisibleForTesting
+ Throttler mThrottler;
+
+ @VisibleForTesting
+ static class Throttler {
+ @VisibleForTesting
+ static final int THROTTLE_MILLIS = 500;
+
+ @VisibleForTesting
+ MediaNotificationManager mManager;
+
+ private final Handler mHandler;
+
+ @VisibleForTesting
+ Throttler(@NonNull MediaNotificationManager manager) {
+ mManager = manager;
+ mHandler = new Handler();
+ }
+
+ // When |mTask| is non-null, it will always be queued in mHandler. When |mTask| is non-null,
+ // all notification updates will be throttled and their info will be stored as
+ // mLastPendingInfo. When |mTask| fires, it will call {@link showNotification()} with
+ // the latest queued notification info.
+ @VisibleForTesting
+ Runnable mTask;
+
+ // The last pending info. If non-null, it will be the latest notification info.
+ // Otherwise, the latest notification info will be |mManager.mMediaNotificationInfo|.
+ @VisibleForTesting
+ MediaNotificationInfo mLastPendingInfo;
+
+ /**
+ * Queue |mediaNotificationInfo| for update. In unthrottled state (i.e. |mTask| != null),
+ * the notification will be updated immediately and enter the throttled state. In
+ * unthrottled state, the method will only update the pending notification info, which will
+ * be used for updating the notification when |mTask| is fired.
+ *
+ * @param mediaNotificationInfo The notification info to be queued.
+ */
+ public void queueNotification(MediaNotificationInfo mediaNotificationInfo) {
+ assert mediaNotificationInfo != null;
+
+ MediaNotificationInfo latestMediaNotificationInfo =
+ mLastPendingInfo != null ? mLastPendingInfo : mManager.mMediaNotificationInfo;
+
+ if (shouldIgnoreMediaNotificationInfo(
+ latestMediaNotificationInfo, mediaNotificationInfo)) {
+ return;
+ }
+
+ if (mTask == null) {
+ showNotificationImmediately(mediaNotificationInfo);
+ } else {
+ mLastPendingInfo = mediaNotificationInfo;
+ }
+ }
+
+ /**
+ * Clears the pending notification and enter unthrottled state.
+ */
+ public void clearPendingNotifications() {
+ mHandler.removeCallbacks(mTask);
+ mLastPendingInfo = null;
+ mTask = null;
+ }
+
+ @VisibleForTesting
+ void showNotificationImmediately(MediaNotificationInfo mediaNotificationInfo) {
+ // If no notification hasn't been updated in the last THROTTLE_MILLIS, update
+ // immediately and queue a task for blocking further updates.
+ mManager.showNotification(mediaNotificationInfo);
+ mTask = new Runnable() {
+ @Override
+ public void run() {
+ if (mLastPendingInfo != null) {
+ // If any notification info is pended during the throttling time window,
+ // update the notification.
+ showNotificationImmediately(mLastPendingInfo);
+ mLastPendingInfo = null;
+ } else {
+ // Otherwise, clear the task so further update is unthrottled.
+ mTask = null;
+ }
+ }
+ };
+ if (!mHandler.postDelayed(mTask, THROTTLE_MILLIS)) {
+ Log.w(TAG, "Failed to post the throttler task.");
+ mTask = null;
+ }
+ }
+ }
+
private final MediaSessionCompat.Callback mMediaSessionCallback =
new MediaSessionCompat.Callback() {
@Override
@@ -468,7 +563,7 @@ public class MediaNotificationManager {
sManagers.put(notificationInfo.id, manager);
}
- manager.showNotification(notificationInfo);
+ manager.mThrottler.queueNotification(notificationInfo);
}
/**
@@ -644,6 +739,8 @@ public class MediaNotificationManager {
new MediaButtonInfo(R.drawable.ic_fast_rewind_white_36dp,
R.string.accessibility_seek_backward,
ListenerService.ACTION_SEEK_BACKWARD));
+
+ mThrottler = new Throttler(this);
}
/**
@@ -692,9 +789,7 @@ public class MediaNotificationManager {
@VisibleForTesting
void showNotification(MediaNotificationInfo mediaNotificationInfo) {
- if (mediaNotificationInfo.equals(mMediaNotificationInfo)) return;
- if (mediaNotificationInfo.isPaused && mMediaNotificationInfo != null
- && mediaNotificationInfo.tabId != mMediaNotificationInfo.tabId) {
+ if (shouldIgnoreMediaNotificationInfo(mMediaNotificationInfo, mediaNotificationInfo)) {
return;
}
@@ -715,7 +810,15 @@ public class MediaNotificationManager {
}
}
- private void clearNotification() {
+ private static boolean shouldIgnoreMediaNotificationInfo(
+ MediaNotificationInfo oldInfo, MediaNotificationInfo newInfo) {
+ return newInfo.equals(oldInfo)
+ || ((newInfo.isPaused && oldInfo != null && newInfo.tabId != oldInfo.tabId));
+ }
+
+ @VisibleForTesting
+ void clearNotification() {
+ mThrottler.clearPendingNotifications();
if (mMediaNotificationInfo == null) return;
NotificationManagerCompat manager = NotificationManagerCompat.from(getContext());
« no previous file with comments | « no previous file | chrome/android/java_sources.gni » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698