| Index: chrome/android/java/src/org/chromium/chrome/browser/media/remote/LockScreenTransportControl.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/remote/LockScreenTransportControl.java b/chrome/android/java/src/org/chromium/chrome/browser/media/remote/LockScreenTransportControl.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..04488c3c5a2babde7a4470009d77be682ad452f9
|
| --- /dev/null
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/remote/LockScreenTransportControl.java
|
| @@ -0,0 +1,177 @@
|
| +// 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.content.BroadcastReceiver;
|
| +import android.content.Context;
|
| +import android.content.Intent;
|
| +import android.util.Log;
|
| +import android.view.KeyEvent;
|
| +
|
| +import org.chromium.base.CommandLine;
|
| +import org.chromium.base.VisibleForTesting;
|
| +import org.chromium.chrome.ChromeSwitches;
|
| +import org.chromium.chrome.browser.media.remote.RemoteVideoInfo.PlayerState;
|
| +
|
| +import java.util.Set;
|
| +
|
| +import javax.annotation.Nullable;
|
| +
|
| +/**
|
| + * An abstract base class and factory for {@link TransportControl}s that are displayed on the lock
|
| + * screen.
|
| + */
|
| +public abstract class LockScreenTransportControl
|
| + extends TransportControl implements MediaRouteController.UiListener {
|
| + private static final String TAG = "LockScreenTransportControl";
|
| +
|
| + private static LockScreenTransportControl sInstance;
|
| +
|
| + private MediaRouteController mMediaRouteController = null;
|
| +
|
| + private static final Object LOCK = new Object();
|
| +
|
| + private static boolean sDebug;
|
| +
|
| + // Needed to get round findbugs complaints.
|
| + private static void setSDebug() {
|
| + sDebug = CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_CAST_DEBUG_LOGS);
|
| + }
|
| +
|
| + public LockScreenTransportControl() {
|
| + setSDebug();
|
| + }
|
| +
|
| + /**
|
| + * {@link BroadcastReceiver} that receives the media button events from the lock screen and
|
| + * forwards the messages on to the {@link TransportControl}'s listeners.
|
| + *
|
| + * Ideally this class should be private, but public is required to create as a
|
| + * BroadcastReceiver.
|
| + */
|
| + public static class MediaButtonIntentReceiver extends BroadcastReceiver {
|
| + @Override
|
| + public void onReceive(Context context, Intent intent) {
|
| + if (sDebug) Log.d(TAG, "Received intent: " + intent);
|
| + if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
|
| + KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
|
| + LockScreenTransportControl control = LockScreenTransportControl.getIfExists();
|
| + if (control == null) {
|
| + Log.w(TAG, "Event received when no LockScreenTransportControl exists");
|
| + return;
|
| + }
|
| + Set<Listener> listeners = control.getListeners();
|
| +
|
| + // Ignore ACTION_DOWN. We'll get an ACTION_UP soon enough!
|
| + if (event.getAction() == KeyEvent.ACTION_DOWN) return;
|
| +
|
| + switch (event.getKeyCode()) {
|
| + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
| + for (Listener listener : listeners) {
|
| + if (control.isPlaying()) {
|
| + listener.onPause();
|
| + } else {
|
| + listener.onPlay();
|
| + }
|
| + }
|
| + break;
|
| + case KeyEvent.KEYCODE_MEDIA_STOP:
|
| + for (Listener listener : listeners)
|
| + listener.onStop();
|
| + break;
|
| + default:
|
| + Log.w(TAG, "Unrecognized event: " + event);
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| +
|
| + /**
|
| + * @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 LockScreenTransportControl getOrCreate(Context context,
|
| + @Nullable MediaRouteController mediaRouteController) {
|
| + Log.d(TAG, "getOrCreate called");
|
| + synchronized (LOCK) {
|
| + if (sInstance == null) {
|
| +
|
| + // TODO(aberent) Once the Android L SDK is formally released we should disable the
|
| + // lock screen for L onwards. On L the lock screen is replaced by lock screen
|
| + // notifications.
|
| + if (!enabled()) {
|
| + return null;
|
| + } else if (android.os.Build.VERSION.SDK_INT < 16) {
|
| + sInstance = new LockScreenTransportControlV14(context);
|
| + } else if (android.os.Build.VERSION.SDK_INT < 18) {
|
| + sInstance = new LockScreenTransportControlV16(context);
|
| + } else {
|
| + sInstance = new LockScreenTransportControlV18(context);
|
| + }
|
| + }
|
| + sInstance.setVideoInfo(
|
| + new RemoteVideoInfo(null, 0, RemoteVideoInfo.PlayerState.STOPPED, 0, null));
|
| +
|
| + sInstance.mMediaRouteController = mediaRouteController;
|
| + return sInstance;
|
| + }
|
| + }
|
| +
|
| + protected MediaRouteController getMediaRouteController() {
|
| + return mMediaRouteController;
|
| + }
|
| +
|
| + /**
|
| + * TODO(aberent) From PlayMovies code. Either remove this and get V14/15 working or combine V14
|
| + * and V16 versions only and change getOrCreate to only support V16 or later.
|
| + *
|
| + * @return true if lock screen transport controls should be used on this device.
|
| + */
|
| + private static boolean enabled() {
|
| + // Lock screen controls don't work well prior to JB, see b/9101584
|
| + return android.os.Build.VERSION.SDK_INT >= 16;
|
| + }
|
| +
|
| + /**
|
| + * Internal function for callbacks that need to get the current lock screen statically, but
|
| + * don't want to create a new one.
|
| + *
|
| + * @return the current lock screen, if any.
|
| + */
|
| + @VisibleForTesting
|
| + static LockScreenTransportControl getIfExists() {
|
| + return sInstance;
|
| + }
|
| +
|
| + @Override
|
| + public void hide() {
|
| + onLockScreenPlaybackStateChanged(null, PlayerState.STOPPED);
|
| + mMediaRouteController.removeUiListener(this);
|
| + }
|
| +
|
| + @Override
|
| + public void show(PlayerState initialState) {
|
| + mMediaRouteController.addUiListener(this);
|
| + onLockScreenPlaybackStateChanged(null, initialState);
|
| + }
|
| +
|
| + @Override
|
| + public void setRouteController(MediaRouteController controller) {
|
| + synchronized (LOCK) {
|
| + if (sInstance != null) sInstance.mMediaRouteController = controller;
|
| + }
|
| + }
|
| +
|
| + @Override
|
| + public void onPlaybackStateChanged(PlayerState oldState, PlayerState newState) {
|
| + onLockScreenPlaybackStateChanged(oldState, newState);
|
| + }
|
| +
|
| + protected abstract void onLockScreenPlaybackStateChanged(PlayerState oldState,
|
| + PlayerState newState);
|
| +
|
| + protected abstract boolean isPlaying();
|
| +}
|
|
|