Disconnect PBAP while disconnecting HFP profile.

PBAP profile is associated with HFP profile. Disconnect PBAP
profile while disconnecting HFP profile. We ever never doing this
and were expecting the remote end to do it. So when the user
disconnects a headset, we will end up with the ACL link still up
because PBAP has not been disconnected.

This is little bit of a hack till PBAP profile is converted to
use the new profile APIs.

Change-Id: I04821daae6588955fbfea01472e6a1b6f9212608
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index e460839..1c53c45 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -75,6 +75,7 @@
     public static final int DISCONNECT_A2DP_INCOMING = 53;
     public static final int DISCONNECT_HID_OUTGOING = 54;
     public static final int DISCONNECT_HID_INCOMING = 55;
+    public static final int DISCONNECT_PBAP_OUTGOING = 56;
 
     public static final int UNPAIR = 100;
     public static final int AUTO_CONNECT_PROFILES = 101;
@@ -94,6 +95,8 @@
     private BluetoothService mService;
     private BluetoothA2dpService mA2dpService;
     private BluetoothHeadset  mHeadsetService;
+    private BluetoothPbap     mPbapService;
+    private boolean mPbapServiceConnected;
 
     private BluetoothDevice mDevice;
     private int mHeadsetState = BluetoothProfile.STATE_DISCONNECTED;
@@ -201,6 +204,8 @@
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
         adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
                                 BluetoothProfile.HEADSET);
+        // TODO(): Convert PBAP to the new Profile APIs.
+        PbapServiceListener p = new PbapServiceListener();
     }
 
     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
@@ -217,6 +222,22 @@
         }
     };
 
+    private class PbapServiceListener implements BluetoothPbap.ServiceListener {
+        public PbapServiceListener() {
+            mPbapService = new BluetoothPbap(mContext, this);
+        }
+        public void onServiceConnected() {
+            synchronized(BluetoothDeviceProfileState.this) {
+                mPbapServiceConnected = true;
+            }
+        }
+        public void onServiceDisconnected() {
+            synchronized(BluetoothDeviceProfileState.this) {
+                mPbapServiceConnected = false;
+            }
+        }
+    }
+
     private class BondedDevice extends HierarchicalState {
         @Override
         protected void enter() {
@@ -255,6 +276,9 @@
                 case DISCONNECT_HID_INCOMING:
                     transitionTo(mIncomingHid);
                     break;
+                case DISCONNECT_PBAP_OUTGOING:
+                    processCommand(DISCONNECT_PBAP_OUTGOING);
+                    break;
                 case UNPAIR:
                     if (mHeadsetState != BluetoothHeadset.STATE_DISCONNECTED) {
                         sendMessage(DISCONNECT_HFP_OUTGOING);
@@ -404,6 +428,7 @@
                         deferMessage(deferMsg);
                     }
                     break; // ignore
+                case DISCONNECT_PBAP_OUTGOING:
                 case UNPAIR:
                 case AUTO_CONNECT_PROFILES:
                     deferMessage(message);
@@ -478,6 +503,7 @@
                 case CONNECT_HID_INCOMING:
                 case DISCONNECT_HID_INCOMING:
                      break; // ignore
+                case DISCONNECT_PBAP_OUTGOING:
                 case UNPAIR:
                 case AUTO_CONNECT_PROFILES:
                     deferMessage(message);
@@ -582,6 +608,7 @@
                         deferMessage(deferMsg);
                     }
                     break; // ignore
+                case DISCONNECT_PBAP_OUTGOING:
                 case UNPAIR:
                 case AUTO_CONNECT_PROFILES:
                     deferMessage(message);
@@ -654,6 +681,7 @@
                 case CONNECT_HID_INCOMING:
                 case DISCONNECT_HID_INCOMING:
                      break; // ignore
+                case DISCONNECT_PBAP_OUTGOING:
                 case UNPAIR:
                 case AUTO_CONNECT_PROFILES:
                     deferMessage(message);
@@ -734,7 +762,7 @@
                 case DISCONNECT_HID_INCOMING:
                     // Ignore, will be handled by Bluez
                     break;
-
+                case DISCONNECT_PBAP_OUTGOING:
                 case UNPAIR:
                 case AUTO_CONNECT_PROFILES:
                     deferMessage(message);
@@ -792,6 +820,7 @@
               case DISCONNECT_A2DP_INCOMING:
                   // Ignore, will be handled by Bluez
                   break;
+              case DISCONNECT_PBAP_OUTGOING:
               case UNPAIR:
               case AUTO_CONNECT_PROFILES:
                   deferMessage(message);
@@ -818,7 +847,7 @@
         }
     }
 
-    synchronized void deferHeadsetMessage(int command) {
+    synchronized void deferProfileServiceMessage(int command) {
         Message msg = new Message();
         msg.what = command;
         deferMessage(msg);
@@ -829,14 +858,14 @@
         switch(command) {
             case  CONNECT_HFP_OUTGOING:
                 if (mHeadsetService == null) {
-                    deferHeadsetMessage(command);
+                    deferProfileServiceMessage(command);
                 } else {
                     return mHeadsetService.connectHeadsetInternal(mDevice);
                 }
                 break;
             case CONNECT_HFP_INCOMING:
                 if (mHeadsetService == null) {
-                    deferHeadsetMessage(command);
+                    deferProfileServiceMessage(command);
                 } else if (mHeadsetState == BluetoothHeadset.STATE_CONNECTING) {
                     return mHeadsetService.acceptIncomingConnect(mDevice);
                 } else if (mHeadsetState == BluetoothHeadset.STATE_DISCONNECTED) {
@@ -857,8 +886,13 @@
                 return true;
             case DISCONNECT_HFP_OUTGOING:
                 if (mHeadsetService == null) {
-                    deferHeadsetMessage(command);
+                    deferProfileServiceMessage(command);
                 } else {
+                    // Disconnect PBAP
+                    // TODO(): Add PBAP to the state machine.
+                    Message m = new Message();
+                    m.what = DISCONNECT_PBAP_OUTGOING;
+                    deferMessage(m);
                     if (mHeadsetService.getPriority(mDevice) ==
                         BluetoothHeadset.PRIORITY_AUTO_CONNECT) {
                         mHeadsetService.setPriority(mDevice, BluetoothHeadset.PRIORITY_ON);
@@ -890,6 +924,13 @@
                     mService.setInputDevicePriority(mDevice, BluetoothInputDevice.PRIORITY_ON);
                 }
                 return mService.disconnectInputDeviceInternal(mDevice);
+            case DISCONNECT_PBAP_OUTGOING:
+                if (!mPbapServiceConnected) {
+                    deferProfileServiceMessage(command);
+                } else {
+                    return mPbapService.disconnect();
+                }
+                break;
             case UNPAIR:
                 return mService.removeBondInternal(mDevice.getAddress());
             default: