AVRCP Controller request focus when idle

When no music is playing and an incoming play request comes in from a
paired device, request focus on it's behalf.

Bug: 135112399
Test: atest com.android.bluetooth.avrcpcontroller.AvrcpControllerStateMachineTest
Change-Id: Ia764ea54af95166be6b6c3d9b47f3e3c2d09a0d7
(cherry picked from commit e6ff50d6328dca536acd131d91c109072febd70f)

Merged-In: Ia764ea54af95166be6b6c3d9b47f3e3c2d09a0d7
Change-Id: I16d132e6fc90c1bb0f21d05de3ddf877ff5ea5b4
diff --git a/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java b/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java
index e41def0..5271cc7 100644
--- a/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java
+++ b/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java
@@ -413,7 +413,8 @@
         if (state == StackEvent.AUDIO_STATE_STARTED) {
             mA2dpSinkStreamHandler.obtainMessage(
                     A2dpSinkStreamHandler.SRC_STR_START).sendToTarget();
-        } else if (state == StackEvent.AUDIO_STATE_STOPPED) {
+        } else if (state == StackEvent.AUDIO_STATE_STOPPED
+                || state == StackEvent.AUDIO_STATE_REMOTE_SUSPEND) {
             mA2dpSinkStreamHandler.obtainMessage(
                     A2dpSinkStreamHandler.SRC_STR_STOP).sendToTarget();
         }
diff --git a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
index 83ba850..23f1ce7 100644
--- a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
+++ b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
@@ -361,10 +361,13 @@
                     BluetoothMediaBrowserService.notifyChanged(mAddressedPlayer.getPlaybackState());
                     if (mAddressedPlayer.getPlaybackState().getState()
                             == PlaybackStateCompat.STATE_PLAYING
-                            && A2dpSinkService.getFocusState() == AudioManager.AUDIOFOCUS_NONE
-                            && !shouldRequestFocus()) {
+                            && A2dpSinkService.getFocusState() == AudioManager.AUDIOFOCUS_NONE) {
+                        if (shouldRequestFocus()) {
+                            mSessionCallbacks.onPrepare();
+                        } else {
                         sendMessage(MSG_AVRCP_PASSTHRU,
                                 AvrcpControllerService.PASS_THRU_CMD_ID_PAUSE);
+                        }
                     }
                     return true;
 
@@ -882,6 +885,7 @@
 
     private boolean shouldRequestFocus() {
         return mService.getResources()
-                .getBoolean(R.bool.a2dp_sink_automatically_request_audio_focus);
+                .getBoolean(R.bool.a2dp_sink_automatically_request_audio_focus)
+                || !mAudioManager.isMusicActive();
     }
 }
diff --git a/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java b/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
index 4c77e0a..c766c7c 100644
--- a/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
+++ b/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
@@ -26,6 +26,7 @@
 import android.media.AudioManager;
 import android.os.Looper;
 import android.support.v4.media.session.MediaControllerCompat;
+import android.support.v4.media.session.PlaybackStateCompat;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.MediumTest;
@@ -34,6 +35,7 @@
 
 import com.android.bluetooth.R;
 import com.android.bluetooth.TestUtils;
+import com.android.bluetooth.a2dpsink.A2dpSinkService;
 import com.android.bluetooth.btservice.AdapterService;
 import com.android.bluetooth.btservice.ProfileService;
 
@@ -66,10 +68,15 @@
     private ArgumentCaptor<Intent> mIntentArgument = ArgumentCaptor.forClass(Intent.class);
     private byte[] mTestAddress = new byte[]{00, 01, 02, 03, 04, 05};
 
-    @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule();
+    @Rule public final ServiceTestRule mAvrcpServiceRule = new ServiceTestRule();
+    @Rule public final ServiceTestRule mA2dpServiceRule = new ServiceTestRule();
 
     @Mock
-    private AdapterService mAdapterService;
+    private AdapterService mAvrcpAdapterService;
+
+    @Mock
+    private AdapterService mA2dpAdapterService;
+
     @Mock
     private AudioManager mAudioManager;
     @Mock
@@ -90,8 +97,11 @@
 
         // Setup mocks and test assets
         MockitoAnnotations.initMocks(this);
-        TestUtils.setAdapterService(mAdapterService);
-        TestUtils.startService(mServiceRule, AvrcpControllerService.class);
+        TestUtils.setAdapterService(mAvrcpAdapterService);
+        TestUtils.startService(mAvrcpServiceRule, AvrcpControllerService.class);
+        TestUtils.clearAdapterService(mAvrcpAdapterService);
+        TestUtils.setAdapterService(mA2dpAdapterService);
+        TestUtils.startService(mA2dpServiceRule, A2dpSinkService.class);
         doReturn(mTargetContext.getResources()).when(mAvrcpControllerService).getResources();
         doReturn(15).when(mAudioManager).getStreamMaxVolume(anyInt());
         doReturn(8).when(mAudioManager).getStreamVolume(anyInt());
@@ -113,7 +123,7 @@
         if (!mTargetContext.getResources().getBoolean(R.bool.profile_supported_avrcp_controller)) {
             return;
         }
-        TestUtils.clearAdapterService(mAdapterService);
+        TestUtils.clearAdapterService(mA2dpAdapterService);
     }
 
     /**
@@ -545,6 +555,45 @@
     }
 
     /**
+     * Test playback does not request focus when another app is playing music.
+     */
+    @Test
+    public void testPlaybackWhileMusicPlaying() {
+        Assert.assertEquals(AudioManager.AUDIOFOCUS_NONE, A2dpSinkService.getFocusState());
+        doReturn(true).when(mAudioManager).isMusicActive();
+        setUpConnectedState(true, true);
+        mAvrcpStateMachine.sendMessage(
+                AvrcpControllerStateMachine.MESSAGE_PROCESS_PLAY_STATUS_CHANGED,
+                PlaybackStateCompat.STATE_PLAYING);
+        TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper());
+        verify(mAudioManager, times(1)).isMusicActive();
+        verify(mAvrcpControllerService,
+                timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)).sendPassThroughCommandNative(
+                eq(mTestAddress), eq(AvrcpControllerService.PASS_THRU_CMD_ID_PAUSE), eq(KEY_DOWN));
+        TestUtils.waitForLooperToFinishScheduledTask(
+                A2dpSinkService.getA2dpSinkService().getMainLooper());
+        Assert.assertEquals(AudioManager.AUDIOFOCUS_NONE, A2dpSinkService.getFocusState());
+    }
+
+    /**
+     * Test playback requests focus while nothing is playing music.
+     */
+    @Test
+    public void testPlaybackWhileIdle() {
+        Assert.assertEquals(AudioManager.AUDIOFOCUS_NONE, A2dpSinkService.getFocusState());
+        doReturn(false).when(mAudioManager).isMusicActive();
+        setUpConnectedState(true, true);
+        mAvrcpStateMachine.sendMessage(
+                AvrcpControllerStateMachine.MESSAGE_PROCESS_PLAY_STATUS_CHANGED,
+                PlaybackStateCompat.STATE_PLAYING);
+        TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper());
+        verify(mAudioManager, times(1)).isMusicActive();
+        TestUtils.waitForLooperToFinishScheduledTask(
+                A2dpSinkService.getA2dpSinkService().getMainLooper());
+        Assert.assertEquals(AudioManager.AUDIOFOCUS_GAIN, A2dpSinkService.getFocusState());
+    }
+
+    /**
      * Setup Connected State
      *
      * @return number of times mAvrcpControllerService.sendBroadcastAsUser() has been invoked