Bug 849185 - Disable the airplane mode when an emergency number is dialed. r=allstars.chh
authorHsin-Yi Tsai <htsai@mozilla.com>
Mon, 18 Mar 2013 17:03:49 +0800
changeset 126670 c59a33280850872064deda04f2a84c2d2120dbdf
parent 126669 d470390898dffab895ea781aa372237579f43179
child 126671 2c10a759015fcd3796fa0f21897de39207ee01a2
push idunknown
push userunknown
push dateunknown
reviewersallstars.chh
bugs849185
milestone22.0a1
Bug 849185 - Disable the airplane mode when an emergency number is dialed. r=allstars.chh
dom/system/gonk/RadioInterfaceLayer.js
dom/system/gonk/ril_worker.js
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -710,16 +710,20 @@ RadioInterfaceLayer.prototype = {
         this.handleQueryCallForwardStatus(message);
         break;
       case "setCallForward":
         this.handleSetCallForward(message);
         break;
       case "setCellBroadcastSearchList":
         this.handleSetCellBroadcastSearchList(message);
         break;
+      case "setRadioEnabled":
+        let lock = gSettingsService.createLock();
+        lock.set("ril.radio.disabled", !message.on, null, null);
+        break;
       default:
         throw new Error("Don't know about this message type: " +
                         message.rilMessageType);
     }
   },
 
   _messageManagerByRequest: null,
   saveRequestTarget: function saveRequestTarget(msg) {
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -1368,17 +1368,17 @@ let RIL = {
 
   /**
    * Request the phone's radio power to be switched on or off.
    *
    * @param on
    *        Boolean indicating the desired power state.
    */
   setRadioPower: function setRadioPower(options) {
-    Buf.newParcel(REQUEST_RADIO_POWER);
+    Buf.newParcel(REQUEST_RADIO_POWER, options);
     Buf.writeUint32(1);
     Buf.writeUint32(options.on ? 1 : 0);
     Buf.sendParcel();
   },
 
   /**
    * Set call waiting status.
    *
@@ -1598,50 +1598,88 @@ let RIL = {
     Buf.simpleRequest(REQUEST_DEVICE_IDENTITY);
   },
 
   getBasebandVersion: function getBasebandVersion() {
     Buf.simpleRequest(REQUEST_BASEBAND_VERSION);
   },
 
   /**
+   * 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 the phone.
    *
    * @param number
    *        String containing the number to dial.
    * @param clirMode
    *        Integer doing something XXX TODO
    * @param uusInfo
    *        Integer doing something XXX TODO
    */
   dial: function dial(options) {
-    let dial_request_type = REQUEST_DIAL;
+    let onerror = (function onerror(errorMsg) {
+      options.callIndex = -1;
+      options.rilMessageType = "callError";
+      options.errorMsg = errorMsg;
+      this.sendDOMMessage(options);
+    }).bind(this);
+
+    if (this._isEmergencyNumber(options.number)) {
+      this.dialEmergencyNumber(options, onerror);
+    } else {
+      this.dialNonEmergencyNumber(options, onerror);
+    }
+  },
+
+  dialNonEmergencyNumber: function dialNonEmergencyNumber(options, onerror) {
+    if (this.radioState == GECKO_RADIOSTATE_OFF) {
+      // Notify error in establishing the call without radio.
+      onerror(GECKO_ERROR_RADIO_NOT_AVAILABLE);
+      return;
+    }
+
     if (this.voiceRegistrationState.emergencyCallsOnly ||
         options.isDialEmergency) {
-      if (!this._isEmergencyNumber(options.number)) {
-        // Notify error in establishing the call with an invalid number.
-        options.callIndex = -1;
-        options.rilMessageType = "callError";
-        options.errorMsg =
-          RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_UNOBTAINABLE_NUMBER];
-        this.sendDOMMessage(options);
-        return;
-      }
-
-      if (RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL) {
-        dial_request_type = REQUEST_DIAL_EMERGENCY_CALL;
-      }
-    } else {
-      if (this._isEmergencyNumber(options.number) &&
-          RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL) {
-        dial_request_type = REQUEST_DIAL_EMERGENCY_CALL;
-      }
-    }
-
-    let token = Buf.newParcel(dial_request_type);
+      onerror(RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_UNOBTAINABLE_NUMBER]);
+      return;
+    }
+
+    options.request = REQUEST_DIAL;
+    this.sendDialRequest(options);
+  },
+
+  dialEmergencyNumber: function dialEmergencyNumber(options, onerror) {
+    options.request = RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL ?
+                      REQUEST_DIAL_EMERGENCY_CALL : REQUEST_DIAL;
+
+    if (this.radioState == GECKO_RADIOSTATE_OFF) {
+      if (DEBUG) debug("Automatically enable radio for an emergency call.");
+
+      if (!this.cachedDialRequest) {
+        this.cachedDialRequest = {};
+      }
+      this.cachedDialRequest.onerror = onerror;
+      this.cachedDialRequest.callback = this.sendDialRequest.bind(this, options);
+
+      // Change radio setting value in settings DB to enable radio.
+      this.sendDOMMessage({rilMessageType: "setRadioEnabled", on: true});
+      return;
+    }
+
+    this.sendDialRequest(options);
+  },
+
+  sendDialRequest: function sendDialRequest(options) {
+    let token = Buf.newParcel(options.request);
     Buf.writeString(options.number);
     Buf.writeUint32(options.clirMode || 0);
     Buf.writeUint32(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.
     Buf.writeUint32(0);
     Buf.sendParcel();
   },
@@ -4508,16 +4546,22 @@ RIL[REQUEST_SIGNAL_STRENGTH] = function 
     obj.lteRSSNR = Buf.readUint32();
     // Channel Quality Indicator, valid values are 0 to 15.
     obj.lteCQI = Buf.readUint32();
   }
 
   if (DEBUG) debug("Signal strength " + JSON.stringify(obj));
   obj.rilMessageType = "signalstrengthchange";
   this.sendDOMMessage(obj);
+
+  if (this.cachedDialRequest && obj.gsmDBM && obj.gsmRelative) {
+    // Radio is ready for making the cached emergency call.
+    this.cachedDialRequest.callback();
+    this.cachedDialRequest = null;
+  }
 };
 RIL[REQUEST_VOICE_REGISTRATION_STATE] = function REQUEST_VOICE_REGISTRATION_STATE(length, options) {
   this._receivedNetworkInfo(NETWORK_INFO_VOICE_REGISTRATION_STATE);
 
   if (options.rilRequestError) {
     return;
   }
 
@@ -4544,16 +4588,21 @@ RIL[REQUEST_OPERATOR] = function REQUEST
   }
 
   let operatorData = Buf.readStringList();
   if (DEBUG) debug("Operator: " + operatorData);
   this._processOperator(operatorData);
 };
 RIL[REQUEST_RADIO_POWER] = function REQUEST_RADIO_POWER(length, options) {
   if (options.rilRequestError) {
+    if (this.cachedDialRequest && options.on) {
+      // Turning on radio fails. Notify the error of making an emergency call.
+      this.cachedDialRequest.onerror(GECKO_ERROR_RADIO_NOT_AVAILABLE);
+      this.cachedDialRequest = null;
+    }
     return;
   }
 
   if (this._isInitialRadioState) {
     this._isInitialRadioState = false;
   }
 };
 RIL[REQUEST_DTMF] = null;