Merge "PBAP: Set Pbap connection state to DISCONNECTED on ACL_DISCONNECT."
diff --git a/src/com/android/bluetooth/btservice/AdapterProperties.java b/src/com/android/bluetooth/btservice/AdapterProperties.java
index abc349d..257eb1f 100644
--- a/src/com/android/bluetooth/btservice/AdapterProperties.java
+++ b/src/com/android/bluetooth/btservice/AdapterProperties.java
@@ -139,6 +139,9 @@
                 case BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED:
                     sendConnectionStateChange(BluetoothProfile.PBAP_CLIENT, intent);
                     break;
+                case BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED:
+                    sendConnectionStateChange(BluetoothProfile.PBAP, intent);
+                    break;
                 default:
                     Log.w(TAG, "Received unknown intent " + intent);
                     break;
diff --git a/src/com/android/bluetooth/hfp/AtPhonebook.java b/src/com/android/bluetooth/hfp/AtPhonebook.java
index 0387394..f272725 100755
--- a/src/com/android/bluetooth/hfp/AtPhonebook.java
+++ b/src/com/android/bluetooth/hfp/AtPhonebook.java
@@ -490,6 +490,7 @@
         // Check phonebook
         PhonebookResult pbr = getPhonebookResult(mCurrentPhonebook, true); //false);
         if (pbr == null) {
+            Log.e(TAG, "pbr is null");
             atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_ALLOWED;
             return atCommandResult;
         }
@@ -499,11 +500,17 @@
         // When we send error, certain kits like BMW disconnect the
         // Handsfree connection.
         if (pbr.cursor.getCount() == 0 || mCpbrIndex1 <= 0 || mCpbrIndex2 < mCpbrIndex1  ||
-            mCpbrIndex2 > pbr.cursor.getCount() || mCpbrIndex1 > pbr.cursor.getCount()) {
+            mCpbrIndex1 > pbr.cursor.getCount()) {
             atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK;
+            Log.e(TAG, "Invalid request or no results, returning");
             return atCommandResult;
         }
 
+        if (mCpbrIndex2 > pbr.cursor.getCount()) {
+            Log.w(TAG, "max index requested is greater than number of records"
+                        + " available, resetting it");
+            mCpbrIndex2 = pbr.cursor.getCount();
+        }
         // Process
         atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK;
         int errorDetected = -1; // no error
diff --git a/src/com/android/bluetooth/pbap/BluetoothPbapService.java b/src/com/android/bluetooth/pbap/BluetoothPbapService.java
index af38eb3..cc2dd25 100644
--- a/src/com/android/bluetooth/pbap/BluetoothPbapService.java
+++ b/src/com/android/bluetooth/pbap/BluetoothPbapService.java
@@ -239,7 +239,7 @@
     private BluetoothPbapContentObserver mContactChangeObserver;
 
     public BluetoothPbapService() {
-        mState = BluetoothPbap.STATE_DISCONNECTED;
+        mState = BluetoothProfile.STATE_DISCONNECTED;
         mContext = this;
     }
 
@@ -481,7 +481,7 @@
         }
         BluetoothObexTransport transport = new BluetoothObexTransport(mConnSocket);
         mServerSession = new ServerSession(transport, mPbapServer, mAuth);
-        setState(BluetoothPbap.STATE_CONNECTED);
+        setState(BluetoothProfile.STATE_CONNECTED);
 
         mSessionStatusHandler.removeMessages(MSG_RELEASE_WAKE_LOCK);
         mSessionStatusHandler.sendMessageDelayed(mSessionStatusHandler
@@ -513,7 +513,7 @@
         if (mAdapter != null && mAdapter.isEnabled()) {
             startSocketListeners();
         }
-        setState(BluetoothPbap.STATE_DISCONNECTED);
+        setState(BluetoothProfile.STATE_DISCONNECTED);
     }
 
     private void notifyAuthKeyInput(final String key) {
@@ -733,7 +733,7 @@
                     + result);
             int prevState = mState;
             mState = state;
