Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 72223c2f authored by Sungsoo Lim's avatar Sungsoo Lim Committed by Android (Google) Code Review
Browse files

Merge "Remove unused MediaBrowser2 and relevant classes"

parents 0d5a91b1 049a32c1
Loading
Loading
Loading
Loading
+0 −238
Original line number Diff line number Diff line
/*
 * 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.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.media.MediaLibraryService2.MediaLibrarySession;
import android.media.MediaSession2.ControllerInfo;
import android.media.update.ApiLoader;
import android.media.update.MediaBrowser2Provider;
import android.os.Bundle;

import java.util.List;
import java.util.concurrent.Executor;

/**
 * @hide
 * Browses media content offered by a {@link MediaLibraryService2}.
 */
public class MediaBrowser2 extends MediaController2 {
    // Equals to the ((MediaBrowser2Provider) getProvider())
    private final MediaBrowser2Provider mProvider;

    /**
     * Callback to listen events from {@link MediaLibraryService2}.
     */
    public static class BrowserCallback extends MediaController2.ControllerCallback {
        /**
         * Called with the result of {@link #getLibraryRoot(Bundle)}.
         * <p>
         * {@code rootMediaId} and {@code rootExtra} can be {@code null} if the library root isn't
         * available.
         *
         * @param browser the browser for this event
         * @param rootHints rootHints that you previously requested.
         * @param rootMediaId media id of the library root. Can be {@code null}
         * @param rootExtra extra of the library root. Can be {@code null}
         */
        public void onGetLibraryRootDone(@NonNull MediaBrowser2 browser, @Nullable Bundle rootHints,
                @Nullable String rootMediaId, @Nullable Bundle rootExtra) { }

        /**
         * Called when there's change in the parent's children.
         * <p>
         * This API is called when the library service called
         * {@link MediaLibrarySession#notifyChildrenChanged(ControllerInfo, String, int, Bundle)} or
         * {@link MediaLibrarySession#notifyChildrenChanged(String, int, Bundle)} for the parent.
         *
         * @param browser the browser for this event
         * @param parentId parent id that you've specified with {@link #subscribe(String, Bundle)}
         * @param itemCount number of children
         * @param extras extra bundle from the library service. Can be differ from extras that
         *               you've specified with {@link #subscribe(String, Bundle)}.
         */
        public void onChildrenChanged(@NonNull MediaBrowser2 browser, @NonNull String parentId,
                int itemCount, @Nullable Bundle extras) { }

        /**
         * Called when the list of items has been returned by the library service for the previous
         * {@link MediaBrowser2#getChildren(String, int, int, Bundle)}.
         *
         * @param browser the browser for this event
         * @param parentId parent id
         * @param page page number that you've specified with
         *             {@link #getChildren(String, int, int, Bundle)}
         * @param pageSize page size that you've specified with
         *                 {@link #getChildren(String, int, int, Bundle)}
         * @param result result. Can be {@code null}
         * @param extras extra bundle from the library service
         */
        public void onGetChildrenDone(@NonNull MediaBrowser2 browser, @NonNull String parentId,
                int page, int pageSize, @Nullable List<MediaItem2> result,
                @Nullable Bundle extras) { }

        /**
         * Called when the item has been returned by the library service for the previous
         * {@link MediaBrowser2#getItem(String)} call.
         * <p>
         * Result can be null if there had been error.
         *
         * @param browser the browser for this event
         * @param mediaId media id
         * @param result result. Can be {@code null}
         */
        public void onGetItemDone(@NonNull MediaBrowser2 browser, @NonNull String mediaId,
                @Nullable MediaItem2 result) { }

        /**
         * Called when there's change in the search result requested by the previous
         * {@link MediaBrowser2#search(String, Bundle)}.
         *
         * @param browser the browser for this event
         * @param query search query that you've specified with {@link #search(String, Bundle)}
         * @param itemCount The item count for the search result
         * @param extras extra bundle from the library service
         */
        public void onSearchResultChanged(@NonNull MediaBrowser2 browser, @NonNull String query,
                int itemCount, @Nullable Bundle extras) { }

        /**
         * Called when the search result has been returned by the library service for the previous
         * {@link MediaBrowser2#getSearchResult(String, int, int, Bundle)}.
         * <p>
         * Result can be null if there had been error.
         *
         * @param browser the browser for this event
         * @param query search query that you've specified with
         *              {@link #getSearchResult(String, int, int, Bundle)}
         * @param page page number that you've specified with
         *             {@link #getSearchResult(String, int, int, Bundle)}
         * @param pageSize page size that you've specified with
         *                 {@link #getSearchResult(String, int, int, Bundle)}
         * @param result result. Can be {@code null}.
         * @param extras extra bundle from the library service
         */
        public void onGetSearchResultDone(@NonNull MediaBrowser2 browser, @NonNull String query,
                int page, int pageSize, @Nullable List<MediaItem2> result,
                @Nullable Bundle extras) { }
    }

