Bug 990423 - [Bluetooth] Fix the incorrect condition for reporting call held status when call state changed. r=echou, f=btian

---
 dom/bluetooth/bluez/BluetoothHfpManager.cpp |  108 ++++++++++++++++++++++++---
 dom/bluetooth/bluez/BluetoothHfpManager.h   |    2 +
 2 files changed, 99 insertions(+), 11 deletions(-)
This commit is contained in:
Jamin Liu 2014-04-25 09:59:32 +08:00
parent 7f592479f6
commit 388d09ec68
2 changed files with 99 additions and 11 deletions

View File

@ -1378,6 +1378,37 @@ BluetoothHfpManager::GetNumberOfCalls(uint16_t aState)
return num;
}
uint32_t
BluetoothHfpManager::GetNumberOfConCalls()
{
uint32_t num = 0;
uint32_t callLength = mCurrentCallArray.Length();
for (uint32_t i = 1; i < callLength; ++i) {
if (mCurrentCallArray[i].mIsConference) {
++num;
}
}
return num;
}
uint32_t
BluetoothHfpManager::GetNumberOfConCalls(uint16_t aState)
{
uint32_t num = 0;
uint32_t callLength = mCurrentCallArray.Length();
for (uint32_t i = 1; i < callLength; ++i) {
if (mCurrentCallArray[i].mIsConference
&& mCurrentCallArray[i].mState == aState) {
++num;
}
}
return num;
}
void
BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
uint16_t aCallState,
@ -1422,15 +1453,59 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
switch (aCallState) {
case nsITelephonyProvider::CALL_STATE_HELD:
if (prevCallState == nsITelephonyProvider::CALL_STATE_CONNECTED) {
if (mCurrentCallArray.Length() == 1) {
// A single active call is put on hold (+CIEV, callheld=2)
sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_NOACTIVE;
} else {
// Releases all active calls and accepts the other (+CIEV, callheld=1)
sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
switch (prevCallState) {
case nsITelephonyProvider::CALL_STATE_CONNECTED: {
uint32_t numActive = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_CONNECTED);
uint32_t numHeld = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_HELD);
uint32_t numConCalls = GetNumberOfConCalls();
/**
* An active call becomes a held call.
*
* If this call is not a conference call,
* - callheld state = ONHOLD_NOACTIVE if no active call remains;
* - callheld state = ONHOLD_ACTIVE otherwise.
* If this call belongs to a conference call and all other members of
* the conference call have become held calls,
* - callheld state = ONHOLD_NOACTIVE if no active call remains;
* - callheld state = ONHOLD_ACTIVE otherwise.
*
* Note number of active calls may be 0 in-between state transition
* (c1 has become held but c2 has not become active yet), so we regard
* no active call remains if there is no other active/held call
* besides this changed call/group of conference call.
*/
if (!aIsConference) {
if (numActive + numHeld == 1) {
// A single active call is put on hold.
sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_NOACTIVE;
} else {
// An active call is placed on hold or active/held calls swapped.
sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
}
SendCommand(RESPONSE_CIEV, CINDType::CALLHELD);
} else if (GetNumberOfConCalls(nsITelephonyProvider::CALL_STATE_HELD)
== numConCalls) {
if (numActive + numHeld == numConCalls) {
// An active conference call is put on hold.
sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_NOACTIVE;
} else {
// Active calls are placed on hold or active/held calls swapped.
sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
}
SendCommand(RESPONSE_CIEV, CINDType::CALLHELD);
}
break;
}
SendCommand(RESPONSE_CIEV, CINDType::CALLHELD);
case nsITelephonyProvider::CALL_STATE_DISCONNECTED:
// The call state changed from DISCONNECTED to HELD. It could happen
// when user held a call before Bluetooth got connected.
if (FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
// callheld = ONHOLD_ACTIVE if an active call already exists.
sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
SendCommand(RESPONSE_CIEV, CINDType::CALLHELD);
}
break;
}
break;
case nsITelephonyProvider::CALL_STATE_INCOMING:
@ -1476,6 +1551,12 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
ConnectSco();
break;
case nsITelephonyProvider::CALL_STATE_CONNECTED:
/**
* A call becomes active because:
* - user answers an incoming call,
* - user dials a outgoing call and it is answered, or
* - SLC is connected when a call is active.
*/
switch (prevCallState) {
case nsITelephonyProvider::CALL_STATE_INCOMING:
case nsITelephonyProvider::CALL_STATE_DISCONNECTED:
@ -1488,10 +1569,15 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
// Outgoing call
UpdateCIND(CINDType::CALL, CallState::IN_PROGRESS, aSend);
UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, aSend);
if (FindFirstCall(nsITelephonyProvider::CALL_STATE_HELD)) {
// callheld state = ONHOLD_ACTIVE if a held call already exists.
UpdateCIND(CINDType::CALLHELD, CallHeldState::ONHOLD_ACTIVE, aSend);
}
break;
// User wants to add a held call to the conversation.
// The original connected call become a conference call here.
case nsITelephonyProvider::CALL_STATE_CONNECTED:
// User wants to add a held call to the conversation.
// The original connected call becomes a conference call here.
if (aIsConference) {
UpdateCIND(CINDType::CALLHELD, CallHeldState::NO_CALLHELD, aSend);
}
@ -1499,7 +1585,7 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
case nsITelephonyProvider::CALL_STATE_HELD:
if (!FindFirstCall(nsITelephonyProvider::CALL_STATE_HELD)) {
if (aIsConference && !prevCallIsConference) {
// The held call was merged and become a conference call.
// The held call was merged and becomes a conference call.
UpdateCIND(CINDType::CALLHELD, CallHeldState::NO_CALLHELD, aSend);
} else if (sCINDItems[CINDType::CALLHELD].value ==
CallHeldState::ONHOLD_NOACTIVE) {

View File

@ -157,6 +157,8 @@ private:
void ResetCallArray();
uint32_t FindFirstCall(uint16_t aState);
uint32_t GetNumberOfCalls(uint16_t aState);
uint32_t GetNumberOfConCalls();
uint32_t GetNumberOfConCalls(uint16_t aState);
PhoneType GetPhoneType(const nsAString& aType);
#endif