Bug 782513 - B2G RIL: Support multiple instances of RILNetworkInterface. r=philikon

This commit is contained in:
Shian-Yow Wu 2012-09-26 20:52:21 +08:00
parent a3883315b3
commit 0160c54f69
2 changed files with 73 additions and 30 deletions

View File

@ -28,6 +28,8 @@ const DEBUG = RIL.DEBUG_RIL;
const RADIOINTERFACELAYER_CID =
Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
const RILNETWORKINTERFACE_CID =
Components.ID("{3bdd52a9-3965-4130-b569-0ac5afed045e}");
const nsIAudioManager = Ci.nsIAudioManager;
const nsIRadioInterfaceLayer = Ci.nsIRadioInterfaceLayer;
@ -93,6 +95,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger",
"@mozilla.org/system-message-internal;1",
"nsISystemMessagesInternal");
XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager",
"@mozilla.org/network/manager;1",
"nsINetworkManager");
XPCOMUtils.defineLazyGetter(this, "WAP", function () {
let WAP = {};
Cu.import("resource://gre/modules/WapPushManager.js", WAP);
@ -150,6 +156,10 @@ XPCOMUtils.defineLazyGetter(this, "gAudioManager", function getAudioManager() {
function RadioInterfaceLayer() {
this.dataNetworkInterface = new RILNetworkInterface(this, Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE);
this.mmsNetworkInterface = new RILNetworkInterface(this, Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS);
this.suplNetworkInterface = new RILNetworkInterface(this, Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL);
debug("Starting RIL Worker");
this.worker = new ChromeWorker("resource://gre/modules/ril_worker.js");
this.worker.onerror = this.onerror.bind(this);
@ -619,7 +629,7 @@ RadioInterfaceLayer.prototype = {
dataInfo.type = newInfo.type;
// For the data connection, the `connected` flag indicates whether
// there's an active data call.
dataInfo.connected = RILNetworkInterface.connected;
dataInfo.connected = this.dataNetworkInterface.connected;
// Make sure we also reset the operator and signal strength information
// if we drop off the network.
@ -646,14 +656,12 @@ RadioInterfaceLayer.prototype = {
* Handle data errors
*/
handleDataCallError: function handleDataCallError(message) {
if (message.apn != this.dataCallSettings["apn"]) {
return;
// Notify data call error only for data APN
if (message.apn == this.dataCallSettings["apn"]) {
ppmm.broadcastAsyncMessage("RIL:DataError", message);
}
// 3G Network revoked the data connection, possible unavailable APN
RILNetworkInterface.reset();
// Notify datacall error
ppmm.broadcastAsyncMessage("RIL:DataError", message);
this._deliverDataCallCallback("dataCallError", [message]);
},
handleSignalStrengthChange: function handleSignalStrengthChange(message) {
@ -797,12 +805,12 @@ RadioInterfaceLayer.prototype = {
return;
}
if (!this.dataCallSettings["enabled"] && RILNetworkInterface.connected) {
if (!this.dataCallSettings["enabled"] && this.dataNetworkInterface.connected) {
debug("Data call settings: disconnect data call.");
RILNetworkInterface.disconnect();
this.dataNetworkInterface.disconnect();
return;
}
if (!this.dataCallSettings["enabled"] || RILNetworkInterface.connected) {
if (!this.dataCallSettings["enabled"] || this.dataNetworkInterface.connected) {
debug("Data call settings: nothing to do.");
return;
}
@ -822,7 +830,7 @@ RadioInterfaceLayer.prototype = {
}
debug("Data call settings: connect data call.");
RILNetworkInterface.connect(this.dataCallSettings);
this.dataNetworkInterface.connect(this.dataCallSettings);
},
/**
@ -1113,7 +1121,8 @@ RadioInterfaceLayer.prototype = {
handleDataCallState: function handleDataCallState(datacall) {
let data = this.rilContext.data;
if (datacall.ifname) {
if (datacall.ifname &&
datacall.apn == this.dataCallSettings["apn"]) {
data.connected = (datacall.state == RIL.GECKO_NETWORK_STATE_CONNECTED);
ppmm.broadcastAsyncMessage("RIL:DataInfoChanged", data);
}
@ -1192,7 +1201,10 @@ RadioInterfaceLayer.prototype = {
for each (let msgname in RIL_IPC_MSG_NAMES) {
ppmm.removeMessageListener(msgname, this);
}
RILNetworkInterface.shutdown();
// Shutdown all RIL network interfaces
this.dataNetworkInterface.shutdown();
this.mmsNetworkInterface.shutdown();
this.suplNetworkInterface.shutdown();
ppmm = null;
Services.obs.removeObserver(this, "xpcom-shutdown");
Services.obs.removeObserver(this, kMozSettingsChangedObserverTopic);
@ -1889,8 +1901,18 @@ RadioInterfaceLayer.prototype = {
}
};
let RILNetworkInterface = {
function RILNetworkInterface(ril, type)
{
this.mRIL = ril;
this.type = type;
}
RILNetworkInterface.prototype = {
classID: RILNETWORKINTERFACE_CID,
classInfo: XPCOMUtils.generateCI({classID: RILNETWORKINTERFACE_CID,
classDescription: "RILNetworkInterface",
interfaces: [Ci.nsINetworkInterface,
Ci.nsIRIODataCallback]}),
QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface,
Ci.nsIRILDataCallback]),
@ -1942,8 +1964,20 @@ let RILNetworkInterface = {
// nsIRILDataCallback
dataCallError: function dataCallError(message) {
if (message.apn != this.dataCallSettings["apn"]) {
return;
}
debug("Data call error on APN: " + message.apn);
this.reset();
},
dataCallStateChanged: function dataCallStateChanged(datacall) {
debug("Data call ID: " + datacall.cid + ", interface name: " + datacall.ifname);
if (datacall.apn != this.dataCallSettings["apn"]) {
return;
}
debug("Data call ID: " + datacall.cid + ", interface name: " +
datacall.ifname + ", APN name: " + datacall.apn);
if (this.connecting &&
(datacall.state == RIL.GECKO_NETWORK_STATE_CONNECTING ||
datacall.state == RIL.GECKO_NETWORK_STATE_CONNECTED)) {
@ -1959,9 +1993,7 @@ let RILNetworkInterface = {
this.dns2 = datacall.dns[1];
}
if (!this.registeredAsNetworkInterface) {
let networkManager = Cc["@mozilla.org/network/manager;1"]
.getService(Ci.nsINetworkManager);
networkManager.registerNetworkInterface(this);
gNetworkManager.registerNetworkInterface(this);
this.registeredAsNetworkInterface = true;
}
}
@ -1973,6 +2005,14 @@ let RILNetworkInterface = {
}
this.state = datacall.state;
if (this.state == RIL.GECKO_NETWORK_STATE_UNKNOWN &&
this.registeredAsNetworkInterface) {
gNetworkManager.unregisterNetworkInterface(this);
this.registeredAsNetworkInterface = false;
return;
}
Services.obs.notifyObservers(this,
kNetworkInterfaceStateChangedTopic,
null);
@ -1992,13 +2032,6 @@ let RILNetworkInterface = {
// APN failed connections. Retry counter
apnRetryCounter: 0,
get mRIL() {
delete this.mRIL;
return this.mRIL = Cc["@mozilla.org/telephony/system-worker-manager;1"]
.getService(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIRadioInterfaceLayer);
},
get connected() {
return this.state == RIL.GECKO_NETWORK_STATE_CONNECTED;
},
@ -2069,7 +2102,7 @@ let RILNetworkInterface = {
// Entry method for timer events. Used to reconnect to a failed APN
notify: function(timer) {
RILNetworkInterface.connect();
this.connect();
},
shutdown: function() {

View File

@ -2972,13 +2972,20 @@ let RIL = {
}
if (!updatedDataCall) {
delete this.currentDataCalls[currentDataCall.callIndex];
currentDataCall.state = GECKO_NETWORK_STATE_DISCONNECTED;
currentDataCall.rilMessageType = "datacallstatechange";
this.sendDOMMessage(currentDataCall);
continue;
}
if (updatedDataCall && !updatedDataCall.ifname) {
delete this.currentDataCalls[currentDataCall.cid];
currentDataCall.state = GECKO_NETWORK_STATE_UNKNOWN;
currentDataCall.rilMessageType = "datacallstatechange";
this.sendDOMMessage(currentDataCall);
continue;
}
this._setDataCallGeckoState(updatedDataCall);
if (updatedDataCall.state != currentDataCall.state) {
currentDataCall.status = updatedDataCall.status;
@ -2990,6 +2997,9 @@ let RIL = {
}
for each (let newDataCall in datacalls) {
if (!newDataCall.ifname) {
continue;
}
this.currentDataCalls[newDataCall.cid] = newDataCall;
this._setDataCallGeckoState(newDataCall);
if (newDataCallOptions) {
@ -4071,7 +4081,7 @@ RIL[REQUEST_DEACTIVATE_DATA_CALL] = function REQUEST_DEACTIVATE_DATA_CALL(length
let datacall = this.currentDataCalls[options.cid];
delete this.currentDataCalls[options.cid];
datacall.state = GECKO_NETWORK_STATE_DISCONNECTED;
datacall.state = GECKO_NETWORK_STATE_UNKNOWN;
datacall.rilMessageType = "datacallstatechange";
this.sendDOMMessage(datacall);
};