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

Commit c7840a9c authored by Hyundo Moon's avatar Hyundo Moon
Browse files

MediaController2: Implement setVolumeTo/adjustVolume for remote volume

This CL implements MediaController2.setVolumeTo/adjustVolume for the
case when a volume provider is set.

Bug: 72788940
Test: Passed MediaController2Test
Change-Id: Ia87ca5dfb0957930849ac647b54470b8e9a3d220
parent 489b3604
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -40,6 +40,9 @@ interface IMediaSession2 {
    void connect(String callingPackage, IMediaSession2Callback callback);
    void release(IMediaSession2Callback caller);

    void setVolumeTo(IMediaSession2Callback caller, int value, int flags);
    void adjustVolume(IMediaSession2Callback caller, int direction, int flags);

    //////////////////////////////////////////////////////////////////////////////////////////////
    // send command
    //////////////////////////////////////////////////////////////////////////////////////////////
+22 −2
Original line number Diff line number Diff line
@@ -286,12 +286,32 @@ public class MediaController2Impl implements MediaController2Provider {

    @Override
    public void setVolumeTo_impl(int value, int flags) {
        // TODO(jaewan): Implement
        // TODO(hdmoon): sanity check
        final IMediaSession2 binder = mSessionBinder;
        if (binder != null) {
            try {
                binder.setVolumeTo(mSessionCallbackStub, value, flags);
            } catch (RemoteException e) {
                Log.w(TAG, "Cannot connect to the service or the session is gone", e);
            }
        } else {
            Log.w(TAG, "Session isn't active", new IllegalStateException());
        }
    }

    @Override
    public void adjustVolume_impl(int direction, int flags) {
        // TODO(jaewan): Implement
        // TODO(hdmoon): sanity check
        final IMediaSession2 binder = mSessionBinder;
        if (binder != null) {
            try {
                binder.adjustVolume(mSessionCallbackStub, direction, flags);
            } catch (RemoteException e) {
                Log.w(TAG, "Cannot connect to the service or the session is gone", e);
            }
        } else {
            Log.w(TAG, "Session isn't active", new IllegalStateException());
        }
    }

    @Override
+4 −0
Original line number Diff line number Diff line
@@ -559,6 +559,10 @@ public class MediaSession2Impl implements MediaSession2Provider {
        return mCallback;
    }

    VolumeProvider2 getVolumeProvider() {
        return mVolumeProvider;
    }

    private static class MyPlaybackListener implements MediaPlayerInterface.PlaybackListener {
        private final WeakReference<MediaSession2Impl> mSession;
        private final MediaPlayerInterface mPlayer;
+77 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.media.MediaSession2.CommandGroup;
import android.media.MediaSession2.ControllerInfo;
import android.media.MediaSession2.PlaylistParams;
import android.media.PlaybackState2;
import android.media.VolumeProvider2;
import android.media.update.MediaSession2Provider.CommandButtonProvider;
import android.os.Binder;
import android.os.Bundle;
@@ -161,6 +162,82 @@ public class MediaSession2Stub extends IMediaSession2.Stub {
        }
    }

    @Override
    public void setVolumeTo(IMediaSession2Callback caller, int value, int flags)
            throws RuntimeException {
        final MediaSession2Impl sessionImpl = getSession();
        final ControllerInfo controller = getController(caller);
        if (controller == null) {
            if (DEBUG) {
                Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
            }
            return;
        }
        sessionImpl.getCallbackExecutor().execute(() -> {
            final MediaSession2Impl session = mSession.get();
            if (session == null) {
                return;
            }
            // TODO(jaewan): Sanity check.
            Command command = new Command(
                    session.getContext(), MediaSession2.COMMAND_CODE_SET_VOLUME);
            boolean accepted = session.getCallback().onCommandRequest(controller, command);
            if (!accepted) {
                // Don't run rejected command.
                if (DEBUG) {
                    Log.d(TAG, "Command " + MediaSession2.COMMAND_CODE_SET_VOLUME + " from "
                            + controller + " was rejected by " + session);
                }
                return;
            }

            VolumeProvider2 volumeProvider = session.getVolumeProvider();
            if (volumeProvider == null) {
                // TODO(jaewan): Set local stream volume
            } else {
                volumeProvider.onSetVolumeTo(value);
            }
        });
    }

    @Override
    public void adjustVolume(IMediaSession2Callback caller, int direction, int flags)
            throws RuntimeException {
        final MediaSession2Impl sessionImpl = getSession();
        final ControllerInfo controller = getController(caller);
        if (controller == null) {
            if (DEBUG) {
                Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
            }
            return;
        }
        sessionImpl.getCallbackExecutor().execute(() -> {
            final MediaSession2Impl session = mSession.get();
            if (session == null) {
                return;
            }
            // TODO(jaewan): Sanity check.
            Command command = new Command(
                    session.getContext(), MediaSession2.COMMAND_CODE_SET_VOLUME);
            boolean accepted = session.getCallback().onCommandRequest(controller, command);
            if (!accepted) {
                // Don't run rejected command.
                if (DEBUG) {
                    Log.d(TAG, "Command " + MediaSession2.COMMAND_CODE_SET_VOLUME + " from "
                            + controller + " was rejected by " + session);
                }
                return;
            }

            VolumeProvider2 volumeProvider = session.getVolumeProvider();
            if (volumeProvider == null) {
                // TODO(jaewan): Adjust local stream volume
            } else {
                volumeProvider.onAdjustVolume(direction);
            }
        });
    }

    @Override
    public void sendCommand(IMediaSession2Callback caller, Bundle command, Bundle args)
            throws RuntimeException {
+64 −1
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

package android.media;

import android.media.MediaController2.ControllerCallback;
import android.content.Context;
import android.media.MediaPlayerInterface.PlaybackListener;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.ControllerInfo;
@@ -223,6 +223,42 @@ public class MediaController2Test extends MediaSession2TestBase {
        ensurePlaylistParamsModeEquals(params, controller.getPlaylistParams());
    }

    @Test
    public void testSetVolumeTo() throws Exception {
        final int maxVolume = 100;
        final int currentVolume = 23;
        final int volumeControlType = VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
        TestVolumeProvider volumeProvider =
                new TestVolumeProvider(mContext, volumeControlType, maxVolume, currentVolume);

        mSession.setPlayer(new MockPlayer(0), volumeProvider);
        final MediaController2 controller = createController(mSession.getToken(), true, null);

        final int targetVolume = 50;
        controller.setVolumeTo(targetVolume, 0 /* flags */);
        assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
        assertTrue(volumeProvider.mSetVolumeToCalled);
        assertEquals(targetVolume, volumeProvider.mVolume);
    }

    @Test
    public void testAdjustVolume() throws Exception {
        final int maxVolume = 100;
        final int currentVolume = 23;
        final int volumeControlType = VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
        TestVolumeProvider volumeProvider =
                new TestVolumeProvider(mContext, volumeControlType, maxVolume, currentVolume);

        mSession.setPlayer(new MockPlayer(0), volumeProvider);
        final MediaController2 controller = createController(mSession.getToken(), true, null);

        final int direction = AudioManager.ADJUST_RAISE;
        controller.adjustVolume(direction, 0 /* flags */);
        assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
        assertTrue(volumeProvider.mAdjustVolumeCalled);
        assertEquals(direction, volumeProvider.mDirection);
    }

    @Test
    public void testGetPackageName() {
        assertEquals(mContext.getPackageName(), mController.getSessionToken().getPackageName());
@@ -570,4 +606,31 @@ public class MediaController2Test extends MediaSession2TestBase {

    // TODO(jaewan): Add  test for service connect rejection, when we differentiate session
    //               active/inactive and connection accept/refuse

    class TestVolumeProvider extends VolumeProvider2 {
        final CountDownLatch mLatch = new CountDownLatch(1);
        boolean mSetVolumeToCalled;
        boolean mAdjustVolumeCalled;
        int mVolume;
        int mDirection;

        public TestVolumeProvider(Context context, int controlType, int maxVolume,
                int currentVolume) {
            super(context, controlType, maxVolume, currentVolume);
        }

        @Override
        public void onSetVolumeTo(int volume) {
            mSetVolumeToCalled = true;
            mVolume = volume;
            mLatch.countDown();
        }

        @Override
        public void onAdjustVolume(int direction) {
            mAdjustVolumeCalled = true;
            mDirection = direction;
            mLatch.countDown();
        }
    }
}