author | Philipp von Weitershausen <philipp@weitershausen.de> |
Wed, 07 Dec 2011 14:57:05 +0800 | |
changeset 82154 | c634c79dd8293bd20d48adca0d30a59db75f0fa5 |
parent 82153 | 346e090f5a4dc361b37de2235c518d4350a25f05 |
child 82155 | 40d760a401001241d3b624306832c241515f4c12 |
push id | 21584 |
push user | mbrubeck@mozilla.com |
push date | Wed, 07 Dec 2011 20:15:44 +0000 |
treeherder | mozilla-central@7ab478082ca7 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | gal |
bugs | 707629 |
milestone | 11.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
dom/telephony/ril_consts.js | file | annotate | diff | comparison | revisions | |
dom/telephony/ril_worker.js | file | annotate | diff | comparison | revisions |
--- a/dom/telephony/ril_consts.js +++ b/dom/telephony/ril_consts.js @@ -31,29 +31,16 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -const CARD_MAX_APPS = 8; - -const RADIO_STATE_OFF = 0; -const RADIO_STATE_UNAVAILABLE = 1; -const RADIO_STATE_SIM_NOT_READY = 2; -const RADIO_STATE_SIM_LOCKED_OR_ABSENT = 3; -const RADIO_STATE_SIM_READY = 4; -const RADIO_STATE_RUIM_NOT_READY = 5; -const RADIO_STATE_RUIM_READY = 6; -const RADIO_STATE_RUIM_LOCKED_OR_ABSENT = 7; -const RADIO_STATE_NV_NOT_READY = 8; -const RADIO_STATE_NV_READY = 9; - const REQUEST_GET_SIM_STATUS = 1; const REQUEST_ENTER_SIM_PIN = 2; const REQUEST_ENTER_SIM_PUK = 3; const REQUEST_ENTER_SIM_PIN2 = 4; const REQUEST_ENTER_SIM_PUK2 = 5; const REQUEST_CHANGE_SIM_PIN = 6; const REQUEST_CHANGE_SIM_PIN2 = 7; const REQUEST_ENTER_NETWORK_DEPERSONALIZATION = 8; @@ -149,16 +136,19 @@ const REQUEST_CDMA_WRITE_SMS_TO_RUIM = 9 const REQUEST_CDMA_DELETE_SMS_ON_RUIM = 97; const REQUEST_DEVICE_IDENTITY = 98; const REQUEST_EXIT_EMERGENCY_CALLBACK_MODE = 99; const REQUEST_GET_SMSC_ADDRESS = 100; const REQUEST_SET_SMSC_ADDRESS = 101; const REQUEST_REPORT_SMS_MEMORY_STATUS = 102; const REQUEST_REPORT_STK_SERVICE_IS_RUNNING = 103; +const RESPONSE_TYPE_SOLICITED = 0; +const RESPONSE_TYPE_UNSOLICITED = 1; + const UNSOLICITED_RESPONSE_BASE = 1000; const UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED = 1000; const UNSOLICITED_RESPONSE_CALL_STATE_CHANGED = 1001; const UNSOLICITED_RESPONSE_NETWORK_STATE_CHANGED = 1002; const UNSOLICITED_RESPONSE_NEW_SMS = 1003; const UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT = 1004; const UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM = 1005; const UNSOLICITED_ON_USSD = 1006; @@ -182,8 +172,72 @@ const UNSOLICITED_RESTRICTED_STATE_CHANG const UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE = 1024; const UNSOLICITED_CDMA_CALL_WAITING = 1025; const UNSOLICITED_CDMA_OTA_PROVISION_STATUS = 1026; const UNSOLICITED_CDMA_INFO_REC = 1027; const UNSOLICITED_OEM_HOOK_RAW = 1028; const UNSOLICITED_RINGBACK_TONE = 1029; const UNSOLICITED_RESEND_INCALL_MUTE = 1030; +const RADIO_STATE_OFF = 0; +const RADIO_STATE_UNAVAILABLE = 1; +const RADIO_STATE_SIM_NOT_READY = 2; +const RADIO_STATE_SIM_LOCKED_OR_ABSENT = 3; +const RADIO_STATE_SIM_READY = 4; +const RADIO_STATE_RUIM_NOT_READY = 5; +const RADIO_STATE_RUIM_READY = 6; +const RADIO_STATE_RUIM_LOCKED_OR_ABSENT = 7; +const RADIO_STATE_NV_NOT_READY = 8; +const RADIO_STATE_NV_READY = 9; + +const CARD_MAX_APPS = 8; + +const CALL_STATE_ACTIVE = 0; +const CALL_STATE_HOLDING = 1; +const CALL_STATE_DIALING = 2; +const CALL_STATE_ALERTING = 3; +const CALL_STATE_INCOMING = 4; +const CALL_STATE_WAITING = 5; + +const TOA_INTERNATIONAL = 0x91; +const TOA_UNKNOWN = 0x81; + +const CALL_PRESENTATION_ALLOWED = 0; +const CALL_PRESENTATION_RESTRICTED = 1; +const CALL_PRESENTATION_UNKNOWN = 2; +const CALL_PRESENTATION_PAYPHONE = 3; + + +/** + * DOM constants + */ + +const DOM_RADIOSTATE_UNAVAILABLE = "unavailable"; +const DOM_RADIOSTATE_OFF = "off"; +const DOM_RADIOSTATE_READY = "ready"; + +const DOM_CARDSTATE_UNAVAILABLE = "unavailable"; +const DOM_CARDSTATE_ABSENT = "absent"; +const DOM_CARDSTATE_PIN_REQUIRED = "pin_required"; +const DOM_CARDSTATE_PUK_REQUIRED = "puk_required"; +const DOM_CARDSTATE_NETWORK_LOCKED = "network_locked"; +const DOM_CARDSTATE_NOT_READY = "not_ready"; +const DOM_CARDSTATE_READY = "ready"; + +const DOM_CALL_READYSTATE_DIALING = "dialing"; +const DOM_CALL_READYSTATE_RINGING = "ringing"; +const DOM_CALL_READYSTATE_BUSY = "busy"; +const DOM_CALL_READYSTATE_CONNECTING = "connecting"; +const DOM_CALL_READYSTATE_CONNECTED = "connected"; +const DOM_CALL_READYSTATE_DISCONNECTING = "disconnecting"; +const DOM_CALL_READYSTATE_DISCONNECTED = "disconnected"; +const DOM_CALL_READYSTATE_INCOMING = "incoming"; +const DOM_CALL_READYSTATE_HOLDING = "holding"; +const DOM_CALL_READYSTATE_HELD = "held"; + +const RIL_TO_DOM_CALL_STATE = [ + DOM_CALL_READYSTATE_CONNECTED, // CALL_READYSTATE_ACTIVE + DOM_CALL_READYSTATE_HELD, // CALL_READYSTATE_HOLDING + DOM_CALL_READYSTATE_DIALING, // CALL_READYSTATE_DIALING + DOM_CALL_READYSTATE_RINGING, // CALL_READYSTATE_ALERTING + DOM_CALL_READYSTATE_INCOMING, // CALL_READYSTATE_INCOMING + DOM_CALL_READYSTATE_HELD // CALL_READYSTATE_WAITING (XXX is this right?) +];
--- a/dom/telephony/ril_worker.js +++ b/dom/telephony/ril_worker.js @@ -66,19 +66,16 @@ importScripts("ril_consts.js"); const DEBUG = true; const INT32_MAX = 2147483647; const UINT8_SIZE = 1; const UINT16_SIZE = 2; const UINT32_SIZE = 4; const PARCEL_SIZE_SIZE = UINT32_SIZE; -const RESPONSE_TYPE_SOLICITED = 0; -const RESPONSE_TYPE_UNSOLICITED = 1; - /** * This object contains helpers buffering incoming data & deconstructing it * into parcels as well as buffering outgoing data & constructing parcels. * For that it maintains two buffers and corresponding uint8 views, indexes. * * The incoming buffer is a circular buffer where we store incoming data. * As soon as a complete parcel is received, it is processed right away, so * the buffer only needs to be large enough to hold one parcel. @@ -429,34 +426,36 @@ let Buf = { }, /** * Process one parcel. */ processParcel: function processParcel() { let response_type = this.readUint32(); - let length = this.readIncoming - 2 * UINT32_SIZE; + let length = this.readIncoming - UINT32_SIZE; let request_type; if (response_type == RESPONSE_TYPE_SOLICITED) { let token = this.readUint32(); let error = this.readUint32(); + length -= 2 * UINT32_SIZE; request_type = this.tokenRequestMap[token]; if (error) { //TODO debug("Received error " + error + " for solicited parcel type " + request_type); return; } debug("Solicited response for request type " + request_type + ", token " + token); delete this.tokenRequestMap[token]; } else if (response_type == RESPONSE_TYPE_UNSOLICITED) { request_type = this.readUint32(); + length -= UINT32_SIZE; debug("Unsolicited response for request type " + request_type); } else { debug("Unknown response type: " + response_type); return; } RIL.handleParcel(request_type, length); }, @@ -621,16 +620,43 @@ let RIL = { Buf.writeUint32(uusInfo || 0); // TODO Why do we need this extra 0? It was put it in to make this // match the format of the binary message. Buf.writeUint32(0); Buf.sendParcel(); }, /** + * Hang up the phone. + * + * @param index + * Call index (1-based) as reported by REQUEST_GET_CURRENT_CALLS. + */ + hangUp: function hangUp(index) { + Buf.newParcel(REQUEST_HANGUP); + Buf.writeUint32(1); + Buf.writeUint32(index); + Buf.sendParcel(); + }, + + /** + * Answer an incoming call. + */ + answerCall: function answerCall() { + Buf.simpleRequest(REQUEST_ANSWER); + }, + + /** + * Reject an incoming call. + */ + rejectCall: function rejectCall() { + Buf.simpleRequest(REQUEST_UDUB); + }, + + /** * Send an SMS. * * @param smscPDU * String containing the SMSC PDU in hex format. * @param pdu * String containing the PDU in hex format. */ sendSMS: function sendSMS(smscPDU, pdu) { @@ -693,67 +719,83 @@ RIL[REQUEST_ENTER_SIM_PIN] = function RE Phone.onEnterICCPIN(response); }; RIL[REQUEST_ENTER_SIM_PUK] = null; RIL[REQUEST_ENTER_SIM_PIN2] = null; RIL[REQUEST_ENTER_SIM_PUK2] = null; RIL[REQUEST_CHANGE_SIM_PIN] = null; RIL[REQUEST_CHANGE_SIM_PIN2] = null; RIL[REQUEST_ENTER_NETWORK_DEPERSONALIZATION] = null; -RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS() { - let calls = []; - let calls_length = Buf.readUint32(); +RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length) { + let calls_length = 0; + // The RIL won't even send us the length integer if there are no active calls. + // So only read this integer if the parcel actually has it. + if (length) { + calls_length = Buf.readUint32(); + } + if (!calls_length) { + Phone.onCurrentCalls(null); + return; + } + let calls = {}; for (let i = 0; i < calls_length; i++) { - let dc = { - state: Buf.readUint32(), // CALLSTATE_* constants - index: Buf.readUint32(), + let call = { + state: Buf.readUint32(), // CALL_STATE_* + index: Buf.readUint32(), // GSM index (1-based) toa: Buf.readUint32(), isMpty: Boolean(Buf.readUint32()), isMT: Boolean(Buf.readUint32()), als: Buf.readUint32(), isVoice: Boolean(Buf.readUint32()), isVoicePrivacy: Boolean(Buf.readUint32()), somethingOrOther: Buf.readUint32(), //XXX TODO whatziz? not in ril.h, but it's in the output... number: Buf.readString(), //TODO munge with TOA - numberPresentation: Buf.readUint32(), // Connection.PRESENTATION XXX TODO + numberPresentation: Buf.readUint32(), // CALL_PRESENTATION_* name: Buf.readString(), namePresentation: Buf.readUint32(), uusInfo: null }; let uusInfoPresent = Buf.readUint32(); if (uusInfoPresent == 1) { - dc.uusInfo = { + call.uusInfo = { type: Buf.readUint32(), dcs: Buf.readUint32(), userData: null //XXX TODO byte array?!? }; } - calls.push(dc); + calls[call.index] = call; } - Phone.onCurrentCalls(calls); }; -RIL[REQUEST_DIAL] = null; +RIL[REQUEST_DIAL] = function REQUEST_DIAL(length) { + Phone.onDial(); +}; RIL[REQUEST_GET_IMSI] = function REQUEST_GET_IMSI(length) { - let imsi = Buf.readString(length); + let imsi = Buf.readString(); Phone.onIMSI(imsi); }; -RIL[REQUEST_HANGUP] = null; +RIL[REQUEST_HANGUP] = function REQUEST_HANGUP(length) { + Phone.onHangUp(); +}; 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_CONFERENCE] = null; -RIL[REQUEST_UDUB] = null; +RIL[REQUEST_UDUB] = function REQUEST_UDUB(length) { + Phone.onRejectCall(); +}; RIL[REQUEST_LAST_CALL_FAIL_CAUSE] = null; RIL[REQUEST_SIGNAL_STRENGTH] = function REQUEST_SIGNAL_STRENGTH() { let strength = { // Valid values are (0-31, 99) as defined in TS 27.007 8.5. - gsmSignalStrength: Buf.readUint32(), + // For some reason we're getting int32s like [99, 4, 0, 0] and [99, 3, 0, 0] + // here, so let's strip of anything beyond the first byte. + gsmSignalStrength: Buf.readUint32() & 0xff, // GSM bit error rate (0-7, 99) as defined in TS 27.007 8.5. gsmBitErrorRate: Buf.readUint32(), // The CDMA RSSI value. cdmaDBM: Buf.readUint32(), // The CDMA EC/IO. cdmaECIO: Buf.readUint32(), // The EVDO RSSI value. evdoDBM: Buf.readUint32(), @@ -799,17 +841,19 @@ RIL[REQUEST_SMS_ACKNOWLEDGE] = null; RIL[REQUEST_GET_IMEI] = function REQUEST_GET_IMEI() { let imei = Buf.readString(); Phone.onIMEI(imei); }; RIL[REQUEST_GET_IMEISV] = function REQUEST_GET_IMEISV() { let imeiSV = Buf.readString(); Phone.onIMEISV(imeiSV); }; -RIL[REQUEST_ANSWER] = null; +RIL[REQUEST_ANSWER] = function REQUEST_ANSWER(length) { + Phone.onAnswerCall(); +}; RIL[REQUEST_DEACTIVATE_DATA_CALL] = null; RIL[REQUEST_QUERY_FACILITY_LOCK] = null; RIL[REQUEST_SET_FACILITY_LOCK] = null; RIL[REQUEST_CHANGE_BARRING_PASSWORD] = null; RIL[REQUEST_QUERY_NETWORK_SELECTION_MODE] = function REQUEST_QUERY_NETWORK_SELECTION_MODE() { let response = Buf.readUint32List(); Phone.onNetworkSelectionMode(response); }; @@ -896,17 +940,25 @@ RIL[UNSOLICITED_SIGNAL_STRENGTH] = funct RIL[UNSOLICITED_DATA_CALL_LIST_CHANGED] = null; RIL[UNSOLICITED_SUPP_SVC_NOTIFICATION] = null; RIL[UNSOLICITED_STK_SESSION_END] = null; RIL[UNSOLICITED_STK_PROACTIVE_COMMAND] = null; RIL[UNSOLICITED_STK_EVENT_NOTIFY] = null; RIL[UNSOLICITED_STK_CALL_SETUP] = null; RIL[UNSOLICITED_SIM_SMS_STORAGE_FULL] = null; RIL[UNSOLICITED_SIM_REFRESH] = null; -RIL[UNSOLICITED_CALL_RING] = null; +RIL[UNSOLICITED_CALL_RING] = function UNSOLICITED_CALL_RING() { + let info = { + isPresent: Buf.readUint32(), + signalType: Buf.readUint32(), + alertPitch: Buf.readUint32(), + signal: Buf.readUint32() + }; + Phone.onCallRing(info); +}; RIL[UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED] = null; RIL[UNSOLICITED_RESPONSE_CDMA_NEW_SMS] = null; RIL[UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS] = null; RIL[UNSOLICITED_CDMA_RUIM_SMS_STORAGE_FULL] = null; RIL[UNSOLICITED_RESTRICTED_STATE_CHANGED] = null; RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE] = null; RIL[UNSOLICITED_CDMA_CALL_WAITING] = null; RIL[UNSOLICITED_CDMA_OTA_PROVISION_STATUS] = null; @@ -956,17 +1008,17 @@ let Phone = { /** * ICC card status */ iccStatus: null, /** * Active calls */ - calls: null, + currentCalls: {}, /** * Handlers for messages from the RIL. They all begin with on* and are called * from RIL object. */ onRadioStateChanged: function onRadioStateChanged(newState) { debug("Radio state changed from " + this.radioState + " to " + newState); @@ -996,78 +1048,131 @@ let Phone = { } if (cdma) { RIL.getDeviceIdentity(); } Buf.simpleRequest(REQUEST_BASEBAND_VERSION); RIL.setScreenState(true); this.sendDOMMessage({ type: "radiostatechange", - radioState: (newState == RADIO_STATE_OFF) ? "off" : "ready" + radioState: (newState == RADIO_STATE_OFF) ? + DOM_RADIOSTATE_OFF : DOM_RADIOSTATE_READY }); //XXX TODO For now, just turn the radio on if it's off. for the real // deal we probably want to do the opposite: start with a known state // when we boot up and let the UI layer control the radio power. if (newState == RADIO_STATE_OFF) { RIL.setRadioPower(true); } } if (newState == RADIO_STATE_UNAVAILABLE) { // The radio is no longer available, we need to deal with any // remaining pending requests. //TODO do that this.sendDOMMessage({type: "radiostatechange", - radioState: "unavailable"}); + radioState: DOM_RADIOSTATE_UNAVAILABLE}); } if (newState == RADIO_STATE_SIM_READY || newState == RADIO_STATE_RUIM_READY || newState == RADIO_STATE_NV_READY) { // The ICC card has become available. Get all the things. RIL.getICCStatus(); this.requestNetworkInfo(); RIL.getSignalStrength(); this.sendDOMMessage({type: "cardstatechange", - cardState: "ready"}); + cardState: DOM_CARDSTATE_READY}); } if (newState == RADIO_STATE_SIM_LOCKED_OR_ABSENT || newState == RADIO_STATE_RUIM_LOCKED_OR_ABSENT) { RIL.getICCStatus(); this.sendDOMMessage({type: "cardstatechange", - cardState: "unavailable"}); + cardState: DOM_CARDSTATE_UNAVAILABLE}); } let wasOn = this.radioState != RADIO_STATE_OFF && this.radioState != RADIO_STATE_UNAVAILABLE; let isOn = newState != RADIO_STATE_OFF && newState != RADIO_STATE_UNAVAILABLE; if (!wasOn && isOn) { //TODO } if (wasOn && !isOn) { //TODO } this.radioState = newState; }, - onCurrentCalls: function onCurrentCalls(calls) { - debug("onCurrentCalls"); - debug(calls); - //TODO - this.sendDOMMessage({type: "callstatechange", callState: calls}); + onCurrentCalls: function onCurrentCalls(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. + for each (let currentCall in this.currentCalls) { + let callIndex = currentCall.index; + let newCall; + if (newCalls) { + newCall = newCalls[callIndex]; + delete newCalls[callIndex]; + } + + if (!newCall) { + // Call is no longer reported by the radio. Send disconnected + // state change. + this.sendDOMMessage({type: "callstatechange", + callState: DOM_CALL_READYSTATE_DISCONNECTED, + callIndex: callIndex, + number: currentCall.number, + name: currentCall.name}); + delete this.currentCalls[currentCall]; + continue; + } + + if (newCall.state == currentCall.state) { + continue; + } + + this._handleChangedCallState(newCall); + } + + // Go through any remaining calls that are new to us. + for each (let newCall in newCalls) { + if (newCall.isVoice) { + this._handleChangedCallState(newCall); + } + } + }, + + _handleChangedCallState: function handleChangedCallState(newCall) { + // Format international numbers appropriately. + if (newCall.number && + newCall.toa == TOA_INTERNATIONAL && + newCall.number[0] != "+") { + newCall.number = "+" + newCall.number; + } + this.currentCalls[newCall.index] = newCall; + this.sendDOMMessage({type: "callstatechange", + callState: RIL_TO_DOM_CALL_STATE[newCall.state], + callIndex: newCall.index, + number: newCall.number, + name: newCall.name}); }, onCallStateChanged: function onCallStateChanged() { RIL.getCurrentCalls(); }, + onCallRing: function onCallRing(info) { + debug("onCallRing " + JSON.stringify(info)); //DEBUG + RIL.getCurrentCalls(); + }, + onNetworkStateChanged: function onNetworkStateChanged() { debug("Network state changed, re-requesting phone state."); this.requestNetworkInfo(); }, onICCStatus: function onICCStatus(iccStatus) { debug("SIM card state is " + iccStatus.cardState); debug("Universal PIN state is " + iccStatus.universalPINState); @@ -1126,16 +1231,28 @@ let Phone = { }, onSignalStrength: function onSignalStrength(strength) { debug("Signal strength " + JSON.stringify(strength)); this.sendDOMMessage({type: "signalstrengthchange", signalStrength: strength}); }, + onDial: function onDial() { + }, + + onHangUp: function onHangUp() { + }, + + onAnswerCall: function onAnswerCall() { + }, + + onRejectCall: function onRejectCall() { + }, + onSendSMS: function onSendSMS(messageRef, ackPDU, errorCode) { //TODO }, /** * Outgoing requests to the RIL. These can be triggered from the * main thread via messages that look like this: @@ -1166,16 +1283,42 @@ let Phone = { * @param number * String containing the number to dial. */ dial: function dial(options) { RIL.dial(options.number, 0, 0); }, /** + * Hang up a call. + * + * @param callIndex + * Call index of the call to hang up. + */ + hangUp: function hangUp(options) { + //TODO need to check whether call is holding/waiting/background + // and then use REQUEST_HANGUP_WAITING_OR_BACKGROUND + RIL.hangUp(options.callIndex); + }, + + /** + * Answer an incoming call. + */ + answerCall: function answerCall() { + RIL.answerCall(); + }, + + /** + * Reject an incoming call. + */ + rejectCall: function rejectCall() { + RIL.rejectCall(); + }, + + /** * Send an SMS. * * @param number * String containing the recipient number. * @param message * String containing the message text. */ sendSMS: function sendSMS(options) {