Bug 734299 - Part 3: Set up a datacall when registering with the network. r=qDot DONTBUILD because NPOTB
authorPhilipp von Weitershausen <philipp@weitershausen.de>
Mon, 12 Mar 2012 16:46:08 -0700
changeset 88812 dfcb11712ec227cc6ec259acc8646b98f81f8d00
parent 88811 789068a4ba16cbc641652b7d504ec0ff797388e9
child 88813 0c35057e2bb41d3440942338b5ad3c7d9c2a3345
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersqDot
bugs734299
milestone13.0a1
Bug 734299 - Part 3: Set up a datacall when registering with the network. r=qDot DONTBUILD because NPOTB
b2g/app/b2g.js
dom/system/b2g/RadioInterfaceLayer.js
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -439,8 +439,17 @@ pref("b2g.keys.menu.enabled", true);
 pref("b2g.keys.search.enabled", false);
 
 // Screen timeout in minutes
 pref("power.screen.timeout", 60);
 
 pref("full-screen-api.enabled", true);
 
 pref("media.volume.steps", 10);
+
+// Data connection settings. These will eventually live in the
+// navigator.settings API, or even in a database where we can look
+// it up automatically (bug 729440), but for this will have to do.
+pref("ril.data.enabled", false);
+pref("ril.data.roaming.enabled", false);
+pref("ril.data.apn", "");
+pref("ril.data.user", "");
+pref("ril.data.passwd", "");
--- a/dom/system/b2g/RadioInterfaceLayer.js
+++ b/dom/system/b2g/RadioInterfaceLayer.js
@@ -42,17 +42,17 @@
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 var RIL = {};
 Cu.import("resource://gre/modules/ril_consts.js", RIL);
 
-const DEBUG = true; // set to true to see debug messages
+const DEBUG = false; // set to true to see debug messages
 
 const RADIOINTERFACELAYER_CID =
   Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
 const DATACALLINFO_CID =
   Components.ID("{ef474cd9-94f7-4c05-a31b-29b9de8a10d2}");
 
 const nsIAudioManager = Ci.nsIAudioManager;
 const nsIRadioInterfaceLayer = Ci.nsIRadioInterfaceLayer;
@@ -189,21 +189,25 @@ RadioInterfaceLayer.prototype = {
         // This one will handle its own notifications.
         this.handleCallDisconnected(message.call);
         break;
       case "enumerateCalls":
         // This one will handle its own notifications.
         this.handleEnumerateCalls(message.calls);
         break;
       case "registrationstatechange":
-        //TODO for simplicity's sake, for now we only look at
-        // gprsregistrationstatechange.
+        this.updateDataConnection(message.registrationState);
         break;
       case "gprsregistrationstatechange":
         let state = message.gprsRegistrationState;
+        this.updateDataConnection(state);
+
+        //TODO for simplicity's sake, for now we only look at
+        // gprsRegistrationState for the radio registration state.
+
         if (!state || state.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) {
           this.resetRadioState();
           this.notifyRadioStateChanged();
           return;
         }
 
         this.radioState.connected =
           (state.regState == RIL.NETWORK_CREG_STATE_REGISTERED_HOME) ||
@@ -274,16 +278,51 @@ RadioInterfaceLayer.prototype = {
                + " timestamp=" + message.localTimeStampInMS);
         }
         break;
       default:
         throw new Error("Don't know about this message type: " + message.type);
     }
   },
 
