summaryrefslogtreecommitdiffstats
path: root/tests/OneMedia
diff options
context:
space:
mode:
authorRoboErik <epastern@google.com>2014-03-20 13:33:52 -0700
committerRoboErik <epastern@google.com>2014-04-17 15:02:33 -0700
commit07c7077c54717dbbf2c401ea32d00fa6df6d77c6 (patch)
tree49f9e8019caa93c702c6d2d8213767de3d1499c6 /tests/OneMedia
parent46175e152891eabd9051523f2f077de5a5562996 (diff)
downloadframeworks_base-07c7077c54717dbbf2c401ea32d00fa6df6d77c6.zip
frameworks_base-07c7077c54717dbbf2c401ea32d00fa6df6d77c6.tar.gz
frameworks_base-07c7077c54717dbbf2c401ea32d00fa6df6d77c6.tar.bz2
Add RouteProviders to the new Media APIs
Compiles and works with OneMedia. This currently is a rough test of the system for finding, connecting to, and sending messages to routes. This will just connect to the first route it finds when a request to open the route picker is made (and disconnect when another request is made). Change-Id: I5de5521a079471b9e02664be4654c0591dfd9a6d
Diffstat (limited to 'tests/OneMedia')
-rw-r--r--tests/OneMedia/AndroidManifest.xml9
-rw-r--r--tests/OneMedia/res/layout/activity_one_player.xml6
-rw-r--r--tests/OneMedia/res/values/strings.xml1
-rw-r--r--tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl4
-rw-r--r--tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl4
-rw-r--r--tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java12
-rw-r--r--tests/OneMedia/src/com/android/onemedia/PlayerController.java21
-rw-r--r--tests/OneMedia/src/com/android/onemedia/PlayerService.java4
-rw-r--r--tests/OneMedia/src/com/android/onemedia/PlayerSession.java100
-rw-r--r--tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java17
-rw-r--r--tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java15
-rw-r--r--tests/OneMedia/src/com/android/onemedia/playback/OneMRPRenderer.java44
-rw-r--r--tests/OneMedia/src/com/android/onemedia/playback/PlaybackError.java15
-rw-r--r--tests/OneMedia/src/com/android/onemedia/playback/Renderer.java48
-rw-r--r--tests/OneMedia/src/com/android/onemedia/playback/RendererFactory.java22
-rw-r--r--tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java15
-rw-r--r--tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java204
17 files changed, 481 insertions, 60 deletions
diff --git a/tests/OneMedia/AndroidManifest.xml b/tests/OneMedia/AndroidManifest.xml
index 7d6ba1d..504d471 100644
--- a/tests/OneMedia/AndroidManifest.xml
+++ b/tests/OneMedia/AndroidManifest.xml
@@ -25,6 +25,15 @@
android:name="com.android.onemedia.OnePlayerService"
android:exported="false"
android:process="com.android.onemedia.service" />
+ <service
+ android:name=".provider.OneMediaRouteProvider"
+ android:permission="android.permission.BIND_ROUTE_PROVIDER"
+ android:exported="true"
+ android:process="com.android.onemedia.provider">
+ <intent-filter>
+ <action android:name="com.android.media.session.MediaRouteProvider" />
+ </intent-filter>
+ </service>
</application>
</manifest>
diff --git a/tests/OneMedia/res/layout/activity_one_player.xml b/tests/OneMedia/res/layout/activity_one_player.xml
index 4208355..516562f 100644
--- a/tests/OneMedia/res/layout/activity_one_player.xml
+++ b/tests/OneMedia/res/layout/activity_one_player.xml
@@ -53,6 +53,12 @@
android:layout_weight="1"
android:text="@string/play_button" />
</LinearLayout>
+ <Button
+ android:id="@+id/route_button"
+ style="@style/BottomBarButton"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/route_button" />
<TextView
android:id="@+id/status"
android:layout_width="match_parent"
diff --git a/tests/OneMedia/res/values/strings.xml b/tests/OneMedia/res/values/strings.xml
index 1b0cebb..3735c8d 100644
--- a/tests/OneMedia/res/values/strings.xml
+++ b/tests/OneMedia/res/values/strings.xml
@@ -7,6 +7,7 @@
<string name="start_button">Start</string>
<string name="play_button">Play</string>
+ <string name="route_button">Change route</string>
<string name="media_content_hint">Content</string>
<string name="media_next_hint">Next content</string>
<string name="has_video">Is video</string>
diff --git a/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl b/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl
index 2b14384..189fa6a 100644
--- a/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl
+++ b/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl
@@ -15,8 +15,8 @@
package com.android.onemedia;
-import android.media.session.MediaSessionToken;
+import android.media.session.SessionToken;
interface IPlayerCallback {
- void onSessionChanged(in MediaSessionToken session);
+ void onSessionChanged(in SessionToken session);
} \ No newline at end of file
diff --git a/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl b/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl
index efdbe9a..15ea25f 100644
--- a/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl
+++ b/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl
@@ -15,14 +15,14 @@
package com.android.onemedia;
-import android.media.session.MediaSessionToken;
+import android.media.session.SessionToken;
import android.os.Bundle;
import com.android.onemedia.IPlayerCallback;
import com.android.onemedia.playback.IRequestCallback;
interface IPlayerService {
- MediaSessionToken getSessionToken();
+ SessionToken getSessionToken();
void registerCallback(in IPlayerCallback cb);
void unregisterCallback(in IPlayerCallback cb);
void sendRequest(String action, in Bundle params, in IRequestCallback cb);
diff --git a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
index 3114ca9..b9a6470 100644
--- a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
+++ b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
@@ -37,6 +37,7 @@ public class OnePlayerActivity extends Activity {
private Button mStartButton;
private Button mPlayButton;
+ private Button mRouteButton;
private TextView mStatusView;
private EditText mContentText;
@@ -54,6 +55,7 @@ public class OnePlayerActivity extends Activity {
mStartButton = (Button) findViewById(R.id.start_button);
mPlayButton = (Button) findViewById(R.id.play_button);
+ mRouteButton = (Button) findViewById(R.id.route_button);
mStatusView = (TextView) findViewById(R.id.status);
mContentText = (EditText) findViewById(R.id.content);
mNextContentText = (EditText) findViewById(R.id.next_content);
@@ -61,6 +63,7 @@ public class OnePlayerActivity extends Activity {
mStartButton.setOnClickListener(mButtonListener);
mPlayButton.setOnClickListener(mButtonListener);
+ mRouteButton.setOnClickListener(mButtonListener);
}
@@ -107,6 +110,9 @@ public class OnePlayerActivity extends Activity {
Log.d(TAG, "Start button pressed, in state " + mPlaybackState);
mPlayer.setContent(mContentText.getText().toString());
break;
+ case R.id.route_button:
+ mPlayer.showRoutePicker();
+ break;
}
}
@@ -117,6 +123,7 @@ public class OnePlayerActivity extends Activity {
public void onPlaybackStateChange(PlaybackState state) {
mPlaybackState = state.getState();
boolean enablePlay = false;
+ boolean enableControls = true;
StringBuilder statusBuilder = new StringBuilder();
switch (mPlaybackState) {
case PlaybackState.PLAYSTATE_PLAYING:
@@ -143,12 +150,17 @@ public class OnePlayerActivity extends Activity {
case PlaybackState.PLAYSTATE_NONE:
statusBuilder.append("none");
break;
+ case PlaybackState.PLAYSTATE_CONNECTING:
+ statusBuilder.append("connecting");
+ enableControls = false;
+ break;
default:
statusBuilder.append(mPlaybackState);
}
statusBuilder.append(" -- At position: ").append(state.getPosition());
mStatusView.setText(statusBuilder.toString());
mPlayButton.setEnabled(enablePlay);
+ setControlsEnabled(enableControls);
}
@Override
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerController.java b/tests/OneMedia/src/com/android/onemedia/PlayerController.java
index e831ec6..e3f5c0c 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerController.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerController.java
@@ -16,9 +16,10 @@
*/
package com.android.onemedia;
-import android.media.session.MediaController;
+import android.media.session.SessionController;
import android.media.session.MediaMetadata;
-import android.media.session.MediaSessionManager;
+import android.media.session.RouteInfo;
+import android.media.session.SessionManager;
import android.media.session.PlaybackState;
import android.media.session.TransportController;
import android.os.Bundle;
@@ -39,7 +40,7 @@ public class PlayerController {
public static final int STATE_DISCONNECTED = 0;
public static final int STATE_CONNECTED = 1;
- protected MediaController mController;
+ protected SessionController mController;
protected IPlayerService mBinder;
protected TransportController mTransportControls;
@@ -48,7 +49,7 @@ public class PlayerController {
private Listener mListener;
private TransportListener mTransportListener = new TransportListener();
private SessionCallback mControllerCb;
- private MediaSessionManager mManager;
+ private SessionManager mManager;
private Handler mHandler = new Handler();
private boolean mResumed;
@@ -61,7 +62,7 @@ public class PlayerController {
mServiceIntent = serviceIntent;
}
mControllerCb = new SessionCallback();
- mManager = (MediaSessionManager) context
+ mManager = (SessionManager) context
.getSystemService(Context.MEDIA_SESSION_SERVICE);
mResumed = false;
@@ -121,6 +122,10 @@ public class PlayerController {
}
}
+ public void showRoutePicker() {
+ mController.showRoutePicker();
+ }
+
private void unbindFromService() {
mContext.unbindService(mServiceConnection);
}
@@ -150,7 +155,7 @@ public class PlayerController {
mBinder = IPlayerService.Stub.asInterface(service);
Log.d(TAG, "service is " + service + " binder is " + mBinder);
try {
- mController = MediaController.fromToken(mBinder.getSessionToken());
+ mController = SessionController.fromToken(mBinder.getSessionToken());
} catch (RemoteException e) {
Log.e(TAG, "Error getting session", e);
return;
@@ -171,9 +176,9 @@ public class PlayerController {
}
};
- private class SessionCallback extends MediaController.Callback {
+ private class SessionCallback extends SessionController.Callback {
@Override
- public void onRouteChanged(Bundle route) {
+ public void onRouteChanged(RouteInfo route) {
// TODO
}
}
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerService.java b/tests/OneMedia/src/com/android/onemedia/PlayerService.java
index 0ad6dd1..8b53ddf 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerService.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerService.java
@@ -17,7 +17,7 @@ package com.android.onemedia;
import android.app.Service;
import android.content.Intent;
-import android.media.session.MediaSessionToken;
+import android.media.session.SessionToken;
import android.media.session.PlaybackState;
import android.os.Bundle;
import android.os.IBinder;
@@ -149,7 +149,7 @@ public class PlayerService extends Service {
}
@Override
- public MediaSessionToken getSessionToken() throws RemoteException {
+ public SessionToken getSessionToken() throws RemoteException {
return mSession.getSessionToken();
}
}
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
index a2d7897..5dc3904 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
@@ -17,9 +17,13 @@ package com.android.onemedia;
import android.content.Context;
import android.content.Intent;
-import android.media.session.MediaSession;
-import android.media.session.MediaSessionManager;
-import android.media.session.MediaSessionToken;
+import android.media.session.Route;
+import android.media.session.RouteInfo;
+import android.media.session.RouteOptions;
+import android.media.session.RoutePlaybackControls;
+import android.media.session.Session;
+import android.media.session.SessionManager;
+import android.media.session.SessionToken;
import android.media.session.PlaybackState;
import android.media.session.TransportPerformer;
import android.os.Bundle;
@@ -27,41 +31,55 @@ import android.util.Log;
import android.view.KeyEvent;
import com.android.onemedia.playback.LocalRenderer;
+import com.android.onemedia.playback.OneMRPRenderer;
import com.android.onemedia.playback.Renderer;
-import com.android.onemedia.playback.RendererFactory;
+import com.android.onemedia.playback.RequestUtils;
+
+import java.util.ArrayList;
public class PlayerSession {
private static final String TAG = "PlayerSession";
- protected MediaSession mSession;
+ protected Session mSession;
protected Context mContext;
- protected RendererFactory mRendererFactory;
- protected LocalRenderer mRenderer;
- protected MediaSession.Callback mCallback;
+ protected Renderer mRenderer;
+ protected Session.Callback mCallback;
protected Renderer.Listener mRenderListener;
protected TransportPerformer mPerformer;
protected PlaybackState mPlaybackState;
protected Listener mListener;
+ protected ArrayList<RouteOptions> mRouteOptions;
+ protected Route mRoute;
+ protected RoutePlaybackControls mRouteControls;
+ protected RouteListener mRouteListener;
+
+ private String mContent;
public PlayerSession(Context context) {
mContext = context;
- mRendererFactory = new RendererFactory();
mRenderer = new LocalRenderer(context, null);
- mCallback = new ControllerCb();
+ mCallback = new SessionCb();
mRenderListener = new RenderListener();
mPlaybackState = new PlaybackState();
mPlaybackState.setActions(PlaybackState.ACTION_PAUSE
| PlaybackState.ACTION_PLAY);
mRenderer.registerListener(mRenderListener);
+
+ // TODO need an easier way to build route options
+ mRouteOptions = new ArrayList<RouteOptions>();
+ RouteOptions.Builder bob = new RouteOptions.Builder();
+ bob.addInterface(RoutePlaybackControls.NAME);
+ mRouteOptions.add(bob.build());
+ mRouteListener = new RouteListener();
}
public void createSession() {
if (mSession != null) {
mSession.release();
}
- MediaSessionManager man = (MediaSessionManager) mContext
+ SessionManager man = (SessionManager) mContext
.getSystemService(Context.MEDIA_SESSION_SERVICE);
Log.d(TAG, "Creating session for package " + mContext.getBasePackageName());
mSession = man.createSession("OneMedia");
@@ -69,6 +87,7 @@ public class PlayerSession {
mPerformer = mSession.setTransportPerformerEnabled();
mPerformer.addListener(new TransportListener());
mPerformer.setPlaybackState(mPlaybackState);
+ mSession.setRouteOptions(mRouteOptions);
mSession.publish();
}
@@ -86,18 +105,24 @@ public class PlayerSession {
mListener = listener;
}
- public MediaSessionToken getSessionToken() {
+ public SessionToken getSessionToken() {
return mSession.getSessionToken();
}
public void setContent(Bundle request) {
mRenderer.setContent(request);
+ mContent = request.getString(RequestUtils.EXTRA_KEY_SOURCE);
}
public void setNextContent(Bundle request) {
mRenderer.setNextContent(request);
}
+ private void updateState(int newState) {
+ mPlaybackState.setState(newState);
+ mPerformer.setPlaybackState(mPlaybackState);
+ }
+
public interface Listener {
public void onPlayStateChanged(PlaybackState state);
}
@@ -145,7 +170,11 @@ public class PlayerSession {
mPlaybackState.setErrorMessage("unkown state");
break;
}
- mPlaybackState.setPosition(mRenderer.getSeekPosition());
+ if (mRenderer != null) {
+ mPlaybackState.setPosition(mRenderer.getSeekPosition());
+ } else {
+ mPlaybackState.setPosition(-1);
+ }
mPerformer.setPlaybackState(mPlaybackState);
if (mListener != null) {
mListener.onPlayStateChanged(mPlaybackState);
@@ -173,8 +202,7 @@ public class PlayerSession {
}
- private class ControllerCb extends MediaSession.Callback {
-
+ private class SessionCb extends Session.Callback {
@Override
public void onMediaButton(Intent mediaRequestIntent) {
if (Intent.ACTION_MEDIA_BUTTON.equals(mediaRequestIntent.getAction())) {
@@ -192,6 +220,40 @@ public class PlayerSession {
}
}
}
+
+ @Override
+ public void onRequestRouteChange(RouteInfo route) {
+ if (mRenderer != null) {
+ mRenderer.onStop();
+ }
+ if (route == null) {
+ // Use local route
+ mRoute = null;
+ mRenderer = new LocalRenderer(mContext, null);
+ mRenderer.registerListener(mRenderListener);
+ updateState(PlaybackState.PLAYSTATE_NONE);
+ } else {
+ // Use remote route
+ mSession.connect(route, mRouteOptions.get(0));
+ mRenderer = null;
+ updateState(PlaybackState.PLAYSTATE_CONNECTING);
+ }
+ }
+
+ @Override
+ public void onRouteConnected(Route route) {
+ mRoute = route;
+ mRouteControls = RoutePlaybackControls.from(route);
+ mRouteControls.addListener(mRouteListener);
+ Log.d(TAG, "Connected to route, registering listener");
+ mRenderer = new OneMRPRenderer(mRouteControls);
+ updateState(PlaybackState.PLAYSTATE_NONE);
+ }
+
+ @Override
+ public void onRouteDisconnected(Route route, int reason) {
+
+ }
}
private class TransportListener extends TransportPerformer.Listener {
@@ -206,4 +268,12 @@ public class PlayerSession {
}
}
+ private class RouteListener extends RoutePlaybackControls.Listener {
+ @Override
+ public void onPlaybackStateChange(int state) {
+ Log.d(TAG, "Updating state to " + state);
+ updateState(state);
+ }
+ }
+
}
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java b/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
index 7f62f66..c8a8d6c 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.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.playback;
import org.apache.http.Header;
@@ -370,6 +385,8 @@ public class LocalRenderer extends Renderer implements OnPreparedListener,
* Prepares the player for the given playback request. If the holder is null
* it is assumed this is an audio only source. If playOnReady is set to true
* the media will begin playing as soon as it can.
+ *
+ * @see RequestUtils for the set of valid keys.
*/
public void setContent(Bundle request, SurfaceHolder holder) {
String source = request.getString(RequestUtils.EXTRA_KEY_SOURCE);
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java b/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java
index f9e6794..05516d2 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.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.playback;
import android.os.Bundle;
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/OneMRPRenderer.java b/tests/OneMedia/src/com/android/onemedia/playback/OneMRPRenderer.java
new file mode 100644
index 0000000..9b0a2b2
--- /dev/null
+++ b/tests/OneMedia/src/com/android/onemedia/playback/OneMRPRenderer.java
@@ -0,0 +1,44 @@
+package com.android.onemedia.playback;
+
+import android.media.session.RoutePlaybackControls;
+import android.os.Bundle;
+
+/**
+ * Renderer for communicating with the OneMRP route
+ */
+public class OneMRPRenderer extends Renderer {
+ private final RoutePlaybackControls mControls;
+
+ public OneMRPRenderer(RoutePlaybackControls controls) {
+ super(null, null);
+ mControls = controls;
+ }
+
+ @Override
+ public void setContent(Bundle request) {
+ mControls.playNow(request.getString(RequestUtils.EXTRA_KEY_SOURCE));
+ }
+
+ @Override
+ public boolean onStop() {
+ mControls.pause();
+ return true;
+ }
+
+ @Override
+ public boolean onPlay() {
+ mControls.resume();
+ return true;
+ }
+
+ @Override
+ public boolean onPause() {
+ mControls.pause();
+ return true;
+ }
+
+ @Override
+ public long getSeekPosition() {
+ return -1;
+ }
+}
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/PlaybackError.java b/tests/OneMedia/src/com/android/onemedia/playback/PlaybackError.java
index 72d936c..ac9da23 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/PlaybackError.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/PlaybackError.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.playback;
import android.os.Bundle;
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/Renderer.java b/tests/OneMedia/src/com/android/onemedia/playback/Renderer.java
index 2451bdf..09debcf 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/Renderer.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/Renderer.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.playback;
import android.content.Context;
@@ -77,39 +92,54 @@ public abstract class Renderer {
}
public boolean onPlay() {
- throw new UnsupportedOperationException("play is not supported.");
+ // TODO consider making these log warnings instead of crashes (or
+ // Log.wtf)
+ // throw new UnsupportedOperationException("play is not supported.");
+ return false;
}
public boolean onPause() {
- throw new UnsupportedOperationException("pause is not supported.");
+ // throw new UnsupportedOperationException("pause is not supported.");
+ return false;
}
public boolean onNext() {
- throw new UnsupportedOperationException("next is not supported.");
+ // throw new UnsupportedOperationException("next is not supported.");
+ return false;
}
public boolean onPrevious() {
- throw new UnsupportedOperationException("previous is not supported.");
+ // throw new
+ // UnsupportedOperationException("previous is not supported.");
+ return false;
}
public boolean onStop() {
- throw new UnsupportedOperationException("stop is not supported.");
+ // throw new UnsupportedOperationException("stop is not supported.");
+ return false;
}
public boolean onSeekTo(int time) {
- throw new UnsupportedOperationException("seekTo is not supported.");
+ // throw new UnsupportedOperationException("seekTo is not supported.");
+ return false;
}
public long getSeekPosition() {
- throw new UnsupportedOperationException("getSeekPosition is not supported.");
+ // throw new
+ // UnsupportedOperationException("getSeekPosition is not supported.");
+ return -1;
}
public long getDuration() {
- throw new UnsupportedOperationException("getDuration is not supported.");
+ // throw new
+ // UnsupportedOperationException("getDuration is not supported.");
+ return -1;
}
public int getPlayState() {
- throw new UnsupportedOperationException("getPlayState is not supported.");
+ // throw new
+ // UnsupportedOperationException("getPlayState is not supported.");
+ return 0;
}
public void onDestroy() {
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/RendererFactory.java b/tests/OneMedia/src/com/android/onemedia/playback/RendererFactory.java
deleted file mode 100644
index f333fce..0000000
--- a/tests/OneMedia/src/com/android/onemedia/playback/RendererFactory.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.android.onemedia.playback;
-
-import android.content.Context;
-import android.media.MediaRouter;
-import android.os.Bundle;
-import android.util.Log;
-
-/**
- * TODO: Insert description here.
- */
-public class RendererFactory {
- private static final String TAG = "RendererFactory";
-
- public Renderer createRenderer(MediaRouter.RouteInfo route, Context context, Bundle params) {
- if (route.getPlaybackType() == MediaRouter.RouteInfo.PLAYBACK_TYPE_LOCAL) {
- return new LocalRenderer(context, params);
- }
- Log.e(TAG, "Unable to create renderer for route of playback type "
- + route.getPlaybackType());
- return null;
- }
-}
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java b/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java
index 9b50dad..dd0d982 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.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.playback;
import android.os.Bundle;
diff --git a/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java b/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java
new file mode 100644
index 0000000..6edcd7d
--- /dev/null
+++ b/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java
@@ -0,0 +1,204 @@
+/*
+ * 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.provider;
+
+import android.media.routeprovider.RouteConnection;
+import android.media.routeprovider.RouteInterfaceHandler;
+import android.media.routeprovider.RoutePlaybackControlsHandler;
+import android.media.routeprovider.RouteProviderService;
+import android.media.routeprovider.RouteRequest;
+import android.media.session.RouteInfo;
+import android.media.session.RoutePlaybackControls;
+import android.media.session.RouteInterface;
+import android.media.session.PlaybackState;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.ResultReceiver;
+import android.util.Log;
+
+import com.android.onemedia.playback.LocalRenderer;
+import com.android.onemedia.playback.Renderer;
+import com.android.onemedia.playback.RequestUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Test of MediaRouteProvider. Show a dummy provider with a simple interface for
+ * playing music.
+ */
+public class OneMediaRouteProvider extends RouteProviderService {
+ private static final String TAG = "OneMRP";
+ private static final boolean DEBUG = true;
+
+ private Renderer mRenderer;
+ private RenderListener mRenderListener;
+ private PlaybackState mPlaybackState;
+ private RouteConnection mConnection;
+ private RoutePlaybackControlsHandler mControls;
+ private String mRouteId;
+ private Handler mHandler;
+
+ @Override
+ public void onCreate() {
+ mHandler = new Handler();
+ mRouteId = UUID.randomUUID().toString();
+ mRenderer = new LocalRenderer(this, null);
+ mRenderListener = new RenderListener();
+ mPlaybackState = new PlaybackState();
+ mPlaybackState.setActions(PlaybackState.ACTION_PAUSE
+ | PlaybackState.ACTION_PLAY);
+
+ mRenderer.registerListener(mRenderListener);
+
+ if (DEBUG) {
+ Log.d(TAG, "onCreate, routeId is " + mRouteId);
+ }
+ }
+
+ @Override
+ public List<RouteInfo> getMatchingRoutes(List<RouteRequest> requests) {
+ RouteInfo.Builder bob = new RouteInfo.Builder();
+ bob.setName("OneMedia").setId(mRouteId);
+ // TODO add a helper library for generating route info with the correct
+ // options
+ Log.d(TAG, "Requests:");
+ for (RouteRequest request : requests) {
+ List<String> ifaces = request.getConnectionOptions().getInterfaceNames();
+ Log.d(TAG, " request ifaces:" + ifaces.toString());
+ if (ifaces != null && ifaces.size() == 1
+ && RoutePlaybackControls.NAME.equals(ifaces.get(0))) {
+ bob.addRouteOptions(request.getConnectionOptions());
+ }
+ }
+ ArrayList<RouteInfo> result = new ArrayList<RouteInfo>();
+ if (bob.getOptionsSize() > 0) {
+ RouteInfo info = bob.build();
+ result.add(info);
+ }
+ if (DEBUG) {
+ Log.d(TAG, "getRoutes returning " + result.toString());
+ }
+ return result;
+ }
+
+ @Override
+ public RouteConnection connect(RouteInfo route, RouteRequest request) {
+ if (mConnection != null) {
+ disconnect(mConnection);
+ }
+ RouteConnection connection = new RouteConnection(this, route);
+ mControls = RoutePlaybackControlsHandler.addTo(connection);
+ mControls.addListener(new PlayHandler(mRouteId), mHandler);
+ if (DEBUG) {
+ Log.d(TAG, "Connected to route");
+ }
+ return connection;
+ }
+
+ private class PlayHandler extends RoutePlaybackControlsHandler.Listener {
+ private final String mRouteId;
+
+ public PlayHandler(String routeId) {
+ mRouteId = routeId;
+ }
+
+ @Override
+ public void playNow(String content, ResultReceiver cb) {
+ if (DEBUG) {
+ Log.d(TAG, "Attempting to play " + content);
+ }
+ // look up the route and send a play command to it
+ Bundle bundle = new Bundle();
+ bundle.putString(RequestUtils.EXTRA_KEY_SOURCE, content);
+ mRenderer.setContent(bundle);
+ RouteInterfaceHandler.sendResult(cb, RouteInterface.RESULT_SUCCESS, null);
+ }
+
+ @Override
+ public boolean resume() {
+ mRenderer.onPlay();
+ return true;
+ }
+
+ @Override
+ public boolean pause() {
+ mRenderer.onPause();
+ return true;
+ }
+ }
+
+ private class RenderListener implements Renderer.Listener {
+
+ @Override
+ public void onError(int type, int extra, Bundle extras, Throwable error) {
+ Log.d(TAG, "Sending onError with type " + type + " and extra " + extra);
+ if (mControls != null) {
+ mControls.sendPlaybackChangeEvent(PlaybackState.PLAYSTATE_ERROR);
+ }
+ }
+
+ @Override
+ public void onStateChanged(int 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());
+
+ mControls.sendPlaybackChangeEvent(mPlaybackState.getState());
+ }
+
+ @Override
+ public void onBufferingUpdate(int percent) {
+ }
+
+ @Override
+ public void onFocusLost() {
+ Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED);
+ mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED);
+ mPlaybackState.setPosition(mRenderer.getSeekPosition());
+ }
+
+ @Override
+ public void onNextStarted() {
+ }
+ }
+}