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

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

Issue 928643003: Upstream Chrome for Android Cast. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix dependencies (second attempt). Created 5 years, 9 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/LockScreenTransportControlV14.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/remote/LockScreenTransportControlV14.java b/chrome/android/java/src/org/chromium/chrome/browser/media/remote/LockScreenTransportControlV14.java
new file mode 100644
index 0000000000000000000000000000000000000000..f4dc73ebe70599cdcead81428e5c7a8b4b37d650
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/remote/LockScreenTransportControlV14.java
@@ -0,0 +1,234 @@
+// Copyright 2014 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.annotation.TargetApi;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.media.AudioManager;
+import android.media.AudioManager.OnAudioFocusChangeListener;
+import android.media.MediaMetadataRetriever;
+import android.os.Build;
+import android.util.Log;
+
+import org.chromium.base.CommandLine;
+import org.chromium.chrome.ChromeSwitches;
+import org.chromium.chrome.browser.media.remote.RemoteVideoInfo.PlayerState;
+
+/**
+ * An implementation of {@link LockScreenTransportControl} targeting platforms with an API of 14 or
+ * above.
+ */
+@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+// TODO(aberent) This whole class is based upon RemoteControlClient, which is deprecated in
+// the Android L SDK. It, however, still seems to be the only way of controlling the
+// lock screen wallpaper. We need to investigate whether there is an alternative. See
+// LockScreenTransportControl.java.
+@SuppressWarnings("deprecation")
+public class LockScreenTransportControlV14 extends LockScreenTransportControl {
+
+ private static final String TAG = "LockScreenTransportControlV14";
+
+ private static boolean sDebug;
+ private final AudioManager mAudioManager;
+ private final PendingIntent mMediaPendingIntent;
+ private final ComponentName mMediaEventReceiver;
+ private final AudioFocusListener mAudioFocusListener;
+
+ private android.media.RemoteControlClient mRemoteControlClient;
+ private boolean mIsPlaying;
+
+ protected LockScreenTransportControlV14(Context context) {
+ sDebug = CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_CAST_DEBUG_LOGS);
+
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+ mMediaEventReceiver = new ComponentName(context.getPackageName(),
+ MediaButtonIntentReceiver.class.getName());
+ Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+ mediaButtonIntent.setComponent(mMediaEventReceiver);
+ mMediaPendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0,
+ mediaButtonIntent, 0);
+ mAudioFocusListener = new AudioFocusListener();
+ }
+
+ @Override
+ public void onErrorChanged() {
+ if (hasError()) updatePlaybackState(android.media.RemoteControlClient.PLAYSTATE_ERROR);
+ }
+
+ @Override
+ public void onLockScreenPlaybackStateChanged(PlayerState oldState, PlayerState newState) {
+ if (sDebug) Log.d(TAG, "onLockScreenPlaybackStateChanged - new state: " + newState);
+ int playbackState = android.media.RemoteControlClient.PLAYSTATE_STOPPED;
+ boolean shouldBeRegistered = false;
+ if (newState != null) {
+ mIsPlaying = false;
+ shouldBeRegistered = true;
+ switch (newState) {
+ case PAUSED:
+ playbackState = android.media.RemoteControlClient.PLAYSTATE_PAUSED;
+ break;
+ case ERROR:
+ playbackState = android.media.RemoteControlClient.PLAYSTATE_ERROR;
+ break;
+ case PLAYING:
+ playbackState = android.media.RemoteControlClient.PLAYSTATE_PLAYING;
+ mIsPlaying = true;
+ break;
+ case LOADING:
+ playbackState = android.media.RemoteControlClient.PLAYSTATE_BUFFERING;
+ break;
+ default:
+ shouldBeRegistered = false;
+ break;
+ }
+ }
+
+ boolean registered = (mRemoteControlClient != null);
+ if (registered != shouldBeRegistered) {
+ if (shouldBeRegistered) {
+ register();
+ onVideoInfoChanged();
+ onPosterBitmapChanged();
+ } else {
+ unregister();
+ }
+ }
+
+ updatePlaybackState(playbackState);
+ }
+
+ @Override
+ public void onVideoInfoChanged() {
+ if (mRemoteControlClient == null) return;
+
+ RemoteVideoInfo videoInfo = getVideoInfo();
+
+ String title = null;
+ long duration = 0;
+ if (videoInfo != null) {
+ title = videoInfo.title;
+ duration = videoInfo.durationMillis;
+ }
+
+ android.media.RemoteControlClient.MetadataEditor editor = mRemoteControlClient.editMetadata(
+ true);
+ editor.putString(MediaMetadataRetriever.METADATA_KEY_TITLE, title);
+ editor.putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, duration);
+ updateBitmap(editor);
+ editor.apply();
+ }
+
+ @Override
+ public void onPosterBitmapChanged() {
+ if (mRemoteControlClient == null) return;
+
+ android.media.RemoteControlClient.MetadataEditor editor = mRemoteControlClient.editMetadata(
+ false);
+ updateBitmap(editor);
+ editor.apply();
+ }
+
+ private void updateBitmap(android.media.RemoteControlClient.MetadataEditor editor) {
+ // RemoteControlClient likes to recycle bitmaps that have been passed to it through
+ // BITMAP_KEY_ARTWORK. We can't go recycling bitmaps like this since they are also used by
+ // {@link ExpandedControllerActivity} and their life cycle is controller by
+ // {@link RemoteMediaPlayerController}. See crbug.com/356612
+ Bitmap src = getPosterBitmap();
+ Bitmap copy = src != null ? src.copy(src.getConfig(), true) : null;
+ editor.putBitmap(android.media.RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, copy);
+ }
+
+ protected final android.media.RemoteControlClient getRemoteControlClient() {
+ return mRemoteControlClient;
+ }
+
+ protected void register() {
+ if (sDebug) Log.d(TAG, "register called");
+ mRemoteControlClient = new android.media.RemoteControlClient(mMediaPendingIntent);
+ mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.USE_DEFAULT_STREAM_TYPE,
+ AudioManager.AUDIOFOCUS_GAIN);
+ mAudioManager.registerMediaButtonEventReceiver(mMediaEventReceiver);
+ mAudioManager.registerRemoteControlClient(mRemoteControlClient);
+ mRemoteControlClient.setTransportControlFlags(getTransportControlFlags());
+ }
+
+ protected void unregister() {
+ if (sDebug) Log.d(TAG, "unregister called");
+ mRemoteControlClient.editMetadata(true).apply();
+ mRemoteControlClient.setTransportControlFlags(0);
+ mAudioManager.abandonAudioFocus(mAudioFocusListener);
+ mAudioManager.unregisterMediaButtonEventReceiver(mMediaEventReceiver);
+ mAudioManager.unregisterRemoteControlClient(mRemoteControlClient);
+ mRemoteControlClient = null;
+ }
+
+ protected void updatePlaybackState(int state) {
+ if (mRemoteControlClient != null) mRemoteControlClient.setPlaybackState(state);
+ }
+
+ protected int getTransportControlFlags() {
+ return android.media.RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE
+ | android.media.RemoteControlClient.FLAG_KEY_MEDIA_STOP;
+ }
+
+ private static class AudioFocusListener implements OnAudioFocusChangeListener {
+ @Override
+ public void onAudioFocusChange(int focusChange) {
+ // Do nothing, the listener is only used to later abandon audio focus.
+ }
+ }
+
+ // TODO(aberent): Investigate moving some or all of the MediaRouterController.Listener
+ // implementations to TransportControl. See http://crbug/354490.
+ @Override
+ public void onRouteSelected(String name, MediaRouteController mediaRouteController) {
+ setScreenName(name);
+ }
+
+ @Override
+ public void onRouteUnselected(MediaRouteController mediaRouteController) {
+ hide();
+ }
+
+ @Override
+ public void onPrepared(MediaRouteController mediaRouteController) {
+ }
+
+ @Override
+ public void onError(int error, String errorMessage) {
+ // Stop the session for all errors
+ hide();
+ }
+
+ @Override
+ public void onDurationUpdated(int durationMillis) {
+ RemoteVideoInfo videoInfo = new RemoteVideoInfo(getVideoInfo());
+ videoInfo.durationMillis = durationMillis;
+ setVideoInfo(videoInfo);
+ }
+
+ @Override
+ public void onPositionChanged(int positionMillis) {
+ RemoteVideoInfo videoInfo = new RemoteVideoInfo(getVideoInfo());
+ videoInfo.currentTimeMillis = positionMillis;
+ setVideoInfo(videoInfo);
+ }
+
+ @Override
+ public void onTitleChanged(String title) {
+ RemoteVideoInfo videoInfo = new RemoteVideoInfo(getVideoInfo());
+ videoInfo.title = title;
+ setVideoInfo(videoInfo);
+ }
+
+ @Override
+ protected boolean isPlaying() {
+ return mIsPlaying;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698