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

Commit 4dc8b320 authored by Jaewan Kim's avatar Jaewan Kim Committed by android-build-merger
Browse files

Merge changes from topic "msm_callback"

am: 7e8dffc5

Change-Id: I41d84015fdc917f4ca61fbaa71b740bfaccc37b4
parents 7231799d 7e8dffc5
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -3883,10 +3883,22 @@ package android.media.audiopolicy {
package android.media.session {
  public final class MediaSessionManager {
    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void addOnMediaKeyEventDispatchedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventDispatchedListener);
    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void addOnMediaKeyEventSessionChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void removeOnMediaKeyEventDispatchedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventDispatchedListener);
    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void removeOnMediaKeyEventSessionChangedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
    method @RequiresPermission(android.Manifest.permission.SET_MEDIA_KEY_LISTENER) public void setOnMediaKeyListener(android.media.session.MediaSessionManager.OnMediaKeyListener, @Nullable android.os.Handler);
    method @RequiresPermission(android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER) public void setOnVolumeKeyLongPressListener(android.media.session.MediaSessionManager.OnVolumeKeyLongPressListener, @Nullable android.os.Handler);
  }
  public static interface MediaSessionManager.OnMediaKeyEventDispatchedListener {
    method public default void onMediaKeyEventDispatched(@NonNull android.view.KeyEvent, @NonNull String, @NonNull android.media.session.MediaSession.Token);
  }
  public static interface MediaSessionManager.OnMediaKeyEventSessionChangedListener {
    method public default void onMediaKeyEventSessionChanged(@NonNull String, @Nullable android.media.session.MediaSession.Token);
  }
  public static interface MediaSessionManager.OnMediaKeyListener {
    method public boolean onMediaKey(android.view.KeyEvent);
  }
+4 −11
Original line number Diff line number Diff line
/* Copyright (C) 2016 The Android Open Source Project
/*
 * Copyright 2019 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.
@@ -15,21 +16,13 @@

package android.media.session;

import android.app.PendingIntent;
import android.content.ComponentName;
import android.media.session.MediaSession;
import android.view.KeyEvent;

/**
 * @hide
 */