    public MediaBrowser2(@NonNull Context context, @NonNull SessionToken2 token,
            @NonNull @CallbackExecutor Executor executor, @NonNull BrowserCallback callback) {
        super(context, token, executor, callback);
        mProvider = (MediaBrowser2Provider) getProvider();
    }

    @Override
    MediaBrowser2Provider createProvider(Context context, SessionToken2 token,
            Executor executor, ControllerCallback callback) {
        return ApiLoader.getProvider().createMediaBrowser2(
                context, this, token, executor, (BrowserCallback) callback);
    }

    /**
     * Get the library root. Result would be sent back asynchronously with the
     * {@link BrowserCallback#onGetLibraryRootDone(MediaBrowser2, Bundle, String, Bundle)}.
     *
     * @param rootHints hint for the root
     * @see BrowserCallback#onGetLibraryRootDone(MediaBrowser2, Bundle, String, Bundle)
     */
    public void getLibraryRoot(@Nullable Bundle rootHints) {
        mProvider.getLibraryRoot_impl(rootHints);
    }

    /**
     * Subscribe to a parent id for the change in its children. When there's a change,
     * {@link BrowserCallback#onChildrenChanged(MediaBrowser2, String, int, Bundle)} will be called
     * with the bundle that you've specified. You should call
     * {@link #getChildren(String, int, int, Bundle)} to get the actual contents for the parent.
     *
     * @param parentId parent id
     * @param extras extra bundle
     */
    public void subscribe(@NonNull String parentId, @Nullable Bundle extras) {
        mProvider.subscribe_impl(parentId, extras);
    }

    /**
     * Unsubscribe for changes to the children of the parent, which was previously subscribed with
     * {@link #subscribe(String, Bundle)}.
     * <p>
     * This unsubscribes all previous subscription with the parent id, regardless of the extra
     * that was previously sent to the library service.
     *
     * @param parentId parent id
     */
    public void unsubscribe(@NonNull String parentId) {
        mProvider.unsubscribe_impl(parentId);
    }

    /**
     * Get list of children under the parent. Result would be sent back asynchronously with the
     * {@link BrowserCallback#onGetChildrenDone(MediaBrowser2, String, int, int, List, Bundle)}.
     *
     * @param parentId parent id for getting the children.
     * @param page page number to get the result. Starts from {@code 1}
     * @param pageSize page size. Should be greater or equal to {@code 1}
     * @param extras extra bundle
     */
    public void getChildren(@NonNull String parentId, int page, int pageSize,
            @Nullable Bundle extras) {
        mProvider.getChildren_impl(parentId, page, pageSize, extras);
    }

    /**
     * Get the media item with the given media id. Result would be sent back asynchronously with the
     * {@link BrowserCallback#onGetItemDone(MediaBrowser2, String, MediaItem2)}.
     *
     * @param mediaId media id for specifying the item
     */
    public void getItem(@NonNull String mediaId) {
        mProvider.getItem_impl(mediaId);
    }

    /**
     * Send a search request to the library service. When the search result is changed,
     * {@link BrowserCallback#onSearchResultChanged(MediaBrowser2, String, int, Bundle)} will be
     * called. You should call {@link #getSearchResult(String, int, int, Bundle)} to get the actual
     * search result.
     *
     * @param query search query. Should not be an empty string.
     * @param extras extra bundle
     */
    public void search(@NonNull String query, @Nullable Bundle extras) {
        mProvider.search_impl(query, extras);
    }

    /**
     * Get the search result from lhe library service. Result would be sent back asynchronously with
     * the
     * {@link BrowserCallback#onGetSearchResultDone(MediaBrowser2, String, int, int, List, Bundle)}.
     *
     * @param query search query that you've specified with {@link #search(String, Bundle)}
     * @param page page number to get search result. Starts from {@code 1}
     * @param pageSize page size. Should be greater or equal to {@code 1}
     * @param extras extra bundle
     */
    public void getSearchResult(@NonNull String query, int page, int pageSize,
            @Nullable Bundle extras) {
        mProvider.getSearchResult_impl(query, page, pageSize, extras);
    }
}
+2 −10
Original line number Diff line number Diff line
@@ -41,9 +41,8 @@ import java.util.concurrent.Executor;

