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

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/media/remote/CastNotificationControl.java

Issue 1652163002: Refactor Clank cast code to use MediaNotificationManager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@MediaUi
Patch Set: Respond to final batch of nits Created 4 years, 10 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
Index: chrome/android/java/src/org/chromium/chrome/browser/media/remote/CastNotificationControl.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/remote/CastNotificationControl.java b/chrome/android/java/src/org/chromium/chrome/browser/media/remote/CastNotificationControl.java
new file mode 100644
index 0000000000000000000000000000000000000000..9864d7b4a7c49e0d91c2a2c06916b5eeba3eebe8
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/remote/CastNotificationControl.java
@@ -0,0 +1,211 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.media.remote;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.media.AudioManager;
+
+import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.media.remote.RemoteVideoInfo.PlayerState;
+import org.chromium.chrome.browser.media.ui.MediaNotificationInfo;
+import org.chromium.chrome.browser.media.ui.MediaNotificationListener;
+import org.chromium.chrome.browser.media.ui.MediaNotificationManager;
+import org.chromium.chrome.browser.tab.Tab;
+
+import javax.annotation.Nullable;
+
+/**
+ * Notification control controls the cast notification and lock screen, using
+ * {@link MediaNotificationManager}
+ */
+public class CastNotificationControl implements MediaRouteController.UiListener,
+ MediaNotificationListener, AudioManager.OnAudioFocusChangeListener {
+
+ private static CastNotificationControl sInstance;
+
+ private Bitmap mPosterBitmap;
+ protected MediaRouteController mMediaRouteController = null;
+ private MediaNotificationInfo.Builder mNotificationBuilder;
+ private Context mContext;
+ private PlayerState mState;
+ private String mTitle = "";
+ private AudioManager mAudioManager;
+
+ private boolean mIsShowing = false;
+
+ private static final Object LOCK = new Object();
+
+
+ private CastNotificationControl(Context context) {
+ mContext = context;
+ mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ }
+ /**
+ * Get the unique NotificationControl, creating it if necessary.
+ * @param context The context of the activity
+ * @param mediaRouteController The current mediaRouteController, if any.
+ * @return a {@code LockScreenTransportControl} based on the platform's SDK API or null if the
+ * current platform's SDK API is not supported.
+ */
+ public static CastNotificationControl getOrCreate(Context context,
+ @Nullable MediaRouteController mediaRouteController) {
+ synchronized (LOCK) {
+ if (sInstance == null) {
+ sInstance = new CastNotificationControl(context);
+ }
+ sInstance.mMediaRouteController = mediaRouteController;
+ return sInstance;
+ }
+ }
+
+ /**
+ * @return the poster bitmap previously assigned with {@link #setPosterBitmap(Bitmap)}, or
+ * {@code null} if the poster bitmap has not yet been assigned.
+ */
+ public final Bitmap getPosterBitmap() {
+ return mPosterBitmap;
+ }
+
+ /**
+ * Sets the poster bitmap to display on the TransportControl.
+ */
+ public final void setPosterBitmap(Bitmap posterBitmap) {
+ if (mPosterBitmap == posterBitmap
+ || (mPosterBitmap != null && mPosterBitmap.sameAs(posterBitmap))) {
+ return;
+ }
+ mPosterBitmap = posterBitmap;
+ if (mNotificationBuilder == null || mMediaRouteController == null) return;
+ mNotificationBuilder.setImage(mMediaRouteController.getPoster());
+ updateNotification();
+ }
+
+ public void hide() {
+ mIsShowing = false;
+ MediaNotificationManager.hide(Tab.INVALID_TAB_ID, R.id.remote_notification);
+ mAudioManager.abandonAudioFocus(this);
+ mMediaRouteController.removeUiListener(this);
+ }
+
+ public void show(PlayerState initialState) {
+ mMediaRouteController.addUiListener(this);
+ // TODO(aberent): investigate why this is necessary, and whether we are handling
+ // it correctly. Also add code to restore it when Chrome is resumed.
+ mAudioManager.requestAudioFocus(this, AudioManager.USE_DEFAULT_STREAM_TYPE,
+ AudioManager.AUDIOFOCUS_GAIN);
+ Intent contentIntent = new Intent(mContext, ExpandedControllerActivity.class);
+ mNotificationBuilder = new MediaNotificationInfo.Builder()
+ .setPaused(false)
+ .setPrivate(false)
+ .setIcon(R.drawable.ic_notification_media_route)
+ .setContentIntent(contentIntent)
+ .setImage(mMediaRouteController.getPoster())
+ .setId(R.id.remote_notification)
+ .setListener(this);
+ mState = initialState;
+ updateNotification();
+ mIsShowing = true;
+ }
+
+ public void setRouteController(MediaRouteController controller) {
+ mMediaRouteController = controller;
+ }
+
+ private void updateNotification() {
+ mNotificationBuilder.setTitle(mTitle);
+ if (mState == PlayerState.PAUSED || mState == PlayerState.PLAYING) {
+ mNotificationBuilder.setPaused(mState != PlayerState.PLAYING);
+ mNotificationBuilder.setActions(MediaNotificationInfo.ACTION_STOP
+ | MediaNotificationInfo.ACTION_PLAY_PAUSE);
+ MediaNotificationManager.show(mContext, mNotificationBuilder.build());
+ } else if (mState == PlayerState.LOADING) {
+ mNotificationBuilder.setActions(MediaNotificationInfo.ACTION_STOP);
+ MediaNotificationManager.show(mContext, mNotificationBuilder.build());
+ } else {
+ hide();
+ }
+ }
+
+ // TODO(aberent) at the moment this is only called from a test, but it should be called if the
+ // poster changes.
+ public void onPosterBitmapChanged() {
+ if (mNotificationBuilder == null || mMediaRouteController == null) return;
+ mNotificationBuilder.setImage(mMediaRouteController.getPoster());
+ updateNotification();
+ }
+
+ // MediaRouteController.UiListener implementation.
+ @Override
+ public void onPlaybackStateChanged(PlayerState oldState, PlayerState newState) {
+ mState = newState;
+ updateNotification();
+ }
+
+ @Override
+ public void onRouteSelected(String name, MediaRouteController mediaRouteController) {
+ }
+
+ @Override
+ public void onRouteUnselected(MediaRouteController mediaRouteController) {
+ hide();
+ }
+
+ @Override
+ public void onPrepared(MediaRouteController mediaRouteController) {
+ }
+
+ @Override
+ public void onError(int errorType, String message) {
+ }
+
+ @Override
+ public void onDurationUpdated(long durationMillis) {
+ }
+
+ @Override
+ public void onPositionChanged(long positionMillis) {
+ }
+
+ @Override
+ public void onTitleChanged(String title) {
+ mTitle = (title == null) ? "" : title;
+ updateNotification();
+ }
+
+ // MediaNotificationListener methods
+ @Override
+ public void onPlay(int actionSource) {
+ mMediaRouteController.resume();
+ }
+
+ @Override
+ public void onPause(int actionSource) {
+ mMediaRouteController.pause();
+ }
+
+ @Override
+ public void onStop(int actionSource) {
+ mMediaRouteController.release();
+ }
+
+ // AudioManager.OnAudioFocusChangeListener methods
+ @Override
+ public void onAudioFocusChange(int focusChange) {
+ // Do nothing. The remote player should keep playing.
+ }
+
+ @VisibleForTesting
+ static CastNotificationControl getForTests() {
+ return sInstance;
+ }
+
+ @VisibleForTesting
+ boolean isShowingForTests() {
+ return mIsShowing;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698