Bug 1093014 - Part 1: Refactoring. r=hsinyi
authorSzu-Yu Chen [:aknow] <szchen@mozilla.com>
Thu, 11 Dec 2014 16:27:44 +0800
changeset 235893 95e8b9ca4957667b42349b3d94e513eab9f15d39
parent 235892 8d7362ccdb61904f97a66da5b06d1c1b01cb0f3b
child 235894 a9e9218619c95e5fc4fa94318aec51ef7c700bc7
push id7472
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 20:36:27 +0000
treeherdermozilla-aurora@300ca104f8fb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershsinyi
bugs1093014
milestone37.0a1
Bug 1093014 - Part 1: Refactoring. r=hsinyi
dom/system/gonk/ril_worker.js
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -217,20 +217,19 @@ const TELEPHONY_REQUESTS = [
   REQUEST_HANGUP,
   REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
   REQUEST_HANGUP_WAITING_OR_BACKGROUND,
   REQUEST_SEPARATE_CONNECTION,
   REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE,
   REQUEST_UDUB
 ];
 
-function TelephonyRequestEntry(request, action, options) {
+function TelephonyRequestEntry(request, callback) {
   this.request = request;
-  this.action = action;
-  this.options = options;
+  this.callback = callback;
 }
 
 function TelephonyRequestQueue(ril) {
   this.ril = ril;
   this.currentQueue = null;  // Point to the current running queue.
 
   this.queryQueue = [];
   this.controlQueue = [];
@@ -269,43 +268,43 @@ TelephonyRequestQueue.prototype = {
     this.currentQueue = queue;
     for (let entry of queue) {
       this._executeEntry(entry);
     }
   },
 
   _executeEntry: function(entry) {
     if (DEBUG) this.debug("execute " + this._getRequestName(entry.request));
-    entry.action.call(this.ril, entry.options);
+    entry.callback();
   },
 
   _getRequestName: function(request) {
     let method = this.ril[request];
     return (typeof method === 'function') ? method.name : "";
   },
 
   debug: function(msg) {
     this.ril.context.debug("[TeleQ] " + msg);
   },
 
   isValidRequest: function(request) {
     return TELEPHONY_REQUESTS.indexOf(request) !== -1;
   },
 
-  push: function(request, action, options) {
+  push: function(request, callback) {
     if (!this.isValidRequest(request)) {
       if (DEBUG) {
         this.debug("Error: " + this._getRequestName(request) +
                    " is not a telephony request");
       }
       return;
     }
 
     if (DEBUG) this.debug("push " + this._getRequestName(request));
-    let entry = new TelephonyRequestEntry(request, action, options);
+    let entry = new TelephonyRequestEntry(request, callback);
     let queue = this._getQueue(request);
     queue.push(entry);
 
     // Try to run the request.
     if (this.currentQueue === queue) {
       this._executeEntry(entry);
     } else if (!this.currentQueue) {
       this._startQueue(queue);
@@ -1541,28 +1540,16 @@ RilObject.prototype = {
     let numeric = (options.mcc && options.mnc) ? options.mcc + options.mnc : null;
     let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SET_NETWORK_SELECTION_MANUAL, options);
     Buf.writeString(numeric);
     Buf.sendParcel();
   },
 
   /**
-   * Get current calls.
-   */
-  getCurrentCalls: function() {
-    this.telephonyRequestQueue.push(REQUEST_GET_CURRENT_CALLS,
-                                    this.sendRilRequestGetCurrentCalls, null);
-  },
-
-  sendRilRequestGetCurrentCalls: function() {
-    this.context.Buf.simpleRequest(REQUEST_GET_CURRENT_CALLS);
-  },
-
-  /**
    * Get the signal strength.
    */
   getSignalStrength: function() {
     this.context.Buf.simpleRequest(REQUEST_SIGNAL_STRENGTH);
   },
 
   getIMEI: function(options) {
     this.context.Buf.simpleRequest(REQUEST_GET_IMEI, options);
@@ -1626,107 +1613,80 @@ RilObject.prototype = {
       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.dialEmergencyNumber.bind(this, options),
+          callback: this.dialInternal.bind(this, options),
           onerror: onerror
         };
+
         this.setRadioEnabled({enabled: true});
         return;
       }
 
-      this.dialEmergencyNumber(options);
+      this.dialInternal(options);
     } else {
       // Notify error in establishing the call without radio.
       if (isRadioOff) {
         onerror(GECKO_ERROR_RADIO_NOT_AVAILABLE);
         return;
       }
 
       // Shouldn't dial a non-emergency number by dialEmergency.
       if (options.isDialEmergency || this.voiceRegistrationState.emergencyCallsOnly) {
         onerror(GECKO_CALL_ERROR_BAD_NUMBER);
         return;
       }
 
-      this.dialNonEmergencyNumber(options);
-    }
-  },
-
-  /**
-   * Dial a non-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
-   */
-  dialNonEmergencyNumber: function(options) {
-    // Exit emergency callback mode when user dial a non-emergency call.
-    if (this._isInEmergencyCbMode) {
-      this.exitEmergencyCbMode();
-    }
-
-    options.request = REQUEST_DIAL;
-    this.sendDialRequest(options);
-  },
-
-  /**
-   * Dial 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
-   */
-  dialEmergencyNumber: function(options) {
-    options.request = RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL ?
-                      REQUEST_DIAL_EMERGENCY_CALL : REQUEST_DIAL;
-    this.sendDialRequest(options);
-  },
-
-  sendDialRequest: function(options) {
+      // 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) {
+    // Make a Cdma 3way call.
     if (this._isCdma && Object.keys(this.currentCalls).length == 1) {
-      // Make a Cdma 3way call.
       options.featureStr = options.number;
-      this.sendCdmaFlashCommand(options);
-    } else {
-      this.telephonyRequestQueue.push(options.request, this.sendRilRequestDial,
-                                      options);
-    }
-  },
-
-  sendRilRequestDial: function(options) {
-    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.
-    Buf.writeInt32(0);
-    Buf.sendParcel();
-  },
-
-  sendCdmaFlashCommand: function(options) {
+      this.cdmaFlash(options);
+      return;
+    }
+
+    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.
+      Buf.writeInt32(0);
+      Buf.sendParcel();
+    });
+  },
+
+  cdmaFlash: function(options) {
     let Buf = this.context.Buf;
     options.isCdma = true;
     options.request = REQUEST_CDMA_FLASH;
     Buf.newParcel(options.request, options);
     Buf.writeString(options.featureStr);
     Buf.sendParcel();
   },
 
