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

Commit 0083ed6d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topics "sessiontoken2_simpl", "move_binder2",...

Merge changes from topics "sessiontoken2_simpl", "move_binder2", "mediaitem2_updatable", "session2_sendcustomcommand"

* changes:
  MediaSession2: Simplify constructor of SessionToken2
  MediaSession2: Move binder interfaces into the updatable
  MediaSession2: Move MediaItem2 to updatable
  MediaSession2: Implements sendCustomCommand()
parents f30dc952 44fec2d6
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -429,8 +429,6 @@ java_library {
        "media/java/android/media/IMediaRouterService.aidl",
        "media/java/android/media/IMediaScannerListener.aidl",
        "media/java/android/media/IMediaScannerService.aidl",
        "media/java/android/media/IMediaSession2.aidl",
        "media/java/android/media/IMediaSession2Callback.aidl",
        "media/java/android/media/IPlaybackConfigDispatcher.aidl",
        "media/java/android/media/ISessionTokensListener.aidl",
        ":libaudioclient_aidl",
+0 −50
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.media.IMediaSession2Callback;
import android.os.Bundle;

/**
 * Interface to MediaSession2. Framework MUST only call oneway APIs.
 *
 * @hide
 */
oneway interface IMediaSession2 {
    // TODO(jaewan): add onCommand() to send private command
    // TODO(jaewan): Due to the nature of oneway calls, APIs can be called in out of order
    //               Add id for individual calls to address this.

    // TODO(jaewan): We may consider to add another binder just for the connection
    //               not to expose other methods to the controller whose connection wasn't accepted.
    //               But this would be enough for now because it's the same as existing
    //               MediaBrowser and MediaBrowserService.
    void connect(String callingPackage, IMediaSession2Callback callback);
    void release(IMediaSession2Callback caller);

    //////////////////////////////////////////////////////////////////////////////////////////////
    // send command
    //////////////////////////////////////////////////////////////////////////////////////////////
    void sendCommand(IMediaSession2Callback caller, in Bundle command, in Bundle args);
    void sendTransportControlCommand(IMediaSession2Callback caller,
            int commandCode, in Bundle args);

    //////////////////////////////////////////////////////////////////////////////////////////////
    // Get library service specific
    //////////////////////////////////////////////////////////////////////////////////////////////
    void getBrowserRoot(IMediaSession2Callback callback, in Bundle rootHints);
}
+0 −55
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.os.Bundle;
import android.media.session.PlaybackState;
import android.media.IMediaSession2;

/**
 * Interface from MediaSession2 to MediaSession2Record.
 * <p>
 * Keep this interface oneway. Otherwise a malicious app may implement fake version of this,
 * and holds calls from session to make session owner(s) frozen.
 *
 * @hide
 */
oneway interface IMediaSession2Callback {
    void onPlaybackStateChanged(in Bundle state);
    void onPlaylistParamsChanged(in Bundle params);

    /**
     * Called only when the controller is created with service's token.
     *
     * @param sessionBinder {@code null} if the connect is rejected or is disconnected. a session
     *     binder if the connect is accepted.
     * @param commands initially allowed commands.
     */
    // TODO(jaewan): Also need to pass flags for allowed actions for permission check.
    //               For example, a media can allow setRating only for whitelisted apps
    //               it's better for controller to know such information in advance.
    //               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);

    void onCustomLayoutChanged(in List<Bundle> commandButtonlist);

    //////////////////////////////////////////////////////////////////////////////////////////////
    // Browser sepcific
    //////////////////////////////////////////////////////////////////////////////////////////////
    void onGetRootResult(in Bundle rootHints, String rootMediaId, in Bundle rootExtra);
}
+43 −30
Original line number Diff line number Diff line
@@ -20,6 +20,9 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.media.update.ApiLoader;
import android.media.update.MediaItem2Provider;
import android.os.Bundle;
import android.text.TextUtils;

@@ -36,10 +39,6 @@ import java.lang.annotation.RetentionPolicy;
 * @hide
 */
public class MediaItem2 {
    private final int mFlags;
    private MediaMetadata2 mMetadata;
    private DataSourceDesc mDataSourceDesc;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag=true, value = { FLAG_BROWSABLE, FLAG_PLAYABLE })
@@ -58,17 +57,29 @@ public class MediaItem2 {
     */
    public static final int FLAG_PLAYABLE = 1 << 1;

    private final MediaItem2Provider mProvider;

    /**
     * Create a new media item.
     *
     * @param mediaId id of this item. It must be unique whithin this app
     * @param metadata metadata with the media id.
     * @param flags The flags for this item.
     */
    public MediaItem2(@Nullable MediaMetadata2 metadata,
            @Nullable DataSourceDesc data, @Flags int flags) {
        mFlags = flags;
        mDataSourceDesc = data;
        setMetadata(metadata);
    public MediaItem2(@NonNull Context context, @NonNull String mediaId,
            @NonNull DataSourceDesc dsd, @Nullable MediaMetadata2 metadata,
            @Flags int flags) {
        mProvider = ApiLoader.getProvider(context).createMediaItem2Provider(
                context, this, mediaId, dsd, metadata, flags);
    }

    /**
     * Create a new media item
     * @hide
     */
    @SystemApi
    public MediaItem2(MediaItem2Provider provider) {
        mProvider = provider;
    }

    /**
@@ -78,22 +89,22 @@ public class MediaItem2 {
     */
    public Bundle toBundle() {
        // TODO(jaewan): Fill here when we rebase.
        return new Bundle();
        return mProvider.toBundle_impl();
    }

    public static MediaItem2 fromBundle(Context context, Bundle bundle) {
        return ApiLoader.getProvider(context).fromBundle_MediaItem2(context, bundle);
    }

    public String toString() {
        final StringBuilder sb = new StringBuilder("MediaItem2{");
        sb.append("mFlags=").append(mFlags);
        sb.append(", mMetadata=").append(mMetadata);
        sb.append('}');
        return sb.toString();
        return mProvider.toString_impl();
    }

    /**
     * Gets the flags of the item.
     */
    public @Flags int getFlags() {
        return mFlags;
        return mProvider.getFlags_impl();
    }

    /**
@@ -101,7 +112,7 @@ public class MediaItem2 {
     * @see #FLAG_BROWSABLE
     */
    public boolean isBrowsable() {
        return (mFlags & FLAG_BROWSABLE) != 0;
        return mProvider.isBrowsable_impl();
    }

    /**
@@ -109,29 +120,24 @@ public class MediaItem2 {
     * @see #FLAG_PLAYABLE
     */
    public boolean isPlayable() {
        return (mFlags & FLAG_PLAYABLE) != 0;
        return mProvider.isPlayable_impl();
    }

    /**
     * Set a metadata. Metadata shouldn't be null and should have non-empty media id.
     * Set a metadata. Metadata shouldn't be {@code null} and its id should be match
     * with this instance's id.
     *
     * @param metadata
     * @param metadata metadata to update
     */
    public void setMetadata(@NonNull MediaMetadata2 metadata) {
        if (metadata == null) {
            throw new IllegalArgumentException("metadata cannot be null");
        }
        if (TextUtils.isEmpty(metadata.getMediaId())) {
            throw new IllegalArgumentException("metadata must have a non-empty media id");
        }
        mMetadata = metadata;
        mProvider.setMetadata_impl(metadata);
    }

    /**
     * Returns the metadata of the media.
     */
    public @NonNull MediaMetadata2 getMetadata() {
        return mMetadata;
        return mProvider.getMetadata_impl();
    }

    /**
@@ -139,10 +145,17 @@ public class MediaItem2 {
     * @see MediaMetadata2#METADATA_KEY_MEDIA_ID
     */
    public @Nullable String getMediaId() {
        return mMetadata.getMediaId();
        return mProvider.getMediaId_impl();
    }

    /**
     * Return the {@link DataSourceDesc}
     * <p>
     * Can be {@code null} if the MediaItem2 came from another process and anonymized
     *
     * @return data source descriptor
     */
    public @Nullable DataSourceDesc getDataSourceDesc() {
        return mDataSourceDesc;
        return mProvider.getDataSourceDesc_impl();
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.media.update.MediaSession2Provider.ControllerInfoProvider;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IInterface;
import android.os.Parcelable;
import android.os.ResultReceiver;
import android.text.TextUtils;
@@ -630,7 +631,7 @@ public class MediaSession2 implements AutoCloseable {
        // TODO(jaewan): SystemApi
        // TODO(jaewan): Also accept componentName to check notificaiton listener.
        public ControllerInfo(Context context, int uid, int pid, String packageName,
                IMediaSession2Callback callback) {
                IInterface callback) {
            mProvider = ApiLoader.getProvider(context)
                    .createMediaSession2ControllerInfoProvider(
                            context, this, uid, pid, packageName, callback);
Loading