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 id24994
push useremorley@mozilla.com
push dateTue, 23 Jul 2013 12:46:01 +0000
treeherdermozilla-central@23e0a8d7030d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersHsinYi
bugs891242
milestone25.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 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();