+  _isDataEnabled: function _isDataEnabled() {
+    try {
+      return Services.prefs.getBoolPref("ril.data.enabled");
+    } catch(ex) {
+      return false;
+    }
+  },
+
+  _isDataRoamingEnabled: function _isDataRoamingEnabled() {
+    try {
+      return Services.prefs.getBoolPref("ril.data.roaming.enabled");
+    } catch(ex) {
+      return false;
+    }
+  },
+
+  updateDataConnection: function updateDataConnection(state) {
+    if (!this._isDataEnabled()) {
+      return;
+    }
+
+    let isRegistered =
+      state.regState == RIL.NETWORK_CREG_STATE_REGISTERED_HOME ||
+        (this._isDataRoamingEnabled() &&
+         state.regState == RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING);
+    let haveDataConnection =
+      state.radioTech != RIL.NETWORK_CREG_TECH_UNKNOWN;
+
+    if (isRegistered && haveDataConnection) {
+      debug("Radio is ready for data connection.");
+      // RILNetworkInterface will ignore this if it's already connected.
+      RILNetworkInterface.connect();
+    }
+  },
+
   /**
    * Track the active call and update the audio system as its state changes.
    *
    * XXX Needs some more work to support hold/resume.
    */
   _activeCall: null,
   updateCallAudioState: function updateCallAudioState() {
     if (!this._activeCall) {
@@ -637,16 +676,118 @@ RadioInterfaceLayer.prototype = {
   },
 
   getDataCallList: function getDataCallList() {
     this.worker.postMessage({type: "getDataCallList"});
   },
 
 };
 
+
+let RILNetworkInterface = {
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIRILDataCallback]),
+
+  state: RIL.GECKO_NETWORK_STATE_UNKNOWN,
+  name: null,
+
+  worker: null,
+  cid: null,
+  registeredAsDataCallCallback: false,
+  connecting: false,
+
+  initWorker: function initWorker() {
+    debug("Starting net_worker.");
+    this.worker = new ChromeWorker("resource://gre/modules/net_worker.js");
+    this.worker.onerror = function onerror(event) {
+      debug("Received error from worker: " + event.filename +
+            ":" + event.lineno + ": " + event.message + "\n");
+      // Prevent the event from bubbling any further.
+      event.preventDefault();
+    };
+  },
+
+  // nsIRILDataCallback
+
+  dataCallStateChanged: function dataCallStateChanged(cid, interfaceName, callState) {
+    if (this.connecting &&
+        callState == RIL.GECKO_NETWORK_STATE_CONNECTING) {
+      this.connecting = false;
+      this.cid = cid;
+      this.name = interfaceName;
+      debug("Data call ID: " + cid + ", interface name: " + interfaceName);
+    }
+    if (this.cid != cid) {
+      return;
+    }
+    if (this.state == callState) {
+      return;
+    }
+
+    this.state = callState;
+
+    if (callState == RIL.GECKO_NETWORK_STATE_CONNECTED) {
+      debug("Data call is connected, going to configure networking bits.");
+      this.worker.postMessage({cmd: "setDefaultRouteAndDNS",
+                               ifname: this.name});
+    }
+  },
+
+  receiveDataCallList: function receiveDataCallList(dataCalls, length) {
+  },
+
+  // Helpers
+
+  get mRIL() {
+    delete this.mRIL;
+    return this.mRIL = Cc["@mozilla.org/telephony/system-worker-manager;1"]
+                         .getService(Ci.nsIInterfaceRequestor)
+                         .getInterface(Ci.nsIRadioInterfaceLayer);
+  },
+
+  connect: function connect() {
+    if (this.connecting ||
+        this.state == RIL.GECKO_NETWORK_STATE_CONNECTED ||
+        this.state == RIL.GECKO_NETWORK_STATE_SUSPENDED ||
+        this.state == RIL.GECKO_NETWORK_STATE_DISCONNECTING) {
+      return;
+    }
+    if (!this.registeredAsDataCallCallback) {
+      this.mRIL.registerDataCallCallback(this);
+      this.registeredAsDataCallCallback = true;
+    }
+
+    if (!this.worker) {
+      this.initWorker();
+    }
+
+    let apn, user, passwd;
+    // Eventually these values would be retrieved from the user's preferences
+    // via the settings API. For now we just use Gecko's preferences.
+    try {
+      apn = Services.prefs.getCharPref("ril.data.apn");
+      user = Services.prefs.getCharPref("ril.data.user");
+      passwd = Services.prefs.getCharPref("ril.data.passwd");
+    } catch (ex) {
+      debug("No APN settings found, not going to set up data connection.");
+      return;
+    }
+    debug("Going to set up data connection with APN " + apn);
+    this.mRIL.setupDataCall(RIL.DATACALL_RADIOTECHNOLOGY_GSM,
+                            apn, user, passwd,
+                            RIL.DATACALL_AUTH_PAP_OR_CHAP, "IP");
+    this.connecting = true;
+  },
+
+  disconnect: function disconnect() {
+    this.mRIL.deactivateDataCall(this.cid);
+  },
+
+};
+
 const NSGetFactory = XPCOMUtils.generateNSGetFactory([RadioInterfaceLayer]);
 
 let debug;
 if (DEBUG) {
   debug = function (s) {
     dump("-*- RadioInterfaceLayer: " + s + "\n");
   };
 } else {