summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorRoboErik <epastern@google.com>2014-02-24 18:02:08 -0800
committerRoboErik <epastern@google.com>2014-03-12 15:09:42 -0700
commit8ae0f34db936a649ddaf9cdd086c224f6514efeb (patch)
tree6699d2481e68c205dc62a35c1c434f05d721c03f /tests
parent1ebd4ad6cd645830d1eca12b2108c6ab4327c108 (diff)
downloadframeworks_base-8ae0f34db936a649ddaf9cdd086c224f6514efeb.zip
frameworks_base-8ae0f34db936a649ddaf9cdd086c224f6514efeb.tar.gz
frameworks_base-8ae0f34db936a649ddaf9cdd086c224f6514efeb.tar.bz2
Adds a TransportController and TransportPerformer to session
This makes transport controls a primitive interface on sessions with a way to create the performer, register callbacks, and send commands and updates between controllers and performers. This still needs some cleanup but has been tested with OneMedia. Change-Id: I373d35f7ccc383b8421bd14044457467d80425f3
Diffstat (limited to 'tests')
-rw-r--r--tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java66
-rw-r--r--tests/OneMedia/src/com/android/onemedia/OnePlayerService.java18
-rw-r--r--tests/OneMedia/src/com/android/onemedia/PlayerController.java78
-rw-r--r--tests/OneMedia/src/com/android/onemedia/PlayerService.java61
-rw-r--r--tests/OneMedia/src/com/android/onemedia/PlayerSession.java108
-rw-r--r--tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java5
6 files changed, 286 insertions, 50 deletions
diff --git a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
index 7ff81e4..3114ca9 100644
--- a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
+++ b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
@@ -1,7 +1,24 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.android.onemedia;
import android.app.Activity;
+import android.media.session.MediaMetadata;
+import android.media.session.PlaybackState;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
@@ -79,10 +96,10 @@ public class OnePlayerActivity extends Activity {
switch (v.getId()) {
case R.id.play_button:
Log.d(TAG, "Play button pressed, in state " + mPlaybackState);
- if (mPlaybackState == Renderer.STATE_PAUSED
- || mPlaybackState == Renderer.STATE_ENDED) {
+ if (mPlaybackState == PlaybackState.PLAYSTATE_PAUSED
+ || mPlaybackState == PlaybackState.PLAYSTATE_STOPPED) {
mPlayer.play();
- } else if (mPlaybackState == Renderer.STATE_PLAYING) {
+ } else if (mPlaybackState == PlaybackState.PLAYSTATE_PLAYING) {
mPlayer.pause();
}
break;
@@ -97,48 +114,55 @@ public class OnePlayerActivity extends Activity {
private PlayerController.Listener mListener = new PlayerController.Listener() {
@Override
- public void onSessionStateChange(int state) {
- mPlaybackState = state;
+ public void onPlaybackStateChange(PlaybackState state) {
+ mPlaybackState = state.getState();
boolean enablePlay = false;
+ StringBuilder statusBuilder = new StringBuilder();
switch (mPlaybackState) {
- case Renderer.STATE_PLAYING:
- mStatusView.setText("playing");
+ case PlaybackState.PLAYSTATE_PLAYING:
+ statusBuilder.append("playing");
mPlayButton.setText("Pause");
enablePlay = true;
break;
- case Renderer.STATE_PAUSED:
- mStatusView.setText("paused");
+ case PlaybackState.PLAYSTATE_PAUSED:
+ statusBuilder.append("paused");
mPlayButton.setText("Play");
enablePlay = true;
break;
- case Renderer.STATE_ENDED:
- mStatusView.setText("ended");
+ case PlaybackState.PLAYSTATE_STOPPED:
+ statusBuilder.append("ended");
mPlayButton.setText("Play");
enablePlay = true;
break;
- case Renderer.STATE_ERROR:
- mStatusView.setText("error");
+ case PlaybackState.PLAYSTATE_ERROR:
+ statusBuilder.append("error: ").append(state.getErrorMessage());
break;
- case Renderer.STATE_PREPARING:
- mStatusView.setText("preparing");
+ case PlaybackState.PLAYSTATE_BUFFERING:
+ statusBuilder.append("buffering");
break;
- case Renderer.STATE_READY:
- mStatusView.setText("ready");
- break;
- case Renderer.STATE_STOPPED:
- mStatusView.setText("stopped");
+ case PlaybackState.PLAYSTATE_NONE:
+ statusBuilder.append("none");
break;
+ default:
+ statusBuilder.append(mPlaybackState);
}
+ statusBuilder.append(" -- At position: ").append(state.getPosition());
+ mStatusView.setText(statusBuilder.toString());
mPlayButton.setEnabled(enablePlay);
}
@Override
- public void onPlayerStateChange(int state) {
+ public void onConnectionStateChange(int state) {
if (state == PlayerController.STATE_DISCONNECTED) {
setControlsEnabled(false);
} else if (state == PlayerController.STATE_CONNECTED) {
setControlsEnabled(true);
}
}
+
+ @Override
+ public void onMetadataChange(MediaMetadata metadata) {
+ Log.d(TAG, "Metadata update! Title: " + metadata);
+ }
};
}
diff --git a/tests/OneMedia/src/com/android/onemedia/OnePlayerService.java b/tests/OneMedia/src/com/android/onemedia/OnePlayerService.java
index 01610cd..573f7ff 100644
--- a/tests/OneMedia/src/com/android/onemedia/OnePlayerService.java
+++ b/tests/OneMedia/src/com/android/onemedia/OnePlayerService.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.android.onemedia;
import android.content.Context;
@@ -5,9 +20,6 @@ import android.content.Intent;
import java.util.ArrayList;
-/**
- * TODO: Insert description here. (generated by epastern)
- */
public class OnePlayerService extends PlayerService {
private static final String TAG = "OnePlayerService";
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerController.java b/tests/OneMedia/src/com/android/onemedia/PlayerController.java
index 3f15db5..e831ec6 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerController.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerController.java
@@ -1,8 +1,27 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.android.onemedia;
import android.media.session.MediaController;
+import android.media.session.MediaMetadata;
import android.media.session.MediaSessionManager;
+import android.media.session.PlaybackState;
+import android.media.session.TransportController;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
@@ -11,22 +30,23 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;
-import android.view.KeyEvent;
import com.android.onemedia.playback.RequestUtils;
public class PlayerController {
- private static final String TAG = "PlayerSession";
+ private static final String TAG = "PlayerController";
public static final int STATE_DISCONNECTED = 0;
public static final int STATE_CONNECTED = 1;
protected MediaController mController;
protected IPlayerService mBinder;
+ protected TransportController mTransportControls;
private final Intent mServiceIntent;
private Context mContext;
private Listener mListener;
+ private TransportListener mTransportListener = new TransportListener();
private SessionCallback mControllerCb;
private MediaSessionManager mManager;
private Handler mHandler = new Handler();
@@ -52,7 +72,7 @@ public class PlayerController {
Log.d(TAG, "Listener set to " + listener + " session is " + mController);
if (mListener != null) {
mHandler = new Handler();
- mListener.onPlayerStateChange(
+ mListener.onConnectionStateChange(
mController == null ? STATE_DISCONNECTED : STATE_CONNECTED);
}
}
@@ -70,11 +90,15 @@ public class PlayerController {
}
public void play() {
- mController.sendMediaButton(KeyEvent.KEYCODE_MEDIA_PLAY);
+ if (mTransportControls != null) {
+ mTransportControls.play();
+ }
}
public void pause() {
- mController.sendMediaButton(KeyEvent.KEYCODE_MEDIA_PAUSE);
+ if (mTransportControls != null) {
+ mTransportControls.pause();
+ }
}
public void setContent(String source) {
@@ -113,10 +137,11 @@ public class PlayerController {
}
mBinder = null;
mController = null;
+ mTransportControls = null;
Log.d(TAG, "Disconnected from PlayerService");
if (mListener != null) {
- mListener.onPlayerStateChange(STATE_DISCONNECTED);
+ mListener.onConnectionStateChange(STATE_DISCONNECTED);
}
}
@@ -125,33 +150,60 @@ public class PlayerController {
mBinder = IPlayerService.Stub.asInterface(service);
Log.d(TAG, "service is " + service + " binder is " + mBinder);
try {
- mController = new MediaController(mBinder.getSessionToken());
+ mController = MediaController.fromToken(mBinder.getSessionToken());
} catch (RemoteException e) {
Log.e(TAG, "Error getting session", e);
return;
}
mController.addCallback(mControllerCb, mHandler);
+ mTransportControls = mController.getTransportController();
+ if (mTransportControls != null) {
+ mTransportControls.addStateListener(mTransportListener);
+ }
Log.d(TAG, "Ready to use PlayerService");
if (mListener != null) {
- mListener.onPlayerStateChange(STATE_CONNECTED);
+ mListener.onConnectionStateChange(STATE_CONNECTED);
+ if (mTransportControls != null) {
+ mListener.onPlaybackStateChange(mTransportControls.getPlaybackState());
+ }
}
}
};
private class SessionCallback extends MediaController.Callback {
@Override
- public void onPlaybackStateChange(int state) {
+ public void onRouteChanged(Bundle route) {
+ // TODO
+ }
+ }
+
+ private class TransportListener extends TransportController.TransportStateListener {
+ @Override
+ public void onPlaybackStateChanged(PlaybackState state) {
+ if (state == null) {
+ return;
+ }
+ Log.d(TAG, "Received playback state change to state " + state.getState());
if (mListener != null) {
- mListener.onSessionStateChange(state);
+ mListener.onPlaybackStateChange(state);
}
}
+
+ @Override
+ public void onMetadataChanged(MediaMetadata metadata) {
+ if (metadata == null) {
+ return;
+ }
+ Log.d(TAG, "Received metadata change, title is "
+ + metadata.getString(MediaMetadata.METADATA_KEY_TITLE));
+ }
}
public interface Listener {
- public void onSessionStateChange(int state);
-
- public void onPlayerStateChange(int state);
+ public void onPlaybackStateChange(PlaybackState state);
+ public void onMetadataChange(MediaMetadata metadata);
+ public void onConnectionStateChange(int state);
}
}
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerService.java b/tests/OneMedia/src/com/android/onemedia/PlayerService.java
index 0b2ba8f..0ad6dd1 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerService.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerService.java
@@ -1,11 +1,28 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.android.onemedia;
import android.app.Service;
import android.content.Intent;
import android.media.session.MediaSessionToken;
+import android.media.session.PlaybackState;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.Log;
import com.android.onemedia.playback.IRequestCallback;
import com.android.onemedia.playback.RequestUtils;
@@ -18,14 +35,19 @@ public class PlayerService extends Service {
private PlayerBinder mBinder;
private PlayerSession mSession;
private Intent mIntent;
+ private boolean mStarted = false;
private ArrayList<IPlayerCallback> mCbs = new ArrayList<IPlayerCallback>();
@Override
public void onCreate() {
+ Log.d(TAG, "onCreate");
mIntent = onCreateServiceIntent();
- mSession = onCreatePlayerController();
- mSession.createSession();
+ if (mSession == null) {
+ mSession = onCreatePlayerController();
+ mSession.createSession();
+ mSession.setListener(mPlayerListener);
+ }
}
@Override
@@ -38,12 +60,31 @@ public class PlayerService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.d(TAG, "onStartCommand");
return START_STICKY;
}
@Override
public void onDestroy() {
+ Log.d(TAG, "onDestroy");
mSession.onDestroy();
+ mSession = null;
+ }
+
+ public void onPlaybackStarted() {
+ if (!mStarted) {
+ Log.d(TAG, "Starting self");
+ startService(onCreateServiceIntent());
+ mStarted = true;
+ }
+ }
+
+ public void onPlaybackEnded() {
+ if (mStarted) {
+ Log.d(TAG, "Stopping self");
+ stopSelf();
+ mStarted = false;
+ }
}
protected Intent onCreateServiceIntent() {
@@ -58,6 +99,21 @@ public class PlayerService extends Service {
return null;
}
+ private final PlayerSession.Listener mPlayerListener = new PlayerSession.Listener() {
+ @Override
+ public void onPlayStateChanged(PlaybackState state) {
+ switch (state.getState()) {
+ case PlaybackState.PLAYSTATE_PLAYING:
+ onPlaybackStarted();
+ break;
+ case PlaybackState.PLAYSTATE_STOPPED:
+ case PlaybackState.PLAYSTATE_ERROR:
+ onPlaybackEnded();
+ break;
+ }
+ }
+ };
+
public class PlayerBinder extends IPlayerService.Stub {
@Override
public void sendRequest(String action, Bundle params, IRequestCallback cb) {
@@ -94,7 +150,6 @@ public class PlayerService extends Service {
@Override
public MediaSessionToken getSessionToken() throws RemoteException {
- // TODO(epastern): Auto-generated method stub
return mSession.getSessionToken();
}
}
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
index e5fb0d0..a2d7897 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.android.onemedia;
import android.content.Context;
@@ -5,6 +20,8 @@ import android.content.Intent;
import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.media.session.MediaSessionToken;
+import android.media.session.PlaybackState;
+import android.media.session.TransportPerformer;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
@@ -14,14 +31,18 @@ import com.android.onemedia.playback.Renderer;
import com.android.onemedia.playback.RendererFactory;
public class PlayerSession {
- private static final String TAG = "PlayerController";
+ private static final String TAG = "PlayerSession";
protected MediaSession mSession;
protected Context mContext;
protected RendererFactory mRendererFactory;
protected LocalRenderer mRenderer;
- protected ControllerCb mCallback;
- protected RenderListener mRenderListener;
+ protected MediaSession.Callback mCallback;
+ protected Renderer.Listener mRenderListener;
+ protected TransportPerformer mPerformer;
+
+ protected PlaybackState mPlaybackState;
+ protected Listener mListener;
public PlayerSession(Context context) {
mContext = context;
@@ -29,6 +50,9 @@ public class PlayerSession {
mRenderer = new LocalRenderer(context, null);
mCallback = new ControllerCb();
mRenderListener = new RenderListener();
+ mPlaybackState = new PlaybackState();
+ mPlaybackState.setActions(PlaybackState.ACTION_PAUSE
+ | PlaybackState.ACTION_PLAY);
mRenderer.registerListener(mRenderListener);
}
@@ -42,6 +66,10 @@ public class PlayerSession {
Log.d(TAG, "Creating session for package " + mContext.getBasePackageName());
mSession = man.createSession("OneMedia");
mSession.addCallback(mCallback);
+ mPerformer = mSession.setTransportPerformerEnabled();
+ mPerformer.addListener(new TransportListener());
+ mPerformer.setPlaybackState(mPlaybackState);
+ mSession.publish();
}
public void onDestroy() {
@@ -54,6 +82,10 @@ public class PlayerSession {
}
}
+ public void setListener(Listener listener) {
+ mListener = listener;
+ }
+
public MediaSessionToken getSessionToken() {
return mSession.getSessionToken();
}
@@ -66,16 +98,58 @@ public class PlayerSession {
mRenderer.setNextContent(request);
}
- protected class RenderListener implements Renderer.Listener {
+ public interface Listener {
+ public void onPlayStateChanged(PlaybackState state);
+ }
+
+ private class RenderListener implements Renderer.Listener {
@Override
public void onError(int type, int extra, Bundle extras, Throwable error) {
- mSession.setPlaybackState(Renderer.STATE_ERROR);
+ Log.d(TAG, "Sending onError with type " + type + " and extra " + extra);
+ mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR);
+ if (error != null) {
+ mPlaybackState.setErrorMessage(error.getLocalizedMessage());
+ }
+ mPerformer.setPlaybackState(mPlaybackState);
+ if (mListener != null) {
+ mListener.onPlayStateChanged(mPlaybackState);
+ }
}
@Override
public void onStateChanged(int newState) {
- mSession.setPlaybackState(newState);
+ if (newState != Renderer.STATE_ERROR) {
+ mPlaybackState.setErrorMessage(null);
+ }
+ switch (newState) {
+ case Renderer.STATE_ENDED:
+ case Renderer.STATE_STOPPED:
+ mPlaybackState.setState(PlaybackState.PLAYSTATE_STOPPED);
+ break;
+ case Renderer.STATE_INIT:
+ case Renderer.STATE_PREPARING:
+ mPlaybackState.setState(PlaybackState.PLAYSTATE_BUFFERING);
+ break;
+ case Renderer.STATE_ERROR:
+ mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR);
+ break;
+ case Renderer.STATE_PAUSED:
+ mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED);
+ break;
+ case Renderer.STATE_PLAYING:
+ mPlaybackState.setState(PlaybackState.PLAYSTATE_PLAYING);
+ break;
+ default:
+ mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR);
+ mPlaybackState.setErrorMessage("unkown state");
+ break;
+ }
+ mPlaybackState.setPosition(mRenderer.getSeekPosition());
+ mPerformer.setPlaybackState(mPlaybackState);
+ if (mListener != null) {
+ mListener.onPlayStateChanged(mPlaybackState);
+ }
}
@Override
@@ -84,7 +158,13 @@ public class PlayerSession {
@Override
public void onFocusLost() {
- mSession.setPlaybackState(Renderer.STATE_PAUSED);
+ Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED);
+ mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED);
+ mPlaybackState.setPosition(mRenderer.getSeekPosition());
+ mPerformer.setPlaybackState(mPlaybackState);
+ if (mListener != null) {
+ mListener.onPlayStateChanged(mPlaybackState);
+ }
}
@Override
@@ -93,7 +173,7 @@ public class PlayerSession {
}
- protected class ControllerCb extends MediaSession.Callback {
+ private class ControllerCb extends MediaSession.Callback {
@Override
public void onMediaButton(Intent mediaRequestIntent) {
@@ -114,4 +194,16 @@ public class PlayerSession {
}
}
+ private class TransportListener extends TransportPerformer.Listener {
+ @Override
+ public void onPlay() {
+ mRenderer.onPlay();
+ }
+
+ @Override
+ public void onPause() {
+ mRenderer.onPause();
+ }
+ }
+
}
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java b/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
index 7493366..7f62f66 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
@@ -499,11 +499,12 @@ public class LocalRenderer extends Renderer implements OnPreparedListener,
@Override
public boolean onPause() {
MediaPlayer player = mPlayer;
+ // If the user paused us make sure we won't start playing again until
+ // asked to
+ mPlayOnReady = false;
if (player != null && (mState & CAN_PAUSE) != 0) {
player.pause();
setState(STATE_PAUSED);
- } else if ((mState & CAN_READY_PLAY) != 0) {
- mPlayOnReady = false;
} else if (!isPaused()) {
return false;
}