/**
 * @hide
 * Allows an app to interact with an active {@link MediaSession2} or a
 * {@link MediaSessionService2} in any status. Media buttons and other commands can be sent to
 * the session.
 * Allows an app to interact with an active {@link MediaSession2} in any status. Media buttons and
 * other commands can be sent to the session.
 * <p>
 * When you're done, use {@link #close()} to clean up resources. This also helps session service
 * to be destroyed when there's no controller associated with it.
@@ -51,12 +50,6 @@ import java.util.concurrent.Executor;
 * When controlling {@link MediaSession2}, the controller will be available immediately after
 * the creation.
 * <p>
 * When controlling {@link MediaSessionService2}, the {@link MediaController2} would be
 * available only if the session service allows this controller by
 * {@link MediaSession2.SessionCallback#onConnect(MediaSession2, ControllerInfo)} for the service.
 * Wait {@link ControllerCallback#onConnected(MediaController2, SessionCommandGroup2)} or
 * {@link ControllerCallback#onDisconnected(MediaController2)} for the result.
 * <p>
 * A controller can be created through token from {@link MediaSessionManager} if you hold the
 * signature|privileged permission "android.permission.MEDIA_CONTENT_CONTROL" permission or are
 * an enabled notification listener or by getting a {@link SessionToken2} directly the
@@ -65,7 +58,6 @@ import java.util.concurrent.Executor;
 * MediaController2 objects are thread-safe.
 * <p>
 * @see MediaSession2
 * @see MediaSessionService2
 */
public class MediaController2 implements AutoCloseable {
    /**
+0 −422

File deleted.

Preview size limit exceeded, changes collapsed.

+0 −6
Original line number Diff line number Diff line
@@ -59,10 +59,6 @@ import java.util.concurrent.Executor;
 * handle media keys. In general an app only needs one session for all playback, though multiple
 * sessions can be created to provide finer grain controls of media.
 * <p>
 * If you want to support background playback, {@link MediaSessionService2} is preferred
 * instead. With it, your playback can be revived even after playback is finished. See
 * {@link MediaSessionService2} for details.
 * <p>
 * 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.
@@ -75,8 +71,6 @@ import java.util.concurrent.Executor;
 * and notify any controllers.
 * <p>
 * {@link MediaSession2} objects should be used on the thread on the looper.
 *
 * @see MediaSessionService2
 */
public class MediaSession2 implements AutoCloseable {
    private final MediaSession2Provider mProvider;
+0 −233
Original line number Diff line number Diff line
/*
 * 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.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
import android.app.Service;
import android.content.Intent;
import android.media.MediaSession2.ControllerInfo;
import android.media.update.ApiLoader;
import android.media.update.MediaSessionService2Provider;
import android.media.update.MediaSessionService2Provider.MediaNotificationProvider;
import android.os.IBinder;

/**
 * @hide
 * 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.
 * <p>
 * Here's the benefits of using {@link MediaSessionService2} instead of
 * {@link MediaSession2}.
 * <ul>
 * <li>Another app can know that your app supports {@link MediaSession2} even when your app
 * isn't running.
 * <li>Another app can start playback of your app even when your app isn't running.
 * </ul>
 * For example, user's voice command can start playback of your app even when it's not running.
 * <p>
 * To extend this class, adding followings directly to your {@code AndroidManifest.xml}.
 * <pre>
 * &lt;service android:name="component_name_of_your_implementation" &gt;
 *   &lt;intent-filter&gt;
 *     &lt;action android:name="android.media.MediaSessionService2" /&gt;
 *   &lt;/intent-filter&gt;
 * &lt;/service&gt;</pre>
 * <p>
 * A {@link MediaSessionService2} is another form of {@link MediaSession2}. 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.
 * <pre>
 * &lt;service android:name="component_name_of_your_implementation" &gt;
 *   &lt;intent-filter&gt;
 *     &lt;action android:name="android.media.MediaSessionService2" /&gt;
 *   &lt;/intent-filter&gt;
 *   &lt;meta-data android:name="android.media.session"
 *       android:value="session_id"/&gt;
 * &lt;/service&gt;</pre>
 * <p>
 * It's recommended for an app to have a single {@link MediaSessionService2} declared in the
 * manifest. Otherwise, your app might be shown twice in the list of the Auto/Wearable, or another
 * app fails to pick the right session service when it wants to start the playback this app.
 * <p>
 * If there's conflicts with the session ID among the services, services wouldn't be available for
 * any controllers.
 * <p>
 * Topic covered here:
 * <ol>
 * <li><a href="#ServiceLifecycle">Service Lifecycle</a>
 * <li><a href="#Permissions">Permissions</a>
 * </ol>
 * <div class="special reference">
 * <a name="ServiceLifecycle"></a>
 * <h3>Service Lifecycle</h3>
 * <p>
 * Session service is bounded service. When a {@link MediaController2} is created for the
 * session service, the controller binds to the session service. {@link #onCreateSession(String)}
 * may be called after the {@link #onCreate} if the service hasn't created yet.
 * <p>
 * After the binding, session's {@link MediaSession2.SessionCallback#onConnect(MediaSession2, ControllerInfo)}
 *
 * will be called to accept or reject connection request from a controller. If the connection is
 * rejected, the controller will unbind. If it's accepted, the controller will be available to use
 * and keep binding.
 * <p>
 * When playback is started for this session service, {@link #onUpdateNotification()}
 * is called and service would become a foreground service. It's needed to keep playback after the
 * controller is destroyed. The session service becomes background service when the playback is
 * stopped.
 * <a name="Permissions"></a>
 * <h3>Permissions</h3>
 * <p>
 * Any app can bind to the session service with controller, but the controller can be used only if
 * the session service accepted the connection request through
 * {@link MediaSession2.SessionCallback#onConnect(MediaSession2, ControllerInfo)}.
 */
public abstract class MediaSessionService2 extends Service {
    private final MediaSessionService2Provider mProvider;

