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

Commit 27c9c79f authored by Hyundo Moon's avatar Hyundo Moon
Browse files

Add public add/removeOnMediaKeyEventSessionChangedListener

The MediaSessionManager has two system APIs
 - addOnMediaKeyEventSessionChangedListener
 - removeOnMediaKeyEventSessionChangedListener
which listen the media key session updates.

Since the APIs require MEDIA_CONTENT_CONTROL permission,
non-system apps could not use the APIs.

This CL adds an overloaded version of those APIs so that apps with
enabled notification listener can use the functionality.

Bug: 187483932
Test: Passed MediaSessionManager(Host)Test
Change-Id: Ic13353983e23f557afaa13eb11a48e48d24d4358
parent 2e8839e9
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -25266,6 +25266,7 @@ package android.media.session {
  public final class MediaSessionManager {
    method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName);
    method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName, @Nullable android.os.Handler);
    method public void addOnMediaKeyEventSessionChangedListener(@NonNull android.content.ComponentName, @NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
    method public void addOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener);
    method public void addOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener, @NonNull android.os.Handler);
    method @NonNull public java.util.List<android.media.session.MediaController> getActiveSessions(@Nullable android.content.ComponentName);
@@ -25273,6 +25274,7 @@ package android.media.session {
    method public boolean isTrustedForMediaControl(@NonNull android.media.session.MediaSessionManager.RemoteUserInfo);
    method @Deprecated public void notifySession2Created(@NonNull android.media.Session2Token);
    method public void removeOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener);
    method public void removeOnMediaKeyEventSessionChangedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
    method public void removeOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener);
  }
@@ -25280,6 +25282,10 @@ package android.media.session {
    method public void onActiveSessionsChanged(@Nullable java.util.List<android.media.session.MediaController>);
  }
  public static interface MediaSessionManager.OnMediaKeyEventSessionChangedListener {
    method public void onMediaKeyEventSessionChanged(@NonNull String, @Nullable android.media.session.MediaSession.Token);
  }
  public static interface MediaSessionManager.OnSession2TokensChangedListener {
    method public void onSession2TokensChanged(@NonNull java.util.List<android.media.Session2Token>);
  }
+0 −5
Original line number Diff line number Diff line
@@ -5587,7 +5587,6 @@ package android.media.session {
    method @Nullable @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public android.media.session.MediaSession.Token getMediaKeyEventSession();
    method @NonNull @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public String getMediaKeyEventSessionPackageName();
    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);
  }
@@ -5596,10 +5595,6 @@ package android.media.session {
    method public void onMediaKeyEventDispatched(@NonNull android.view.KeyEvent, @NonNull String, @Nullable android.media.session.MediaSession.Token);
  }
  public static interface MediaSessionManager.OnMediaKeyEventSessionChangedListener {
    method public void onMediaKeyEventSessionChanged(@NonNull String, @Nullable android.media.session.MediaSession.Token);
  }
  public static interface MediaSessionManager.OnMediaKeyListener {
    method public boolean onMediaKey(android.view.KeyEvent);
  }
+2 −1
Original line number Diff line number Diff line
@@ -66,7 +66,8 @@ interface ISessionManager {
    void addOnMediaKeyEventDispatchedListener(in IOnMediaKeyEventDispatchedListener listener);
    void removeOnMediaKeyEventDispatchedListener(in IOnMediaKeyEventDispatchedListener listener);
    void addOnMediaKeyEventSessionChangedListener(
            in IOnMediaKeyEventSessionChangedListener listener);
            in IOnMediaKeyEventSessionChangedListener listener,
            in ComponentName notificationListener);
    void removeOnMediaKeyEventSessionChangedListener(
            in IOnMediaKeyEventSessionChangedListener listener);
    void setOnVolumeKeyLongPressListener(in IOnVolumeKeyLongPressListener listener);
