Bug 869768 - Part 3: RIL implementation for roaming preference. r=hsinyi
authorEdgar Chen <echen@mozilla.com>
Mon, 10 Jun 2013 15:47:03 +0800
changeset 140261 a58c0eb539322c05f3d2d1cbb7482bf66a5b454f
parent 140260 2f065dbfe9cbca190c67d1f49859d52d5ce9cfe8
child 140262 e98be421d74be4471a8b02d54027943136834868
push id1951
push userryanvm@gmail.com
push dateSun, 28 Jul 2013 01:55:51 +0000
treeherderfx-team@73b69c146ca6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershsinyi
bugs869768
milestone25.0a1
Bug 869768 - Part 3: RIL implementation for roaming preference. r=hsinyi
dom/network/interfaces/nsIMobileConnectionProvider.idl
dom/system/gonk/RILContentHelper.js
dom/system/gonk/RadioInterfaceLayer.js
dom/system/gonk/ril_consts.js
dom/system/gonk/ril_worker.js
--- a/dom/network/interfaces/nsIMobileConnectionProvider.idl
+++ b/dom/network/interfaces/nsIMobileConnectionProvider.idl
@@ -25,17 +25,17 @@ interface nsIMobileConnectionListener : 
                            in unsigned short timeSeconds,
                            in unsigned short serviceClass);
 };
 
 /**
  * XPCOM component (in the content process) that provides the mobile
  * network information.
  */
-[scriptable, uuid(3fea6ca5-c535-4662-9f42-eb2fc2ae9975)]
+[scriptable, uuid(12705160-d1b6-11e2-8b8b-0800200c9a66)]
 interface nsIMobileConnectionProvider : nsISupports
 {
   /**
    * Called when a content process registers receiving unsolicited messages from
    * RadioInterfaceLayer in the chrome process. Only a content process that has
    * the 'mobileconnection' permission is allowed to register.
    */
   void registerMobileConnectionMsg(in nsIMobileConnectionListener listener);
@@ -44,16 +44,20 @@ interface nsIMobileConnectionProvider : 
   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 setRoamingPreference(in nsIDOMWindow window,
+                                        in DOMString mode);
+  nsIDOMDOMRequest getRoamingPreference(in nsIDOMWindow window);
+
   nsIDOMDOMRequest sendMMI(in nsIDOMWindow window, in DOMString mmi);
   nsIDOMDOMRequest cancelMMI(in nsIDOMWindow window);
 
   nsIDOMDOMRequest getCallForwardingOption(in nsIDOMWindow   window,
                                            in unsigned short reason);
   nsIDOMDOMRequest setCallForwardingOption(in nsIDOMWindow          window,
                                            in nsIDOMMozMobileCFInfo CFInfo);
 
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -97,17 +97,19 @@ const RIL_IPC_MSG_NAMES = [
   "RIL:SetCallingLineIdRestriction",
   "RIL:GetCallingLineIdRestriction",
   "RIL:CellBroadcastReceived",
   "RIL:CfStateChanged",
   "RIL:IccOpenChannel",
   "RIL:IccCloseChannel",
   "RIL:IccExchangeAPDU",
   "RIL:ReadIccContacts",
-  "RIL:UpdateIccContact"
+  "RIL:UpdateIccContact",
+  "RIL:SetRoamingPreference",
+  "RIL:GetRoamingPreference"
 ];
 
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
                                    "@mozilla.org/childprocessmessagemanager;1",
                                    "nsISyncMessageSender");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
                                    "@mozilla.org/uuid-generator;1",
@@ -619,16 +621,58 @@ RILContentHelper.prototype = {
       clientId: 0,
       data: {
         requestId: requestId
       }
     });
     return request;
   },
 
