Bug 790547 - Part 3: Add send Location Status Event in RIL. r=philikon
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -448,16 +448,25 @@ RILContentHelper.prototype = {
if (window == null) {
throw Components.Exception("Can't get window object",
Cr.NS_ERROR_UNEXPECTED);
}
cpmm.sendAsyncMessage("RIL:SendStkMenuSelection", {itemIdentifier: itemIdentifier,
helpRequested: helpRequested});
},
+ sendStkEventDownload: function sendStkEventDownload(window,
+ event) {
+ if (window == null) {
+ throw Components.Exception("Can't get window object",
+ Cr.NS_ERROR_UNEXPECTED);
+ }
+ cpmm.sendAsyncMessage("RIL:SendStkEventDownload", {event: event});
+ },
+
_telephonyCallbacks: null,
_voicemailCallbacks: null,
_enumerateTelephonyCallbacks: null,
voicemailStatus: null,
voicemailNumber: null,
voicemailDisplayName: null,
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -68,16 +68,17 @@ const RIL_IPC_MOBILECONNECTION_MSG_NAMES
"RIL:SelectNetworkAuto",
"RIL:GetCardLock",
"RIL:UnlockCardLock",
"RIL:SetCardLock",
"RIL:SendUSSD",
"RIL:CancelUSSD",
"RIL:SendStkResponse",
"RIL:SendStkMenuSelection",
+ "RIL:SendStkEventDownload",
];
XPCOMUtils.defineLazyServiceGetter(this, "gSmsService",
"@mozilla.org/sms/smsservice;1",
"nsISmsService");
XPCOMUtils.defineLazyServiceGetter(this, "gSmsRequestManager",
"@mozilla.org/sms/smsrequestmanager;1",
@@ -379,16 +380,19 @@ RadioInterfaceLayer.prototype = {
this.cancelUSSD(msg.json);
break;
case "RIL:SendStkResponse":
this.sendStkResponse(msg.json);
break;
case "RIL:SendStkMenuSelection":
this.sendStkMenuSelection(msg.json);
break;
+ case "RIL:SendStkEventDownload":
+ this.sendStkEventDownload(msg.json);
+ break;
}
},
onerror: function onerror(event) {
debug("Got an error: " + event.filename + ":" +
event.lineno + ": " + event.message + "\n");
event.preventDefault();
},
@@ -1525,16 +1529,21 @@ RadioInterfaceLayer.prototype = {
this.worker.postMessage(message);
},
sendStkMenuSelection: function sendStkMenuSelection(message) {
message.rilMessageType = "sendStkMenuSelection";
this.worker.postMessage(message);
},
+ sendStkEventDownload: function sendStkEventDownload(message) {
+ message.rilMessageType = "sendStkEventDownload";
+ this.worker.postMessage(message);
+ },
+
get microphoneMuted() {
return gAudioManager.microphoneMuted;
},
set microphoneMuted(value) {
if (value == this.microphoneMuted) {
return;
}
gAudioManager.microphoneMuted = value;
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -535,18 +535,20 @@ const COMPREHENSIONTLV_TAG_RESULT = 0x03
const COMPREHENSIONTLV_TAG_DURATION = 0x04;
const COMPREHENSIONTLV_TAG_ALPHA_ID = 0x05;
const COMPREHENSIONTLV_TAG_ADDRESS = 0x06;
const COMPREHENSIONTLV_TAG_SMS_TPDU = 0x0b;
const COMPREHENSIONTLV_TAG_TEXT_STRING = 0x0d;
const COMPREHENSIONTLV_TAG_ITEM = 0x0f;
const COMPREHENSIONTLV_TAG_ITEM_ID = 0x10;
const COMPREHENSIONTLV_TAG_RESPONSE_LENGTH = 0x11;
+const COMPREHENSIONTLV_TAG_LOCATION_INFO = 0x13;
const COMPREHENSIONTLV_TAG_HELP_REQUEST = 0x15;
const COMPREHENSIONTLV_TAG_DEFAULT_TEXT = 0x17;
+const COMPREHENSIONTLV_TAG_LOCATION_STATUS = 0x1b;
const COMPREHENSIONTLV_TAG_EVENT_LIST = 0x19;
const COMPREHENSIONTLV_TAG_ICON_ID = 0x1e;
const COMPREHENSIONTLV_TAG_ICON_ID_LIST = 0x1f;
const COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE = 0x2b;
const COMPREHENSIONTLV_TAG_URL = 0x31;
// Device identifiers, see TS 11.14, clause 12.7
const STK_DEVICE_ID_KEYPAD = 0x01;
@@ -720,16 +722,21 @@ const STK_EVENT_TYPE_BROWSER_TERMINATION
const STK_EVENT_TYPE_DATA_AVAILABLE = 0x09;
const STK_EVENT_TYPE_CHANNEL_STATUS = 0x0a;
const STK_EVENT_TYPE_SINGLE_ACCESS_TECHNOLOGY_CHANGED = 0x0b;
const STK_EVENT_TYPE_DISPLAY_PARAMETER_CHANGED = 0x0c;
const STK_EVENT_TYPE_LOCAL_CONNECTION = 0x0d;
const STK_EVENT_TYPE_NETWORK_SEARCH_MODE_CHANGED = 0x0e;
const STK_EVENT_TYPE_BROWSING_STATUS = 0x0f;
+// STK Service state of Location Status.
+const STK_SERVICE_STATE_NORMAL = 0x00;
+const STK_SERVICE_STATE_LIMITED = 0x01;
+const STK_SERVICE_STATE_UNAVAILABLE = 0x02;
+
/**
* (U)SIM Services.
*
* @see 3GPP TS 51.011 10.3.7 (SIM) and 3GPP TS 31.102 4.2.8 (USIM).
*/
const GECKO_ICC_SERVICES = {
sim: {
ADN: 2,
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -46,16 +46,26 @@ let DEBUG = DEBUG_WORKER;
const INT32_MAX = 2147483647;
const UINT8_SIZE = 1;
const UINT16_SIZE = 2;
const UINT32_SIZE = 4;
const PARCEL_SIZE_SIZE = UINT32_SIZE;
const PDU_HEX_OCTET_SIZE = 4;
+const TLV_COMMAND_DETAILS_SIZE = 5;
+const TLV_DEVICE_ID_SIZE = 4;
+const TLV_RESULT_SIZE = 3;
+const TLV_ITEM_ID_SIZE = 3;
+const TLV_HELP_REQUESTED_SIZE = 2;
+const TLV_EVENT_LIST_SIZE = 3;
+const TLV_LOCATION_STATUS_SIZE = 3;
+const TLV_LOCATION_INFO_GSM_SIZE = 9;
+const TLV_LOCATION_INFO_UMTS_SIZE = 11;
+
const DEFAULT_EMERGENCY_NUMBERS = ["112", "911"];
let RILQUIRKS_CALLSTATE_EXTRA_UINT32 = libcutils.property_get("ro.moz.ril.callstate_extra_int");
// This may change at runtime since in RIL v6 and later, we get the version
// number via the UNSOLICITED_RIL_CONNECTED parcel.
let RILQUIRKS_V5_LEGACY = libcutils.property_get("ro.moz.ril.v5_legacy");
let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = libcutils.property_get("ro.moz.ril.dial_emergency_call");
let RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE = libcutils.property_get("ro.moz.ril.emergency_by_default");
@@ -2252,20 +2262,20 @@ let RIL = {
textLen = bits * 7 / 8 + (bits % 8 ? 1 : 0);
} else {
textLen = response.input.length;
}
}
}
// 1 octets = 2 chars.
- let size = (5 + /* Size of Command Details TLV */
- 4 + /* Size of Device Identifier TLV */
- 3 + /* Size of Result */
- (response.itemIdentifier ? 3 : 0) +
+ let size = (TLV_COMMAND_DETAILS_SIZE +
+ TLV_DEVICE_ID_SIZE +
+ TLV_RESULT_SIZE +
+ (response.itemIdentifier ? TLV_ITEM_ID_SIZE : 0) +
(textLen ? textLen + 3 : 0)) * 2;
Buf.writeUint32(size);
// Command Details
GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
COMPREHENSIONTLV_FLAG_CR);
GsmPDUHelper.writeHexOctet(3);
if (response.command) {
@@ -2361,28 +2371,64 @@ let RIL = {
command.deviceId = {
sourceId :STK_DEVICE_ID_KEYPAD,
destinationId: STK_DEVICE_ID_SIM
};
this.sendICCEnvelopeCommand(command);
},
/**
+ * Send STK Envelope(Event Download) command.
+ * @param event
+ */
+ sendStkEventDownload: function sendStkEventDownload(command) {
+ command.tag = BER_EVENT_DOWNLOAD_TAG;
+ command.eventList = command.event.eventType;
+ switch (command.eventList) {
+ case STK_EVENT_TYPE_LOCATION_STATUS:
+ command.deviceId = {
+ sourceId :STK_DEVICE_ID_ME,
+ destinationId: STK_DEVICE_ID_SIM
+ };
+ command.locationStatus = command.event.locationStatus;
+ // Location info should only be provided when locationStatus is normal.
+ if (command.locationStatus == STK_SERVICE_STATE_NORMAL) {
+ command.locationInfo = command.event.locationInfo;
+ }
+ break;
+ }
+ this.sendICCEnvelopeCommand(command);
+ },
+
+ /**
* Send REQUEST_STK_SEND_ENVELOPE_COMMAND to ICC.
*
* @param tag
* @patam deviceId
* @param [optioanl] itemIdentifier
* @param [optional] helpRequested
+ * @param [optional] eventList
+ * @param [optional] locationStatus
+ * @param [optional] locationInfo
*/
sendICCEnvelopeCommand: function sendICCEnvelopeCommand(options) {
+ if (DEBUG) {
+ debug("Stk Envelope " + JSON.stringify(options));
+ }
let token = Buf.newParcel(REQUEST_STK_SEND_ENVELOPE_COMMAND);
- let berLen = 4 + /* Size of Device Identifier TLV */
- (options.itemIdentifier ? 3 : 0) +
- (options.helpRequested ? 2 : 0);
+ let berLen = TLV_DEVICE_ID_SIZE + /* Size of Device Identifier TLV */
+ (options.itemIdentifier ? TLV_ITEM_ID_SIZE : 0) +
+ (options.helpRequested ? TLV_HELP_REQUESTED_SIZE : 0) +
+ (options.eventList ? TLV_EVENT_LIST_SIZE : 0) +
+ (options.locationStatus ? TLV_LOCATION_STATUS_SIZE : 0) +
+ (options.locationInfo ?
+ (options.locationInfo.gsmCellId > 0xffff ?
+ TLV_LOCATION_INFO_UMTS_SIZE :
+ TLV_LOCATION_INFO_GSM_SIZE) :
+ 0);
let size = (2 + berLen) * 2;
Buf.writeUint32(size);
// Write a BER-TLV
GsmPDUHelper.writeHexOctet(options.tag);
GsmPDUHelper.writeHexOctet(berLen);
@@ -2404,16 +2450,38 @@ let RIL = {
// Help Request
if (options.helpRequested) {
GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_HELP_REQUEST |
COMPREHENSIONTLV_FLAG_CR);
GsmPDUHelper.writeHexOctet(0);
// Help Request doesn't have value
}
+ // Event List
+ if (options.eventList) {
+ GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_EVENT_LIST |
+ COMPREHENSIONTLV_FLAG_CR);
+ GsmPDUHelper.writeHexOctet(1);
+ GsmPDUHelper.writeHexOctet(options.eventList);
+ }
+
+ // Location Status
+ if (options.locationStatus) {
+ let len = options.locationStatus.length;
+ GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_LOCATION_STATUS |
+ COMPREHENSIONTLV_FLAG_CR);
+ GsmPDUHelper.writeHexOctet(1);
+ GsmPDUHelper.writeHexOctet(options.locationStatus);
+ }
+
+ // Location Info
+ if (options.locationInfo) {
+ ComprehensionTlvHelper.writeLocationInfoTlv(options.locationInfo);
+ }
+
Buf.writeUint32(0);
Buf.sendParcel();
},
/**
* Check a given number against the list of emergency numbers provided by the RIL.
*
* @param number
@@ -6664,17 +6732,78 @@ let ComprehensionTlvHelper = {
let index = 0;
while (index < length) {
let tlv = this.decode();
chunks.push(tlv);
index += tlv.length;
index += tlv.hlen;
}
return chunks;
- }
+ },
+
+ /**
+ * Write Location Info Comprehension TLV.
+ *
+ * @param loc location Information.
+ */
+ writeLocationInfoTlv: function writeLocationInfoTlv(loc) {
+ GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_LOCATION_INFO |
+ COMPREHENSIONTLV_FLAG_CR);
+ GsmPDUHelper.writeHexOctet(loc.gsmCellId > 0xffff ? 9 : 7);
+ // From TS 11.14, clause 12.19
+ // "The mobile country code (MCC), the mobile network code (MNC),
+ // the location area code (LAC) and the cell ID are
+ // coded as in TS 04.08."
+ // And from TS 04.08 and TS 24.008,
+ // the format is as follows:
+ //
+ // MCC = MCC_digit_1 + MCC_digit_2 + MCC_digit_3
+ //
+ // 8 7 6 5 4 3 2 1
+ // +-------------+-------------+
+ // | MCC digit 2 | MCC digit 1 | octet 2
+ // | MNC digit 3 | MCC digit 3 | octet 3
+ // | MNC digit 2 | MNC digit 1 | octet 4
+ // +-------------+-------------+
+ //
+ // Also in TS 24.008
+ // "However a network operator may decide to
+ // use only two digits in the MNC in the LAI over the
+ // radio interface. In this case, bits 5 to 8 of octet 3
+ // shall be coded as '1111'".
+
+ // MCC & MNC, 3 octets
+ let mcc = loc.mcc.toString();
+ let mnc = loc.mnc.toString();
+ if (mnc.length == 1) {
+ mnc = "F0" + mnc;
+ } else if (mnc.length == 2) {
+ mnc = "F" + mnc;
+ } else {
+ mnc = mnc[2] + mnc[0] + mnc[1];
+ }
+ GsmPDUHelper.writeSwappedNibbleBCD(mcc + mnc);
+
+ // LAC, 2 octets
+ GsmPDUHelper.writeHexOctet((loc.gsmLocationAreaCode >> 8) & 0xff);
+ GsmPDUHelper.writeHexOctet(loc.gsmLocationAreaCode & 0xff);
+
+ // Cell Id
+ if (loc.gsmCellId > 0xffff) {
+ // UMTS/WCDMA, gsmCellId is 28 bits.
+ GsmPDUHelper.writeHexOctet((loc.gsmCellId >> 24) & 0xff);
+ GsmPDUHelper.writeHexOctet((loc.gsmCellId >> 16) & 0xff);
+ GsmPDUHelper.writeHexOctet((loc.gsmCellId >> 8) & 0xff);
+ GsmPDUHelper.writeHexOctet(loc.gsmCellId & 0xff);
+ } else {
+ // GSM, gsmCellId is 16 bits.
+ GsmPDUHelper.writeHexOctet((loc.gsmCellId >> 8) & 0xff);
+ GsmPDUHelper.writeHexOctet(loc.gsmCellId & 0xff);
+ }
+ },
};
let BerTlvHelper = {
/**
* Decode Ber TLV.
*
* @param dataLen
* The length of data in bytes.