From e89ca09f92821491e1a643ea2afaf249e1148baf Mon Sep 17 00:00:00 2001 From: Hsinyi Tsai Date: Thu, 5 Apr 2012 16:12:42 +0800 Subject: [PATCH] Bug 735170 - WebTelephony: add API to hold a call. r=philikon --- dom/system/gonk/RadioInterfaceLayer.js | 11 ++++-- dom/system/gonk/nsIRadioInterfaceLayer.idl | 4 ++- dom/system/gonk/ril_worker.js | 27 +++++++++++--- dom/telephony/TelephonyCall.cpp | 42 ++++++++++++++++++++-- dom/telephony/TelephonyCall.h | 4 ++- dom/telephony/nsIDOMTelephonyCall.idl | 8 +++-- 6 files changed, 83 insertions(+), 13 deletions(-) diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index 261bfc05963..a9eb407c90c 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -84,9 +84,8 @@ function convertRILCallState(state) { case RIL.CALL_STATE_ALERTING: return nsIRadioInterfaceLayer.CALL_STATE_ALERTING; case RIL.CALL_STATE_INCOMING: - return nsIRadioInterfaceLayer.CALL_STATE_INCOMING; case RIL.CALL_STATE_WAITING: - return nsIRadioInterfaceLayer.CALL_STATE_HELD; // XXX This may not be right... + return nsIRadioInterfaceLayer.CALL_STATE_INCOMING; default: throw new Error("Unknown rilCallState: " + state); } @@ -513,6 +512,14 @@ RadioInterfaceLayer.prototype = { rejectCall: function rejectCall(callIndex) { this.worker.postMessage({type: "rejectCall", callIndex: callIndex}); }, + + holdCall: function holdCall(callIndex) { + this.worker.postMessage({type: "holdCall", callIndex: callIndex}); + }, + + resumeCall: function resumeCall(callIndex) { + this.worker.postMessage({type: "resumeCall", callIndex: callIndex}); + }, get microphoneMuted() { return gAudioManager.microphoneMuted; diff --git a/dom/system/gonk/nsIRadioInterfaceLayer.idl b/dom/system/gonk/nsIRadioInterfaceLayer.idl index 23711d8c78a..2fa580abfcc 100644 --- a/dom/system/gonk/nsIRadioInterfaceLayer.idl +++ b/dom/system/gonk/nsIRadioInterfaceLayer.idl @@ -116,7 +116,7 @@ interface nsIRILDataCallback : nsISupports in unsigned long length); }; -[scriptable, uuid(7a439b15-d398-4c57-9772-15aa6d3bc34f)] +[scriptable, uuid(d2025763-fc32-436e-b207-0228ea1ccd12)] interface nsIRadioInterfaceLayer : nsISupports { const unsigned short CALL_STATE_UNKNOWN = 0; @@ -161,6 +161,8 @@ interface nsIRadioInterfaceLayer : nsISupports void answerCall(in unsigned long callIndex); void rejectCall(in unsigned long callIndex); + void holdCall(in unsigned long callIndex); + void resumeCall(in unsigned long callIndex); attribute bool microphoneMuted; attribute bool speakerEnabled; diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index 40da1bec38a..20524116032 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -985,6 +985,20 @@ let RIL = { Buf.simpleRequest(REQUEST_UDUB); } }, + + holdCall: function holdCall(options) { + let call = this.currentCalls[options.callIndex]; + if (call && call.state == CALL_STATE_ACTIVE) { + Buf.simpleRequest(REQUEST_SWITCH_HOLDING_AND_ACTIVE); + } + }, + + resumeCall: function resumeCall(options) { + let call = this.currentCalls[options.callIndex]; + if (call && call.state == CALL_STATE_HOLDING) { + Buf.simpleRequest(REQUEST_SWITCH_HOLDING_AND_ACTIVE); + } + }, /** * Send an SMS. @@ -1675,13 +1689,18 @@ RIL[REQUEST_DIAL] = null; RIL[REQUEST_GET_IMSI] = function REQUEST_GET_IMSI(length) { this.IMSI = Buf.readString(); }; -RIL[REQUEST_HANGUP] = function REQUEST_HANGUP (length) { - this.getCurrentCalls(); -}; +RIL[REQUEST_HANGUP] = function REQUEST_HANGUP(length) { + this.getCurrentCalls(); +}; RIL[REQUEST_HANGUP_WAITING_OR_BACKGROUND] = null; RIL[REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND] = null; RIL[REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE] = null; -RIL[REQUEST_SWITCH_HOLDING_AND_ACTIVE] = null; +RIL[REQUEST_SWITCH_HOLDING_AND_ACTIVE] = function REQUEST_SWITCH_HOLDING_AND_ACTIVE(length) { + // XXX Normally we should get a UNSOLICITED_RESPONSE_CALL_STATE_CHANGED parcel + // notifying us of call state changes, but sometimes we don't (have no idea why). + // this.getCurrentCalls() helps update the call state actively. + this.getCurrentCalls(); +}; RIL[REQUEST_CONFERENCE] = null; RIL[REQUEST_UDUB] = null; RIL[REQUEST_LAST_CALL_FAIL_CAUSE] = null; diff --git a/dom/telephony/TelephonyCall.cpp b/dom/telephony/TelephonyCall.cpp index 65fc462cd78..035c1bde567 100644 --- a/dom/telephony/TelephonyCall.cpp +++ b/dom/telephony/TelephonyCall.cpp @@ -164,7 +164,9 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TelephonyCall, NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(connected) NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(disconnecting) NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(disconnected) - NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(incoming) + NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(holding) + NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(held) + NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(resuming) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TelephonyCall, @@ -178,7 +180,9 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TelephonyCall, NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(connected) NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(disconnecting) NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(disconnected) - NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(incoming) + NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(holding) + NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(held) + NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(resuming) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TelephonyCall) @@ -238,6 +242,36 @@ TelephonyCall::HangUp() return NS_OK; } +NS_IMETHODIMP +TelephonyCall::Hold() +{ + if (mCallState != nsIRadioInterfaceLayer::CALL_STATE_CONNECTED) { + NS_WARNING("Hold non-connected call ignored!"); + return NS_OK; + } + + nsresult rv = mTelephony->RIL()->HoldCall(mCallIndex); + NS_ENSURE_SUCCESS(rv,rv); + + ChangeStateInternal(nsIRadioInterfaceLayer::CALL_STATE_HOLDING, true); + return NS_OK; +} + +NS_IMETHODIMP +TelephonyCall::Resume() +{ + if (mCallState != nsIRadioInterfaceLayer::CALL_STATE_HELD) { + NS_WARNING("Resume non-held call ignored!"); + return NS_OK; + } + + nsresult rv = mTelephony->RIL()->ResumeCall(mCallIndex); + NS_ENSURE_SUCCESS(rv,rv); + + ChangeStateInternal(nsIRadioInterfaceLayer::CALL_STATE_RESUMING, true); + return NS_OK; +} + NS_IMPL_EVENT_HANDLER(TelephonyCall, statechange) NS_IMPL_EVENT_HANDLER(TelephonyCall, dialing) NS_IMPL_EVENT_HANDLER(TelephonyCall, alerting) @@ -246,4 +280,6 @@ NS_IMPL_EVENT_HANDLER(TelephonyCall, connecting) NS_IMPL_EVENT_HANDLER(TelephonyCall, connected) NS_IMPL_EVENT_HANDLER(TelephonyCall, disconnecting) NS_IMPL_EVENT_HANDLER(TelephonyCall, disconnected) -NS_IMPL_EVENT_HANDLER(TelephonyCall, incoming) +NS_IMPL_EVENT_HANDLER(TelephonyCall, holding) +NS_IMPL_EVENT_HANDLER(TelephonyCall, held) +NS_IMPL_EVENT_HANDLER(TelephonyCall, resuming) diff --git a/dom/telephony/TelephonyCall.h b/dom/telephony/TelephonyCall.h index 32ef7d73ff6..99a591ed5a1 100644 --- a/dom/telephony/TelephonyCall.h +++ b/dom/telephony/TelephonyCall.h @@ -60,7 +60,9 @@ class TelephonyCall : public nsDOMEventTargetHelper, NS_DECL_EVENT_HANDLER(connected) NS_DECL_EVENT_HANDLER(disconnecting) NS_DECL_EVENT_HANDLER(disconnected) - NS_DECL_EVENT_HANDLER(incoming) + NS_DECL_EVENT_HANDLER(holding) + NS_DECL_EVENT_HANDLER(held) + NS_DECL_EVENT_HANDLER(resuming) nsRefPtr mTelephony; diff --git a/dom/telephony/nsIDOMTelephonyCall.idl b/dom/telephony/nsIDOMTelephonyCall.idl index 59c240b335c..3be437aed6f 100644 --- a/dom/telephony/nsIDOMTelephonyCall.idl +++ b/dom/telephony/nsIDOMTelephonyCall.idl @@ -41,7 +41,7 @@ interface nsIDOMEventListener; -[scriptable, builtinclass, uuid(f741d52a-38bd-48f8-838b-cf4cd74a6ea5)] +[scriptable, builtinclass, uuid(2fb9502b-2054-4eda-8db7-3726c39144f7)] interface nsIDOMTelephonyCall : nsIDOMEventTarget { readonly attribute DOMString number; @@ -50,6 +50,8 @@ interface nsIDOMTelephonyCall : nsIDOMEventTarget void answer(); void hangUp(); + void hold(); + void resume(); attribute nsIDOMEventListener onstatechange; @@ -60,5 +62,7 @@ interface nsIDOMTelephonyCall : nsIDOMEventTarget attribute nsIDOMEventListener onconnected; attribute nsIDOMEventListener ondisconnecting; attribute nsIDOMEventListener ondisconnected; - attribute nsIDOMEventListener onincoming; + attribute nsIDOMEventListener onholding; + attribute nsIDOMEventListener onheld; + attribute nsIDOMEventListener onresuming; };