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

Commit bac9bb86 authored by Dave Rim's avatar Dave Rim
Browse files

Enable bluetooth a2dpsink to request audio focus from source

- Allow source to initiate play on IoT devices without having audiofocus
  first
- Added mockPackageManager and testSrcPlayIot to A2dpSinkStreamHandler
  unit test

Test: Bluetooth a2dp sink works using the sample-audio-bluetooth
      sample app
Bug: 38098044
Change-Id: I98472c857afa4922ae9ce118c1bcf0f801ffd304
parent e1c09d19
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.bluetooth.a2dpsink;

import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioManager.OnAudioFocusChangeListener;
@@ -131,7 +132,16 @@ public class A2dpSinkStreamHandler extends Handler {
                break;

            case SRC_PLAY:
                // Remote play command, if we have audio focus update avrcp, otherwise send pause.
                // Remote play command.
                // If is an iot device gain focus and start avrcp updates.
                if (isIotDevice()) {
                    if (mAudioFocus == AudioManager.AUDIOFOCUS_NONE) {
                        requestAudioFocus();
                    }
                    startAvrcpUpdates();
                    break;
                }
                // Otherwise, pause if we don't have focus
                if (mAudioFocus == AudioManager.AUDIOFOCUS_NONE) {
                    sendAvrcpPause();
                } else {
@@ -311,4 +321,8 @@ public class A2dpSinkStreamHandler extends Handler {
            Log.e(TAG, "Passthrough not sent, connection un-available.");
        }
    }

    private boolean isIotDevice() {
        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_EMBEDDED);
    }
}
+15 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.media.AudioManager;
import android.media.AudioManager.OnAudioFocusChangeListener;
@@ -56,6 +57,8 @@ public class A2dpSinkStreamHandlerTest extends AndroidTestCase {

    @Mock Resources mockResources;

    @Mock PackageManager mockPackageManager;

    @Before
    public void setUp() {
        // Mock the looper
@@ -77,6 +80,8 @@ public class A2dpSinkStreamHandlerTest extends AndroidTestCase {
        when(mockAudioManager.abandonAudioFocus(any())).thenReturn(AudioManager.AUDIOFOCUS_GAIN);
        doNothing().when(mockA2dpSink).informAudioTrackGainNative(anyFloat());
        when(mockContext.getMainLooper()).thenReturn(mHandlerThread.getLooper());
        when(mockContext.getPackageManager()).thenReturn(mockPackageManager);
        when(mockPackageManager.hasSystemFeature(any())).thenReturn(false);

        streamHandler = spy(new A2dpSinkStreamHandler(mockA2dpSink, mockContext));
    }
@@ -137,6 +142,16 @@ public class A2dpSinkStreamHandlerTest extends AndroidTestCase {
        verify(mockA2dpSink, times(0)).informAudioTrackGainNative(1.0f);
    }

    @Test
    public void testSrcPlayIot() {
        // Play was pressed remotely for an iot device, expect streaming to start.
        when(mockPackageManager.hasSystemFeature(any())).thenReturn(true);
        streamHandler.handleMessage(streamHandler.obtainMessage(A2dpSinkStreamHandler.SRC_PLAY));
        verify(mockAudioManager, times(1)).requestAudioFocus(any(), anyInt(), anyInt());
        verify(mockA2dpSink, times(1)).informAudioFocusStateNative(1);
        verify(mockA2dpSink, times(1)).informAudioTrackGainNative(1.0f);
    }

    @Test
    public void testSrcPause() {
        // Play was pressed locally, expect streaming to start.