@@ -1748,109 +1708,82 @@ RilObject.prototype = {
   hangUp: function(options) {
     let call = this.currentCalls[options.callIndex];
     if (!call) {
       return;
     }
 
     call.hangUpLocal = true;
     if (call.state === CALL_STATE_HOLDING) {
-      this.sendHangUpBackgroundRequest();
+      this.hangUpBackground(options);
     } else {
-      this.sendHangUpRequest(options);
-    }
-  },
-
-  sendHangUpRequest: function(options) {
-    this.telephonyRequestQueue.push(REQUEST_HANGUP, this.sendRilRequestHangUp,
-                                    options);
-  },
-
-  sendRilRequestHangUp: function(options) {
-    let Buf = this.context.Buf;
-    Buf.newParcel(REQUEST_HANGUP, options);
-    Buf.writeInt32(1);
-    Buf.writeInt32(options.callIndex);
-    Buf.sendParcel();
-  },
-
-  sendHangUpForegroundRequest: function(options) {
-    this.telephonyRequestQueue.push(REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
-                                    this.sendRilRequestHangUpForeground,
-                                    options);
-  },
-
-  sendRilRequestHangUpForeground: function(options) {
-    this.context.Buf.simpleRequest(REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
-                                   options);
-  },
-
-  sendHangUpBackgroundRequest: function(options) {
-    this.telephonyRequestQueue.push(REQUEST_HANGUP_WAITING_OR_BACKGROUND,
-                                    this.sendRilRequestHangUpWaiting, options);
-  },
-
-  sendRilRequestHangUpWaiting: function(options) {
-    this.context.Buf.simpleRequest(REQUEST_HANGUP_WAITING_OR_BACKGROUND,
-                                   options);
-  },
-
-  /**
-   * Mute or unmute the radio.
-   *
-   * @param mute
-   *        Boolean to indicate whether to mute or unmute the radio.
-   */
-  setMute: function(options) {
-    let Buf = this.context.Buf;
-    Buf.newParcel(REQUEST_SET_MUTE);
-    Buf.writeInt32(1);
-    Buf.writeInt32(options.muted ? 1 : 0);
-    Buf.sendParcel();
+      this.telephonyRequestQueue.push(REQUEST_HANGUP, () => {
+        let Buf = this.context.Buf;
+        Buf.newParcel(REQUEST_HANGUP, options);
+        Buf.writeInt32(1);
+        Buf.writeInt32(options.callIndex);
+        Buf.sendParcel();
+      });
+    }
+  },
+
+  hangUpForeground: function(options) {
+    this.telephonyRequestQueue.push(REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND, () => {
+      this.context.Buf.simpleRequest(REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
+                                     options);
+    });
+  },
+
+  hangUpBackground: function(options) {
+    this.telephonyRequestQueue.push(REQUEST_HANGUP_WAITING_OR_BACKGROUND, () => {
+      this.context.Buf.simpleRequest(REQUEST_HANGUP_WAITING_OR_BACKGROUND,
+                                     options);
+    });
+  },
+
+  switchActiveCall: function(options) {
+    this.telephonyRequestQueue.push(REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, () => {
+      this.context.Buf.simpleRequest(REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE,
+                                     options);
+    });
+  },
+
+  udub: function(options) {
+    this.telephonyRequestQueue.push(REQUEST_UDUB, () => {
+      this.context.Buf.simpleRequest(REQUEST_UDUB, options);
+    });
   },
 
   /**
    * Answer an incoming/waiting call.
    *
    * @param callIndex
    *        Call index of the call to answer.
    */
   answerCall: function(options) {
+    let call = this.currentCalls[options.callIndex];
+    if (!call) {
+      return;
+    }
+
     // Check for races. Since we dispatched the incoming/waiting call
     // notification the incoming/waiting call may have changed. The main
     // thread thinks that it is answering the call with the given index,
     // so only answer if that is still incoming/waiting.
-    let call = this.currentCalls[options.callIndex];
-    if (!call) {
-      return;
-    }
-
     switch (call.state) {
       case CALL_STATE_INCOMING:
-        this.telephonyRequestQueue.push(REQUEST_ANSWER, this.sendRilRequestAnswer,
-                                        null);
+        this.telephonyRequestQueue.push(REQUEST_ANSWER, () => {
+          this.context.Buf.simpleRequest(REQUEST_ANSWER);
+        });
         break;
       case CALL_STATE_WAITING:
         // Answer the waiting (second) call, and hold the first call.
-        this.sendSwitchWaitingRequest();
-        break;
-    }
-  },
-
-  sendRilRequestAnswer: function() {
-    this.context.Buf.simpleRequest(REQUEST_ANSWER);
-  },
-
-  sendSwitchWaitingRequest: function() {
-    this.telephonyRequestQueue.push(REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE,
-                                    this.sendRilRequestSwitch, null);
-  },
-
-  sendRilRequestSwitch: function() {
-    this.context.Buf.simpleRequest(REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE);
+        this.switchActiveCall(options);
+        break;
+    }
   },
 
   /**
    * Reject an incoming/waiting call.
    *
    * @param callIndex
    *        Call index of the call to reject.
    */
