/** * Some dial strings in GSM are defined to do non-call setup things, such as modify or query * supplementary service settings (eg, call forwarding). These are generally referred to as "MMI * codes". We look to see if the dial string contains a valid MMI code (potentially with a dial * string at the end as well) and return info here. * * <p>If the dial string contains no MMI code, we return an instance with only "dialingNumber" set * * <p>Please see flow chart in TS 22.030 6.5.3.2 */ static GsmMmiCode newFromDialString(String dialString, GSMPhone phone, UiccCardApplication app) { Matcher m; GsmMmiCode ret = null; if (SystemProperties.getBoolean("ro.config.multimode_cdma", false)) { m = sPatternSuppServiceGlobalDev.matcher(dialString); if (m.matches()) { ret = new GsmMmiCode(phone, app); ret.action = makeEmptyNull(m.group(MATCH_GROUP_ACTION)); String DialCode = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE)); if (DialCode.equals(SC_GLOBALDEV_VM)) { ret.sc = SC_GLOBALDEV_VM; ret.dialingNumber = "+1" + phone.getMdn(); return ret; } else if (DialCode.equals(SC_GLOBALDEV_CS)) { ret.sc = SC_GLOBALDEV_CS; ret.dialingNumber = GLOBALDEV_CS; return ret; } else if (DialCode.length() >= 3 && DialCode.startsWith(SC_GLOBALDEV_CLIR_INVK)) { // Dial "#31#PhoneNum" to invoke CLIR temporarily dialString = ACTION_DEACTIVATE + SC_CLIR + ACTION_DEACTIVATE + DialCode.substring(2); } else if (DialCode.length() >= 3 && DialCode.startsWith(SC_GLOBALDEV_CLIR_SUPP)) { // Dial "*31#PhoneNum" to suppress CLIR temporarily dialString = ACTION_ACTIVATE + SC_CLIR + ACTION_DEACTIVATE + DialCode.substring(2); } } } m = sPatternSuppService.matcher(dialString); // Is this formatted like a standard supplementary service code? if (m.matches()) { ret = new GsmMmiCode(phone, app); ret.poundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING)); ret.action = makeEmptyNull(m.group(MATCH_GROUP_ACTION)); ret.sc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE)); ret.sia = makeEmptyNull(m.group(MATCH_GROUP_SIA)); ret.sib = makeEmptyNull(m.group(MATCH_GROUP_SIB)); ret.sic = makeEmptyNull(m.group(MATCH_GROUP_SIC)); ret.pwd = makeEmptyNull(m.group(MATCH_GROUP_PWD_CONFIRM)); ret.dialingNumber = makeEmptyNull(m.group(MATCH_GROUP_DIALING_NUMBER)); } else if (dialString.endsWith("#")) { // TS 22.030 sec 6.5.3.2 // "Entry of any characters defined in the 3GPP TS 23.038 [8] Default Alphabet // (up to the maximum defined in 3GPP TS 24.080 [10]), followed by #SEND". ret = new GsmMmiCode(phone, app); ret.poundString = dialString; } else if (isTwoDigitShortCode(phone.getContext(), dialString)) { // Is a country-specific exception to short codes as defined in TS 22.030, 6.5.3.2 ret = null; } else if (isShortCode(dialString, phone)) { // this may be a short code, as defined in TS 22.030, 6.5.3.2 ret = new GsmMmiCode(phone, app); ret.dialingNumber = dialString; } return ret; }
/** * Helper function for newFromDialString. Returns true if dialString appears to be a short code * AND conditions are correct for it to be treated as such. */ private static boolean isShortCode(String dialString, GSMPhone phone) { // check for any Adapt change requirements. boolean shortCodeExclusionFlag = false; if (SystemProperties.getBoolean("persist.cust.tel.adapt", false)) { if (dialString.length() == 2) { Log.i(LOG_TAG, "Adapt, Number needs to be checked for short code exclusion list"); shortCodeExclusionFlag = isExcludedShortCode(dialString); } } // Refer to TS 22.030 Figure 3.5.3.2: // A 1 or 2 digit "short code" is treated as USSD if it is entered while on a call or // does not satisfy the condition (exactly 2 digits && starts with '1'). return ((dialString != null && dialString.length() <= 2) && !PhoneNumberUtils.isEmergencyNumber(dialString) && (phone.isInCall() || !((dialString.length() == 2 && dialString.charAt(0) == '1') || shortCodeExclusionFlag /* * While contrary to TS 22.030, there is strong precedence for * treating "0" and "00" as call setup strings. */ || dialString.equals("0") || dialString.equals("00")))); }