diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2010-05-06 15:18:59 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2010-05-06 15:18:59 -0700 |
commit | f4dffd8a45386b5a5f0e6de4f30facc9eaac4001 (patch) | |
tree | 8bb50f53d5cc0458327cbca8ed93bb5228f188dd /telephony | |
parent | 71bd9fc81e3154b9cad22ca7ff2d9c6ed6fdbe6c (diff) | |
parent | af7c978216cec465ad038b579ffc2be3ca8c7c66 (diff) | |
download | frameworks_base-f4dffd8a45386b5a5f0e6de4f30facc9eaac4001.zip frameworks_base-f4dffd8a45386b5a5f0e6de4f30facc9eaac4001.tar.gz frameworks_base-f4dffd8a45386b5a5f0e6de4f30facc9eaac4001.tar.bz2 |
merge from open-source master
Change-Id: I4c28751bd84b41259b12b0f3e3307e11234c8b64
Diffstat (limited to 'telephony')
4 files changed, 353 insertions, 3 deletions
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java index 1f5accf..d4b807c 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java @@ -67,6 +67,7 @@ import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OP import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC; import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY; +import java.util.ArrayList; import java.util.List; @@ -101,6 +102,7 @@ public class CDMAPhone extends PhoneBase { RuimFileHandler mRuimFileHandler; RuimRecords mRuimRecords; RuimCard mRuimCard; + ArrayList <CdmaMmiCode> mPendingMmis = new ArrayList<CdmaMmiCode>(); RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager; RuimSmsInterfaceManager mRuimSmsInterfaceManager; PhoneSubInfo mSubInfo; @@ -219,6 +221,8 @@ public class CDMAPhone extends PhoneBase { mSST.unregisterForNetworkAttach(this); //EVENT_REGISTERED_TO_NETWORK mCM.unSetOnSuppServiceNotification(this); + mPendingMmis.clear(); + //Force all referenced classes to unregister their former registered events mCT.dispose(); mDataConnection.dispose(); @@ -355,8 +359,7 @@ public class CDMAPhone extends PhoneBase { public List<? extends MmiCode> getPendingMmiCodes() { - Log.e(LOG_TAG, "method getPendingMmiCodes is NOT supported in CDMA!"); - return null; + return mPendingMmis; } public void registerForSuppServiceNotification( @@ -373,6 +376,15 @@ public class CDMAPhone extends PhoneBase { return false; } + boolean isInCall() { + CdmaCall.State foregroundCallState = getForegroundCall().getState(); + CdmaCall.State backgroundCallState = getBackgroundCall().getState(); + CdmaCall.State ringingCallState = getRingingCall().getState(); + + return (foregroundCallState.isAlive() || backgroundCallState.isAlive() || ringingCallState + .isAlive()); + } + public void setNetworkSelectionModeAutomatic(Message response) { Log.e(LOG_TAG, "method setNetworkSelectionModeAutomatic is NOT supported in CDMA!"); @@ -472,7 +484,18 @@ public class CDMAPhone extends PhoneBase { } public boolean handlePinMmi(String dialString) { - Log.e(LOG_TAG, "method handlePinMmi is NOT supported in CDMA!"); + CdmaMmiCode mmi = CdmaMmiCode.newFromDialString(dialString, this); + + if (mmi == null) { + Log.e(LOG_TAG, "Mmi is NULL!"); + return false; + } else if (mmi.isPukCommand()) { + mPendingMmis.add(mmi); + mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); + mmi.processCode(); + return true; + } + Log.e(LOG_TAG, "Unrecognized mmi!"); return false; } @@ -484,6 +507,22 @@ public class CDMAPhone extends PhoneBase { (mDataConnection.getDataOnRoamingEnabled() || !getServiceState().getRoaming()); } + /** + * Removes the given MMI from the pending list and notifies registrants that + * it is complete. + * + * @param mmi MMI that is done + */ + void onMMIDone(CdmaMmiCode mmi) { + /* + * Only notify complete if it's on the pending list. Otherwise, it's + * already been handled (eg, previously canceled). + */ + if (mPendingMmis.remove(mmi)) { + mMmiCompleteRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); + } + } + public void setLine1Number(String alphaTag, String number, Message onComplete) { Log.e(LOG_TAG, "setLine1Number: not possible in CDMA"); } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaMmiCode.java b/telephony/java/com/android/internal/telephony/cdma/CdmaMmiCode.java new file mode 100644 index 0000000..8dd8c2e --- /dev/null +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaMmiCode.java @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.telephony.cdma; + +import android.content.Context; + +import com.android.internal.telephony.CommandException; +import com.android.internal.telephony.MmiCode; + +import android.os.AsyncResult; +import android.os.Handler; +import android.os.Message; +import android.util.Log; + +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +/** + * This class can handle Puk code Mmi + * + * {@hide} + * + */ +public final class CdmaMmiCode extends Handler implements MmiCode { + static final String LOG_TAG = "CDMA_MMI"; + + // Constants + + // From TS 22.030 6.5.2 + static final String ACTION_REGISTER = "**"; + + // Supp Service codes from TS 22.030 Annex B + static final String SC_PUK = "05"; + + // Event Constant + + static final int EVENT_SET_COMPLETE = 1; + + // Instance Variables + + CDMAPhone phone; + Context context; + + String action; // ACTION_REGISTER + String sc; // Service Code + String sia, sib, sic; // Service Info a,b,c + String poundString; // Entire MMI string up to and including # + String dialingNumber; + String pwd; // For password registration + + State state = State.PENDING; + CharSequence message; + + // Class Variables + + static Pattern sPatternSuppService = Pattern.compile( + "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)"); +/* 1 2 3 4 5 6 7 8 9 10 11 12 + + 1 = Full string up to and including # + 2 = action + 3 = service code + 5 = SIA + 7 = SIB + 9 = SIC + 10 = dialing number +*/ + + static final int MATCH_GROUP_POUND_STRING = 1; + static final int MATCH_GROUP_ACTION = 2; + static final int MATCH_GROUP_SERVICE_CODE = 3; + static final int MATCH_GROUP_SIA = 5; + static final int MATCH_GROUP_SIB = 7; + static final int MATCH_GROUP_SIC = 9; + static final int MATCH_GROUP_PWD_CONFIRM = 11; + static final int MATCH_GROUP_DIALING_NUMBER = 12; + + + // Public Class methods + + /** + * Check if provided string contains Mmi code in it and create corresponding + * Mmi if it does + */ + + public static CdmaMmiCode + newFromDialString(String dialString, CDMAPhone phone) { + Matcher m; + CdmaMmiCode ret = null; + + m = sPatternSuppService.matcher(dialString); + + // Is this formatted like a standard supplementary service code? + if (m.matches()) { + ret = new CdmaMmiCode(phone); + 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)); + + } + + return ret; + } + + // Private Class methods + + /** make empty strings be null. + * Regexp returns empty strings for empty groups + */ + private static String + makeEmptyNull (String s) { + if (s != null && s.length() == 0) return null; + + return s; + } + + // Constructor + + CdmaMmiCode (CDMAPhone phone) { + super(phone.getHandler().getLooper()); + this.phone = phone; + this.context = phone.getContext(); + } + + // MmiCode implementation + + public State + getState() { + return state; + } + + public CharSequence + getMessage() { + return message; + } + + // inherited javadoc suffices + public void + cancel() { + // Complete or failed cannot be cancelled + if (state == State.COMPLETE || state == State.FAILED) { + return; + } + + state = State.CANCELLED; + phone.onMMIDone (this); + } + + public boolean isCancelable() { + return false; + } + + // Instance Methods + + /** + * @return true if the Service Code is PIN/PIN2/PUK/PUK2-related + */ + boolean isPukCommand() { + return sc != null && sc.equals(SC_PUK); + } + + boolean isRegister() { + return action != null && action.equals(ACTION_REGISTER); + } + + public boolean isUssdRequest() { + Log.w(LOG_TAG, "isUssdRequest is not implemented in CdmaMmiCode"); + return false; + } + + /** Process a MMI PUK code */ + void + processCode () { + try { + if (isPukCommand()) { + // sia = old 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 { + phone.mCM.supplyIccPuk(oldPinOrPuk, newPin, + obtainMessage(EVENT_SET_COMPLETE, this)); + } + } else { + throw new RuntimeException ("Invalid or Unsupported MMI Code"); + } + } 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 handlePasswordError(int res) { + state = State.FAILED; + StringBuilder sb = new StringBuilder(getScString()); + sb.append("\n"); + sb.append(context.getText(res)); + message = sb; + phone.onMMIDone(this); + } + + public void + handleMessage (Message msg) { + AsyncResult ar; + + if (msg.what == EVENT_SET_COMPLETE) { + ar = (AsyncResult) (msg.obj); + onSetComplete(ar); + } else { + Log.e(LOG_TAG, "Unexpected reply"); + } + } + // Private instance methods + + private CharSequence getScString() { + if (sc != null) { + if (isPukCommand()) { + return context.getText(com.android.internal.R.string.PinMmi); + } + } + + return ""; + } + + 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 (isPukCommand()) { + sb.append(context.getText( + com.android.internal.R.string.badPuk)); + } else { + sb.append(context.getText( + com.android.internal.R.string.passwordIncorrect)); + } + } else { + sb.append(context.getText( + com.android.internal.R.string.mmiError)); + } + } else { + sb.append(context.getText( + com.android.internal.R.string.mmiError)); + } + } else if (isRegister()) { + state = State.COMPLETE; + sb.append(context.getText( + com.android.internal.R.string.serviceRegistered)); + } else { + state = State.FAILED; + sb.append(context.getText( + com.android.internal.R.string.mmiError)); + } + + message = sb; + phone.onMMIDone(this); + } + +} diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java index 6ae316d..d720516 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java @@ -94,6 +94,13 @@ final class GsmSMSDispatcher extends SMSDispatcher { SmsMessage sms = (SmsMessage) smsb; boolean handled = false; + if (sms.isTypeZero()) { + // As per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not be + // Displayed/Stored/Notified. They should only be acknowledged. + Log.d(TAG, "Received short message type 0, Dont display or store it. Send Ack"); + return Intents.RESULT_SMS_HANDLED; + } + // Special case the message waiting indicator messages if (sms.isMWISetMessage()) { mGsmPhone.updateMessageWaitingIndicator(true); diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index d627baf..12c6b88 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -111,6 +111,14 @@ public class SmsMessage extends SmsMessageBase{ } /** + * 3GPP TS 23.040 9.2.3.9 specifies that Type Zero messages are indicated + * by TP_PID field set to value 0x40 + */ + public boolean isTypeZero() { + return (protocolIdentifier == 0x40); + } + + /** * TS 27.005 3.4.1 lines[0] and lines[1] are the two lines read from the * +CMT unsolicited response (PDU mode, of course) * +CMT: [<alpha>],<length><CR><LF><pdu> |