@@ -1863,149 +1796,164 @@ RilObject.prototype = {
     if (!call) {
       return;
     }
 
     call.hangUpLocal = true;
 
     if (this._isCdma) {
       // AT+CHLD=0 means "release held or UDUB."
-      this.sendHangUpBackgroundRequest();
+      this.hangUpBackground(options);
       return;
     }
 
     switch (call.state) {
       case CALL_STATE_INCOMING:
-        this.telephonyRequestQueue.push(REQUEST_UDUB, this.sendRilRequestUdub,
-                                        null);
+        this.udub(options);
         break;
       case CALL_STATE_WAITING:
         // Reject the waiting (second) call, and remain the first call.
-        this.sendHangUpBackgroundRequest();
-        break;
-    }
-  },
-
-  sendRilRequestUdub: function() {
-    this.context.Buf.simpleRequest(REQUEST_UDUB);
+        this.hangUpBackground(options);
+        break;
+    }
   },
 
   holdCall: function(options) {
     let call = this.currentCalls[options.callIndex];
     if (!call) {
       options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
       options.success = false;
       this.sendChromeMessage(options);
       return;
     }
 
     let Buf = this.context.Buf;
     if (this._isCdma) {
       options.featureStr = "";
-      this.sendCdmaFlashCommand(options);
+      this.cdmaFlash(options);
     } else if (call.state == CALL_STATE_ACTIVE) {
-      this.sendSwitchWaitingRequest();
+      this.switchActiveCall(options);
     }
   },
 
   resumeCall: function(options) {
     let call = this.currentCalls[options.callIndex];
     if (!call) {
       options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
       options.success = false;
       this.sendChromeMessage(options);
       return;
     }
 
     let Buf = this.context.Buf;
     if (this._isCdma) {
       options.featureStr = "";
-      this.sendCdmaFlashCommand(options);
+      this.cdmaFlash(options);
     } else if (call.state == CALL_STATE_HOLDING) {
-      this.sendSwitchWaitingRequest();
+      this.switchActiveCall(options);
     }
   },
 
   conferenceCall: function(options) {
     if (this._isCdma) {
       options.featureStr = "";
-      this.sendCdmaFlashCommand(options);
-    } else {
-      this.telephonyRequestQueue.push(REQUEST_CONFERENCE,
-                                      this.sendRilRequestConference, options);
-    }
-  },
-
-  sendRilRequestConference: function(options) {
-    this.context.Buf.simpleRequest(REQUEST_CONFERENCE, options);
+      this.cdmaFlash(options);
+      return;
+    }
+
+    this.telephonyRequestQueue.push(REQUEST_CONFERENCE, () => {
+      this.context.Buf.simpleRequest(REQUEST_CONFERENCE, options);
+    });
   },
 
   separateCall: function(options) {
     let call = this.currentCalls[options.callIndex];
     if (!call) {
       options.errorName = "removeError";
       options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
       options.success = false;
       this.sendChromeMessage(options);
       return;
     }
 
     if (this._isCdma) {
       options.featureStr = "";
-      this.sendCdmaFlashCommand(options);
-    } else {
-      this.telephonyRequestQueue.push(REQUEST_SEPARATE_CONNECTION,
-                                     this.sendRilRequestSeparateConnection,
-                                     options);
-    }
- },
-
-  sendRilRequestSeparateConnection: function(options) {
-    let Buf = this.context.Buf;
-    Buf.newParcel(REQUEST_SEPARATE_CONNECTION, options);
-    Buf.writeInt32(1);
-    Buf.writeInt32(options.callIndex);
-    Buf.sendParcel();
+      this.cdmaFlash(options);
+      return;
+    }
+
+    this.telephonyRequestQueue.push(REQUEST_SEPARATE_CONNECTION, () => {
+      let Buf = this.context.Buf;
+      Buf.newParcel(REQUEST_SEPARATE_CONNECTION, options);
+      Buf.writeInt32(1);
+      Buf.writeInt32(options.callIndex);
+      Buf.sendParcel();
+    });
   },
 
   hangUpConference: function(options) {
     if (this._isCdma) {
       // In cdma, ril only maintains one call index.
       let call = this.currentCalls[1];
       if (!call) {
         options.success = false;
         options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
         this.sendChromeMessage(options);
         return;
       }
-      call.hangUpLocal = true;
-      this.sendHangUpRequest(1);
+
+      options.callIndex = 1;
+      this.hangUp(options);
+      return;
+    }
+
+    if (this.currentConferenceState === CALL_STATE_ACTIVE) {
+      this.hangUpForeground(options);
     } else {
-      if (this.currentConferenceState === CALL_STATE_ACTIVE) {
-        this.sendHangUpForegroundRequest(options);
-      } else {
-        this.sendHangUpBackgroundRequest(options);
-      }
-    }
-  },
-
-  holdConference: function() {
+      this.hangUpBackground(options);
+    }
+  },
+
+  holdConference: function(options) {
+    if (this._isCdma) {
+      return;
+    }
+
+    this.switchActiveCall(options);
+  },
+
+  resumeConference: function(options) {
     if (this._isCdma) {
       return;
     }
 
-    this.sendSwitchWaitingRequest();
-  },
-
-  resumeConference: function() {
-    if (this._isCdma) {
-      return;
-    }
-
-    this.sendSwitchWaitingRequest();
+    this.switchActiveCall(options);
+  },
+
+  /**
+   * Get current calls.
+   */
+  getCurrentCalls: function() {
+    this.telephonyRequestQueue.push(REQUEST_GET_CURRENT_CALLS, () => {
+      this.context.Buf.simpleRequest(REQUEST_GET_CURRENT_CALLS);
+    });
+  },
+
+  /**
+   * Mute or unmute the radio.
+   *
+   * @param mute
+   *        Boolean to indicate whether to mute or unmute the radio.
+   */
+  setMute: function(options) {
+    let Buf = this.context.Buf;
+    Buf.newParcel(REQUEST_SET_MUTE);
+    Buf.writeInt32(1);
+    Buf.writeInt32(options.muted ? 1 : 0);
+    Buf.sendParcel();
   },
 
   /**
    * Send an SMS.
    *
    * The `options` parameter object should contain the following attributes:
    *
    * @param number
@@ -2682,20 +2630,16 @@ RilObject.prototype = {
   sendUSSD: function(options) {
     if (options.checkSession && !this._ussdSession) {
       options.success = false;
       options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
       this.sendChromeMessage(options);
       return;
     }
 
-    this.sendRilRequestSendUSSD(options);
-  },
-
-  sendRilRequestSendUSSD: function(options) {
     let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SEND_USSD, options);
     Buf.writeString(options.ussd);
     Buf.sendParcel();
   },
 
   /**
    * Cancel pending USSD.
@@ -3931,16 +3875,18 @@ RilObject.prototype = {
 
     return [CALL_STATE_UNKNOWN, new Set()];
   },
 
   /**
    * Helpers for processing call state changes.
    */
   _processCalls: function(newCalls, failCause) {
+    if (DEBUG) this.context.debug("_processCalls: " + JSON.stringify(newCalls));
+
     // Let's get the failCause first if there are removed calls. Otherwise, we
     // need to trigger another async request when removing call and it cause
     // the order of callDisconnected and conferenceCallStateChanged
     // unpredictable.
     if (failCause === undefined) {
       for each (let currentCall in this.currentCalls) {
         if (!newCalls[currentCall.callIndex] && !currentCall.hangUpLocal) {
           this.getFailCauseCode((function(newCalls, failCause) {
@@ -5459,27 +5405,30 @@ RilObject.prototype[REQUEST_GET_IMSI] = 
     this.context.debug("IMSI: " + this.iccInfoPrivate.imsi);
   }
 
   options.rilMessageType = "iccimsi";
   options.imsi = this.iccInfoPrivate.imsi;
   this.sendChromeMessage(options);
 };
 RilObject.prototype[REQUEST_HANGUP] = function REQUEST_HANGUP(length, options) {
-  options.success = options.rilRequestError === 0;
+  options.success = (options.rilRequestError === 0);
   options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   this.sendChromeMessage(options);
 };
 RilObject.prototype[REQUEST_HANGUP_WAITING_OR_BACKGROUND] = function REQUEST_HANGUP_WAITING_OR_BACKGROUND(length, options) {
   RilObject.prototype[REQUEST_HANGUP].call(this, length, options);
 };
 RilObject.prototype[REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND] = function REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND(length, options) {
   RilObject.prototype[REQUEST_HANGUP].call(this, length, options);
 };
 RilObject.prototype[REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE] = function REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE(length, options) {
+  options.success = (options.rilRequestError === 0);
+  options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
+  this.sendChromeMessage(options);
 };
 RilObject.prototype[REQUEST_CONFERENCE] = function REQUEST_CONFERENCE(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorName = "addError";
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;