diff --git a/dom/system/b2g/Makefile.in b/dom/system/b2g/Makefile.in index 6daa3ab351d..31b337e74bb 100644 --- a/dom/system/b2g/Makefile.in +++ b/dom/system/b2g/Makefile.in @@ -83,6 +83,7 @@ EXTRA_COMPONENTS = \ EXTRA_JS_MODULES = \ ril_consts.js \ ril_worker.js \ + systemlibs.js \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/dom/system/b2g/ril_worker.js b/dom/system/b2g/ril_worker.js index 5dcce3f2a6f..d5873b5aa3c 100644 --- a/dom/system/b2g/ril_worker.js +++ b/dom/system/b2g/ril_worker.js @@ -62,7 +62,7 @@ "use strict"; -importScripts("ril_consts.js"); +importScripts("ril_consts.js", "systemlibs.js"); let DEBUG = false; @@ -72,6 +72,8 @@ const UINT16_SIZE = 2; const UINT32_SIZE = 4; const PARCEL_SIZE_SIZE = UINT32_SIZE; +let RILQUIRKS_CALLSTATE_EXTRA_UINT32 = false; + /** * This object contains helpers buffering incoming data & deconstructing it * into parcels as well as buffering outgoing data & constructing parcels. @@ -518,6 +520,25 @@ let Buf = { */ let RIL = { + /** + * Set quirk flags based on the RIL model detected. Note that this + * requires the RIL being "warmed up" first, which happens when on + * an incoming or outgoing call. + */ + rilQuirksInitialized: false, + initRILQuirks: function initRILQuirks() { + // The Samsung Galaxy S2 I-9100 radio sends an extra Uint32 in the + // call state. + let model_id = libcutils.property_get("ril.model_id"); + if (DEBUG) debug("Detected RIL model " + model_id); + if (model_id == "I9100") { + if (DEBUG) debug("Enabling RILQUIRKS_CALLSTATE_EXTRA_UINT32 for I9100."); + RILQUIRKS_CALLSTATE_EXTRA_UINT32 = true; + } + + this.rilQuirksInitialized = true; + }, + /** * Retrieve the ICC's status. * @@ -917,6 +938,10 @@ RIL[REQUEST_CHANGE_SIM_PIN] = function REQUEST_CHANGE_SIM_PIN() { RIL[REQUEST_CHANGE_SIM_PIN2] = null; RIL[REQUEST_ENTER_NETWORK_DEPERSONALIZATION] = null; RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length) { + if (!this.rilQuirksInitialized) { + this.initRILQuirks(); + } + 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. @@ -930,22 +955,24 @@ RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length) { let calls = {}; for (let i = 0; i < calls_length; i++) { - let call = { - state: Buf.readUint32(), // CALL_STATE_* - callIndex: 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(), // CALL_PRESENTATION_* - name: Buf.readString(), - namePresentation: Buf.readUint32(), - uusInfo: null - }; + let call = {}; + call.state = Buf.readUint32(); // CALL_STATE_* + call.callIndex = Buf.readUint32(); // GSM index (1-based) + call.toa = Buf.readUint32(); + call.isMpty = Boolean(Buf.readUint32()); + call.isMT = Boolean(Buf.readUint32()); + call.als = Buf.readUint32(); + call.isVoice = Boolean(Buf.readUint32()); + call.isVoicePrivacy = Boolean(Buf.readUint32()); + if (RILQUIRKS_CALLSTATE_EXTRA_UINT32) { + Buf.readUint32(); + } + call.number = Buf.readString(); //TODO munge with TOA + call.numberPresentation = Buf.readUint32(); // CALL_PRESENTATION_* + call.name = Buf.readString(); + call.namePresentation = Buf.readUint32(); + + call.uusInfo = null; let uusInfoPresent = Buf.readUint32(); if (uusInfoPresent == 1) { call.uusInfo = { @@ -954,6 +981,7 @@ RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length) { userData: null //XXX TODO byte array?!? }; } + calls[call.callIndex] = call; } Phone.onCurrentCalls(calls); diff --git a/dom/system/b2g/systemlibs.js b/dom/system/b2g/systemlibs.js new file mode 100644 index 00000000000..df09d3a3f8c --- /dev/null +++ b/dom/system/b2g/systemlibs.js @@ -0,0 +1,79 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const SYSTEM_PROPERTY_KEY_MAX = 32; +const SYSTEM_PROPERTY_VALUE_MAX = 92; + +/** + * Expose some system-level functions. + */ +let libcutils = (function() { + let lib; + try { + lib = ctypes.open("libcutils.so"); + } catch(ex) { + // Return a fallback option in case libcutils.so isn't present (e.g. + // when building Firefox with MOZ_B2G_RIL. + dump("Could not load libcutils.so. Using fake propdb."); + let fake_propdb = Object.create(null); + return { + property_get: function fake_property_get(key, defaultValue) { + if (key in fake_propdb) { + return fake_propdb[key]; + } + return defaultValue === undefined ? null : defaultValue; + }, + property_set: function fake_property_set(key, value) { + fake_propdb[key] = value; + } + }; + } + + let c_property_get = lib.declare("property_get", ctypes.default_abi, + ctypes.int, // return value: length + ctypes.char.ptr, // key + ctypes.char.ptr, // value + ctypes.char.ptr); // default + let c_property_set = lib.declare("property_set", ctypes.default_abi, + ctypes.int, // return value: success + ctypes.char.ptr, // key + ctypes.char.ptr); // value + let c_value_buf = ctypes.char.array(SYSTEM_PROPERTY_VALUE_MAX)(); + + return { + + /** + * Get a system property. + * + * @param key + * Name of the property + * @param defaultValue [optional] + * Default value to return if the property isn't set (default: null) + */ + property_get: function property_get(key, defaultValue) { + if (defaultValue === undefined) { + defaultValue = null; + } + c_property_get(key, c_value_buf, defaultValue); + return c_value_buf.readString(); + }, + + /** + * Set a system property + * + * @param key + * Name of the property + * @param value + * Value to set the property to. + */ + property_set: function property_set(key, value) { + let rv = c_property_set(key, value); + if (rv) { + throw Error('libcutils.property_set("' + key + '", "' + value + + '") failed with error ' + rv); + } + } + + }; +})();