+  setRoamingPreference: function setRoamingPreference(window, mode) {
+    if (window == null) {
+      throw Components.Exception("Can't get window object",
+                                  Cr.NS_ERROR_UNEXPECTED);
+    }
+
+    let request = Services.DOMRequest.createRequest(window);
+    let requestId = this.getRequestId(request);
+
+    if (!mode) {
+      this.dispatchFireRequestError(requestId, "InvalidParameter");
+      return request;
+    }
+
+    cpmm.sendAsyncMessage("RIL:SetRoamingPreference", {
+      clientId: 0,
+      data: {
+        requestId: requestId,
+        mode: mode
+      }
+    });
+    return request;
+  },
+
+  getRoamingPreference: function getRoamingPreference(window) {
+    if (window == null) {
+      throw Components.Exception("Can't get window object",
+                                  Cr.NS_ERROR_UNEXPECTED);
+    }
+
+    let request = Services.DOMRequest.createRequest(window);
+    let requestId = this.getRequestId(request);
+
+    cpmm.sendAsyncMessage("RIL:GetRoamingPreference", {
+      clientId: 0,
+      data: {
+        requestId: requestId
+      }
+    });
+    return request;
+  },
+
   getCardLockState: function getCardLockState(window, lockType) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
     cpmm.sendAsyncMessage("RIL:GetCardLockState", {
@@ -1536,16 +1580,22 @@ RILContentHelper.prototype = {
         break;
       case "RIL:CellBroadcastReceived": {
         let message = new CellBroadcastMessage(msg.json.data);
         this._deliverEvent("_cellBroadcastListeners",
                            "notifyMessageReceived",
                            [message]);
         break;
       }
+      case "RIL:SetRoamingPreference":
+        this.handleSetRoamingPreference(msg.json);
+        break;
+      case "RIL:GetRoamingPreference":
+        this.handleGetRoamingPreference(msg.json);
+        break;
     }
   },
 
   handleEnumerateCalls: function handleEnumerateCalls(calls) {
     debug("handleEnumerateCalls: " + JSON.stringify(calls));
     let callback = this._enumerateTelephonyCallbacks.shift();
     if (!calls.length) {
       callback.enumerateCallStateComplete();
@@ -1871,16 +1921,32 @@ RILContentHelper.prototype = {
       Services.DOMRequest.fireDetailedError(request, mmiError);
     }
   },
 
   _getRandomId: function _getRandomId() {
     return gUUIDGenerator.generateUUID().toString();
   },
 
+  handleSetRoamingPreference: function handleSetRoamingPreference(message) {
+    if (message.errorMsg) {
+      this.fireRequestError(message.requestId, message.errorMsg);
+    } else {
+      this.fireRequestSuccess(message.requestId, null);
+    }
+  },
+
+  handleGetRoamingPreference: function handleGetRoamingPreference(message) {
+    if (message.errorMsg) {
+      this.fireRequestError(message.requestId, message.errorMsg);
+    } else {
+      this.fireRequestSuccess(message.requestId, message.mode);
+    }
+  },
+
   _deliverEvent: function _deliverEvent(listenerType, name, args) {
     let thisListeners = this[listenerType];
     if (!thisListeners) {
       return;
     }
 
     let listeners = thisListeners.slice();
     for (let listener of listeners) {
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -101,17 +101,19 @@ const RIL_IPC_MOBILECONNECTION_MSG_NAMES
   "RIL:RegisterMobileConnectionMsg",
   "RIL:SetCallForwardingOption",
   "RIL:GetCallForwardingOption",
   "RIL:SetCallBarringOption",
   "RIL:GetCallBarringOption",
   "RIL:SetCallWaitingOption",
   "RIL:GetCallWaitingOption",
   "RIL:SetCallingLineIdRestriction",
-  "RIL:GetCallingLineIdRestriction"
+  "RIL:GetCallingLineIdRestriction",
+  "RIL:SetRoamingPreference",
+  "RIL:GetRoamingPreference"
 ];
 
 const RIL_IPC_ICCMANAGER_MSG_NAMES = [
   "RIL:SendStkResponse",
   "RIL:SendStkMenuSelection",
   "RIL:SendStkTimerExpiration",
   "RIL:SendStkEventDownload",
   "RIL:GetCardLockState",
@@ -871,16 +873,24 @@ RadioInterface.prototype = {
         break;
       case "RIL:GetCallingLineIdRestriction":
         gMessageManager.saveRequestTarget(msg);
         this.getCallingLineIdRestriction(msg.json.data);
         break;
       case "RIL:GetVoicemailInfo":
         // This message is sync.
         return this.voicemailInfo;
+      case "RIL:SetRoamingPreference":
+        gMessageManager.saveRequestTarget(msg);
+        this.setRoamingPreference(msg.json.data);
+        break;
+      case "RIL:GetRoamingPreference":
+        gMessageManager.saveRequestTarget(msg);
+        this.getRoamingPreference(msg.json.data);
+        break;
     }
   },
 
   onerror: function onerror(event) {
     if (DEBUG) {
       this.debug("Got an error: " + event.filename + ":" +
                  event.lineno + ": " + event.message + "\n");
     }
@@ -1067,16 +1077,22 @@ RadioInterface.prototype = {
         break;
       case "setCellBroadcastSearchList":
         this.handleSetCellBroadcastSearchList(message);
         break;
       case "setRadioEnabled":
         let lock = gSettingsService.createLock();
         lock.set("ril.radio.disabled", !message.on, null, null);
         break;
+      case "setRoamingPreference":
+        this.handleSetRoamingPreference(message);
+        break;
+      case "queryRoamingPreference":
+        this.handleQueryRoamingPreference(message);
+        break;
       default:
         throw new Error("Don't know about this message type: " +
                         message.rilMessageType);
     }
   },
 
   getMsisdn: function getMsisdn() {
     let iccInfo = this.rilContext.iccInfo;
@@ -2263,16 +2279,26 @@ RadioInterface.prototype = {
   },
 
   handleSetCLIR: function handleSetCLIR(message) {
     if (DEBUG) this.debug("handleSetCLIR: " + JSON.stringify(message));
     gMessageManager.sendRequestResults("RIL:SetCallingLineIdRestriction",
                                        message);
   },
 
+  handleSetRoamingPreference: function handleSetRoamingPreference(message) {
+    if (DEBUG) this.debug("handleSetRoamingPreference: " + JSON.stringify(message));
+    gMessageManager.sendRequestResults("RIL:SetRoamingPreference", message);
+  },
+
+  handleQueryRoamingPreference: function handleQueryRoamingPreference(message) {
+    if (DEBUG) this.debug("handleQueryRoamingPreference: " + JSON.stringify(message));
+    gMessageManager.sendRequestResults("RIL:GetRoamingPreference", message);
+  },
+
   // nsIObserver
 
   observe: function observe(subject, topic, data) {
     switch (topic) {
       case kSysMsgListenerReadyObserverTopic:
         Services.obs.removeObserver(this, kSysMsgListenerReadyObserverTopic);
         this._sysMsgListenerReady = true;
         this._ensureRadioState();
@@ -2652,16 +2678,28 @@ RadioInterface.prototype = {
   getCallingLineIdRestriction: function getCallingLineIdRestriction(message) {
     if (DEBUG) {
       this.debug("getCallingLineIdRestriction: " + JSON.stringify(message));
     }
     message.rilMessageType = "getCLIR";
     this.worker.postMessage(message);
   },
 
+  getRoamingPreference: function getRoamingPreference(message) {
+    if (DEBUG) this.debug("getRoamingPreference: " + JSON.stringify(message));
+    message.rilMessageType = "queryRoamingPreference";
+    this.worker.postMessage(message);
+  },
+
+  setRoamingPreference: function setRoamingPreference(message) {
+    if (DEBUG) this.debug("setRoamingPreference: " + JSON.stringify(message));
+    message.rilMessageType = "setRoamingPreference";
+    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
@@ -2676,16 +2676,31 @@ this.PDU_CDMA_REPLY_OPTION = 0x0A;      
 this.PDU_CDMA_MSG_USERDATA_CALLBACK_NUMBER = 0x0E;  // Callback Number
 
 // IS-91 Message Type, as defined in TIA/EIA/IS-91-A, Table 9
 this.PDU_CDMA_MSG_CODING_IS_91_TYPE_VOICEMAIL_STATUS = 0x82;
 this.PDU_CDMA_MSG_CODING_IS_91_TYPE_SMS_FULL = 0x83;
 this.PDU_CDMA_MSG_CODING_IS_91_TYPE_CLI = 0x84;
 this.PDU_CDMA_MSG_CODING_IS_91_TYPE_SMS = 0x85;
 
+// CDMA roaming preference mode
+this.CDMA_ROAMING_PREFERENCE_HOME = 0;
+this.CDMA_ROAMING_PREFERENCE_AFFILIATED = 1;
+this.CDMA_ROAMING_PREFERENCE_ANY = 2;
+
+this.GECKO_CDMA_ROAMING_PREFERENCE_HOME = "home";
+this.GECKO_CDMA_ROAMING_PREFERENCE_AFFILIATED = "affiliated";
+this.GECKO_CDMA_ROAMING_PREFERENCE_ANY = "any";
+
+this.CDMA_ROAMING_PREFERENCE_TO_GECKO = [
+  GECKO_CDMA_ROAMING_PREFERENCE_HOME,       // CDMA_ROAMING_PREFERENCE_HOME
+  GECKO_CDMA_ROAMING_PREFERENCE_AFFILIATED, // CDMA_ROAMING_PREFERENCE_AFFILIATED
+  GECKO_CDMA_ROAMING_PREFERENCE_ANY         // CDMA_ROAMING_PREFERENCE_ANY
+];
+
 /**
  * The table for MCC which the length of MNC is 3
  *
  * This table is built from below links.
  * - http://www.itu.int/pub/T-SP-E.212B-2013
  * - http://en.wikipedia.org/wiki/Mobile_Network_Code
  */
 this.MCC_TABLE_FOR_MNC_LENGTH_IS_3 = [
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -1604,16 +1604,41 @@ let RIL = {
    * 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);
   },
 
   /**
+   * Set the roaming preference mode
+   */
+  setRoamingPreference: function setRoamingPreference(options) {
+    let roamingMode = CDMA_ROAMING_PREFERENCE_TO_GECKO.indexOf(options.mode);
+
+    if (roamingMode === -1) {
+      options.errorMsg = GECKO_ERROR_INVALID_PARAMETER;
+      this.sendDOMMessage(options);
+      return;
+    }
+
+    Buf.newParcel(REQUEST_CDMA_SET_ROAMING_PREFERENCE, options);
+    Buf.writeUint32(1);
+    Buf.writeUint32(roamingMode);
+    Buf.sendParcel();
+  },
+
+  /**
+   * Get the roaming preference mode
+   */
+  queryRoamingPreference: function getRoamingPreference(options) {
+    Buf.simpleRequest(REQUEST_CDMA_QUERY_ROAMING_PREFERENCE, options);
+  },
+
+  /**
    * Open Logical UICC channel (aid) for Secure Element access
    */
   iccOpenChannel: function iccOpenChannel(options) {
     if (DEBUG) {
       debug("iccOpenChannel: " + JSON.stringify(options));
     }
 
     Buf.newParcel(REQUEST_SIM_OPEN_CHANNEL, options);
@@ -5553,18 +5578,36 @@ RIL[REQUEST_GET_PREFERRED_NETWORK_TYPE] 
     rilMessageType: "getPreferredNetworkType",
     networkType: networkType,
     success: options.rilRequestError == ERROR_SUCCESS
   });
 };
 RIL[REQUEST_GET_NEIGHBORING_CELL_IDS] = null;
 RIL[REQUEST_SET_LOCATION_UPDATES] = null;
 RIL[REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE] = null;
-RIL[REQUEST_CDMA_SET_ROAMING_PREFERENCE] = null;
-RIL[REQUEST_CDMA_QUERY_ROAMING_PREFERENCE] = null;
+RIL[REQUEST_CDMA_SET_ROAMING_PREFERENCE] = function REQUEST_CDMA_SET_ROAMING_PREFERENCE(length, options) {
+  if (options.rilRequestError) {
+    options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
+    this.sendDOMMessage(options);
+    return;
+  }
+
+  this.sendDOMMessage(options);
+};
+RIL[REQUEST_CDMA_QUERY_ROAMING_PREFERENCE] = function REQUEST_CDMA_QUERY_ROAMING_PREFERENCE(length, options) {
+  if (options.rilRequestError) {
+    options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
+    this.sendDOMMessage(options);
+    return;
+  }
+
+  let mode = Buf.readUint32List();
+  options.mode = CDMA_ROAMING_PREFERENCE_TO_GECKO[mode[0]];
+  this.sendDOMMessage(options);
+};
 RIL[REQUEST_SET_TTY_MODE] = null;
 RIL[REQUEST_QUERY_TTY_MODE] = null;
 RIL[REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE] = null;
 RIL[REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE] = null;
 RIL[REQUEST_CDMA_FLASH] = null;
 RIL[REQUEST_CDMA_BURST_DTMF] = null;
 RIL[REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY] = null;
 RIL[REQUEST_CDMA_SEND_SMS] = function REQUEST_CDMA_SEND_SMS(length, options) {