-            Intent intent = new Intent(BluetoothPbap.PBAP_STATE_CHANGED_ACTION);
+            Intent intent = new Intent(BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED);
             intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
             intent.putExtra(BluetoothProfile.EXTRA_STATE, mState);
             intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
@@ -859,13 +859,13 @@
             Log.w(TAG, "Unable to unregister pbap receiver", e);
         }
         mSessionStatusHandler.obtainMessage(SHUTDOWN).sendToTarget();
-        setState(BluetoothPbap.STATE_DISCONNECTED, BluetoothPbap.RESULT_CANCELED);
+        setState(BluetoothProfile.STATE_DISCONNECTED, BluetoothPbap.RESULT_CANCELED);
         return true;
     }
 
     protected void disconnect() {
         synchronized (this) {
-            if (mState == BluetoothPbap.STATE_CONNECTED) {
+            if (mState == BluetoothProfile.STATE_CONNECTED) {
                 if (mServerSession != null) {
                     mServerSession.close();
                     mServerSession = null;
@@ -873,7 +873,7 @@
 
                 closeConnectionSocket();
 
-                setState(BluetoothPbap.STATE_DISCONNECTED, BluetoothPbap.RESULT_CANCELED);
+                setState(BluetoothProfile.STATE_DISCONNECTED, BluetoothPbap.RESULT_CANCELED);
             }
         }
     }
@@ -907,7 +907,7 @@
         public int getState() {
             if (DEBUG) Log.d(TAG, "getState = " + mService.getState());
             BluetoothPbapService service = getService(BLUETOOTH_PERM);
-            if (service == null) return BluetoothPbap.STATE_DISCONNECTED;
+            if (service == null) return BluetoothProfile.STATE_DISCONNECTED;
 
             return service.getState();
         }
@@ -923,7 +923,7 @@
             if (DEBUG) Log.d(TAG, "isConnected " + device);
             BluetoothPbapService service = getService(BLUETOOTH_PERM);
             if (service == null) return false;
-            return service.getState() == BluetoothPbap.STATE_CONNECTED
+            return service.getState() == BluetoothProfile.STATE_CONNECTED
                     && service.getRemoteDevice().equals(device);
         }
 
diff --git a/tests/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java b/tests/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java
index a56f144..efa17ac 100644
--- a/tests/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java
+++ b/tests/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java
@@ -76,8 +76,7 @@
         when(mockContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mockAudioManager);
         when(mockContext.getResources()).thenReturn(mockResources);
         when(mockResources.getInteger(anyInt())).thenReturn(DUCK_PERCENT);
-        when(mockAudioManager.requestAudioFocus(audioFocusChangeListenerArgumentCaptor.capture(),
-                     eq(AudioManager.STREAM_MUSIC), eq(AudioManager.AUDIOFOCUS_GAIN)))
+        when(mockAudioManager.requestAudioFocus(any()))
                 .thenReturn(AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
         when(mockAudioManager.abandonAudioFocus(any())).thenReturn(AudioManager.AUDIOFOCUS_GAIN);
         doNothing().when(mockA2dpSink).informAudioTrackGainNative(anyFloat());
@@ -93,7 +92,7 @@
         // Stream started without local play, expect no change in streaming.
         streamHandler.handleMessage(
                 streamHandler.obtainMessage(A2dpSinkStreamHandler.SRC_STR_START));
-        verify(mockAudioManager, times(0)).requestAudioFocus(any(), anyInt(), anyInt());
+        verify(mockAudioManager, times(0)).requestAudioFocus(any());
         verify(mockA2dpSink, times(0)).informAudioFocusStateNative(1);
         verify(mockA2dpSink, times(0)).informAudioTrackGainNative(1.0f);
     }
@@ -103,7 +102,7 @@
         // Stream stopped without local play, expect no change in streaming.
         streamHandler.handleMessage(
                 streamHandler.obtainMessage(A2dpSinkStreamHandler.SRC_STR_STOP));
-        verify(mockAudioManager, times(0)).requestAudioFocus(any(), anyInt(), anyInt());
+        verify(mockAudioManager, times(0)).requestAudioFocus(any());
         verify(mockA2dpSink, times(0)).informAudioFocusStateNative(1);
         verify(mockA2dpSink, times(0)).informAudioTrackGainNative(1.0f);
     }
