Bug 1200134 - Control USSD Sessions with State-Transitions instead of Boolean. r=echen
authorBevis Tseng <btseng@mozilla.com>
Fri, 28 Aug 2015 16:39:57 +0800
changeset 267414 6611408430fb3ea33044623b8144107d2117f17c
parent 267413 b61b2827299785c726fa70892b8df3514dffb103
child 267415 518db6df5ceb10aef5682d7b2db67f1798976afb
push id29519
push usercbook@mozilla.com
push dateWed, 14 Oct 2015 10:29:57 +0000
treeherdermozilla-central@6307530f9f1e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersechen
bugs1200134
milestone44.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 1200134 - Control USSD Sessions with State-Transitions instead of Boolean. r=echen
dom/telephony/gonk/TelephonyService.js
--- a/dom/telephony/gonk/TelephonyService.js
+++ b/dom/telephony/gonk/TelephonyService.js
@@ -159,16 +159,21 @@ const MMI_KS_SERVICE_CLASS_VOICE = "serv
 const MMI_KS_SERVICE_CLASS_DATA = "serviceClassData";
 const MMI_KS_SERVICE_CLASS_FAX = "serviceClassFax";
 const MMI_KS_SERVICE_CLASS_SMS = "serviceClassSms";
 const MMI_KS_SERVICE_CLASS_DATA_SYNC = "serviceClassDataSync";
 const MMI_KS_SERVICE_CLASS_DATA_ASYNC = "serviceClassDataAsync";
 const MMI_KS_SERVICE_CLASS_PACKET = "serviceClassPacket";
 const MMI_KS_SERVICE_CLASS_PAD = "serviceClassPad";
 
+// States of USSD Session : DONE -> ONGOING [-> CANCELLING] -> DONE
+const USSD_SESSION_DONE = "DONE";
+const USSD_SESSION_ONGOING = "ONGOING";
+const USSD_SESSION_CANCELLING = "CANCELLING";
+
 const MMI_PROC_TO_CF_ACTION = {};
 MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_ACTIVATION] = Ci.nsIMobileConnection.CALL_FORWARD_ACTION_ENABLE;
 MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_DEACTIVATION] = Ci.nsIMobileConnection.CALL_FORWARD_ACTION_DISABLE;
 MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_INTERROGATION] = Ci.nsIMobileConnection.CALL_FORWARD_ACTION_QUERY_STATUS;
 MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_REGISTRATION] = Ci.nsIMobileConnection.CALL_FORWARD_ACTION_REGISTRATION;
 MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_ERASURE] = Ci.nsIMobileConnection.CALL_FORWARD_ACTION_ERASURE;
 
 const MMI_SC_TO_CF_REASON = {};
@@ -375,17 +380,17 @@ function TelephonyService() {
 
   Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
   Services.prefs.addObserver(kPrefDefaultServiceId, this, false);
 
   Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
 
   for (let i = 0; i < this._numClients; ++i) {
     this._audioStates[i] = nsITelephonyAudioService.PHONE_STATE_NORMAL;
-    this._ussdSessions[i] = false;
+    this._ussdSessions[i] = USSD_SESSION_DONE;
     this._currentCalls[i] = {};
     this._enumerateCallsForClient(i);
   }
 }
 TelephonyService.prototype = {
   classID: GONK_TELEPHONYSERVICE_CID,
   classInfo: XPCOMUtils.generateCI({classID: GONK_TELEPHONYSERVICE_CID,
                                     contractID: GONK_TELEPHONYSERVICE_CONTRACTID,
@@ -1065,17 +1070,17 @@ TelephonyService.prototype = {
 
       // Call waiting
       case MMI_KS_SC_CALL_WAITING:
         this._callWaitingMMI(aClientId, aMmi, aCallback);
         break;
 
       // Handle unknown MMI code as USSD.
       default:
-        if (this._ussdSessions[aClientId]) {
+        if (this._ussdSessions[aClientId] == USSD_SESSION_ONGOING) {
           // Cancel the previous ussd session first.
           this._cancelUSSDInternal(aClientId, aResponse => {
             // Fail to cancel ussd session, report error instead of sending ussd
             // request.
             if (aResponse.errorMsg) {
               aCallback.notifyDialMMIError(aResponse.errorMsg);
               return;
             }
@@ -2149,30 +2154,36 @@ TelephonyService.prototype = {
   },
 
   sendUSSD: function(aClientId, aUssd, aCallback) {
     this._sendUSSDInternal(aClientId, aUssd,
                            this._defaultCallbackHandler.bind(this, aCallback));
   },
 
   _sendUSSDInternal: function(aClientId, aUssd, aCallback) {
+    this._ussdSessions[aClientId] = USSD_SESSION_ONGOING;
     this._sendToRilWorker(aClientId, "sendUSSD", { ussd: aUssd }, aResponse => {
-      this._ussdSessions[aClientId] = !aResponse.errorMsg;
+      if (aResponse.errorMsg) {
+        this._ussdSessions[aClientId] = USSD_SESSION_DONE;
+      }
       aCallback(aResponse);
     });
   },
 
   cancelUSSD: function(aClientId, aCallback) {
     this._cancelUSSDInternal(aClientId,
                              this._defaultCallbackHandler.bind(this, aCallback));
   },
 
   _cancelUSSDInternal: function(aClientId, aCallback) {
+    this._ussdSessions[aClientId] = USSD_SESSION_CANCELLING;
     this._sendToRilWorker(aClientId, "cancelUSSD", {}, aResponse => {
-      this._ussdSessions[aClientId] = !!aResponse.errorMsg;
+      if (aResponse.errorMsg) {
+        this._ussdSessions[aClientId] = USSD_SESSION_ONGOING;
+      }
       aCallback(aResponse);
     });
   },
 
   get microphoneMuted() {
     return gAudioService.microphoneMuted;
   },
 
@@ -2436,19 +2447,33 @@ TelephonyService.prototype = {
 
   notifyUssdReceived: function(aClientId, aMessage, aSessionEnded) {
     if (DEBUG) {
       debug("notifyUssdReceived for " + aClientId + ": " +
             aMessage + " (sessionEnded : " + aSessionEnded + ")");
     }
 
     let oldSession = this._ussdSessions[aClientId];
-    this._ussdSessions[aClientId] = !aSessionEnded;
+    this._ussdSessions[aClientId] =
+      aSessionEnded ? USSD_SESSION_DONE : USSD_SESSION_ONGOING;
 
-    if (!oldSession && !this._ussdSessions[aClientId] && !aMessage) {
+    // We suppress the empty message only when the session is not changed and
+    // is not alive. See Bug 1057455, 1198676.
+    // Moreover, we should allow a notification initiated by network
+    // in which further response is not required.
+    // See |5.2.2 Actions at the UE| in 3GPP TS 22.090:
+    // "
+    //  The network may explicitly indicate to the UE that a response
+    //  from the user is required. ...
+    //  If the network does not indicate that a response is required,
+    //  then the normal MMI procedures on the UE continue to apply.
+    // "
+    if (oldSession != USSD_SESSION_ONGOING &&
+        this._ussdSessions[aClientId] != USSD_SESSION_ONGOING &&
+        !aMessage) {
       return;
     }
 
     gTelephonyMessenger.notifyUssdReceived(aClientId, aMessage, aSessionEnded);
   },
 
   /**
    * nsIObserver interface.