diff options
Diffstat (limited to 'telephony')
49 files changed, 860 insertions, 252 deletions
diff --git a/telephony/java/android/telephony/NeighboringCellInfo.java b/telephony/java/android/telephony/NeighboringCellInfo.java index ad7dfc9..2f7666d 100644 --- a/telephony/java/android/telephony/NeighboringCellInfo.java +++ b/telephony/java/android/telephony/NeighboringCellInfo.java @@ -133,8 +133,11 @@ public class NeighboringCellInfo implements Parcelable case NETWORK_TYPE_GPRS: case NETWORK_TYPE_EDGE: mNetworkType = radioType; - mLac = Integer.valueOf(location.substring(0, 4), 16); - mCid = Integer.valueOf(location.substring(4), 16); + // check if 0xFFFFFFFF for UNKNOWN_CID + if (!location.equalsIgnoreCase("FFFFFFFF")) { + mCid = Integer.valueOf(location.substring(4), 16); + mLac = Integer.valueOf(location.substring(0, 4), 16); + } break; case NETWORK_TYPE_UMTS: case NETWORK_TYPE_HSDPA: @@ -293,4 +296,4 @@ public class NeighboringCellInfo implements Parcelable return new NeighboringCellInfo[size]; } }; -}
\ No newline at end of file +} diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index 55d25a5..03194ff 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -732,7 +732,8 @@ public class PhoneNumberUtils return ""; } - if ((bytes[offset] & 0xff) == TOA_International) { + //Only TON field should be taken in consideration + if ((bytes[offset] & 0xf0) == (TOA_International & 0xf0)) { prependPlus = true; } diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 6c66559..35a2c19 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -57,7 +57,7 @@ public class ServiceState implements Parcelable { public static final int STATE_EMERGENCY_ONLY = 2; /** - * Radio of telephony is explictly powered off. + * Radio of telephony is explicitly powered off. */ public static final int STATE_POWER_OFF = 3; @@ -89,6 +89,8 @@ public class ServiceState implements Parcelable { public static final int RADIO_TECHNOLOGY_HSUPA = 10; /** @hide */ public static final int RADIO_TECHNOLOGY_HSPA = 11; + /** @hide */ + public static final int RADIO_TECHNOLOGY_EVDO_B = 12; /** * Available registration states for GSM, UMTS and CDMA. @@ -218,7 +220,8 @@ public class ServiceState implements Parcelable { return 0; } - public static final Parcelable.Creator<ServiceState> CREATOR = new Parcelable.Creator() { + public static final Parcelable.Creator<ServiceState> CREATOR = + new Parcelable.Creator<ServiceState>() { public ServiceState createFromParcel(Parcel in) { return new ServiceState(in); } @@ -229,7 +232,7 @@ public class ServiceState implements Parcelable { }; /** - * Get current servcie state of phone + * Get current service state of phone * * @see #STATE_IN_SERVICE * @see #STATE_OUT_OF_SERVICE @@ -288,10 +291,10 @@ public class ServiceState implements Parcelable { } /** - * Get current registered operator name in long alphanumeric format + * Get current registered operator name in long alphanumeric format. * - * In GSM/UMTS, long format can be upto 16 characters long - * In CDMA, returns the ERI text, if set, otherwise the ONS + * In GSM/UMTS, long format can be up to 16 characters long. + * In CDMA, returns the ERI text, if set. Otherwise, returns the ONS. * * @return long name of operator, null if unregistered or unknown */ @@ -300,9 +303,9 @@ public class ServiceState implements Parcelable { } /** - * Get current registered operator name in short lphanumeric format + * Get current registered operator name in short alphanumeric format. * - * In GSM/UMST, short format can be upto 8 characters long + * In GSM/UMTS, short format can be up to 8 characters long. * * @return short name of operator, null if unregistered or unknown */ @@ -311,21 +314,23 @@ public class ServiceState implements Parcelable { } /** - * Get current registered operator numeric id + * Get current registered operator numeric id. * * In GSM/UMTS, numeric format is 3 digit country code plus 2 or 3 digit - * network code - * - * The country code can be decoded using MccTable.countryCodeForMcc() + * network code. * * @return numeric format of operator, null if unregistered or unknown */ + /* + * The country code can be decoded using + * {@link com.android.internal.telephony.MccTable#countryCodeForMcc(int)}. + */ public String getOperatorNumeric() { return mOperatorNumeric; } /** - * Get current network selection mode + * Get current network selection mode. * * @return true if manual mode, false if automatic mode */ @@ -379,7 +384,6 @@ public class ServiceState implements Parcelable { @Override public String toString() { String radioTechnology = new String("Error in radioTechnology"); - switch(this.mRadioTechnology) { case 0: radioTechnology = "Unknown"; @@ -417,6 +421,9 @@ public class ServiceState implements Parcelable { case 11: radioTechnology = "HSPA"; break; + case 12: + radioTechnology = "EvDo rev. B"; + break; default: Log.w(LOG_TAG, "mRadioTechnology variable out of range."); break; @@ -454,7 +461,7 @@ public class ServiceState implements Parcelable { mIsEmergencyOnly = false; } - // TODO - can't this be combined with the above func.. + // TODO - can't this be combined with the above method? public void setStateOff() { mState = STATE_POWER_OFF; mRoaming = false; @@ -524,8 +531,8 @@ public class ServiceState implements Parcelable { } /** - * In CDMA mOperatorAlphaLong can be set from the ERI - * text, this is done from the CDMAPhone and not from the CdmaServiceStateTracker + * In CDMA, mOperatorAlphaLong can be set from the ERI text. + * This is done from the CDMAPhone and not from the CdmaServiceStateTracker. * * @hide */ @@ -538,7 +545,7 @@ public class ServiceState implements Parcelable { } /** - * Test whether two objects hold the same data values or both are null + * Test whether two objects hold the same data values or both are null. * * @param a first obj * @param b second obj @@ -549,7 +556,7 @@ public class ServiceState implements Parcelable { } /** - * Set ServiceState based on intent notifier map + * Set ServiceState based on intent notifier map. * * @param m intent notifier map * @hide @@ -571,7 +578,7 @@ public class ServiceState implements Parcelable { } /** - * Set intent notifier Bundle based on service state + * Set intent notifier Bundle based on service state. * * @param m intent notifier Bundle * @hide diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index 3122722..f5e9751 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -398,4 +398,6 @@ public final class SmsManager { static public final int RESULT_ERROR_NO_SERVICE = 4; /** Failed because we reached the sending queue limit. {@hide} */ static public final int RESULT_ERROR_LIMIT_EXCEEDED = 5; + /** Failed because FDN is enabled. {@hide} */ + static public final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 4ee9560..aa916e0 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -391,6 +391,9 @@ public class TelephonyManager { public static final int NETWORK_TYPE_HSPA = 10; /** Current network is iDen */ public static final int NETWORK_TYPE_IDEN = 11; + /** Current network is EVDO revision B*/ + public static final int NETWORK_TYPE_EVDO_B = 12; + /** * Returns a constant indicating the radio technology (network type) @@ -407,6 +410,7 @@ public class TelephonyManager { * @see #NETWORK_TYPE_CDMA * @see #NETWORK_TYPE_EVDO_0 * @see #NETWORK_TYPE_EVDO_A + * @see #NETWORK_TYPE_EVDO_B * @see #NETWORK_TYPE_1xRTT */ public int getNetworkType() { @@ -454,6 +458,8 @@ public class TelephonyManager { return "CDMA - EvDo rev. 0"; case NETWORK_TYPE_EVDO_A: return "CDMA - EvDo rev. A"; + case NETWORK_TYPE_EVDO_B: + return "CDMA - EvDo rev. B"; case NETWORK_TYPE_1xRTT: return "CDMA - 1xRTT"; default: diff --git a/telephony/java/android/telephony/gsm/SmsManager.java b/telephony/java/android/telephony/gsm/SmsManager.java index 241c485..3b75298 100644 --- a/telephony/java/android/telephony/gsm/SmsManager.java +++ b/telephony/java/android/telephony/gsm/SmsManager.java @@ -56,7 +56,7 @@ import java.util.ArrayList; * the current default SMSC * @param text the body of the message to send * @param sentIntent if not NULL this <code>PendingIntent</code> is - * broadcast when the message is sucessfully sent, or failed. + * broadcast when the message is successfully sent, or failed. * The result code will be <code>Activity.RESULT_OK<code> for success, * or one of these errors: * <code>RESULT_ERROR_GENERIC_FAILURE</code> diff --git a/telephony/java/com/android/internal/telephony/AdnRecord.java b/telephony/java/com/android/internal/telephony/AdnRecord.java index 0896ba6..1bf2d3c 100644 --- a/telephony/java/com/android/internal/telephony/AdnRecord.java +++ b/telephony/java/com/android/internal/telephony/AdnRecord.java @@ -19,10 +19,9 @@ package com.android.internal.telephony; import android.os.Parcel; import android.os.Parcelable; import android.telephony.PhoneNumberUtils; +import android.text.TextUtils; import android.util.Log; -import com.android.internal.telephony.GsmAlphabet; - import java.util.Arrays; @@ -38,8 +37,8 @@ public class AdnRecord implements Parcelable { //***** Instance Variables - String alphaTag = ""; - String number = ""; + String alphaTag = null; + String number = null; String[] emails; int extRecord = 0xff; int efid; // or 0 if none @@ -63,8 +62,8 @@ public class AdnRecord implements Parcelable { // ADN offset static final int ADN_BCD_NUMBER_LENGTH = 0; static final int ADN_TON_AND_NPI = 1; - static final int ADN_DAILING_NUMBER_START = 2; - static final int ADN_DAILING_NUMBER_END = 11; + static final int ADN_DIALING_NUMBER_START = 2; + static final int ADN_DIALING_NUMBER_END = 11; static final int ADN_CAPABILITY_ID = 12; static final int ADN_EXTENSION_ID = 13; @@ -152,17 +151,31 @@ public class AdnRecord implements Parcelable { } public boolean isEmpty() { - return alphaTag.equals("") && number.equals("") && emails == null; + return TextUtils.isEmpty(alphaTag) && TextUtils.isEmpty(number) && emails == null; } public boolean hasExtendedRecord() { return extRecord != 0 && extRecord != 0xff; } + /** Helper function for {@link #isEqual}. */ + private static boolean stringCompareNullEqualsEmpty(String s1, String s2) { + if (s1 == s2) { + return true; + } + if (s1 == null) { + s1 = ""; + } + if (s2 == null) { + s2 = ""; + } + return (s1.equals(s2)); + } + public boolean isEqual(AdnRecord adn) { - return ( alphaTag.equals(adn.getAlphaTag()) && - number.equals(adn.getNumber()) && - Arrays.equals(emails, adn.getEmails())); + return ( stringCompareNullEqualsEmpty(alphaTag, adn.alphaTag) && + stringCompareNullEqualsEmpty(number, adn.number) && + Arrays.equals(emails, adn.emails)); } //***** Parcelable Implementation @@ -184,36 +197,33 @@ public class AdnRecord implements Parcelable { * * @param recordSize is the size X of EF record * @return hex byte[recordSize] to be written to EF record - * return nulll for wrong format of dialing nubmer or tag + * return null for wrong format of dialing number or tag */ public byte[] buildAdnString(int recordSize) { byte[] bcdNumber; byte[] byteTag; - byte[] adnString = null; + byte[] adnString; int footerOffset = recordSize - FOOTER_SIZE_BYTES; - if (number == null || number.equals("") || - alphaTag == null || alphaTag.equals("")) { + // create an empty record + adnString = new byte[recordSize]; + for (int i = 0; i < recordSize; i++) { + adnString[i] = (byte) 0xFF; + } - Log.w(LOG_TAG, "[buildAdnString] Empty alpha tag or number"); - adnString = new byte[recordSize]; - for (int i = 0; i < recordSize; i++) { - adnString[i] = (byte) 0xFF; - } + if (TextUtils.isEmpty(number)) { + Log.w(LOG_TAG, "[buildAdnString] Empty dialing number"); + return adnString; // return the empty record (for delete) } else if (number.length() - > (ADN_DAILING_NUMBER_END - ADN_DAILING_NUMBER_START + 1) * 2) { + > (ADN_DIALING_NUMBER_END - ADN_DIALING_NUMBER_START + 1) * 2) { Log.w(LOG_TAG, - "[buildAdnString] Max length of dailing number is 20"); - } else if (alphaTag.length() > footerOffset) { + "[buildAdnString] Max length of dialing number is 20"); + return null; + } else if (alphaTag != null && alphaTag.length() > footerOffset) { Log.w(LOG_TAG, "[buildAdnString] Max length of tag is " + footerOffset); + return null; } else { - - adnString = new byte[recordSize]; - for (int i = 0; i < recordSize; i++) { - adnString[i] = (byte) 0xFF; - } - bcdNumber = PhoneNumberUtils.numberToCalledPartyBCD(number); System.arraycopy(bcdNumber, 0, adnString, @@ -222,16 +232,17 @@ public class AdnRecord implements Parcelable { adnString[footerOffset + ADN_BCD_NUMBER_LENGTH] = (byte) (bcdNumber.length); adnString[footerOffset + ADN_CAPABILITY_ID] - = (byte) 0xFF; // Capacility Id + = (byte) 0xFF; // Capability Id adnString[footerOffset + ADN_EXTENSION_ID] = (byte) 0xFF; // Extension Record Id - byteTag = GsmAlphabet.stringToGsm8BitPacked(alphaTag); - System.arraycopy(byteTag, 0, adnString, 0, byteTag.length); + if (!TextUtils.isEmpty(alphaTag)) { + byteTag = GsmAlphabet.stringToGsm8BitPacked(alphaTag); + System.arraycopy(byteTag, 0, adnString, 0, byteTag.length); + } + return adnString; } - - return adnString; } /** diff --git a/telephony/java/com/android/internal/telephony/AdnRecordLoader.java b/telephony/java/com/android/internal/telephony/AdnRecordLoader.java index cfb5aaa..55bdc06 100644 --- a/telephony/java/com/android/internal/telephony/AdnRecordLoader.java +++ b/telephony/java/com/android/internal/telephony/AdnRecordLoader.java @@ -106,7 +106,7 @@ public class AdnRecordLoader extends Handler { * It will get the record size of EF record and compose hex adn array * then write the hex array to EF record * - * @param adn is set with alphaTag and phoneNubmer + * @param adn is set with alphaTag and phone number * @param ef EF fileid * @param extensionEF extension EF fileid * @param recordNumber 1-based record index @@ -159,7 +159,7 @@ public class AdnRecordLoader extends Handler { data = adn.buildAdnString(recordSize[0]); if(data == null) { - throw new RuntimeException("worong ADN format", + throw new RuntimeException("wrong ADN format", ar.exception); } @@ -218,7 +218,7 @@ public class AdnRecordLoader extends Handler { throw new RuntimeException("load failed", ar.exception); } - Log.d(LOG_TAG,"ADN extention EF: 0x" + Log.d(LOG_TAG,"ADN extension EF: 0x" + Integer.toHexString(extensionEF) + ":" + adn.extRecord + "\n" + IccUtils.bytesToHexString(data)); diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java index 802e79b..798a5a5 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java +++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java @@ -284,7 +284,7 @@ public class CallerInfoAsyncQuery { */ public static CallerInfoAsyncQuery startQuery(int token, Context context, String number, OnQueryCompleteListener listener, Object cookie) { - //contruct the URI object and start Query. + //construct the URI object and start Query. Uri contactRef = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)); CallerInfoAsyncQuery c = new CallerInfoAsyncQuery(); diff --git a/telephony/java/com/android/internal/telephony/CommandException.java b/telephony/java/com/android/internal/telephony/CommandException.java index eb0a440..94c544e 100644 --- a/telephony/java/com/android/internal/telephony/CommandException.java +++ b/telephony/java/com/android/internal/telephony/CommandException.java @@ -37,6 +37,10 @@ public class CommandException extends RuntimeException { OP_NOT_ALLOWED_DURING_VOICE_CALL, OP_NOT_ALLOWED_BEFORE_REG_NW, SMS_FAIL_RETRY, + SIM_ABSENT, + SUBSCRIPTION_NOT_AVAILABLE, + MODE_NOT_SUPPORTED, + FDN_CHECK_FAILURE, ILLEGAL_SIM_OR_ME, } @@ -69,6 +73,14 @@ public class CommandException extends RuntimeException { return new CommandException(Error.OP_NOT_ALLOWED_BEFORE_REG_NW); case RILConstants.SMS_SEND_FAIL_RETRY: return new CommandException(Error.SMS_FAIL_RETRY); + case RILConstants.SIM_ABSENT: + return new CommandException(Error.SIM_ABSENT); + case RILConstants.SUBSCRIPTION_NOT_AVAILABLE: + return new CommandException(Error.SUBSCRIPTION_NOT_AVAILABLE); + case RILConstants.MODE_NOT_SUPPORTED: + return new CommandException(Error.MODE_NOT_SUPPORTED); + case RILConstants.FDN_CHECK_FAILURE: + return new CommandException(Error.FDN_CHECK_FAILURE); case RILConstants.ILLEGAL_SIM_OR_ME: return new CommandException(Error.ILLEGAL_SIM_OR_ME); default: diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java index d90c305..8e03c5a 100644 --- a/telephony/java/com/android/internal/telephony/CommandsInterface.java +++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java @@ -664,6 +664,19 @@ public interface CommandsInterface { * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure * ar.userObject contains the orignal value of result.obj + * ar.result is null on success and failure + * + * CLIR_DEFAULT == on "use subscription default value" + * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation) + * CLIR_INVOCATION == on "CLIR invocation" (restrict CLI presentation) + */ + void dial(String address, int clirMode, UUSInfo uusInfo, Message result); + + /** + * returned message + * retMsg.obj = AsyncResult ar + * ar.exception carries exception on failure + * ar.userObject contains the orignal value of result.obj * ar.result is String containing IMSI on success */ void getIMSI(Message result); diff --git a/telephony/java/com/android/internal/telephony/Connection.java b/telephony/java/com/android/internal/telephony/Connection.java index 37e8a99..11d0b1b 100644 --- a/telephony/java/com/android/internal/telephony/Connection.java +++ b/telephony/java/com/android/internal/telephony/Connection.java @@ -45,17 +45,18 @@ public abstract class Connection { POWER_OFF, /* radio is turned off explicitly */ OUT_OF_SERVICE, /* out of service */ ICC_ERROR, /* No ICC, ICC locked, or other ICC error */ - CALL_BARRED, /* call was blocked by call barrring */ + CALL_BARRED, /* call was blocked by call barring */ FDN_BLOCKED, /* call was blocked by fixed dial number */ CS_RESTRICTED, /* call was blocked by restricted all voice access */ CS_RESTRICTED_NORMAL, /* call was blocked by restricted normal voice access */ CS_RESTRICTED_EMERGENCY, /* call was blocked by restricted emergency voice access */ + UNOBTAINABLE_NUMBER, /* Unassigned number (3GPP TS 24.008 table 10.5.123) */ CDMA_LOCKED_UNTIL_POWER_CYCLE, /* MS is locked until next power cycle */ CDMA_DROP, CDMA_INTERCEPT, /* INTERCEPT order received, MS state idle entered */ CDMA_REORDER, /* MS has been redirected, call is cancelled */ CDMA_SO_REJECT, /* service option rejection */ - CDMA_RETRY_ORDER, /* requeseted service is rejected, retry delay is set */ + CDMA_RETRY_ORDER, /* requested service is rejected, retry delay is set */ CDMA_ACCESS_FAILURE, CDMA_PREEMPTED, CDMA_NOT_EMERGENCY, /* not an emergency call */ @@ -68,8 +69,8 @@ public abstract class Connection { /* Instance Methods */ /** - * Gets address (e.g., phone number) associated with connection - * TODO: distinguish reasons for unavailablity + * Gets address (e.g. phone number) associated with connection. + * TODO: distinguish reasons for unavailability * * @return address or null if unavailable */ @@ -77,7 +78,7 @@ public abstract class Connection { public abstract String getAddress(); /** - * Gets cdma CNAP name associated with connection + * Gets CDMA CNAP name associated with connection. * @return cnap name or null if unavailable */ public String getCnapName() { @@ -85,15 +86,15 @@ public abstract class Connection { } /** - * Get orignal dial string - * @return orignal dial string or null if unavailable + * Get original dial string. + * @return original dial string or null if unavailable */ public String getOrigDialString(){ return null; } /** - * Gets cdma CNAP presentation associated with connection + * Gets CDMA CNAP presentation associated with connection. * @return cnap name or null if unavailable */ @@ -115,45 +116,45 @@ public abstract class Connection { public abstract long getCreateTime(); /** - * Connection connect time in currentTimeMillis() format - * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition - * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition - * Returns 0 before then + * Connection connect time in currentTimeMillis() format. + * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition. + * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition. + * Returns 0 before then. */ public abstract long getConnectTime(); /** - * Disconnect time in currentTimeMillis() format - * The time when this Connection makes a transition into ENDED or FAIL - * Returns 0 before then + * Disconnect time in currentTimeMillis() format. + * The time when this Connection makes a transition into ENDED or FAIL. + * Returns 0 before then. */ public abstract long getDisconnectTime(); /** - * returns the number of milliseconds the call has been connected, + * Returns the number of milliseconds the call has been connected, * or 0 if the call has never connected. * If the call is still connected, then returns the elapsed - * time since connect + * time since connect. */ public abstract long getDurationMillis(); /** * If this connection is HOLDING, return the number of milliseconds - * that it has been on hold for (approximently) - * If this connection is in any other state, return 0 + * that it has been on hold for (approximately). + * If this connection is in any other state, return 0. */ public abstract long getHoldDurationMillis(); /** - * Returns "NOT_DISCONNECTED" if not yet disconnected + * Returns "NOT_DISCONNECTED" if not yet disconnected. */ public abstract DisconnectCause getDisconnectCause(); /** * Returns true of this connection originated elsewhere * ("MT" or mobile terminated; another party called this terminal) - * or false if this call originated here (MO or mobile originated) + * or false if this call originated here (MO or mobile originated). */ public abstract boolean isIncoming(); @@ -273,6 +274,13 @@ public abstract class Connection { public abstract int getNumberPresentation(); /** + * Returns the User to User Signaling (UUS) information associated with + * incoming and waiting calls + * @return UUSInfo containing the UUS userdata. + */ + public abstract UUSInfo getUUSInfo(); + + /** * Build a human representation of a connection instance, suitable for debugging. * Don't log personal stuff unless in debug mode. * @return a string representing the internal state of this connection. diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java index 1f8bbcf..6634017 100644 --- a/telephony/java/com/android/internal/telephony/DataConnection.java +++ b/telephony/java/com/android/internal/telephony/DataConnection.java @@ -164,7 +164,7 @@ public abstract class DataConnection extends HierarchicalStateMachine { NONE, OPERATOR_BARRED, INSUFFICIENT_RESOURCES, - MISSING_UKNOWN_APN, + MISSING_UNKNOWN_APN, UNKNOWN_PDP_ADDRESS, USER_AUTHENTICATION, ACTIVATION_REJECT_GGSN, @@ -181,7 +181,7 @@ public abstract class DataConnection extends HierarchicalStateMachine { RADIO_NOT_AVAILABLE; public boolean isPermanentFail() { - return (this == OPERATOR_BARRED) || (this == MISSING_UKNOWN_APN) || + return (this == OPERATOR_BARRED) || (this == MISSING_UNKNOWN_APN) || (this == UNKNOWN_PDP_ADDRESS) || (this == USER_AUTHENTICATION) || (this == ACTIVATION_REJECT_GGSN) || (this == ACTIVATION_REJECT_UNSPECIFIED) || (this == SERVICE_OPTION_NOT_SUPPORTED) || @@ -208,12 +208,12 @@ public abstract class DataConnection extends HierarchicalStateMachine { return "Operator Barred"; case INSUFFICIENT_RESOURCES: return "Insufficient Resources"; - case MISSING_UKNOWN_APN: + case MISSING_UNKNOWN_APN: return "Missing / Unknown APN"; case UNKNOWN_PDP_ADDRESS: return "Unknown PDP Address"; case USER_AUTHENTICATION: - return "Error User Autentication"; + return "Error User Authentication"; case ACTIVATION_REJECT_GGSN: return "Activation Reject GGSN"; case ACTIVATION_REJECT_UNSPECIFIED: diff --git a/telephony/java/com/android/internal/telephony/DriverCall.java b/telephony/java/com/android/internal/telephony/DriverCall.java index 66f6b9c..663c284 100644 --- a/telephony/java/com/android/internal/telephony/DriverCall.java +++ b/telephony/java/com/android/internal/telephony/DriverCall.java @@ -49,6 +49,7 @@ public class DriverCall implements Comparable { public int numberPresentation; public String name; public int namePresentation; + public UUSInfo uusInfo; /** returns null on error */ static DriverCall diff --git a/telephony/java/com/android/internal/telephony/IccProvider.java b/telephony/java/com/android/internal/telephony/IccProvider.java index fa91457..3471ec2 100644 --- a/telephony/java/com/android/internal/telephony/IccProvider.java +++ b/telephony/java/com/android/internal/telephony/IccProvider.java @@ -417,11 +417,11 @@ public class IccProvider extends ContentProvider { } } - if (TextUtils.isEmpty(tag)) { + if (TextUtils.isEmpty(number)) { return 0; } - if (efType == FDN && TextUtils.isEmpty(pin2)) { + if (efType == IccConstants.EF_FDN && TextUtils.isEmpty(pin2)) { return 0; } diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java index 7179bef..23325f6 100644 --- a/telephony/java/com/android/internal/telephony/Phone.java +++ b/telephony/java/com/android/internal/telephony/Phone.java @@ -243,15 +243,14 @@ public interface Phone { /** * Get the current DataState. No change notification exists at this * interface -- use - * {@link com.android.telephony.PhoneStateListener PhoneStateListener} - * instead. + * {@link android.telephony.PhoneStateListener} instead. */ DataState getDataConnectionState(); /** * Get the current DataActivityState. No change notification exists at this * interface -- use - * {@link TelephonyManager} instead. + * {@link android.telephony.TelephonyManager} instead. */ DataActivityState getDataActivityState(); @@ -789,6 +788,19 @@ public interface Phone { Connection dial(String dialString) throws CallStateException; /** + * Initiate a new voice connection with supplementary User to User + * Information. This happens asynchronously, so you cannot assume the audio + * path is connected (or a call index has been assigned) until + * PhoneStateChanged notification has occurred. + * + * @exception CallStateException if a new outgoing call is not currently + * possible because no more call slots exist or a call exists + * that is dialing, alerting, ringing, or waiting. Other + * errors are handled asynchronously. + */ + Connection dial(String dialString, UUSInfo uusInfo) throws CallStateException; + + /** * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated * without SEND (so <code>dial</code> is not appropriate). * @@ -840,7 +852,7 @@ public interface Phone { * @param dtmfString is string representing the dialing digit(s) in the active call * @param on the DTMF ON length in milliseconds, or 0 for default * @param off the DTMF OFF length in milliseconds, or 0 for default - * @param onCompelte is the callback message when the action is processed by BP + * @param onComplete is the callback message when the action is processed by BP * */ void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete); @@ -980,7 +992,7 @@ public interface Phone { * ((AsyncResult)onComplete.obj) is an array of int, with a length of 2. * * @param onComplete a callback message when the action is completed. - * @see com.android.internal.telephony.CommandsInterface.getCLIR for details. + * @see com.android.internal.telephony.CommandsInterface#getCLIR for details. */ void getOutgoingCallerIdDisplay(Message onComplete); @@ -1002,7 +1014,7 @@ public interface Phone { * ((AsyncResult)onComplete.obj) is an array of int, with a length of 1. * * @param onComplete a callback message when the action is completed. - * @see com.android.internal.telephony.CommandsInterface.queryCallWaiting for details. + * @see com.android.internal.telephony.CommandsInterface#queryCallWaiting for details. */ void getCallWaiting(Message onComplete); @@ -1445,7 +1457,7 @@ public interface Phone { * setTTYMode * sets a TTY mode option. * - * @param enable is a boolean representing the state that you are + * @param ttyMode is a boolean representing the state that you are * requesting, true for enabled, false for disabled. * @param onComplete a callback message when the action is completed */ diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java index a8f4143..74601e6 100644 --- a/telephony/java/com/android/internal/telephony/PhoneBase.java +++ b/telephony/java/com/android/internal/telephony/PhoneBase.java @@ -543,7 +543,7 @@ public abstract class PhoneBase extends Handler implements Phone { private void setPropertiesByCarrier() { String carrier = SystemProperties.get("ro.carrier"); - if (null == carrier || 0 == carrier.length()) { + if (null == carrier || 0 == carrier.length() || "unknown".equals(carrier)) { return; } diff --git a/telephony/java/com/android/internal/telephony/PhoneFactory.java b/telephony/java/com/android/internal/telephony/PhoneFactory.java index cd72752..803b736 100644 --- a/telephony/java/com/android/internal/telephony/PhoneFactory.java +++ b/telephony/java/com/android/internal/telephony/PhoneFactory.java @@ -109,13 +109,13 @@ public class PhoneFactory { int phoneType = getPhoneType(networkMode); if (phoneType == Phone.PHONE_TYPE_GSM) { + Log.i(LOG_TAG, "Creating GSMPhone"); sProxyPhone = new PhoneProxy(new GSMPhone(context, sCommandsInterface, sPhoneNotifier)); - Log.i(LOG_TAG, "Creating GSMPhone"); } else if (phoneType == Phone.PHONE_TYPE_CDMA) { + Log.i(LOG_TAG, "Creating CDMAPhone"); sProxyPhone = new PhoneProxy(new CDMAPhone(context, sCommandsInterface, sPhoneNotifier)); - Log.i(LOG_TAG, "Creating CDMAPhone"); } sMadeDefaults = true; diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java index 6d3798e..e1511e6 100644 --- a/telephony/java/com/android/internal/telephony/PhoneProxy.java +++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java @@ -423,6 +423,10 @@ public class PhoneProxy extends Handler implements Phone { return mActivePhone.dial(dialString); } + public Connection dial(String dialString, UUSInfo uusInfo) throws CallStateException { + return mActivePhone.dial(dialString, uusInfo); + } + public boolean handlePinMmi(String dialString) { return mActivePhone.handlePinMmi(dialString); } diff --git a/telephony/java/com/android/internal/telephony/PhoneSubInfo.java b/telephony/java/com/android/internal/telephony/PhoneSubInfo.java index 0b55736..86c86bb 100644 --- a/telephony/java/com/android/internal/telephony/PhoneSubInfo.java +++ b/telephony/java/com/android/internal/telephony/PhoneSubInfo.java @@ -69,7 +69,7 @@ public class PhoneSubInfo extends IPhoneSubInfo.Stub { } /** - * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones. + * Retrieves the unique subscriber ID, e.g., IMSI for GSM phones. */ public String getSubscriberId() { mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE"); diff --git a/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java b/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java index a036046..7009893 100644 --- a/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java +++ b/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java @@ -47,7 +47,7 @@ public class PhoneSubInfoProxy extends IPhoneSubInfo.Stub { } /** - * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones. + * Retrieves the unique subscriber ID, e.g., IMSI for GSM phones. */ public String getSubscriberId() { return mPhoneSubInfo.getSubscriberId(); diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java index d8e313a..3d410fd 100644 --- a/telephony/java/com/android/internal/telephony/RIL.java +++ b/telephony/java/com/android/internal/telephony/RIL.java @@ -796,12 +796,26 @@ public final class RIL extends BaseCommands implements CommandsInterface { public void dial (String address, int clirMode, Message result) { + dial(address, clirMode, null, result); + } + + public void + dial(String address, int clirMode, UUSInfo uusInfo, Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result); rr.mp.writeString(address); rr.mp.writeInt(clirMode); rr.mp.writeInt(0); // UUS information is absent + if (uusInfo == null) { + rr.mp.writeInt(0); // UUS information is absent + } else { + rr.mp.writeInt(1); // UUS information is present + rr.mp.writeInt(uusInfo.getType()); + rr.mp.writeInt(uusInfo.getDcs()); + rr.mp.writeByteArray(uusInfo.getUserData()); + } + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); send(rr); @@ -2837,10 +2851,21 @@ public final class RIL extends BaseCommands implements CommandsInterface { dc.namePresentation = p.readInt(); int uusInfoPresent = p.readInt(); if (uusInfoPresent == 1) { - // TODO: Copy the data to dc to forward to the apps. - p.readInt(); - p.readInt(); - p.createByteArray(); + dc.uusInfo = new UUSInfo(); + dc.uusInfo.setType(p.readInt()); + dc.uusInfo.setDcs(p.readInt()); + byte[] userData = p.createByteArray(); + dc.uusInfo.setUserData(userData); + Log + .v(LOG_TAG, String.format("Incoming UUS : type=%d, dcs=%d, length=%d", + dc.uusInfo.getType(), dc.uusInfo.getDcs(), + dc.uusInfo.getUserData().length)); + Log.v(LOG_TAG, "Incoming UUS : data (string)=" + + new String(dc.uusInfo.getUserData())); + Log.v(LOG_TAG, "Incoming UUS : data (hex): " + + IccUtils.bytesToHexString(dc.uusInfo.getUserData())); + } else { + Log.v(LOG_TAG, "Incoming UUS : NOT present!"); } // Make sure there's a leading + on addresses with a TOA of 145 diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 01f4ab2..71a80e0 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -45,6 +45,11 @@ public interface RILConstants { int OP_NOT_ALLOWED_BEFORE_REG_NW = 9; /* request is not allowed before device registers to network */ int SMS_SEND_FAIL_RETRY = 10; /* send sms fail and need retry */ + int SIM_ABSENT = 11; /* ICC card is absent */ + int SUBSCRIPTION_NOT_AVAILABLE = 12; /* fail to find CDMA subscription from specified + location */ + int MODE_NOT_SUPPORTED = 13; /* HW does not support preferred network type */ + int FDN_CHECK_FAILURE = 14; /* send operation barred error when FDN is enabled */ int ILLEGAL_SIM_OR_ME = 15; /* network selection failure due to wrong SIM/ME and no retries needed */ diff --git a/telephony/java/com/android/internal/telephony/RetryManager.java b/telephony/java/com/android/internal/telephony/RetryManager.java index 779f358..b1049a2 100644 --- a/telephony/java/com/android/internal/telephony/RetryManager.java +++ b/telephony/java/com/android/internal/telephony/RetryManager.java @@ -25,7 +25,7 @@ import java.util.ArrayList; /** * Retry manager allows a simple way to declare a series of - * retires timeouts. After creating a RetryManager the configure + * retry timeouts. After creating a RetryManager the configure * method is used to define the sequence. A simple linear series * may be initialized using configure with three integer parameters * The other configure method allows a series to be declared using @@ -54,18 +54,18 @@ import java.util.ArrayList; *<p> * Examples: * <ul> - * <li>3 retires with no randomization value which means its 0: + * <li>3 retries with no randomization value which means its 0: * <ul><li><code>"1000, 2000, 3000"</code></ul> * - * <li>10 retires with a 500 default randomization value for each and + * <li>10 retries with a 500 default randomization value for each and * the 4..10 retries all using 3000 as the delay: * <ul><li><code>"max_retries=10, default_randomization=500, 1000, 2000, 3000"</code></ul> * - * <li>4 retires with a 100 as the default randomization value for the first 2 values and + * <li>4 retries with a 100 as the default randomization value for the first 2 values and * the other two having specified values of 500: * <ul><li><code>"default_randomization=100, 1000, 2000, 4000:500, 5000:500"</code></ul> * - * <li>Infinite number of retires with the first one at 1000, the second at 2000 all + * <li>Infinite number of retries with the first one at 1000, the second at 2000 all * others will be at 3000. * <ul><li><code>"max_retries=infinite,1000,2000,3000</code></ul> * </ul> @@ -75,9 +75,6 @@ import java.util.ArrayList; public class RetryManager { static public final String LOG_TAG = "RetryManager"; static public final boolean DBG = false; - static public final int RETRYIES_NOT_STARTED = 0; - static public final int RETRYIES_ON_GOING = 1; - static public final int RETRYIES_COMPLETED = 2; /** * Retry record with times in milli-seconds @@ -104,7 +101,7 @@ public class RetryManager { */ private int mMaxRetryCount; - /** The current number of retires */ + /** The current number of retries */ private int mRetryCount; /** Random number generator */ @@ -125,7 +122,7 @@ public class RetryManager { * @param randomizationTime a random value between 0 and * randomizationTime will be added to retryTime. this * parameter may be 0. - * @return true if successfull + * @return true if successful */ public boolean configure(int maxRetryCount, int retryTime, int randomizationTime) { Pair<Boolean, Integer> value; @@ -242,7 +239,7 @@ public class RetryManager { /** * Report whether data reconnection should be retried * - * @return {@code true} if the max retires has not been reached. {@code + * @return {@code true} if the max retries has not been reached. {@code * false} otherwise. */ public boolean isRetryNeeded() { @@ -289,7 +286,7 @@ public class RetryManager { if (mRetryCount > mMaxRetryCount) { mRetryCount = mMaxRetryCount; } - if (DBG) log("increseRetryCount: " + mRetryCount); + if (DBG) log("increaseRetryCount: " + mRetryCount); } /** diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java index 764d12e..ca526a5 100644 --- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java @@ -62,6 +62,7 @@ import static android.telephony.SmsManager.RESULT_ERROR_NO_SERVICE; import static android.telephony.SmsManager.RESULT_ERROR_NULL_PDU; import static android.telephony.SmsManager.RESULT_ERROR_RADIO_OFF; import static android.telephony.SmsManager.RESULT_ERROR_LIMIT_EXCEEDED; +import static android.telephony.SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE; public abstract class SMSDispatcher extends Handler { @@ -499,13 +500,20 @@ public abstract class SMSDispatcher extends Handler { Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker); sendMessageDelayed(retryMsg, SEND_RETRY_DELAY); } else if (tracker.mSentIntent != null) { + int error = RESULT_ERROR_GENERIC_FAILURE; + + if (((CommandException)(ar.exception)).getCommandError() + == CommandException.Error.FDN_CHECK_FAILURE) { + error = RESULT_ERROR_FDN_CHECK_FAILURE; + } // Done retrying; return an error to the app. try { Intent fillIn = new Intent(); if (ar.result != null) { fillIn.putExtra("errorCode", ((SmsResponse)ar.result).errorCode); } - tracker.mSentIntent.send(mContext, RESULT_ERROR_GENERIC_FAILURE, fillIn); + tracker.mSentIntent.send(mContext, error, fillIn); + } catch (CanceledException ex) {} } } diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java index 7383649..e8bbe5e 100644 --- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java @@ -44,6 +44,7 @@ public abstract class ServiceStateTracker extends Handler { protected static final int DATA_ACCESS_HSDPA = 9; protected static final int DATA_ACCESS_HSUPA = 10; protected static final int DATA_ACCESS_HSPA = 11; + protected static final int DATA_ACCESS_CDMA_EvDo_B = 12; protected CommandsInterface cm; @@ -206,8 +207,8 @@ public abstract class ServiceStateTracker extends Handler { } /** - * Reregister network through toggle perferred network type - * This is a work aorund to deregister and register network since there is + * Re-register network by toggling preferred network type. + * This is a work-around to deregister and register network since there is * no ril api to set COPS=2 (deregister) only. * * @param onComplete is dispatched when this is complete. it will be @@ -229,7 +230,7 @@ public abstract class ServiceStateTracker extends Handler { /** * These two flags manage the behavior of the cell lock -- the * lock should be held if either flag is true. The intention is - * to allow temporary aquisition of the lock to get a single + * to allow temporary acquisition of the lock to get a single * update. Such a lock grab and release can thus be made to not * interfere with more permanent lock holds -- in other words, the * lock will only be released if both flags are false, and so diff --git a/telephony/java/com/android/internal/telephony/UUSInfo.java b/telephony/java/com/android/internal/telephony/UUSInfo.java new file mode 100644 index 0000000..801b845 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/UUSInfo.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2010 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; + +public class UUSInfo { + + /* + * User-to-User signaling Info activation types derived from 3GPP 23.087 + * v8.0 + */ + + public static final int UUS_TYPE1_IMPLICIT = 0; + + public static final int UUS_TYPE1_REQUIRED = 1; + + public static final int UUS_TYPE1_NOT_REQUIRED = 2; + + public static final int UUS_TYPE2_REQUIRED = 3; + + public static final int UUS_TYPE2_NOT_REQUIRED = 4; + + public static final int UUS_TYPE3_REQUIRED = 5; + + public static final int UUS_TYPE3_NOT_REQUIRED = 6; + + /* + * User-to-User Signaling Information data coding schemes. Possible values + * for Octet 3 (Protocol Discriminator field) in the UUIE. The values have + * been specified in section 10.5.4.25 of 3GPP TS 24.008 + */ + + public static final int UUS_DCS_USP = 0; /* User specified protocol */ + + public static final int UUS_DCS_OSIHLP = 1; /* OSI higher layer protocol */ + + public static final int UUS_DCS_X244 = 2; /* X.244 */ + + public static final int UUS_DCS_RMCF = 3; /* + * Reserved for system management + * convergence function + */ + + public static final int UUS_DCS_IA5c = 4; /* IA5 characters */ + + private int uusType; + + private int uusDcs; + + private byte[] uusData; + + public UUSInfo() { + this.uusType = UUS_TYPE1_IMPLICIT; + this.uusDcs = UUS_DCS_IA5c; + this.uusData = null; + } + + public UUSInfo(int uusType, int uusDcs, byte[] uusData) { + this.uusType = uusType; + this.uusDcs = uusDcs; + this.uusData = uusData; + } + + public int getDcs() { + return uusDcs; + } + + public void setDcs(int uusDcs) { + this.uusDcs = uusDcs; + } + + public int getType() { + return uusType; + } + + public void setType(int uusType) { + this.uusType = uusType; + } + + public byte[] getUserData() { + return uusData; + } + + public void setUserData(byte[] uusData) { + this.uusData = uusData; + } +} diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java index 1f5accf..0c591e4 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java @@ -62,11 +62,13 @@ import com.android.internal.telephony.PhoneProxy; import com.android.internal.telephony.PhoneSubInfo; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyProperties; +import com.android.internal.telephony.UUSInfo; import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA; 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 +103,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 +222,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(); @@ -344,6 +349,10 @@ public class CDMAPhone extends PhoneBase { return mCT.dial(newDialString); } + public Connection dial(String dialString, UUSInfo uusInfo) throws CallStateException { + throw new CallStateException("Sending UUS information NOT supported in CDMA!"); + } + public SignalStrength getSignalStrength() { return mSST.mSignalStrength; } @@ -355,8 +364,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 +381,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 +489,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 +512,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"); } @@ -1405,5 +1449,4 @@ public class CDMAPhone extends PhoneBase { } return false; } - } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java index 1005d20..3669e60 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java @@ -61,7 +61,7 @@ public final class CdmaCallTracker extends CallTracker { RegistrantList callWaitingRegistrants = new RegistrantList(); - // connections dropped durin last poll + // connections dropped during last poll ArrayList<CdmaConnection> droppedDuringPoll = new ArrayList<CdmaConnection>(MAX_CONNECTIONS); diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java index 188145b..fbe455e 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java @@ -945,4 +945,10 @@ public class CdmaConnection extends Connection { public int getNumberPresentation() { return numberPresentation; } + + @Override + public UUSInfo getUUSInfo() { + // UUS information not supported in CDMA + return null; + } } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java index 217e1e8..9f2a44b 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java @@ -114,7 +114,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { // if we have no active Apn this is null protected ApnSetting mActiveApn; - // Possibly promoate to base class, the only difference is + // Possibly promote to base class, the only difference is // the INTENT_RECONNECT_ALARM action is a different string. // Do consider technology changes if it is promoted. BroadcastReceiver mIntentReceiver = new BroadcastReceiver () @@ -420,7 +420,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { CdmaDataConnection conn = findFreeDataConnection(); if (conn == null) { - if (DBG) log("setupData: No free CdmaDataConnectionfound!"); + if (DBG) log("setupData: No free CdmaDataConnection found!"); return false; } @@ -646,7 +646,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { } /** - * @override com.android.intenral.telephony.DataConnectionTracker + * @override com.android.internal.telephony.DataConnectionTracker */ @Override protected void onEnableNewApn() { 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/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index 39fe007..2cad6cc 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -66,7 +66,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { CdmaCellLocation cellLoc; CdmaCellLocation newCellLoc; - /** if time between NTIZ updates is less than mNitzUpdateSpacing the update may be ignored. */ + /** if time between NITZ updates is less than mNitzUpdateSpacing the update may be ignored. */ private static final int NITZ_UPDATE_SPACING_DEFAULT = 1000 * 60 * 10; private int mNitzUpdateSpacing = SystemProperties.getInt("ro.nitz_update_spacing", NITZ_UPDATE_SPACING_DEFAULT); @@ -395,7 +395,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { } // Release any temporary cell lock, which could have been - // aquired to allow a single-shot location update. + // acquired to allow a single-shot location update. disableSingleLocationUpdate(); break; @@ -591,7 +591,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { boolean showPlmn = false; int rule = 0; if (cm.getRadioState().isRUIMReady()) { - // TODO RUIM SPN is not implemnted, EF_SPN has to be read and Display Condition + // TODO RUIM SPN is not implemented, EF_SPN has to be read and Display Condition // Character Encoding, Language Indicator and SPN has to be set // rule = phone.mRuimRecords.getDisplayRule(ss.getOperatorNumeric()); // spn = phone.mSIMRecords.getServiceProvideName(); @@ -872,7 +872,6 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { * and start over again if the radio notifies us that some * event has changed */ - private void pollState() { pollingContext = new int[1]; @@ -945,6 +944,9 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { case DATA_ACCESS_CDMA_EvDo_A: ret = "CDMA - EvDo rev. A"; break; + case DATA_ACCESS_CDMA_EvDo_B: + ret = "CDMA - EvDo rev. B"; + break; default: if (DBG) { Log.e(LOG_TAG, "Wrong network. Can not return a string."); @@ -1237,6 +1239,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { case 6: // RADIO_TECHNOLOGY_1xRTT case 7: // RADIO_TECHNOLOGY_EVDO_0 case 8: // RADIO_TECHNOLOGY_EVDO_A + case 12: // RADIO_TECHNOLOGY_EVDO_B retVal = ServiceState.STATE_IN_SERVICE; break; default: @@ -1256,7 +1259,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { return ServiceState.STATE_IN_SERVICE; case 2: // 2 is "searching", fall through case 3: // 3 is "registration denied", fall through - case 4: // 4 is "unknown" no vaild in current baseband + case 4: // 4 is "unknown", not valid in current baseband return ServiceState.STATE_OUT_OF_SERVICE; case 5:// 5 is "Registered, roaming" return ServiceState.STATE_IN_SERVICE; @@ -1295,12 +1298,12 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { */ private boolean isRoamIndForHomeSystem(String roamInd) { // retrieve the carrier-specified list of ERIs for home system - String homeRoamIndcators = SystemProperties.get("ro.cdma.homesystem"); + String homeRoamIndicators = SystemProperties.get("ro.cdma.homesystem"); - if (!TextUtils.isEmpty(homeRoamIndcators)) { + if (!TextUtils.isEmpty(homeRoamIndicators)) { // searches through the comma-separated list for a match, // return true if one is found. - for (String homeRoamInd : homeRoamIndcators.split(",")) { + for (String homeRoamInd : homeRoamIndicators.split(",")) { if (homeRoamInd.equals(roamInd)) { return true; } diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index 403b7a1..b50502c 100755 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -313,7 +313,7 @@ public class SmsMessage extends SmsMessageBase { } /** - * Get an SMS-SUBMIT PDU for a data message to a destination address & port + * Get an SMS-SUBMIT PDU for a data message to a destination address and port. * * @param scAddr Service Centre address. null == use default * @param destAddr the address of the destination for the message diff --git a/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java b/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java index 3813b1d..4907aa9 100644 --- a/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java +++ b/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java @@ -56,10 +56,10 @@ public class TtyIntent { /** * The lookup key for an int that indicates preferred TTY mode. * Valid modes are: - * - {@link Phone.TTY_MODE_OFF} - * - {@link Phone.TTY_MODE_FULL} - * - {@link Phone.TTY_MODE_HCO} - * - {@link Phone.TTY_MODE_VCO} + * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} + * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} + * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} + * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO} * * {@hide} */ diff --git a/telephony/java/com/android/internal/telephony/gsm/CallFailCause.java b/telephony/java/com/android/internal/telephony/gsm/CallFailCause.java index e7fbf6b..af2ad48 100644 --- a/telephony/java/com/android/internal/telephony/gsm/CallFailCause.java +++ b/telephony/java/com/android/internal/telephony/gsm/CallFailCause.java @@ -25,6 +25,9 @@ package com.android.internal.telephony.gsm; * */ public interface CallFailCause { + // Unassigned/Unobtainable number + static final int UNOBTAINABLE_NUMBER = 1; + static final int NORMAL_CLEARING = 16; // Busy Tone static final int USER_BUSY = 17; diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java index 2bb7968..c7b1e5c 100755..100644 --- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java +++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java @@ -67,6 +67,7 @@ import com.android.internal.telephony.PhoneNotifier; import com.android.internal.telephony.PhoneProxy; import com.android.internal.telephony.PhoneSubInfo; import com.android.internal.telephony.TelephonyProperties; +import com.android.internal.telephony.UUSInfo; import com.android.internal.telephony.gsm.stk.StkService; import com.android.internal.telephony.test.SimulatedRadioControl; import com.android.internal.telephony.IccVmNotSupportedException; @@ -711,7 +712,12 @@ public class GSMPhone extends PhoneBase { } public Connection - dial (String dialString) throws CallStateException { + dial(String dialString) throws CallStateException { + return dial(dialString, null); + } + + public Connection + dial (String dialString, UUSInfo uusInfo) throws CallStateException { // Need to make sure dialString gets parsed properly String newDialString = PhoneNumberUtils.stripSeparators(dialString); @@ -727,9 +733,9 @@ public class GSMPhone extends PhoneBase { "dialing w/ mmi '" + mmi + "'..."); if (mmi == null) { - return mCT.dial(newDialString); + return mCT.dial(newDialString, uusInfo); } else if (mmi.isTemporaryModeCLIR()) { - return mCT.dial(mmi.dialingNumber, mmi.getCLIRMode()); + return mCT.dial(mmi.dialingNumber, mmi.getCLIRMode(), uusInfo); } else { mPendingMMIs.add(mmi); mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java index 87530e4..06f310c 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java @@ -37,6 +37,7 @@ import com.android.internal.telephony.DriverCall; import com.android.internal.telephony.EventLogTags; import com.android.internal.telephony.Phone; import com.android.internal.telephony.TelephonyProperties; +import com.android.internal.telephony.UUSInfo; import com.android.internal.telephony.gsm.CallFailCause; import com.android.internal.telephony.gsm.GSMPhone; import com.android.internal.telephony.gsm.GsmCall; @@ -65,7 +66,7 @@ public final class GsmCallTracker extends CallTracker { RegistrantList voiceCallStartedRegistrants = new RegistrantList(); - // connections dropped durin last poll + // connections dropped during last poll ArrayList<GsmConnection> droppedDuringPoll = new ArrayList<GsmConnection>(MAX_CONNECTIONS); @@ -167,7 +168,7 @@ public final class GsmCallTracker extends CallTracker { * clirMode is one of the CLIR_ constants */ Connection - dial (String dialString, int clirMode) throws CallStateException { + dial (String dialString, int clirMode, UUSInfo uusInfo) throws CallStateException { // note that this triggers call state changed notif clearDisconnected(); @@ -213,7 +214,7 @@ public final class GsmCallTracker extends CallTracker { // Always unmute when initiating a new call setMute(false); - cm.dial(pendingMO.address, clirMode, obtainCompleteMessage()); + cm.dial(pendingMO.address, clirMode, uusInfo, obtainCompleteMessage()); } updatePhoneState(); @@ -222,10 +223,19 @@ public final class GsmCallTracker extends CallTracker { return pendingMO; } + Connection + dial(String dialString) throws CallStateException { + return dial(dialString, CommandsInterface.CLIR_DEFAULT, null); + } + + Connection + dial(String dialString, UUSInfo uusInfo) throws CallStateException { + return dial(dialString, CommandsInterface.CLIR_DEFAULT, uusInfo); + } Connection - dial (String dialString) throws CallStateException { - return dial(dialString, CommandsInterface.CLIR_DEFAULT); + dial(String dialString, int clirMode) throws CallStateException { + return dial(dialString, clirMode, null); } void diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java index 4788a01..7dc2504 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java @@ -73,6 +73,7 @@ public class GsmConnection extends Connection { DisconnectCause cause = DisconnectCause.NOT_DISCONNECTED; PostDialState postDialState = PostDialState.NOT_STARTED; int numberPresentation = Connection.PRESENTATION_ALLOWED; + UUSInfo uusInfo; Handler h; @@ -126,6 +127,7 @@ public class GsmConnection extends Connection { isIncoming = dc.isMT; createTime = System.currentTimeMillis(); numberPresentation = dc.numberPresentation; + uusInfo = dc.uusInfo; this.index = index; @@ -356,6 +358,9 @@ public class GsmConnection extends Connection { case CallFailCause.FDN_BLOCKED: return DisconnectCause.FDN_BLOCKED; + case CallFailCause.UNOBTAINABLE_NUMBER: + return DisconnectCause.UNOBTAINABLE_NUMBER; + case CallFailCause.ERROR_UNSPECIFIED: case CallFailCause.NORMAL_CLEARING: default: @@ -728,4 +733,9 @@ public class GsmConnection extends Connection { public int getNumberPresentation() { return numberPresentation; } + + @Override + public UUSInfo getUUSInfo() { + return uusInfo; + } } diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java index d893ec4..09d46dd 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java @@ -134,7 +134,7 @@ public class GsmDataConnection extends DataConnection { cause = FailCause.INSUFFICIENT_RESOURCES; break; case PDP_FAIL_MISSING_UKNOWN_APN: - cause = FailCause.MISSING_UKNOWN_APN; + cause = FailCause.MISSING_UNKNOWN_APN; break; case PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE: cause = FailCause.UNKNOWN_PDP_ADDRESS; diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index 627d94d..f6d4491 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -45,7 +45,6 @@ import android.provider.Telephony; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.telephony.gsm.GsmCellLocation; -import android.text.TextUtils; import android.util.EventLog; import android.util.Log; @@ -151,9 +150,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { static final String APN_ID = "apn_id"; private boolean canSetPreferApn = false; - // for tracking retrys on the default APN + // for tracking retries on the default APN private RetryManager mDefaultRetryManager; - // for tracking retrys on a secondary APN + // for tracking retries on a secondary APN private RetryManager mSecondaryRetryManager; BroadcastReceiver mIntentReceiver = new BroadcastReceiver () @@ -190,8 +189,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED; if (!enabled) { - // when wifi got disabeled, the NETWORK_STATE_CHANGED_ACTION - // quit and wont report disconnected til next enalbing. + // when wifi got disabled, the NETWORK_STATE_CHANGED_ACTION + // quit and won't report disconnected til next enabling. mIsWifiConnected = false; } } @@ -452,7 +451,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { waitingApns = buildWaitingApns(); if (waitingApns.isEmpty()) { if (DBG) log("No APN found"); - notifyNoData(GsmDataConnection.FailCause.MISSING_UKNOWN_APN); + notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN); return false; } else { log ("Create from allApns : " + apnListToString(allApns)); @@ -1130,7 +1129,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) { SystemProperties.set("gsm.defaultpdpcontext.active", "true"); if (canSetPreferApn && preferredApn == null) { - Log.d(LOG_TAG, "PREFERED APN is null"); + Log.d(LOG_TAG, "PREFERRED APN is null"); preferredApn = mActiveApn; setPreferredApn(preferredApn.id); } @@ -1280,7 +1279,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (allApns.isEmpty()) { if (DBG) log("No APN found for carrier: " + operator); preferredApn = null; - notifyNoData(GsmDataConnection.FailCause.MISSING_UKNOWN_APN); + notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN); } else { preferredApn = getPreferredApn(); Log.d(LOG_TAG, "Get PreferredAPN"); diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java index bcbd127..aa16fa3 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java @@ -39,7 +39,7 @@ import java.util.regex.Matcher; * {@hide} * */ -public final class GsmMmiCode extends Handler implements MmiCode { +public final class GsmMmiCode extends Handler implements MmiCode { static final String LOG_TAG = "GSM"; //***** Constants @@ -51,7 +51,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { static final String ACTION_REGISTER = "**"; static final String ACTION_ERASURE = "##"; - // Supp Service cocdes from TS 22.030 Annex B + // Supp Service codes from TS 22.030 Annex B //Called line presentation static final String SC_CLIP = "30"; @@ -154,7 +154,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { /** * Some dial strings in GSM are defined to do non-call setup - * things, such as modify or query supplementry service settings (eg, call + * 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. @@ -457,12 +457,13 @@ public final class GsmMmiCode extends Handler implements MmiCode { && !PhoneNumberUtils.isEmergencyNumber(dialString) && (phone.isInCall() || !((dialString.length() == 2 && dialString.charAt(0) == '1') - /* While contrary to TS 22.030, there is strong precendence + /* 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")))); } + /** * @return true if the Service Code is PIN/PIN2/PUK/PUK2-related */ @@ -472,13 +473,12 @@ public final class GsmMmiCode extends Handler implements MmiCode { } /** - * *See TS 22.030 Annex B + * See TS 22.030 Annex B. * In temporary mode, to suppress CLIR for a single call, enter: - * " * 31 # <called number> SEND " + * " * 31 # [called number] SEND " * In temporary mode, to invoke CLIR for a single call enter: - * " # 31 # <called number> SEND " + * " # 31 # [called number] SEND " */ - boolean isTemporaryModeCLIR() { return sc != null && sc.equals(SC_CLIR) && dialingNumber != null @@ -779,7 +779,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { // 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 doene in GSMPhone. + // The matching up of this is done in GSMPhone. phone.mCM.sendUSSD(ussdMessage, obtainMessage(EVENT_USSD_COMPLETE, this)); @@ -832,8 +832,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { if (ar.exception != null) { state = State.FAILED; - message = context.getText( - com.android.internal.R.string.mmiError); + message = getErrorMessage(ar); phone.onMMIDone(this); } @@ -852,6 +851,19 @@ public final class GsmMmiCode extends Handler implements MmiCode { } //***** Private instance methods + private CharSequence getErrorMessage(AsyncResult ar) { + + if (ar.exception instanceof CommandException) { + CommandException.Error err = ((CommandException)(ar.exception)).getCommandError(); + if (err == CommandException.Error.FDN_CHECK_FAILURE) { + Log.i(LOG_TAG, "FDN_CHECK_FAILURE"); + return context.getText(com.android.internal.R.string.mmiFdnError); + } + } + + return context.getText(com.android.internal.R.string.mmiError); + } + private CharSequence getScString() { if (sc != null) { if (isServiceCodeCallBarring(sc)) { @@ -904,6 +916,9 @@ public final class GsmMmiCode extends Handler implements MmiCode { 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)); @@ -953,7 +968,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { if (ar.exception != null) { state = State.FAILED; - sb.append(context.getText(com.android.internal.R.string.mmiError)); + sb.append(getErrorMessage(ar)); } else { int clirArgs[]; @@ -1123,7 +1138,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { if (ar.exception != null) { state = State.FAILED; - sb.append(context.getText(com.android.internal.R.string.mmiError)); + sb.append(getErrorMessage(ar)); } else { CallForwardInfo infos[]; @@ -1141,7 +1156,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { // 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 classs, find out + // CallForwardInfos. So, for each service class, find out // which CallForwardInfo represents it and then build // the response text based on that @@ -1175,7 +1190,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { if (ar.exception != null) { state = State.FAILED; - sb.append(context.getText(com.android.internal.R.string.mmiError)); + sb.append(getErrorMessage(ar)); } else { int[] ints = (int[])ar.result; 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/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java index 50b8eba..d539f6f 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java @@ -40,7 +40,6 @@ import android.provider.Settings.SettingNotFoundException; import android.provider.Telephony.Intents; import android.telephony.ServiceState; import android.telephony.SignalStrength; -import android.telephony.TelephonyManager; import android.telephony.gsm.GsmCellLocation; import android.text.TextUtils; import android.util.Config; @@ -130,7 +129,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { */ private boolean mNeedToRegForSimLoaded; - /** Started the recheck process after finding gprs should registerd but not. */ + /** Started the recheck process after finding gprs should registered but not. */ private boolean mStartedGprsRegCheck = false; /** Already sent the event-log for no gprs register. */ @@ -415,7 +414,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } // Release any temporary cell lock, which could have been - // aquired to allow a single-shot location update. + // acquired to allow a single-shot location update. disableSingleLocationUpdate(); break; @@ -500,9 +499,9 @@ final class GsmServiceStateTracker extends ServiceStateTracker { break; case EVENT_CHECK_REPORT_GPRS: - if (ss != null && !isGprsConsistant(gprsState, ss.getState())) { + if (ss != null && !isGprsConsistent(gprsState, ss.getState())) { - // Can't register data sevice while voice service is ok + // Can't register data service while voice service is ok // i.e. CREG is ok while CGREG is not // possible a network or baseband side error GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation()); @@ -1027,7 +1026,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { phone.notifyLocationChanged(); } - if (! isGprsConsistant(gprsState, ss.getState())) { + if (! isGprsConsistent(gprsState, ss.getState())) { if (!mStartedGprsRegCheck && !mReportedGprsNoReg) { mStartedGprsRegCheck = true; @@ -1044,13 +1043,13 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } /** - * Check if GPRS got registred while voice is registered + * Check if GPRS got registered while voice is registered. * * @param gprsState for GPRS registration state, i.e. CGREG in GSM * @param serviceState for voice registration state, i.e. CREG in GSM * @return false if device only register to voice but not gprs */ - private boolean isGprsConsistant (int gprsState, int serviceState) { + private boolean isGprsConsistent(int gprsState, int serviceState) { return !((serviceState == ServiceState.STATE_IN_SERVICE) && (gprsState != ServiceState.STATE_IN_SERVICE)); } @@ -1105,13 +1104,13 @@ final class GsmServiceStateTracker extends ServiceStateTracker { long nextTime; - // TODO Done't poll signal strength if screen is off + // TODO Don't poll signal strength if screen is off sendMessageDelayed(msg, POLL_PERIOD_MILLIS); } /** - * send signal-strength-changed notification if changed - * Called both for solicited and unsolicited signal stength updates + * Send signal-strength-changed notification if changed. + * Called both for solicited and unsolicited signal strength updates. */ private void onSignalStrengthResult(AsyncResult ar) { SignalStrength oldSignalStrength = mSignalStrength; @@ -1332,7 +1331,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { /** * @return true if phone is camping on a technology (eg UMTS) - * that could support voice and data simultaniously. + * that could support voice and data simultaneously. */ boolean isConcurrentVoiceAndData() { return (networkType >= DATA_ACCESS_UMTS); 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> diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java index 11b3fd6..a120f52 100644 --- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java +++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java @@ -29,6 +29,7 @@ import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.DataCallState; import com.android.internal.telephony.IccCard; import com.android.internal.telephony.Phone; +import com.android.internal.telephony.UUSInfo; import com.android.internal.telephony.gsm.CallFailCause; import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; import com.android.internal.telephony.gsm.SuppServiceNotification; @@ -496,6 +497,23 @@ public final class SimulatedCommands extends BaseCommands * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure * ar.userObject contains the orignal value of result.obj + * ar.result is null on success and failure + * + * CLIR_DEFAULT == on "use subscription default value" + * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation) + * CLIR_INVOCATION == on "CLIR invocation" (restrict CLI presentation) + */ + public void dial(String address, int clirMode, UUSInfo uusInfo, Message result) { + simulatedCallState.onDial(address); + + resultSuccess(result, null); + } + + /** + * returned message + * retMsg.obj = AsyncResult ar + * ar.exception carries exception on failure + * ar.userObject contains the orignal value of result.obj * ar.result is String containing IMSI on success */ public void getIMSI(Message result) { diff --git a/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java index 02590d3..de59b81 100644 --- a/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java +++ b/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java @@ -16,13 +16,16 @@ package com.android.internal.telephony; +import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import android.text.SpannableStringBuilder; import android.telephony.PhoneNumberUtils; +import android.telephony.TelephonyManager; +import android.content.Context; import junit.framework.TestCase; -public class PhoneNumberUtilsTest extends TestCase { +public class PhoneNumberUtilsTest extends AndroidTestCase { @SmallTest public void testExtractNetworkPortion() throws Exception { @@ -82,6 +85,16 @@ public class PhoneNumberUtilsTest extends TestCase { assertEquals("17005550020", PhoneNumberUtils.calledPartyBCDToString(b, 0, 7)); + b[0] = (byte) 0x80; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55; + b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xF0; + assertEquals("17005550020", + PhoneNumberUtils.calledPartyBCDToString(b, 0, 7)); + + b[0] = (byte) 0x90; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55; + b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xF0; + assertEquals("+17005550020", + PhoneNumberUtils.calledPartyBCDToString(b, 0, 7)); + b[0] = (byte) 0x91; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55; b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xF0; assertEquals("+17005550020", @@ -472,4 +485,22 @@ public class PhoneNumberUtilsTest extends TestCase { PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+18475797000", PhoneNumberUtils.FORMAT_UNKNOWN,PhoneNumberUtils.FORMAT_UNKNOWN)); } + + /** + * Basic checks for the VoiceMail number. + */ + @SmallTest + public void testWithNumberNotEqualToVoiceMail() throws Exception { + assertFalse(PhoneNumberUtils.isVoiceMailNumber("911")); + assertFalse(PhoneNumberUtils.isVoiceMailNumber("tel:911")); + assertFalse(PhoneNumberUtils.isVoiceMailNumber("+18001234567")); + assertFalse(PhoneNumberUtils.isVoiceMailNumber("")); + assertFalse(PhoneNumberUtils.isVoiceMailNumber(null)); + // This test fails on a device without a sim card + /*TelephonyManager mTelephonyManager = + (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE); + String mVoiceMailNumber = mTelephonyManager.getDefault().getVoiceMailNumber(); + assertTrue(PhoneNumberUtils.isVoiceMailNumber(mVoiceMailNumber)); + */ + } } diff --git a/telephony/tests/telephonytests/src/com/android/telephonytest/unit/CallerInfoUnitTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/CallerInfoTest.java index 0f24f15..1e5dafb 100644 --- a/telephony/tests/telephonytests/src/com/android/telephonytest/unit/CallerInfoUnitTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/CallerInfoTest.java @@ -14,7 +14,8 @@ * limitations under the License. */ -package com.android.telephonytest.unit; +package com.android.internal.telephony; + import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; @@ -33,7 +34,7 @@ import android.util.StringBuilderPrinter; * */ -public class CallerInfoUnitTest extends AndroidTestCase { +public class CallerInfoTest extends AndroidTestCase { private CallerInfo mInfo; private Context mContext; diff --git a/telephony/tests/telephonytests/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java b/telephony/tests/telephonytests/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java deleted file mode 100644 index 2d3c548..0000000 --- a/telephony/tests/telephonytests/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2009 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.telephonytest.unit; -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.Log; - -import android.telephony.PhoneNumberUtils; -import android.telephony.TelephonyManager; - -/* - * Check the PhoneNumberUtils utility class works as expected. - * - */ - -public class PhoneNumberUtilsUnitTest extends AndroidTestCase { - private String mVoiceMailNumber; - private static final String TAG = "PhoneNumberUtilsUnitTest"; - - @Override - protected void setUp() throws Exception { - super.setUp(); - // FIXME: Why are we getting a security exception here? The - // permission is declared in the manifest.... - // mVoiceMailNumber = TelephonyManager.getDefault().getVoiceMailNumber(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - /** - * Basic checks for the VoiceMail number. - * Assumes READ_PHONE_STATE permission and we don't have it. - */ - // TODO: Figure out why we don't have the permission declared in the manifest. - @SmallTest - public void testWithNumberNotEqualToVoiceMail() throws Exception { - assertFalse(PhoneNumberUtils.isVoiceMailNumber("911")); - assertFalse(PhoneNumberUtils.isVoiceMailNumber("tel:911")); - assertFalse(PhoneNumberUtils.isVoiceMailNumber("+18001234567")); - assertFalse(PhoneNumberUtils.isVoiceMailNumber("")); - assertFalse(PhoneNumberUtils.isVoiceMailNumber(null)); - // FIXME: - // assertTrue(PhoneNumberUtils.isVoiceMailNumber(mVoiceMailNumber)); - } - -} |