Bug 1110619 - Part 2: Implementation Changes. r=echen
authorBevis Tseng <btseng@mozilla.com>
Tue, 10 Nov 2015 15:30:48 +0800
changeset 272678 8d957f94e34ccdbc62f68597cb7adf97638fa806
parent 272677 11cc5726cc2d47157c1fa230a244bad3596a50a8
child 272679 d308e79cbdbe861d6172fb615ac461a3c9752859
push id18680
push usercbook@mozilla.com
push dateMon, 16 Nov 2015 15:26:29 +0000
treeherderb2g-inbound@d308e79cbdbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersechen
bugs1110619
milestone45.0a1
Bug 1110619 - Part 2: Implementation Changes. r=echen
dom/mobileconnection/MobileConnection.cpp
dom/mobileconnection/gonk/MobileConnectionService.js
dom/mobileconnection/ipc/MobileConnectionChild.cpp
dom/mobileconnection/ipc/MobileConnectionParent.cpp
dom/mobilemessage/gonk/SmsService.js
dom/system/gonk/DataCallManager.js
dom/system/gonk/RadioInterfaceLayer.js
dom/system/gonk/ril_worker.js
dom/telephony/gonk/TelephonyService.js
--- a/dom/mobileconnection/MobileConnection.cpp
+++ b/dom/mobileconnection/MobileConnection.cpp
@@ -1122,16 +1122,23 @@ MobileConnection::NotifyLastKnownHomeNet
 }
 
 NS_IMETHODIMP
 MobileConnection::NotifyNetworkSelectionModeChanged()
 {
   return NS_OK;
 }
 
+NS_IMETHODIMP
+MobileConnection::NotifyDeviceIdentitiesChanged()
+{
+  // To be supported when bug 1222870 is required in m-c.
+  return NS_OK;
+}
+
 // nsIIccListener
 
 NS_IMETHODIMP
 MobileConnection::NotifyStkCommand(nsIStkProactiveCmd *aStkProactiveCmd)
 {
   return NS_OK;
 }
 
--- a/dom/mobileconnection/gonk/MobileConnectionService.js
+++ b/dom/mobileconnection/gonk/MobileConnectionService.js
@@ -457,16 +457,32 @@ CdmaCellInfo.prototype = {
   latitude: UNKNOWN_VALUE,
   cdmaDbm: UNKNOWN_VALUE,
   cdmaEcio: UNKNOWN_VALUE,
   evdoDbm: UNKNOWN_VALUE,
   evdoEcio: UNKNOWN_VALUE,
   evdoSnr: UNKNOWN_VALUE
 };
 
