Bug 891242 - [MMI] Short Code MMI (length<3) does not work as expected - Gecko part, r=HsinYi
authorShawn Ku <sku@mozilla.com>
Tue, 23 Jul 2013 15:02:37 +0800
changeset 139493 0ebf0fabe24d628cb1e7ac9b463ce72d8ab2c618
parent 139492 89c6b432de08c5a7bcc2024c71553c6bb6ad531a
child 139494 7577d1be4d9d6b7b0880a83f9694e55720d542bd
push idunknown
push userunknown
push dateunknown
reviewersHsinYi
bugs891242
milestone25.0a1
Bug 891242 - [MMI] Short Code MMI (length<3) does not work as expected - Gecko part, r=HsinYi
dom/system/gonk/ril_worker.js
dom/system/gonk/tests/test_ril_worker_mmi.js
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -2172,23 +2172,62 @@ let RIL = {
   /**
    * Get failure casue code for the most recently failed PDP context.
    */
   getFailCauseCode: function getFailCauseCode(options) {
     Buf.simpleRequest(REQUEST_LAST_CALL_FAIL_CAUSE, options);
   },
 
   /**
-   * Helper to parse and process a MMI string.
+   * Helper to parse MMI/USSD string. TS.22.030 Figure 3.5.3.2.
    */
   _parseMMI: function _parseMMI(mmiString) {
     if (!mmiString || !mmiString.length) {
       return null;
     }
 
+    let matches = this._matchMMIRegexp(mmiString);
+    if (matches) {
+      // After successfully executing the regular expresion over the MMI string,
+      // the following match groups should contain:
+      // 1 = full MMI string that might be used as a USSD request.
+      // 2 = MMI procedure.
+      // 3 = Service code.
+      // 5 = SIA.
+      // 7 = SIB.
+      // 9 = SIC.
+      // 11 = Password registration.
+      // 12 = Dialing number.
+      return {
+        fullMMI: matches[MMI_MATCH_GROUP_FULL_MMI],
+        procedure: matches[MMI_MATCH_GROUP_MMI_PROCEDURE],
+        serviceCode: matches[MMI_MATCH_GROUP_SERVICE_CODE],
+        sia: matches[MMI_MATCH_GROUP_SIA],
+        sib: matches[MMI_MATCH_GROUP_SIB],
+        sic: matches[MMI_MATCH_GROUP_SIC],
+        pwd: matches[MMI_MATCH_GROUP_PWD_CONFIRM],
+        dialNumber: matches[MMI_MATCH_GROUP_DIALING_NUMBER]
+      };
+    }
+
+    if (this._isPoundString(mmiString) ||
+        this._isMMIShortString(mmiString)) {
+      return {
+        fullMMI: mmiString
+      };
+    }
+
+    return null;
+  },
+
+  /**
+   * Helper to parse MMI string via regular expression. TS.22.030 Figure
+   * 3.5.3.2.
+   */
+  _matchMMIRegexp: function _matchMMIRegexp(mmiString) {
     // Regexp to parse and process the MMI code.
     if (this._mmiRegExp == null) {
       // The first group of the regexp takes the whole MMI string.
       // The second group takes the MMI procedure that can be:
       //    - Activation (*SC*SI#).
       //    - Deactivation (#SC*SI#).
       //    - Interrogation (*#SC*SI#).
       //    - Registration (**SC*SI#).
@@ -2221,51 +2260,51 @@ let RIL = {
       // registration procedure.
       pattern += "(\\*([^*#]*))?)?)?)?#)";
 
       // The last group takes the dial string after the #.
       pattern += "([^#]*)";
 
       this._mmiRegExp = new RegExp(pattern);
     }
-    let matches = this._mmiRegExp.exec(mmiString);
-
-    // If the regex does not apply over the MMI string, it can still be an MMI
-    // code. If the MMI String is a #-string (entry of any characters defined
-    // in the TS.23.038 Default Alphabet followed by #SEND) it shall be treated
-    // as a USSD code.
-    if (matches == null) {
-      if (mmiString.charAt(mmiString.length - 1) == MMI_END_OF_USSD) {
-        return {
-          fullMMI: mmiString
-        };
-      }
-      return null;
-    }
-
-    // After successfully executing the regular expresion over the MMI string,
-    // the following match groups should contain:
-    // 1 = full MMI string that might be used as a USSD request.
-    // 2 = MMI procedure.
-    // 3 = Service code.
-    // 5 = SIA.
-    // 7 = SIB.
-    // 9 = SIC.
-    // 11 = Password registration.
-    // 12 = Dialing number.
-    return {
-      fullMMI: matches[MMI_MATCH_GROUP_FULL_MMI],
-      procedure: matches[MMI_MATCH_GROUP_MMI_PROCEDURE],
-      serviceCode: matches[MMI_MATCH_GROUP_SERVICE_CODE],
-      sia: matches[MMI_MATCH_GROUP_SIA],
-      sib: matches[MMI_MATCH_GROUP_SIB],
-      sic: matches[MMI_MATCH_GROUP_SIC],
-      pwd: matches[MMI_MATCH_GROUP_PWD_CONFIRM],
-      dialNumber: matches[MMI_MATCH_GROUP_DIALING_NUMBER]
-    };
+
+    // Regex only applys for those well-defined MMI strings (refer to TS.22.030
+    // Annex B), otherwise, null should be the expected return value.
+    return this._mmiRegExp.exec(mmiString);
+  },
+
+  /**
+   * Helper to parse # string. TS.22.030 Figure 3.5.3.2.
+   */
+  _isPoundString: function _isPoundString(mmiString) {
+    return (mmiString.charAt(mmiString.length - 1) === MMI_END_OF_USSD);
+  },
+
+  /**
+   * Helper to parse short string. TS.22.030 Figure 3.5.3.2.
+   */
+  _isMMIShortString: function _isMMIShortString(mmiString) {
+    if (mmiString.length > 2) {
+      return false;
+    }
+
+    if (this._isEmergencyNumber(mmiString)) {
+      return false;
+    }
+
+    // In a call case.
+    if (Object.getOwnPropertyNames(this.currentCalls).length > 0) {
+      return true;
+    }
+
+    if ((mmiString.length != 2) || (mmiString.charAt(0) !== '1')) {
+      return true;
+    }
+
+    return false;
   },
 
   sendMMI: function sendMMI(options) {
     if (DEBUG) {
       debug("SendMMI " + JSON.stringify(options));
     }
     let mmiString = options.mmi;
     let mmi = this._parseMMI(mmiString);
@@ -2496,20 +2535,19 @@ let RIL = {
       case MMI_SC_BA_MO:
       case MMI_SC_BA_MT:
       // Call waiting
       case MMI_SC_CALL_WAITING:
         _sendMMIError(MMI_ERROR_KS_NOT_SUPPORTED);
         return;
     }
 
-    // If the MMI code is not a known code and is a recognized USSD request or
-    // a #-string, it shall still be sent as a USSD request.
-    if (mmi.fullMMI &&
-        (mmiString.charAt(mmiString.length - 1) == MMI_END_OF_USSD)) {
+    // If the MMI code is not a known code and is a recognized USSD request,
+    // it shall still be sent as a USSD request.
+    if (mmi.fullMMI) {
       if (!_isRadioAvailable(MMI_KS_SC_USSD)) {
         return;
       }
 
       options.ussd = mmi.fullMMI;
       options.mmiServiceCode = MMI_KS_SC_USSD;
       this.sendUSSD(options);
       return;
--- a/dom/system/gonk/tests/test_ril_worker_mmi.js
+++ b/dom/system/gonk/tests/test_ril_worker_mmi.js
@@ -65,32 +65,77 @@ add_test(function test_parseMMI_empty() 
 add_test(function test_parseMMI_undefined() {
   let mmi = parseMMI();
 
   do_check_null(mmi);
 
   run_next_test();
 });
 
-add_test(function test_parseMMI_invalid() {
-  let mmi = parseMMI("**");
+add_test(function test_parseMMI_one_digit_short_code() {
+  let mmi = parseMMI("1");
+
+  do_check_eq(mmi.fullMMI, "1");
+  do_check_eq(mmi.procedure, undefined);
+  do_check_eq(mmi.serviceCode, undefined);
+  do_check_eq(mmi.sia, undefined);
+  do_check_eq(mmi.sib, undefined);
+  do_check_eq(mmi.sic, undefined);
+  do_check_eq(mmi.pwd, undefined);
+  do_check_eq(mmi.dialNumber, undefined);
+
+  run_next_test();
+});
+
+add_test(function test_parseMMI_invalid_short_code() {
+  let mmi = parseMMI("11");
 
   do_check_null(mmi);
 
   run_next_test();
 });
 
+add_test(function test_parseMMI_short_code() {
+  let mmi = parseMMI("21");
+
+  do_check_eq(mmi.fullMMI, "21");
+  do_check_eq(mmi.procedure, undefined);
+  do_check_eq(mmi.serviceCode, undefined);
+  do_check_eq(mmi.sia, undefined);
+  do_check_eq(mmi.sib, undefined);
+  do_check_eq(mmi.sic, undefined);
+  do_check_eq(mmi.pwd, undefined);
+  do_check_eq(mmi.dialNumber, undefined);
+
+  run_next_test();
+});
+
 add_test(function test_parseMMI_dial_string() {
   let mmi = parseMMI("12345");
 
   do_check_null(mmi);
 
   run_next_test();
 });
 
+add_test(function test_parseMMI_USSD_without_asterisk_prefix() {
+  let mmi = parseMMI("123#");
+
+  do_check_eq(mmi.fullMMI, "123#");
+  do_check_eq(mmi.procedure, undefined);
+  do_check_eq(mmi.serviceCode, undefined);
+  do_check_eq(mmi.sia, undefined);
+  do_check_eq(mmi.sib, undefined);
+  do_check_eq(mmi.sic, undefined);
+  do_check_eq(mmi.pwd, undefined);
+  do_check_eq(mmi.dialNumber, undefined);
+
+  run_next_test();
+});
+
 add_test(function test_parseMMI_USSD() {
   let mmi = parseMMI("*123#");
 
   do_check_eq(mmi.fullMMI, "*123#");
   do_check_eq(mmi.procedure, MMI_PROCEDURE_ACTIVATION);
   do_check_eq(mmi.serviceCode, "123");
   do_check_eq(mmi.sia, undefined);
   do_check_eq(mmi.sib, undefined);
@@ -313,17 +358,43 @@ add_test(function test_sendMMI_empty() {
 
 add_test(function test_sendMMI_undefined() {
   testSendMMI({}, MMI_ERROR_KS_ERROR);
 
   run_next_test();
 });
 
 add_test(function test_sendMMI_invalid() {
-  testSendMMI("**", MMI_ERROR_KS_ERROR);
+  testSendMMI("11", MMI_ERROR_KS_ERROR);
+
+  run_next_test();
+});
+
+add_test(function test_sendMMI_short_code() {
+  let workerhelper = getWorker();
+  let worker = workerhelper.worker;
+
+  let ussdOptions;
+
+  worker.RIL.sendUSSD = function fakeSendUSSD(options){
+    ussdOptions = options;
+    worker.RIL[REQUEST_SEND_USSD](0, {
+      rilRequestError: ERROR_SUCCESS
+    });
+
+  }
+
+  worker.RIL.radioState = GECKO_RADIOSTATE_READY;
+  worker.RIL.sendMMI({mmi: "**"});
+
+  let postedMessage = workerhelper.postedMessage;
+  do_check_eq(ussdOptions.ussd, "**");
+  do_check_eq (postedMessage.errorMsg, GECKO_ERROR_SUCCESS);
+  do_check_true(postedMessage.success);
+  do_check_true(worker.RIL._ussdSession);
 
   run_next_test();
 });
 
 add_test(function test_sendMMI_dial_string() {
   testSendMMI("123", MMI_ERROR_KS_ERROR);
 
   run_next_test();