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

Commit 2bdb9af0 authored by Jaewan Kim's avatar Jaewan Kim Committed by Android (Google) Code Review
Browse files

Merge changes from topics "medialibraryservice2", "mediabrowser2"

* changes:
  MediaSession2: Initial commit of MediaLibraryService2
  MediaSession2: Initial commit of MediaBrowser2
parents c7904e1d bcecf31a
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -46,6 +46,11 @@ interface IMediaSession2 {

    PlaybackState getPlaybackState();

    //////////////////////////////////////////////////////////////////////////////////////////////
    // Get library service specific
    //////////////////////////////////////////////////////////////////////////////////////////////
    oneway void getBrowserRoot(IMediaSession2Callback callback, in Bundle rootHints);

    //////////////////////////////////////////////////////////////////////////////////////////////
    // Callbacks -- remove them
    //////////////////////////////////////////////////////////////////////////////////////////////
+5 −0
Original line number Diff line number Diff line
@@ -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);
}
+69 −0
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.Nullable;
import android.content.Context;
import android.media.update.ApiLoader;
import android.media.update.MediaBrowser2Provider;
import android.os.Bundle;

import java.util.concurrent.Executor;

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

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

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

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

    public void getBrowserRoot(Bundle rootHints) {
        mProvider.getBrowserRoot_impl(rootHints);
    }
}
+7 −1
Original line number Diff line number Diff line
@@ -104,7 +104,13 @@ public class MediaController2 extends MediaPlayerBase {
        // session whose session binder is only valid while it's active.
        // prevent a controller from reusable after the
        // session is released and recreated.
        mProvider = ApiLoader.getProvider(context)
        mProvider = createProvider(context, token, callback, executor);
    }

    MediaController2Provider createProvider(@NonNull Context context,
            @NonNull SessionToken token, @NonNull ControllerCallback callback,
            @NonNull Executor executor) {
        return ApiLoader.getProvider(context)
                .createMediaController2(this, context, token, callback, executor);
    }

+144 −0
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.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>
 * &lt;service android:name="component_name_of_your_implementation" &gt;
 *   &lt;intent-filter&gt;
 *     &lt;action android:name="android.media.MediaLibraryService2" /&gt;
 *   &lt;/intent-filter&gt;
 * &lt;/service&gt;</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);
}
Loading