+function MobileDeviceIdentities(aImei, aImeisv, aEsn, aMeid) {
+  this.imei = aImei;
+  this.imeisv = aImeisv;
+  this.esn = aEsn;
+  this.meid = aMeid;
+}
+MobileDeviceIdentities.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileDeviceIdentities]),
+
+  // nsIMobileDeviceIdentities
+  imei: null,
+  imeisv: null,
+  esn: null,
+  meid: null
+};
+
 function MobileConnectionProvider(aClientId, aRadioInterface) {
   this._clientId = aClientId;
   this._radioInterface = aRadioInterface;
   this._operatorInfo = new MobileNetworkInfo();
   // An array of nsIMobileConnectionListener instances.
   this._listeners = [];
 
   this.supportedNetworkTypes = this._getSupportedNetworkTypes();
@@ -496,16 +512,17 @@ MobileConnectionProvider.prototype = {
 
   voice: null,
   data: null,
   networkSelectionMode: Ci.nsIMobileConnection.NETWORK_SELECTION_MODE_UNKNOWN,
   radioState: Ci.nsIMobileConnection.MOBILE_RADIO_STATE_UNKNOWN,
   lastKnownNetwork: null,
   lastKnownHomeNetwork: null,
   supportedNetworkTypes: null,
+  deviceIdentities: null,
 
   /**
    * A utility function to dump debug message.
    */
   _debug: function(aMessage) {
     dump("MobileConnectionProvider[" + this._clientId + "]: " + aMessage + "\n");
   },
 
@@ -956,16 +973,27 @@ MobileConnectionProvider.prototype = {
 
   notifyCFStateChanged: function(aAction, aReason, aNumber, aTimeSeconds,
                                  aServiceClass) {
     this.deliverListenerEvent("notifyCFStateChanged",
                               [aAction, aReason, aNumber, aTimeSeconds,
                                aServiceClass]);
   },
 
+  notifyDeviceIdentitiesChanged: function(aImei, aImeisv, aEsn, aMeid) {
+    if (this.deviceIdentities) {
+      if (DEBUG) this._debug("deviceIdentities shall not be changed once being updated.");
+      return;
+    }
+
+    this.deviceIdentities =
+      new MobileDeviceIdentities(aImei, aImeisv, aEsn, aMeid);
+    this.deliverListenerEvent("notifyDeviceIdentitiesChanged");
+  },
+
   getSupportedNetworkTypes: function(aTypes) {
     aTypes.value = this.supportedNetworkTypes.slice();
     return aTypes.value.length;
   },
 
   getNetworks: function(aCallback) {
     this._radioInterface.sendWorkerMessage("getAvailableNetworks", null,
                                            (function(aResponse) {
@@ -1688,16 +1716,22 @@ MobileConnectionService.prototype = {
     gMobileConnectionMessenger.notifyCdmaInfoRecClir(aClientId, aCause);
   },
 
   notifyCdmaInfoRecAudioControl: function(aClientId, aUpLink, aDownLink) {
     gMobileConnectionMessenger
       .notifyCdmaInfoRecAudioControl(aClientId, aUpLink, aDownLink);
   },
 
+  notifyDeviceIdentitiesChanged: function(aClientId, aImei, aImeisv,
+                                          aEsn, aMeid) {
+    this.getItemByServiceId(aClientId)
+      .notifyDeviceIdentitiesChanged(aImei, aImeisv, aEsn, aMeid);
+  },
+
   /**
    * nsIObserver interface.
    */
   observe: function(aSubject, aTopic, aData) {
     switch (aTopic) {
       case NS_NETWORK_ACTIVE_CHANGED_TOPIC_ID:
         for (let i = 0; i < this.numItems; i++) {
           let provider = this._providers[i];
--- a/dom/mobileconnection/ipc/MobileConnectionChild.cpp
+++ b/dom/mobileconnection/ipc/MobileConnectionChild.cpp
@@ -103,16 +103,22 @@ MobileConnectionChild::GetData(nsIMobile
 NS_IMETHODIMP
 MobileConnectionChild::GetRadioState(int32_t* aRadioState)
 {
   *aRadioState = mRadioState;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+MobileConnectionChild::GetDeviceIdentities(nsIMobileDeviceIdentities** aIdentities)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 MobileConnectionChild::GetSupportedNetworkTypes(int32_t** aTypes,
                                                 uint32_t* aLength)
 {
   NS_ENSURE_ARG(aTypes);
   NS_ENSURE_ARG(aLength);
 
   *aLength = mSupportedNetworkTypes.Length();
   *aTypes =
--- a/dom/mobileconnection/ipc/MobileConnectionParent.cpp
+++ b/dom/mobileconnection/ipc/MobileConnectionParent.cpp
@@ -283,16 +283,23 @@ MobileConnectionParent::NotifyNetworkSel
   nsresult rv;
   int32_t mode;
   rv = mMobileConnection->GetNetworkSelectionMode(&mode);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return SendNotifyNetworkSelectionModeChanged(mode) ? NS_OK : NS_ERROR_FAILURE;
 }
 
+NS_IMETHODIMP
+MobileConnectionParent::NotifyDeviceIdentitiesChanged()
+{
+  // To be supported when bug 1222870 is required in m-c.
+  return NS_OK;
+}
+
 /******************************************************************************
  * PMobileConnectionRequestParent
  ******************************************************************************/
 
 void
 MobileConnectionRequestParent::ActorDestroy(ActorDestroyReason why)
 {
   mLive = false;
--- a/dom/mobilemessage/gonk/SmsService.js
+++ b/dom/mobilemessage/gonk/SmsService.js
@@ -1405,12 +1405,14 @@ SmsSendingScheduler.prototype = {
   notifyDataError: function(message) {},
   notifyCFStateChanged: function(action, reason, number, timeSeconds, serviceClass) {},
   notifyEmergencyCbModeChanged: function(active, timeoutMs) {},
   notifyOtaStatusChanged: function(status) {},
   notifyRadioStateChanged: function() {},
   notifyClirModeChanged: function(mode) {},
   notifyLastKnownNetworkChanged: function() {},
   notifyLastKnownHomeNetworkChanged: function() {},
-  notifyNetworkSelectionModeChanged: function() {}
+  notifyNetworkSelectionModeChanged: function() {},
+  notifyDeviceIdentitiesChanged: function() {}
+
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SmsService]);
--- a/dom/system/gonk/DataCallManager.js
+++ b/dom/system/gonk/DataCallManager.js
@@ -936,17 +936,19 @@ DataCallHandler.prototype = {
   notifyRadioStateChanged: function() {},
 
   notifyClirModeChanged: function(aMode) {},
 
   notifyLastKnownNetworkChanged: function() {},
 
   notifyLastKnownHomeNetworkChanged: function() {},
 
-  notifyNetworkSelectionModeChanged: function() {}
+  notifyNetworkSelectionModeChanged: function() {},
+
+  notifyDeviceIdentitiesChanged: function() {}
 };
 
 function DataCall(aClientId, aApnSetting, aDataCallHandler) {
   this.clientId = aClientId;
   this.dataCallHandler = aDataCallHandler;
   this.apnProfile = {
     apn: aApnSetting.apn,
     user: aApnSetting.user,
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -763,16 +763,23 @@ RadioInterface.prototype = {
                                                              message);
         break;
       case "operatorchange":
         gMobileConnectionService.notifyOperatorChanged(this.clientId, message);
         break;
       case "otastatuschange":
         gMobileConnectionService.notifyOtaStatusChanged(this.clientId, message.status);
         break;
+      case "deviceidentitieschange":
+        gMobileConnectionService.notifyDeviceIdentitiesChanged(this.clientId,
+                                                               message.deviceIdentities.imei,
+                                                               message.deviceIdentities.imeisv,
+                                                               message.deviceIdentities.esn,
+                                                               message.deviceIdentities.meid);
+        break;
       case "radiostatechange":
         // gRadioEnabledController should know the radio state for each client,
         // so notify gRadioEnabledController here.
         gRadioEnabledController.notifyRadioStateChanged(this.clientId,
                                                         message.radioState);
         break;
       case "cardstatechange":
         gIccService.notifyCardStateChanged(this.clientId,
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -159,22 +159,19 @@ RilObject.prototype = {
     this._waitingRadioTech = false;
 
     /**
      * Card state
      */
     this.cardState = GECKO_CARDSTATE_UNINITIALIZED;
 
     /**
-     * Strings
+     * Device Identities including IMEI, IMEISV, ESN and MEID.
      */
-    this.IMEI = null;
-    this.IMEISV = null;
-    this.ESN = null;
-    this.MEID = null;
+    this.deviceIdentities = null;
 
     /**
      * ICC information that is not exposed to Gaia.
      */
     this.iccInfoPrivate = {};
 
     /**
      * ICC information, such as MSISDN, MCC, MNC, SPN...etc.
@@ -1161,35 +1158,18 @@ RilObject.prototype = {
 
   /**
    * Get the signal strength.
    */
   getSignalStrength: function() {
     this.context.Buf.simpleRequest(REQUEST_SIGNAL_STRENGTH);
   },
 
-  getIMEI: function(options) {
-    // A device's IMEI can't change, so we only need to request it once.
-    if (this.IMEI) {
-      if (options && options.rilMessageType) {
-        options.imei = this.IMEI;
-        this.sendChromeMessage(options);
-      }
-      return;
-    }
-
-    this.context.Buf.simpleRequest(REQUEST_GET_IMEI, options);
-  },
-
-  getIMEISV: function() {
-    this.context.Buf.simpleRequest(REQUEST_GET_IMEISV);
-  },
-
   getDeviceIdentity: function() {
-    this.context.Buf.simpleRequest(REQUEST_DEVICE_IDENTITY);
+    this.deviceIdentities || this.context.Buf.simpleRequest(REQUEST_DEVICE_IDENTITY);
   },
 
   getBasebandVersion: function() {
     this.context.Buf.simpleRequest(REQUEST_BASEBAND_VERSION);
   },
 
   sendExitEmergencyCbModeRequest: function(options) {
     this.context.Buf.simpleRequest(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, options);
@@ -3132,22 +3112,16 @@ RilObject.prototype = {
     }
 
     // We should request SIM information when
     //  1. Radio state has been changed, so we are waiting for radioTech or
     //  2. isCdma is different from this._isCdma.
     if (this._waitingRadioTech || isCdma != this._isCdma) {
       this._isCdma = isCdma;
       this._waitingRadioTech = false;
-      if (this._isCdma) {
-        this.getDeviceIdentity();
-      } else {
-        this.getIMEI();
-        this.getIMEISV();
-      }
       this.getICCStatus();
     }
   },
 
   /**
    * Helper for returning the TOA for the given dial string.
    */
   _toaFromString: function(number) {
@@ -4364,38 +4338,18 @@ RilObject.prototype[REQUEST_QUERY_CALL_W
   options.serviceClass = enabled ? results[1] : ICC_SERVICE_CLASS_NONE;
   this.sendChromeMessage(options);
 };
 
 RilObject.prototype[REQUEST_SET_CALL_WAITING] = function REQUEST_SET_CALL_WAITING(length, options) {
   this.sendChromeMessage(options);
 };
 RilObject.prototype[REQUEST_SMS_ACKNOWLEDGE] = null;
-RilObject.prototype[REQUEST_GET_IMEI] = function REQUEST_GET_IMEI(length, options) {
-  this.IMEI = this.context.Buf.readString();
-
-  // If the request wasn't made by ril_worker itself, we send the IMEI back to
-  // chrome.
-  if (options.rilMessageType) {
-    if (options.errorMsg) {
-      this.sendChromeMessage(options);
-      return;
-    }
-
-    options.imei = this.IMEI;
-    this.sendChromeMessage(options);
-  }
-};
-RilObject.prototype[REQUEST_GET_IMEISV] = function REQUEST_GET_IMEISV(length, options) {
-  if (options.errorMsg) {
-    return;
-  }
-
-  this.IMEISV = this.context.Buf.readString();
-};
+RilObject.prototype[REQUEST_GET_IMEI] = null;
+RilObject.prototype[REQUEST_GET_IMEISV] = null;
 RilObject.prototype[REQUEST_ANSWER] = function REQUEST_ANSWER(length, options) {
   this.sendDefaultResponse(options);
 };
 RilObject.prototype[REQUEST_DEACTIVATE_DATA_CALL] = function REQUEST_DEACTIVATE_DATA_CALL(length, options) {
   this.sendChromeMessage(options);
 };
 RilObject.prototype[REQUEST_QUERY_FACILITY_LOCK] = function REQUEST_QUERY_FACILITY_LOCK(length, options) {
   if (options.errorMsg) {
@@ -4801,26 +4755,32 @@ RilObject.prototype[REQUEST_CDMA_SUBSCRI
   this.iccInfo.prlVersion = parseInt(result[4], 10);
 
   this.context.ICCUtilsHelper.handleICCInfoChange();
 };
 RilObject.prototype[REQUEST_CDMA_WRITE_SMS_TO_RUIM] = null;
 RilObject.prototype[REQUEST_CDMA_DELETE_SMS_ON_RUIM] = null;
 RilObject.prototype[REQUEST_DEVICE_IDENTITY] = function REQUEST_DEVICE_IDENTITY(length, options) {
   if (options.errorMsg) {
+    this.context.debug("Failed to get device identities:" + options.errorMsg);
     return;
   }
 
   let result = this.context.Buf.readStringList();
-
-  // The result[0] is for IMEI. (Already be handled in REQUEST_GET_IMEI)
-  // The result[1] is for IMEISV. (Already be handled in REQUEST_GET_IMEISV)
-  // They are both ignored.
-  this.ESN = result[2];
-  this.MEID = result[3];
+  this.deviceIdentities = {
+    imei: result[0] || null,
+    imeisv: result[1] || null,
+    esn: result[2] || null,
+    meid: result[3] || null,
+  };
+
+  this.sendChromeMessage({
+    rilMessageType: "deviceidentitieschange",
+    deviceIdentities: this.deviceIdentities
+  });
 };
 RilObject.prototype[REQUEST_EXIT_EMERGENCY_CALLBACK_MODE] = function REQUEST_EXIT_EMERGENCY_CALLBACK_MODE(length, options) {
   if (options.internal) {
     return;
   }
 
   this.sendChromeMessage(options);
 };
@@ -5056,36 +5016,33 @@ RilObject.prototype[UNSOLICITED_RESPONSE
   if (DEBUG) {
     this.context.debug("Radio state changed from '" + this.radioState +
                        "' to '" + newState + "'");
   }
   if (this.radioState == newState) {
     return;
   }
 
+  if (radioState !== RADIO_STATE_UNAVAILABLE) {
+    // Retrieve device identities once radio is available.
+    this.getDeviceIdentity();
+  }
+
   if (radioState == RADIO_STATE_ON) {
     // This value is defined in RIL v7, we will retrieve radio tech by another
     // request. We leave _isCdma untouched, and it will be set once we get the
     // radio technology.
     this._waitingRadioTech = true;
     this.getVoiceRadioTechnology();
   }
 
   if ((this.radioState == GECKO_RADIOSTATE_UNKNOWN ||
        this.radioState == GECKO_RADIOSTATE_DISABLED) &&
        newState == GECKO_RADIOSTATE_ENABLED) {
     // The radio became available, let's get its info.
-    if (!this._waitingRadioTech) {
-      if (this._isCdma) {
-        this.getDeviceIdentity();
-      } else {
-        this.getIMEI();
-        this.getIMEISV();
-      }
-    }
     this.getBasebandVersion();
     this.updateCellBroadcastConfig();
     if ((RILQUIRKS_DATA_REGISTRATION_ON_DEMAND ||
          RILQUIRKS_SUBSCRIPTION_CONTROL) &&
         this._attachDataRegistration) {
       this.setDataRegistration({attach: true});
     }
 
--- a/dom/telephony/gonk/TelephonyService.js
+++ b/dom/telephony/gonk/TelephonyService.js
@@ -354,17 +354,18 @@ MobileConnectionListener.prototype = {
   notifyDataError: function(message) {},
   notifyCFStateChanged: function(action, reason, number, timeSeconds, serviceClass) {},
   notifyEmergencyCbModeChanged: function(active, timeoutMs) {},
   notifyOtaStatusChanged: function(status) {},
   notifyRadioStateChanged: function() {},
   notifyClirModeChanged: function(mode) {},
   notifyLastKnownNetworkChanged: function() {},
   notifyLastKnownHomeNetworkChanged: function() {},
-  notifyNetworkSelectionModeChanged: function() {}
+  notifyNetworkSelectionModeChanged: function() {},
+  notifyDeviceIdentitiesChanged: function() {}
 };
 
 function TelephonyService() {
   this._numClients = gRadioInterfaceLayer.numRadioInterfaces;
   this._listeners = [];
 
   this._isDialing = false;
   this._cachedDialRequest = null;
@@ -1225,32 +1226,23 @@ TelephonyService.prototype = {
    * @param aClientId
    *        Client id.
    * @param aMmi
    *        Parsed MMI structure.
    * @param aCallback
    *        A nsITelephonyDialCallback object.
    */
   _getImeiMMI: function(aClientId, aMmi, aCallback) {
-    this._sendToRilWorker(aClientId, "getIMEI", {}, aResponse => {
-      if (aResponse.errorMsg) {
-        aCallback.notifyDialMMIError(aResponse.errorMsg);
-        return;
-      }
+    let connection = gGonkMobileConnectionService.getItemByServiceId(aClientId);
+    if (!connection.deviceIdentities || !connection.deviceIdentities.imei) {
+      aCallback.notifyDialMMIError(RIL.GECKO_ERROR_GENERIC_FAILURE);
+      return;
+    }
 
-      // We expect to have an IMEI at this point if the request was supposed
-      // to query for the IMEI, so getting a successful reply from the RIL
-       // without containing an actual IMEI number is considered an error.
-      if (!aResponse.imei) {
-        aCallback.notifyDialMMIError(RIL.GECKO_ERROR_GENERIC_FAILURE);
-        return;
-      }
-
-      aCallback.notifyDialMMISuccess(aResponse.imei);
-    });
+    aCallback.notifyDialMMISuccess(connection.deviceIdentities.imei);
   },
 
   /**
    * Handle CLIP MMI code.
    *
    * @param aClientId
    *        Client id.
    * @param aMmi