From 74cf7b604551d5dfb906fe3a79ae58a0fc87f2c4 Mon Sep 17 00:00:00 2001 From: Edgar Chen Date: Wed, 28 Nov 2012 16:16:20 +0800 Subject: [PATCH] Bug 804667 - Part 3: Support TIMER MANAGEMENT in RIL. r=allstars.chh --- .../nsIMobileConnectionProvider.idl | 2 + dom/system/gonk/RILContentHelper.js | 9 ++ dom/system/gonk/RadioInterfaceLayer.js | 9 ++ dom/system/gonk/ril_consts.js | 15 +- dom/system/gonk/ril_worker.js | 140 +++++++++++++++++- 5 files changed, 171 insertions(+), 4 deletions(-) diff --git a/dom/network/interfaces/nsIMobileConnectionProvider.idl b/dom/network/interfaces/nsIMobileConnectionProvider.idl index 827d7fba8fd5..1d57a44af20f 100644 --- a/dom/network/interfaces/nsIMobileConnectionProvider.idl +++ b/dom/network/interfaces/nsIMobileConnectionProvider.idl @@ -51,6 +51,8 @@ interface nsIMobileConnectionProvider : nsISupports void sendStkMenuSelection(in nsIDOMWindow window, in unsigned short itemIdentifier, in boolean helpRequested); + void sendStkTimerExpiration(in nsIDOMWindow window, + in jsval timer); void sendStkEventDownload(in nsIDOMWindow window, in jsval event); diff --git a/dom/system/gonk/RILContentHelper.js b/dom/system/gonk/RILContentHelper.js index 1452498d1201..45ed20e1541a 100644 --- a/dom/system/gonk/RILContentHelper.js +++ b/dom/system/gonk/RILContentHelper.js @@ -580,6 +580,15 @@ RILContentHelper.prototype = { helpRequested: helpRequested}); }, + sendStkTimerExpiration: function sendStkTimerExpiration(window, + timer) { + if (window == null) { + throw Components.Exception("Can't get window object", + Cr.NS_ERROR_UNEXPECTED); + } + cpmm.sendAsyncMessage("RIL:SendStkTimerExpiration", {timer: timer}); + }, + sendStkEventDownload: function sendStkEventDownload(window, event) { if (window == null) { diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index 2299dbecd2e2..64dd9b64d803 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -91,6 +91,7 @@ const RIL_IPC_MOBILECONNECTION_MSG_NAMES = [ "RIL:CancelMMI", "RIL:SendStkResponse", "RIL:SendStkMenuSelection", + "RIL:SendStkTimerExpiration", "RIL:SendStkEventDownload", "RIL:RegisterMobileConnectionMsg", "RIL:SetCallForwardingOption", @@ -458,6 +459,9 @@ RadioInterfaceLayer.prototype = { case "RIL:SendStkMenuSelection": this.sendStkMenuSelection(msg.json); break; + case "RIL:SendStkTimerExpiration": + this.sendStkTimerExpiration(msg.json); + break; case "RIL:SendStkEventDownload": this.sendStkEventDownload(msg.json); break; @@ -1913,6 +1917,11 @@ RadioInterfaceLayer.prototype = { this.worker.postMessage(message); }, + sendStkTimerExpiration: function sendStkTimerExpiration(message) { + message.rilMessageType = "sendStkTimerExpiration"; + this.worker.postMessage(message); + }, + sendStkEventDownload: function sendStkEventDownload(message) { message.rilMessageType = "sendStkEventDownload"; this.worker.postMessage(message); diff --git a/dom/system/gonk/ril_consts.js b/dom/system/gonk/ril_consts.js index c401a9dd62ca..2ad8319feb26 100644 --- a/dom/system/gonk/ril_consts.js +++ b/dom/system/gonk/ril_consts.js @@ -536,6 +536,7 @@ this.BER_PROACTIVE_COMMAND_TAG = 0xd0; this.BER_SMS_PP_DOWNLOAD_TAG = 0xd1; this.BER_MENU_SELECTION_TAG = 0xd3; this.BER_EVENT_DOWNLOAD_TAG = 0xd6; +this.BER_TIMER_EXPIRATION_TAG = 0xd7; // Flags in Comprehension TLV. this.COMPREHENSIONTLV_FLAG_CR = 0x80; // Comprehension required. @@ -566,6 +567,8 @@ this.COMPREHENSIONTLV_TAG_TRANSACTION_ID = 0x1c; this.COMPREHENSIONTLV_TAG_EVENT_LIST = 0x19; this.COMPREHENSIONTLV_TAG_ICON_ID = 0x1e; this.COMPREHENSIONTLV_TAG_ICON_ID_LIST = 0x1f; +this.COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER = 0x24; +this.COMPREHENSIONTLV_TAG_TIMER_VALUE = 0x25; this.COMPREHENSIONTLV_TAG_DATE_TIME_ZONE = 0x26; this.COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE = 0x2b; this.COMPREHENSIONTLV_TAG_LANGUAGE = 0x2d; @@ -614,6 +617,7 @@ this.STK_CMD_GET_INPUT = 0x23; this.STK_CMD_SELECT_ITEM = 0x24; this.STK_CMD_SET_UP_MENU = 0x25; this.STK_CMD_PROVIDE_LOCAL_INFO = 0x26; +this.STK_CMD_TIMER_MANAGEMENT = 0x27; this.STK_CMD_SET_UP_IDLE_MODE_TEXT = 0x28; // STK Result code. @@ -816,6 +820,11 @@ this.STK_LOCAL_INFO_MULTIPLE_ACCESS_TECH = 0x0E; this.STK_LOCAL_INFO_INFO_FOR_MULTIPLE_ACCESS_TECH = 0x0F; this.STK_LOCAL_INFO_NMR_FOR_MULTIPLE_ACCESS_TECH = 0x10; +// Timer Management. +this.STK_TIMER_START = 0x00; +this.STK_TIMER_DEACTIVATE = 0x01; +this.STK_TMIER_GET_CURRENT_VALUE = 0x02; + /** * Supported Terminal Facilities. * @@ -827,7 +836,7 @@ this.STK_TERMINAL_SUPPORT_SMS_PP_DOWNLOAD = 1; this.STK_TERMINAL_SUPPORT_CELL_BROADCAST_DATA_DOWNLOAD = 0; this.STK_TERMINAL_SUPPORT_MENU_SELECTION = 1; this.STK_TERMINAL_SUPPORT_SIM_DATA_DOWNLOAD_ERROR = 0; -this.STK_TERMINAL_SUPPORT_TIMER_EXPIRATION = 0; +this.STK_TERMINAL_SUPPORT_TIMER_EXPIRATION = 1; this.STK_TERMINAL_SUPPORT_USSD_IN_CALL_CONTROL = 0; this.STK_TERMINAL_SUPPORT_CALL_CONTROL_IN_REDIAL = 0; @@ -867,8 +876,8 @@ this.STK_TERMINAL_SUPPORT_EVENT_USER_ACTIVITY = 0; this.STK_TERMINAL_SUPPORT_EVENT_IDLE_SCREEN_AVAILABLE = 0; this.STK_TERMINAL_SUPPORT_EVENT_CARD_READER_STATUS = 0; -this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_START_STOP = 0; -this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_GET_CURRENT = 0; +this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_START_STOP = 1; +this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_GET_CURRENT = 1; this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_DATE = 1; this.STK_TERMINAL_SUPPORT_GET_INKEY = 1; this.STK_TERMINAL_SUPPORT_SET_UP_IDLE_MODE_TEXT = 1; diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index 39b0d776aa56..37474feb3812 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -63,6 +63,8 @@ const TLV_LOCATION_INFO_UMTS_SIZE = 11; const TLV_IMEI_SIZE = 10; const TLV_DATE_TIME_ZONE_SIZE = 9; const TLV_LANGUAGE_SIZE = 4; +const TLV_TIMER_IDENTIFIER = 3; +const TLV_TIMER_VALUE = 5; const DEFAULT_EMERGENCY_NUMBERS = ["112", "911"]; @@ -3364,6 +3366,7 @@ let RIL = { * @param [optional] isYesNo * @param [optional] hasConfirmed * @param [optional] localInfo + * @param [optional] timer */ sendStkTerminalResponse: function sendStkTerminalResponse(response) { if (response.hasConfirmed !== undefined) { @@ -3407,6 +3410,12 @@ let RIL = { (localInfo.date ? TLV_DATE_TIME_ZONE_SIZE : 0) + (localInfo.language ? TLV_LANGUAGE_SIZE : 0)) * 2); } + if (response.timer) { + let timer = response.timer; + size = size + + ((timer.timerId ? TLV_TIMER_IDENTIFIER : 0) + + (timer.timerValue ? TLV_TIMER_VALUE : 0)) * 2; + } Buf.writeUint32(size); // Command Details @@ -3525,6 +3534,21 @@ let RIL = { } } + // Timer + if (response.timer) { + let timer = response.timer; + + if (timer.timerId) { + GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER); + GsmPDUHelper.writeHexOctet(1); + GsmPDUHelper.writeHexOctet(timer.timerId); + } + + if (timer.timerValue) { + ComprehensionTlvHelper.writeTimerValueTlv(timer.timerValue, false); + } + } + Buf.writeUint32(0); Buf.sendParcel(); }, @@ -3544,6 +3568,22 @@ let RIL = { this.sendICCEnvelopeCommand(command); }, + /** + * Send STK Envelope(Timer Expiration) command. + * + * @param timer + */ + sendStkTimerExpiration: function sendStkTimerExpiration(command) { + command.tag = BER_TIMER_EXPIRATION_TAG; + command.deviceId = { + sourceId: STK_DEVICE_ID_ME, + destinationId: STK_DEVICE_ID_SIM + }; + command.timerId = command.timer.timerId; + command.timerValue = command.timer.timerValue; + this.sendICCEnvelopeCommand(command); + }, + /** * Send STK Envelope(Event Download) command. * @param event @@ -3598,6 +3638,8 @@ let RIL = { * @param [optional] address * @param [optional] transactionId * @param [optional] cause + * @param [optional] timerId + * @param [optional] timerValue */ sendICCEnvelopeCommand: function sendICCEnvelopeCommand(options) { if (DEBUG) { @@ -3621,7 +3663,9 @@ let RIL = { Math.ceil(options.address.length/2) + 1) + // Length of length field. Math.ceil(options.address.length/2) + 1 // address BCD + TON. : 0) + - (options.cause ? 4 : 0); + (options.cause ? 4 : 0) + + (options.timerId ? TLV_TIMER_IDENTIFIER : 0) + + (options.timerValue ? TLV_TIMER_VALUE : 0); let size = (2 + berLen) * 2; Buf.writeUint32(size); @@ -3698,6 +3742,19 @@ let RIL = { ComprehensionTlvHelper.writeCauseTlv(options.cause); } + // Timer Identifier + if (options.timerId) { + GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER | + COMPREHENSIONTLV_FLAG_CR); + GsmPDUHelper.writeHexOctet(1); + GsmPDUHelper.writeHexOctet(options.timerId); + } + + // Timer Value + if (options.timerValue) { + ComprehensionTlvHelper.writeTimerValueTlv(options.timerValue, true); + } + Buf.writeUint32(0); Buf.sendParcel(); }, @@ -8199,6 +8256,9 @@ let StkCommandParamsFactory = { case STK_CMD_PLAY_TONE: param = this.processPlayTone(cmdDetails, ctlvs); break; + case STK_CMD_TIMER_MANAGEMENT: + param = this.processTimerManagement(cmdDetails, ctlvs); + break; default: debug("unknown proactive command"); break; @@ -8572,6 +8632,26 @@ let StkCommandParamsFactory = { localInfoType: cmdDetails.commandQualifier }; return provideLocalInfo; + }, + + processTimerManagement: function processTimerManagement(cmdDetails, ctlvs) { + let timer = { + timerAction: cmdDetails.commandQualifier + }; + + let ctlv = StkProactiveCmdHelper.searchForTag( + COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER, ctlvs); + if (ctlv) { + timer.timerId = ctlv.value.timerId; + } + + ctlv = StkProactiveCmdHelper.searchForTag( + COMPREHENSIONTLV_TAG_TIMER_VALUE, ctlvs); + if (ctlv) { + timer.timerValue = ctlv.value.timerValue; + } + + return timer; } }; @@ -8604,6 +8684,10 @@ let StkProactiveCmdHelper = { return this.retrieveDefaultText(length); case COMPREHENSIONTLV_TAG_EVENT_LIST: return this.retrieveEventList(length); + case COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER: + return this.retrieveTimerId(length); + case COMPREHENSIONTLV_TAG_TIMER_VALUE: + return this.retrieveTimerValue(length); case COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE: return this.retrieveImmediaResponse(length); case COMPREHENSIONTLV_TAG_URL: @@ -8860,6 +8944,40 @@ let StkProactiveCmdHelper = { }; }, + /** + * Timer Identifier. + * + * | Byte | Description | Length | + * | 1 | Timer Identifier Tag | 1 | + * | 2 | Length = 01 | 1 | + * | 3 | Timer Identifier | 1 | + */ + retrieveTimerId: function retrieveTimerId(length) { + let id = { + timerId: GsmPDUHelper.readHexOctet() + }; + return id; + }, + + /** + * Timer Value. + * + * | Byte | Description | Length | + * | 1 | Timer Value Tag | 1 | + * | 2 | Length = 03 | 1 | + * | 3 | Hour | 1 | + * | 4 | Minute | 1 | + * | 5 | Second | 1 | + */ + retrieveTimerValue: function retrieveTimerValue(length) { + let value = { + timerValue: (GsmPDUHelper.readSwappedNibbleBcdNum(1) * 60 * 60) + + (GsmPDUHelper.readSwappedNibbleBcdNum(1) * 60) + + (GsmPDUHelper.readSwappedNibbleBcdNum(1)) + }; + return value; + }, + /** * Immediate Response. * @@ -9116,6 +9234,26 @@ let ComprehensionTlvHelper = { PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT].indexOf(language[1])); }, + /** + * Write Timer Value Comprehension TLV. + * + * @param seconds length of time during of the timer. + * @param cr Comprehension Required or not + */ + writeTimerValueTlv: function writeTimerValueTlv(seconds, cr) { + GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TIMER_VALUE | + (cr ? COMPREHENSIONTLV_FLAG_CR : 0)); + GsmPDUHelper.writeHexOctet(3); + + // TS 102.223, clause 8.38 + // +----------------+------------------+-------------------+ + // | hours (1 byte) | minutes (1 btye) | secounds (1 byte) | + // +----------------+------------------+-------------------+ + GsmPDUHelper.writeSwappedNibbleBCDNum(Math.floor(seconds / 60 / 60)); + GsmPDUHelper.writeSwappedNibbleBCDNum(Math.floor(seconds / 60) % 60); + GsmPDUHelper.writeSwappedNibbleBCDNum(seconds % 60); + }, + getSizeOfLengthOctets: function getSizeOfLengthOctets(length) { if (length >= 0x10000) { return 4; // 0x83, len_1, len_2, len_3