AdapterService: Check the PIN code length before using am: d6c84aa349
am: 460a9b814a

Change-Id: Ic1f8a10bc0284773d10f2c02883fe638b340d1af
diff --git a/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java b/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java
index c24eca9..5e3b356 100644
--- a/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java
+++ b/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java
@@ -24,6 +24,8 @@
 import android.media.AudioManager;
 import android.media.AudioManager.OnAudioFocusChangeListener;
 import android.media.MediaPlayer;
+import android.media.session.PlaybackState;
+
 import android.os.Handler;
 import android.os.Message;
 import android.util.Log;
@@ -225,7 +227,8 @@
                 break;
 
             case DELAYED_PAUSE:
-                if (mStreamAvailable && !inCallFromStreamingDevice()) {
+                if (BluetoothMediaBrowserService.getPlaybackState()
+                            == PlaybackState.STATE_PLAYING && !inCallFromStreamingDevice()) {
                     sendAvrcpPause();
                     mSentPause = true;
                     mStreamAvailable = false;
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/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java b/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java
index 3504cd4..304d5a2 100644
--- a/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java
+++ b/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java
@@ -177,6 +177,20 @@
     }
 
     /**
+     * Get playback state
+     */
+    public static synchronized int getPlaybackState() {
+        if (sBluetoothMediaBrowserService != null) {
+            PlaybackState currentPlaybackState =
+                    sBluetoothMediaBrowserService.mSession.getController().getPlaybackState();
+            if (currentPlaybackState != null) {
+                return currentPlaybackState.getState();
+            }
+        }
+        return PlaybackState.STATE_ERROR;
+    }
+
+    /**
      * Get object for controlling playback
      */
     public static synchronized MediaController.TransportControls getTransportControls() {
diff --git a/src/com/android/bluetooth/btservice/RemoteDevices.java b/src/com/android/bluetooth/btservice/RemoteDevices.java
index 46e28a5..2965715 100644
--- a/src/com/android/bluetooth/btservice/RemoteDevices.java
+++ b/src/com/android/bluetooth/btservice/RemoteDevices.java
@@ -320,6 +320,7 @@
                     without waiting for the ACTION_UUID intent.
                     This was resulting in multiple calls to connect().*/
                     mUuids = null;
+                    mAlias = null;
                 }
             }
         }
diff --git a/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java b/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java
index 53e8419..c759a8a 100644
--- a/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java
+++ b/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java
@@ -195,6 +195,24 @@
     }
 
     @Test
+    public void testFocusGainTransient() {
+        // Focus was lost then regained.
+        testSnkPlay();
+        mStreamHandler.handleMessage(
+                mStreamHandler.obtainMessage(A2dpSinkStreamHandler.AUDIO_FOCUS_CHANGE,
+                        AudioManager.AUDIOFOCUS_LOSS_TRANSIENT));
+        mStreamHandler.handleMessage(
+                mStreamHandler.obtainMessage(A2dpSinkStreamHandler.DELAYED_PAUSE));
+        mStreamHandler.handleMessage(
+                mStreamHandler.obtainMessage(A2dpSinkStreamHandler.AUDIO_FOCUS_CHANGE,
+                        AudioManager.AUDIOFOCUS_GAIN));
+        verify(mMockAudioManager, times(0)).abandonAudioFocus(any());
+        verify(mMockA2dpSink, times(0)).informAudioFocusStateNative(0);
+        verify(mMockA2dpSink, times(1)).informAudioTrackGainNative(0);
+        verify(mMockA2dpSink, times(2)).informAudioTrackGainNative(1.0f);
+    }
+
+    @Test
     public void testFocusLost() {
         // Focus was lost permanently, expect streaming to stop.
         testSnkPlay();
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