oneway interface ICallback {
    void onMediaKeyEventDispatchedToMediaSession(in KeyEvent event,
oneway interface IOnMediaKeyEventDispatchedListener {
    void onMediaKeyEventDispatched(in KeyEvent event, in String packageName,
            in MediaSession.Token sessionToken);
    void onMediaKeyEventDispatchedToMediaButtonReceiver(in KeyEvent event,
            in ComponentName mediaButtonReceiver);

    void onAddressedPlayerChangedToMediaSession(in MediaSession.Token sessionToken);
    void onAddressedPlayerChangedToMediaButtonReceiver(in ComponentName mediaButtonReceiver);
}
+28 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 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.session;

import android.media.session.MediaSession;

/**
 * @hide
 */
oneway interface IOnMediaKeyEventSessionChangedListener {
    void onMediaKeyEventSessionChanged(in String packageName,
            in MediaSession.Token mediaKeyEventSessionToken);
}
+8 −2
Original line number Diff line number Diff line
@@ -20,7 +20,8 @@ import android.content.pm.ParceledListSlice;
import android.media.IRemoteVolumeController;
import android.media.Session2Token;
import android.media.session.IActiveSessionsListener;
import android.media.session.ICallback;
import android.media.session.IOnMediaKeyEventDispatchedListener;
import android.media.session.IOnMediaKeyEventSessionChangedListener;
import android.media.session.IOnMediaKeyListener;
import android.media.session.IOnVolumeKeyLongPressListener;
import android.media.session.ISession;
@@ -62,7 +63,12 @@ interface ISessionManager {
    // For PhoneWindowManager to precheck media keys
    boolean isGlobalPriorityActive();

    void setCallback(in ICallback callback);
    void addOnMediaKeyEventDispatchedListener(in IOnMediaKeyEventDispatchedListener listener);
    void removeOnMediaKeyEventDispatchedListener(in IOnMediaKeyEventDispatchedListener listener);
    void addOnMediaKeyEventSessionChangedListener(
            in IOnMediaKeyEventSessionChangedListener listener);
    void removeOnMediaKeyEventSessionChangedListener(
            in IOnMediaKeyEventSessionChangedListener listener);
    void setOnVolumeKeyLongPressListener(in IOnVolumeKeyLongPressListener listener);
    void setOnMediaKeyListener(in IOnMediaKeyListener listener);

+178 −100
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.media.session;

import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -46,8 +47,11 @@ import android.view.KeyEvent;
import com.android.internal.annotations.GuardedBy;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executor;

/**
 * Provides support for interacting with {@link MediaSession media sessions}
@@ -72,19 +76,32 @@ public final class MediaSessionManager {
     * @hide
     */
    public static final int RESULT_MEDIA_KEY_HANDLED = 1;
    private final ISessionManager mService;
    private final OnMediaKeyEventDispatchedListenerStub mOnMediaKeyEventDispatchedListenerStub =
            new OnMediaKeyEventDispatchedListenerStub();
    private final OnMediaKeyEventSessionChangedListenerStub
            mOnMediaKeyEventSessionChangedListenerStub =
            new OnMediaKeyEventSessionChangedListenerStub();

    private final Object mLock = new Object();
    @GuardedBy("mLock")
    private final ArrayMap<OnActiveSessionsChangedListener, SessionsChangedWrapper> mListeners
            = new ArrayMap<OnActiveSessionsChangedListener, SessionsChangedWrapper>();
    private final ArrayMap<OnActiveSessionsChangedListener, SessionsChangedWrapper> mListeners =
            new ArrayMap<OnActiveSessionsChangedListener, SessionsChangedWrapper>();
    @GuardedBy("mLock")
    private final ArrayMap<OnSession2TokensChangedListener, Session2TokensChangedWrapper>
            mSession2TokensListeners = new ArrayMap<>();
    private final ISessionManager mService;
    @GuardedBy("mLock")
    private final Map<OnMediaKeyEventDispatchedListener, Executor>
            mOnMediaKeyEventDispatchedListeners = new HashMap<>();
    @GuardedBy("mLock")
    private final Map<OnMediaKeyEventSessionChangedListener, Executor>
            mMediaKeyEventSessionChangedCallbacks = new HashMap<>();
    @GuardedBy("mLock")
    private String mCurMediaKeyEventSessionPackage;
    @GuardedBy("mLock")
    private MediaSession.Token mCurMediaKeyEventSession;

    private Context mContext;

    private CallbackImpl mCallback;
    private OnVolumeKeyLongPressListenerImpl mOnVolumeKeyLongPressListener;
    private OnMediaKeyListenerImpl mOnMediaKeyListener;

@@ -742,31 +759,118 @@ public final class MediaSessionManager {
    }

    /**
     * Set a {@link Callback}.
     * Add a {@link OnMediaKeyEventDispatchedListener}.
     *
     * <p>System can only have a single callback, and the callback can only be set by
     * Bluetooth service process.
     * @param executor The executor on which the callback should be invoked
     * @param listener A {@link OnMediaKeyEventDispatchedListener}.
     * @hide
     */
    @SystemApi
    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
    public void addOnMediaKeyEventDispatchedListener(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnMediaKeyEventDispatchedListener listener) {
        if (executor == null) {
            throw new NullPointerException("executor shouldn't be null");
        }
        if (listener == null) {
            throw new NullPointerException("listener shouldn't be null");
        }
        synchronized (mLock) {
            try {
                mOnMediaKeyEventDispatchedListeners.put(listener, executor);
                if (mOnMediaKeyEventDispatchedListeners.size() == 1) {
                    mService.addOnMediaKeyEventDispatchedListener(
                            mOnMediaKeyEventDispatchedListenerStub);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to set media key listener", e);
            }
        }
    }

    /**
     * Remove a {@link OnMediaKeyEventDispatchedListener}.
     *
     * @param callback A {@link Callback}. {@code null} to reset.
     * @param handler The handler on which the callback should be invoked, or {@code null}
     *            if the callback should be invoked on the calling thread's looper.
     * @param listener A {@link OnMediaKeyEventDispatchedListener}.
     * @hide
     */
    public void setCallback(@Nullable Callback callback, @Nullable Handler handler) {
    @SystemApi
    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
    public void removeOnMediaKeyEventDispatchedListener(
            @NonNull OnMediaKeyEventDispatchedListener listener) {
        if (listener == null) {
            throw new NullPointerException("listener shouldn't be null");
        }
        synchronized (mLock) {
            try {
                if (callback == null) {
                    mCallback = null;
                    mService.setCallback(null);
                } else {
                    if (handler == null) {
                        handler = new Handler();
                mOnMediaKeyEventDispatchedListeners.remove(listener);
                if (mOnMediaKeyEventDispatchedListeners.size() == 0) {
                    mService.removeOnMediaKeyEventDispatchedListener(
                            mOnMediaKeyEventDispatchedListenerStub);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to set media key event dispatched listener", e);
            }
        }
    }
                    mCallback = new CallbackImpl(callback, handler);
                    mService.setCallback(mCallback);

    /**
     * Add a {@link OnMediaKeyEventDispatchedListener}.
     *
     * @param executor The executor on which the callback should be invoked
     * @param listener A {@link OnMediaKeyEventSessionChangedListener}.
     * @hide
     */
    @SystemApi
    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
    public void addOnMediaKeyEventSessionChangedListener(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnMediaKeyEventSessionChangedListener listener) {
        if (executor == null) {
            throw new NullPointerException("executor shouldn't be null");
        }
        if (listener == null) {
            throw new NullPointerException("listener shouldn't be null");
        }
        synchronized (mLock) {
            try {
                mMediaKeyEventSessionChangedCallbacks.put(listener, executor);
                executor.execute(
                        () -> listener.onMediaKeyEventSessionChanged(
                                mCurMediaKeyEventSessionPackage, mCurMediaKeyEventSession));
                if (mMediaKeyEventSessionChangedCallbacks.size() == 1) {
                    mService.addOnMediaKeyEventSessionChangedListener(
                            mOnMediaKeyEventSessionChangedListenerStub);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to set media key callback", e);
                Log.e(TAG, "Failed to set media key listener", e);
            }
        }
    }

    /**
     * Remove a {@link OnMediaKeyEventSessionChangedListener}.
     *
     * @param listener A {@link OnMediaKeyEventSessionChangedListener}.
     * @hide
     */
    @SystemApi
    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
    public void removeOnMediaKeyEventSessionChangedListener(
            @NonNull OnMediaKeyEventSessionChangedListener listener) {
        if (listener == null) {
            throw new NullPointerException("listener shouldn't be null");
        }
        synchronized (mLock) {
            try {
                mMediaKeyEventSessionChangedCallbacks.remove(listener);
                if (mMediaKeyEventSessionChangedCallbacks.size() == 0) {
                    mService.removeOnMediaKeyEventSessionChangedListener(
                            mOnMediaKeyEventSessionChangedListenerStub);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to set media key listener", e);
            }
        }
    }
@@ -828,53 +932,46 @@ public final class MediaSessionManager {
    }

    /**
     * Callbacks for the media session service.
     *
     * <p>Called when a media key event is dispatched or the addressed player is changed.
     * The addressed player is either the media session or the media button receiver that will
     * receive media key events.
     * Listener to receive when the media session service
     * @hide
     */
    public static abstract class Callback {
    @SystemApi
    public interface OnMediaKeyEventDispatchedListener {
        /**
         * Called when a media key event is dispatched to the media session
         * through the media session service.
         * Called when a media key event is dispatched through the media session service. The
         * session token can be {@link null} if the framework has sent the media key event to the
         * media button receiver to revive the media app's playback.
         *
         * @param event Dispatched media key event.
         * @param sessionToken The media session's token.
         */
        public abstract void onMediaKeyEventDispatched(KeyEvent event,
                MediaSession.Token sessionToken);

        /**
         * Called when a media key event is dispatched to the media button receiver
         * through the media session service.
         * <p>MediaSessionService may broadcast key events to the media button receiver
         * when reviving playback after the media session is released.
         * the session is dead when , but the framework sent
         *
         * @param event Dispatched media key event.
         * @param mediaButtonReceiver The media button receiver.
         * @param packageName Package
         * @param sessionToken The media session's token. Can be {@code null}.
         */
        public abstract void onMediaKeyEventDispatched(KeyEvent event,
                ComponentName mediaButtonReceiver);
        default void onMediaKeyEventDispatched(@NonNull KeyEvent event, @NonNull String packageName,
                @NonNull MediaSession.Token sessionToken) { }
    }

    /**
         * Called when the addressed player is changed to a media session.
         * <p>One of the {@ #onAddressedPlayerChanged} will be also called immediately after
         * {@link #setCallback} if the addressed player exists.
         *
         * @param sessionToken The media session's token.
     * Listener to receive changes in the media key event session, which would receive the media key
     * event unless specified.
     * @hide
     */
        public abstract void onAddressedPlayerChanged(MediaSession.Token sessionToken);

    @SystemApi
    public interface OnMediaKeyEventSessionChangedListener {
        /**
         * Called when the addressed player is changed to the media button receiver.
         * <p>One of the {@ #onAddressedPlayerChanged} will be also called immediately after
         * {@link #setCallback} if the addressed player exists.
         * Called when the media key session is changed to the given media session. The key event
         * session is the media session which would receive key event by default, unless the caller
         * has specified the target.
         * <p>
         * The session token can be {@link null} if the media button session is unset. In that case,
         * framework would dispatch to the last sessions's media button receiver.
         *
         * @param mediaButtonReceiver The media button receiver.
         * @param packageName The package name who would receive the media key event. Can be empty.
         * @param sessionToken The media session's token. Can be {@code null.}
         */
        public abstract void onAddressedPlayerChanged(ComponentName mediaButtonReceiver);
        default void onMediaKeyEventSessionChanged(@NonNull String packageName,
                @Nullable MediaSession.Token sessionToken) { }
    }

    /**
@@ -1076,56 +1173,37 @@ public final class MediaSessionManager {
        }
    }

    private static final class CallbackImpl extends ICallback.Stub {
        private final Callback mCallback;
        private final Handler mHandler;

        public CallbackImpl(@NonNull Callback callback, @NonNull Handler handler) {
            mCallback = callback;
            mHandler = handler;
        }
    private final class OnMediaKeyEventDispatchedListenerStub
            extends IOnMediaKeyEventDispatchedListener.Stub {

        @Override
        public void onMediaKeyEventDispatchedToMediaSession(KeyEvent event,
        public void onMediaKeyEventDispatched(KeyEvent event, String packageName,
                MediaSession.Token sessionToken) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onMediaKeyEventDispatched(event, sessionToken);
            synchronized (mLock) {
                for (Map.Entry<OnMediaKeyEventDispatchedListener, Executor> e
                        : mOnMediaKeyEventDispatchedListeners.entrySet()) {
                    e.getValue().execute(
                            () -> e.getKey().onMediaKeyEventDispatched(event, packageName,
                                    sessionToken));
                }
            });
            }

        @Override
        public void onMediaKeyEventDispatchedToMediaButtonReceiver(KeyEvent event,
                ComponentName mediaButtonReceiver) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onMediaKeyEventDispatched(event, mediaButtonReceiver);
        }
            });
    }

    private final class OnMediaKeyEventSessionChangedListenerStub
            extends IOnMediaKeyEventSessionChangedListener.Stub {
        @Override
        public void onAddressedPlayerChangedToMediaSession(MediaSession.Token sessionToken) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onAddressedPlayerChanged(sessionToken);
                }
            });
        public void onMediaKeyEventSessionChanged(String packageName,
                MediaSession.Token sessionToken) {
            synchronized (mLock) {
                mCurMediaKeyEventSessionPackage = packageName;
                mCurMediaKeyEventSession = sessionToken;
                for (Map.Entry<OnMediaKeyEventSessionChangedListener, Executor> e
                        : mMediaKeyEventSessionChangedCallbacks.entrySet()) {
                    e.getValue().execute(() -> e.getKey().onMediaKeyEventSessionChanged(packageName,
                            sessionToken));
                }

        @Override
        public void onAddressedPlayerChangedToMediaButtonReceiver(
                ComponentName mediaButtonReceiver) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onAddressedPlayerChanged(mediaButtonReceiver);
            }
            });
        }
    }
}
Loading