// inherited javadoc suffices public void cancel() { // Complete or failed cannot be cancelled if (state == State.COMPLETE || state == State.FAILED) { return; } state = State.CANCELLED; if (isPendingUSSD) { /* * There can only be one pending USSD session, so tell the radio to * cancel it. */ phone.mCM.cancelPendingUssd(obtainMessage(EVENT_USSD_CANCEL_COMPLETE, this)); /* * Don't call phone.onMMIDone here; wait for CANCEL_COMPLETE notice * from RIL. */ } else { // TODO in cases other than USSD, it would be nice to cancel // the pending radio operation. This requires RIL cancellation // support, which does not presently exist. phone.onMMIDone(this); } }
private void onQueryComplete(AsyncResult ar) { StringBuilder sb = new StringBuilder(getScString()); sb.append("\n"); if (ar.exception != null) { state = State.FAILED; sb.append(getErrorMessage(ar)); } else { int[] ints = (int[]) ar.result; if (ints.length != 0) { if (ints[0] == 0) { sb.append(context.getText(com.android.internal.R.string.serviceDisabled)); } else if (sc.equals(SC_WAIT)) { // Call Waiting includes additional data in the response. sb.append(createQueryCallWaitingResultMessage(ints[1])); } else if (isServiceCodeCallBarring(sc)) { // ints[0] for Call Barring is a bit vector of services sb.append(createQueryCallBarringResultMessage(ints[0])); } else if (ints[0] == 1) { // for all other services, treat it as a boolean sb.append(context.getText(com.android.internal.R.string.serviceEnabled)); } else { sb.append(context.getText(com.android.internal.R.string.mmiError)); } } else { sb.append(context.getText(com.android.internal.R.string.mmiError)); } state = State.COMPLETE; } message = sb; phone.onMMIDone(this); }
/** * Called from GSMPhone * * <p>The radio has reset, and this is still pending */ void onUssdFinishedError() { if (state == State.PENDING) { state = State.FAILED; message = context.getText(com.android.internal.R.string.mmiError); phone.onMMIDone(this); } }
private void handlePasswordError(int res) { state = State.FAILED; StringBuilder sb = new StringBuilder(getScString()); sb.append("\n"); sb.append(context.getText(res)); message = sb; phone.onMMIDone(this); }
private void onQueryCfComplete(AsyncResult ar) { StringBuilder sb = new StringBuilder(getScString()); sb.append("\n"); if (ar.exception != null) { state = State.FAILED; sb.append(getErrorMessage(ar)); } else { CallForwardInfo infos[]; infos = (CallForwardInfo[]) ar.result; if (infos.length == 0) { // Assume the default is not active sb.append(context.getText(com.android.internal.R.string.serviceDisabled)); // Set unconditional CFF in SIM to false if (phone.mSIMRecords != null) { phone.setCallForwardingPreference(false); phone.mSIMRecords.setVoiceCallForwardingFlag(1, false); } else { Log.w(LOG_TAG, "setVoiceCallForwardingFlag aborted. sim records is null."); } } else { SpannableStringBuilder tb = new SpannableStringBuilder(); // Each bit in the service class gets its own result line // The service classes may be split up over multiple // CallForwardInfos. So, for each service class, find out // which CallForwardInfo represents it and then build // the response text based on that for (int serviceClassMask = 1; serviceClassMask <= SERVICE_CLASS_MAX; serviceClassMask <<= 1) { for (int i = 0, s = infos.length; i < s; i++) { if ((serviceClassMask & infos[i].serviceClass) != 0) { tb.append(makeCFQueryResultMessage(infos[i], serviceClassMask)); tb.append("\n"); } } } sb.append(tb); } state = State.COMPLETE; } message = sb; phone.onMMIDone(this); }
/** * Called from GSMPhone * * <p>An unsolicited USSD NOTIFY or REQUEST has come in matching up with this pending USSD request * * <p>Note: If REQUEST, this exchange is complete, but the session remains active (ie, the network * expects user input). */ void onUssdFinished(String ussdMessage, boolean isUssdRequest) { if (state == State.PENDING) { if (ussdMessage == null) { message = context.getText(com.android.internal.R.string.mmiComplete); } else { message = ussdMessage; } this.isUssdRequest = isUssdRequest; // If it's a request, leave it PENDING so that it's cancelable. if (!isUssdRequest) { state = State.COMPLETE; } phone.onMMIDone(this); } }
private void onSetComplete(AsyncResult ar) { StringBuilder sb = new StringBuilder(getScString()); sb.append("\n"); if (ar.exception != null) { state = State.FAILED; if (ar.exception instanceof CommandException) { CommandException.Error err = ((CommandException) (ar.exception)).getCommandError(); if (err == CommandException.Error.PASSWORD_INCORRECT) { if (isPinCommand()) { // look specifically for the PUK commands and adjust // the message accordingly. if (sc.equals(SC_PUK) || sc.equals(SC_PUK2)) { sb.append(context.getText(com.android.internal.R.string.badPuk)); } else { sb.append(context.getText(com.android.internal.R.string.badPin)); } } else { sb.append(context.getText(com.android.internal.R.string.passwordIncorrect)); } } else if (err == CommandException.Error.SIM_PUK2) { sb.append(context.getText(com.android.internal.R.string.badPin)); sb.append("\n"); sb.append(context.getText(com.android.internal.R.string.needPuk2)); } else if (err == CommandException.Error.FDN_CHECK_FAILURE) { Log.i(LOG_TAG, "FDN_CHECK_FAILURE"); sb.append(context.getText(com.android.internal.R.string.mmiFdnError)); } else { sb.append(context.getText(com.android.internal.R.string.mmiError)); } } else { sb.append(context.getText(com.android.internal.R.string.mmiError)); } } else if (isActivate()) { state = State.COMPLETE; if (isCallFwdRegister) { sb.append(context.getText(com.android.internal.R.string.serviceRegistered)); isCallFwdRegister = false; } else { sb.append(context.getText(com.android.internal.R.string.serviceEnabled)); } // Record CLIR setting if (sc.equals(SC_CLIR)) { phone.saveClirSetting(CommandsInterface.CLIR_INVOCATION); } } else if (isDeactivate()) { state = State.COMPLETE; sb.append(context.getText(com.android.internal.R.string.serviceDisabled)); // Record CLIR setting if (sc.equals(SC_CLIR)) { phone.saveClirSetting(CommandsInterface.CLIR_SUPPRESSION); } } else if (isRegister()) { state = State.COMPLETE; sb.append(context.getText(com.android.internal.R.string.serviceRegistered)); } else if (isErasure()) { state = State.COMPLETE; sb.append(context.getText(com.android.internal.R.string.serviceErased)); } else { state = State.FAILED; sb.append(context.getText(com.android.internal.R.string.mmiError)); } message = sb; phone.onMMIDone(this); }
/** Called from GSMPhone.handleMessage; not a Handler subclass */ public void handleMessage(Message msg) { AsyncResult ar; switch (msg.what) { case EVENT_SET_COMPLETE: ar = (AsyncResult) (msg.obj); onSetComplete(ar); break; case EVENT_SET_CFF_COMPLETE: ar = (AsyncResult) (msg.obj); /* * msg.arg1 = 1 means to set unconditional voice call forwarding * msg.arg2 = 1 means to enable voice call forwarding */ if ((ar.exception == null) && (msg.arg1 == 1)) { boolean cffEnabled = (msg.arg2 == 1); if (phone.mSIMRecords != null) { phone.mSIMRecords.setVoiceCallForwardingFlag(1, cffEnabled); phone.setCallForwardingPreference(cffEnabled); } else { Log.w(LOG_TAG, "setVoiceCallForwardingFlag aborted. sim records is null."); } } onSetComplete(ar); break; case EVENT_GET_CLIR_COMPLETE: ar = (AsyncResult) (msg.obj); onGetClirComplete(ar); break; case EVENT_QUERY_CF_COMPLETE: ar = (AsyncResult) (msg.obj); onQueryCfComplete(ar); break; case EVENT_QUERY_COMPLETE: ar = (AsyncResult) (msg.obj); onQueryComplete(ar); break; case EVENT_USSD_COMPLETE: ar = (AsyncResult) (msg.obj); if (ar.exception != null) { state = State.FAILED; message = getErrorMessage(ar); phone.onMMIDone(this); } // Note that unlike most everything else, the USSD complete // response does not complete this MMI code...we wait for // an unsolicited USSD "Notify" or "Request". // The matching up of this is done in GSMPhone. break; case EVENT_USSD_CANCEL_COMPLETE: phone.onMMIDone(this); break; } }
/** 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); } }
private void onGetClirComplete(AsyncResult ar) { StringBuilder sb = new StringBuilder(getScString()); sb.append("\n"); if (ar.exception != null) { state = State.FAILED; sb.append(getErrorMessage(ar)); } else { int clirArgs[]; clirArgs = (int[]) ar.result; // the 'm' parameter from TS 27.007 7.7 switch (clirArgs[1]) { case 0: // CLIR not provisioned sb.append(context.getText(com.android.internal.R.string.serviceNotProvisioned)); state = State.COMPLETE; break; case 1: // CLIR provisioned in permanent mode sb.append(context.getText(com.android.internal.R.string.CLIRPermanent)); state = State.COMPLETE; break; case 2: // unknown (e.g. no network, etc.) sb.append(context.getText(com.android.internal.R.string.mmiError)); state = State.FAILED; break; case 3: // CLIR temporary mode presentation restricted // the 'n' parameter from TS 27.007 7.7 switch (clirArgs[0]) { default: case 0: // Default sb.append(context.getText(com.android.internal.R.string.CLIRDefaultOnNextCallOn)); break; case 1: // CLIR invocation sb.append(context.getText(com.android.internal.R.string.CLIRDefaultOnNextCallOn)); break; case 2: // CLIR suppression sb.append(context.getText(com.android.internal.R.string.CLIRDefaultOnNextCallOff)); break; } state = State.COMPLETE; break; case 4: // CLIR temporary mode presentation allowed // the 'n' parameter from TS 27.007 7.7 switch (clirArgs[0]) { default: case 0: // Default sb.append(context.getText(com.android.internal.R.string.CLIRDefaultOffNextCallOff)); break; case 1: // CLIR invocation sb.append(context.getText(com.android.internal.R.string.CLIRDefaultOffNextCallOn)); break; case 2: // CLIR suppression sb.append(context.getText(com.android.internal.R.string.CLIRDefaultOffNextCallOff)); break; } state = State.COMPLETE; break; } } message = sb; phone.onMMIDone(this); }