summaryrefslogtreecommitdiffstats
path: root/media/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'media/java/android')
-rw-r--r--media/java/android/media/session/ISession.aidl4
-rw-r--r--media/java/android/media/session/ISessionManager.aidl2
-rw-r--r--media/java/android/media/session/MediaSessionLegacyHelper.java16
-rw-r--r--media/java/android/media/session/Session.java107
-rw-r--r--media/java/android/media/session/SessionManager.java27
5 files changed, 105 insertions, 51 deletions
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
index ca77f04..3ff07d9 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -31,8 +31,8 @@ import android.os.ResultReceiver;
interface ISession {
void sendEvent(String event, in Bundle data);
ISessionController getController();
- void setTransportPerformerEnabled();
- void publish();
+ void setFlags(int flags);
+ void setActive(boolean active);
void destroy();
// These commands are for setting up and communicating with routes
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 84b9a0f..7a8c22e 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -15,6 +15,7 @@
package android.media.session;
+import android.content.ComponentName;
import android.media.session.ISession;
import android.media.session.ISessionCallback;
import android.os.Bundle;
@@ -25,4 +26,5 @@ import android.os.Bundle;
*/
interface ISessionManager {
ISession createSession(String packageName, in ISessionCallback cb, String tag);
+ List<IBinder> getSessions(in ComponentName compName);
} \ No newline at end of file
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index 4ee67d1..c07229d 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -43,7 +43,8 @@ public class MediaSessionLegacyHelper {
private Handler mHandler = new Handler(Looper.getMainLooper());
// The legacy APIs use PendingIntents to register/unregister media button
// receivers and these are associated with RCC.
- private ArrayMap<PendingIntent, SessionHolder> mSessions = new ArrayMap<PendingIntent, SessionHolder>();
+ private ArrayMap<PendingIntent, SessionHolder> mSessions
+ = new ArrayMap<PendingIntent, SessionHolder>();
private MediaSessionLegacyHelper(Context context) {
mSessionManager = (SessionManager) context
@@ -78,6 +79,8 @@ public class MediaSessionLegacyHelper {
}
performer.addListener(listener, mHandler);
holder.mRccListener = listener;
+ holder.mFlags |= Session.FLAG_HANDLES_TRANSPORT_CONTROLS;
+ holder.mSession.setFlags(holder.mFlags);
holder.update();
}
@@ -86,6 +89,8 @@ public class MediaSessionLegacyHelper {
if (holder != null && holder.mRccListener != null) {
holder.mSession.getTransportPerformer().removeListener(holder.mRccListener);
holder.mRccListener = null;
+ holder.mFlags &= ~Session.FLAG_HANDLES_TRANSPORT_CONTROLS;
+ holder.mSession.setFlags(holder.mFlags);
holder.update();
}
}
@@ -98,6 +103,8 @@ public class MediaSessionLegacyHelper {
return;
}
holder.mMediaButtonListener = new MediaButtonListener(pi, context);
+ holder.mFlags |= Session.FLAG_HANDLES_MEDIA_BUTTONS;
+ holder.mSession.setFlags(holder.mFlags);
holder.mSession.getTransportPerformer().addListener(holder.mMediaButtonListener, mHandler);
}
@@ -105,6 +112,9 @@ public class MediaSessionLegacyHelper {
SessionHolder holder = getHolder(pi, false);
if (holder != null && holder.mMediaButtonListener != null) {
holder.mSession.getTransportPerformer().removeListener(holder.mMediaButtonListener);
+ holder.mFlags &= ~Session.FLAG_HANDLES_MEDIA_BUTTONS;
+ holder.mSession.setFlags(holder.mFlags);
+ holder.mMediaButtonListener = null;
holder.update();
}
}
@@ -113,8 +123,7 @@ public class MediaSessionLegacyHelper {
SessionHolder holder = mSessions.get(pi);
if (holder == null && createIfMissing) {
Session session = mSessionManager.createSession(TAG);
- session.setTransportPerformerEnabled();
- session.publish();
+ session.setActive(true);
holder = new SessionHolder(session, pi);
mSessions.put(pi, holder);
}
@@ -193,6 +202,7 @@ public class MediaSessionLegacyHelper {
public final PendingIntent mPi;
public MediaButtonListener mMediaButtonListener;
public TransportPerformer.Listener mRccListener;
+ public int mFlags;
public SessionHolder(Session session, PendingIntent pi) {
mSession = session;
diff --git a/media/java/android/media/session/Session.java b/media/java/android/media/session/Session.java
index 8ccd788..194679e7 100644
--- a/media/java/android/media/session/Session.java
+++ b/media/java/android/media/session/Session.java
@@ -45,12 +45,13 @@ import java.util.List;
* media to multiple routes or to provide finer grain controls of media.
* <p>
* A MediaSession is created by calling
- * {@link SessionManager#createSession(String)}. Once a session is created
- * apps that have the MEDIA_CONTENT_CONTROL permission can interact with the
- * session through {@link SessionManager#getActiveSessions()}. The owner of
- * the session may also use {@link #getSessionToken()} to allow apps without
- * this permission to create a {@link SessionController} to interact with this
- * session.
+ * {@link SessionManager#createSession(String)}. Once a session is created apps
+ * that have the MEDIA_CONTENT_CONTROL permission can interact with the session
+ * through
+ * {@link SessionManager#getActiveSessions(android.content.ComponentName)}. The
+ * owner of the session may also use {@link #getSessionToken()} to allow apps
+ * without this permission to create a {@link SessionController} to interact
+ * with this session.
* <p>
* To receive commands, media keys, and other events a Callback must be set with
* {@link #addCallback(Callback)}.
@@ -63,6 +64,28 @@ import java.util.List;
public final class Session {
private static final String TAG = "Session";
+ /**
+ * Set this flag on the session to indicate that it can handle media button
+ * events.
+ */
+ public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1 << 0;
+
+ /**
+ * Set this flag on the session to indicate that it handles commands through
+ * the {@link TransportPerformer}. The performer can be retrieved by calling
+ * {@link #getTransportPerformer()}.
+ */
+ public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 1 << 1;
+
+ /**
+ * System only flag for a session that needs to have priority over all other
+ * sessions. This flag ensures this session will receive media button events
+ * regardless of the current ordering in the system.
+ *
+ * @hide
+ */
+ public static final int FLAG_EXCLUSIVE_GLOBAL_PRIORITY = 1 << 16;
+
private static final int MSG_MEDIA_BUTTON = 1;
private static final int MSG_COMMAND = 2;
private static final int MSG_ROUTE_CHANGE = 3;
@@ -86,7 +109,7 @@ public final class Session {
private TransportPerformer mPerformer;
private Route mRoute;
- private boolean mPublished = false;;
+ private boolean mActive = false;;
/**
* @hide
@@ -101,6 +124,7 @@ public final class Session {
throw new RuntimeException("Dead object in MediaSessionController constructor: ", e);
}
mSessionToken = new SessionToken(controllerBinder);
+ mPerformer = new TransportPerformer(mBinder);
}
/**
@@ -148,56 +172,57 @@ public final class Session {
}
/**
- * Start using a TransportPerformer with this media session. This must be
- * called before calling publish and cannot be called more than once.
- * Calling this will allow MediaControllers to retrieve a
- * TransportController.
+ * Retrieves the {@link TransportPerformer} for this session. To receive
+ * commands through the performer you must also set the
+ * {@link #FLAG_HANDLES_TRANSPORT_CONTROLS} flag using
+ * {@link #setFlags(int)}.
*
- * @see TransportController
- * @return The TransportPerformer created for this session
+ * @return The performer associated with this session.
*/
- public TransportPerformer setTransportPerformerEnabled() {
- if (mPerformer != null) {
- throw new IllegalStateException("setTransportPerformer can only be called once.");
- }
- if (mPublished) {
- throw new IllegalStateException("setTransportPerformer cannot be called after publish");
- }
-
- mPerformer = new TransportPerformer(mBinder);
- try {
- mBinder.setTransportPerformerEnabled();
- } catch (RemoteException e) {
- Log.wtf(TAG, "Failure in setTransportPerformerEnabled.", e);
- }
+ public TransportPerformer getTransportPerformer() {
return mPerformer;
}
/**
- * Retrieves the TransportPerformer used by this session. If called before
- * {@link #setTransportPerformerEnabled} null will be returned.
+ * Set any flags for the session.
*
- * @return The TransportPerformer associated with this session or null
+ * @param flags The flags to set for this session.
*/
- public TransportPerformer getTransportPerformer() {
- return mPerformer;
+ public void setFlags(int flags) {
+ try {
+ mBinder.setFlags(flags);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Failure in setFlags.", e);
+ }
}
/**
- * Call after you have finished setting up the session. This will make it
- * available to listeners and begin pushing updates to MediaControllers.
- * This can only be called once.
+ * Set if this session is currently active and ready to receive commands. If
+ * set to false your session's controller may not be discoverable. You must
+ * set the session to active before it can start receiving media button
+ * events or transport commands.
+ *
+ * @param active Whether this session is active or not.
*/
- public void publish() {
- if (mPublished) {
- throw new RuntimeException("publish() may only be called once.");
+ public void setActive(boolean active) {
+ if (mActive == active) {
+ return;
}
try {
- mBinder.publish();
+ mBinder.setActive(active);
+ mActive = active;
} catch (RemoteException e) {
- Log.wtf(TAG, "Failure in publish.", e);
+ Log.wtf(TAG, "Failure in setActive.", e);
}
- mPublished = true;
+ }
+
+ /**
+ * Get the current active state of this session.
+ *
+ * @return True if the session is active, false otherwise.
+ */
+ public boolean isActive() {
+ return mActive;
}
/**
diff --git a/media/java/android/media/session/SessionManager.java b/media/java/android/media/session/SessionManager.java
index 15bf0e3..fd022fc 100644
--- a/media/java/android/media/session/SessionManager.java
+++ b/media/java/android/media/session/SessionManager.java
@@ -16,11 +16,13 @@
package android.media.session;
+import android.content.ComponentName;
import android.content.Context;
import android.media.session.ISessionManager;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.service.notification.NotificationListenerService;
import android.util.Log;
import java.util.ArrayList;
@@ -79,12 +81,27 @@ public final class SessionManager {
/**
* Get a list of controllers for all ongoing sessions. This requires the
* android.Manifest.permission.MEDIA_CONTENT_CONTROL permission be held by
- * the calling app.
+ * the calling app. You may also retrieve this list if your app is an
+ * enabled notification listener using the
+ * {@link NotificationListenerService} APIs, in which case you must pass the
+ * {@link ComponentName} of your enabled listener.
*
- * @return a list of controllers for ongoing sessions
+ * @param notificationListener The enabled notification listener component.
+ * May be null.
+ * @return A list of controllers for ongoing sessions
*/
- public List<SessionController> getActiveSessions() {
- // TODO
- return new ArrayList<SessionController>();
+ public List<SessionController> getActiveSessions(ComponentName notificationListener) {
+ ArrayList<SessionController> controllers = new ArrayList<SessionController>();
+ try {
+ List<IBinder> binders = mService.getSessions(notificationListener);
+ for (int i = binders.size() - 1; i >= 0; i--) {
+ SessionController controller = SessionController.fromBinder(ISessionController.Stub
+ .asInterface(binders.get(i)));
+ controllers.add(controller);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to get active sessions: ", e);
+ }
+ return controllers;
}
}