@@ -112,7 +111,7 @@
     public void testSnkPlay() {
         // Play was pressed locally, expect streaming to start.
         streamHandler.handleMessage(streamHandler.obtainMessage(A2dpSinkStreamHandler.SNK_PLAY));
-        verify(mockAudioManager, times(1)).requestAudioFocus(any(), anyInt(), anyInt());
+        verify(mockAudioManager, times(1)).requestAudioFocus(any());
         verify(mockA2dpSink, times(1)).informAudioFocusStateNative(1);
         verify(mockA2dpSink, times(1)).informAudioTrackGainNative(1.0f);
     }
@@ -121,7 +120,7 @@
     public void testSnkPause() {
         // Pause was pressed locally, expect streaming to stop.
         streamHandler.handleMessage(streamHandler.obtainMessage(A2dpSinkStreamHandler.SNK_PAUSE));
-        verify(mockAudioManager, times(0)).requestAudioFocus(any(), anyInt(), anyInt());
+        verify(mockAudioManager, times(0)).requestAudioFocus(any());
         verify(mockA2dpSink, times(0)).informAudioFocusStateNative(1);
         verify(mockA2dpSink, times(0)).informAudioTrackGainNative(1.0f);
     }
@@ -139,7 +138,7 @@
     public void testSrcPlay() {
         // Play was pressed remotely, expect no streaming due to lack of audio focus.
         streamHandler.handleMessage(streamHandler.obtainMessage(A2dpSinkStreamHandler.SRC_PLAY));
-        verify(mockAudioManager, times(0)).requestAudioFocus(any(), anyInt(), anyInt());
+        verify(mockAudioManager, times(0)).requestAudioFocus(any());
         verify(mockA2dpSink, times(0)).informAudioFocusStateNative(1);
         verify(mockA2dpSink, times(0)).informAudioTrackGainNative(1.0f);
     }
@@ -149,7 +148,7 @@
         // 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(mockAudioManager, times(1)).requestAudioFocus(any());
         verify(mockA2dpSink, times(1)).informAudioFocusStateNative(1);
         verify(mockA2dpSink, times(1)).informAudioTrackGainNative(1.0f);
     }
@@ -158,7 +157,7 @@
     public void testSrcPause() {
         // Play was pressed locally, expect streaming to start.
         streamHandler.handleMessage(streamHandler.obtainMessage(A2dpSinkStreamHandler.SRC_PLAY));
-        verify(mockAudioManager, times(0)).requestAudioFocus(any(), anyInt(), anyInt());
+        verify(mockAudioManager, times(0)).requestAudioFocus(any());
         verify(mockA2dpSink, times(0)).informAudioFocusStateNative(1);
         verify(mockA2dpSink, times(0)).informAudioTrackGainNative(1.0f);
     }
@@ -169,7 +168,7 @@
         testSnkPlay();
         streamHandler.handleMessage(streamHandler.obtainMessage(
                 A2dpSinkStreamHandler.AUDIO_FOCUS_CHANGE, AudioManager.AUDIOFOCUS_GAIN));
-        verify(mockAudioManager, times(1)).requestAudioFocus(any(), anyInt(), anyInt());
+        verify(mockAudioManager, times(1)).requestAudioFocus(any());
         verify(mockA2dpSink, times(2)).informAudioFocusStateNative(1);
         verify(mockA2dpSink, times(2)).informAudioTrackGainNative(1.0f);
     }