/**
   * Return true if time zone needs fixing.
   *
   * @param phoneBase
   * @param operatorNumeric
   * @param prevOperatorNumeric
   * @param needToFixTimeZone
   * @return true if time zone needs to be fixed
   */
  protected boolean shouldFixTimeZoneNow(
      PhoneBase phoneBase,
      String operatorNumeric,
      String prevOperatorNumeric,
      boolean needToFixTimeZone) {
    // Return false if the mcc isn't valid as we don't know where we are.
    // Return true if we have an IccCard and the mcc changed or we
    // need to fix it because when the NITZ time came in we didn't
    // know the country code.

    // If mcc is invalid then we'll return false
    int mcc;
    try {
      mcc = Integer.parseInt(operatorNumeric.substring(0, 3));
    } catch (Exception e) {
      if (DBG) {
        log("shouldFixTimeZoneNow: no mcc, operatorNumeric=" + operatorNumeric + " retVal=false");
      }
      return false;
    }

    // If prevMcc is invalid will make it different from mcc
    // so we'll return true if the card exists.
    int prevMcc;
    try {
      prevMcc = Integer.parseInt(prevOperatorNumeric.substring(0, 3));
    } catch (Exception e) {
      prevMcc = mcc + 1;
    }

    // Determine if the Icc card exists
    boolean iccCardExist = false;
    if (mUiccApplcation != null) {
      iccCardExist = mUiccApplcation.getState() != AppState.APPSTATE_UNKNOWN;
    }

    // Determine retVal
    boolean retVal = ((iccCardExist && (mcc != prevMcc)) || needToFixTimeZone);
    if (DBG) {
      long ctm = System.currentTimeMillis();
      log(
          "shouldFixTimeZoneNow: retVal="
              + retVal
              + " iccCardExist="
              + iccCardExist
              + " operatorNumeric="
              + operatorNumeric
              + " mcc="
              + mcc
              + " prevOperatorNumeric="
              + prevOperatorNumeric
              + " prevMcc="
              + prevMcc
              + " needToFixTimeZone="
              + needToFixTimeZone
              + " ltod="
              + TimeUtils.logTimeOfDay(ctm));
    }
    return retVal;
  }
  /** Process a MMI code or short code...anything that isn't a dialing number */
  void processCode() {
    try {
      if (isShortCode()) {
        Log.d(LOG_TAG, "isShortCode");
        // These just get treated as USSD.
        sendUssd(dialingNumber);
      } else if (dialingNumber != null) {
        // We should have no dialing numbers here
        throw new RuntimeException("Invalid or Unsupported MMI Code");
      } else if (sc != null && sc.equals(SC_CLIP)) {
        Log.d(LOG_TAG, "is CLIP");
        if (isInterrogate()) {
          phone.mCM.queryCLIP(obtainMessage(EVENT_QUERY_COMPLETE, this));
        } else {
          throw new RuntimeException("Invalid or Unsupported MMI Code");
        }
      } else if (sc != null && sc.equals(SC_CLIR)) {
        Log.d(LOG_TAG, "is CLIR");
        if (isActivate()) {
          phone.mCM.setCLIR(
              CommandsInterface.CLIR_INVOCATION, obtainMessage(EVENT_SET_COMPLETE, this));
        } else if (isDeactivate()) {
          phone.mCM.setCLIR(
              CommandsInterface.CLIR_SUPPRESSION, obtainMessage(EVENT_SET_COMPLETE, this));
        } else if (isInterrogate()) {
          phone.mCM.getCLIR(obtainMessage(EVENT_GET_CLIR_COMPLETE, this));
        } else {
          throw new RuntimeException("Invalid or Unsupported MMI Code");
        }
      } else if (isServiceCodeCallForwarding(sc)) {
        Log.d(LOG_TAG, "is CF");

        String dialingNumber = sia;
        int serviceClass = siToServiceClass(sib);
        int reason = scToCallForwardReason(sc);
        int time = siToTime(sic);

        if (isInterrogate()) {
          phone.mCM.queryCallForwardStatus(
              reason, serviceClass, dialingNumber, obtainMessage(EVENT_QUERY_CF_COMPLETE, this));
        } else {
          int cfAction;

          if (isActivate()) {
            if (dialingNumber != null) {
              isCallFwdRegister = true;
              cfAction = CommandsInterface.CF_ACTION_REGISTRATION;
            } else {
              cfAction = CommandsInterface.CF_ACTION_ENABLE;
            }
          } else if (isDeactivate()) {
            cfAction = CommandsInterface.CF_ACTION_DISABLE;
          } else if (isRegister()) {
            cfAction = CommandsInterface.CF_ACTION_REGISTRATION;
          } else if (isErasure()) {
            cfAction = CommandsInterface.CF_ACTION_ERASURE;
          } else {
            throw new RuntimeException("invalid action");
          }

          int isSettingUnconditionalVoice =
              (((reason == CommandsInterface.CF_REASON_UNCONDITIONAL)
                          || (reason == CommandsInterface.CF_REASON_ALL))
                      && (((serviceClass & CommandsInterface.SERVICE_CLASS_VOICE) != 0)
                          || (serviceClass == CommandsInterface.SERVICE_CLASS_NONE)))
                  ? 1
                  : 0;

          int isEnableDesired =
              ((cfAction == CommandsInterface.CF_ACTION_ENABLE)
                      || (cfAction == CommandsInterface.CF_ACTION_REGISTRATION))
                  ? 1
                  : 0;

          Log.d(LOG_TAG, "is CF setCallForward");
          phone.mCM.setCallForward(
              cfAction,
              reason,
              serviceClass,
              dialingNumber,
              time,
              obtainMessage(
                  EVENT_SET_CFF_COMPLETE, isSettingUnconditionalVoice, isEnableDesired, this));
        }
      } else if (isServiceCodeCallBarring(sc)) {
        // sia = password
        // sib = basic service group

        String password = sia;
        int serviceClass = siToServiceClass(sib);
        String facility = scToBarringFacility(sc);

        if (isInterrogate()) {
          phone.mCM.queryFacilityLock(
              0, "", facility, password, serviceClass, obtainMessage(EVENT_QUERY_COMPLETE, this));
        } else if (isActivate() || isDeactivate()) {
          phone.mCM.setFacilityLock(
              0,
              "",
              facility,
              isActivate(),
              password,
              serviceClass,
              obtainMessage(EVENT_SET_COMPLETE, this));
        } else {
          throw new RuntimeException("Invalid or Unsupported MMI Code");
        }

      } else if (sc != null && sc.equals(SC_PWD)) {
        // sia = fac
        // sib = old pwd
        // sic = new pwd
        // pwd = new pwd
        String facility;
        String oldPwd = sib;
        String newPwd = sic;
        if (isActivate() || isRegister()) {
          // Even though ACTIVATE is acceptable, this is really termed a REGISTER
          action = ACTION_REGISTER;

          if (sia == null) {
            // If sc was not specified, treat it as BA_ALL.
            facility = CommandsInterface.CB_FACILITY_BA_ALL;
          } else {
            facility = scToBarringFacility(sia);
          }
          if (newPwd.equals(pwd)) {
            phone.mCM.changeBarringPassword(
                facility, oldPwd, newPwd, obtainMessage(EVENT_SET_COMPLETE, this));
          } else {
            // password mismatch; return error
            handlePasswordError(com.android.internal.R.string.passwordIncorrect);
          }
        } else {
          throw new RuntimeException("Invalid or Unsupported MMI Code");
        }

      } else if (sc != null && sc.equals(SC_WAIT)) {
        // sia = basic service group
        int serviceClass = siToServiceClass(sia);

        if (isActivate() || isDeactivate()) {
          phone.mCM.setCallWaiting(
              isActivate(), serviceClass, obtainMessage(EVENT_SET_COMPLETE, this));
        } else if (isInterrogate()) {
          phone.mCM.queryCallWaiting(serviceClass, obtainMessage(EVENT_QUERY_COMPLETE, this));
        } else {
          throw new RuntimeException("Invalid or Unsupported MMI Code");
        }
      } else if (isPinCommand()) {
        // sia = old PIN or PUK
        // sib = new PIN
        // sic = new PIN
        String oldPinOrPuk = sia;
        String newPin = sib;
        int pinLen = newPin.length();
        if (isRegister()) {
          if (!newPin.equals(sic)) {
            // password mismatch; return error
            handlePasswordError(com.android.internal.R.string.mismatchPin);
          } else if (pinLen < 4 || pinLen > 8) {
            // invalid length
            handlePasswordError(com.android.internal.R.string.invalidPin);
          } else if (sc.equals(SC_PIN)
              && phone.m3gppApplication != null
              && phone.m3gppApplication.getState() == UiccConstants.AppState.APPSTATE_PUK) {
            // Sim is puk-locked
            handlePasswordError(com.android.internal.R.string.needPuk);
          } else {
            // pre-checks OK
            if (sc.equals(SC_PIN)) {
              if (mUiccApp != null)
                mUiccApp.changeIccLockPassword(
                    oldPinOrPuk, newPin, obtainMessage(EVENT_SET_COMPLETE, this));
            } else if (sc.equals(SC_PIN2)) {
              if (mUiccApp != null)
                mUiccApp.changeIccFdnPassword(
                    oldPinOrPuk, newPin, obtainMessage(EVENT_SET_COMPLETE, this));
            } else if (sc.equals(SC_PUK)) {
              if (mUiccApp != null)
                mUiccApp.supplyPuk(oldPinOrPuk, newPin, obtainMessage(EVENT_SET_COMPLETE, this));
            } else if (sc.equals(SC_PUK2)) {
              if (mUiccApp != null)
                mUiccApp.supplyPuk2(oldPinOrPuk, newPin, obtainMessage(EVENT_SET_COMPLETE, this));
            }
          }
        } else {
          throw new RuntimeException("Invalid or Unsupported MMI Code");
        }
      } else if (isServiceCodeUnsupported(sc)) {
        Log.d(LOG_TAG, "Unsupported MMI code: " + sc);
        state = State.FAILED;
        message = context.getText(com.android.internal.R.string.unsupportedMmiCode);
        phone.onMMIDone(this);
      } else if (poundString != null) {
        sendUssd(poundString);
      } else {
        throw new RuntimeException("Invalid or Unsupported MMI Code");
      }
    } catch (RuntimeException exc) {
      state = State.FAILED;
      message = context.getText(com.android.internal.R.string.mmiError);
      phone.onMMIDone(this);
    }
  }