MediaSession2: Initial commit of MediaLibraryService2
MediaLibraryService2 is the new name for the MediaBrowserService Test: Run all MediaComponents tests once Change-Id: I7a1ae20ff59aa4714cff08e43cdabb5b8c557b98
This commit is contained in:
@@ -47,7 +47,7 @@ interface IMediaSession2 {
|
||||
PlaybackState getPlaybackState();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Get browser service specific
|
||||
// Get library service specific
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
oneway void getBrowserRoot(IMediaSession2Callback callback, in Bundle rootHints);
|
||||
|
||||
|
||||
@@ -44,4 +44,9 @@ oneway interface IMediaSession2Callback {
|
||||
// Follow-up TODO: Add similar functions to the session.
|
||||
// TODO(jaewan): Is term 'accepted/rejected' correct? For permission, 'grant' is used.
|
||||
void onConnectionChanged(IMediaSession2 sessionBinder, in Bundle commandGroup);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Browser sepcific
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void onGetRootResult(in Bundle rootHints, String rootMediaId, in Bundle rootExtra);
|
||||
}
|
||||
|
||||
144
media/java/android/media/MediaLibraryService2.java
Normal file
144
media/java/android/media/MediaLibraryService2.java
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2018 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 android.media;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.media.MediaSession2.BuilderBase;
|
||||
import android.media.MediaSession2.ControllerInfo;
|
||||
import android.media.update.ApiLoader;
|
||||
import android.media.update.MediaSessionService2Provider;
|
||||
import android.os.Bundle;
|
||||
import android.service.media.MediaBrowserService.BrowserRoot;
|
||||
|
||||
/**
|
||||
* Base class for media library services.
|
||||
* <p>
|
||||
* Media library services enable applications to browse media content provided by an application
|
||||
* and ask the application to start playing it. They may also be used to control content that
|
||||
* is already playing by way of a {@link MediaSession2}.
|
||||
* <p>
|
||||
* To extend this class, adding followings directly to your {@code AndroidManifest.xml}.
|
||||
* <pre>
|
||||
* <service android:name="component_name_of_your_implementation" >
|
||||
* <intent-filter>
|
||||
* <action android:name="android.media.MediaLibraryService2" />
|
||||
* </intent-filter>
|
||||
* </service></pre>
|
||||
* <p>
|
||||
* A {@link MediaLibraryService2} is extension of {@link MediaSessionService2}. IDs shouldn't
|
||||
* be shared between the {@link MediaSessionService2} and {@link MediaSession2}. By
|
||||
* default, an empty string will be used for ID of the service. If you want to specify an ID,
|
||||
* declare metadata in the manifest as follows.
|
||||
* @hide
|
||||
*/
|
||||
// TODO(jaewan): Unhide
|
||||
public abstract class MediaLibraryService2 extends MediaSessionService2 {
|
||||
/**
|
||||
* This is the interface name that a service implementing a session service should say that it
|
||||
* support -- that is, this is the action it uses for its intent filter.
|
||||
*/
|
||||
public static final String SERVICE_INTERFACE = "android.media.MediaLibraryService2";
|
||||
|
||||
/**
|
||||
* Session for the media library service.
|
||||
*/
|
||||
public class MediaLibrarySession extends MediaSession2 {
|
||||
MediaLibrarySession(Context context, MediaPlayerBase player, String id,
|
||||
SessionCallback callback) {
|
||||
super(context, player, id, callback);
|
||||
}
|
||||
// TODO(jaewan): Place public methods here.
|
||||
}
|
||||
|
||||
public static abstract class MediaLibrarySessionCallback extends MediaSession2.SessionCallback {
|
||||
/**
|
||||
* Called to get the root information for browsing by a particular client.
|
||||
* <p>
|
||||
* The implementation should verify that the client package has permission
|
||||
* to access browse media information before returning the root id; it
|
||||
* should return null if the client is not allowed to access this
|
||||
* information.
|
||||
*
|
||||
* @param controllerInfo information of the controller requesting access to browse media.
|
||||
* @param rootHints An optional bundle of service-specific arguments to send
|
||||
* to the media browser service when connecting and retrieving the
|
||||
* root id for browsing, or null if none. The contents of this
|
||||
* bundle may affect the information returned when browsing.
|
||||
* @return The {@link BrowserRoot} for accessing this app's content or null.
|
||||
* @see BrowserRoot#EXTRA_RECENT
|
||||
* @see BrowserRoot#EXTRA_OFFLINE
|
||||
* @see BrowserRoot#EXTRA_SUGGESTED
|
||||
*/
|
||||
public abstract @Nullable BrowserRoot onGetRoot(
|
||||
@NonNull ControllerInfo controllerInfo, @Nullable Bundle rootHints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for {@link MediaLibrarySession}.
|
||||
*/
|
||||
// TODO(jaewan): Move this to updatable.
|
||||
public class MediaLibrarySessionBuilder
|
||||
extends BuilderBase<MediaLibrarySessionBuilder, MediaLibrarySessionCallback> {
|
||||
public MediaLibrarySessionBuilder(
|
||||
@NonNull Context context, @NonNull MediaPlayerBase player,
|
||||
@NonNull MediaLibrarySessionCallback callback) {
|
||||
super(context, player);
|
||||
setSessionCallback(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaLibrarySessionBuilder setSessionCallback(
|
||||
@NonNull MediaLibrarySessionCallback callback) {
|
||||
if (callback == null) {
|
||||
throw new IllegalArgumentException("MediaLibrarySessionCallback cannot be null");
|
||||
}
|
||||
return super.setSessionCallback(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaLibrarySession build() throws IllegalStateException {
|
||||
return new MediaLibrarySession(mContext, mPlayer, mId, mCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
MediaSessionService2Provider createProvider() {
|
||||
return ApiLoader.getProvider(this).createMediaLibraryService2(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when another app requested to start this service.
|
||||
* <p>
|
||||
* Library service will accept or reject the connection with the
|
||||
* {@link MediaLibrarySessionCallback} in the created session.
|
||||
* <p>
|
||||
* Service wouldn't run if {@code null} is returned or session's ID doesn't match with the
|
||||
* expected ID that you've specified through the AndroidManifest.xml.
|
||||
* <p>
|
||||
* This method will be called on the main thread.
|
||||
*
|
||||
* @param sessionId session id written in the AndroidManifest.xml.
|
||||
* @return a new browser session
|
||||
* @see MediaLibrarySessionBuilder
|
||||
* @see #getSession()
|
||||
* @throws RuntimeException if returned session is invalid
|
||||
*/
|
||||
@Override
|
||||
public @NonNull abstract MediaLibrarySession onCreateSession(String sessionId);
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package android.media;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
@@ -29,12 +28,9 @@ import android.media.update.MediaSession2Provider.ControllerInfoProvider;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcelable;
|
||||
import android.os.Process;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -55,20 +51,17 @@ import java.util.List;
|
||||
* instead. With it, your playback can be revived even after you've finished playback. See
|
||||
* {@link MediaSessionService2} for details.
|
||||
* <p>
|
||||
* A session can be obtained by {@link #getInstance(Context, Handler)}. The owner of the session may
|
||||
* pass its session token to other processes to allow them to create a {@link MediaController2}
|
||||
* to interact with the session.
|
||||
* A session can be obtained by {@link Builder}. The owner of the session may pass its session token
|
||||
* to other processes to allow them to create a {@link MediaController2} to interact with the
|
||||
* session.
|
||||
* <p>
|
||||
* To receive transport control commands, an underlying media player must be set with
|
||||
* {@link #setPlayer(MediaPlayerBase)}. Commands will be sent to the underlying player directly
|
||||
* on the thread that had been specified by {@link #getInstance(Context, Handler)}.
|
||||
* When a session receive transport control commands, the session sends the commands directly to
|
||||
* the the underlying media player set by {@link Builder} or {@link #setPlayer(MediaPlayerBase)}.
|
||||
* <p>
|
||||
* When an app is finished performing playback it must call
|
||||
* {@link #setPlayer(MediaPlayerBase)} with {@code null} to clean up the session and notify any
|
||||
* controllers. It's developers responsibility of cleaning the session and releasing resources.
|
||||
* When an app is finished performing playback it must call {@link #close()} to clean up the session
|
||||
* and notify any controllers.
|
||||
* <p>
|
||||
* MediaSession2 objects should be used on the handler's thread that is initially given by
|
||||
* {@link #getInstance(Context, Handler)}.
|
||||
* {@link MediaSession2} objects should be used on the thread on the looper.
|
||||
*
|
||||
* @see MediaSessionService2
|
||||
* @hide
|
||||
@@ -81,7 +74,7 @@ import java.util.List;
|
||||
// TODO(jaewan): Should we make APIs for MediaSessionService2 public? It's helpful for
|
||||
// developers that doesn't want to override from Browser, but user may not use this
|
||||
// correctly.
|
||||
public final class MediaSession2 extends MediaPlayerBase {
|
||||
public class MediaSession2 extends MediaPlayerBase {
|
||||
private final MediaSession2Provider mProvider;
|
||||
|
||||
// Note: Do not define IntDef because subclass can add more command code on top of these.
|
||||
@@ -321,19 +314,16 @@ public final class MediaSession2 extends MediaPlayerBase {
|
||||
};
|
||||
|
||||
/**
|
||||
* Builder for {@link MediaSession2}.
|
||||
* <p>
|
||||
* Any incoming event from the {@link MediaController2} will be handled on the thread
|
||||
* that created session with the {@link Builder#build()}.
|
||||
* Base builder class for MediaSession2 and its subclass.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
// TODO(jaewan): Move this to updatable
|
||||
// TODO(jaewan): Add setRatingType()
|
||||
// TODO(jaewan): Add setSessionActivity()
|
||||
public final static class Builder {
|
||||
private final Context mContext;
|
||||
private final MediaPlayerBase mPlayer;
|
||||
private String mId;
|
||||
private SessionCallback mCallback;
|
||||
static abstract class BuilderBase
|
||||
<T extends MediaSession2.BuilderBase<T, C>, C extends SessionCallback> {
|
||||
final Context mContext;
|
||||
final MediaPlayerBase mPlayer;
|
||||
String mId;
|
||||
C mCallback;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -343,7 +333,8 @@ public final class MediaSession2 extends MediaPlayerBase {
|
||||
* @throws IllegalArgumentException if any parameter is null, or the player is a
|
||||
* {@link MediaSession2} or {@link MediaController2}.
|
||||
*/
|
||||
public Builder(@NonNull Context context, @NonNull MediaPlayerBase player) {
|
||||
// TODO(jaewan): Also need executor
|
||||
public BuilderBase(@NonNull Context context, @NonNull MediaPlayerBase player) {
|
||||
if (context == null) {
|
||||
throw new IllegalArgumentException("context shouldn't be null");
|
||||
}
|
||||
@@ -370,12 +361,12 @@ public final class MediaSession2 extends MediaPlayerBase {
|
||||
* @throws IllegalArgumentException if id is {@code null}
|
||||
* @return
|
||||
*/
|
||||
public Builder setId(@NonNull String id) {
|
||||
public T setId(@NonNull String id) {
|
||||
if (id == null) {
|
||||
throw new IllegalArgumentException("id shouldn't be null");
|
||||
}
|
||||
mId = id;
|
||||
return this;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -384,9 +375,9 @@ public final class MediaSession2 extends MediaPlayerBase {
|
||||
* @param callback session callback.
|
||||
* @return
|
||||
*/
|
||||
public Builder setSessionCallback(@Nullable SessionCallback callback) {
|
||||
public T setSessionCallback(@Nullable C callback) {
|
||||
mCallback = callback;
|
||||
return this;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -396,6 +387,24 @@ public final class MediaSession2 extends MediaPlayerBase {
|
||||
* @throws IllegalStateException if the session with the same id is already exists for the
|
||||
* package.
|
||||
*/
|
||||
public abstract MediaSession2 build() throws IllegalStateException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for {@link MediaSession2}.
|
||||
* <p>
|
||||
* Any incoming event from the {@link MediaController2} will be handled on the thread
|
||||
* that created session with the {@link Builder#build()}.
|
||||
*/
|
||||
// TODO(jaewan): Move this to updatable
|
||||
// TODO(jaewan): Add setRatingType()
|
||||
// TODO(jaewan): Add setSessionActivity()
|
||||
public static final class Builder extends BuilderBase<Builder, SessionCallback> {
|
||||
public Builder(Context context, @NonNull MediaPlayerBase player) {
|
||||
super(context, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaSession2 build() throws IllegalStateException {
|
||||
if (mCallback == null) {
|
||||
mCallback = new SessionCallback();
|
||||
@@ -492,7 +501,7 @@ public final class MediaSession2 extends MediaPlayerBase {
|
||||
* framework had to add heuristics to figure out if an app is
|
||||
* @hide
|
||||
*/
|
||||
private MediaSession2(Context context, MediaPlayerBase player, String id,
|
||||
MediaSession2(Context context, MediaPlayerBase player, String id,
|
||||
SessionCallback callback) {
|
||||
super();
|
||||
mProvider = ApiLoader.getProvider(context)
|
||||
|
||||
@@ -29,7 +29,7 @@ import android.media.update.MediaSessionService2Provider;
|
||||
import android.os.IBinder;
|
||||
|
||||
/**
|
||||
* Service version of the {@link MediaSession2}.
|
||||
* Base class for media session services, which is the service version of the {@link MediaSession2}.
|
||||
* <p>
|
||||
* It's highly recommended for an app to use this instead of {@link MediaSession2} if it wants
|
||||
* to keep media playback in the background.
|
||||
@@ -43,11 +43,11 @@ import android.os.IBinder;
|
||||
* </ul>
|
||||
* For example, user's voice command can start playback of your app even when it's not running.
|
||||
* <p>
|
||||
* To use this class, adding followings directly to your {@code AndroidManifest.xml}.
|
||||
* To extend this class, adding followings directly to your {@code AndroidManifest.xml}.
|
||||
* <pre>
|
||||
* <service android:name="component_name_of_your_implementation" >
|
||||
* <intent-filter>
|
||||
* <action android:name="android.media.session.MediaSessionService2" />
|
||||
* <action android:name="android.media.MediaSessionService2" />
|
||||
* </intent-filter>
|
||||
* </service></pre>
|
||||
* <p>
|
||||
@@ -58,7 +58,7 @@ import android.os.IBinder;
|
||||
* <pre>
|
||||
* <service android:name="component_name_of_your_implementation" >
|
||||
* <intent-filter>
|
||||
* <action android:name="android.media.session.MediaSessionService2" />
|
||||
* <action android:name="android.media.MediaSessionService2" />
|
||||
* </intent-filter>
|
||||
* <meta-data android:name="android.media.session"
|
||||
* android:value="session_id"/>
|
||||
@@ -120,8 +120,7 @@ public abstract class MediaSessionService2 extends Service {
|
||||
* This is the interface name that a service implementing a session service should say that it
|
||||
* support -- that is, this is the action it uses for its intent filter.
|
||||
*/
|
||||
public static final String SERVICE_INTERFACE =
|
||||
"android.media.session.MediaSessionService2";
|
||||
public static final String SERVICE_INTERFACE = "android.media.MediaSessionService2";
|
||||
|
||||
/**
|
||||
* Name under which a MediaSessionService2 component publishes information about itself.
|
||||
@@ -129,21 +128,13 @@ public abstract class MediaSessionService2 extends Service {
|
||||
*/
|
||||
public static final String SERVICE_META_DATA = "android.media.session";
|
||||
|
||||
/**
|
||||
* Default notification channel ID used by {@link #onUpdateNotification(PlaybackState)}.
|
||||
*
|
||||
*/
|
||||
public static final String DEFAULT_MEDIA_NOTIFICATION_CHANNEL_ID = "media_session_service";
|
||||
|
||||
/**
|
||||
* Default notification channel ID used by {@link #onUpdateNotification(PlaybackState)}.
|
||||
*
|
||||
*/
|
||||
public static final int DEFAULT_MEDIA_NOTIFICATION_ID = 1001;
|
||||
|
||||
public MediaSessionService2() {
|
||||
super();
|
||||
mProvider = ApiLoader.getProvider(this).createMediaSessionService2(this);
|
||||
mProvider = createProvider();
|
||||
}
|
||||
|
||||
MediaSessionService2Provider createProvider() {
|
||||
return ApiLoader.getProvider(this).createMediaSessionService2(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,32 +159,24 @@ public abstract class MediaSessionService2 extends Service {
|
||||
* Service wouldn't run if {@code null} is returned or session's ID doesn't match with the
|
||||
* expected ID that you've specified through the AndroidManifest.xml.
|
||||
* <p>
|
||||
* This method will be call on the main thread.
|
||||
* This method will be called on the main thread.
|
||||
*
|
||||
* @param sessionId session id written in the AndroidManifest.xml.
|
||||
* @return a new session
|
||||
* @see MediaSession2.Builder
|
||||
* @see #getSession()
|
||||
*/
|
||||
// TODO(jaewan): Replace this with onCreateSession(). Its sesssion callback will replace
|
||||
// this abstract method.
|
||||
// TODO(jaewan): Should we also include/documents notification listener access?
|
||||
// TODO(jaewan): Is term accepted/rejected correct? For permission, granted is more common.
|
||||
// TODO(jaewan): Return ConnectResult() that encapsulate supported action and player.
|
||||
public @NonNull abstract MediaSession2 onCreateSession(String sessionId);
|
||||
|
||||
/**
|
||||
* Called when the playback state of this session is changed, and notification needs update.
|
||||
* <p>
|
||||
* Default media style notification will be shown if you don't override this or return
|
||||
* {@code null}. Override this method to show your own notification UI.
|
||||
* Override this method to show your own notification UI.
|
||||
* <p>
|
||||
* With the notification returned here, the service become foreground service when the playback
|
||||
* is started. It becomes background service after the playback is stopped.
|
||||
*
|
||||
* @param state playback state
|
||||
* @return a {@link MediaNotification}. If it's {@code null}, default notification will be shown
|
||||
* instead.
|
||||
* @return a {@link MediaNotification}. If it's {@code null}, notification wouldn't be shown.
|
||||
*/
|
||||
// TODO(jaewan): Also add metadata
|
||||
public MediaNotification onUpdateNotification(PlaybackState state) {
|
||||
|
||||
@@ -42,12 +42,13 @@ import java.lang.annotation.RetentionPolicy;
|
||||
// TODO(jaewan): Find better name for this (SessionToken or Session2Token)
|
||||
public final class SessionToken {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(value = {TYPE_SESSION, TYPE_SESSION_SERVICE})
|
||||
@IntDef(value = {TYPE_SESSION, TYPE_SESSION_SERVICE, TYPE_LIBRARY_SERVICE})
|
||||
public @interface TokenType {
|
||||
}
|
||||
|
||||
public static final int TYPE_SESSION = 0;
|
||||
public static final int TYPE_SESSION_SERVICE = 1;
|
||||
public static final int TYPE_LIBRARY_SERVICE = 2;
|
||||
|
||||
private static final String KEY_TYPE = "android.media.token.type";
|
||||
private static final String KEY_PACKAGE_NAME = "android.media.token.package_name";
|
||||
@@ -73,6 +74,7 @@ public final class SessionToken {
|
||||
* @hide
|
||||
*/
|
||||
// TODO(jaewan): UID is also needed.
|
||||
// TODO(jaewan): Unhide
|
||||
public SessionToken(@TokenType int type, @NonNull String packageName, @NonNull String id,
|
||||
@Nullable String serviceName, @Nullable IMediaSession2 sessionBinder) {
|
||||
// TODO(jaewan): Add sanity check.
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2018 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 android.media.update;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public interface MediaLibraryService2Provider extends MediaSessionService2Provider {
|
||||
// Nothing new for now
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import android.media.MediaBrowser2;
|
||||
import android.media.MediaBrowser2.BrowserCallback;
|
||||
import android.media.MediaController2;
|
||||
import android.media.MediaController2.ControllerCallback;
|
||||
import android.media.MediaLibraryService2;
|
||||
import android.media.MediaPlayerBase;
|
||||
import android.media.MediaSession2;
|
||||
import android.media.MediaSessionService2;
|
||||
@@ -62,4 +63,6 @@ public interface StaticProvider {
|
||||
BrowserCallback callback, Executor executor);
|
||||
MediaSessionService2Provider createMediaSessionService2(
|
||||
MediaSessionService2 instance);
|
||||
MediaSessionService2Provider createMediaLibraryService2(
|
||||
MediaLibraryService2 instance);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import android.media.AudioSystem;
|
||||
import android.media.IAudioService;
|
||||
import android.media.IMediaSession2;
|
||||
import android.media.IRemoteVolumeController;
|
||||
import android.media.MediaLibraryService2;
|
||||
import android.media.MediaSessionService2;
|
||||
import android.media.SessionToken;
|
||||
import android.media.session.IActiveSessionsListener;
|
||||
@@ -445,9 +446,18 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
}
|
||||
|
||||
// TODO(jaewan): Query per users.
|
||||
List<ResolveInfo> services = getContext().getPackageManager().queryIntentServices(
|
||||
new Intent(MediaSessionService2.SERVICE_INTERFACE),
|
||||
PackageManager.GET_META_DATA);
|
||||
List<ResolveInfo> services = new ArrayList<>();
|
||||
// If multiple actions are declared for a service, browser gets higher priority.
|
||||
List<ResolveInfo> libraryServices = getContext().getPackageManager().queryIntentServices(
|
||||
new Intent(MediaLibraryService2.SERVICE_INTERFACE), PackageManager.GET_META_DATA);
|
||||
if (libraryServices != null) {
|
||||
services.addAll(libraryServices);
|
||||
}
|
||||
List<ResolveInfo> sessionServices = getContext().getPackageManager().queryIntentServices(
|
||||
new Intent(MediaSessionService2.SERVICE_INTERFACE), PackageManager.GET_META_DATA);
|
||||
if (sessionServices != null) {
|
||||
services.addAll(sessionServices);
|
||||
}
|
||||
synchronized (mLock) {
|
||||
mSessions.clear();
|
||||
if (services == null) {
|
||||
@@ -470,10 +480,11 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
+ " the same ID=" + id + ". Ignoring "
|
||||
+ serviceInfo.packageName + "/" + serviceInfo.name);
|
||||
} else {
|
||||
int type = (libraryServices.contains(services.get(i)))
|
||||
? SessionToken.TYPE_LIBRARY_SERVICE : SessionToken.TYPE_SESSION_SERVICE;
|
||||
MediaSessionService2Record record =
|
||||
new MediaSessionService2Record(getContext(), mSessionDestroyedListener,
|
||||
SessionToken.TYPE_SESSION_SERVICE,
|
||||
serviceInfo.packageName, serviceInfo.name, id);
|
||||
type, serviceInfo.packageName, serviceInfo.name, id);
|
||||
mSessions.add(record);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user