Bug 875677 - Modify the logic of sending 'callheld' indicator to fit HFP 1.6, r=gyeh, a=tef+
authorEric Chou <echou@mozilla.com>
Sun, 02 Jun 2013 22:03:16 +0800
changeset 119502 4785b1353fd7b71a86168def5f39c8761f013c82
parent 119501 3f274ad25d7ee54c0863914ce1c330177fc2bcec
child 119503 d0089d140ecb15b26992be24bb6c9e7a971aa288
push id848
push userechou@mozilla.com
push dateSun, 02 Jun 2013 16:31:01 +0000
reviewersgyeh, tef
bugs875677
milestone18.0
Bug 875677 - Modify the logic of sending 'callheld' indicator to fit HFP 1.6, r=gyeh, a=tef+ According to HFP spec 1.6, we should update callheld status very carefully when the status of other calls are changed.
dom/bluetooth/BluetoothHfpManager.cpp
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -1273,17 +1273,21 @@ BluetoothHfpManager::HandleCallStateChan
   uint16_t prevCallState = mCurrentCallArray[aCallIndex].mState;
   mCurrentCallArray[aCallIndex].mState = aCallState;
   mCurrentCallArray[aCallIndex].mDirection = !aIsOutgoing;
 
   nsString address;
 
   switch (aCallState) {
     case nsIRadioInterfaceLayer::CALL_STATE_HELD:
-      sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
+      if (!FindFirstCall(nsIRadioInterfaceLayer::CALL_STATE_CONNECTED)) {
+        sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_NOACTIVE;
+      } else {
+        sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
+      }
       SendCommand("+CIEV: ", CINDType::CALLHELD);
       break;
     case nsIRadioInterfaceLayer::CALL_STATE_INCOMING:
       if (FindFirstCall(nsIRadioInterfaceLayer::CALL_STATE_CONNECTED)) {
         if (mCCWA) {
           nsAutoCString ccwaMsg("+CCWA: \"");
           ccwaMsg.Append(NS_ConvertUTF16toUTF8(aNumber));
           ccwaMsg.AppendLiteral("\",");
@@ -1333,35 +1337,37 @@ BluetoothHfpManager::HandleCallStateChan
           sStopSendingRingFlag = true;
 
           ConnectSco();
         case nsIRadioInterfaceLayer::CALL_STATE_ALERTING:
           // Outgoing call
           UpdateCIND(CINDType::CALL, CallState::IN_PROGRESS, aSend);
           UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, aSend);
           break;
-        case nsIRadioInterfaceLayer::CALL_STATE_HELD:
-          // Besides checking if there is still held calls, another thing we
-          // need to consider is the state change when receiving AT+CHLD=2.
-          // Assume that there is one active call(c1) and one call on hold(c2).
-          // We got AT+CHLD=2, which swaps active/held position. The first
-          // action would be c2 -> ACTIVE, then c1 -> HELD. When we get the
-          // CallStateChanged event of c2 becoming ACTIVE, we enter here.
-          // However we can't send callheld=0 at this time because we should
-          // see c2 -> ACTIVE + c1 -> HELD as one operation. That's the reason
-          // why I added the GetNumberOfCalls() condition check.
-          if (!FindFirstCall(nsIRadioInterfaceLayer::CALL_STATE_HELD) &&
-              GetNumberOfCalls(
-                nsIRadioInterfaceLayer::CALL_STATE_CONNECTED) == 1) {
-            UpdateCIND(CINDType::CALLHELD, CallHeldState::NO_CALLHELD, aSend);
-          }
-          break;
         default:
           NS_WARNING("Not handling state changed");
       }
+
+      // = Handle callheld separately =
+      // Besides checking if there is still held calls, another thing we
+      // need to consider is the state change when receiving AT+CHLD=2.
+      // Assume that there is one active call(c1) and one call on hold(c2).
+      // We got AT+CHLD=2, which swaps active/held position. The first
+      // action would be c2 -> ACTIVE, then c1 -> HELD. When we get the
+      // CallStateChanged event of c2 becoming ACTIVE, we enter here.
+      // However we can't send callheld=0 at this time because we should
+      // see c2 -> ACTIVE + c1 -> HELD as one operation. That's the reason
+      // why I added the GetNumberOfCalls() condition check.
+      if (GetNumberOfCalls(nsIRadioInterfaceLayer::CALL_STATE_CONNECTED) == 1) {
+        if (FindFirstCall(nsIRadioInterfaceLayer::CALL_STATE_HELD)) {
+          UpdateCIND(CINDType::CALLHELD, CallHeldState::ONHOLD_ACTIVE, aSend);
+        } else if (prevCallState == nsIRadioInterfaceLayer::CALL_STATE_HELD) {
+          UpdateCIND(CINDType::CALLHELD, CallHeldState::NO_CALLHELD, aSend);
+        }
+      }
       break;
     case nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED:
       switch (prevCallState) {
         case nsIRadioInterfaceLayer::CALL_STATE_INCOMING:
         case nsIRadioInterfaceLayer::CALL_STATE_BUSY:
           // Incoming call, no break
           sStopSendingRingFlag = true;
         case nsIRadioInterfaceLayer::CALL_STATE_DIALING:
@@ -1371,23 +1377,29 @@ BluetoothHfpManager::HandleCallStateChan
           break;
         case nsIRadioInterfaceLayer::CALL_STATE_CONNECTED:
           // No call is ongoing
           if (sCINDItems[CINDType::CALLHELD].value ==
               CallHeldState::NO_CALLHELD) {
             UpdateCIND(CINDType::CALL, CallState::NO_CALL, aSend);
           }
           break;
-        case nsIRadioInterfaceLayer::CALL_STATE_HELD:
-          UpdateCIND(CINDType::CALLHELD, CallHeldState::NO_CALLHELD, aSend);
-          break;
         default:
           NS_WARNING("Not handling state changed");
       }
 
+      // Handle held calls separately
+      if (!FindFirstCall(nsIRadioInterfaceLayer::CALL_STATE_HELD)) {
+        UpdateCIND(CINDType::CALLHELD, CallHeldState::NO_CALLHELD, aSend);
+      } else if (!FindFirstCall(nsIRadioInterfaceLayer::CALL_STATE_CONNECTED)) {
+        UpdateCIND(CINDType::CALLHELD, CallHeldState::ONHOLD_NOACTIVE, aSend);
+      } else {
+        UpdateCIND(CINDType::CALLHELD, CallHeldState::ONHOLD_ACTIVE, aSend);
+      }
+
       // -1 is necessary because call 0 is an invalid (padding) call object.
       if (mCurrentCallArray.Length() - 1 ==
             GetNumberOfCalls(nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED)) {
         // There is no call, close Sco and clear mCurrentCallArray
         DisconnectSco();
         ResetCallArray();
       }
       break;