    /**
     * 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.MediaSessionService2";

    /**
     * Name under which a MediaSessionService2 component publishes information about itself.
     * This meta-data must provide a string value for the ID.
     */
    public static final String SERVICE_META_DATA = "android.media.session";

    public MediaSessionService2() {
        super();
        mProvider = createProvider();
    }

    MediaSessionService2Provider createProvider() {
        return ApiLoader.getProvider().createMediaSessionService2(this);
    }

    /**
     * Default implementation for {@link MediaSessionService2} to initialize session service.
     * <p>
     * Override this method if you need your own initialization. Derived classes MUST call through
     * to the super class's implementation of this method.
     */
    @CallSuper
    @Override
    public void onCreate() {
        super.onCreate();
        mProvider.onCreate_impl();
    }

    /**
     * Called when another app requested to start this service to get {@link MediaSession2}.
     * <p>
     * Session service will accept or reject the connection with the
     * {@link MediaSession2.SessionCallback} 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 session
     * @see MediaSession2.Builder
     * @see #getSession()
     */
    public @NonNull abstract MediaSession2 onCreateSession(String sessionId);

    /**
     * Called when the playback state of this session is changed so notification needs update.
     * Override this method to show or cancel 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.
     *
     * @return a {@link MediaNotification}. If it's {@code null}, notification wouldn't be shown.
     */
    public @Nullable MediaNotification onUpdateNotification() {
        return mProvider.onUpdateNotification_impl();
    }

    /**
     * Get instance of the {@link MediaSession2} that you've previously created with the
     * {@link #onCreateSession} for this service.
     * <p>
     * This may be {@code null} before the {@link #onCreate()} is finished.
     *
     * @return created session
     */
    public final @Nullable MediaSession2 getSession() {
        return mProvider.getSession_impl();
    }

    /**
     * Default implementation for {@link MediaSessionService2} to handle incoming binding
     * request. If the request is for getting the session, the intent will have action
     * {@link #SERVICE_INTERFACE}.
     * <p>
     * Override this method if this service also needs to handle binder requests other than
     * {@link #SERVICE_INTERFACE}. Derived classes MUST call through to the super class's
     * implementation of this method.
     *
     * @param intent
     * @return Binder
     */
    @CallSuper
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mProvider.onBind_impl(intent);
    }

    /**
     * Returned by {@link #onUpdateNotification()} for making session service foreground service
     * to keep playback running in the background. It's highly recommended to show media style
     * notification here.
     */
    public static class MediaNotification {
        private final MediaNotificationProvider mProvider;

        /**
         * Default constructor
         *
         * @param notificationId notification id to be used for
         *      {@link android.app.NotificationManager#notify(int, Notification)}.
         * @param notification a notification to make session service foreground service. Media
         *      style notification is recommended here.
         */
        public MediaNotification(int notificationId, @NonNull Notification notification) {
            mProvider = ApiLoader.getProvider().createMediaSessionService2MediaNotification(
                    this, notificationId, notification);
        }

        public int getNotificationId() {
            return mProvider.getNotificationId_impl();
        }

        public @NonNull Notification getNotification() {
            return mProvider.getNotification_impl();
        }
    }
}
Loading