AVRCP Controller AbsoluteVolumeNotification

Update AbsoluteVolumeNotification request to properly respond to
requests based upon the Fixed vs Dynamic volume levels.

Bug: 129478624
Test: atest com.android.bluetooth.avrcpcontroller.AvrcpControllerStateMachineTest#testRegisterAbsVolumeNotification
Merged-In: Ic9b745641a84712c005d40ecec50e55e9684d3ef
Merged-In: I610dd3eff955e926a2c52921c0ef347db80c0cae
(cherry picked from commit 3897e86022f7c061f874fffa6b8058d7fa4aa108)

Change-Id: I253484d27bf2e0a26307084c23ce983d281e6874
diff --git a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
index 1d1a635..66571c4 100644
--- a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
+++ b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
@@ -89,7 +89,14 @@
      */
     private static final int ABS_VOL_BASE = 127;
 
+    /*
+     * Notification types for Avrcp protocol JNI.
+     */
+    private static final byte NOTIFICATION_RSP_TYPE_INTERIM = 0x00;
+    private static final byte NOTIFICATION_RSP_TYPE_CHANGED = 0x01;
+
     private final AudioManager mAudioManager;
+    private final boolean mIsVolumeFixed;
 
     protected final BluetoothDevice mDevice;
     protected final byte[] mDeviceAddress;
@@ -108,6 +115,7 @@
     private int mAddressedPlayerId = -1;
     private SparseArray<AvrcpPlayer> mAvailablePlayerList = new SparseArray<AvrcpPlayer>();
     private int mVolumeChangedNotificationsToIgnore = 0;
+    private int mVolumeNotificationLabel = -1;
 
     GetFolderList mGetFolderList = null;
 
@@ -137,6 +145,7 @@
         mGetFolderList = new GetFolderList();
         addState(mGetFolderList, mConnected);
         mAudioManager = (AudioManager) service.getSystemService(Context.AUDIO_SERVICE);
+        mIsVolumeFixed = mAudioManager.isVolumeFixed();
 
         setInitialState(mDisconnected);
     }
@@ -309,6 +318,13 @@
                     setAbsVolume(msg.arg1, msg.arg2);
                     return true;
 
+                case MESSAGE_PROCESS_REGISTER_ABS_VOL_NOTIFICATION:
+                    mVolumeNotificationLabel = msg.arg1;
+                    mService.sendRegisterAbsVolRspNative(mDeviceAddress,
+                            NOTIFICATION_RSP_TYPE_INTERIM,
+                            getAbsVolumeResponse(), mVolumeNotificationLabel);
+                    return true;
+
                 case MESSAGE_GET_FOLDER_ITEMS:
                     transitionTo(mGetFolderList);
                     return true;
@@ -548,24 +564,9 @@
                     }
                     break;
 
-                case CONNECT:
-                case DISCONNECT:
-                case MSG_AVRCP_PASSTHRU:
-                case MESSAGE_PROCESS_SET_ABS_VOL_CMD:
-                case MESSAGE_PROCESS_REGISTER_ABS_VOL_NOTIFICATION:
-                case MESSAGE_PROCESS_TRACK_CHANGED:
-                case MESSAGE_PROCESS_PLAY_POS_CHANGED:
-                case MESSAGE_PROCESS_PLAY_STATUS_CHANGED:
-                case MESSAGE_PROCESS_VOLUME_CHANGED_NOTIFICATION:
-                case MESSAGE_PLAY_ITEM:
-                case MESSAGE_PROCESS_ADDRESSED_PLAYER_CHANGED:
+                default:
                     // All of these messages should be handled by parent state immediately.
                     return false;
-
-                default:
-                    logD(STATE_TAG + " deferring message " + msg.what
-                                + " to connected!");
-                    deferMessage(msg);
             }
             return true;
         }
@@ -694,7 +695,17 @@
             mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, newIndex,
                     AudioManager.FLAG_SHOW_UI);
         }
-        mService.sendAbsVolRspNative(mDeviceAddress, absVol, label);
+        mService.sendAbsVolRspNative(mDeviceAddress, getAbsVolumeResponse(), label);
+    }
+
+    private int getAbsVolumeResponse() {
+        if (mIsVolumeFixed) {
+            return ABS_VOL_BASE;
+        }
+        int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+        int currIndex = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
+        int newIndex = (currIndex * ABS_VOL_BASE) / maxVolume;
+        return newIndex;
     }
 
     MediaSession.Callback mSessionCallbacks = new MediaSession.Callback() {
diff --git a/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java b/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
index b1d1743..4fedc88 100644
--- a/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
+++ b/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
@@ -23,6 +23,7 @@
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.content.Intent;
+import android.media.AudioManager;
 import android.media.session.MediaController;
 import android.os.Looper;
 
@@ -70,6 +71,8 @@
     @Mock
     private AdapterService mAdapterService;
     @Mock
+    private AudioManager mAudioManager;
+    @Mock
     private AvrcpControllerService mAvrcpControllerService;
 
     AvrcpControllerStateMachine mAvrcpStateMachine;
@@ -90,6 +93,11 @@
         TestUtils.setAdapterService(mAdapterService);
         TestUtils.startService(mServiceRule, AvrcpControllerService.class);
         doReturn(mTargetContext.getResources()).when(mAvrcpControllerService).getResources();
+        doReturn(15).when(mAudioManager).getStreamMaxVolume(anyInt());
+        doReturn(8).when(mAudioManager).getStreamVolume(anyInt());
+        doReturn(true).when(mAudioManager).isVolumeFixed();
+        doReturn(mAudioManager).when(mAvrcpControllerService)
+                .getSystemService(Context.AUDIO_SERVICE);
 
         // This line must be called to make sure relevant objects are initialized properly
         mAdapter = BluetoothAdapter.getDefaultAdapter();
@@ -487,6 +495,18 @@
     }
 
     /**
+     * Test that Absolute Volume Registration is working
+     */
+    @Test
+    public void testRegisterAbsVolumeNotification() {
+        setUpConnectedState(true, true);
+        mAvrcpStateMachine.sendMessage(
+                AvrcpControllerStateMachine.MESSAGE_PROCESS_REGISTER_ABS_VOL_NOTIFICATION);
+        verify(mAvrcpControllerService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1))
+                .sendRegisterAbsVolRspNative(any(), anyByte(), eq(127), anyInt());
+    }
+
+    /**
      * Setup Connected State
      *
      * @return number of times mAvrcpControllerService.sendBroadcastAsUser() has been invoked