From 2768bdbd4d1b24911770655e17e398b8eb8354d4 Mon Sep 17 00:00:00 2001 From: Hsin-Yi Tsai Date: Mon, 14 May 2012 21:13:06 -0700 Subject: [PATCH] Bug 746496 - B2G telephony: update the audio system for incoming calls and holding calls. r=philikon --- dom/system/gonk/AudioManager.cpp | 2 + dom/system/gonk/RILContentHelper.js | 10 ++--- dom/system/gonk/RadioInterfaceLayer.js | 26 ++++++------- dom/system/gonk/nsIRadioInterfaceLayer.idl | 7 +++- dom/system/gonk/ril_worker.js | 45 ++++++++++++++++++++-- dom/telephony/Telephony.cpp | 4 +- 6 files changed, 67 insertions(+), 27 deletions(-) diff --git a/dom/system/gonk/AudioManager.cpp b/dom/system/gonk/AudioManager.cpp index 4bcb36b3b060..59ddc751b479 100644 --- a/dom/system/gonk/AudioManager.cpp +++ b/dom/system/gonk/AudioManager.cpp @@ -166,6 +166,8 @@ AudioManager::SetPhoneState(PRInt32 aState) if (AudioSystem::setPhoneState(aState)) { return NS_ERROR_FAILURE; } + + mPhoneState = aState; return NS_OK; } diff --git a/dom/system/gonk/RILContentHelper.js b/dom/system/gonk/RILContentHelper.js index afd6b3bf795b..62e172ce014e 100644 --- a/dom/system/gonk/RILContentHelper.js +++ b/dom/system/gonk/RILContentHelper.js @@ -232,7 +232,7 @@ RILContentHelper.prototype = { case "RIL:CallStateChanged": this._deliverTelephonyCallback("callStateChanged", [msg.json.callIndex, msg.json.state, - msg.json.number]); + msg.json.number, msg.json.isActive]); break; case "RIL:CallError": this._deliverTelephonyCallback("notifyError", @@ -242,18 +242,16 @@ RILContentHelper.prototype = { } }, - handleEnumerateCalls: function handleEnumerateCalls(message) { - debug("handleEnumerateCalls: " + JSON.stringify(message)); + handleEnumerateCalls: function handleEnumerateCalls(calls) { + debug("handleEnumerateCalls: " + JSON.stringify(calls)); let callback = this._enumerationTelephonyCallbacks.shift(); - let calls = message.calls; - let activeCallIndex = message.activeCallIndex; for (let i in calls) { let call = calls[i]; let keepGoing; try { keepGoing = callback.enumerateCallState(call.callIndex, call.state, call.number, - call.callIndex == activeCallIndex); + call.isActive); } catch (e) { debug("callback handler for 'enumerateCallState' threw an " + " exception: " + e); diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index c4ce26d10f31..ca39bfe5e00f 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -440,28 +440,29 @@ RadioInterfaceLayer.prototype = { /** * Track the active call and update the audio system as its state changes. - * - * XXX Needs some more work to support hold/resume. */ _activeCall: null, updateCallAudioState: function updateCallAudioState() { if (!this._activeCall) { // Disable audio. gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL; - debug("No active call, put audio system into PHONE_STATE_NORMAL."); + debug("No active call, put audio system into PHONE_STATE_NORMAL: " + + gAudioManager.phoneState); return; } switch (this._activeCall.state) { case nsIRadioInterfaceLayer.CALL_STATE_INCOMING: gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_RINGTONE; - debug("Incoming call, put audio system into PHONE_STATE_RINGTONE."); + debug("Incoming call, put audio system into PHONE_STATE_RINGTONE: " + + gAudioManager.phoneState); break; case nsIRadioInterfaceLayer.CALL_STATE_DIALING: // Fall through... case nsIRadioInterfaceLayer.CALL_STATE_CONNECTED: gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL; gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION, nsIAudioManager.FORCE_NONE); - debug("Active call, put audio system into PHONE_STATE_IN_CALL."); + debug("Active call, put audio system into PHONE_STATE_IN_CALL: " + + gAudioManager.phoneState); break; } }, @@ -473,11 +474,12 @@ RadioInterfaceLayer.prototype = { handleCallStateChange: function handleCallStateChange(call) { debug("handleCallStateChange: " + JSON.stringify(call)); call.state = convertRILCallState(call.state); - if (call.state == nsIRadioInterfaceLayer.CALL_STATE_DIALING || - call.state == nsIRadioInterfaceLayer.CALL_STATE_ALERTING || - call.state == nsIRadioInterfaceLayer.CALL_STATE_CONNECTED) { - // This is now the active call. + if (call.isActive) { this._activeCall = call; + } else if (this._activeCall && + this._activeCall.callIndex == call.callIndex) { + // Previously active call is not active now. + this._activeCall = null; } this.updateCallAudioState(); ppmm.sendAsyncMessage("RIL:CallStateChanged", call); @@ -488,7 +490,7 @@ RadioInterfaceLayer.prototype = { */ handleCallDisconnected: function handleCallDisconnected(call) { debug("handleCallDisconnected: " + JSON.stringify(call)); - if (this._activeCall && this._activeCall.callIndex == call.callIndex) { + if (call.isActive) { this._activeCall = null; } this.updateCallAudioState(); @@ -501,12 +503,10 @@ RadioInterfaceLayer.prototype = { */ handleEnumerateCalls: function handleEnumerateCalls(calls) { debug("handleEnumerateCalls: " + JSON.stringify(calls)); - let activeCallIndex = this._activeCall ? this._activeCall.callIndex : -1; for (let i in calls) { calls[i].state = convertRILCallState(calls[i].state); } - ppmm.sendAsyncMessage("RIL:EnumerateCalls", - {calls: calls, activeCallIndex: activeCallIndex}); + ppmm.sendAsyncMessage("RIL:EnumerateCalls", calls); }, /** diff --git a/dom/system/gonk/nsIRadioInterfaceLayer.idl b/dom/system/gonk/nsIRadioInterfaceLayer.idl index 62a912228079..a53377d71d5c 100644 --- a/dom/system/gonk/nsIRadioInterfaceLayer.idl +++ b/dom/system/gonk/nsIRadioInterfaceLayer.idl @@ -44,7 +44,7 @@ interface nsIDOMMozMobileConnectionInfo; interface nsIDOMDOMRequest; interface nsIDOMWindow; -[scriptable, uuid(28e80bfa-96db-4f52-8ed5-00a30758fba4)] +[scriptable, uuid(c14c71b8-afba-403b-8320-94593de9380f)] interface nsIRILTelephonyCallback : nsISupports { /** @@ -56,10 +56,13 @@ interface nsIRILTelephonyCallback : nsISupports * One of the nsIRadioInterfaceLayer::CALL_STATE_* values. * @param number * Number of the other party. + * @param isActive + * Indicates whether this call is the currently active one. */ void callStateChanged(in unsigned long callIndex, in unsigned short callState, - in AString number); + in AString number, + in boolean isActive); /** * Called when nsIRILContentHelper is asked to enumerate the current diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index fe3f4d74adab..4cf3a02cfe40 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -644,10 +644,15 @@ let RIL = { networkSelectionMode: null, /** - * Active calls + * Valid calls. */ currentCalls: {}, + /** + * Current calls length. + */ + currentCallsLength: null, + /** * Existing data calls. */ @@ -1749,12 +1754,19 @@ let RIL = { }, /** - * Helpers for processing call state. + * Helpers for processing call state and handle the active call. */ _processCalls: function _processCalls(newCalls) { // Go through the calls we currently have on file and see if any of them // changed state. Remove them from the newCalls map as we deal with them // so that only new calls remain in the map after we're done. + let lastCallsLength = this.currentCallsLength; + if (newCalls) { + this.currentCallsLength = newCalls.length; + } else { + this.currentCallsLength = 0; + } + for each (let currentCall in this.currentCalls) { let newCall; if (newCalls) { @@ -1764,9 +1776,12 @@ let RIL = { if (newCall) { // Call is still valid. - if (newCall.state != currentCall.state) { - // State has changed. + if (newCall.state != currentCall.state || + this.currentCallsLength != lastCallsLength) { + // State has changed. Active call may have changed as valid + // calls change. currentCall.state = newCall.state; + currentCall.isActive = this._isActiveCall(currentCall.state); this._handleChangedCallState(currentCall); } } else { @@ -1788,6 +1803,7 @@ let RIL = { } // Add to our map. this.currentCalls[newCall.callIndex] = newCall; + newCall.isActive = this._isActiveCall(newCall.state); this._handleChangedCallState(newCall); } } @@ -1809,6 +1825,24 @@ let RIL = { this.sendDOMMessage(message); }, + _isActiveCall: function _isActiveCall(callState) { + switch (callState) { + case CALL_STATE_INCOMING: + case CALL_STATE_DIALING: + case CALL_STATE_ALERTING: + case CALL_STATE_ACTIVE: + return true; + case CALL_STATE_HOLDING: + return false; + case CALL_STATE_WAITING: + if (this.currentCallsLength == 1) { + return true; + } else { + return false; + } + } + }, + _processDataCallList: function _processDataCallList(datacalls) { for each (let currentDataCall in this.currentDataCalls) { let updatedDataCall; @@ -2254,8 +2288,11 @@ RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length, opti }; } + call.isActive = false; + calls[call.callIndex] = call; } + calls.length = calls_length; this._processCalls(calls); }; RIL[REQUEST_DIAL] = function REQUEST_DIAL(length, options) { diff --git a/dom/telephony/Telephony.cpp b/dom/telephony/Telephony.cpp index 3ed1943fc141..c6d510bfdc92 100644 --- a/dom/telephony/Telephony.cpp +++ b/dom/telephony/Telephony.cpp @@ -404,7 +404,7 @@ NS_IMPL_EVENT_HANDLER(Telephony, callschanged) NS_IMETHODIMP Telephony::CallStateChanged(PRUint32 aCallIndex, PRUint16 aCallState, - const nsAString& aNumber) + const nsAString& aNumber, bool aIsActive) { NS_ASSERTION(aCallIndex != kOutgoingPlaceholderCallIndex, "This should never happen!"); @@ -445,7 +445,7 @@ Telephony::CallStateChanged(PRUint32 aCallIndex, PRUint16 aCallState, modifiedCall->ChangeState(aCallState); // See if this should replace our current active call. - if (aCallState == nsIRadioInterfaceLayer::CALL_STATE_CONNECTED) { + if (aIsActive) { mActiveCall = modifiedCall; }