+36 −15
Original line number Diff line number Diff line
@@ -905,44 +905,67 @@ public final class MediaSessionManager {
    public void addOnMediaKeyEventSessionChangedListener(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnMediaKeyEventSessionChangedListener listener) {
        addOnMediaKeyEventSessionChangedListenerInternal(null, executor, listener);
    }

    /**
     * Add a listener to be notified when the media key session is changed.
     * <p>
     * This requires that your app is an enabled notificationlistener using the
     * {@link NotificationListenerService} APIs, in which case you must pass
     * the {@link ComponentName} of your enabled listener.
     *
     * @param notificationListener The enabled notification listener component.
     * @param executor The executor on which the listener should be invoked.
     * @param listener A {@link OnMediaKeyEventSessionChangedListener}.
     */
    public void addOnMediaKeyEventSessionChangedListener(
            @NonNull ComponentName notificationListener,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnMediaKeyEventSessionChangedListener listener) {
        Objects.requireNonNull(notificationListener, "notificationListener shouldn't be null");
        addOnMediaKeyEventSessionChangedListenerInternal(notificationListener, executor, listener);
    }

    private void addOnMediaKeyEventSessionChangedListenerInternal(
            @Nullable ComponentName notificationListener,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnMediaKeyEventSessionChangedListener listener) {
        Objects.requireNonNull(executor, "executor shouldn't be null");
        Objects.requireNonNull(listener, "listener shouldn't be null");
        synchronized (mLock) {
            try {
                if (mMediaKeyEventSessionChangedCallbacks.isEmpty()) {
                    mService.addOnMediaKeyEventSessionChangedListener(
                            mOnMediaKeyEventSessionChangedListenerStub, notificationListener);
                }
                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 listener", e);
                Log.e(TAG, "Failed to add MediaKeyEventSessionChangedListener", e);
            }
        }
    }

    /**
     * Remove a {@link OnMediaKeyEventSessionChangedListener}.
     * Stop receiving updates on media key event session change on the specified listener.
     *
     * @param listener A {@link OnMediaKeyEventSessionChangedListener}.
     * @hide
     */
    @SystemApi
    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
    public void removeOnMediaKeyEventSessionChangedListener(
            @NonNull OnMediaKeyEventSessionChangedListener listener) {
        Objects.requireNonNull(listener, "listener shouldn't be null");
        synchronized (mLock) {
            try {
                mMediaKeyEventSessionChangedCallbacks.remove(listener);
                if (mMediaKeyEventSessionChangedCallbacks.size() == 0) {
                if (mMediaKeyEventSessionChangedCallbacks.remove(listener) != null
                        && mMediaKeyEventSessionChangedCallbacks.isEmpty()) {
                    mService.removeOnMediaKeyEventSessionChangedListener(
                            mOnMediaKeyEventSessionChangedListenerStub);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to set media key listener", e);
                Log.e(TAG, "Failed to remove MediaKeyEventSessionChangedListener", e);
            }
        }
    }
@@ -1124,16 +1147,14 @@ public final class MediaSessionManager {
    /**
     * Listener to receive changes in the media key event session, which would receive a media key
     * event unless specified.
     * @hide
     */
    @SystemApi
    public interface OnMediaKeyEventSessionChangedListener {
        /**
         * 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,
         * The session token can be {@code null} if the media button session is unset. In that case,
         * packageName will return the package name of the last session's media button receiver, or
         * an empty string if the last session didn't set a media button receiver.
         *
+15 −11
Original line number Diff line number Diff line
@@ -1587,19 +1587,25 @@ public class MediaSessionService extends SystemService implements Monitor {

        @Override
        public void addOnMediaKeyEventSessionChangedListener(
                final IOnMediaKeyEventSessionChangedListener listener) {
                final IOnMediaKeyEventSessionChangedListener listener,
                final ComponentName notificationListener) {
            if (listener == null) {
                Log.w(TAG, "addOnMediaKeyEventSessionChangedListener: lister is null, ignoring");
                Log.w(TAG, "addOnMediaKeyEventSessionChangedListener: listener is null, ignoring");
                return;
            }

            final int pid = Binder.getCallingPid();
            final int uid = Binder.getCallingUid();
            final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
            final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
            final int userId = userHandle.getIdentifier();
            final long token = Binder.clearCallingIdentity();
            try {
                if (!hasMediaControlPermission(pid, uid)) {
                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
                            + "  add MediaKeyEventSessionChangedListener");
                if (!hasMediaControlPermission(pid, uid)
                        && !isEnabledNotificationListener(
                                notificationListener, userHandle, userId)) {
                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission or an enabled"
                            + " notification listener is required to"
                            + " add MediaKeyEventSessionChangedListener.");
                }
                synchronized (mLock) {
                    FullUserRecord user = getFullUserRecordLocked(userId);
@@ -1621,18 +1627,16 @@ public class MediaSessionService extends SystemService implements Monitor {
        public void removeOnMediaKeyEventSessionChangedListener(
                final IOnMediaKeyEventSessionChangedListener listener) {
            if (listener == null) {
                Log.w(TAG, "removeOnMediaKeyEventSessionChangedListener: lister is null, ignoring");
                Log.w(TAG, "removeOnMediaKeyEventSessionChangedListener: listener is null,"
                        + " ignoring");
                return;
            }

            final int pid = Binder.getCallingPid();
            final int uid = Binder.getCallingUid();
            final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
            final long token = Binder.clearCallingIdentity();
            try {
                if (!hasMediaControlPermission(pid, uid)) {
                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
                            + "  remove MediaKeyEventSessionChangedListener");
                }
                synchronized (mLock) {
                    FullUserRecord user = getFullUserRecordLocked(userId);
                    if (user == null || user.mFullUserId != userId) {