Created
June 18, 2012 22:41
-
-
Save marshall/2951208 to your computer and use it in GitHub Desktop.
networkSelectionModes.patch - v4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# HG changeset patch | |
# User Marshall Culpepper <[email protected]> | |
Bug 759637: Initial implementation of MobileConnection network selection APIs. r=philikon sr=sicking | |
diff --git a/dom/network/interfaces/nsIDOMMobileConnection.idl b/dom/network/interfaces/nsIDOMMobileConnection.idl | |
index 1df7131..ef434cd 100644 | |
--- a/dom/network/interfaces/nsIDOMMobileConnection.idl | |
+++ b/dom/network/interfaces/nsIDOMMobileConnection.idl | |
@@ -31,17 +31,52 @@ interface nsIDOMMozMobileConnection : nsIDOMEventTarget | |
readonly attribute nsIDOMMozMobileConnectionInfo data; | |
/** | |
+ * The selection mode of the voice and data networks. | |
+ * | |
+ * Possible values: null (unknown), 'automatic', 'manual' | |
+ */ | |
+ readonly attribute DOMString networkSelectionMode; | |
+ | |
+ /** | |
* Search for available networks. | |
* | |
* If successful, the request's onsuccess will be called, and the request's | |
* result will be an array of nsIDOMMozMobileNetworkInfo. | |
* | |
* Otherwise, the request's onerror will be called, and the request's error | |
- * will be either 'RadioNotAvailable', 'RequestNotSupported', or 'GenericFailure'. | |
+ * will be either 'RadioNotAvailable', 'RequestNotSupported', | |
+ * or 'GenericFailure'. | |
*/ | |
nsIDOMDOMRequest getNetworks(); | |
/** | |
+ * Manually selects the passed in network, overriding the radio's current | |
+ * selection. | |
+ * | |
+ * If successful, the request's onsuccess will be called. | |
+ * Note: If the network was actually changed by this request, | |
+ * the 'voicechange' and 'datachange' events will also be fired. | |
+ * | |
+ * Otherwise, the request's onerror will be called, and the request's error | |
+ * will be either 'RadioNotAvailable', 'RequestNotSupported', | |
+ * 'IllegalSIMorME', or 'GenericFailure' | |
+ */ | |
+ nsIDOMDOMRequest selectNetwork(in nsIDOMMozMobileNetworkInfo network); | |
+ | |
+ /** | |
+ * Tell the radio to automatically select a network. | |
+ * | |
+ * If successful, the request's onsuccess will be called. | |
+ * Note: If the network was actually changed by this request, the | |
+ * 'voicechange' and 'datachange' events will also be fired. | |
+ * | |
+ * Otherwise, the request's onerror will be called, and the request's error | |
+ * will be either 'RadioNotAvailable', 'RequestNotSupported', | |
+ * 'IllegalSIMorME', or 'GenericFailure' | |
+ */ | |
+ nsIDOMDOMRequest selectNetworkAutomatically(); | |
+ | |
+ /** | |
* Find out about the status of an ICC lock (e.g. the PIN lock). | |
* | |
* @param lockType | |
diff --git a/dom/network/interfaces/nsIMobileConnectionProvider.idl b/dom/network/interfaces/nsIMobileConnectionProvider.idl | |
index 7458052..91d694f 100644 | |
--- a/dom/network/interfaces/nsIMobileConnectionProvider.idl | |
+++ b/dom/network/interfaces/nsIMobileConnectionProvider.idl | |
@@ -5,6 +5,7 @@ | |
#include "nsISupports.idl" | |
interface nsIDOMMozMobileConnectionInfo; | |
+interface nsIDOMMozMobileNetworkInfo; | |
interface nsIDOMDOMRequest; | |
interface nsIDOMWindow; | |
@@ -18,8 +19,12 @@ interface nsIMobileConnectionProvider : nsISupports | |
readonly attribute DOMString cardState; | |
readonly attribute nsIDOMMozMobileConnectionInfo voiceConnectionInfo; | |
readonly attribute nsIDOMMozMobileConnectionInfo dataConnectionInfo; | |
+ readonly attribute DOMString networkSelectionMode; | |
nsIDOMDOMRequest getNetworks(in nsIDOMWindow window); | |
+ nsIDOMDOMRequest selectNetwork(in nsIDOMWindow window, in nsIDOMMozMobileNetworkInfo network); | |
+ nsIDOMDOMRequest selectNetworkAutomatically(in nsIDOMWindow window); | |
+ | |
nsIDOMDOMRequest getCardLock(in nsIDOMWindow window, in DOMString lockType); | |
nsIDOMDOMRequest unlockCardLock(in nsIDOMWindow window, in jsval info); | |
nsIDOMDOMRequest setCardLock(in nsIDOMWindow window, in jsval info); | |
diff --git a/dom/network/src/MobileConnection.cpp b/dom/network/src/MobileConnection.cpp | |
index b2407e4..803a67e 100644 | |
--- a/dom/network/src/MobileConnection.cpp | |
+++ b/dom/network/src/MobileConnection.cpp | |
@@ -171,6 +171,16 @@ MobileConnection::GetData(nsIDOMMozMobileConnectionInfo** data) | |
} | |
NS_IMETHODIMP | |
+MobileConnection::GetNetworkSelectionMode(nsAString& networkSelectionMode) | |
+{ | |
+ if (!mProvider) { | |
+ networkSelectionMode.SetIsVoid(true); | |
+ return NS_OK; | |
+ } | |
+ return mProvider->GetNetworkSelectionMode(networkSelectionMode); | |
+} | |
+ | |
+NS_IMETHODIMP | |
MobileConnection::GetNetworks(nsIDOMDOMRequest** request) | |
{ | |
*request = nsnull; | |
@@ -183,6 +193,30 @@ MobileConnection::GetNetworks(nsIDOMDOMRequest** request) | |
} | |
NS_IMETHODIMP | |
+MobileConnection::SelectNetwork(nsIDOMMozMobileNetworkInfo* network, nsIDOMDOMRequest** request) | |
+{ | |
+ *request = nsnull; | |
+ | |
+ if (!mProvider) { | |
+ return NS_ERROR_FAILURE; | |
+ } | |
+ | |
+ return mProvider->SelectNetwork(GetOwner(), network, request); | |
+} | |
+ | |
+NS_IMETHODIMP | |
+MobileConnection::SelectNetworkAutomatically(nsIDOMDOMRequest** request) | |
+{ | |
+ *request = nsnull; | |
+ | |
+ if (!mProvider) { | |
+ return NS_ERROR_FAILURE; | |
+ } | |
+ | |
+ return mProvider->SelectNetworkAutomatically(GetOwner(), request); | |
+} | |
+ | |
+NS_IMETHODIMP | |
MobileConnection::GetCardLock(const nsAString& aLockType, nsIDOMDOMRequest** aDomRequest) | |
{ | |
*aDomRequest = nsnull; | |
diff --git a/dom/network/tests/marionette/test_mobile_networks.js b/dom/network/tests/marionette/test_mobile_networks.js | |
index c44cc91..520c640 100644 | |
--- a/dom/network/tests/marionette/test_mobile_networks.js | |
+++ b/dom/network/tests/marionette/test_mobile_networks.js | |
@@ -3,7 +3,7 @@ | |
* You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
// getNetworks() can take some time.. | |
-MARIONETTE_TIMEOUT = 30000; | |
+MARIONETTE_TIMEOUT = 60000; | |
const WHITELIST_PREF = "dom.mobileconnection.whitelist"; | |
let uriPrePath = window.location.protocol + "//" + window.location.host; | |
@@ -13,6 +13,11 @@ let connection = navigator.mozMobileConnection; | |
ok(connection instanceof MozMobileConnection, | |
"connection is instanceof " + connection.constructor); | |
+is(connection.networkSelectionMode, "automatic"); | |
+ | |
+let androidNetwork = null; | |
+let telkilaNetwork = null; | |
+ | |
function isAndroidNetwork(network) { | |
is(network.longName, "Android"); | |
is(network.shortName, "Android"); | |
@@ -20,6 +25,13 @@ function isAndroidNetwork(network) { | |
is(network.mnc, 260); | |
} | |
+function isTelkilaNetwork(network) { | |
+ is(network.longName, "TelKila"); | |
+ is(network.shortName, "TelKila"); | |
+ is(network.mcc, 310); | |
+ is(network.mnc, 295); | |
+} | |
+ | |
function testConnectionInfo() { | |
let voice = connection.voice; | |
is(voice.connected, true); | |
@@ -28,7 +40,7 @@ function testConnectionInfo() { | |
isAndroidNetwork(voice.network); | |
let data = connection.data; | |
- // TODO Bug 762959: enable these checks when data state updates have been implemented | |
+ // TODO Bug 762959: enable these checks when data state updates are implemented | |
// is(data.connected, true); | |
// is(data.emergencyCallsOnly, false); | |
// is(data.roaming, false); | |
@@ -40,11 +52,11 @@ function testConnectionInfo() { | |
function testGetNetworks() { | |
let request = connection.getNetworks(); | |
ok(request instanceof DOMRequest, | |
- "request is instanceof " + request.constructor); | |
+ "request is instanceof " + request.constructor); | |
request.onerror = function() { | |
ok(false, request.error); | |
- cleanUp(); | |
+ setTimeout(testSelectNetwork, 0); | |
}; | |
request.onsuccess = function() { | |
@@ -56,16 +68,165 @@ function testGetNetworks() { | |
// {"longName":"TelKila","shortName":"TelKila","mcc":310,"mnc":295,"state":"available"} | |
is(networks.length, 2); | |
- let network1 = networks[0]; | |
+ let network1 = androidNetwork = networks[0]; | |
isAndroidNetwork(network1); | |
is(network1.state, "available"); | |
- let network2 = networks[1]; | |
- is(network2.longName, "TelKila"); | |
- is(network2.shortName, "TelKila"); | |
- is(network2.mcc, 310); | |
- is(network2.mnc, 295); | |
+ let network2 = telkilaNetwork = networks[1]; | |
+ isTelkilaNetwork(network2); | |
is(network2.state, "available"); | |
+ | |
+ setTimeout(testSelectNetwork, 0); | |
+ }; | |
+} | |
+ | |
+function testSelectNetwork() { | |
+ let request = connection.selectNetwork(telkilaNetwork); | |
+ ok(request instanceof DOMRequest, | |
+ "request instanceof " + request.constructor); | |
+ | |
+ connection.addEventListener("voicechange", function voiceChange() { | |
+ connection.removeEventListener("voicechange", voiceChange); | |
+ | |
+ isTelkilaNetwork(connection.voice.network); | |
+ setTimeout(testSelectNetworkAutomatically, 0); | |
+ }); | |
+ | |
+ request.onsuccess = function() { | |
+ is(connection.networkSelectionMode, "manual", | |
+ "selectNetwork sets mode to: " + connection.networkSelectionMode); | |
+ }; | |
+ | |
+ request.onerror = function() { | |
+ ok(false, request.error); | |
+ setTimeout(testSelectNetworkAutomatically, 0); | |
+ }; | |
+} | |
+ | |
+function testSelectNetworkAutomatically() { | |
+ let request = connection.selectNetworkAutomatically(); | |
+ ok(request instanceof DOMRequest, | |
+ "request instanceof " + request.constructor); | |
+ | |
+ connection.addEventListener("voicechange", function voiceChange() { | |
+ connection.removeEventListener("voicechange", voiceChange); | |
+ | |
+ isAndroidNetwork(connection.voice.network); | |
+ setTimeout(testSelectNetworkErrors, 0); | |
+ }); | |
+ | |
+ request.onsuccess = function() { | |
+ is(connection.networkSelectionMode, "automatic", | |
+ "selectNetworkAutomatically sets mode to: " + | |
+ connection.networkSelectionMode); | |
+ }; | |
+ | |
+ request.onerror = function() { | |
+ ok(false, request.error); | |
+ setTimeout(testSelectNetworkErrors, 0); | |
+ }; | |
+} | |
+ | |
+function throwsException(fn) { | |
+ try { | |
+ fn(); | |
+ ok(false, "function did not throw an exception: " + fn); | |
+ } catch (e) { | |
+ ok(true, "function succesfully caught exception: " + e); | |
+ } | |
+} | |
+ | |
+function testSelectNetworkErrors() { | |
+ throwsException(function() { | |
+ connection.selectNetwork(null); | |
+ }); | |
+ | |
+ throwsException(function() { | |
+ connection.selectNetwork({}); | |
+ }); | |
+ | |
+ connection.addEventListener("voicechange", function voiceChange() { | |
+ connection.removeEventListener("voicechange", voiceChange); | |
+ setTimeout(testSelectExistingNetworkManual, 0); | |
+ }); | |
+ | |
+ let request1 = connection.selectNetwork(telkilaNetwork); | |
+ request1.onerror = function() { | |
+ ok(false, request.error); | |
+ setTimeout(testSelectExistingNetworkManual, 0); | |
+ }; | |
+ | |
+ // attempt to selectNetwork while one request has already been sent | |
+ throwsException(function() { | |
+ connection.selectNetwork(androidNetwork); | |
+ }); | |
+} | |
+ | |
+function testSelectExistingNetworkManual() { | |
+ // When the current network is selected again, the DOMRequest's onsuccess | |
+ // should be called, but the network shouldn't actually change | |
+ | |
+ // Telkila should be the currently selected network | |
+ log("Selecting TelKila (should already be selected"); | |
+ let request = connection.selectNetwork(telkilaNetwork); | |
+ | |
+ let voiceChanged = false; | |
+ connection.addEventListener("voicechange", function voiceChange() { | |
+ connection.removeEventListener("voicechange", voiceChange); | |
+ voiceChanged = true; | |
+ }); | |
+ | |
+ function nextTest() { | |
+ // Switch back to automatic selection to setup the next test | |
+ let autoRequest = connection.selectNetworkAutomatically(); | |
+ autoRequest.onsuccess = function() { | |
+ setTimeout(testSelectExistingNetworkAuto, 0); | |
+ }; | |
+ autoRequest.onerror = function() { | |
+ ok(false, autoRequest.error); | |
+ cleanUp(); | |
+ }; | |
+ } | |
+ | |
+ request.onsuccess = function() { | |
+ // Give the voicechange event another opportunity to fire | |
+ setTimeout(function() { | |
+ is(voiceChanged, false, | |
+ "voiceNetwork changed while manually selecting Telkila network? " + | |
+ voiceChanged); | |
+ nextTest(); | |
+ }, 0); | |
+ }; | |
+ | |
+ request.onerror = function() { | |
+ ok(false, request.error); | |
+ nextTest(); | |
+ }; | |
+} | |
+ | |
+function testSelectExistingNetworkAuto() { | |
+ // Now try the same thing but using automatic selection | |
+ log("Selecting automatically (should already be auto)"); | |
+ let request = connection.selectNetworkAutomatically(); | |
+ | |
+ let voiceChanged = false; | |
+ connection.addEventListener("voicechange", function voiceChange() { | |
+ connection.removeEventListener("voicechange", voiceChange); | |
+ voiceChanged = true; | |
+ }); | |
+ | |
+ request.onsuccess = function() { | |
+ // Give the voicechange event another opportunity to fire | |
+ setTimeout(function() { | |
+ is(voiceChanged, false, | |
+ "voiceNetwork changed while automatically selecting network? " + | |
+ voiceChanged); | |
+ cleanUp(); | |
+ }, 0); | |
+ }; | |
+ | |
+ request.onerror = function() { | |
+ ok(false, request.error); | |
cleanUp(); | |
}; | |
} | |
diff --git a/dom/system/gonk/RILContentHelper.js b/dom/system/gonk/RILContentHelper.js | |
index fb1298a..996ab14 100644 | |
--- a/dom/system/gonk/RILContentHelper.js | |
+++ b/dom/system/gonk/RILContentHelper.js | |
@@ -13,7 +13,8 @@ Cu.import("resource://gre/modules/DOMRequestHelper.jsm"); | |
var RIL = {}; | |
Cu.import("resource://gre/modules/ril_consts.js", RIL); | |
-const DEBUG = false; // set to true to see debug messages | |
+// set to true to in ril_consts.js to see debug messages | |
+const DEBUG = RIL.DEBUG_CONTENT_HELPER; | |
const RILCONTENTHELPER_CID = | |
Components.ID("{472816e1-1fd6-4405-996c-806f9ea68174}"); | |
@@ -28,6 +29,9 @@ const RIL_IPC_MSG_NAMES = [ | |
"RIL:DataInfoChanged", | |
"RIL:EnumerateCalls", | |
"RIL:GetAvailableNetworks", | |
+ "RIL:NetworkSelectionModeChanged", | |
+ "RIL:SelectNetwork", | |
+ "RIL:SelectNetworkAuto", | |
"RIL:CallStateChanged", | |
"RIL:CallError", | |
"RIL:GetCardLock:Return:OK", | |
@@ -156,6 +160,13 @@ RILContentHelper.prototype = { | |
cardState: RIL.GECKO_CARDSTATE_UNAVAILABLE, | |
voiceConnectionInfo: null, | |
dataConnectionInfo: null, | |
+ networkSelectionMode: RIL.GECKO_NETWORK_SELECTION_UNKNOWN, | |
+ | |
+ /** | |
+ * The network that is currently trying to be selected (or "automatic"). | |
+ * This helps ensure that only one network is selected at a time. | |
+ */ | |
+ _selectingNetwork: null, | |
getNetworks: function getNetworks(window) { | |
if (window == null) { | |
@@ -170,6 +181,79 @@ RILContentHelper.prototype = { | |
return request; | |
}, | |
+ selectNetwork: function selectNetwork(window, network) { | |
+ if (window == null) { | |
+ throw Components.Exception("Can't get window object", | |
+ Cr.NS_ERROR_UNEXPECTED); | |
+ } | |
+ | |
+ if (this._selectingNetwork) { | |
+ throw new Error("Already selecting a network: " + this._selectingNetwork); | |
+ } | |
+ | |
+ if (!network) { | |
+ throw new Error("Invalid network provided: " + network); | |
+ } | |
+ | |
+ let mnc = network.mnc; | |
+ if (!mnc) { | |
+ throw new Error("Invalid network MNC: " + mnc); | |
+ } | |
+ | |
+ let mcc = network.mcc; | |
+ if (!mcc) { | |
+ throw new Error("Invalid network MCC: " + mcc); | |
+ } | |
+ | |
+ let request = Services.DOMRequest.createRequest(window); | |
+ let requestId = this.getRequestId(request); | |
+ | |
+ if (this.networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_MANUAL | |
+ && this.voiceConnectionInfo.network === network) { | |
+ | |
+ // Already manually selected this network, so schedule | |
+ // onsuccess to be fired on the next tick | |
+ this.dispatchFireRequestSuccess(requestId, null); | |
+ return request; | |
+ } | |
+ | |
+ this._selectingNetwork = network; | |
+ | |
+ cpmm.sendAsyncMessage("RIL:SelectNetwork", { | |
+ requestId: requestId, | |
+ mnc: mnc, | |
+ mcc: mcc | |
+ }); | |
+ | |
+ return request; | |
+ }, | |
+ | |
+ selectNetworkAutomatically: function selectNetworkAutomatically(window) { | |
+ | |
+ if (window == null) { | |
+ throw Components.Exception("Can't get window object", | |
+ Cr.NS_ERROR_UNEXPECTED); | |
+ } | |
+ | |
+ if (this._selectingNetwork) { | |
+ throw new Error("Already selecting a network: " + this._selectingNetwork); | |
+ } | |
+ | |
+ let request = Services.DOMRequest.createRequest(window); | |
+ let requestId = this.getRequestId(request); | |
+ | |
+ if (this.networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_AUTOMATIC) { | |
+ // Already using automatic selection mode, so schedule | |
+ // onsuccess to be be fired on the next tick | |
+ this.dispatchFireRequestSuccess(requestId, null); | |
+ return request; | |
+ } | |
+ | |
+ this._selectingNetwork = "automatic"; | |
+ cpmm.sendAsyncMessage("RIL:SelectNetworkAuto", requestId); | |
+ return request; | |
+ }, | |
+ | |
getCardLock: function getCardLock(window, lockType) { | |
if (window == null) { | |
throw Components.Exception("Can't get window object", | |
@@ -330,28 +414,39 @@ RILContentHelper.prototype = { | |
let request = this.takeRequest(requestId); | |
if (!request) { | |
if (DEBUG) { | |
- debug("not firing success for id: " + requestId + ", result: " + JSON.stringify(result)); | |
+ debug("not firing success for id: " + requestId + | |
+ ", result: " + JSON.stringify(result)); | |
} | |
return; | |
} | |
if (DEBUG) { | |
- debug("fire request success, id: " + requestId + ", result: " + JSON.stringify(result)); | |
+ debug("fire request success, id: " + requestId + | |
+ ", result: " + JSON.stringify(result)); | |
} | |
Services.DOMRequest.fireSuccess(request, result); | |
}, | |
+ dispatchFireRequestSuccess: function dispatchFireRequestSuccess(requestId, result) { | |
+ let currentThread = Services.tm.currentThread; | |
+ | |
+ currentThread.dispatch(this.fireRequestSuccess.bind(this, requestId, result), | |
+ Ci.nsIThread.DISPATCH_NORMAL); | |
+ }, | |
+ | |
fireRequestError: function fireRequestError(requestId, error) { | |
let request = this.takeRequest(requestId); | |
if (!request) { | |
if (DEBUG) { | |
- debug("not firing error for id: " + requestId + ", error: " + JSON.stringify(error)); | |
+ debug("not firing error for id: " + requestId + | |
+ ", error: " + JSON.stringify(error)); | |
} | |
return; | |
} | |
if (DEBUG) { | |
- debug("fire request error, id: " + requestId + ", result: " + JSON.stringify(error)); | |
+ debug("fire request error, id: " + requestId + | |
+ ", result: " + JSON.stringify(error)); | |
} | |
Services.DOMRequest.fireError(request, error); | |
}, | |
@@ -380,6 +475,17 @@ RILContentHelper.prototype = { | |
case "RIL:GetAvailableNetworks": | |
this.handleGetAvailableNetworks(msg.json); | |
break; | |
+ case "RIL:NetworkSelectionModeChanged": | |
+ this.networkSelectionMode = msg.json.mode; | |
+ break; | |
+ case "RIL:SelectNetwork": | |
+ this.handleSelectNetwork(msg.json, | |
+ RIL.GECKO_NETWORK_SELECTION_MANUAL); | |
+ break; | |
+ case "RIL:SelectNetworkAuto": | |
+ this.handleSelectNetwork(msg.json, | |
+ RIL.GECKO_NETWORK_SELECTION_AUTOMATIC); | |
+ break; | |
case "RIL:CallStateChanged": | |
this._deliverTelephonyCallback("callStateChanged", | |
[msg.json.callIndex, msg.json.state, | |
@@ -473,6 +579,17 @@ RILContentHelper.prototype = { | |
Services.DOMRequest.fireSuccess(request, networks); | |
}, | |
+ handleSelectNetwork: function handleSelectNetwork(message, mode) { | |
+ this._selectingNetwork = null; | |
+ this.networkSelectionMode = mode; | |
+ | |
+ if (message.error) { | |
+ this.fireRequestError(message.requestId, message.error); | |
+ } else { | |
+ this.fireRequestSuccess(message.requestId, null); | |
+ } | |
+ }, | |
+ | |
_deliverTelephonyCallback: function _deliverTelephonyCallback(name, args) { | |
if (!this._telephonyCallbacks) { | |
return; | |
diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js | |
index 403c4f5..6022603 100644 | |
--- a/dom/system/gonk/RadioInterfaceLayer.js | |
+++ b/dom/system/gonk/RadioInterfaceLayer.js | |
@@ -12,7 +12,8 @@ Cu.import("resource://gre/modules/Services.jsm"); | |
var RIL = {}; | |
Cu.import("resource://gre/modules/ril_consts.js", RIL); | |
-const DEBUG = false; // set to true to see debug messages | |
+// set to true in ril_consts.js to see debug messages | |
+const DEBUG = RIL.DEBUG_RIL; | |
const RADIOINTERFACELAYER_CID = | |
Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}"); | |
@@ -45,6 +46,8 @@ const RIL_IPC_MSG_NAMES = [ | |
"RIL:HoldCall", | |
"RIL:ResumeCall", | |
"RIL:GetAvailableNetworks", | |
+ "RIL:SelectNetwork", | |
+ "RIL:SelectNetworkAuto", | |
"RIL:GetCardLock", | |
"RIL:UnlockCardLock", | |
"RIL:SetCardLock", | |
@@ -249,6 +252,11 @@ RadioInterfaceLayer.prototype = { | |
case "RIL:GetAvailableNetworks": | |
this.getAvailableNetworks(msg.json); | |
break; | |
+ case "RIL:SelectNetwork": | |
+ this.selectNetwork(msg.json); | |
+ break; | |
+ case "RIL:SelectNetworkAuto": | |
+ this.selectNetworkAuto(msg.json); | |
case "RIL:GetCardLock": | |
this.getCardLock(msg.json); | |
break; | |
@@ -302,6 +310,18 @@ RadioInterfaceLayer.prototype = { | |
case "getAvailableNetworks": | |
this.handleGetAvailableNetworks(message); | |
break; | |
+ case "selectNetwork": | |
+ this.handleSelectNetwork(message); | |
+ break; | |
+ case "selectNetworkAuto": | |
+ this.handleSelectNetworkAuto(message); | |
+ break; | |
+ case "networkinfochanged": | |
+ this.updateNetworkInfo(message); | |
+ break; | |
+ case "networkselectionmodechange": | |
+ this.updateNetworkSelectionMode(message); | |
+ break; | |
case "voiceregistrationstatechange": | |
this.updateVoiceConnection(message); | |
break; | |
@@ -398,10 +418,64 @@ RadioInterfaceLayer.prototype = { | |
} | |
}, | |
+ updateNetworkInfo: function updateNetworkInfo(message) { | |
+ let voiceMessage = message[RIL.NETWORK_INFO_VOICE_REGISTRATION_STATE]; | |
+ let dataMessage = message[RIL.NETWORK_INFO_DATA_REGISTRATION_STATE]; | |
+ let operatorMessage = message[RIL.NETWORK_INFO_OPERATOR]; | |
+ let selectionMessage = message[RIL.NETWORK_INFO_NETWORK_SELECTION_MODE]; | |
+ | |
+ // Batch the *InfoChanged messages together | |
+ let voiceInfoChanged = false; | |
+ if (voiceMessage) { | |
+ voiceMessage.batch = true; | |
+ voiceInfoChanged = this.updateVoiceConnection(voiceMessage); | |
+ } | |
+ | |
+ let dataInfoChanged = false; | |
+ if (dataMessage) { | |
+ dataMessage.batch = true; | |
+ dataInfoChanged = this.updateDataConnection(dataMessage); | |
+ } | |
+ | |
+ let voice = this.radioState.voice; | |
+ let data = this.radioState.data; | |
+ if (operatorMessage) { | |
+ if (this.networkChanged(operatorMessage, voice.network)) { | |
+ voiceInfoChanged = true; | |
+ voice.network = operatorMessage; | |
+ } | |
+ | |
+ if (this.networkChanged(operatorMessage, data.network)) { | |
+ dataInfoChanged = true; | |
+ data.network = operatorMessage; | |
+ } | |
+ } | |
+ | |
+ if (voiceInfoChanged) { | |
+ ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voice); | |
+ } | |
+ if (dataInfoChanged) { | |
+ ppmm.sendAsyncMessage("RIL:DataInfoChanged", data); | |
+ } | |
+ | |
+ if (selectionMessage) { | |
+ this.updateNetworkSelectionMode(selectionMessage); | |
+ } | |
+ }, | |
+ | |
+ /** | |
+ * Sends the RIL:VoiceInfoChanged message when the voice | |
+ * connection's state has changed. | |
+ * | |
+ * @param state The new voice connection state. When state.batch is true, | |
+ * the RIL:VoiceInfoChanged message will not be sent. | |
+ * @return Whether or not this.radioState.voice was updated | |
+ */ | |
updateVoiceConnection: function updateVoiceConnection(state) { | |
let voiceInfo = this.radioState.voice; | |
+ let regState = state.regState; | |
voiceInfo.type = "gsm"; //TODO see bug 726098. | |
- if (!state || state.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) { | |
+ if (!state || regState == RIL.NETWORK_CREG_STATE_UNKNOWN) { | |
voiceInfo.connected = false; | |
voiceInfo.emergencyCallsOnly = false; | |
voiceInfo.roaming = false; | |
@@ -413,17 +487,30 @@ RadioInterfaceLayer.prototype = { | |
voiceInfo); | |
return; | |
} | |
- voiceInfo.emergencyCallsOnly = state.emergencyCallsOnly; | |
- voiceInfo.connected = | |
- (state.regState == RIL.NETWORK_CREG_STATE_REGISTERED_HOME) || | |
- (state.regState == RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING); | |
- voiceInfo.roaming = | |
- voiceInfo.connected && | |
- (state == RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING); | |
- voiceInfo.type = | |
- RIL.GECKO_RADIO_TECH[state.radioTech] || null; | |
- ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo); | |
+ let isRoaming = regState == RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING; | |
+ let isHome = regState == RIL.NETWORK_CREG_STATE_REGISTERED_HOME; | |
+ let isConnected = isRoaming || isHome; | |
+ let radioTech = RIL.GECKO_RADIO_TECH[state.radioTech] || null; | |
+ | |
+ // Ensure that we check for changes before sending the message | |
+ if (voiceInfo.emergencyCallsOnly != state.emergencyCallsOnly || | |
+ voiceInfo.connected != isConnected || | |
+ voiceInfo.roaming != isRoaming || | |
+ voiceInfo.type != radioTech) { | |
+ | |
+ voiceInfo.emergencyCallsOnly = state.emergencyCallsOnly; | |
+ voiceInfo.connected = isConnected; | |
+ voiceInfo.roaming = isRoaming; | |
+ voiceInfo.type = radioTech; | |
+ | |
+ // When batch is true, hold off on firing VoiceInfoChanged events | |
+ if (!state.batch) { | |
+ ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo); | |
+ } | |
+ return true; | |
+ } | |
+ return false; | |
}, | |
_isDataEnabled: function _isDataEnabled() { | |
@@ -444,7 +531,7 @@ RadioInterfaceLayer.prototype = { | |
updateDataConnection: function updateDataConnection(state) { | |
if (!this._isDataEnabled()) { | |
- return; | |
+ return false; | |
} | |
let isRegistered = | |
@@ -462,6 +549,7 @@ RadioInterfaceLayer.prototype = { | |
//TODO need to keep track of some of the state information, and then | |
// notify the content when state changes (connected, technology | |
// changes, etc.). This should be done in RILNetworkInterface. | |
+ return false; | |
}, | |
handleSignalStrengthChange: function handleSignalStrengthChange(message) { | |
@@ -614,6 +702,30 @@ RadioInterfaceLayer.prototype = { | |
}, | |
/** | |
+ * Update network selection mode | |
+ */ | |
+ updateNetworkSelectionMode: function updateNetworkSelectionMode(message) { | |
+ debug("updateNetworkSelectionMode: " + JSON.stringify(message)); | |
+ ppmm.sendAsyncMessage("RIL:NetworkSelectionModeChanged", message); | |
+ }, | |
+ | |
+ /** | |
+ * Handle "manual" network selection request. | |
+ */ | |
+ handleSelectNetwork: function handleSelectNetwork(message) { | |
+ debug("handleSelectNetwork: " + JSON.stringify(message)); | |
+ ppmm.sendAsyncMessage("RIL:SelectNetwork", message); | |
+ }, | |
+ | |
+ /** | |
+ * Handle "automatic" network selection request. | |
+ */ | |
+ handleSelectNetworkAuto: function handleSelectNetworkAuto(message) { | |
+ debug("handleSelectNetworkAuto: " + JSON.stringify(message)); | |
+ ppmm.sendAsyncMessage("RIL:SelectNetworkAuto", message); | |
+ }, | |
+ | |
+ /** | |
* Handle call error. | |
*/ | |
handleCallError: function handleCallError(message) { | |
@@ -951,6 +1063,16 @@ RadioInterfaceLayer.prototype = { | |
this.worker.postMessage(message); | |
}, | |
+ selectNetworkAuto: function selectNetworkAuto(requestId) { | |
+ this.worker.postMessage({type: "selectNetworkAuto", requestId: requestId}); | |
+ }, | |
+ | |
+ selectNetwork: function selectNetwork(message) { | |
+ message.type = "selectNetwork"; | |
+ this.worker.postMessage(message); | |
+ }, | |
+ | |
+ | |
get microphoneMuted() { | |
return gAudioManager.microphoneMuted; | |
}, | |
diff --git a/dom/system/gonk/ril_consts.js b/dom/system/gonk/ril_consts.js | |
index f406fe8..128324f 100644 | |
--- a/dom/system/gonk/ril_consts.js | |
+++ b/dom/system/gonk/ril_consts.js | |
@@ -2,6 +2,14 @@ | |
* 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/. */ | |
+// Set to true to debug all RIL layers | |
+const DEBUG_ALL = false; | |
+ | |
+// Set individually to debug specific layers | |
+const DEBUG_WORKER = false || DEBUG_ALL; | |
+const DEBUG_CONTENT_HELPER = false || DEBUG_ALL; | |
+const DEBUG_RIL = false || DEBUG_ALL; | |
+ | |
const REQUEST_GET_SIM_STATUS = 1; | |
const REQUEST_ENTER_SIM_PIN = 2; | |
const REQUEST_ENTER_SIM_PUK = 3; | |
@@ -211,12 +219,14 @@ const GECKO_ERROR_SUCCESS = null; | |
const GECKO_ERROR_RADIO_NOT_AVAILABLE = "RadioNotAvailable"; | |
const GECKO_ERROR_GENERIC_FAILURE = "GenericFailure"; | |
const GECKO_ERROR_REQUEST_NOT_SUPPORTED = "RequestNotSupported"; | |
+const GECKO_ERROR_ILLEGAL_SIM_OR_ME = "IllegalSIMorME"; | |
const RIL_ERROR_TO_GECKO_ERROR = {}; | |
RIL_ERROR_TO_GECKO_ERROR[ERROR_SUCCESS] = GECKO_ERROR_SUCCESS; | |
RIL_ERROR_TO_GECKO_ERROR[ERROR_RADIO_NOT_AVAILABLE] = GECKO_ERROR_RADIO_NOT_AVAILABLE; | |
RIL_ERROR_TO_GECKO_ERROR[ERROR_GENERIC_FAILURE] = GECKO_ERROR_GENERIC_FAILURE; | |
RIL_ERROR_TO_GECKO_ERROR[ERROR_REQUEST_NOT_SUPPORTED] = GECKO_ERROR_REQUEST_NOT_SUPPORTED; | |
+RIL_ERROR_TO_GECKO_ERROR[ERROR_ILLEGAL_SIM_OR_ME] = GECKO_ERROR_ILLEGAL_SIM_OR_ME; | |
// 3GPP 23.040 clause 9.2.3.6 TP-Message-Reference(TP-MR): | |
// The number of times the MS automatically repeats the SMS-SUBMIT shall be in | |
@@ -301,6 +311,15 @@ const NETWORK_STATE_FORBIDDEN = "forbidden"; | |
const NETWORK_SELECTION_MODE_AUTOMATIC = 0; | |
const NETWORK_SELECTION_MODE_MANUAL = 1; | |
+const NETWORK_INFO_VOICE_REGISTRATION_STATE = "voiceRegistrationState"; | |
+const NETWORK_INFO_DATA_REGISTRATION_STATE = "dataRegistrationState"; | |
+const NETWORK_INFO_OPERATOR = "operator"; | |
+const NETWORK_INFO_NETWORK_SELECTION_MODE = "networkSelectionMode"; | |
+const NETWORK_INFO_MESSAGES = [NETWORK_INFO_VOICE_REGISTRATION_STATE, | |
+ NETWORK_INFO_DATA_REGISTRATION_STATE, | |
+ NETWORK_INFO_OPERATOR, | |
+ NETWORK_INFO_NETWORK_SELECTION_MODE]; | |
+ | |
const PREFERRED_NETWORK_TYPE_GSM_WCDMA = 0; | |
const PREFERRED_NETWORK_TYPE_GSM_ONLY = 1; | |
const PREFERRED_NETWORK_TYPE_WCDMA = 2; | |
@@ -1394,6 +1413,10 @@ const GECKO_CARDSTATE_NETWORK_LOCKED = "network_locked"; | |
const GECKO_CARDSTATE_NOT_READY = null; | |
const GECKO_CARDSTATE_READY = "ready"; | |
+const GECKO_NETWORK_SELECTION_UNKNOWN = null; | |
+const GECKO_NETWORK_SELECTION_AUTOMATIC = "automatic"; | |
+const GECKO_NETWORK_SELECTION_MANUAL = "manual"; | |
+ | |
const GECKO_CALL_ERROR_BAD_NUMBER = "BadNumberError"; | |
const GECKO_CALL_ERROR_NORMAL_CALL_CLEARING = "NormalCallClearingError"; | |
const GECKO_CALL_ERROR_BUSY = "BusyError"; | |
diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js | |
index 5b6dc97..4a275d7 100644 | |
--- a/dom/system/gonk/ril_worker.js | |
+++ b/dom/system/gonk/ril_worker.js | |
@@ -29,10 +29,8 @@ | |
importScripts("ril_consts.js", "systemlibs.js"); | |
-// We leave this as 'undefined' instead of setting it to 'false'. That | |
-// way an outer scope can define it to 'true' (e.g. for testing purposes) | |
-// without us overriding that here. | |
-let DEBUG; | |
+// set to true in ril_consts.js to see debug messages | |
+let DEBUG = DEBUG_WORKER; | |
const INT32_MAX = 2147483647; | |
const UINT8_SIZE = 1; | |
@@ -520,6 +518,7 @@ let Buf = { | |
*/ | |
newParcel: function newParcel(type, options) { | |
if (DEBUG) debug("New outgoing parcel of type " + type); | |
+ | |
// We're going to leave room for the parcel size at the beginning. | |
this.outgoingIndex = PARCEL_SIZE_SIZE; | |
this.writeUint32(type); | |
@@ -617,11 +616,6 @@ let RIL = { | |
basebandVersion: null, | |
/** | |
- * Network selection mode. 0 for automatic, 1 for manual selection. | |
- */ | |
- networkSelectionMode: null, | |
- | |
- /** | |
* Valid calls. | |
*/ | |
currentCalls: {}, | |
@@ -649,6 +643,11 @@ let RIL = { | |
_pendingSentSmsMap: {}, | |
/** | |
+ * Whether or not the multiple requests in requestNetworkInfo() are currently being processed | |
+ */ | |
+ _processingNetworkInfo: false, | |
+ | |
+ /** | |
* Mute or unmute the radio. | |
*/ | |
_muted: true, | |
@@ -1360,14 +1359,6 @@ let RIL = { | |
Buf.simpleRequest(REQUEST_OPERATOR); | |
}, | |
- getNetworkSelectionMode: function getNetworkSelectionMode() { | |
- Buf.simpleRequest(REQUEST_QUERY_NETWORK_SELECTION_MODE); | |
- }, | |
- | |
- setNetworkSelectionAutomatic: function setNetworkSelectionAutomatic() { | |
- Buf.simpleRequest(REQUEST_SET_NETWORK_SELECTION_AUTOMATIC); | |
- }, | |
- | |
/** | |
* Set the preferred network type. | |
* | |
@@ -1384,7 +1375,19 @@ let RIL = { | |
* Request various states about the network. | |
*/ | |
requestNetworkInfo: function requestNetworkInfo() { | |
- if (DEBUG) debug("Requesting phone state"); | |
+ if (this._processingNetworkInfo) { | |
+ if (DEBUG) { | |
+ debug("Already requesting network info: " + | |
+ JSON.stringify(this._pendingNetworkInfo)) | |
+ } | |
+ return; | |
+ } | |
+ | |
+ if (DEBUG) debug("Requesting network info"); | |
+ // This should match the number of parcels sent below | |
+ this._pendingNetworkInfo = {}; | |
+ this._processingNetworkInfo = true; | |
+ | |
this.getVoiceRegistrationState(); | |
this.getDataRegistrationState(); //TODO only GSM | |
this.getOperator(); | |
@@ -1401,6 +1404,36 @@ let RIL = { | |
}, | |
/** | |
+ * Request the radio's network selection mode | |
+ */ | |
+ getNetworkSelectionMode: function getNetworkSelectionMode(options) { | |
+ if (DEBUG) debug("Getting network selection mode"); | |
+ Buf.simpleRequest(REQUEST_QUERY_NETWORK_SELECTION_MODE, options); | |
+ }, | |
+ | |
+ /** | |
+ * Tell the radio to automatically choose a voice/data network | |
+ */ | |
+ selectNetworkAuto: function selectNetworkAuto(options) { | |
+ if (DEBUG) debug("Setting automatic network selection"); | |
+ Buf.simpleRequest(REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, options); | |
+ }, | |
+ | |
+ /** | |
+ * Tell the radio to choose a specific voice/data network | |
+ */ | |
+ selectNetwork: function selectNetwork(options) { | |
+ if (DEBUG) { | |
+ debug("Setting manual network selection: " + options.mcc + options.mnc); | |
+ } | |
+ | |
+ let numeric = String(options.mcc) + options.mnc; | |
+ Buf.newParcel(REQUEST_SET_NETWORK_SELECTION_MANUAL, options); | |
+ Buf.writeString(numeric); | |
+ Buf.sendParcel(); | |
+ }, | |
+ | |
+ /** | |
* Get current calls. | |
*/ | |
getCurrentCalls: function getCurrentCalls() { | |
@@ -1846,9 +1879,6 @@ let RIL = { | |
newCardState = GECKO_CARDSTATE_NETWORK_LOCKED; | |
break; | |
case CARD_APPSTATE_READY: | |
- this.requestNetworkInfo(); | |
- this.getSignalStrength(); | |
- this.fetchICCRecords(); | |
newCardState = GECKO_CARDSTATE_READY; | |
break; | |
case CARD_APPSTATE_UNKNOWN: | |
@@ -1860,6 +1890,12 @@ let RIL = { | |
if (this.cardState == newCardState) { | |
return; | |
} | |
+ | |
+ // This was moved down from CARD_APPSTATE_READY | |
+ this.requestNetworkInfo(); | |
+ this.getSignalStrength(); | |
+ this.fetchICCRecords(); | |
+ | |
this.cardState = newCardState; | |
this.sendDOMMessage({type: "cardstatechange", | |
cardState: this.cardState}); | |
@@ -1976,6 +2012,61 @@ let RIL = { | |
} | |
}, | |
+ // We combine all of the network info messages into one "networkinfochange" | |
+ // message to the RadioInterfaceLayer, so we can avoid sending multiple | |
+ // VoiceInfoChanged events for both operator / voice_data_registration | |
+ _sendNetworkInfoMessage: function _sendNetworkInfoMessage(type, message) { | |
+ if (!this._processingNetworkInfo) { | |
+ // We only combine these messages in the case of the combined request | |
+ // in requestNetworkInfo() | |
+ this.sendDOMMessage(message); | |
+ return; | |
+ } | |
+ | |
+ this._pendingNetworkInfo[type] = message; | |
+ }, | |
+ | |
+ _processNetworkInfoResult: function _processNetworkInfoResult(type) { | |
+ let pending = this._pendingNetworkInfo; | |
+ if (!pending || !this._processingNetworkInfo) { | |
+ return; | |
+ } | |
+ | |
+ // We still need to track states for events that aren't fired | |
+ if (!(type in pending)) { | |
+ pending[type] = null; | |
+ } | |
+ | |
+ // Pending network info is ready to be sent when no more messages | |
+ // are waiting for responses, but the combined payload hasn't been sent. | |
+ for (let i = 0; i < NETWORK_INFO_MESSAGES.length; i++) { | |
+ let message = NETWORK_INFO_MESSAGES[i]; | |
+ if (!(message in pending)) { | |
+ return; | |
+ } | |
+ } | |
+ | |
+ this._pendingNetworkInfo.type = "networkinfochanged"; | |
+ | |
+ // Clean up the dead-weight events | |
+ let keys = Object.keys(pending); | |
+ for (let i = 0; i < keys.length; i++) { | |
+ let key = keys[i]; | |
+ if (!pending[key]) { | |
+ delete pending[key]; | |
+ } | |
+ } | |
+ | |
+ // Send the message on the next tick of the worker's loop, so we give the | |
+ // last message a chance to call _sendNetworkInfoMessage first. | |
+ let self = this; | |
+ setTimeout(function() { | |
+ self.sendDOMMessage(self._pendingNetworkInfo); | |
+ self._processingNetworkInfo = false; | |
+ self._pendingNetworkInfo = null; | |
+ }, 0); | |
+ }, | |
+ | |
_processVoiceRegistrationState: function _processVoiceRegistrationState(state) { | |
this.initRILQuirks(); | |
@@ -2048,7 +2139,7 @@ let RIL = { | |
if (stateChanged) { | |
rs.type = "voiceregistrationstatechange"; | |
- this.sendDOMMessage(rs); | |
+ this._sendNetworkInfoMessage(NETWORK_INFO_VOICE_REGISTRATION_STATE, rs); | |
} | |
}, | |
@@ -2070,7 +2161,7 @@ let RIL = { | |
if (stateChanged) { | |
rs.type = "dataregistrationstatechange"; | |
- this.sendDOMMessage(rs); | |
+ this._sendNetworkInfoMessage(NETWORK_INFO_DATA_REGISTRATION_STATE, rs); | |
} | |
}, | |
@@ -2823,15 +2914,20 @@ RIL[REQUEST_SIGNAL_STRENGTH] = function REQUEST_SIGNAL_STRENGTH(length, options) | |
this.sendDOMMessage(obj); | |
}; | |
RIL[REQUEST_VOICE_REGISTRATION_STATE] = function REQUEST_VOICE_REGISTRATION_STATE(length, options) { | |
+ this._processNetworkInfoResult(NETWORK_INFO_VOICE_REGISTRATION_STATE); | |
+ | |
if (options.rilRequestError) { | |
return; | |
} | |
let state = Buf.readStringList(); | |
if (DEBUG) debug("voice registration state: " + state); | |
+ | |
this._processVoiceRegistrationState(state); | |
}; | |
RIL[REQUEST_DATA_REGISTRATION_STATE] = function REQUEST_DATA_REGISTRATION_STATE(length, options) { | |
+ this._processNetworkInfoResult(NETWORK_INFO_DATA_REGISTRATION_STATE); | |
+ | |
if (options.rilRequestError) { | |
return; | |
} | |
@@ -2840,11 +2936,14 @@ RIL[REQUEST_DATA_REGISTRATION_STATE] = function REQUEST_DATA_REGISTRATION_STATE( | |
this._processDataRegistrationState(state); | |
}; | |
RIL[REQUEST_OPERATOR] = function REQUEST_OPERATOR(length, options) { | |
+ this._processNetworkInfoResult(NETWORK_INFO_OPERATOR); | |
+ | |
if (options.rilRequestError) { | |
return; | |
} | |
let operator = Buf.readStringList(); | |
+ | |
if (DEBUG) debug("Operator data: " + operator); | |
if (operator.length < 3) { | |
if (DEBUG) debug("Expected at least 3 strings for operator."); | |
@@ -2871,7 +2970,7 @@ RIL[REQUEST_OPERATOR] = function REQUEST_OPERATOR(length, options) { | |
debug("Error processing operator tuple: " + e); | |
} | |
- this.sendDOMMessage(this.operator); | |
+ this._sendNetworkInfoMessage(NETWORK_INFO_OPERATOR, this.operator); | |
} | |
}; | |
RIL[REQUEST_RADIO_POWER] = null; | |
@@ -3046,15 +3145,53 @@ RIL[REQUEST_SET_FACILITY_LOCK] = function REQUEST_SET_FACILITY_LOCK(length, opti | |
}; | |
RIL[REQUEST_CHANGE_BARRING_PASSWORD] = null; | |
RIL[REQUEST_QUERY_NETWORK_SELECTION_MODE] = function REQUEST_QUERY_NETWORK_SELECTION_MODE(length, options) { | |
+ this._processNetworkInfoResult(NETWORK_INFO_NETWORK_SELECTION_MODE); | |
+ | |
if (options.rilRequestError) { | |
+ options.error = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]; | |
+ this.sendDOMMessage(options); | |
return; | |
} | |
let mode = Buf.readUint32List(); | |
- this.networkSelectionMode = mode[0]; | |
+ let selectionMode; | |
+ | |
+ switch (mode[0]) { | |
+ case NETWORK_SELECTION_MODE_AUTOMATIC: | |
+ selectionMode = GECKO_NETWORK_SELECTION_AUTOMATIC; | |
+ break; | |
+ case NETWORK_SELECTION_MODE_MANUAL: | |
+ selectionMode = GECKO_NETWORK_SELECTION_MANUAL; | |
+ break; | |
+ default: | |
+ selectionMode = GECKO_NETWORK_SELECTION_UNKNOWN; | |
+ break; | |
+ } | |
+ | |
+ if (this.mode != selectionMode) { | |
+ this.mode = options.mode = selectionMode; | |
+ options.type = "networkselectionmodechange"; | |
+ this._sendNetworkInfoMessage(NETWORK_INFO_NETWORK_SELECTION_MODE, options); | |
+ } | |
+}; | |
+RIL[REQUEST_SET_NETWORK_SELECTION_AUTOMATIC] = function REQUEST_SET_NETWORK_SELECTION_AUTOMATIC(length, options) { | |
+ if (options.rilRequestError) { | |
+ options.error = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]; | |
+ this.sendDOMMessage(options); | |
+ return; | |
+ } | |
+ | |
+ this.sendDOMMessage(options); | |
+}; | |
+RIL[REQUEST_SET_NETWORK_SELECTION_MANUAL] = function REQUEST_SET_NETWORK_SELECTION_MANUAL(length, options) { | |
+ if (options.rilRequestError) { | |
+ options.error = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]; | |
+ this.sendDOMMessage(options); | |
+ return; | |
+ } | |
+ | |
+ this.sendDOMMessage(options); | |
}; | |
-RIL[REQUEST_SET_NETWORK_SELECTION_AUTOMATIC] = null; | |
-RIL[REQUEST_SET_NETWORK_SELECTION_MANUAL] = null; | |
RIL[REQUEST_QUERY_AVAILABLE_NETWORKS] = function REQUEST_QUERY_AVAILABLE_NETWORKS(length, options) { | |
if (options.rilRequestError) { | |
options.error = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment