Bug 1137093 - Part 10: Turn on radio for emergency call in TelephonyService. r=hsinyi
authorSzu-Yu Chen [:aknow] <szchen@mozilla.com>
Tue, 24 Mar 2015 18:04:49 +0800
changeset 264433 db752db6d34a2a6c4214c5c060c56471fa8da7b5
parent 264432 00d5d6ee14a06325d35c41d0477857a8496ea786
child 264434 7690d9e5ba8a4d485392dd3a88833b6e3d06a2f4
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershsinyi
bugs1137093
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1137093 - Part 10: Turn on radio for emergency call in TelephonyService. r=hsinyi
dom/system/gonk/ril_worker.js
dom/telephony/gonk/TelephonyService.js
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -1419,76 +1419,41 @@ RilObject.prototype = {
     if (!options) {
       options = {internal: true};
     }
     this._cancelEmergencyCbModeTimeout();
     this.sendExitEmergencyCbModeRequest(options);
   },
 
   /**
-   * Cache the request for making an emergency call when radio is off. The
-   * request shall include two types of callback functions. 'callback' is
-   * called when radio is ready, and 'onerror' is called when turning radio
-   * on fails.
-   */
-  cachedDialRequest : null,
-
-  /**
    * Dial a non-emergency number.
    *
    * @param isEmergency
    *        Whether the number is an emergency number.
    * @param number
    *        String containing the number to dial.
    * @param clirMode
    *        Integer for showing/hidding the caller Id to the called party.
    * @param uusInfo
    *        Integer doing something XXX TODO
    */
   dial: function(options) {
-    let onerror = (function onerror(options, errorMsg) {
-      options.success = false;
-      options.errorMsg = errorMsg;
-      this.sendChromeMessage(options);
-    }).bind(this, options);
-
-    let isRadioOff = (this.radioState === GECKO_RADIOSTATE_DISABLED);
-
     if (options.isEmergency) {
       options.request = RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL ?
                         REQUEST_DIAL_EMERGENCY_CALL : REQUEST_DIAL;
 
-      if (isRadioOff) {
-        if (DEBUG) {
-          this.context.debug("Automatically enable radio for an emergency call.");
-        }
-
-        this.cachedDialRequest = {
-          callback: this.dialInternal.bind(this, options),
-          onerror: onerror
-        };
-
-        this.setRadioEnabled({enabled: true});
-        return;
-      }
-
-      this.dialInternal(options);
     } else {
+      options.request = REQUEST_DIAL;
+
       // Exit emergency callback mode when user dial a non-emergency call.
       if (this._isInEmergencyCbMode) {
         this.exitEmergencyCbMode();
       }
-
-      options.request = REQUEST_DIAL;
-
-      this.dialInternal(options);
-    }
-  },
-
-  dialInternal: function(options) {
+    }
+
     this.telephonyRequestQueue.push(options.request, () => {
       let Buf = this.context.Buf;
       Buf.newParcel(options.request, options);
       Buf.writeString(options.number);
       Buf.writeInt32(options.clirMode || 0);
       Buf.writeInt32(options.uusInfo || 0);
       // TODO Why do we need this extra 0? It was put it in to make this
       // match the format of the binary message.
@@ -3353,22 +3318,16 @@ RilObject.prototype = {
           let signalLevel = this._processSignalLevel(signalStrength, -110, -85);
           info.voice.relSignalStrength = info.data.relSignalStrength = signalLevel;
         }
       }
     }
 
     info.rilMessageType = "signalstrengthchange";
     this._sendNetworkInfoMessage(NETWORK_INFO_SIGNAL, info);
-
-    if (this.cachedDialRequest && info.voice.signalStrength) {
-      // Radio is ready for making the cached emergency call.
-      this.cachedDialRequest.callback();
-      this.cachedDialRequest = null;
-    }
   },
 
   /**
    * Process the network registration flags.
    *
    * @return true if the state changed, false otherwise.
    */
   _processCREG: function(curState, newState) {
@@ -4809,25 +4768,16 @@ RilObject.prototype[REQUEST_VOICE_REGIST
   if (options.rilRequestError) {
     return;
   }
 
   let state = this.context.Buf.readStringList();
   if (DEBUG) this.context.debug("voice registration state: " + state);
 
   this._processVoiceRegistrationState(state);
-
-  if (this.cachedDialRequest &&
-       (this.voiceRegistrationState.emergencyCallsOnly ||
-        this.voiceRegistrationState.connected) &&
-      this.voiceRegistrationState.radioTech != NETWORK_CREG_TECH_UNKNOWN) {
-    // Radio is ready for making the cached emergency call.
-    this.cachedDialRequest.callback();
-    this.cachedDialRequest = null;
-  }
 };
 RilObject.prototype[REQUEST_DATA_REGISTRATION_STATE] = function REQUEST_DATA_REGISTRATION_STATE(length, options) {
   this._receivedNetworkInfo(NETWORK_INFO_DATA_REGISTRATION_STATE);
 
   if (options.rilRequestError) {
     return;
   }
 
@@ -4841,29 +4791,17 @@ RilObject.prototype[REQUEST_OPERATOR] = 
     return;
   }
 
   let operatorData = this.context.Buf.readStringList();
   if (DEBUG) this.context.debug("Operator: " + operatorData);
   this._processOperator(operatorData);
 };
 RilObject.prototype[REQUEST_RADIO_POWER] = function REQUEST_RADIO_POWER(length, options) {
-  if (options.rilMessageType == null) {
-    // The request was made by ril_worker itself.
-    if (options.rilRequestError) {
-      if (this.cachedDialRequest && options.enabled) {
-        // Turning on radio fails. Notify the error of making an emergency call.
-        this.cachedDialRequest.onerror(GECKO_ERROR_RADIO_NOT_AVAILABLE);
-        this.cachedDialRequest = null;
-      }
-    }
-    return;
-  }
-
-  this.sendChromeMessage(options);
+  this.sendDefaultResponse(options);
 };
 RilObject.prototype[REQUEST_DTMF] = null;
 RilObject.prototype[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS(length, options) {
   this._processSmsSendResult(length, options);
 };
 RilObject.prototype[REQUEST_SEND_SMS_EXPECT_MORE] = null;
 
 RilObject.prototype.readSetupDataCall_v5 = function readSetupDataCall_v5(options) {
--- a/dom/telephony/gonk/TelephonyService.js
+++ b/dom/telephony/gonk/TelephonyService.js
@@ -180,16 +180,35 @@ Call.prototype = {
   isOutgoing: true,
   isEmergency: false,
   isConference: false,
   isSwitchable: true,
   isMergeable: true,
   started: null
 };
 
+function MobileConnectionListener() {}
+MobileConnectionListener.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionListener]),
+
+  // nsIMobileConnectionListener
+
+  notifyVoiceChanged: function() {},
+  notifyDataChanged: function() {},
+  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() {}
+};
+
 function TelephonyService() {
   this._numClients = gRadioInterfaceLayer.numRadioInterfaces;
   this._listeners = [];
 
   this._isDialing = false;
   this._cachedDialRequest = null;
   this._currentCalls = {};
   this._currentConferenceState = nsITelephonyService.CALL_STATE_UNKNOWN;
@@ -287,17 +306,18 @@ TelephonyService.prototype = {
     return !this._isGsmTechGroup(type);
   },
 
   _isEmergencyOnly: function(aClientId) {
     return gGonkMobileConnectionService.getItemByServiceId(aClientId).voice.emergencyCallsOnly;
   },
 
   _isRadioOn: function(aClientId) {
-    return gGonkMobileConnectionService.getItemByServiceId(aClientId).radioState === nsIMobileConnection.MOBILE_RADIO_STATE_ENABLED;
+    let connection = gGonkMobileConnectionService.getItemByServiceId(aClientId);
+    return connection.radioState === nsIMobileConnection.MOBILE_RADIO_STATE_ENABLED;
   },
 
   // An array of nsITelephonyListener instances.
   _listeners: null,
   _notifyAllListeners: function(aMethodName, aArgs) {
     let listeners = this._listeners.slice();
     for (let listener of listeners) {
       if (this._listeners.indexOf(listener) == -1) {
@@ -681,16 +701,42 @@ TelephonyService.prototype = {
     if (isEmergency) {
       // Automatically select a proper clientId for emergency call.
       aClientId = gRadioInterfaceLayer.getClientIdForEmergencyCall() ;
       if (aClientId === -1) {
         if (DEBUG) debug("Error: No client is avaialble for emergency call.");
         aCallback.notifyError(DIAL_ERROR_INVALID_STATE_ERROR);
         return;
       }
+
+      // Radio is off. Turn it on first.
+      if (!this._isRadioOn(aClientId)) {
+        let connection = gGonkMobileConnectionService.getItemByServiceId(aClientId);
+        let listener = new MobileConnectionListener();
+
+        listener.notifyRadioStateChanged = () => {
+          if (this._isRadioOn(aClientId)) {
+            this._dialCall(aClientId, aNumber, undefined, aCallback);
+            connection.unregisterListener(listener);
+          }
+        };
+        connection.registerListener(listener);
+
+        // Turn on radio.
+        connection.setRadioEnabled(true, {
+          QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionCallback]),
+          notifySuccess: () => {},
+          notifyError: aErrorMsg => {
+            connection.unregisterListener(listener);
+            aCallback.notifyError(DIAL_ERROR_RADIO_NOT_AVAILABLE);
+          }
+        });
+
+        return;
+      }
     }
 
     let options = {
       isEmergency: isEmergency,
       number: aNumber,
       clirMode: aClirMode
     };