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

Commit 8aa7f0f0 authored by Sandeep Samdaria's avatar Sandeep Samdaria Committed by Automerger Merge Worker
Browse files

Merge "Media session should start on audio focus" am: f3ac5e2b am: 195c8d88

parents fa235124 195c8d88
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -135,7 +135,7 @@ public class A2dpSinkStreamHandler extends Handler {
    public void handleMessage(Message message) {
        if (DBG) {
            Log.d(TAG, " process message: " + message.what);
            Log.d(TAG, " audioFocus =  " + mAudioFocus);
            Log.d(TAG, " current audioFocus state =  " + mAudioFocus);
        }
        switch (message.what) {
            case SRC_STR_START:
@@ -183,7 +183,12 @@ public class A2dpSinkStreamHandler extends Handler {
                break;

            case AUDIO_FOCUS_CHANGE:
                mAudioFocus = (int) message.obj;
                final int focusChangeCode = (int) message.obj;
                if (DBG) {
                    Log.d(TAG, "New audioFocus =  " + focusChangeCode
                            + " Previous audio focus = " + mAudioFocus);
                }
                mAudioFocus = focusChangeCode;
                // message.obj is the newly granted audio focus.
                switch (mAudioFocus) {
                    case AudioManager.AUDIOFOCUS_GAIN:
@@ -221,7 +226,7 @@ public class A2dpSinkStreamHandler extends Handler {
                AvrcpControllerService avrcpControllerService =
                        AvrcpControllerService.getAvrcpControllerService();
                if (avrcpControllerService != null) {
                    avrcpControllerService.onAudioFocusStateChanged(mAudioFocus);
                    avrcpControllerService.onAudioFocusStateChanged(focusChangeCode);
                } else {
                    Log.w(TAG, "AVRCP Controller Service not available to send focus events to.");
                }
@@ -259,8 +264,12 @@ public class A2dpSinkStreamHandler extends Handler {
        int focusRequestStatus = mAudioManager.requestAudioFocus(focusRequest);
        // If the request is granted begin streaming immediately and schedule an upgrade.
        if (focusRequestStatus == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
            startFluorideStreaming();
            mAudioFocus = AudioManager.AUDIOFOCUS_GAIN;
            final Message a2dpSinkStreamHandlerMessage = A2dpSinkStreamHandler.this
                    .obtainMessage(AUDIO_FOCUS_CHANGE, mAudioFocus);
            A2dpSinkStreamHandler.this.sendMessageAtFrontOfQueue(a2dpSinkStreamHandlerMessage);
        } else {
            Log.e(TAG, "Audio focus was not granted:" + focusRequestStatus);
        }
        return focusRequestStatus;
    }
+9 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.bluetooth.BluetoothProfile;
import android.bluetooth.IBluetoothAvrcpController;
import android.content.AttributionSource;
import android.content.Intent;
import android.media.AudioManager;
import android.support.v4.media.MediaBrowserCompat.MediaItem;
import android.support.v4.media.session.PlaybackStateCompat;
import android.sysprop.BluetoothProperties;
@@ -510,13 +511,11 @@ public class AvrcpControllerService extends ProfileService {
            // The first device to connect gets to be the active device
            if (getActiveDevice() == null) {
                setActiveDevice(device);
                BluetoothMediaBrowserService.setActive(true);
            }
        } else {
            stateMachine.disconnect();
            if (device.equals(getActiveDevice())) {
                setActiveDevice(null);
                BluetoothMediaBrowserService.setActive(false);
            }
        }
    }
@@ -585,6 +584,14 @@ public class AvrcpControllerService extends ProfileService {
        // Make sure the active device isn't changed while we're processing the event so play/pause
        // commands get routed to the correct device
        synchronized (mActiveDeviceLock) {
            switch (state) {
                case AudioManager.AUDIOFOCUS_GAIN:
                    BluetoothMediaBrowserService.setActive(true);
                    break;
                case AudioManager.AUDIOFOCUS_LOSS:
                    BluetoothMediaBrowserService.setActive(false);
                    break;
            }
            BluetoothDevice device = getActiveDevice();
            if (device == null) {
                Log.w(TAG, "No active device set, ignore focus change");
+14 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import androidx.media.MediaBrowserServiceCompat;

import com.android.bluetooth.BluetoothPrefs;
import com.android.bluetooth.R;
import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
import java.util.List;
@@ -304,12 +305,24 @@ public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat {
     */
    public static synchronized void setActive(boolean active) {
        if (sBluetoothMediaBrowserService != null) {
            if (DBG) Log.d(TAG, "Setting the session active state to:" + active);
            sBluetoothMediaBrowserService.mSession.setActive(active);
        } else {
            Log.w(TAG, "setActive Unavailable");
        }
    }

    /**
     * Checks if the media session is active or not.
     * @return true if media session is active, false otherwise.
     */
    @VisibleForTesting
    public static synchronized boolean isActive() {
        if (sBluetoothMediaBrowserService != null) {
            return sBluetoothMediaBrowserService.mSession.isActive();
        }
        return false;
    }
    /**
     * Get Media session for updating state
     */
@@ -371,6 +384,7 @@ public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat {
            sb.append("\n    playbackState=" + playbackState);
            sb.append("\n    queue=" + queue);
            sb.append("\n    internal_queue=" + sBluetoothMediaBrowserService.mMediaQueue);
            sb.append("\n    session active state=").append(isActive());
        } else {
            Log.w(TAG, "dump Unavailable");
            sb.append(" null");
+3 −3
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ public class TestUtils {
            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        Assert.assertNull("AdapterService.getAdapterService() must be null before setting another"
                + " AdapterService", AdapterService.getAdapterService());
        Assert.assertNotNull(adapterService);
        Assert.assertNotNull("Adapter service should not be null", adapterService);
        // We cannot mock AdapterService.getAdapterService() with Mockito.
        // Hence we need to use reflection to call a private method to
        // initialize properly the AdapterService.sAdapterService field.
@@ -119,7 +119,7 @@ public class TestUtils {
        Assert.assertSame("AdapterService.getAdapterService() must return the same object as the"
                        + " supplied adapterService in this method", adapterService,
                AdapterService.getAdapterService());
        Assert.assertNotNull(adapterService);
        Assert.assertNotNull("Adapter service should not be null", adapterService);
        Method method =
                AdapterService.class.getDeclaredMethod("clearAdapterService", AdapterService.class);
        method.setAccessible(true);
@@ -142,7 +142,7 @@ public class TestUtils {
    public static <T extends ProfileService> void startService(ServiceTestRule serviceTestRule,
            Class<T> profileServiceClass) throws TimeoutException {
        AdapterService adapterService = AdapterService.getAdapterService();
        Assert.assertNotNull(adapterService);
        Assert.assertNotNull("Adapter service should not be null", adapterService);
        Assert.assertTrue("AdapterService.getAdapterService() must return a mocked or spied object"
                + " before calling this method", MockUtil.isMock(adapterService));
        Intent startIntent =
+40 −8
Original line number Diff line number Diff line
@@ -29,13 +29,19 @@ import android.os.Looper;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.rule.ServiceTestRule;
import androidx.test.runner.AndroidJUnit4;

import com.android.bluetooth.R;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.avrcpcontroller.AvrcpControllerService;
import com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService;
import com.android.bluetooth.btservice.AdapterService;

import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -59,14 +65,23 @@ public class A2dpSinkStreamHandlerTest {

    @Mock private PackageManager mMockPackageManager;

    @Rule
    public final ServiceTestRule mServiceRule = new ServiceTestRule();

    @Mock
    private AdapterService mAdapterService;

    @Before
    public void setUp() {
    public void setUp() throws Exception{
        mTargetContext = InstrumentationRegistry.getTargetContext();
        MockitoAnnotations.initMocks(this);
        // Mock the looper
        if (Looper.myLooper() == null) {
            Looper.prepare();
        }
        TestUtils.setAdapterService(mAdapterService);
        doReturn(true, false).when(mAdapterService).isStartedProfile(anyString());
        TestUtils.startService(mServiceRule, AvrcpControllerService.class);

        mHandlerThread = new HandlerThread("A2dpSinkStreamHandlerTest");
        mHandlerThread.start();
@@ -86,6 +101,13 @@ public class A2dpSinkStreamHandlerTest {
        when(mMockPackageManager.hasSystemFeature(any())).thenReturn(false);

        mStreamHandler = spy(new A2dpSinkStreamHandler(mMockA2dpSink, mMockNativeInterface));
        BluetoothMediaBrowserService.setActive(false);
    }

    @After
    public void tearDown() throws Exception {
        TestUtils.stopService(mServiceRule, AvrcpControllerService.class);
        TestUtils.clearAdapterService(mAdapterService);
    }

    @Test
@@ -97,6 +119,7 @@ public class A2dpSinkStreamHandlerTest {
        verify(mMockNativeInterface, times(0)).informAudioFocusState(1);
        verify(mMockNativeInterface, times(0)).informAudioTrackGain(1.0f);
        assertThat(mStreamHandler.isPlaying()).isFalse();
        assertThat(BluetoothMediaBrowserService.isActive()).isFalse();
    }

    @Test
@@ -108,6 +131,7 @@ public class A2dpSinkStreamHandlerTest {
        verify(mMockNativeInterface, times(0)).informAudioFocusState(1);
        verify(mMockNativeInterface, times(0)).informAudioTrackGain(1.0f);
        assertThat(mStreamHandler.isPlaying()).isFalse();
        assertThat(BluetoothMediaBrowserService.isActive()).isFalse();
    }

    @Test
@@ -115,9 +139,8 @@ public class A2dpSinkStreamHandlerTest {
        // Play was pressed locally, expect streaming to start soon.
        mStreamHandler.handleMessage(mStreamHandler.obtainMessage(A2dpSinkStreamHandler.SNK_PLAY));
        verify(mMockAudioManager, times(1)).requestAudioFocus(any());
        verify(mMockNativeInterface, times(1)).informAudioFocusState(1);
        verify(mMockNativeInterface, times(1)).informAudioTrackGain(1.0f);
        assertThat(mStreamHandler.isPlaying()).isFalse();
        assertThat(BluetoothMediaBrowserService.isActive()).isFalse();
    }

    @Test
@@ -128,6 +151,7 @@ public class A2dpSinkStreamHandlerTest {
        verify(mMockNativeInterface, times(0)).informAudioFocusState(1);
        verify(mMockNativeInterface, times(0)).informAudioTrackGain(1.0f);
        assertThat(mStreamHandler.isPlaying()).isFalse();
        assertThat(BluetoothMediaBrowserService.isActive()).isFalse();
    }

    @Test
@@ -139,6 +163,7 @@ public class A2dpSinkStreamHandlerTest {
        verify(mMockAudioManager, times(0)).abandonAudioFocus(any());
        verify(mMockNativeInterface, times(0)).informAudioFocusState(0);
        assertThat(mStreamHandler.isPlaying()).isFalse();
        assertThat(BluetoothMediaBrowserService.isActive()).isFalse();
    }

    @Test
@@ -149,6 +174,7 @@ public class A2dpSinkStreamHandlerTest {
        verify(mMockNativeInterface, times(0)).informAudioFocusState(1);
        verify(mMockNativeInterface, times(0)).informAudioTrackGain(1.0f);
        assertThat(mStreamHandler.isPlaying()).isFalse();
        assertThat(BluetoothMediaBrowserService.isActive()).isFalse();
    }

    @Test
@@ -157,8 +183,7 @@ public class A2dpSinkStreamHandlerTest {
        when(mMockPackageManager.hasSystemFeature(any())).thenReturn(true);
        mStreamHandler.handleMessage(mStreamHandler.obtainMessage(A2dpSinkStreamHandler.SRC_PLAY));
        verify(mMockAudioManager, times(1)).requestAudioFocus(any());
        verify(mMockNativeInterface, times(1)).informAudioFocusState(1);
        verify(mMockNativeInterface, times(1)).informAudioTrackGain(1.0f);
        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
        assertThat(mStreamHandler.isPlaying()).isTrue();
    }

@@ -180,11 +205,12 @@ public class A2dpSinkStreamHandlerTest {
                mStreamHandler.obtainMessage(A2dpSinkStreamHandler.AUDIO_FOCUS_CHANGE,
                        AudioManager.AUDIOFOCUS_GAIN));
        verify(mMockAudioManager, times(1)).requestAudioFocus(any());
        verify(mMockNativeInterface, times(2)).informAudioFocusState(1);
        verify(mMockNativeInterface, times(2)).informAudioTrackGain(1.0f);
        verify(mMockNativeInterface, times(1)).informAudioFocusState(1);
        verify(mMockNativeInterface, times(1)).informAudioTrackGain(1.0f);

        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
        assertThat(mStreamHandler.getFocusState()).isEqualTo(AudioManager.AUDIOFOCUS_GAIN);
        assertThat(BluetoothMediaBrowserService.isActive()).isTrue();
    }

    @Test
@@ -199,6 +225,7 @@ public class A2dpSinkStreamHandlerTest {
        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
        assertThat(mStreamHandler.getFocusState()).isEqualTo(
                AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK);
        assertThat(BluetoothMediaBrowserService.isActive()).isFalse();
    }

    @Test
@@ -215,6 +242,7 @@ public class A2dpSinkStreamHandlerTest {
        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
        assertThat(mStreamHandler.getFocusState()).isEqualTo(
                AudioManager.AUDIOFOCUS_LOSS_TRANSIENT);
        assertThat(BluetoothMediaBrowserService.isActive()).isFalse();
    }

    @Test
@@ -230,6 +258,8 @@ public class A2dpSinkStreamHandlerTest {
        mStreamHandler.handleMessage(
                mStreamHandler.obtainMessage(A2dpSinkStreamHandler.REQUEST_FOCUS, true));
        verify(mMockAudioManager, times(2)).requestAudioFocus(any());
        assertThat(BluetoothMediaBrowserService.isActive()).isFalse();
        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
    }

    @Test
@@ -241,9 +271,10 @@ public class A2dpSinkStreamHandlerTest {
                mStreamHandler.obtainMessage(A2dpSinkStreamHandler.AUDIO_FOCUS_CHANGE,
                        AudioManager.AUDIOFOCUS_GAIN));
        verify(mMockAudioManager, times(0)).abandonAudioFocus(any());
        verify(mMockNativeInterface, times(2)).informAudioTrackGain(1.0f);
        verify(mMockNativeInterface, times(1)).informAudioTrackGain(1.0f);

        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
        assertThat(BluetoothMediaBrowserService.isActive()).isTrue();
        assertThat(mStreamHandler.getFocusState()).isEqualTo(AudioManager.AUDIOFOCUS_GAIN);
    }

@@ -258,6 +289,7 @@ public class A2dpSinkStreamHandlerTest {
        verify(mMockNativeInterface, times(1)).informAudioFocusState(0);

        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
        assertThat(BluetoothMediaBrowserService.isActive()).isFalse();
        assertThat(mStreamHandler.getFocusState()).isEqualTo(AudioManager.AUDIOFOCUS_NONE);
        assertThat(mStreamHandler.isPlaying()).isFalse();
    }
Loading