diff options
Diffstat (limited to 'telephony')
66 files changed, 2532 insertions, 1195 deletions
diff --git a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java index 8a47339..ffabb7b 100644 --- a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java +++ b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java @@ -16,83 +16,200 @@ package android.telephony; +import com.google.i18n.phonenumbers.AsYouTypeFormatter; +import com.google.i18n.phonenumbers.PhoneNumberUtil; + +import android.telephony.PhoneNumberUtils; import android.text.Editable; import android.text.Selection; import android.text.TextWatcher; -import android.widget.TextView; import java.util.Locale; /** - * Watches a {@link TextView} and if a phone number is entered will format it using - * {@link PhoneNumberUtils#formatNumber(Editable, int)}. The formatting is based on - * the current system locale when this object is created and future locale changes - * may not take effect on this instance. + * Watches a {@link android.widget.TextView} and if a phone number is entered + * will format it. + * <p> + * Stop formatting when the user + * <ul> + * <li>Inputs non-dialable characters</li> + * <li>Removes the separator in the middle of string.</li> + * </ul> + * <p> + * The formatting will be restarted once the text is cleared. */ public class PhoneNumberFormattingTextWatcher implements TextWatcher { + /** + * One or more characters were removed from the end. + */ + private final static int STATE_REMOVE_LAST = 0; + + /** + * One or more characters were appended. + */ + private final static int STATE_APPEND = 1; + + /** + * One or more digits were changed in the beginning or the middle of text. + */ + private final static int STATE_MODIFY_DIGITS = 2; + + /** + * The changes other than the above. + */ + private final static int STATE_OTHER = 3; - static private int sFormatType; - static private Locale sCachedLocale; - private boolean mFormatting; - private boolean mDeletingHyphen; - private int mHyphenStart; - private boolean mDeletingBackward; + /** + * The state of this change could be one value of the above + */ + private int mState; + /** + * Indicates the change was caused by ourselves. + */ + private boolean mSelfChange = false; + + /** + * Indicates the formatting has been stopped. + */ + private boolean mStopFormatting; + + private AsYouTypeFormatter mFormatter; + + /** + * The formatting is based on the current system locale and future locale changes + * may not take effect on this instance. + */ public PhoneNumberFormattingTextWatcher() { - if (sCachedLocale == null || sCachedLocale != Locale.getDefault()) { - sCachedLocale = Locale.getDefault(); - sFormatType = PhoneNumberUtils.getFormatTypeForLocale(sCachedLocale); + this(Locale.getDefault().getCountry()); + } + + /** + * The formatting is based on the given <code>countryCode</code>. + * + * @param countryCode the ISO 3166-1 two-letter country code that indicates the country/region + * where the phone number is being entered. + * + * @hide + */ + public PhoneNumberFormattingTextWatcher(String countryCode) { + if (countryCode == null) throw new IllegalArgumentException(); + mFormatter = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(countryCode); + } + + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + if (mSelfChange || mStopFormatting) { + return; + } + if (count == 0 && s.length() == start) { + // Append one or more new chars + mState = STATE_APPEND; + } else if (after == 0 && start + count == s.length() && count > 0) { + // Remove one or more chars from the end of string. + mState = STATE_REMOVE_LAST; + } else if (count > 0 && !hasSeparator(s, start, count)) { + // Remove the dialable chars in the begin or middle of text. + mState = STATE_MODIFY_DIGITS; + } else { + mState = STATE_OTHER; } } - public synchronized void afterTextChanged(Editable text) { - // Make sure to ignore calls to afterTextChanged caused by the work done below - if (!mFormatting) { - mFormatting = true; - - // If deleting the hyphen, also delete the char before or after that - if (mDeletingHyphen && mHyphenStart > 0) { - if (mDeletingBackward) { - if (mHyphenStart - 1 < text.length()) { - text.delete(mHyphenStart - 1, mHyphenStart); - } - } else if (mHyphenStart < text.length()) { - text.delete(mHyphenStart, mHyphenStart + 1); - } + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (mSelfChange || mStopFormatting) { + return; + } + if (mState == STATE_OTHER) { + if (count > 0 && !hasSeparator(s, start, count)) { + // User inserted the dialable characters in the middle of text. + mState = STATE_MODIFY_DIGITS; } + } + // Check whether we should stop formatting. + if (mState == STATE_APPEND && count > 0 && hasSeparator(s, start, count)) { + // User appended the non-dialable character, stop formatting. + stopFormatting(); + } else if (mState == STATE_OTHER) { + // User must insert or remove the non-dialable characters in the begin or middle of + // number, stop formatting. + stopFormatting(); + } + } - PhoneNumberUtils.formatNumber(text, sFormatType); - - mFormatting = false; + public synchronized void afterTextChanged(Editable s) { + if (mStopFormatting) { + // Restart the formatting when all texts were clear. + mStopFormatting = !(s.length() == 0); + return; + } + if (mSelfChange) { + // Ignore the change caused by s.replace(). + return; + } + String formatted = reformat(s, Selection.getSelectionEnd(s)); + if (formatted != null) { + int rememberedPos = mFormatter.getRememberedPosition(); + mSelfChange = true; + s.replace(0, s.length(), formatted, 0, formatted.length()); + // The text could be changed by other TextWatcher after we changed it. If we found the + // text is not the one we were expecting, just give up calling setSelection(). + if (formatted.equals(s.toString())) { + Selection.setSelection(s, rememberedPos); + } + mSelfChange = false; } } - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - // Check if the user is deleting a hyphen - if (!mFormatting) { - // Make sure user is deleting one char, without a selection - final int selStart = Selection.getSelectionStart(s); - final int selEnd = Selection.getSelectionEnd(s); - if (s.length() > 1 // Can delete another character - && count == 1 // Deleting only one character - && after == 0 // Deleting - && s.charAt(start) == '-' // a hyphen - && selStart == selEnd) { // no selection - mDeletingHyphen = true; - mHyphenStart = start; - // Check if the user is deleting forward or backward - if (selStart == start + 1) { - mDeletingBackward = true; - } else { - mDeletingBackward = false; + /** + * Generate the formatted number by ignoring all non-dialable chars and stick the cursor to the + * nearest dialable char to the left. For instance, if the number is (650) 123-45678 and '4' is + * removed then the cursor should be behind '3' instead of '-'. + */ + private String reformat(CharSequence s, int cursor) { + // The index of char to the leftward of the cursor. + int curIndex = cursor - 1; + String formatted = null; + mFormatter.clear(); + char lastNonSeparator = 0; + boolean hasCursor = false; + int len = s.length(); + for (int i = 0; i < len; i++) { + char c = s.charAt(i); + if (PhoneNumberUtils.isNonSeparator(c)) { + if (lastNonSeparator != 0) { + formatted = getFormattedNumber(lastNonSeparator, hasCursor); + hasCursor = false; } - } else { - mDeletingHyphen = false; + lastNonSeparator = c; } + if (i == curIndex) { + hasCursor = true; + } + } + if (lastNonSeparator != 0) { + formatted = getFormattedNumber(lastNonSeparator, hasCursor); } + return formatted; } - public void onTextChanged(CharSequence s, int start, int before, int count) { - // Does nothing + private String getFormattedNumber(char lastNonSeparator, boolean hasCursor) { + return hasCursor ? mFormatter.inputDigitAndRememberPosition(lastNonSeparator) + : mFormatter.inputDigit(lastNonSeparator); + } + + private void stopFormatting() { + mStopFormatting = true; + mFormatter.clear(); + } + + private boolean hasSeparator(final CharSequence s, final int start, final int count) { + for (int i = start; i < start + count; i++) { + char c = s.charAt(i); + if (!PhoneNumberUtils.isNonSeparator(c)) { + return true; + } + } + return false; } } diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index ddfc520..e37733c 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -16,6 +16,11 @@ package android.telephony; +import com.google.i18n.phonenumbers.NumberParseException; +import com.google.i18n.phonenumbers.PhoneNumberUtil; +import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; + import android.content.Context; import android.content.Intent; import android.database.Cursor; @@ -617,7 +622,7 @@ public class PhoneNumberUtils } } else { // In the US, 1-650-555-1234 must be equal to 650-555-1234, - // while 090-1234-1234 must not be equalt to 90-1234-1234 in Japan. + // while 090-1234-1234 must not be equal to 90-1234-1234 in Japan. // This request exists just in US (with 1 trunk (NDD) prefix). // In addition, "011 11 7005554141" must not equal to "+17005554141", // while "011 1 7005554141" must equal to "+17005554141" @@ -779,10 +784,10 @@ public class PhoneNumberUtils if (prependPlus) { // This is an "international number" and should have // a plus prepended to the dialing number. But there - // can also be Gsm MMI codes as defined in TS 22.030 6.5.2 + // can also be GSM MMI codes as defined in TS 22.030 6.5.2 // so we need to handle those also. // - // http://web.telia.com/~u47904776/gsmkode.htm is a + // http://web.telia.com/~u47904776/gsmkode.htm // has a nice list of some of these GSM codes. // // Examples are: @@ -870,10 +875,10 @@ public class PhoneNumberUtils // FIXME(mkf) TS 23.040 9.1.2.3 says // "if a mobile receives 1111 in a position prior to - // the last semi-octet then processing shall commense with + // the last semi-octet then processing shall commence with // the next semi-octet and the intervening // semi-octet shall be ignored" - // How does this jive with 24,008 10.5.4.7 + // How does this jive with 24.008 10.5.4.7 b = (byte)((bytes[i] >> 4) & 0xf); @@ -1004,7 +1009,7 @@ public class PhoneNumberUtils * Convert a dialing number to BCD byte array * * @param number dialing number string - * if the dialing number starts with '+', set to internationl TOA + * if the dialing number starts with '+', set to international TOA * @return BCD byte array */ public static byte[] @@ -1108,10 +1113,10 @@ public class PhoneNumberUtils * * @param source the phone number to format * @param defaultFormattingType The default formatting rules to apply if the number does - * not begin with +<country_code> + * not begin with +[country_code] * @return The phone number formatted with the given formatting type. * - * @hide TODO:Shuold be unhidden. + * @hide TODO: Should be unhidden. */ public static String formatNumber(String source, int defaultFormattingType) { SpannableStringBuilder text = new SpannableStringBuilder(source); @@ -1138,7 +1143,7 @@ public class PhoneNumberUtils * * @param text The number to be formatted, will be modified with the formatting * @param defaultFormattingType The default formatting rules to apply if the number does - * not begin with +<country_code> + * not begin with +[country_code] */ public static void formatNumber(Editable text, int defaultFormattingType) { int formatType = defaultFormattingType; @@ -1319,6 +1324,132 @@ public class PhoneNumberUtils } } + /** + * Format the given phoneNumber to the E.164 representation. + * <p> + * The given phone number must have an area code and could have a country + * code. + * <p> + * The defaultCountryIso is used to validate the given number and generate + * the E.164 phone number if the given number doesn't have a country code. + * + * @param phoneNumber + * the phone number to format + * @param defaultCountryIso + * the ISO 3166-1 two letters country code + * @return the E.164 representation, or null if the given phone number is + * not valid. + * + * @hide + */ + public static String formatNumberToE164(String phoneNumber, String defaultCountryIso) { + PhoneNumberUtil util = PhoneNumberUtil.getInstance(); + String result = null; + try { + PhoneNumber pn = util.parse(phoneNumber, defaultCountryIso); + if (util.isValidNumber(pn)) { + result = util.format(pn, PhoneNumberFormat.E164); + } + } catch (NumberParseException e) { + } + return result; + } + + /** + * Format a phone number. + * <p> + * If the given number doesn't have the country code, the phone will be + * formatted to the default country's convention. + * + * @param phoneNumber + * the number to be formatted. + * @param defaultCountryIso + * the ISO 3166-1 two letters country code whose convention will + * be used if the given number doesn't have the country code. + * @return the formatted number, or null if the given number is not valid. + * + * @hide + */ + public static String formatNumber(String phoneNumber, String defaultCountryIso) { + PhoneNumberUtil util = PhoneNumberUtil.getInstance(); + String result = null; + try { + PhoneNumber pn = util.parseAndKeepRawInput(phoneNumber, defaultCountryIso); + result = util.formatInOriginalFormat(pn, defaultCountryIso); + } catch (NumberParseException e) { + } + return result; + } + + /** + * Format the phone number only if the given number hasn't been formatted. + * <p> + * The number which has only dailable character is treated as not being + * formatted. + * + * @param phoneNumber + * the number to be formatted. + * @param phoneNumberE164 + * the E164 format number whose country code is used if the given + * phoneNumber doesn't have the country code. + * @param defaultCountryIso + * the ISO 3166-1 two letters country code whose convention will + * be used if the phoneNumberE164 is null or invalid. + * @return the formatted number if the given number has been formatted, + * otherwise, return the given number. + * + * @hide + */ + public static String formatNumber( + String phoneNumber, String phoneNumberE164, String defaultCountryIso) { + int len = phoneNumber.length(); + for (int i = 0; i < len; i++) { + if (!isDialable(phoneNumber.charAt(i))) { + return phoneNumber; + } + } + PhoneNumberUtil util = PhoneNumberUtil.getInstance(); + // Get the country code from phoneNumberE164 + if (phoneNumberE164 != null && phoneNumberE164.length() >= 2 + && phoneNumberE164.charAt(0) == '+') { + try { + PhoneNumber pn = util.parse(phoneNumberE164, defaultCountryIso); + String regionCode = util.getRegionCodeForNumber(pn); + if (!TextUtils.isEmpty(regionCode)) { + defaultCountryIso = regionCode; + } + } catch (NumberParseException e) { + } + } + String result = formatNumber(phoneNumber, defaultCountryIso); + return result != null ? result : phoneNumber; + } + + /** + * Normalize a phone number by removing the characters other than digits. If + * the given number has keypad letters, the letters will be converted to + * digits first. + * + * @param phoneNumber + * the number to be normalized. + * @return the normalized number. + * + * @hide + */ + public static String normalizeNumber(String phoneNumber) { + StringBuilder sb = new StringBuilder(); + int len = phoneNumber.length(); + for (int i = 0; i < len; i++) { + char c = phoneNumber.charAt(i); + if ((i == 0 && c == '+') || PhoneNumberUtils.isISODigit(c)) { + sb.append(c); + } else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + return normalizeNumber(PhoneNumberUtils.convertKeypadLettersToDigits(phoneNumber)); + } + } + return sb.toString(); + } + // Three and four digit phone numbers for either special services, // or 3-6 digit addresses from the network (eg carrier-originated SMS messages) should // not match. @@ -1546,7 +1677,7 @@ public class PhoneNumberUtils * @hide */ public static String - cdmaCheckAndProcessPlusCodeByNumberFormat(String dialStr,int currFormat,int defaultFormt) { + cdmaCheckAndProcessPlusCodeByNumberFormat(String dialStr,int currFormat,int defaultFormat) { String retStr = dialStr; // Checks if the plus sign character is in the passed-in dial string @@ -1554,7 +1685,7 @@ public class PhoneNumberUtils dialStr.lastIndexOf(PLUS_SIGN_STRING) != -1) { // Format the string based on the rules for the country the number is from, // and the current country the phone is camped on. - if ((currFormat == defaultFormt) && (currFormat == FORMAT_NANP)) { + if ((currFormat == defaultFormat) && (currFormat == FORMAT_NANP)) { // Handle case where default and current telephone numbering plans are NANP. String postDialStr = null; String tempDialStr = dialStr; @@ -1741,7 +1872,7 @@ public class PhoneNumberUtils return -1; } - // This function appends the non-diablable P/W character to the original + // This function appends the non-dialable P/W character to the original // dial string based on the dialable index passed in private static String appendPwCharBackToOrigDialStr(int dialableIndex,String origStr, String dialStr) { @@ -1761,7 +1892,7 @@ public class PhoneNumberUtils return retStr; } - //===== Begining of utility methods used in compareLoosely() ===== + //===== Beginning of utility methods used in compareLoosely() ===== /** * Phone numbers are stored in "lookup" form in the database @@ -1883,12 +2014,12 @@ public class PhoneNumberUtils //===== End of utility methods used only in compareLoosely() ===== - //===== Beggining of utility methods used only in compareStrictly() ==== + //===== Beginning of utility methods used only in compareStrictly() ==== /* * If true, the number is country calling code. */ - private static final boolean COUNTLY_CALLING_CALL[] = { + private static final boolean COUNTRY_CALLING_CALL[] = { true, true, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, true, true, false, @@ -1900,18 +2031,18 @@ public class PhoneNumberUtils false, true, true, true, true, false, true, false, false, true, true, true, true, true, true, true, false, false, true, false, }; - private static final int CCC_LENGTH = COUNTLY_CALLING_CALL.length; + private static final int CCC_LENGTH = COUNTRY_CALLING_CALL.length; /** * @return true when input is valid Country Calling Code. */ private static boolean isCountryCallingCode(int countryCallingCodeCandidate) { return countryCallingCodeCandidate > 0 && countryCallingCodeCandidate < CCC_LENGTH && - COUNTLY_CALLING_CALL[countryCallingCodeCandidate]; + COUNTRY_CALLING_CALL[countryCallingCodeCandidate]; } /** - * Returns interger corresponding to the input if input "ch" is + * Returns integer corresponding to the input if input "ch" is * ISO-LATIN characters 0-9. * Returns -1 otherwise */ @@ -2046,7 +2177,7 @@ public class PhoneNumberUtils /** * Return true if the prefix of "str" is "ignorable". Here, "ignorable" means - * that "str" has only one digit and separater characters. The one digit is + * that "str" has only one digit and separator characters. The one digit is * assumed to be trunk prefix. */ private static boolean checkPrefixIsIgnorable(final String str, diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java index 830af47..38f44d8 100644 --- a/telephony/java/android/telephony/PhoneStateListener.java +++ b/telephony/java/android/telephony/PhoneStateListener.java @@ -25,6 +25,7 @@ import android.telephony.CellLocation; import android.util.Log; import com.android.internal.telephony.IPhoneStateListener; +import com.android.internal.telephony.Phone; /** * A listener class for monitoring changes in specific telephony states @@ -284,7 +285,7 @@ public class PhoneStateListener { } public void onDataConnectionStateChanged(int state, int networkType) { - Message.obtain(mHandler, LISTEN_DATA_CONNECTION_STATE, state, networkType, null). + Message.obtain(mHandler, LISTEN_DATA_CONNECTION_STATE, state, networkType). sendToTarget(); } diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index f5e9751..953696b 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -21,7 +21,6 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.text.TextUtils; -import com.android.internal.telephony.EncodeException; import com.android.internal.telephony.ISms; import com.android.internal.telephony.IccConstants; import com.android.internal.telephony.SmsRawData; @@ -33,7 +32,7 @@ import java.util.List; /* * TODO(code review): Curious question... Why are a lot of these * methods not declared as static, since they do not seem to require - * any local object state? Assumedly this cannot be changed without + * any local object state? Presumably this cannot be changed without * interfering with the API... */ @@ -42,7 +41,8 @@ import java.util.List; * Get this object by calling the static method SmsManager.getDefault(). */ public final class SmsManager { - private static SmsManager sInstance; + /** Singleton object constructed during class initialization. */ + private static final SmsManager sInstance = new SmsManager(); /** * Send a text based SMS. @@ -52,8 +52,8 @@ public final class SmsManager { * 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. - * The result code will be <code>Activity.RESULT_OK<code> for success, + * 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:<br> * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> * <code>RESULT_ERROR_RADIO_OFF</code><br> @@ -116,7 +116,7 @@ public final class SmsManager { * @param sentIntents if not null, an <code>ArrayList</code> of * <code>PendingIntent</code>s (one for each message part) that is * broadcast when the corresponding message part has been sent. - * The result code will be <code>Activity.RESULT_OK<code> for success, + * The result code will be <code>Activity.RESULT_OK</code> for success, * or one of these errors:<br> * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> * <code>RESULT_ERROR_RADIO_OFF</code><br> @@ -125,7 +125,7 @@ public final class SmsManager { * the extra "errorCode" containing a radio technology specific value, * generally only useful for troubleshooting.<br> * The per-application based SMS control checks sentIntent. If sentIntent - * is NULL the caller will be checked against all unknown applicaitons, + * is NULL the caller will be checked against all unknown applications, * which cause smaller number of SMS to be sent in checking period. * @param deliveryIntents if not null, an <code>ArrayList</code> of * <code>PendingIntent</code>s (one for each message part) that is @@ -178,8 +178,8 @@ public final class SmsManager { * @param destinationPort the port to deliver the message to * @param data 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. - * The result code will be <code>Activity.RESULT_OK<code> for success, + * 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:<br> * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> * <code>RESULT_ERROR_RADIO_OFF</code><br> @@ -188,7 +188,7 @@ public final class SmsManager { * the extra "errorCode" containing a radio technology specific value, * generally only useful for troubleshooting.<br> * The per-application based SMS control checks sentIntent. If sentIntent - * is NULL the caller will be checked against all unknown applicaitons, + * is NULL the caller will be checked against all unknown applications, * which cause smaller number of SMS to be sent in checking period. * @param deliveryIntent if not NULL this <code>PendingIntent</code> is * broadcast when the message is delivered to the recipient. The @@ -224,9 +224,6 @@ public final class SmsManager { * @return the default instance of the SmsManager */ public static SmsManager getDefault() { - if (sInstance == null) { - sInstance = new SmsManager(); - } return sInstance; } diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java index a284ea5..0746562 100644 --- a/telephony/java/android/telephony/SmsMessage.java +++ b/telephony/java/android/telephony/SmsMessage.java @@ -20,7 +20,6 @@ import android.os.Parcel; import android.util.Log; import com.android.internal.telephony.GsmAlphabet; -import com.android.internal.telephony.EncodeException; import com.android.internal.telephony.SmsHeader; import com.android.internal.telephony.SmsMessageBase; import com.android.internal.telephony.SmsMessageBase.SubmitPduBase; @@ -54,6 +53,10 @@ public class SmsMessage { public static final int ENCODING_7BIT = 1; public static final int ENCODING_8BIT = 2; public static final int ENCODING_16BIT = 3; + /** + * @hide This value is not defined in global standard. Only in Korea, this is used. + */ + public static final int ENCODING_KSC5601 = 4; /** The maximum number of payload bytes per message */ public static final int MAX_USER_DATA_BYTES = 140; diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 27e08d4..2370add 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -912,4 +912,25 @@ public class TelephonyManager { return null; } } + + /** + * @return true if the current device is "voice capable". + * <p> + * "Voice capable" means that this device supports circuit-switched + * (i.e. voice) phone calls over the telephony network, and is allowed + * to display the in-call UI while a cellular voice call is active. + * This will be false on "data only" devices which can't make voice + * calls and don't support any in-call UI. + * <p> + * Note: the meaning of this flag is subtly different from the + * PackageManager.FEATURE_TELEPHONY system feature, which is available + * on any device with a telephony radio, even if the device is + * data-only. + * + * @hide pending API review + */ + public boolean isVoiceCapable() { + return mContext.getResources().getBoolean( + com.android.internal.R.bool.config_voice_capable); + } } diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java index cf89848..6e13690 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfo.java +++ b/telephony/java/com/android/internal/telephony/CallerInfo.java @@ -70,6 +70,7 @@ public class CallerInfo { */ public String name; public String phoneNumber; + public String nomalizedNumber; public String cnapName; public int numberPresentation; @@ -150,6 +151,12 @@ public class CallerInfo { info.phoneNumber = cursor.getString(columnIndex); } + // Look for the normalized number + columnIndex = cursor.getColumnIndex(PhoneLookup.NORMALIZED_NUMBER); + if (columnIndex != -1) { + info.nomalizedNumber = cursor.getString(columnIndex); + } + // Look for the label/type combo columnIndex = cursor.getColumnIndex(PhoneLookup.LABEL); if (columnIndex != -1) { diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java index 25ca559..a967850 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java +++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java @@ -20,6 +20,7 @@ import android.content.AsyncQueryHandler; import android.content.Context; import android.database.Cursor; import android.database.SQLException; +import android.location.CountryDetector; import android.net.Uri; import android.os.Handler; import android.os.Looper; @@ -232,7 +233,11 @@ public class CallerInfoAsyncQuery { // Use the number entered by the user for display. if (!TextUtils.isEmpty(cw.number)) { - mCallerInfo.phoneNumber = PhoneNumberUtils.formatNumber(cw.number); + CountryDetector detector = (CountryDetector) mQueryContext.getSystemService( + Context.COUNTRY_DETECTOR); + mCallerInfo.phoneNumber = PhoneNumberUtils.formatNumber(cw.number, + mCallerInfo.nomalizedNumber, + detector.detectCountry().getCountryIso()); } } diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java index 5de0426..27a4dca 100644 --- a/telephony/java/com/android/internal/telephony/CommandsInterface.java +++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java @@ -27,8 +27,8 @@ import android.os.Handler; */ public interface CommandsInterface { enum RadioState { - RADIO_OFF, /* Radio explictly powered off (eg CFUN=0) */ - RADIO_UNAVAILABLE, /* Radio unavailable (eg, resetting or not booted) */ + RADIO_OFF, /* Radio explicitly powered off (e.g. CFUN=0) */ + RADIO_UNAVAILABLE, /* Radio unavailable (e.g. resetting or not booted) */ SIM_NOT_READY, /* Radio is on, but the SIM interface is not ready */ SIM_LOCKED_OR_ABSENT, /* SIM PIN locked, PUK required, network personalization, or SIM absent */ @@ -121,7 +121,7 @@ public interface CommandsInterface { // See 27.007 +CCFC or +CLCK static final int SERVICE_CLASS_NONE = 0; // no user input static final int SERVICE_CLASS_VOICE = (1 << 0); - static final int SERVICE_CLASS_DATA = (1 << 1); //synoym for 16+32+64+128 + static final int SERVICE_CLASS_DATA = (1 << 1); //synonym for 16+32+64+128 static final int SERVICE_CLASS_FAX = (1 << 2); static final int SERVICE_CLASS_SMS = (1 << 3); static final int SERVICE_CLASS_DATA_SYNC = (1 << 4); @@ -952,19 +952,19 @@ public interface CommandsInterface { void writeSmsToRuim(int status, String pdu, Message response); /** - * @deprecated * @param apn * @param user * @param password * @param response */ + @Deprecated void setupDefaultPDP(String apn, String user, String password, Message response); /** - * @deprecated * @param cid * @param response */ + @Deprecated void deactivateDefaultPDP(int cid, Message response); void setRadioPower(boolean on, Message response); @@ -974,7 +974,7 @@ public interface CommandsInterface { void acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message response); /** - * parameters equivilient to 27.007 AT+CRSM command + * parameters equivalent to 27.007 AT+CRSM command * response.obj will be an AsyncResult * response.obj.userObj will be a IccIoResult on success */ @@ -1079,7 +1079,7 @@ public interface CommandsInterface { /** * (AsyncResult)response.obj).result will be an Integer representing - * the sum of enabled serivice classes (sum of SERVICE_CLASS_*) + * the sum of enabled service classes (sum of SERVICE_CLASS_*) * * @param facility one of CB_FACILTY_* * @param password password or "" if not required @@ -1152,7 +1152,7 @@ public interface CommandsInterface { /** * Request to enable/disable network state change notifications when - * location informateion (lac and/or cid) has changed. + * location information (lac and/or cid) has changed. * * @param enable true to enable, false to disable * @param response callback message @@ -1183,7 +1183,7 @@ public interface CommandsInterface { /** * Indicates to the vendor ril that StkService is running - * rand is eady to receive RIL_UNSOL_STK_XXXX commands. + * and is ready to receive RIL_UNSOL_STK_XXXX commands. * * @param result callback message */ diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java index 6634017..3030481 100644 --- a/telephony/java/com/android/internal/telephony/DataConnection.java +++ b/telephony/java/com/android/internal/telephony/DataConnection.java @@ -21,11 +21,19 @@ import com.android.internal.telephony.gsm.ApnSetting; import com.android.internal.util.HierarchicalState; import com.android.internal.util.HierarchicalStateMachine; +import android.net.LinkCapabilities; +import android.net.LinkProperties; import android.os.AsyncResult; import android.os.Message; import android.os.SystemProperties; import android.util.EventLog; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.HashMap; + /** * {@hide} * @@ -255,10 +263,8 @@ public abstract class DataConnection extends HierarchicalStateMachine { protected int mTag; protected PhoneBase phone; protected int cid; - protected String interfaceName; - protected String ipAddress; - protected String gatewayAddress; - protected String[] dnsServers; + protected LinkProperties mLinkProperties = new LinkProperties(); + protected LinkCapabilities mCapabilities = new LinkCapabilities(); protected long createTime; protected long lastFailTime; protected FailCause lastFailCause; @@ -283,8 +289,6 @@ public abstract class DataConnection extends HierarchicalStateMachine { if (DBG) log("DataConnection constructor E"); this.phone = phone; this.cid = -1; - this.dnsServers = new String[2]; - clearSettings(); setDbg(false); @@ -377,11 +381,7 @@ public abstract class DataConnection extends HierarchicalStateMachine { this.lastFailTime = -1; this.lastFailCause = FailCause.NONE; - interfaceName = null; - ipAddress = null; - gatewayAddress = null; - dnsServers[0] = null; - dnsServers[1] = null; + mLinkProperties = new LinkProperties(); } /** @@ -416,35 +416,68 @@ public abstract class DataConnection extends HierarchicalStateMachine { // for (int i = 0; i < response.length; i++) { // log(" response[" + i + "]='" + response[i] + "'"); // } + + // Start with clean network properties and if we have + // a failure we'll clear again at the bottom of this code. + LinkProperties linkProperties = new LinkProperties(); if (response.length >= 2) { cid = Integer.parseInt(response[0]); - interfaceName = response[1]; - if (response.length > 2) { - ipAddress = response[2]; + String interfaceName = response[1]; + result = SetupResult.SUCCESS; + + try { String prefix = "net." + interfaceName + "."; - gatewayAddress = SystemProperties.get(prefix + "gw"); - dnsServers[0] = SystemProperties.get(prefix + "dns1"); - dnsServers[1] = SystemProperties.get(prefix + "dns2"); - if (DBG) { - log("interface=" + interfaceName + " ipAddress=" + ipAddress - + " gateway=" + gatewayAddress + " DNS1=" + dnsServers[0] - + " DNS2=" + dnsServers[1]); - } - if (isDnsOk(dnsServers)) { - result = SetupResult.SUCCESS; - } else { - result = SetupResult.ERR_BadDns; + linkProperties.setInterface(NetworkInterface.getByName(interfaceName)); + + // TODO: Get gateway and dns via RIL interface not property? + String gatewayAddress = SystemProperties.get(prefix + "gw"); + linkProperties.setGateway(InetAddress.getByName(gatewayAddress)); + + if (response.length > 2) { + String ipAddress = response[2]; + linkProperties.addAddress(InetAddress.getByName(ipAddress)); + + // TODO: Get gateway and dns via RIL interface not property? + String dnsServers[] = new String[2]; + dnsServers[0] = SystemProperties.get(prefix + "dns1"); + dnsServers[1] = SystemProperties.get(prefix + "dns2"); + if (isDnsOk(dnsServers)) { + linkProperties.addDns(InetAddress.getByName(dnsServers[0])); + linkProperties.addDns(InetAddress.getByName(dnsServers[1])); + } else { + result = SetupResult.ERR_BadDns; + } } - } else { - result = SetupResult.SUCCESS; + } catch (UnknownHostException e1) { + log("onSetupCompleted: UnknowHostException " + e1); + e1.printStackTrace(); + result = SetupResult.ERR_Other; + } catch (SocketException e2) { + log("onSetupCompleted: SocketException " + e2); + e2.printStackTrace(); + result = SetupResult.ERR_Other; } } else { + log("onSetupCompleted: error; expected number of responses >= 2 was " + + response.length); result = SetupResult.ERR_Other; } + + // An error occurred so clear properties + if (result != SetupResult.SUCCESS) { + log("onSetupCompleted with an error clearing LinkProperties"); + linkProperties.clear(); + } + mLinkProperties = linkProperties; } - if (DBG) log("DataConnection setup result='" + result + "' on cid=" + cid); + if (DBG) { + log("DataConnection setup result='" + result + "' on cid=" + cid); + if (result == SetupResult.SUCCESS) { + log("LinkProperties: " + mLinkProperties.toString()); + } + } return result; } @@ -606,7 +639,16 @@ public abstract class DataConnection extends HierarchicalStateMachine { break; case ERR_BadDns: // Connection succeeded but DNS info is bad so disconnect - EventLog.writeEvent(EventLogTags.PDP_BAD_DNS_ADDRESS, dnsServers[0]); + StringBuilder dnsAddressesSb = new StringBuilder(); + for (InetAddress addr : mLinkProperties.getDnses()) { + if (dnsAddressesSb.length() != 0) dnsAddressesSb.append(" "); + dnsAddressesSb.append(addr.toString()); + } + if (dnsAddressesSb.length() == 0) { + dnsAddressesSb.append("no-dns-addresses"); + } + EventLog.writeEvent(EventLogTags.PDP_BAD_DNS_ADDRESS, + dnsAddressesSb.toString()); tearDownData(cp); transitionTo(mDisconnectingBadDnsState); break; @@ -873,31 +915,22 @@ public abstract class DataConnection extends HierarchicalStateMachine { } /** - * @return the interface name as a string. - */ - public String getInterface() { - return interfaceName; - } - - /** - * @return the ip address as a string. - */ - public String getIpAddress() { - return ipAddress; - } - - /** - * @return the gateway address as a string. + * Return the LinkProperties for the connection. + * + * @return a copy of the LinkProperties, is never null. */ - public String getGatewayAddress() { - return gatewayAddress; + public LinkProperties getLinkProperties() { + return new LinkProperties(mLinkProperties); } /** - * @return an array of associated DNS addresses. + * A capability is an Integer/String pair, the capabilities + * are defined in the class LinkSocket#Key. + * + * @return a copy of this connections capabilities, may be empty but never null. */ - public String[] getDnsServers() { - return dnsServers; + public LinkCapabilities getLinkCapabilities() { + return new LinkCapabilities(mCapabilities); } /** diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java index 3b9e6cc..d753973 100644 --- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java @@ -17,10 +17,11 @@ package com.android.internal.telephony; import android.app.PendingIntent; +import android.net.LinkCapabilities; +import android.net.LinkProperties; import android.os.AsyncResult; import android.os.Handler; import android.os.Message; -import android.os.RemoteException; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; @@ -28,6 +29,7 @@ import android.util.Log; import java.util.ArrayList; + /** * {@hide} * @@ -188,7 +190,16 @@ public abstract class DataConnectionTracker extends Handler { /** CID of active data connection */ protected int cidActive; - /** + /** indication of our availability (preconditions to trysetupData are met) **/ + protected boolean mAvailability = false; + + /** The link properties (dns, gateway, ip, etc) */ + protected LinkProperties mLinkProperties = new LinkProperties(); + + /** The link capabilities */ + protected LinkCapabilities mLinkCapabilities = new LinkCapabilities(); + + /** * Default constructor */ protected DataConnectionTracker(PhoneBase phone) { @@ -411,17 +422,125 @@ public abstract class DataConnectionTracker extends Handler { public abstract ArrayList<DataConnection> getAllDataConnections(); - protected abstract String getInterfaceName(String apnType); + protected abstract void setState(State s); - protected abstract String getIpAddress(String apnType); + protected LinkProperties getLinkProperties(String apnType) { + int id = apnTypeToId(apnType); + if (isApnIdEnabled(id)) { + return new LinkProperties(mLinkProperties); + } else { + return new LinkProperties(); + } + } - protected abstract String getGateway(String apnType); + protected LinkCapabilities getLinkCapabilities(String apnType) { + int id = apnTypeToId(apnType); + if (isApnIdEnabled(id)) { + return new LinkCapabilities(mLinkCapabilities); + } else { + return new LinkCapabilities(); + } + } - protected abstract String[] getDnsServers(String apnType); + /** + * Return the LinkProperties for the connection. + * + * @param connection + * @return a copy of the LinkProperties, is never null. + */ + protected LinkProperties getLinkProperties(DataConnection connection) { + return connection.getLinkProperties(); + } - protected abstract void setState(State s); + /** + * A capability is an Integer/String pair, the capabilities + * are defined in the class LinkSocket#Key. + * + * @param connection + * @return a copy of this connections capabilities, may be empty but never null. + */ + protected LinkCapabilities getLinkCapabilities(DataConnection connection) { + return connection.getLinkCapabilities(); + } - protected synchronized boolean isEnabled(int id) { + // tell all active apns of the current condition + protected void notifyDataConnection(String reason) { + for (int id = 0; id < APN_NUM_TYPES; id++) { + if (dataEnabled[id]) { + phone.notifyDataConnection(reason, apnIdToType(id)); + } + } + notifyDataAvailability(reason); + } + + // a new APN has gone active and needs to send events to catch up with the current condition + private void notifyApnIdUpToCurrent(String reason, int apnId) { + switch (state) { + case IDLE: + case INITING: + break; + case CONNECTING: + case SCANNING: + phone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING); + break; + case CONNECTED: + case DISCONNECTING: + phone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING); + phone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTED); + break; + } + } + + // since we normally don't send info to a disconnected APN, we need to do this specially + private void notifyApnIdDisconnected(String reason, int apnId) { + phone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.DISCONNECTED); + } + + // disabled apn's still need avail/unavail notificiations - send them out + protected void notifyOffApnsOfAvailability(String reason, boolean availability) { + if (mAvailability == availability) return; + mAvailability = availability; + for (int id = 0; id < APN_NUM_TYPES; id++) { + if (!isApnIdEnabled(id)) { + notifyApnIdDisconnected(reason, id); + } + } + } + + // we had an availability change - tell the listeners + protected void notifyDataAvailability(String reason) { + // note that we either just turned all off because we lost availability + // or all were off and could now go on, so only have off apns to worry about + notifyOffApnsOfAvailability(reason, isDataPossible()); + } + + /** + * The only circumstances under which we report that data connectivity is not + * possible are + * <ul> + * <li>Data is disallowed (roaming, power state, voice call, etc).</li> + * <li>The current data state is {@code DISCONNECTED} for a reason other than + * having explicitly disabled connectivity. In other words, data is not available + * because the phone is out of coverage or some like reason.</li> + * </ul> + * @return {@code true} if data connectivity is possible, {@code false} otherwise. + */ + protected boolean isDataPossible() { + boolean possible = (isDataAllowed() && + !(getDataEnabled() && (state == State.FAILED || state == State.IDLE))); + if (!possible && DBG && isDataAllowed()) { + log("Data not possible. No coverage: dataState = " + state); + } + return possible; + } + + protected abstract boolean isDataAllowed(); + + public boolean isApnTypeEnabled(String apnType) { + return isApnIdEnabled(apnTypeToId(apnType)); + } + + protected synchronized boolean isApnIdEnabled(int id) { if (id != APN_INVALID_ID) { return dataEnabled[id]; } @@ -444,22 +563,21 @@ public abstract class DataConnectionTracker extends Handler { return Phone.APN_REQUEST_FAILED; } - if (DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = " - + isApnTypeActive(type) + " and state = " + state); + if (DBG) { + Log.d(LOG_TAG, "enableApnType(" + type + "), isApnTypeActive = " + + isApnTypeActive(type) + ", isApnIdEnabled =" + isApnIdEnabled(id) + + " and state = " + state); + } if (!isApnTypeAvailable(type)) { if (DBG) Log.d(LOG_TAG, "type not available"); return Phone.APN_TYPE_NOT_AVAILABLE; } - // just because it's active doesn't mean we had it explicitly requested before - // (a broad default may handle many types). make sure we mark it enabled - // so if the default is disabled we keep the connection for others - setEnabled(id, true); - - if (isApnTypeActive(type)) { - if (state == State.INITING) return Phone.APN_REQUEST_STARTED; - else if (state == State.CONNECTED) return Phone.APN_ALREADY_ACTIVE; + if (isApnIdEnabled(id)) { + return Phone.APN_ALREADY_ACTIVE; + } else { + setEnabled(id, true); } return Phone.APN_REQUEST_STARTED; } @@ -478,7 +596,7 @@ public abstract class DataConnectionTracker extends Handler { if (id == APN_INVALID_ID) { return Phone.APN_REQUEST_FAILED; } - if (isEnabled(id)) { + if (isApnIdEnabled(id)) { setEnabled(id, false); if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) { if (dataEnabled[APN_DEFAULT_ID]) { @@ -495,9 +613,10 @@ public abstract class DataConnectionTracker extends Handler { } private void setEnabled(int id, boolean enable) { - if (DBG) Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ") with old state = " + - dataEnabled[id] + " and enabledCount = " + enabledCount); - + if (DBG) { + Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ") with old state = " + + dataEnabled[id] + " and enabledCount = " + enabledCount); + } Message msg = obtainMessage(EVENT_ENABLE_NEW_APN); msg.arg1 = id; msg.arg2 = (enable ? ENABLED : DISABLED); @@ -507,9 +626,8 @@ public abstract class DataConnectionTracker extends Handler { protected synchronized void onEnableApn(int apnId, int enabled) { if (DBG) { Log.d(LOG_TAG, "EVENT_APN_ENABLE_REQUEST " + apnId + ", " + enabled); - Log.d(LOG_TAG, " dataEnabled = " + dataEnabled[apnId] + - ", enabledCount = " + enabledCount + - ", isApnTypeActive = " + isApnTypeActive(apnIdToType(apnId))); + Log.d(LOG_TAG, " dataEnabled = " + dataEnabled[apnId] + ", enabledCount = " + + enabledCount + ", isApnTypeActive = " + isApnTypeActive(apnIdToType(apnId))); } if (enabled == ENABLED) { if (!dataEnabled[apnId]) { @@ -520,6 +638,8 @@ public abstract class DataConnectionTracker extends Handler { if (!isApnTypeActive(type)) { mRequestedApnType = type; onEnableNewApn(); + } else { + notifyApnIdUpToCurrent(Phone.REASON_APN_SWITCHED, apnId); } } else { // disable @@ -528,8 +648,17 @@ public abstract class DataConnectionTracker extends Handler { enabledCount--; if (enabledCount == 0) { onCleanUpConnection(true, Phone.REASON_DATA_DISABLED); - } else if (dataEnabled[APN_DEFAULT_ID] == true && - !isApnTypeActive(Phone.APN_TYPE_DEFAULT)) { + } + + // send the disconnect msg manually, since the normal route wont send + // it (it's not enabled) + notifyApnIdDisconnected(Phone.REASON_DATA_DISABLED, apnId); + if (dataEnabled[APN_DEFAULT_ID] == true + && !isApnTypeActive(Phone.APN_TYPE_DEFAULT)) { + // TODO - this is an ugly way to restore the default conn - should be done + // by a real contention manager and policy that disconnects the lower pri + // stuff as enable requests come in and pops them back on as we disable back + // down to the lower pri stuff mRequestedApnType = Phone.APN_TYPE_DEFAULT; onEnableNewApn(); } @@ -574,9 +703,7 @@ public abstract class DataConnectionTracker extends Handler { onTrySetupData(Phone.REASON_DATA_ENABLED); } else { onCleanUpConnection(true, Phone.REASON_DATA_DISABLED); - } + } } } - - } diff --git a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java index 057ba0a..6a163dd 100644 --- a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java +++ b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java @@ -16,6 +16,8 @@ package com.android.internal.telephony; +import android.net.LinkCapabilities; +import android.net.LinkProperties; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; @@ -92,26 +94,45 @@ public class DefaultPhoneNotifier implements PhoneNotifier { } } - public void notifyDataConnection(Phone sender, String reason) { + public void notifyDataConnection(Phone sender, String reason, String apnType) { + doNotifyDataConnection(sender, reason, apnType, sender.getDataConnectionState(apnType)); + } + + public void notifyDataConnection(Phone sender, String reason, String apnType, + Phone.DataState state) { + doNotifyDataConnection(sender, reason, apnType, state); + } + + private void doNotifyDataConnection(Phone sender, String reason, String apnType, + Phone.DataState state) { + // TODO + // use apnType as the key to which connection we're talking about. + // pass apnType back up to fetch particular for this one. TelephonyManager telephony = TelephonyManager.getDefault(); + LinkProperties linkProperties = null; + LinkCapabilities linkCapabilities = null; + if (state == Phone.DataState.CONNECTED) { + linkProperties = sender.getLinkProperties(apnType); + linkCapabilities = sender.getLinkCapabilities(apnType); + } try { mRegistry.notifyDataConnection( - convertDataState(sender.getDataConnectionState()), + convertDataState(state), sender.isDataConnectivityPossible(), reason, sender.getActiveApn(), - sender.getActiveApnTypes(), - sender.getInterfaceName(null), + apnType, + linkProperties, + linkCapabilities, ((telephony!=null) ? telephony.getNetworkType() : - TelephonyManager.NETWORK_TYPE_UNKNOWN), - sender.getGateway(null)); + TelephonyManager.NETWORK_TYPE_UNKNOWN)); } catch (RemoteException ex) { // system process is dead } } - public void notifyDataConnectionFailed(Phone sender, String reason) { + public void notifyDataConnectionFailed(Phone sender, String reason, String apnType) { try { - mRegistry.notifyDataConnectionFailed(reason); + mRegistry.notifyDataConnectionFailed(reason, apnType); } catch (RemoteException ex) { // system process is dead } diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java index 7edf065..e42827f 100644 --- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java +++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java @@ -16,11 +16,14 @@ package com.android.internal.telephony; -import android.telephony.SmsMessage; +import android.text.TextUtils; import android.util.SparseIntArray; import android.util.Log; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; + /** * This class implements the character set mapping between * the GSM SMS 7-bit alphabet specified in TS 23.038 6.2.1 @@ -171,7 +174,7 @@ public class GsmAlphabet { * array cannot contain more than 255 septets. * * @param data The text string to encode. - * @param header Optional header (includeing length byte) that precedes + * @param header Optional header (including length byte) that precedes * the encoded data, padded to septet boundary. * @return Byte array containing header and encoded data. */ @@ -204,7 +207,7 @@ public class GsmAlphabet { * the packed septets. The returned array cannot contain more than 255 * septets. * - * @param data the data string to endcode + * @param data the data string to encode * @throws EncodeException if String is too large to encode */ public static byte[] stringToGsm7BitPacked(String data) @@ -223,7 +226,7 @@ public class GsmAlphabet { * * @param data the text to convert to septets * @param startingSeptetOffset the number of padding septets to put before - * the character data at the begining of the array + * the character data at the beginning of the array * @param throwException If true, throws EncodeException on invalid char. * If false, replaces unencodable char with GSM alphabet space char. * @@ -257,7 +260,7 @@ public class GsmAlphabet { } /** - * Pack a 7-bit char into its appropirate place in a byte array + * Pack a 7-bit char into its appropriate place in a byte array * * @param bitOffset the bit offset that the septet should be packed at * (septet index * 7) @@ -320,7 +323,7 @@ public class GsmAlphabet { gsmVal = (0x7f & (pdu[offset + byteOffset] >> shift)); - // if it crosses a byte boundry + // if it crosses a byte boundary if (shift > 1) { // set msb bits to 0 gsmVal &= 0x7f >> (shift - 1); @@ -355,6 +358,32 @@ public class GsmAlphabet { */ public static String gsm8BitUnpackedToString(byte[] data, int offset, int length) { + return gsm8BitUnpackedToString(data, offset, length, ""); + } + + /** + * Convert a GSM alphabet string that's stored in 8-bit unpacked + * format (as it often appears in SIM records) into a String + * + * Field may be padded with trailing 0xff's. The decode stops + * at the first 0xff encountered. + * + * Additionally, in some country(ex. Korea), there are non-ASCII or MBCS characters. + * If a character set is given, characters in data are treat as MBCS. + */ + public static String + gsm8BitUnpackedToString(byte[] data, int offset, int length, String characterset) { + boolean isMbcs = false; + Charset charset = null; + ByteBuffer mbcsBuffer = null; + + if (!TextUtils.isEmpty(characterset) + && !characterset.equalsIgnoreCase("us-ascii") + && Charset.isSupported(characterset)) { + isMbcs = true; + charset = Charset.forName(characterset); + mbcsBuffer = ByteBuffer.allocate(2); + } boolean prevWasEscape; StringBuilder ret = new StringBuilder(length); @@ -380,7 +409,15 @@ public class GsmAlphabet { if (prevWasEscape) { ret.append((char)gsmExtendedToChar.get(c, ' ')); } else { - ret.append((char)gsmToChar.get(c, ' ')); + if (!isMbcs || c < 0x80 || i + 1 >= offset + length) { + ret.append((char)gsmToChar.get(c, ' ')); + } else { + // isMbcs must be true. So both mbcsBuffer and charset are initialized. + mbcsBuffer.clear(); + mbcsBuffer.put(data, i++, 2); + mbcsBuffer.flip(); + ret.append(charset.decode(mbcsBuffer).toString()); + } } prevWasEscape = false; } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 2328717..7a1587b 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -239,9 +239,11 @@ interface ITelephony { String getCdmaEriText(); /** - * Returns true if CDMA provisioning needs to run. + * Returns true if OTA service provisioning needs to run. + * Only relevant on some technologies, others will always + * return false. */ - boolean getCdmaNeedsProvisioning(); + boolean needsOtaServiceProvisioning(); /** * Returns the unread count of voicemails diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 87e4b52..6407a4e 100644 --- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -17,6 +17,8 @@ package com.android.internal.telephony; import android.content.Intent; +import android.net.LinkProperties; +import android.net.LinkCapabilities; import android.os.Bundle; import android.telephony.ServiceState; import android.telephony.SignalStrength; @@ -32,8 +34,8 @@ interface ITelephonyRegistry { void notifyCallForwardingChanged(boolean cfi); void notifyDataActivity(int state); void notifyDataConnection(int state, boolean isDataConnectivityPossible, - String reason, String apn, in String[] apnTypes, String interfaceName, int networkType, - String gateway); - void notifyDataConnectionFailed(String reason); + String reason, String apn, String apnType, in LinkProperties linkProperties, + in LinkCapabilities linkCapabilities, int networkType); + void notifyDataConnectionFailed(String reason, String apnType); void notifyCellLocation(in Bundle cellLocation); } diff --git a/telephony/java/com/android/internal/telephony/IccUtils.java b/telephony/java/com/android/internal/telephony/IccUtils.java index 957eddd..df579b0 100644 --- a/telephony/java/com/android/internal/telephony/IccUtils.java +++ b/telephony/java/com/android/internal/telephony/IccUtils.java @@ -16,13 +16,16 @@ package com.android.internal.telephony; +import android.content.res.Resources; +import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; import android.graphics.Color; import android.util.Log; import com.android.internal.telephony.GsmAlphabet; - import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; /** * Various methods, useful for dealing with SIM data. @@ -150,6 +153,9 @@ public class IccUtils { */ public static String adnStringFieldToString(byte[] data, int offset, int length) { + if (length == 0) { + return ""; + } if (length >= 1) { if (data[offset] == (byte) 0x80) { int ucslen = (length - 1) / 2; @@ -225,7 +231,15 @@ public class IccUtils { return ret.toString(); } - return GsmAlphabet.gsm8BitUnpackedToString(data, offset, length); + Resources resource = Resources.getSystem(); + String defaultCharset = ""; + try { + defaultCharset = + resource.getString(com.android.internal.R.string.gsm_alphabet_default_charset); + } catch (NotFoundException e) { + // Ignore Exception and defaultCharset is set to a empty string. + } + return GsmAlphabet.gsm8BitUnpackedToString(data, offset, length, defaultCharset.trim()); } static int @@ -267,9 +281,11 @@ public class IccUtils { /** - * Converts a byte array into a String hexidecimal characters + * Converts a byte array into a String of hexadecimal characters. + * + * @param bytes an array of bytes * - * null returns null + * @return hex string representation of bytes array */ public static String bytesToHexString(byte[] bytes) { diff --git a/telephony/java/com/android/internal/telephony/MccTable.java b/telephony/java/com/android/internal/telephony/MccTable.java index b73c2f7..9b0aa3c 100644 --- a/telephony/java/com/android/internal/telephony/MccTable.java +++ b/telephony/java/com/android/internal/telephony/MccTable.java @@ -23,346 +23,13 @@ import android.content.res.Configuration; import android.net.wifi.WifiManager; import android.os.RemoteException; import android.os.SystemProperties; -import android.provider.Settings; import android.text.TextUtils; import android.util.Log; -import java.util.Arrays; - -/** - * The table below is built from two resources: - * - * 1) ITU "Mobile Network Code (MNC) for the international - * identification plan for mobile terminals and mobile users" - * which is available as an annex to the ITU operational bulletin - * available here: http://www.itu.int/itu-t/bulletin/annex.html - * - * 2) The ISO 3166 country codes list, available here: - * http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/index.html - * - * This table was verified (28 Aug 2009) against - * http://en.wikipedia.org/wiki/List_of_mobile_country_codes with the - * only unresolved discrepancy being that this list has an extra entry - * (461) for China. - * - * TODO: Complete the mappings for timezones and language/locale codes. - * - * The actual table data used in the Java code is generated from the - * below Python code for efficiency. The information is expected to - * be static, but if changes are required, the table in the python - * code can be modified and the trailing code run to re-generate the - * tables that are to be used by Java. - -mcc_table = [ - (202, 'gr', 2, 'Greece'), - (204, 'nl', 2, 'Europe/Amsterdam', 'nl', 13, 'Netherlands (Kingdom of the)'), - (206, 'be', 2, 'Belgium'), - (208, 'fr', 2, 'Europe/Paris', 'fr', 'France'), - (212, 'mc', 2, 'Monaco (Principality of)'), - (213, 'ad', 2, 'Andorra (Principality of)'), - (214, 'es', 2, 'Europe/Madrid', 'es', 'Spain'), - (216, 'hu', 2, 'Hungary (Republic of)'), - (218, 'ba', 2, 'Bosnia and Herzegovina'), - (219, 'hr', 2, 'Croatia (Republic of)'), - (220, 'rs', 2, 'Serbia and Montenegro'), - (222, 'it', 2, 'Europe/Rome', 'it', 'Italy'), - (225, 'va', 2, 'Europe/Rome', 'it', 'Vatican City State'), - (226, 'ro', 2, 'Romania'), - (228, 'ch', 2, 'Europe/Zurich', 'de', 'Switzerland (Confederation of)'), - (230, 'cz', 2, 'Europe/Prague', 'cs', 13, 'Czech Republic'), - (231, 'sk', 2, 'Slovak Republic'), - (232, 'at', 2, 'Europe/Vienna', 'de', 13, 'Austria'), - (234, 'gb', 2, 'Europe/London', 'en', 13, 'United Kingdom of Great Britain and Northern Ireland'), - (235, 'gb', 2, 'Europe/London', 'en', 13, 'United Kingdom of Great Britain and Northern Ireland'), - (238, 'dk', 2, 'Denmark'), - (240, 'se', 2, 'Sweden'), - (242, 'no', 2, 'Norway'), - (244, 'fi', 2, 'Finland'), - (246, 'lt', 2, 'Lithuania (Republic of)'), - (247, 'lv', 2, 'Latvia (Republic of)'), - (248, 'ee', 2, 'Estonia (Republic of)'), - (250, 'ru', 2, 'Russian Federation'), - (255, 'ua', 2, 'Ukraine'), - (257, 'by', 2, 'Belarus (Republic of)'), - (259, 'md', 2, 'Moldova (Republic of)'), - (260, 'pl', 2, 'Europe/Warsaw', 'Poland (Republic of)'), - (262, 'de', 2, 'Europe/Berlin', 'de', 13, 'Germany (Federal Republic of)'), - (266, 'gi', 2, 'Gibraltar'), - (268, 'pt', 2, 'Portugal'), - (270, 'lu', 2, 'Luxembourg'), - (272, 'ie', 2, 'Europe/Dublin', 'en', 'Ireland'), - (274, 'is', 2, 'Iceland'), - (276, 'al', 2, 'Albania (Republic of)'), - (278, 'mt', 2, 'Malta'), - (280, 'cy', 2, 'Cyprus (Republic of)'), - (282, 'ge', 2, 'Georgia'), - (283, 'am', 2, 'Armenia (Republic of)'), - (284, 'bg', 2, 'Bulgaria (Republic of)'), - (286, 'tr', 2, 'Turkey'), - (288, 'fo', 2, 'Faroe Islands'), - (289, 'ge', 2, 'Abkhazia (Georgia)'), - (290, 'gl', 2, 'Greenland (Denmark)'), - (292, 'sm', 2, 'San Marino (Republic of)'), - (293, 'sl', 2, 'Slovenia (Republic of)'), - (294, 'mk', 2, 'The Former Yugoslav Republic of Macedonia'), - (295, 'li', 2, 'Liechtenstein (Principality of)'), - (297, 'me', 2, 'Montenegro (Republic of)'), - (302, 'ca', 3, '', '', 11, 'Canada'), - (308, 'pm', 2, 'Saint Pierre and Miquelon (Collectivit territoriale de la Rpublique franaise)'), - (310, 'us', 3, '', 'en', 11, 'United States of America'), - (311, 'us', 3, '', 'en', 11, 'United States of America'), - (312, 'us', 3, '', 'en', 11, 'United States of America'), - (313, 'us', 3, '', 'en', 11, 'United States of America'), - (314, 'us', 3, '', 'en', 11, 'United States of America'), - (315, 'us', 3, '', 'en', 11, 'United States of America'), - (316, 'us', 3, '', 'en', 11, 'United States of America'), - (330, 'pr', 2, 'Puerto Rico'), - (332, 'vi', 2, 'United States Virgin Islands'), - (334, 'mx', 3, 'Mexico'), - (338, 'jm', 3, 'Jamaica'), - (340, 'gp', 2, 'Guadeloupe (French Department of)'), - (342, 'bb', 3, 'Barbados'), - (344, 'ag', 3, 'Antigua and Barbuda'), - (346, 'ky', 3, 'Cayman Islands'), - (348, 'vg', 3, 'British Virgin Islands'), - (350, 'bm', 2, 'Bermuda'), - (352, 'gd', 2, 'Grenada'), - (354, 'ms', 2, 'Montserrat'), - (356, 'kn', 2, 'Saint Kitts and Nevis'), - (358, 'lc', 2, 'Saint Lucia'), - (360, 'vc', 2, 'Saint Vincent and the Grenadines'), - (362, 'nl', 2, 'Netherlands Antilles'), - (363, 'aw', 2, 'Aruba'), - (364, 'bs', 2, 'Bahamas (Commonwealth of the)'), - (365, 'ai', 3, 'Anguilla'), - (366, 'dm', 2, 'Dominica (Commonwealth of)'), - (368, 'cu', 2, 'Cuba'), - (370, 'do', 2, 'Dominican Republic'), - (372, 'ht', 2, 'Haiti (Republic of)'), - (374, 'tt', 2, 'Trinidad and Tobago'), - (376, 'tc', 2, 'Turks and Caicos Islands'), - (400, 'az', 2, 'Azerbaijani Republic'), - (401, 'kz', 2, 'Kazakhstan (Republic of)'), - (402, 'bt', 2, 'Bhutan (Kingdom of)'), - (404, 'in', 2, 'India (Republic of)'), - (405, 'in', 2, 'India (Republic of)'), - (410, 'pk', 2, 'Pakistan (Islamic Republic of)'), - (412, 'af', 2, 'Afghanistan'), - (413, 'lk', 2, 'Sri Lanka (Democratic Socialist Republic of)'), - (414, 'mm', 2, 'Myanmar (Union of)'), - (415, 'lb', 2, 'Lebanon'), - (416, 'jo', 2, 'Jordan (Hashemite Kingdom of)'), - (417, 'sy', 2, 'Syrian Arab Republic'), - (418, 'iq', 2, 'Iraq (Republic of)'), - (419, 'kw', 2, 'Kuwait (State of)'), - (420, 'sa', 2, 'Saudi Arabia (Kingdom of)'), - (421, 'ye', 2, 'Yemen (Republic of)'), - (422, 'om', 2, 'Oman (Sultanate of)'), - (423, 'ps', 2, 'Palestine'), - (424, 'ae', 2, 'United Arab Emirates'), - (425, 'il', 2, 'Israel (State of)'), - (426, 'bh', 2, 'Bahrain (Kingdom of)'), - (427, 'qa', 2, 'Qatar (State of)'), - (428, 'mn', 2, 'Mongolia'), - (429, 'np', 2, 'Nepal'), - (430, 'ae', 2, 'United Arab Emirates'), - (431, 'ae', 2, 'United Arab Emirates'), - (432, 'ir', 2, 'Iran (Islamic Republic of)'), - (434, 'uz', 2, 'Uzbekistan (Republic of)'), - (436, 'tj', 2, 'Tajikistan (Republic of)'), - (437, 'kg', 2, 'Kyrgyz Republic'), - (438, 'tm', 2, 'Turkmenistan'), - (440, 'jp', 2, 'Asia/Tokyo', 'ja', 14, 'Japan'), - (441, 'jp', 2, 'Asia/Tokyo', 'ja', 14, 'Japan'), - (450, 'kr', 2, 'Korea (Republic of)'), - (452, 'vn', 2, 'Viet Nam (Socialist Republic of)'), - (454, 'hk', 2, '"Hong Kong, China"'), - (455, 'mo', 2, '"Macao, China"'), - (456, 'kh', 2, 'Cambodia (Kingdom of)'), - (457, 'la', 2, "Lao People's Democratic Republic"), - (460, 'cn', 2, "Asia/Beijing", 'zh', 13, "China (People's Republic of)"), - (461, 'cn', 2, "Asia/Beijing", 'zh', 13, "China (People's Republic of)"), - (466, 'tw', 2, "Taiwan (Republic of China)"), - (467, 'kp', 2, "Democratic People's Republic of Korea"), - (470, 'bd', 2, "Bangladesh (People's Republic of)"), - (472, 'mv', 2, 'Maldives (Republic of)'), - (502, 'my', 2, 'Malaysia'), - (505, 'au', 2, 'Australia/Sydney', 'en', 11, 'Australia'), - (510, 'id', 2, 'Indonesia (Republic of)'), - (514, 'tl', 2, 'Democratic Republic of Timor-Leste'), - (515, 'ph', 2, 'Philippines (Republic of the)'), - (520, 'th', 2, 'Thailand'), - (525, 'sg', 2, 'Asia/Singapore', 'en', 11, 'Singapore (Republic of)'), - (528, 'bn', 2, 'Brunei Darussalam'), - (530, 'nz', 2, 'Pacific/Auckland', 'en', 'New Zealand'), - (534, 'mp', 2, 'Northern Mariana Islands (Commonwealth of the)'), - (535, 'gu', 2, 'Guam'), - (536, 'nr', 2, 'Nauru (Republic of)'), - (537, 'pg', 2, 'Papua New Guinea'), - (539, 'to', 2, 'Tonga (Kingdom of)'), - (540, 'sb', 2, 'Solomon Islands'), - (541, 'vu', 2, 'Vanuatu (Republic of)'), - (542, 'fj', 2, 'Fiji (Republic of)'), - (543, 'wf', 2, "Wallis and Futuna (Territoire franais d'outre-mer)"), - (544, 'as', 2, 'American Samoa'), - (545, 'ki', 2, 'Kiribati (Republic of)'), - (546, 'nc', 2, "New Caledonia (Territoire franais d'outre-mer)"), - (547, 'pf', 2, "French Polynesia (Territoire franais d'outre-mer)"), - (548, 'ck', 2, 'Cook Islands'), - (549, 'ws', 2, 'Samoa (Independent State of)'), - (550, 'fm', 2, 'Micronesia (Federated States of)'), - (551, 'mh', 2, 'Marshall Islands (Republic of the)'), - (552, 'pw', 2, 'Palau (Republic of)'), - (602, 'eg', 2, 'Egypt (Arab Republic of)'), - (603, 'dz', 2, "Algeria (People's Democratic Republic of)"), - (604, 'ma', 2, 'Morocco (Kingdom of)'), - (605, 'tn', 2, 'Tunisia'), - (606, 'ly', 2, "Libya (Socialist People's Libyan Arab Jamahiriya)"), - (607, 'gm', 2, 'Gambia (Republic of the)'), - (608, 'sn', 2, 'Senegal (Republic of)'), - (609, 'mr', 2, 'Mauritania (Islamic Republic of)'), - (610, 'ml', 2, 'Mali (Republic of)'), - (611, 'gn', 2, 'Guinea (Republic of)'), - (612, 'ci', 2, "Cte d'Ivoire (Republic of)"), - (613, 'bf', 2, 'Burkina Faso'), - (614, 'ne', 2, 'Niger (Republic of the)'), - (615, 'tg', 2, 'Togolese Republic'), - (616, 'bj', 2, 'Benin (Republic of)'), - (617, 'mu', 2, 'Mauritius (Republic of)'), - (618, 'lr', 2, 'Liberia (Republic of)'), - (619, 'sl', 2, 'Sierra Leone'), - (620, 'gh', 2, 'Ghana'), - (621, 'ng', 2, 'Nigeria (Federal Republic of)'), - (622, 'td', 2, 'Chad (Republic of)'), - (623, 'cf', 2, 'Central African Republic'), - (624, 'cm', 2, 'Cameroon (Republic of)'), - (625, 'cv', 2, 'Cape Verde (Republic of)'), - (626, 'st', 2, 'Sao Tome and Principe (Democratic Republic of)'), - (627, 'gq', 2, 'Equatorial Guinea (Republic of)'), - (628, 'ga', 2, 'Gabonese Republic'), - (629, 'cg', 2, 'Congo (Republic of the)'), - (630, 'cg', 2, 'Democratic Republic of the Congo'), - (631, 'ao', 2, 'Angola (Republic of)'), - (632, 'gw', 2, 'Guinea-Bissau (Republic of)'), - (633, 'sc', 2, 'Seychelles (Republic of)'), - (634, 'sd', 2, 'Sudan (Republic of the)'), - (635, 'rw', 2, 'Rwanda (Republic of)'), - (636, 'et', 2, 'Ethiopia (Federal Democratic Republic of)'), - (637, 'so', 2, 'Somali Democratic Republic'), - (638, 'dj', 2, 'Djibouti (Republic of)'), - (639, 'ke', 2, 'Kenya (Republic of)'), - (640, 'tz', 2, 'Tanzania (United Republic of)'), - (641, 'ug', 2, 'Uganda (Republic of)'), - (642, 'bi', 2, 'Burundi (Republic of)'), - (643, 'mz', 2, 'Mozambique (Republic of)'), - (645, 'zm', 2, 'Zambia (Republic of)'), - (646, 'mg', 2, 'Madagascar (Republic of)'), - (647, 're', 2, 'Reunion (French Department of)'), - (648, 'zw', 2, 'Zimbabwe (Republic of)'), - (649, 'na', 2, 'Namibia (Republic of)'), - (650, 'mw', 2, 'Malawi'), - (651, 'ls', 2, 'Lesotho (Kingdom of)'), - (652, 'bw', 2, 'Botswana (Republic of)'), - (653, 'sz', 2, 'Swaziland (Kingdom of)'), - (654, 'km', 2, 'Comoros (Union of the)'), - (655, 'za', 2, 'Africa/Johannesburg', 'en', 'South Africa (Republic of)'), - (657, 'er', 2, 'Eritrea'), - (702, 'bz', 2, 'Belize'), - (704, 'gt', 2, 'Guatemala (Republic of)'), - (706, 'sv', 2, 'El Salvador (Republic of)'), - (708, 'hn', 3, 'Honduras (Republic of)'), - (710, 'ni', 2, 'Nicaragua'), - (712, 'cr', 2, 'Costa Rica'), - (714, 'pa', 2, 'Panama (Republic of)'), - (716, 'pe', 2, 'Peru'), - (722, 'ar', 3, 'Argentine Republic'), - (724, 'br', 2, 'Brazil (Federative Republic of)'), - (730, 'cl', 2, 'Chile'), - (732, 'co', 3, 'Colombia (Republic of)'), - (734, 've', 2, 'Venezuela (Bolivarian Republic of)'), - (736, 'bo', 2, 'Bolivia (Republic of)'), - (738, 'gy', 2, 'Guyana'), - (740, 'ec', 2, 'Ecuador'), - (742, 'gf', 2, 'French Guiana (French Department of)'), - (744, 'py', 2, 'Paraguay (Republic of)'), - (746, 'sr', 2, 'Suriname (Republic of)'), - (748, 'uy', 2, 'Uruguay (Eastern Republic of)'), - (750, 'fk', 2, 'Falkland Islands (Malvinas)')] - -get_mcc = lambda elt: elt[0] -get_iso = lambda elt: elt[1] -get_sd = lambda elt: elt[2] -get_tz = lambda elt: len(elt) > 4 and elt[3] or '' -get_lang = lambda elt: len(elt) > 5 and elt[4] or '' -get_wifi = lambda elt: len(elt) > 6 and elt[5] or 0 - -mcc_codes = ['0x%04x' % get_mcc(elt) for elt in mcc_table] -tz_set = sorted(x for x in set(get_tz(elt) for elt in mcc_table)) -lang_set = sorted(x for x in set(get_lang(elt) for elt in mcc_table)) - -def mk_ind_code(elt): - iso = get_iso(elt) - iso_code = ((ord(iso[0]) << 8) | ord(iso[1])) & 0xFFFF # 16 bits - wifi = get_wifi(elt) & 0x000F # 4 bits - sd = get_sd(elt) & 0x0003 # 2 bits - tz_ind = tz_set.index(get_tz(elt)) & 0x001F # 5 bits - lang_ind = lang_set.index(get_lang(elt)) & 0x000F # 4 bits - return (iso_code << 16) | (wifi << 11) | (sd << 9) | (tz_ind << 4) | lang_ind - -ind_codes = ['0x%08x' % mk_ind_code(elt) for elt in mcc_table] - -def fmt_list(title, l, batch_sz): - sl = [] - for i in range(len(l) / batch_sz + (len(l) % batch_sz and 1 or 0)): - j = i * batch_sz - sl.append((' ' * 8) + ', '.join(l[j:j + batch_sz])) - return ' private static final %s = {\n' % title + ',\n'.join(sl) + '\n };\n' - -def do_autogen_comment(extra_desc=[]): - print ' /' + '**\n * AUTO GENERATED (by the Python code above)' - for line in extra_desc: - print ' * %s' % line - print ' *' + '/' - -do_autogen_comment() -print fmt_list('String[] TZ_STRINGS', ['"%s"' % x for x in tz_set], 1) -do_autogen_comment() -print fmt_list('String[] LANG_STRINGS', ['"%s"' % x for x in lang_set], 10) -do_autogen_comment(['This table is a list of MCC codes. The index in this table', - 'of a given MCC code is the index of extra information about', - 'that MCC in the IND_CODES table.']) -print fmt_list('short[] MCC_CODES', mcc_codes, 10) -do_autogen_comment(['The values in this table are broken down as follows (msb to lsb):', - ' iso country code 16 bits', - ' (unused) 1 bit', - ' wifi channel 4 bits', - ' smalled digit 2 bits', - ' default timezone 5 bits', - ' default language 4 bits']) -print fmt_list('int[] IND_CODES', ind_codes, 6) - -def parse_ind_code(ind): - mcc = eval(mcc_codes[ind]) - code = eval(ind_codes[ind]) - iso_lsb = int((code >> 16) & 0x00FF) - iso_msb = int((code >> 24) & 0x00FF) - iso = '%s%s' % (chr(iso_msb), chr(iso_lsb)) - wifi = int((code >> 11) & 0x000F) - sd = int((code >> 9) & 0x0003) - tz_ind = (code >> 4) & 0x001F - lang_ind = (code >> 0) & 0x000F - return (mcc, iso, sd, tz_set[tz_ind], lang_set[lang_ind], wifi) - -fmt_str = 'mcc = %s, iso = %s, sd = %s, tz = %s, lang = %s, wifi = %s' -orig_table = [fmt_str % (get_mcc(elt), get_iso(elt), get_sd(elt), - get_tz(elt), get_lang(elt), get_wifi(elt)) - for elt in mcc_table] -derived_table = [fmt_str % parse_ind_code(i) for i in range(len(ind_codes))] -for i in range(len(orig_table)): - if orig_table[i] == derived_table[i]: continue - print 'MISMATCH ERROR : ', orig_table[i], " != ", derived_table[i] - -*/ +import java.util.ArrayList; +import java.util.Collections; +import java.util.Locale; +import libcore.icu.TimeZones; /** * Mobile Country Code @@ -371,200 +38,153 @@ for i in range(len(orig_table)): */ public final class MccTable { - /** - * AUTO GENERATED (by the Python code above) - */ - private static final String[] TZ_STRINGS = { - "", - "Africa/Johannesburg", - "Asia/Beijing", - "Asia/Singapore", - "Asia/Tokyo", - "Australia/Sydney", - "Europe/Amsterdam", - "Europe/Berlin", - "Europe/Dublin", - "Europe/London", - "Europe/Madrid", - "Europe/Paris", - "Europe/Prague", - "Europe/Rome", - "Europe/Vienna", - "Europe/Warsaw", - "Europe/Zurich", - "Pacific/Auckland" - }; + static final String LOG_TAG = "MccTable"; - /** - * AUTO GENERATED (by the Python code above) - */ - private static final String[] LANG_STRINGS = { - "", "cs", "de", "en", "es", "fr", "it", "ja", "nl", "zh" - }; + static ArrayList<MccEntry> table; - /** - * AUTO GENERATED (by the Python code above) - * This table is a list of MCC codes. The index in this table - * of a given MCC code is the index of extra information about - * that MCC in the IND_CODES table. - */ - private static final short[] MCC_CODES = { - 0x00ca, 0x00cc, 0x00ce, 0x00d0, 0x00d4, 0x00d5, 0x00d6, 0x00d8, 0x00da, 0x00db, - 0x00dc, 0x00de, 0x00e1, 0x00e2, 0x00e4, 0x00e6, 0x00e7, 0x00e8, 0x00ea, 0x00eb, - 0x00ee, 0x00f0, 0x00f2, 0x00f4, 0x00f6, 0x00f7, 0x00f8, 0x00fa, 0x00ff, 0x0101, - 0x0103, 0x0104, 0x0106, 0x010a, 0x010c, 0x010e, 0x0110, 0x0112, 0x0114, 0x0116, - 0x0118, 0x011a, 0x011b, 0x011c, 0x011e, 0x0120, 0x0121, 0x0122, 0x0124, 0x0125, - 0x0126, 0x0127, 0x0129, 0x012e, 0x0134, 0x0136, 0x0137, 0x0138, 0x0139, 0x013a, - 0x013b, 0x013c, 0x014a, 0x014c, 0x014e, 0x0152, 0x0154, 0x0156, 0x0158, 0x015a, - 0x015c, 0x015e, 0x0160, 0x0162, 0x0164, 0x0166, 0x0168, 0x016a, 0x016b, 0x016c, - 0x016d, 0x016e, 0x0170, 0x0172, 0x0174, 0x0176, 0x0178, 0x0190, 0x0191, 0x0192, - 0x0194, 0x0195, 0x019a, 0x019c, 0x019d, 0x019e, 0x019f, 0x01a0, 0x01a1, 0x01a2, - 0x01a3, 0x01a4, 0x01a5, 0x01a6, 0x01a7, 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, - 0x01ad, 0x01ae, 0x01af, 0x01b0, 0x01b2, 0x01b4, 0x01b5, 0x01b6, 0x01b8, 0x01b9, - 0x01c2, 0x01c4, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01cc, 0x01cd, 0x01d2, 0x01d3, - 0x01d6, 0x01d8, 0x01f6, 0x01f9, 0x01fe, 0x0202, 0x0203, 0x0208, 0x020d, 0x0210, - 0x0212, 0x0216, 0x0217, 0x0218, 0x0219, 0x021b, 0x021c, 0x021d, 0x021e, 0x021f, - 0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0226, 0x0227, 0x0228, 0x025a, - 0x025b, 0x025c, 0x025d, 0x025e, 0x025f, 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, - 0x0265, 0x0266, 0x0267, 0x0268, 0x0269, 0x026a, 0x026b, 0x026c, 0x026d, 0x026e, - 0x026f, 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277, 0x0278, - 0x0279, 0x027a, 0x027b, 0x027c, 0x027d, 0x027e, 0x027f, 0x0280, 0x0281, 0x0282, - 0x0283, 0x0285, 0x0286, 0x0287, 0x0288, 0x0289, 0x028a, 0x028b, 0x028c, 0x028d, - 0x028e, 0x028f, 0x0291, 0x02be, 0x02c0, 0x02c2, 0x02c4, 0x02c6, 0x02c8, 0x02ca, - 0x02cc, 0x02d2, 0x02d4, 0x02da, 0x02dc, 0x02de, 0x02e0, 0x02e2, 0x02e4, 0x02e6, - 0x02e8, 0x02ea, 0x02ec, 0x02ee - }; + static class MccEntry implements Comparable<MccEntry> + { + int mcc; + String iso; + int smallestDigitsMnc; + String language; + int wifiChannels; - /** - * AUTO GENERATED (by the Python code above) - * The values in this table are broken down as follows (msb to lsb): - * iso country code 16 bits - * (unused) 1 bit - * wifi channel 4 bits - * smalled digit 2 bits - * default timezone 5 bits - * default language 4 bits - */ - private static final int[] IND_CODES = { - 0x67720400, 0x6e6c6c68, 0x62650400, 0x667204b5, 0x6d630400, 0x61640400, - 0x657304a4, 0x68750400, 0x62610400, 0x68720400, 0x72730400, 0x697404d6, - 0x766104d6, 0x726f0400, 0x63680502, 0x637a6cc1, 0x736b0400, 0x61746ce2, - 0x67626c93, 0x67626c93, 0x646b0400, 0x73650400, 0x6e6f0400, 0x66690400, - 0x6c740400, 0x6c760400, 0x65650400, 0x72750400, 0x75610400, 0x62790400, - 0x6d640400, 0x706c04f0, 0x64656c72, 0x67690400, 0x70740400, 0x6c750400, - 0x69650483, 0x69730400, 0x616c0400, 0x6d740400, 0x63790400, 0x67650400, - 0x616d0400, 0x62670400, 0x74720400, 0x666f0400, 0x67650400, 0x676c0400, - 0x736d0400, 0x736c0400, 0x6d6b0400, 0x6c690400, 0x6d650400, 0x63615e00, - 0x706d0400, 0x75735e03, 0x75735e03, 0x75735e03, 0x75735e03, 0x75735e03, - 0x75735e03, 0x75735e03, 0x70720400, 0x76690400, 0x6d780600, 0x6a6d0600, - 0x67700400, 0x62620600, 0x61670600, 0x6b790600, 0x76670600, 0x626d0400, - 0x67640400, 0x6d730400, 0x6b6e0400, 0x6c630400, 0x76630400, 0x6e6c0400, - 0x61770400, 0x62730400, 0x61690600, 0x646d0400, 0x63750400, 0x646f0400, - 0x68740400, 0x74740400, 0x74630400, 0x617a0400, 0x6b7a0400, 0x62740400, - 0x696e0400, 0x696e0400, 0x706b0400, 0x61660400, 0x6c6b0400, 0x6d6d0400, - 0x6c620400, 0x6a6f0400, 0x73790400, 0x69710400, 0x6b770400, 0x73610400, - 0x79650400, 0x6f6d0400, 0x70730400, 0x61650400, 0x696c0400, 0x62680400, - 0x71610400, 0x6d6e0400, 0x6e700400, 0x61650400, 0x61650400, 0x69720400, - 0x757a0400, 0x746a0400, 0x6b670400, 0x746d0400, 0x6a707447, 0x6a707447, - 0x6b720400, 0x766e0400, 0x686b0400, 0x6d6f0400, 0x6b680400, 0x6c610400, - 0x636e6c29, 0x636e6c29, 0x74770400, 0x6b700400, 0x62640400, 0x6d760400, - 0x6d790400, 0x61755c53, 0x69640400, 0x746c0400, 0x70680400, 0x74680400, - 0x73675c33, 0x626e0400, 0x6e7a0513, 0x6d700400, 0x67750400, 0x6e720400, - 0x70670400, 0x746f0400, 0x73620400, 0x76750400, 0x666a0400, 0x77660400, - 0x61730400, 0x6b690400, 0x6e630400, 0x70660400, 0x636b0400, 0x77730400, - 0x666d0400, 0x6d680400, 0x70770400, 0x65670400, 0x647a0400, 0x6d610400, - 0x746e0400, 0x6c790400, 0x676d0400, 0x736e0400, 0x6d720400, 0x6d6c0400, - 0x676e0400, 0x63690400, 0x62660400, 0x6e650400, 0x74670400, 0x626a0400, - 0x6d750400, 0x6c720400, 0x736c0400, 0x67680400, 0x6e670400, 0x74640400, - 0x63660400, 0x636d0400, 0x63760400, 0x73740400, 0x67710400, 0x67610400, - 0x63670400, 0x63670400, 0x616f0400, 0x67770400, 0x73630400, 0x73640400, - 0x72770400, 0x65740400, 0x736f0400, 0x646a0400, 0x6b650400, 0x747a0400, - 0x75670400, 0x62690400, 0x6d7a0400, 0x7a6d0400, 0x6d670400, 0x72650400, - 0x7a770400, 0x6e610400, 0x6d770400, 0x6c730400, 0x62770400, 0x737a0400, - 0x6b6d0400, 0x7a610413, 0x65720400, 0x627a0400, 0x67740400, 0x73760400, - 0x686e0600, 0x6e690400, 0x63720400, 0x70610400, 0x70650400, 0x61720600, - 0x62720400, 0x636c0400, 0x636f0600, 0x76650400, 0x626f0400, 0x67790400, - 0x65630400, 0x67660400, 0x70790400, 0x73720400, 0x75790400, 0x666b0400 - }; + MccEntry(int mnc, String iso, int smallestDigitsMCC) { + this(mnc, iso, smallestDigitsMCC, null); + } - static final String LOG_TAG = "MccTable"; + MccEntry(int mnc, String iso, int smallestDigitsMCC, String language) { + this(mnc, iso, smallestDigitsMCC, language, 0); + } + + MccEntry(int mnc, String iso, int smallestDigitsMCC, String language, int wifiChannels) { + this.mcc = mnc; + this.iso = iso; + this.smallestDigitsMnc = smallestDigitsMCC; + this.language = language; + this.wifiChannels = wifiChannels; + } + + + public int compareTo(MccEntry o) + { + return mcc - o.mcc; + } + } + + private static MccEntry + entryForMcc(int mcc) + { + int index; + + MccEntry m; + + m = new MccEntry(mcc, null, 0); + + index = Collections.binarySearch(table, m); - /** - * Given a Mobile Country Code, returns a default time zone ID - * if available. Returns null if unavailable. - */ - public static String defaultTimeZoneForMcc(int mcc) { - int index = Arrays.binarySearch(MCC_CODES, (short)mcc); if (index < 0) { return null; + } else { + return table.get(index); } - int indCode = IND_CODES[index]; - int tzInd = (indCode >>> 4) & 0x001F; - String tz = TZ_STRINGS[tzInd]; - if (tz == "") { + } + + /** + * Returns a default time zone ID for the given MCC. + * @param mcc Mobile Country Code + * @return default TimeZone ID, or null if not specified + */ + public static String defaultTimeZoneForMcc(int mcc) { + MccEntry entry; + + entry = entryForMcc(mcc); + if (entry == null || entry.iso == null) { return null; + } else { + Locale locale; + if (entry.language == null) { + locale = new Locale(entry.iso); + } else { + locale = new Locale(entry.language, entry.iso); + } + String[] tz = TimeZones.forLocale(locale); + if (tz.length == 0) return null; + return tz[0]; } - return tz; } /** - * Given a Mobile Country Code, returns an ISO two-character - * country code if available. Returns "" if unavailable. + * Given a GSM Mobile Country Code, returns + * an ISO two-character country code if available. + * Returns "" if unavailable. */ - public static String countryCodeForMcc(int mcc) { - int index = Arrays.binarySearch(MCC_CODES, (short)mcc); - if (index < 0) { + public static String + countryCodeForMcc(int mcc) + { + MccEntry entry; + + entry = entryForMcc(mcc); + + if (entry == null) { return ""; + } else { + return entry.iso; } - int indCode = IND_CODES[index]; - byte[] iso = {(byte)((indCode >>> 24) & 0x00FF), (byte)((indCode >>> 16) & 0x00FF)}; - return new String(iso); } /** - * Given a GSM Mobile Country Code, returns an ISO 2-3 character - * language code if available. Returns null if unavailable. + * Given a GSM Mobile Country Code, returns + * an ISO 2-3 character language code if available. + * Returns null if unavailable. */ public static String defaultLanguageForMcc(int mcc) { - int index = Arrays.binarySearch(MCC_CODES, (short)mcc); - if (index < 0) { - return null; - } - int indCode = IND_CODES[index]; - int langInd = indCode & 0x000F; - String lang = LANG_STRINGS[langInd]; - if (lang == "") { + MccEntry entry; + + entry = entryForMcc(mcc); + + if (entry == null) { return null; + } else { + return entry.language; } - return lang; } /** - * Given a GSM Mobile Country Code, returns the corresponding - * smallest number of digits field. Returns 2 if unavailable. + * Given a GSM Mobile Country Code, returns + * the smallest number of digits that M if available. + * Returns 2 if unavailable. */ - public static int smallestDigitsMccForMnc(int mcc) { - int index = Arrays.binarySearch(MCC_CODES, (short)mcc); - if (index < 0) { + public static int + smallestDigitsMccForMnc(int mcc) + { + MccEntry entry; + + entry = entryForMcc(mcc); + + if (entry == null) { return 2; + } else { + return entry.smallestDigitsMnc; } - int indCode = IND_CODES[index]; - int smDig = (indCode >>> 9) & 0x0003; - return smDig; } /** * Given a GSM Mobile Country Code, returns the number of wifi * channels allowed in that country. Returns 0 if unavailable. */ - public static int wifiChannelsForMcc(int mcc) { - int index = Arrays.binarySearch(MCC_CODES, (short)mcc); - if (index < 0) { + public static int + wifiChannelsForMcc(int mcc) { + MccEntry entry; + + entry = entryForMcc(mcc); + + if (entry == null) { return 0; + } else { + return entry.wifiChannels; } - int indCode = IND_CODES[index]; - int wifi = (indCode >>> 11) & 0x000F; - return wifi; } /** @@ -656,4 +276,262 @@ public final class MccTable wM.setNumAllowedChannels(wifiChannels, true); } } + + static { + table = new ArrayList<MccEntry>(240); + + + /* + * The table below is built from two resources: + * + * 1) ITU "Mobile Network Code (MNC) for the international + * identification plan for mobile terminals and mobile users" + * which is available as an annex to the ITU operational bulletin + * available here: http://www.itu.int/itu-t/bulletin/annex.html + * + * 2) The ISO 3166 country codes list, available here: + * http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/index.html + * + * This table has not been verified. + * + */ + + table.add(new MccEntry(202,"gr",2)); //Greece + table.add(new MccEntry(204,"nl",2,"nl",13)); //Netherlands (Kingdom of the) + table.add(new MccEntry(206,"be",2)); //Belgium + table.add(new MccEntry(208,"fr",2,"fr")); //France + table.add(new MccEntry(212,"mc",2)); //Monaco (Principality of) + table.add(new MccEntry(213,"ad",2)); //Andorra (Principality of) + table.add(new MccEntry(214,"es",2,"es")); //Spain + table.add(new MccEntry(216,"hu",2)); //Hungary (Republic of) + table.add(new MccEntry(218,"ba",2)); //Bosnia and Herzegovina + table.add(new MccEntry(219,"hr",2)); //Croatia (Republic of) + table.add(new MccEntry(220,"rs",2)); //Serbia and Montenegro + table.add(new MccEntry(222,"it",2,"it")); //Italy + table.add(new MccEntry(225,"va",2,"it")); //Vatican City State + table.add(new MccEntry(226,"ro",2)); //Romania + table.add(new MccEntry(228,"ch",2,"de")); //Switzerland (Confederation of) + table.add(new MccEntry(230,"cz",2,"cs",13)); //Czech Republic + table.add(new MccEntry(231,"sk",2)); //Slovak Republic + table.add(new MccEntry(232,"at",2,"de",13)); //Austria + table.add(new MccEntry(234,"gb",2,"en",13)); //United Kingdom of Great Britain and Northern Ireland + table.add(new MccEntry(235,"gb",2,"en",13)); //United Kingdom of Great Britain and Northern Ireland + table.add(new MccEntry(238,"dk",2)); //Denmark + table.add(new MccEntry(240,"se",2)); //Sweden + table.add(new MccEntry(242,"no",2)); //Norway + table.add(new MccEntry(244,"fi",2)); //Finland + table.add(new MccEntry(246,"lt",2)); //Lithuania (Republic of) + table.add(new MccEntry(247,"lv",2)); //Latvia (Republic of) + table.add(new MccEntry(248,"ee",2)); //Estonia (Republic of) + table.add(new MccEntry(250,"ru",2)); //Russian Federation + table.add(new MccEntry(255,"ua",2)); //Ukraine + table.add(new MccEntry(257,"by",2)); //Belarus (Republic of) + table.add(new MccEntry(259,"md",2)); //Moldova (Republic of) + table.add(new MccEntry(260,"pl",2)); //Poland (Republic of) + table.add(new MccEntry(262,"de",2,"de",13)); //Germany (Federal Republic of) + table.add(new MccEntry(266,"gi",2)); //Gibraltar + table.add(new MccEntry(268,"pt",2)); //Portugal + table.add(new MccEntry(270,"lu",2)); //Luxembourg + table.add(new MccEntry(272,"ie",2,"en")); //Ireland + table.add(new MccEntry(274,"is",2)); //Iceland + table.add(new MccEntry(276,"al",2)); //Albania (Republic of) + table.add(new MccEntry(278,"mt",2)); //Malta + table.add(new MccEntry(280,"cy",2)); //Cyprus (Republic of) + table.add(new MccEntry(282,"ge",2)); //Georgia + table.add(new MccEntry(283,"am",2)); //Armenia (Republic of) + table.add(new MccEntry(284,"bg",2)); //Bulgaria (Republic of) + table.add(new MccEntry(286,"tr",2)); //Turkey + table.add(new MccEntry(288,"fo",2)); //Faroe Islands + table.add(new MccEntry(289,"ge",2)); //Abkhazia (Georgia) + table.add(new MccEntry(290,"gl",2)); //Greenland (Denmark) + table.add(new MccEntry(292,"sm",2)); //San Marino (Republic of) + table.add(new MccEntry(293,"sl",2)); //Slovenia (Republic of) + table.add(new MccEntry(294,"mk",2)); //The Former Yugoslav Republic of Macedonia + table.add(new MccEntry(295,"li",2)); //Liechtenstein (Principality of) + table.add(new MccEntry(297,"me",2)); //Montenegro (Republic of) + table.add(new MccEntry(302,"ca",3,"",11)); //Canada + table.add(new MccEntry(308,"pm",2)); //Saint Pierre and Miquelon (Collectivit territoriale de la Rpublique franaise) + table.add(new MccEntry(310,"us",3,"en",11)); //United States of America + table.add(new MccEntry(311,"us",3,"en",11)); //United States of America + table.add(new MccEntry(312,"us",3,"en",11)); //United States of America + table.add(new MccEntry(313,"us",3,"en",11)); //United States of America + table.add(new MccEntry(314,"us",3,"en",11)); //United States of America + table.add(new MccEntry(315,"us",3,"en",11)); //United States of America + table.add(new MccEntry(316,"us",3,"en",11)); //United States of America + table.add(new MccEntry(330,"pr",2)); //Puerto Rico + table.add(new MccEntry(332,"vi",2)); //United States Virgin Islands + table.add(new MccEntry(334,"mx",3)); //Mexico + table.add(new MccEntry(338,"jm",3)); //Jamaica + table.add(new MccEntry(340,"gp",2)); //Guadeloupe (French Department of) + table.add(new MccEntry(342,"bb",3)); //Barbados + table.add(new MccEntry(344,"ag",3)); //Antigua and Barbuda + table.add(new MccEntry(346,"ky",3)); //Cayman Islands + table.add(new MccEntry(348,"vg",3)); //British Virgin Islands + table.add(new MccEntry(350,"bm",2)); //Bermuda + table.add(new MccEntry(352,"gd",2)); //Grenada + table.add(new MccEntry(354,"ms",2)); //Montserrat + table.add(new MccEntry(356,"kn",2)); //Saint Kitts and Nevis + table.add(new MccEntry(358,"lc",2)); //Saint Lucia + table.add(new MccEntry(360,"vc",2)); //Saint Vincent and the Grenadines + table.add(new MccEntry(362,"nl",2)); //Netherlands Antilles + table.add(new MccEntry(363,"aw",2)); //Aruba + table.add(new MccEntry(364,"bs",2)); //Bahamas (Commonwealth of the) + table.add(new MccEntry(365,"ai",3)); //Anguilla + table.add(new MccEntry(366,"dm",2)); //Dominica (Commonwealth of) + table.add(new MccEntry(368,"cu",2)); //Cuba + table.add(new MccEntry(370,"do",2)); //Dominican Republic + table.add(new MccEntry(372,"ht",2)); //Haiti (Republic of) + table.add(new MccEntry(374,"tt",2)); //Trinidad and Tobago + table.add(new MccEntry(376,"tc",2)); //Turks and Caicos Islands + table.add(new MccEntry(400,"az",2)); //Azerbaijani Republic + table.add(new MccEntry(401,"kz",2)); //Kazakhstan (Republic of) + table.add(new MccEntry(402,"bt",2)); //Bhutan (Kingdom of) + table.add(new MccEntry(404,"in",2)); //India (Republic of) + table.add(new MccEntry(405,"in",2)); //India (Republic of) + table.add(new MccEntry(410,"pk",2)); //Pakistan (Islamic Republic of) + table.add(new MccEntry(412,"af",2)); //Afghanistan + table.add(new MccEntry(413,"lk",2)); //Sri Lanka (Democratic Socialist Republic of) + table.add(new MccEntry(414,"mm",2)); //Myanmar (Union of) + table.add(new MccEntry(415,"lb",2)); //Lebanon + table.add(new MccEntry(416,"jo",2)); //Jordan (Hashemite Kingdom of) + table.add(new MccEntry(417,"sy",2)); //Syrian Arab Republic + table.add(new MccEntry(418,"iq",2)); //Iraq (Republic of) + table.add(new MccEntry(419,"kw",2)); //Kuwait (State of) + table.add(new MccEntry(420,"sa",2)); //Saudi Arabia (Kingdom of) + table.add(new MccEntry(421,"ye",2)); //Yemen (Republic of) + table.add(new MccEntry(422,"om",2)); //Oman (Sultanate of) + table.add(new MccEntry(423,"ps",2)); //Palestine + table.add(new MccEntry(424,"ae",2)); //United Arab Emirates + table.add(new MccEntry(425,"il",2)); //Israel (State of) + table.add(new MccEntry(426,"bh",2)); //Bahrain (Kingdom of) + table.add(new MccEntry(427,"qa",2)); //Qatar (State of) + table.add(new MccEntry(428,"mn",2)); //Mongolia + table.add(new MccEntry(429,"np",2)); //Nepal + table.add(new MccEntry(430,"ae",2)); //United Arab Emirates + table.add(new MccEntry(431,"ae",2)); //United Arab Emirates + table.add(new MccEntry(432,"ir",2)); //Iran (Islamic Republic of) + table.add(new MccEntry(434,"uz",2)); //Uzbekistan (Republic of) + table.add(new MccEntry(436,"tj",2)); //Tajikistan (Republic of) + table.add(new MccEntry(437,"kg",2)); //Kyrgyz Republic + table.add(new MccEntry(438,"tm",2)); //Turkmenistan + table.add(new MccEntry(440,"jp",2,"ja",14)); //Japan + table.add(new MccEntry(441,"jp",2,"ja",14)); //Japan + table.add(new MccEntry(450,"kr",2,"ko",13)); //Korea (Republic of) + table.add(new MccEntry(452,"vn",2)); //Viet Nam (Socialist Republic of) + table.add(new MccEntry(454,"hk",2)); //"Hong Kong, China" + table.add(new MccEntry(455,"mo",2)); //"Macao, China" + table.add(new MccEntry(456,"kh",2)); //Cambodia (Kingdom of) + table.add(new MccEntry(457,"la",2)); //Lao People's Democratic Republic + table.add(new MccEntry(460,"cn",2,"zh",13)); //China (People's Republic of) + table.add(new MccEntry(461,"cn",2,"zh",13)); //China (People's Republic of) + table.add(new MccEntry(466,"tw",2)); //"Taiwan, China" + table.add(new MccEntry(467,"kp",2)); //Democratic People's Republic of Korea + table.add(new MccEntry(470,"bd",2)); //Bangladesh (People's Republic of) + table.add(new MccEntry(472,"mv",2)); //Maldives (Republic of) + table.add(new MccEntry(502,"my",2)); //Malaysia + table.add(new MccEntry(505,"au",2,"en",11)); //Australia + table.add(new MccEntry(510,"id",2)); //Indonesia (Republic of) + table.add(new MccEntry(514,"tl",2)); //Democratic Republic of Timor-Leste + table.add(new MccEntry(515,"ph",2)); //Philippines (Republic of the) + table.add(new MccEntry(520,"th",2)); //Thailand + table.add(new MccEntry(525,"sg",2,"en",11)); //Singapore (Republic of) + table.add(new MccEntry(528,"bn",2)); //Brunei Darussalam + table.add(new MccEntry(530,"nz",2, "en")); //New Zealand + table.add(new MccEntry(534,"mp",2)); //Northern Mariana Islands (Commonwealth of the) + table.add(new MccEntry(535,"gu",2)); //Guam + table.add(new MccEntry(536,"nr",2)); //Nauru (Republic of) + table.add(new MccEntry(537,"pg",2)); //Papua New Guinea + table.add(new MccEntry(539,"to",2)); //Tonga (Kingdom of) + table.add(new MccEntry(540,"sb",2)); //Solomon Islands + table.add(new MccEntry(541,"vu",2)); //Vanuatu (Republic of) + table.add(new MccEntry(542,"fj",2)); //Fiji (Republic of) + table.add(new MccEntry(543,"wf",2)); //Wallis and Futuna (Territoire franais d'outre-mer) + table.add(new MccEntry(544,"as",2)); //American Samoa + table.add(new MccEntry(545,"ki",2)); //Kiribati (Republic of) + table.add(new MccEntry(546,"nc",2)); //New Caledonia (Territoire franais d'outre-mer) + table.add(new MccEntry(547,"pf",2)); //French Polynesia (Territoire franais d'outre-mer) + table.add(new MccEntry(548,"ck",2)); //Cook Islands + table.add(new MccEntry(549,"ws",2)); //Samoa (Independent State of) + table.add(new MccEntry(550,"fm",2)); //Micronesia (Federated States of) + table.add(new MccEntry(551,"mh",2)); //Marshall Islands (Republic of the) + table.add(new MccEntry(552,"pw",2)); //Palau (Republic of) + table.add(new MccEntry(602,"eg",2)); //Egypt (Arab Republic of) + table.add(new MccEntry(603,"dz",2)); //Algeria (People's Democratic Republic of) + table.add(new MccEntry(604,"ma",2)); //Morocco (Kingdom of) + table.add(new MccEntry(605,"tn",2)); //Tunisia + table.add(new MccEntry(606,"ly",2)); //Libya (Socialist People's Libyan Arab Jamahiriya) + table.add(new MccEntry(607,"gm",2)); //Gambia (Republic of the) + table.add(new MccEntry(608,"sn",2)); //Senegal (Republic of) + table.add(new MccEntry(609,"mr",2)); //Mauritania (Islamic Republic of) + table.add(new MccEntry(610,"ml",2)); //Mali (Republic of) + table.add(new MccEntry(611,"gn",2)); //Guinea (Republic of) + table.add(new MccEntry(612,"ci",2)); //Cte d'Ivoire (Republic of) + table.add(new MccEntry(613,"bf",2)); //Burkina Faso + table.add(new MccEntry(614,"ne",2)); //Niger (Republic of the) + table.add(new MccEntry(615,"tg",2)); //Togolese Republic + table.add(new MccEntry(616,"bj",2)); //Benin (Republic of) + table.add(new MccEntry(617,"mu",2)); //Mauritius (Republic of) + table.add(new MccEntry(618,"lr",2)); //Liberia (Republic of) + table.add(new MccEntry(619,"sl",2)); //Sierra Leone + table.add(new MccEntry(620,"gh",2)); //Ghana + table.add(new MccEntry(621,"ng",2)); //Nigeria (Federal Republic of) + table.add(new MccEntry(622,"td",2)); //Chad (Republic of) + table.add(new MccEntry(623,"cf",2)); //Central African Republic + table.add(new MccEntry(624,"cm",2)); //Cameroon (Republic of) + table.add(new MccEntry(625,"cv",2)); //Cape Verde (Republic of) + table.add(new MccEntry(626,"st",2)); //Sao Tome and Principe (Democratic Republic of) + table.add(new MccEntry(627,"gq",2)); //Equatorial Guinea (Republic of) + table.add(new MccEntry(628,"ga",2)); //Gabonese Republic + table.add(new MccEntry(629,"cg",2)); //Congo (Republic of the) + table.add(new MccEntry(630,"cg",2)); //Democratic Republic of the Congo + table.add(new MccEntry(631,"ao",2)); //Angola (Republic of) + table.add(new MccEntry(632,"gw",2)); //Guinea-Bissau (Republic of) + table.add(new MccEntry(633,"sc",2)); //Seychelles (Republic of) + table.add(new MccEntry(634,"sd",2)); //Sudan (Republic of the) + table.add(new MccEntry(635,"rw",2)); //Rwanda (Republic of) + table.add(new MccEntry(636,"et",2)); //Ethiopia (Federal Democratic Republic of) + table.add(new MccEntry(637,"so",2)); //Somali Democratic Republic + table.add(new MccEntry(638,"dj",2)); //Djibouti (Republic of) + table.add(new MccEntry(639,"ke",2)); //Kenya (Republic of) + table.add(new MccEntry(640,"tz",2)); //Tanzania (United Republic of) + table.add(new MccEntry(641,"ug",2)); //Uganda (Republic of) + table.add(new MccEntry(642,"bi",2)); //Burundi (Republic of) + table.add(new MccEntry(643,"mz",2)); //Mozambique (Republic of) + table.add(new MccEntry(645,"zm",2)); //Zambia (Republic of) + table.add(new MccEntry(646,"mg",2)); //Madagascar (Republic of) + table.add(new MccEntry(647,"re",2)); //Reunion (French Department of) + table.add(new MccEntry(648,"zw",2)); //Zimbabwe (Republic of) + table.add(new MccEntry(649,"na",2)); //Namibia (Republic of) + table.add(new MccEntry(650,"mw",2)); //Malawi + table.add(new MccEntry(651,"ls",2)); //Lesotho (Kingdom of) + table.add(new MccEntry(652,"bw",2)); //Botswana (Republic of) + table.add(new MccEntry(653,"sz",2)); //Swaziland (Kingdom of) + table.add(new MccEntry(654,"km",2)); //Comoros (Union of the) + table.add(new MccEntry(655,"za",2,"en")); //South Africa (Republic of) + table.add(new MccEntry(657,"er",2)); //Eritrea + table.add(new MccEntry(702,"bz",2)); //Belize + table.add(new MccEntry(704,"gt",2)); //Guatemala (Republic of) + table.add(new MccEntry(706,"sv",2)); //El Salvador (Republic of) + table.add(new MccEntry(708,"hn",3)); //Honduras (Republic of) + table.add(new MccEntry(710,"ni",2)); //Nicaragua + table.add(new MccEntry(712,"cr",2)); //Costa Rica + table.add(new MccEntry(714,"pa",2)); //Panama (Republic of) + table.add(new MccEntry(716,"pe",2)); //Peru + table.add(new MccEntry(722,"ar",3)); //Argentine Republic + table.add(new MccEntry(724,"br",2)); //Brazil (Federative Republic of) + table.add(new MccEntry(730,"cl",2)); //Chile + table.add(new MccEntry(732,"co",3)); //Colombia (Republic of) + table.add(new MccEntry(734,"ve",2)); //Venezuela (Bolivarian Republic of) + table.add(new MccEntry(736,"bo",2)); //Bolivia (Republic of) + table.add(new MccEntry(738,"gy",2)); //Guyana + table.add(new MccEntry(740,"ec",2)); //Ecuador + table.add(new MccEntry(742,"gf",2)); //French Guiana (French Department of) + table.add(new MccEntry(744,"py",2)); //Paraguay (Republic of) + table.add(new MccEntry(746,"sr",2)); //Suriname (Republic of) + table.add(new MccEntry(748,"uy",2)); //Uruguay (Eastern Republic of) + table.add(new MccEntry(750,"fk",2)); //Falkland Islands (Malvinas) + //table.add(new MccEntry(901,"",2)); //"International Mobile, shared code" + + Collections.sort(table); + } } diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java index 3dd9a01..ec6c023 100644 --- a/telephony/java/com/android/internal/telephony/Phone.java +++ b/telephony/java/com/android/internal/telephony/Phone.java @@ -17,10 +17,10 @@ package com.android.internal.telephony; import android.content.Context; -import android.content.SharedPreferences; +import android.net.LinkCapabilities; +import android.net.LinkProperties; import android.os.Handler; import android.os.Message; -import android.preference.PreferenceManager; import android.telephony.CellLocation; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; @@ -28,7 +28,6 @@ import android.telephony.SignalStrength; import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.gsm.NetworkInfo; -import com.android.internal.telephony.gsm.GsmDataConnection; import com.android.internal.telephony.test.SimulatedRadioControl; import java.util.List; @@ -99,11 +98,12 @@ public interface Phone { static final String PHONE_NAME_KEY = "phoneName"; static final String FAILURE_REASON_KEY = "reason"; static final String STATE_CHANGE_REASON_KEY = "reason"; - static final String DATA_APN_TYPES_KEY = "apnType"; + static final String DATA_APN_TYPE_KEY = "apnType"; static final String DATA_APN_KEY = "apn"; + static final String DATA_LINK_PROPERTIES_KEY = "linkProperties"; + static final String DATA_LINK_CAPABILITIES_KEY = "linkCapabilities"; static final String DATA_IFACE_NAME_KEY = "iface"; - static final String DATA_GATEWAY_KEY = "gateway"; static final String NETWORK_UNAVAILABLE_KEY = "networkUnvailable"; static final String PHONE_IN_ECM_STATE = "phoneinECMState"; @@ -243,11 +243,19 @@ public interface Phone { CellLocation getCellLocation(); /** + * Get the current for the default apn DataState. No change notification + * exists at this interface -- use + * {@link android.telephony.PhoneStateListener} instead. + */ + DataState getDataConnectionState(); + + /** * Get the current DataState. No change notification exists at this * interface -- use * {@link android.telephony.PhoneStateListener} instead. + * @param apnType specify for which apn to get connection state info. */ - DataState getDataConnectionState(); + DataState getDataConnectionState(String apnType); /** * Get the current DataActivityState. No change notification exists at this @@ -313,6 +321,16 @@ public interface Phone { String getActiveApn(); /** + * Return the LinkProperties for the named apn or null if not available + */ + LinkProperties getLinkProperties(String apnType); + + /** + * Return the LinkCapabilities + */ + LinkCapabilities getLinkCapabilities(String apnType); + + /** * Get current signal strength. No change notification available on this * interface. Use <code>PhoneStateNotifier</code> or an equivalent. * An ASU is 0-31 or -1 if unknown (for GSM, dBm = -113 - 2 * asu). @@ -1368,29 +1386,6 @@ public interface Phone { boolean isDataConnectivityPossible(); /** - * Returns the name of the network interface used by the specified APN type. - */ - String getInterfaceName(String apnType); - - /** - * Returns the IP address of the network interface used by the specified - * APN type. - */ - String getIpAddress(String apnType); - - /** - * Returns the gateway for the network interface used by the specified APN - * type. - */ - String getGateway(String apnType); - - /** - * Returns the DNS servers for the network interface used by the specified - * APN type. - */ - public String[] getDnsServers(String apnType); - - /** * Retrieves the unique device ID, e.g., IMEI for GSM phones and MEID for CDMA phones. */ String getDeviceId(); @@ -1535,6 +1530,11 @@ public interface Phone { boolean isOtaSpNumber(String dialStr); /** + * Returns true if OTA Service Provisioning needs to be performed. + */ + boolean needsOtaServiceProvisioning(); + + /** * Register for notifications when CDMA call waiting comes * * @param h Handler that receives the notification message. diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java index 1da9d4d..5412768 100644 --- a/telephony/java/com/android/internal/telephony/PhoneBase.java +++ b/telephony/java/com/android/internal/telephony/PhoneBase.java @@ -21,6 +21,8 @@ import android.app.IActivityManager; import android.content.Context; import android.content.res.Configuration; import android.content.SharedPreferences; +import android.net.LinkCapabilities; +import android.net.LinkProperties; import android.net.wifi.WifiManager; import android.os.AsyncResult; import android.os.Handler; @@ -35,10 +37,8 @@ import android.text.TextUtils; import android.util.Log; import com.android.internal.R; -import com.android.internal.telephony.gsm.GsmDataConnection; import com.android.internal.telephony.test.SimulatedRadioControl; -import java.util.List; import java.util.Locale; @@ -737,8 +737,13 @@ public abstract class PhoneBase extends Handler implements Phone { mNotifier.notifyMessageWaitingChanged(this); } - public void notifyDataConnection(String reason) { - mNotifier.notifyDataConnection(this, reason); + public void notifyDataConnection(String reason, String apnType, + Phone.DataState state) { + mNotifier.notifyDataConnection(this, reason, apnType, state); + } + + public void notifyDataConnection(String reason, String apnType) { + mNotifier.notifyDataConnection(this, reason, apnType); } public abstract String getPhoneName(); @@ -824,9 +829,19 @@ public abstract class PhoneBase extends Handler implements Phone { logUnexpectedCdmaMethodCall("unregisterForSubscriptionInfoReady"); } + /** + * Returns true if OTA Service Provisioning needs to be performed. + * If not overridden return false. + */ + public boolean needsOtaServiceProvisioning() { + return false; + } + + /** + * Return true if number is an OTASP number. + * If not overridden return false. + */ public boolean isOtaSpNumber(String dialStr) { - // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. - logUnexpectedCdmaMethodCall("isOtaSpNumber"); return false; } @@ -916,28 +931,20 @@ public abstract class PhoneBase extends Handler implements Phone { logUnexpectedCdmaMethodCall("unsetOnEcbModeExitResponse"); } - public String getInterfaceName(String apnType) { - return mDataConnection.getInterfaceName(apnType); - } - - public String getIpAddress(String apnType) { - return mDataConnection.getIpAddress(apnType); - } - public boolean isDataConnectivityEnabled() { return mDataConnection.getDataEnabled(); } - public String getGateway(String apnType) { - return mDataConnection.getGateway(apnType); + public String[] getActiveApnTypes() { + return mDataConnection.getActiveApnTypes(); } - public String[] getDnsServers(String apnType) { - return mDataConnection.getDnsServers(apnType); + public LinkProperties getLinkProperties(String apnType) { + return mDataConnection.getLinkProperties(apnType); } - public String[] getActiveApnTypes() { - return mDataConnection.getActiveApnTypes(); + public LinkCapabilities getLinkCapabilities(String apnType) { + return mDataConnection.getLinkCapabilities(apnType); } public String getActiveApn() { @@ -952,6 +959,10 @@ public abstract class PhoneBase extends Handler implements Phone { return mDataConnection.disableApnType(type); } + public boolean isDataConnectivityPossible() { + return ((mDataConnection != null) && (mDataConnection.isDataPossible())); + } + /** * simulateDataConnection * @@ -980,7 +991,7 @@ public abstract class PhoneBase extends Handler implements Phone { } mDataConnection.setState(dcState); - notifyDataConnection(null); + notifyDataConnection(null, Phone.APN_TYPE_DEFAULT); } /** @@ -1034,6 +1045,10 @@ public abstract class PhoneBase extends Handler implements Phone { "called, CDMAPhone inactive."); } + public DataState getDataConnectionState() { + return getDataConnectionState(APN_TYPE_DEFAULT); + } + /** * Common error logger method for unexpected calls to GSM/WCDMA-only methods. */ diff --git a/telephony/java/com/android/internal/telephony/PhoneNotifier.java b/telephony/java/com/android/internal/telephony/PhoneNotifier.java index e96eeae..691271f 100644 --- a/telephony/java/com/android/internal/telephony/PhoneNotifier.java +++ b/telephony/java/com/android/internal/telephony/PhoneNotifier.java @@ -33,9 +33,12 @@ public interface PhoneNotifier { public void notifyCallForwardingChanged(Phone sender); - public void notifyDataConnection(Phone sender, String reason); + public void notifyDataConnection(Phone sender, String reason, String apnType); - public void notifyDataConnectionFailed(Phone sender, String reason); + public void notifyDataConnection(Phone sender, String reason, String apnType, + Phone.DataState state); + + public void notifyDataConnectionFailed(Phone sender, String reason, String apnType); public void notifyDataActivity(Phone sender); diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java index 5e7dcb0..9e0c087 100644 --- a/telephony/java/com/android/internal/telephony/PhoneProxy.java +++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java @@ -20,13 +20,12 @@ package com.android.internal.telephony; import android.app.ActivityManagerNative; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; +import android.net.LinkCapabilities; +import android.net.LinkProperties; import android.os.Handler; import android.os.Message; import android.os.SystemProperties; -import android.preference.PreferenceManager; import android.telephony.CellLocation; -import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.util.Log; @@ -34,7 +33,6 @@ import android.util.Log; import com.android.internal.telephony.cdma.CDMAPhone; import com.android.internal.telephony.gsm.GSMPhone; import com.android.internal.telephony.gsm.NetworkInfo; -import com.android.internal.telephony.gsm.GsmDataConnection; import com.android.internal.telephony.test.SimulatedRadioControl; import java.util.List; @@ -172,7 +170,11 @@ public class PhoneProxy extends Handler implements Phone { } public DataState getDataConnectionState() { - return mActivePhone.getDataConnectionState(); + return mActivePhone.getDataConnectionState(Phone.APN_TYPE_DEFAULT); + } + + public DataState getDataConnectionState(String apnType) { + return mActivePhone.getDataConnectionState(apnType); } public DataActivityState getDataActivityState() { @@ -207,6 +209,14 @@ public class PhoneProxy extends Handler implements Phone { return mActivePhone.getActiveApnTypes(); } + public LinkProperties getLinkProperties(String apnType) { + return mActivePhone.getLinkProperties(apnType); + } + + public LinkCapabilities getLinkCapabilities(String apnType) { + return mActivePhone.getLinkCapabilities(apnType); + } + public String getActiveApn() { return mActivePhone.getActiveApn(); } @@ -660,22 +670,6 @@ public class PhoneProxy extends Handler implements Phone { return mActivePhone.isDataConnectivityPossible(); } - public String getInterfaceName(String apnType) { - return mActivePhone.getInterfaceName(apnType); - } - - public String getIpAddress(String apnType) { - return mActivePhone.getIpAddress(apnType); - } - - public String getGateway(String apnType) { - return mActivePhone.getGateway(apnType); - } - - public String[] getDnsServers(String apnType) { - return mActivePhone.getDnsServers(apnType); - } - public String getDeviceId() { return mActivePhone.getDeviceId(); } @@ -764,6 +758,10 @@ public class PhoneProxy extends Handler implements Phone { mActivePhone.exitEmergencyCallbackMode(); } + public boolean needsOtaServiceProvisioning(){ + return mActivePhone.needsOtaServiceProvisioning(); + } + public boolean isOtaSpNumber(String dialStr){ return mActivePhone.isOtaSpNumber(dialStr); } diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java index 569ac5c..8c2280b 100644 --- a/telephony/java/com/android/internal/telephony/RIL.java +++ b/telephony/java/com/android/internal/telephony/RIL.java @@ -285,9 +285,8 @@ public final class RIL extends BaseCommands implements CommandsInterface { } - //***** Handler implemementation - - public void + //***** Handler implementation + @Override public void handleMessage(Message msg) { RILRequest rr = (RILRequest)(msg.obj); RILRequest req = null; @@ -780,7 +779,7 @@ public final class RIL extends BaseCommands implements CommandsInterface { send(rr); } - public void + @Deprecated public void getPDPContextList(Message result) { getDataCallList(result); } @@ -1299,10 +1298,18 @@ public final class RIL extends BaseCommands implements CommandsInterface { public void setupDataCall(String radioTechnology, String profile, String apn, String user, String password, String authType, Message result) { + setupDataCallWithProtocol(radioTechnology, profile, apn, user, password, + authType, "IP", result); + } + + public void + setupDataCallWithProtocol(String radioTechnology, String profile, + String apn, String user, String password, String authType, + String protocolType, Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result); - rr.mp.writeInt(6); + rr.mp.writeInt(7); rr.mp.writeString(radioTechnology); rr.mp.writeString(profile); @@ -1310,11 +1317,12 @@ public final class RIL extends BaseCommands implements CommandsInterface { rr.mp.writeString(user); rr.mp.writeString(password); rr.mp.writeString(authType); + rr.mp.writeString(protocolType); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + radioTechnology + " " + profile + " " + apn + " " + user + " " - + password + " " + authType); + + password + " " + authType + " " + protocolType); send(rr); } @@ -2902,7 +2910,11 @@ public final class RIL extends BaseCommands implements CommandsInterface { dataCall.active = p.readInt(); dataCall.type = p.readString(); dataCall.apn = p.readString(); - dataCall.address = p.readString(); + String address = p.readString(); + if (address != null) { + address = address.split(" ")[0]; + } + dataCall.address = address; response.add(dataCall); } diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java index 917e1d8..3a7ce47 100644 --- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java @@ -255,6 +255,7 @@ public abstract class SMSDispatcher extends Handler { mCm.unregisterForOn(this); } + @Override protected void finalize() { Log.d(TAG, "SMSDispatcher finalized"); } @@ -927,14 +928,14 @@ public abstract class SMSDispatcher extends Handler { */ static protected class SmsTracker { // fields need to be public for derived SmsDispatchers - public HashMap mData; + public HashMap<String, Object> mData; public int mRetryCount; public int mMessageRef; public PendingIntent mSentIntent; public PendingIntent mDeliveryIntent; - SmsTracker(HashMap data, PendingIntent sentIntent, + SmsTracker(HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent) { mData = data; mSentIntent = sentIntent; @@ -943,7 +944,7 @@ public abstract class SMSDispatcher extends Handler { } } - protected SmsTracker SmsTrackerFactory(HashMap data, PendingIntent sentIntent, + protected SmsTracker SmsTrackerFactory(HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent) { return new SmsTracker(data, sentIntent, deliveryIntent); } diff --git a/telephony/java/com/android/internal/telephony/SipPhoneNotifier.java b/telephony/java/com/android/internal/telephony/SipPhoneNotifier.java index 4092c69..4c4e718 100644 --- a/telephony/java/com/android/internal/telephony/SipPhoneNotifier.java +++ b/telephony/java/com/android/internal/telephony/SipPhoneNotifier.java @@ -16,6 +16,8 @@ package com.android.internal.telephony; +import android.net.LinkCapabilities; +import android.net.LinkProperties; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; @@ -94,26 +96,45 @@ public class SipPhoneNotifier implements PhoneNotifier { } } - public void notifyDataConnection(Phone sender, String reason) { + public void notifyDataConnection(Phone sender, String reason, String apnType) { + doNotifyDataConnection(sender, reason, apnType, sender.getDataConnectionState(apnType)); + } + + public void notifyDataConnection(Phone sender, String reason, String apnType, + Phone.DataState state) { + doNotifyDataConnection(sender, reason, apnType, state); + } + + private void doNotifyDataConnection(Phone sender, String reason, String apnType, + Phone.DataState state) { + // TODO + // use apnType as the key to which connection we're talking about. + // pass apnType back up to fetch particular for this one. TelephonyManager telephony = TelephonyManager.getDefault(); + LinkProperties linkProperties = null; + LinkCapabilities linkCapabilities = null; + if (state == Phone.DataState.CONNECTED) { + linkProperties = sender.getLinkProperties(apnType); + linkCapabilities = sender.getLinkCapabilities(apnType); + } try { mRegistry.notifyDataConnection( - convertDataState(sender.getDataConnectionState()), + convertDataState(state), sender.isDataConnectivityPossible(), reason, sender.getActiveApn(), - sender.getActiveApnTypes(), - sender.getInterfaceName(null), + apnType, + linkProperties, + linkCapabilities, ((telephony!=null) ? telephony.getNetworkType() : - TelephonyManager.NETWORK_TYPE_UNKNOWN), - sender.getGateway(null)); + TelephonyManager.NETWORK_TYPE_UNKNOWN)); } catch (RemoteException ex) { // system process is dead } } - public void notifyDataConnectionFailed(Phone sender, String reason) { + public void notifyDataConnectionFailed(Phone sender, String reason, String apnType) { try { - mRegistry.notifyDataConnectionFailed(reason); + mRegistry.notifyDataConnectionFailed(reason, apnType); } catch (RemoteException ex) { // system process is dead } diff --git a/telephony/java/com/android/internal/telephony/SmsHeader.java b/telephony/java/com/android/internal/telephony/SmsHeader.java index 7872eec..7a65162 100644 --- a/telephony/java/com/android/internal/telephony/SmsHeader.java +++ b/telephony/java/com/android/internal/telephony/SmsHeader.java @@ -30,7 +30,7 @@ import java.util.ArrayList; */ public class SmsHeader { - // TODO(cleanup): this datastructure is generally referred to as + // TODO(cleanup): this data structure is generally referred to as // the 'user data header' or UDH, and so the class name should // change to reflect this... diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java index af6c5f8..cbd8606 100644 --- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java +++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java @@ -16,7 +16,6 @@ package com.android.internal.telephony; -import android.util.Log; import com.android.internal.telephony.SmsHeader; import java.util.Arrays; @@ -366,13 +365,13 @@ public abstract class SmsMessageBase { /** * Try to parse this message as an email gateway message * There are two ways specified in TS 23.040 Section 3.8 : - * - SMS message "may have its TP-PID set for internet electronic mail - MT + * - SMS message "may have its TP-PID set for Internet electronic mail - MT * SMS format: [<from-address><space>]<message> - "Depending on the * nature of the gateway, the destination/origination address is either * derived from the content of the SMS TP-OA or TP-DA field, or the * TP-OA/TP-DA field contains a generic gateway address and the to/from * address is added at the beginning as shown above." (which is supported here) - * - Multiple addreses separated by commas, no spaces, Subject field delimited + * - Multiple addresses separated by commas, no spaces, Subject field delimited * by '()' or '##' and '#' Section 9.2.3.24.11 (which are NOT supported here) */ protected void extractEmailAddressFromMessageBody() { diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index a113787..136d5b1 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -45,7 +45,7 @@ public interface TelephonyProperties * CDMA networks. */ static final String PROPERTY_OPERATOR_ALPHA = "gsm.operator.alpha"; - //TODO: most of these proprieties are generic, substitute gsm. with phone. bug 1856959 + //TODO: most of these properties are generic, substitute gsm. with phone. bug 1856959 /** Numeric name (MCC+MNC) of current registered operator.<p> * Availability: when registered to a network. Result may be unreliable on @@ -83,12 +83,12 @@ public interface TelephonyProperties /** The MCC+MNC (mobile country code+mobile network code) of the * provider of the SIM. 5 or 6 decimal digits. - * Availablity: SIM state must be "READY" + * Availability: SIM state must be "READY" */ static String PROPERTY_ICC_OPERATOR_NUMERIC = "gsm.sim.operator.numeric"; /** PROPERTY_ICC_OPERATOR_ALPHA is also known as the SPN, or Service Provider Name. - * Availablity: SIM state must be "READY" + * Availability: SIM state must be "READY" */ static String PROPERTY_ICC_OPERATOR_ALPHA = "gsm.sim.operator.alpha"; @@ -127,7 +127,7 @@ public interface TelephonyProperties "ro.telephony.call_ring.multiple"; /** - * The number of milli-seconds between CALL_RING notifications. + * The number of milliseconds between CALL_RING notifications. */ static final String PROPERTY_CALL_RING_DELAY = "ro.telephony.call_ring.delay"; diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java index f31bf24..6e53ec5 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java @@ -515,14 +515,6 @@ public class CDMAPhone extends PhoneBase { return false; } - public boolean isDataConnectivityPossible() { - boolean noData = mDataConnection.getDataEnabled() && - getDataConnectionState() == DataState.DISCONNECTED; - return !noData && getIccCard().getState() == IccCard.State.READY && - getServiceState().getState() == ServiceState.STATE_IN_SERVICE && - (mDataConnection.getDataOnRoamingEnabled() || !getServiceState().getRoaming()); - } - /** * Removes the given MMI from the pending list and notifies registrants that * it is complete. @@ -613,7 +605,7 @@ public class CDMAPhone extends PhoneBase { } } - public DataState getDataConnectionState() { + public DataState getDataConnectionState(String apnType) { DataState ret = DataState.DISCONNECTED; if (mSST == null) { @@ -625,6 +617,8 @@ public class CDMAPhone extends PhoneBase { // If we're out of service, open TCP sockets may still work // but no data will flow ret = DataState.DISCONNECTED; + } else if (mDataConnection.isApnTypeEnabled(apnType) == false) { + ret = DataState.DISCONNECTED; } else { switch (mDataConnection.getState()) { case FAILED: @@ -878,26 +872,6 @@ public class CDMAPhone extends PhoneBase { mRuimRecords.setVoiceMessageWaiting(1, mwi); } - /** - * Returns true if CDMA OTA Service Provisioning needs to be performed. - */ - /* package */ boolean - needsOtaServiceProvisioning() { - String cdmaMin = getCdmaMin(); - boolean needsProvisioning; - if (cdmaMin == null || (cdmaMin.length() < 6)) { - if (DBG) Log.d(LOG_TAG, "needsOtaServiceProvisioning: illegal cdmaMin='" - + cdmaMin + "' assume provisioning needed."); - needsProvisioning = true; - } else { - needsProvisioning = (cdmaMin.equals(UNACTIVATED_MIN_VALUE) - || cdmaMin.substring(0,6).equals(UNACTIVATED_MIN2_VALUE)) - || SystemProperties.getBoolean("test_cdma_setup", false); - } - if (DBG) Log.d(LOG_TAG, "needsOtaServiceProvisioning: ret=" + needsProvisioning); - return needsProvisioning; - } - @Override public void exitEmergencyCallbackMode() { if (mWakeLock.isHeld()) { @@ -1191,6 +1165,26 @@ public class CDMAPhone extends PhoneBase { mSMS.setCellBroadcastConfig(configValuesArray, response); } + /** + * Returns true if OTA Service Provisioning needs to be performed. + */ + @Override + public boolean needsOtaServiceProvisioning() { + String cdmaMin = getCdmaMin(); + boolean needsProvisioning; + if (cdmaMin == null || (cdmaMin.length() < 6)) { + if (DBG) Log.d(LOG_TAG, "needsOtaServiceProvisioning: illegal cdmaMin='" + + cdmaMin + "' assume provisioning needed."); + needsProvisioning = true; + } else { + needsProvisioning = (cdmaMin.equals(UNACTIVATED_MIN_VALUE) + || cdmaMin.substring(0,6).equals(UNACTIVATED_MIN2_VALUE)) + || SystemProperties.getBoolean("test_cdma_setup", false); + } + if (DBG) Log.d(LOG_TAG, "needsOtaServiceProvisioning: ret=" + needsProvisioning); + return needsProvisioning; + } + private static final String IS683A_FEATURE_CODE = "*228"; private static final int IS683A_FEATURE_CODE_NUM_DIGITS = 4; private static final int IS683A_SYS_SEL_CODE_NUM_DIGITS = 2; diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java index 9f2a44b..e499e95 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java @@ -23,14 +23,12 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; -import android.net.ConnectivityManager; import android.net.IConnectivityManager; import android.net.NetworkInfo; import android.net.TrafficStats; import android.net.wifi.WifiManager; import android.os.AsyncResult; import android.os.Message; -import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; @@ -50,8 +48,6 @@ import com.android.internal.telephony.DataConnectionTracker; import com.android.internal.telephony.EventLogTags; import com.android.internal.telephony.gsm.ApnSetting; import com.android.internal.telephony.Phone; -import com.android.internal.telephony.RetryManager; -import com.android.internal.telephony.ServiceStateTracker; import java.util.ArrayList; @@ -305,9 +301,40 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { return true; } - private boolean isDataAllowed() { - boolean roaming = phone.getServiceState().getRoaming(); - return getAnyDataEnabled() && (!roaming || getDataOnRoamingEnabled()) && mMasterDataEnabled; + protected boolean isDataAllowed() { + int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState(); + boolean roaming = (phone.getServiceState().getRoaming() && !getDataOnRoamingEnabled()); + boolean desiredPowerState = mCdmaPhone.mSST.getDesiredPowerState(); + + boolean allowed = (psState == ServiceState.STATE_IN_SERVICE && + (phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY || + mCdmaPhone.mRuimRecords.getRecordsLoaded()) && + (mCdmaPhone.mSST.isConcurrentVoiceAndData() || + phone.getState() == Phone.State.IDLE) && + !roaming && + mMasterDataEnabled && + desiredPowerState && + !mPendingRestartRadio && + !mCdmaPhone.needsOtaServiceProvisioning()); + if (!allowed && DBG) { + String reason = ""; + if (psState != ServiceState.STATE_IN_SERVICE) reason += " - psState= " + psState; + if (phone.mCM.getRadioState() != CommandsInterface.RadioState.NV_READY && + !mCdmaPhone.mRuimRecords.getRecordsLoaded()) { + reason += " - radioState= " + phone.mCM.getRadioState() + " - RUIM not loaded"; + } + if (phone.getState() != Phone.State.IDLE && + mCdmaPhone.mSST.isConcurrentVoiceAndData()) { + reason += " - concurrentVoiceAndData not allowed and state= " + phone.getState(); + } + if (roaming) reason += " - Roaming"; + if (!mMasterDataEnabled) reason += " - mMasterDataEnabled= false"; + if (!desiredPowerState) reason += " - desiredPowerState= false"; + if (mPendingRestartRadio) reason += " - mPendingRestartRadio= true"; + if (mCdmaPhone.needsOtaServiceProvisioning()) reason += " - needs Provisioning"; + log("Data not allowed due to" + reason); + } + return allowed; } private boolean trySetupData(String reason) { @@ -317,7 +344,8 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { // Assume data is connected on the simulator // FIXME this can be improved setState(State.CONNECTED); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); + notifyOffApnsOfAvailability(reason, true); Log.i(LOG_TAG, "(fix?) We're on the simulator; assuming data is connected"); return true; @@ -327,36 +355,13 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { boolean roaming = phone.getServiceState().getRoaming(); boolean desiredPowerState = mCdmaPhone.mSST.getDesiredPowerState(); - if ((state == State.IDLE || state == State.SCANNING) - && (psState == ServiceState.STATE_IN_SERVICE) - && ((phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) || - mCdmaPhone.mRuimRecords.getRecordsLoaded()) - && (mCdmaPhone.mSST.isConcurrentVoiceAndData() || - phone.getState() == Phone.State.IDLE ) - && isDataAllowed() - && desiredPowerState - && !mPendingRestartRadio - && !mCdmaPhone.needsOtaServiceProvisioning()) { - - return setupData(reason); - + if ((state == State.IDLE || state == State.SCANNING) && + isDataAllowed() && getAnyDataEnabled()) { + boolean retValue = setupData(reason); + notifyOffApnsOfAvailability(reason, retValue); + return retValue; } else { - if (DBG) { - log("trySetupData: Not ready for data: " + - " dataState=" + state + - " PS state=" + psState + - " radio state=" + phone.mCM.getRadioState() + - " ruim=" + mCdmaPhone.mRuimRecords.getRecordsLoaded() + - " concurrentVoice&Data=" + mCdmaPhone.mSST.isConcurrentVoiceAndData() + - " phoneState=" + phone.getState() + - " dataEnabled=" + getAnyDataEnabled() + - " roaming=" + roaming + - " dataOnRoamingEnable=" + getDataOnRoamingEnabled() + - " desiredPowerState=" + desiredPowerState + - " PendingRestartRadio=" + mPendingRestartRadio + - " MasterDataEnabled=" + mMasterDataEnabled + - " needsOtaServiceProvisioning=" + mCdmaPhone.needsOtaServiceProvisioning()); - } + notifyOffApnsOfAvailability(reason, false); return false; } } @@ -382,6 +387,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { } setState(State.DISCONNECTING); + notifyDataAvailability(reason); boolean notificationDeferred = false; for (DataConnection conn : dataConnectionList) { @@ -440,13 +446,13 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { conn.connect(msg, mActiveApn); setState(State.INITING); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); return true; } private void notifyDefaultData(String reason) { setState(State.CONNECTED); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); startNetStatPoll(); mRetryMgr.resetRetryCount(); } @@ -622,12 +628,13 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { private void notifyNoData(FailCause lastFailCauseCode) { setState(State.FAILED); + notifyDataAvailability(null); } private void gotoIdleAndNotifyDataConnection(String reason) { if (DBG) log("gotoIdleAndNotifyDataConnection: reason=" + reason); setState(State.IDLE); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); mActiveApn = null; } @@ -687,11 +694,13 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { // Assume data is connected on the simulator // FIXME this can be improved setState(State.CONNECTED); - phone.notifyDataConnection(null); + notifyDataConnection(null); Log.i(LOG_TAG, "We're on the simulator; assuming data is connected"); } + notifyDataAvailability(null); + if (state != State.IDLE) { cleanUpConnection(true, null); } @@ -723,6 +732,10 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { } if (ar.exception == null) { + // TODO: We should clear LinkProperties/Capabilities when torn down or disconnected + mLinkProperties = getLinkProperties(mActiveDataConnection); + mLinkCapabilities = getLinkCapabilities(mActiveDataConnection); + // everything is setup notifyDefaultData(reason); } else { @@ -762,7 +775,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { onRestartRadio(); } - phone.notifyDataConnection(reason); + notifyDataConnection(reason); mActiveApn = null; if (retryAfterDisconnected(reason)) { trySetupData(reason); @@ -789,7 +802,8 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { protected void onVoiceCallStarted() { if (state == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndData()) { stopNetStatPoll(); - phone.notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED); + notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED); + notifyDataAvailability(Phone.REASON_VOICE_CALL_STARTED); } } @@ -800,11 +814,12 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { if (state == State.CONNECTED) { if (!mCdmaPhone.mSST.isConcurrentVoiceAndData()) { startNetStatPoll(); - phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED); + notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED); } else { // clean slate after call end. resetPollStats(); } + notifyDataAvailability(Phone.REASON_VOICE_CALL_ENDED); } else { mRetryMgr.resetRetryCount(); // in case data setup was attempted when we were on a voice call @@ -838,7 +853,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { private void onCdmaDataDetached() { if (state == State.CONNECTED) { startNetStatPoll(); - phone.notifyDataConnection(Phone.REASON_CDMA_DATA_DETACHED); + notifyDataConnection(Phone.REASON_CDMA_DATA_DETACHED); } else { if (state == State.FAILED) { cleanUpConnection(false, Phone.REASON_CDMA_DATA_DETACHED); @@ -949,34 +964,6 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { } } - protected String getInterfaceName(String apnType) { - if (mActiveDataConnection != null) { - return mActiveDataConnection.getInterface(); - } - return null; - } - - protected String getIpAddress(String apnType) { - if (mActiveDataConnection != null) { - return mActiveDataConnection.getIpAddress(); - } - return null; - } - - protected String getGateway(String apnType) { - if (mActiveDataConnection != null) { - return mActiveDataConnection.getGatewayAddress(); - } - return null; - } - - protected String[] getDnsServers(String apnType) { - if (mActiveDataConnection != null) { - return mActiveDataConnection.getDnsServers(); - } - return null; - } - public ArrayList<DataConnection> getAllDataConnections() { return dataConnectionList; } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java index dceff2a..37a33bc 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java @@ -70,6 +70,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher { * @param ar AsyncResult passed into the message handler. ar.result should * be a String representing the status report PDU, as ASCII hex. */ + @Override protected void handleStatusReport(AsyncResult ar) { Log.d(TAG, "handleStatusReport is a special GSM function, should never be called in CDMA!"); } @@ -92,6 +93,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected int dispatchMessage(SmsMessageBase smsb) { // If sms is null, means there was a parsing error. @@ -335,6 +337,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendData(String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( @@ -343,6 +346,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent) { SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( @@ -351,6 +355,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendMultipartText(String destAddr, String scAddr, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { @@ -359,7 +364,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher { * TODO(cleanup): There is no real code difference between * this and the GSM version, and hence it should be moved to * the base class or consolidated somehow, provided calling - * the proper submitpdu stuff can be arranged. + * the proper submit pdu stuff can be arranged. */ int refNumber = getNextConcatenatedRef() & 0x00FF; @@ -432,8 +437,9 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendSms(SmsTracker tracker) { - HashMap map = tracker.mData; + HashMap<String, Object> map = tracker.mData; // byte smsc[] = (byte[]) map.get("smsc"); // unused for CDMA byte pdu[] = (byte[]) map.get("pdu"); @@ -444,11 +450,13 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendMultipartSms (SmsTracker tracker) { Log.d(TAG, "TODO: CdmaSMSDispatcher.sendMultipartSms not implemented"); } /** {@inheritDoc} */ + @Override protected void acknowledgeLastIncomingSms(boolean success, int result, Message response){ // FIXME unit test leaves cm == null. this should change @@ -469,16 +477,19 @@ final class CdmaSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void activateCellBroadcastSms(int activate, Message response) { mCm.setCdmaBroadcastActivation((activate == 0), response); } /** {@inheritDoc} */ + @Override protected void getCellBroadcastSmsConfig(Message response) { mCm.getCdmaBroadcastConfig(response); } /** {@inheritDoc} */ + @Override protected void setCellBroadcastConfig(int[] configValuesArray, Message response) { mCm.setCdmaBroadcastConfig(configValuesArray, response); } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index 2cad6cc..b71cf13 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -16,6 +16,16 @@ package com.android.internal.telephony.cdma; +import com.android.internal.telephony.CommandException; +import com.android.internal.telephony.CommandsInterface; +import com.android.internal.telephony.DataConnectionTracker; +import com.android.internal.telephony.EventLogTags; +import com.android.internal.telephony.IccCard; +import com.android.internal.telephony.MccTable; +import com.android.internal.telephony.ServiceStateTracker; +import com.android.internal.telephony.TelephonyIntents; +import com.android.internal.telephony.TelephonyProperties; + import android.app.AlarmManager; import android.content.ContentResolver; import android.content.Context; @@ -38,19 +48,8 @@ import android.telephony.cdma.CdmaCellLocation; import android.text.TextUtils; import android.util.EventLog; import android.util.Log; -import android.util.Config; import android.util.TimeUtils; -import com.android.internal.telephony.CommandException; -import com.android.internal.telephony.CommandsInterface; -import com.android.internal.telephony.DataConnectionTracker; -import com.android.internal.telephony.EventLogTags; -import com.android.internal.telephony.IccCard; -import com.android.internal.telephony.MccTable; -import com.android.internal.telephony.ServiceStateTracker; -import com.android.internal.telephony.TelephonyIntents; -import com.android.internal.telephony.TelephonyProperties; - import java.util.Arrays; import java.util.Calendar; import java.util.Date; @@ -987,7 +986,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { mNeedFixZone = false; if (zone != null) { - if (getAutoTime()) { + if (getAutoTimeZone()) { setAndBroadcastNetworkSetTimeZone(zone.getID()); } saveNitzTimeZone(zone.getID()); @@ -1119,7 +1118,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { } if (hasCdmaDataConnectionChanged || hasNetworkTypeChanged) { - phone.notifyDataConnection(null); + phone.notifyDataConnection(null, null); } if (hasRoamingOn) { @@ -1439,7 +1438,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { } if (zone != null) { - if (getAutoTime()) { + if (getAutoTimeZone()) { setAndBroadcastNetworkSetTimeZone(zone.getID()); } saveNitzTimeZone(zone.getID()); @@ -1529,6 +1528,14 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { } } + private boolean getAutoTimeZone() { + try { + return Settings.System.getInt(cr, Settings.System.AUTO_TIME_ZONE) > 0; + } catch (SettingNotFoundException snfe) { + return true; + } + } + private void saveNitzTimeZone(String zoneId) { mSavedTimeZone = zoneId; } diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java index e97549d..d84b6ab 100644 --- a/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java +++ b/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java @@ -68,8 +68,7 @@ public class RuimSmsInterfaceManager extends IccSmsInterfaceManager { ar = (AsyncResult)msg.obj; synchronized (mLock) { if (ar.exception == null) { - mSms = (List<SmsRawData>) - buildValidRawData((ArrayList<byte[]>) ar.result); + mSms = buildValidRawData((ArrayList<byte[]>) ar.result); } else { if(DBG) log("Cannot load Sms records"); if (mSms != null) diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index 0f3b8ff..e95b2f9 100755 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -18,11 +18,8 @@ package com.android.internal.telephony.cdma; import android.os.Parcel; import android.os.SystemProperties; -import android.text.format.Time; import android.util.Config; import android.util.Log; -import com.android.internal.telephony.EncodeException; -import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.IccUtils; import com.android.internal.telephony.SmsHeader; import com.android.internal.telephony.SmsMessageBase; @@ -33,7 +30,6 @@ import com.android.internal.telephony.cdma.sms.SmsEnvelope; import com.android.internal.telephony.cdma.sms.UserData; import com.android.internal.util.HexDump; -import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -58,7 +54,7 @@ import static android.telephony.SmsMessage.MessageClass; /** * TODO(cleanup): internally returning null in many places makes * debugging very hard (among many other reasons) and should be made - * more meaningful (replaced with execptions for example). Null + * more meaningful (replaced with exceptions for example). Null * returns should only occur at the very outside of the module/class * scope. */ @@ -614,7 +610,7 @@ public class SmsMessage extends SmsMessageBase { * incrementing within the range 1..65535 remembering the state * via a persistent system property. (See C.S0015-B, v2.0, * 4.3.1.5) Since this routine is expected to be accessed via via - * binder-call, and hence should be threadsafe, it has been + * binder-call, and hence should be thread-safe, it has been * synchronized. */ private synchronized static int getNextMessageId() { diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java index ab79fe9..cf06dab 100644 --- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java +++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java @@ -21,7 +21,6 @@ import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES; import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER; import android.util.Log; -import android.util.SparseIntArray; import android.telephony.SmsMessage; @@ -30,10 +29,8 @@ import android.text.format.Time; import com.android.internal.telephony.IccUtils; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.SmsHeader; -import com.android.internal.telephony.cdma.sms.UserData; import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails; -import com.android.internal.util.HexDump; import com.android.internal.util.BitwiseInputStream; import com.android.internal.util.BitwiseOutputStream; @@ -45,13 +42,13 @@ public final class BearerData { private final static String LOG_TAG = "SMS"; /** - * Bearer Data Subparameter Indentifiers + * Bearer Data Subparameter Identifiers * (See 3GPP2 C.S0015-B, v2.0, table 4.5-1) * NOTE: Commented subparameter types are not implemented. */ private final static byte SUBPARAM_MESSAGE_IDENTIFIER = 0x00; private final static byte SUBPARAM_USER_DATA = 0x01; - private final static byte SUBPARAM_USER_REPONSE_CODE = 0x02; + private final static byte SUBPARAM_USER_RESPONSE_CODE = 0x02; private final static byte SUBPARAM_MESSAGE_CENTER_TIME_STAMP = 0x03; private final static byte SUBPARAM_VALIDITY_PERIOD_ABSOLUTE = 0x04; private final static byte SUBPARAM_VALIDITY_PERIOD_RELATIVE = 0x05; @@ -697,7 +694,7 @@ public final class BearerData { /* * TODO(cleanup): CdmaSmsAddress encoding should make use of * CdmaSmsAddress.parse provided that DTMF encoding is unified, - * and the difference in 4bit vs 8bit is resolved. + * and the difference in 4-bit vs. 8-bit is resolved. */ private static void encodeCdmaSmsAddress(CdmaSmsAddress addr) throws CodingException { @@ -805,6 +802,7 @@ public final class BearerData { * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details) * * @param bData an instance of BearerData. + * * @return byte array of raw encoded SMS bearer data. */ public static byte[] encode(BearerData bData) { @@ -915,7 +913,7 @@ public final class BearerData { private static String decodeUtf16(byte[] data, int offset, int numFields) throws CodingException { - // Start reading from the next 16-bit aligned boundry after offset. + // Start reading from the next 16-bit aligned boundary after offset. int padding = offset % 2; numFields -= (offset + padding) / 2; try { @@ -961,7 +959,7 @@ public final class BearerData { private static String decode7bitGsm(byte[] data, int offset, int numFields) throws CodingException { - // Start reading from the next 7-bit aligned boundry after offset. + // Start reading from the next 7-bit aligned boundary after offset. int offsetBits = offset * 8; int offsetSeptets = (offsetBits + 6) / 7; numFields -= offsetSeptets; @@ -1554,7 +1552,7 @@ public final class BearerData { case SUBPARAM_USER_DATA: decodeSuccess = decodeUserData(bData, inStream); break; - case SUBPARAM_USER_REPONSE_CODE: + case SUBPARAM_USER_RESPONSE_CODE: decodeSuccess = decodeUserResponseCode(bData, inStream); break; case SUBPARAM_REPLY_OPTION: diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java index 0dcacc1..a67327a 100644 --- a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java +++ b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java @@ -17,7 +17,7 @@ package com.android.internal.telephony.cdma.sms; -public final class SmsEnvelope{ +public final class SmsEnvelope { /** * Message Types * (See 3GPP2 C.S0015-B 3.4.1) diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java index 43971ff..30a6324 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java +++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java @@ -287,7 +287,7 @@ public class GSMPhone extends PhoneBase { return mPendingMMIs; } - public DataState getDataConnectionState() { + public DataState getDataConnectionState(String apnType) { DataState ret = DataState.DISCONNECTED; if (mSST == null) { @@ -300,6 +300,8 @@ public class GSMPhone extends PhoneBase { // If we're out of service, open TCP sockets may still work // but no data will flow ret = DataState.DISCONNECTED; + } else if (mDataConnection.isApnTypeEnabled(apnType) == false) { + ret = DataState.DISCONNECTED; } else { /* mSST.gprsState == ServiceState.STATE_IN_SERVICE */ switch (mDataConnection.getState()) { case FAILED: @@ -401,8 +403,8 @@ public class GSMPhone extends PhoneBase { } /*package*/ void - notifyDataConnectionFailed(String reason) { - mNotifier.notifyDataConnectionFailed(this, reason); + notifyDataConnectionFailed(String reason, String apnType) { + mNotifier.notifyDataConnectionFailed(this, reason, apnType); } /*package*/ void @@ -1091,27 +1093,6 @@ public class GSMPhone extends PhoneBase { } /** - * The only circumstances under which we report that data connectivity is not - * possible are - * <ul> - * <li>Data roaming is disallowed and we are roaming.</li> - * <li>The current data state is {@code DISCONNECTED} for a reason other than - * having explicitly disabled connectivity. In other words, data is not available - * because the phone is out of coverage or some like reason.</li> - * </ul> - * @return {@code true} if data connectivity is possible, {@code false} otherwise. - */ - public boolean isDataConnectivityPossible() { - // TODO: Currently checks if any GPRS connection is active. Should it only - // check for "default"? - boolean noData = mDataConnection.getDataEnabled() && - getDataConnectionState() == DataState.DISCONNECTED; - return !noData && getIccCard().getState() == SimCard.State.READY && - getServiceState().getState() == ServiceState.STATE_IN_SERVICE && - (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 diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java index 09d46dd..1572f09 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java @@ -180,8 +180,8 @@ public class GsmDataConnection extends DataConnection { @Override protected boolean isDnsOk(String[] domainNameServers) { - if (NULL_IP.equals(dnsServers[0]) && NULL_IP.equals(dnsServers[1]) - && !((GSMPhone) phone).isDnsCheckDisabled()) { + if (NULL_IP.equals(domainNameServers[0]) && NULL_IP.equals(domainNameServers[1]) + && !((GSMPhone) phone).isDnsCheckDisabled()) { // Work around a race condition where QMI does not fill in DNS: // Deactivate PDP and let DataConnectionTracker retry. // Do not apply the race condition workaround for MMS APN @@ -189,6 +189,9 @@ public class GsmDataConnection extends DataConnection { // Otherwise, the default APN will not be restored anymore. if (!apn.types[0].equals(Phone.APN_TYPE_MMS) || !isIpAddress(apn.mmsProxy)) { + log(String.format( + "isDnsOk: return false apn.types[0]=%s APN_TYPE_MMS=%s isIpAddress(%s)=%s", + apn.types[0], Phone.APN_TYPE_MMS, apn.mmsProxy, isIpAddress(apn.mmsProxy))); return false; } } diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index e7d57bc..66da6e8 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -27,15 +27,14 @@ import android.content.IntentFilter; import android.content.SharedPreferences; import android.database.ContentObserver; import android.database.Cursor; -import android.net.ConnectivityManager; import android.net.IConnectivityManager; import android.net.NetworkInfo; +import android.net.ProxyProperties; import android.net.TrafficStats; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.AsyncResult; import android.os.Message; -import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; @@ -58,6 +57,9 @@ import com.android.internal.telephony.EventLogTags; import com.android.internal.telephony.DataConnection.FailCause; import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; import java.util.ArrayList; /** @@ -388,12 +390,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { return pdps; } - private boolean isDataAllowed() { - boolean roaming = phone.getServiceState().getRoaming(); - return getAnyDataEnabled() && (!roaming || getDataOnRoamingEnabled()) && - mMasterDataEnabled; - } - //****** Called from ServiceStateTracker /** * Invoked when ServiceStateTracker observes a transition from GPRS @@ -405,13 +401,13 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { * when GPRS detaches, but we should stop the network polling. */ stopNetStatPoll(); - phone.notifyDataConnection(Phone.REASON_GPRS_DETACHED); + notifyDataConnection(Phone.REASON_GPRS_DETACHED); } private void onGprsAttached() { if (state == State.CONNECTED) { startNetStatPoll(); - phone.notifyDataConnection(Phone.REASON_GPRS_ATTACHED); + notifyDataConnection(Phone.REASON_GPRS_ATTACHED); } else { if (state == State.FAILED) { cleanUpConnection(false, Phone.REASON_GPRS_ATTACHED); @@ -421,6 +417,35 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } } + protected boolean isDataAllowed() { + int gprsState = mGsmPhone.mSST.getCurrentGprsState(); + boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState(); + + boolean allowed = ((gprsState == ServiceState.STATE_IN_SERVICE || noAutoAttach) && + mGsmPhone.mSIMRecords.getRecordsLoaded() && + phone.getState() == Phone.State.IDLE && + mMasterDataEnabled && + (!phone.getServiceState().getRoaming() || getDataOnRoamingEnabled()) && + !mIsPsRestricted && + desiredPowerState); + if (!allowed && DBG) { + String reason = ""; + if (gprsState != ServiceState.STATE_IN_SERVICE) reason += " - gprs= " + gprsState; + if (!mGsmPhone.mSIMRecords.getRecordsLoaded()) reason += " - SIM not loaded"; + if (phone.getState() != Phone.State.IDLE) { + reason += " - PhoneState= " + phone.getState(); + } + if (!mMasterDataEnabled) reason += " - mMasterDataEnabled= false"; + if (phone.getServiceState().getRoaming() && getDataOnRoamingEnabled()) { + reason += " - Roaming"; + } + if (mIsPsRestricted) reason += " - mIsPsRestricted= true"; + if (!desiredPowerState) reason += " - desiredPowerState= false"; + log("Data not allowed due to" + reason); + } + return allowed; + } + private boolean trySetupData(String reason) { if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason)); @@ -430,7 +455,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { // Assume data is connected on the simulator // FIXME this can be improved setState(State.CONNECTED); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); Log.i(LOG_TAG, "(fix?) We're on the simulator; assuming data is connected"); return true; @@ -439,19 +464,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { int gprsState = mGsmPhone.mSST.getCurrentGprsState(); boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState(); - if ((state == State.IDLE || state == State.SCANNING) - && (gprsState == ServiceState.STATE_IN_SERVICE || noAutoAttach) - && mGsmPhone.mSIMRecords.getRecordsLoaded() - && phone.getState() == Phone.State.IDLE - && isDataAllowed() - && !mIsPsRestricted - && desiredPowerState ) { + if (((state == State.IDLE) || (state == State.SCANNING)) && + isDataAllowed() && getAnyDataEnabled()) { if (state == State.IDLE) { waitingApns = buildWaitingApns(); if (waitingApns.isEmpty()) { if (DBG) log("No APN found"); notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN); + notifyOffApnsOfAvailability(reason, false); return false; } else { log ("Create from allApns : " + apnListToString(allApns)); @@ -461,22 +482,11 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (DBG) { log ("Setup waitngApns : " + apnListToString(waitingApns)); } - return setupData(reason); + boolean retValue = setupData(reason); + notifyOffApnsOfAvailability(reason, retValue); + return retValue; } else { - if (DBG) - log("trySetupData: Not ready for data: " + - " dataState=" + state + - " gprsState=" + gprsState + - " sim=" + mGsmPhone.mSIMRecords.getRecordsLoaded() + - " UMTS=" + mGsmPhone.mSST.isConcurrentVoiceAndData() + - " phoneState=" + phone.getState() + - " isDataAllowed=" + isDataAllowed() + - " dataEnabled=" + getAnyDataEnabled() + - " roaming=" + phone.getServiceState().getRoaming() + - " dataOnRoamingEnable=" + getDataOnRoamingEnabled() + - " ps restricted=" + mIsPsRestricted + - " desiredPowerState=" + desiredPowerState + - " MasterDataEnabled=" + mMasterDataEnabled); + notifyOffApnsOfAvailability(reason, false); return false; } } @@ -595,46 +605,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { pdp.connect(msg, apn); setState(State.INITING); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); return true; } - protected String getInterfaceName(String apnType) { - if (mActivePdp != null && - (apnType == null || - (mActiveApn != null && mActiveApn.canHandleType(apnType)))) { - return mActivePdp.getInterface(); - } - return null; - } - - protected String getIpAddress(String apnType) { - if (mActivePdp != null && - (apnType == null || - (mActiveApn != null && mActiveApn.canHandleType(apnType)))) { - return mActivePdp.getIpAddress(); - } - return null; - } - - public String getGateway(String apnType) { - if (mActivePdp != null && - (apnType == null || - (mActiveApn != null && mActiveApn.canHandleType(apnType)))) { - return mActivePdp.getGatewayAddress(); - } - return null; - } - - protected String[] getDnsServers(String apnType) { - if (mActivePdp != null && - (apnType == null || - (mActiveApn != null && mActiveApn.canHandleType(apnType)))) { - return mActivePdp.getDnsServers(); - } - return null; - } - private boolean pdpStatesHasCID (ArrayList<DataCallState> states, int cid) { for (int i = 0, s = states.size() ; i < s ; i++) { @@ -746,7 +720,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { private void notifyDefaultData(String reason) { setState(State.CONNECTED); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); startNetStatPoll(); // reset reconnect timer mRetryMgr.resetRetryCount(); @@ -756,7 +730,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { private void gotoIdleAndNotifyDataConnection(String reason) { if (DBG) log("gotoIdleAndNotifyDataConnection: reason=" + reason); setState(State.IDLE); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); mActiveApn = null; } @@ -998,7 +972,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (!mRetryMgr.isRetryNeeded()) { if (!mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) { // if no more retries on a secondary APN attempt, tell the world and revert. - phone.notifyDataConnection(Phone.REASON_APN_FAILED); + notifyDataConnection(Phone.REASON_APN_FAILED); onEnableApn(apnTypeToId(mRequestedApnType), DISABLED); return; } @@ -1091,7 +1065,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { // Assume data is connected on the simulator // FIXME this can be improved setState(State.CONNECTED); - phone.notifyDataConnection(null); + notifyDataConnection(null); Log.i(LOG_TAG, "We're on the simulator; assuming data is connected"); } @@ -1125,6 +1099,27 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } if (ar.exception == null) { + // TODO: We should clear LinkProperties/Capabilities when torn down or disconnected + mLinkProperties = getLinkProperties(mActivePdp); + mLinkCapabilities = getLinkCapabilities(mActivePdp); + + ApnSetting apn = mActivePdp.getApn(); + if (apn.proxy != null && apn.proxy.length() != 0) { + try { + ProxyProperties proxy = new ProxyProperties(); + proxy.setSocketAddress(new InetSocketAddress(InetAddress.getByName(apn.proxy), + Integer.parseInt(apn.port))); + mLinkProperties.setHttpProxy(proxy); + } catch (UnknownHostException e) { + Log.e(LOG_TAG, "UnknownHostException making ProxyProperties: " + e); + } catch (SecurityException e) { + Log.e(LOG_TAG, "SecurityException making ProxyProperties: " + e); + } catch (NumberFormatException e) { + Log.e(LOG_TAG, "NumberFormatException making ProxyProperties (" + apn.port + + "): " + e); + } + } + // everything is setup if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) { SystemProperties.set("gsm.defaultpdpcontext.active", "true"); @@ -1157,7 +1152,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { // No try for permanent failure if (cause.isPermanentFail()) { notifyNoData(cause); - phone.notifyDataConnection(Phone.REASON_APN_FAILED); + notifyDataConnection(Phone.REASON_APN_FAILED); onEnableApn(apnTypeToId(mRequestedApnType), DISABLED); return; } @@ -1186,7 +1181,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { reason = (String) ar.userObj; } setState(State.IDLE); - phone.notifyDataConnection(reason); + notifyDataConnection(reason); mActiveApn = null; if (retryAfterDisconnected(reason)) { trySetupData(reason); @@ -1217,7 +1212,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { protected void onVoiceCallStarted() { if (state == State.CONNECTED && ! mGsmPhone.mSST.isConcurrentVoiceAndData()) { stopNetStatPoll(); - phone.notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED); + notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED); } } @@ -1225,7 +1220,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (state == State.CONNECTED) { if (!mGsmPhone.mSST.isConcurrentVoiceAndData()) { startNetStatPoll(); - phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED); + notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED); } else { // clean slate after call end. resetPollStats(); diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java index 3079a64..ed7066b 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java @@ -56,6 +56,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { * @param ar AsyncResult passed into the message handler. ar.result should * be a String representing the status report PDU, as ASCII hex. */ + @Override protected void handleStatusReport(AsyncResult ar) { String pduString = (String) ar.result; SmsMessage sms = SmsMessage.newFromCDS(pduString); @@ -84,6 +85,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { /** {@inheritDoc} */ + @Override protected int dispatchMessage(SmsMessageBase smsb) { // If sms is null, means there was a parsing error. @@ -151,6 +153,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendData(String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( @@ -159,6 +162,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent) { SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( @@ -167,6 +171,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendMultipartText(String destinationAddress, String scAddress, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { @@ -306,8 +311,9 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void sendSms(SmsTracker tracker) { - HashMap map = tracker.mData; + HashMap<String, Object> map = tracker.mData; byte smsc[] = (byte[]) map.get("smsc"); byte pdu[] = (byte[]) map.get("pdu"); @@ -322,12 +328,13 @@ final class GsmSMSDispatcher extends SMSDispatcher { * * @param tracker holds the multipart Sms tracker ready to be sent */ + @Override protected void sendMultipartSms (SmsTracker tracker) { ArrayList<String> parts; ArrayList<PendingIntent> sentIntents; ArrayList<PendingIntent> deliveryIntents; - HashMap map = tracker.mData; + HashMap<String, Object> map = tracker.mData; String destinationAddress = (String) map.get("destination"); String scAddress = (String) map.get("scaddress"); @@ -342,6 +349,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void acknowledgeLastIncomingSms(boolean success, int result, Message response){ // FIXME unit test leaves cm == null. this should change if (mCm != null) { @@ -350,6 +358,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void activateCellBroadcastSms(int activate, Message response) { // Unless CBS is implemented for GSM, this point should be unreachable. Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM."); @@ -357,6 +366,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void getCellBroadcastSmsConfig(Message response){ // Unless CBS is implemented for GSM, this point should be unreachable. Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM."); @@ -364,6 +374,7 @@ final class GsmSMSDispatcher extends SMSDispatcher { } /** {@inheritDoc} */ + @Override protected void setCellBroadcastConfig(int[] configValuesArray, Message response) { // Unless CBS is implemented for GSM, this point should be unreachable. Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM."); diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java index 90ecbd7..83ad552 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java @@ -16,6 +16,17 @@ package com.android.internal.telephony.gsm; +import com.android.internal.telephony.CommandException; +import com.android.internal.telephony.CommandsInterface; +import com.android.internal.telephony.DataConnectionTracker; +import com.android.internal.telephony.EventLogTags; +import com.android.internal.telephony.IccCard; +import com.android.internal.telephony.MccTable; +import com.android.internal.telephony.RILConstants; +import com.android.internal.telephony.ServiceStateTracker; +import com.android.internal.telephony.TelephonyIntents; +import com.android.internal.telephony.TelephonyProperties; + import android.app.AlarmManager; import android.app.Notification; import android.app.NotificationManager; @@ -47,17 +58,6 @@ import android.util.EventLog; import android.util.Log; import android.util.TimeUtils; -import com.android.internal.telephony.CommandException; -import com.android.internal.telephony.CommandsInterface; -import com.android.internal.telephony.DataConnectionTracker; -import com.android.internal.telephony.EventLogTags; -import com.android.internal.telephony.IccCard; -import com.android.internal.telephony.MccTable; -import com.android.internal.telephony.RILConstants; -import com.android.internal.telephony.ServiceStateTracker; -import com.android.internal.telephony.TelephonyIntents; -import com.android.internal.telephony.TelephonyProperties; - import java.util.Arrays; import java.util.Calendar; import java.util.Date; @@ -995,7 +995,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { mNeedFixZone = false; if (zone != null) { - if (getAutoTime()) { + if (getAutoTimeZone()) { setAndBroadcastNetworkSetTimeZone(zone.getID()); } saveNitzTimeZone(zone.getID()); @@ -1018,7 +1018,8 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } if (hasNetworkTypeChanged) { - phone.notifyDataConnection(null); + // TODO - do we really want this? + phone.notifyDataConnection(null, null); } if (hasRoamingOn) { @@ -1475,7 +1476,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } if (zone != null) { - if (getAutoTime()) { + if (getAutoTimeZone()) { setAndBroadcastNetworkSetTimeZone(zone.getID()); } saveNitzTimeZone(zone.getID()); @@ -1545,6 +1546,15 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } } + private boolean getAutoTimeZone() { + try { + return Settings.System.getInt(phone.getContext().getContentResolver(), + Settings.System.AUTO_TIME_ZONE) > 0; + } catch (SettingNotFoundException snfe) { + return true; + } + } + private void saveNitzTimeZone(String zoneId) { mSavedTimeZone = zoneId; } diff --git a/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java index 67ecc77..aab359f 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java +++ b/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java @@ -87,6 +87,7 @@ public class SimSmsInterfaceManager extends IccSmsInterfaceManager { public void dispose() { } + @Override protected void finalize() { try { super.finalize(); @@ -192,6 +193,7 @@ public class SimSmsInterfaceManager extends IccSmsInterfaceManager { return mSms; } + @Override protected void log(String msg) { Log.d(LOG_TAG, "[SimSmsInterfaceManager] " + msg); } diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index 9a3c476..e24613f 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -26,7 +26,6 @@ import com.android.internal.telephony.EncodeException; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.SmsHeader; import com.android.internal.telephony.SmsMessageBase; -import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails; import java.io.ByteArrayOutputStream; import java.io.UnsupportedEncodingException; @@ -34,6 +33,7 @@ import java.io.UnsupportedEncodingException; import static android.telephony.SmsMessage.ENCODING_7BIT; import static android.telephony.SmsMessage.ENCODING_8BIT; import static android.telephony.SmsMessage.ENCODING_16BIT; +import static android.telephony.SmsMessage.ENCODING_KSC5601; import static android.telephony.SmsMessage.ENCODING_UNKNOWN; import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES; import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER; @@ -45,7 +45,7 @@ import static android.telephony.SmsMessage.MessageClass; * A Short Message Service message. * */ -public class SmsMessage extends SmsMessageBase{ +public class SmsMessage extends SmsMessageBase { static final String LOG_TAG = "GSM"; private MessageClass messageClass; @@ -311,7 +311,7 @@ public class SmsMessage extends SmsMessageBase{ // the receiver's SIM card. You can then send messages to yourself // (on a phone with this change) and they'll end up on the SIM card. bo.write(0x00); - } else { //assume UCS-2 + } else { // assume UCS-2 if ((0xff & userData[0]) > MAX_USER_DATA_BYTES) { // Message too long return null; @@ -377,7 +377,7 @@ public class SmsMessage extends SmsMessageBase{ * @param destinationAddress the address of the destination for the message * @param destinationPort the port to deliver the message to at the * destination - * @param data the dat for the message + * @param data the data for the message * @return a <code>SubmitPdu</code> containing the encoded SC * address, if applicable, and the encoded message. * Returns null on encode error. @@ -482,7 +482,7 @@ public class SmsMessage extends SmsMessageBase{ return bo; } - static class PduParser { + private static class PduParser { byte pdu[]; int cur; SmsHeader userDataHeader; @@ -490,10 +490,6 @@ public class SmsMessage extends SmsMessageBase{ int mUserDataSeptetPadding; int mUserDataSize; - PduParser(String s) { - this(IccUtils.hexStringToBytes(s)); - } - PduParser(byte[] pdu) { this.pdu = pdu; cur = 0; @@ -545,7 +541,7 @@ public class SmsMessage extends SmsMessageBase{ GsmSmsAddress ret; // "The Address-Length field is an integer representation of - // the number field, i.e. excludes any semi octet containing only + // the number field, i.e. excludes any semi-octet containing only // fill bits." // The TOA field is not included as part of this int addressLength = pdu[cur] & 0xff; @@ -573,7 +569,7 @@ public class SmsMessage extends SmsMessageBase{ int second = IccUtils.gsmBcdByteToInt(pdu[cur++]); // For the timezone, the most significant bit of the - // least signficant nibble is the sign byte + // least significant nibble is the sign byte // (meaning the max range of this field is 79 quarter-hours, // which is more than enough) @@ -632,7 +628,7 @@ public class SmsMessage extends SmsMessageBase{ /* * Here we just create the user data length to be the remainder of * the pdu minus the user data header, since userDataLength means - * the number of uncompressed sepets. + * the number of uncompressed septets. */ bufferLen = pdu.length - offset; } else { @@ -671,10 +667,10 @@ public class SmsMessage extends SmsMessageBase{ } /** - * Returns the number of padding bits at the begining of the user data + * Returns the number of padding bits at the beginning of the user data * array before the start of the septets. * - * @return the number of padding bits at the begining of the user data + * @return the number of padding bits at the beginning of the user data * array before the start of the septets */ int getUserDataSeptetPadding() { @@ -694,7 +690,7 @@ public class SmsMessage extends SmsMessageBase{ XXX Not sure what this one is supposed to be doing, and no one is using it. String getUserDataGSM8bit() { - // System.out.println("remainder of pud:" + + // System.out.println("remainder of pdu:" + // HexDump.dumpHexString(pdu, cur, pdu.length - cur)); int count = pdu[cur++] & 0xff; int size = pdu[cur++]; @@ -781,6 +777,27 @@ public class SmsMessage extends SmsMessageBase{ return ret; } + /** + * Interprets the user data payload as KSC-5601 characters, and + * decodes them into a String. + * + * @param byteCount the number of bytes in the user data payload + * @return a String with the decoded characters + */ + String getUserDataKSC5601(int byteCount) { + String ret; + + try { + ret = new String(pdu, cur, byteCount, "KSC5601"); + } catch (UnsupportedEncodingException ex) { + ret = ""; + Log.e(LOG_TAG, "implausible UnsupportedEncodingException", ex); + } + + cur += byteCount; + return ret; + } + boolean moreDataPresent() { return (pdu.length > cur); } @@ -827,11 +844,13 @@ public class SmsMessage extends SmsMessageBase{ } /** {@inheritDoc} */ + @Override public int getProtocolIdentifier() { return protocolIdentifier; } /** {@inheritDoc} */ + @Override public boolean isReplace() { return (protocolIdentifier & 0xc0) == 0x40 && (protocolIdentifier & 0x3f) > 0 @@ -839,12 +858,14 @@ public class SmsMessage extends SmsMessageBase{ } /** {@inheritDoc} */ + @Override public boolean isCphsMwiMessage() { return ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageClear() || ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageSet(); } /** {@inheritDoc} */ + @Override public boolean isMWIClearMessage() { if (isMwi && (mwiSense == false)) { return true; @@ -855,6 +876,7 @@ public class SmsMessage extends SmsMessageBase{ } /** {@inheritDoc} */ + @Override public boolean isMWISetMessage() { if (isMwi && (mwiSense == true)) { return true; @@ -865,6 +887,7 @@ public class SmsMessage extends SmsMessageBase{ } /** {@inheritDoc} */ + @Override public boolean isMwiDontStore() { if (isMwi && mwiDontStore) { return true; @@ -884,31 +907,34 @@ public class SmsMessage extends SmsMessageBase{ } /** {@inheritDoc} */ + @Override public int getStatus() { return status; } /** {@inheritDoc} */ + @Override public boolean isStatusReportMessage() { return isStatusReportMessage; } /** {@inheritDoc} */ + @Override public boolean isReplyPathPresent() { return replyPathPresent; } /** - * TS 27.005 3.1, <pdu> definition "In the case of SMS: 3GPP TS 24.011 [6] + * TS 27.005 3.1, <pdu> definition "In the case of SMS: 3GPP TS 24.011 [6] * SC address followed by 3GPP TS 23.040 [3] TPDU in hexadecimal format: * ME/TA converts each octet of TP data unit into two IRA character long - * hexad number (e.g. octet with integer value 42 is presented to TE as two + * hex number (e.g. octet with integer value 42 is presented to TE as two * characters 2A (IRA 50 and 65))" ...in the case of cell broadcast, * something else... */ private void parsePdu(byte[] pdu) { mPdu = pdu; - // Log.d(LOG_TAG, "raw sms mesage:"); + // Log.d(LOG_TAG, "raw sms message:"); // Log.d(LOG_TAG, s); PduParser p = new PduParser(pdu); @@ -1107,6 +1133,16 @@ public class SmsMessage extends SmsMessageBase{ Log.w(LOG_TAG, "MWI for fax, email, or other " + (dataCodingScheme & 0xff)); } + } else if ((dataCodingScheme & 0xC0) == 0x80) { + // 3GPP TS 23.038 V7.0.0 (2006-03) section 4 + // 0x80..0xBF == Reserved coding groups + if (dataCodingScheme == 0x84) { + // This value used for KSC5601 by carriers in Korea. + encodingType = ENCODING_KSC5601; + } else { + Log.w(LOG_TAG, "5 - Unsupported SMS data coding scheme " + + (dataCodingScheme & 0xff)); + } } else { Log.w(LOG_TAG, "3 - Unsupported SMS data coding scheme " + (dataCodingScheme & 0xff)); @@ -1131,6 +1167,10 @@ public class SmsMessage extends SmsMessageBase{ case ENCODING_16BIT: messageBody = p.getUserDataUCS2(count); break; + + case ENCODING_KSC5601: + messageBody = p.getUserDataKSC5601(count); + break; } if (Config.LOGV) Log.v(LOG_TAG, "SMS message body (raw): '" + messageBody + "'"); @@ -1162,6 +1202,7 @@ public class SmsMessage extends SmsMessageBase{ /** * {@inheritDoc} */ + @Override public MessageClass getMessageClass() { return messageClass; } diff --git a/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java index b642541..41f3b23 100755 --- a/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java +++ b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java @@ -27,8 +27,6 @@ import com.android.internal.telephony.IccConstants; import com.android.internal.telephony.IccUtils; import com.android.internal.telephony.PhoneBase; -import org.apache.harmony.luni.lang.reflect.ListOfTypes; - import java.util.ArrayList; import java.util.HashMap; import java.util.Map; diff --git a/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java index 6c989b4..f5d84eb 100644 --- a/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java +++ b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java @@ -238,11 +238,9 @@ abstract class SipConnectionBase extends Connection { return Connection.PRESENTATION_ALLOWED; } - /* @Override public UUSInfo getUUSInfo() { // FIXME: what's this for SIP? return null; } - */ } diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java index bceceda..e0eac74 100755 --- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java +++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java @@ -61,7 +61,6 @@ 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 java.io.IOException; import java.text.ParseException; @@ -102,6 +101,14 @@ public class SipPhone extends SipPhoneBase { // new Integer(Phone.PHONE_TYPE_GSM).toString()); } + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof SipPhone)) return false; + SipPhone that = (SipPhone) o; + return mProfile.getUriString().equals(that.mProfile.getUriString()); + } + public String getPhoneName() { return "SIP:" + getUriString(mProfile); } @@ -168,10 +175,6 @@ public class SipPhone extends SipPhoneBase { } } - public Connection dial(String dialString, UUSInfo uusinfo) throws CallStateException { - return dial(dialString); - } - public Connection dial(String dialString) throws CallStateException { synchronized (SipPhone.class) { return dialInternal(dialString); @@ -821,10 +824,6 @@ public class SipPhone extends SipPhoneBase { } } - @Override - public UUSInfo getUUSInfo() { - return null; - } } private static Call.State getCallStateFrom(SipAudioCall sipAudioCall) { diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java index 9098e6f..5f26af4 100755 --- a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java +++ b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java @@ -19,6 +19,7 @@ package com.android.internal.telephony.sip; import android.content.ContentValues; import android.content.Context; import android.content.SharedPreferences; +import android.net.LinkProperties; import android.net.Uri; import android.os.AsyncResult; import android.os.Handler; @@ -65,7 +66,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.UUSInfo; import java.io.IOException; import java.util.ArrayList; @@ -102,13 +103,11 @@ abstract class SipPhoneBase extends PhoneBase { public abstract Call getRingingCall(); - /* public Connection dial(String dialString, UUSInfo uusInfo) throws CallStateException { // ignore UUSInfo return dial(dialString); } - */ void migrateFrom(SipPhoneBase from) { migrate(mRingbackRegistrants, from.mRingbackRegistrants); @@ -533,6 +532,18 @@ abstract class SipPhoneBase extends PhoneBase { Log.e(LOG_TAG, "Error! This functionality is not implemented for SIP."); } + //@Override + public boolean needsOtaServiceProvisioning() { + // FIXME: what's this for SIP? + return false; + } + + //@Override + public LinkProperties getLinkProperties(String apnType) { + // FIXME: what's this for SIP? + return null; + } + void updatePhoneState() { State oldState = state; diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java index 9c72e5a..fdcf78d 100644 --- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java +++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java @@ -16,7 +16,6 @@ package com.android.internal.telephony.test; - import android.os.AsyncResult; import android.os.HandlerThread; import android.os.Looper; @@ -27,7 +26,6 @@ import com.android.internal.telephony.BaseCommands; import com.android.internal.telephony.CommandException; 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; @@ -335,7 +333,7 @@ public final class SimulatedCommands extends BaseCommands /** * (AsyncResult)response.obj).result will be an Integer representing - * the sum of enabled serivice classes (sum of SERVICE_CLASS_*) + * the sum of enabled service classes (sum of SERVICE_CLASS_*) * * @param facility one of CB_FACILTY_* * @param pin password or "" if not required @@ -441,7 +439,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result contains a List of DriverCall * The ar.result List is sorted by DriverCall.index */ @@ -468,7 +466,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result contains a List of DataCallState */ public void getDataCallList(Message result) { @@ -479,7 +477,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure * * CLIR_DEFAULT == on "use subscription default value" @@ -496,7 +494,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure * * CLIR_DEFAULT == on "use subscription default value" @@ -513,7 +511,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is String containing IMSI on success */ public void getIMSI(Message result) { @@ -524,7 +522,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is String containing IMEI on success */ public void getIMEI(Message result) { @@ -535,7 +533,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is String containing IMEISV on success */ public void getIMEISV(Message result) { @@ -547,7 +545,7 @@ public final class SimulatedCommands extends BaseCommands * returned message * retMsg.obj = AsyncResult ar * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure * * 3GPP 22.030 6.5.5 @@ -572,7 +570,7 @@ public final class SimulatedCommands extends BaseCommands * "Releases all held calls or sets User Determined User Busy (UDUB) * for a waiting call." * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void hangupWaitingOrBackground (Message result) { @@ -593,7 +591,7 @@ public final class SimulatedCommands extends BaseCommands * the other (held or waiting) call." * * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void hangupForegroundResumeBackground (Message result) { @@ -614,7 +612,7 @@ public final class SimulatedCommands extends BaseCommands * the other (held or waiting) call." * * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void switchWaitingOrHoldingAndActive (Message result) { @@ -634,7 +632,7 @@ public final class SimulatedCommands extends BaseCommands * "Adds a held call to the conversation" * * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void conference (Message result) { @@ -654,7 +652,7 @@ public final class SimulatedCommands extends BaseCommands * "Connects the two calls and disconnects the subscriber from both calls" * * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void explicitCallTransfer (Message result) { @@ -690,7 +688,7 @@ public final class SimulatedCommands extends BaseCommands /** * * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void acceptCall (Message result) { @@ -708,7 +706,7 @@ public final class SimulatedCommands extends BaseCommands /** * also known as UDUB * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void rejectCall (Message result) { @@ -785,7 +783,7 @@ public final class SimulatedCommands extends BaseCommands * * @param result is callback message * ((AsyncResult)response.obj).result is an int[] with every - * element representing one avialable BM_*_BAND + * element representing one available BM_*_BAND */ public void queryAvailableBandMode (Message result) { int ret[] = new int [4]; @@ -894,7 +892,7 @@ public final class SimulatedCommands extends BaseCommands /** * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void sendDtmf(char c, Message result) { @@ -903,7 +901,7 @@ public final class SimulatedCommands extends BaseCommands /** * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void startDtmf(char c, Message result) { @@ -912,7 +910,7 @@ public final class SimulatedCommands extends BaseCommands /** * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void stopDtmf(Message result) { @@ -921,7 +919,7 @@ public final class SimulatedCommands extends BaseCommands /** * ar.exception carries exception on failure - * ar.userObject contains the orignal value of result.obj + * ar.userObject contains the original value of result.obj * ar.result is null on success and failure */ public void sendBurstDtmf(String dtmfString, int on, int off, Message result) { @@ -956,6 +954,7 @@ public final class SimulatedCommands extends BaseCommands unimplemented(response); } + @Deprecated public void setupDefaultPDP(String apn, String user, String password, Message result) { unimplemented(result); } @@ -967,9 +966,7 @@ public final class SimulatedCommands extends BaseCommands public void deactivateDataCall(int cid, Message result) {unimplemented(result);} - /** - * @deprecated - */ + @Deprecated public void deactivateDefaultPDP(int cid, Message result) {unimplemented(result);} public void setPreferredNetworkType(int networkType , Message result) { @@ -1046,7 +1043,7 @@ public final class SimulatedCommands extends BaseCommands } /** - * parameters equivilient to 27.007 AT+CRSM command + * parameters equivalent to 27.007 AT+CRSM command * response.obj will be an AsyncResult * response.obj.userObj will be a SimIoResult on success */ diff --git a/telephony/mockril/Android.mk b/telephony/mockril/Android.mk new file mode 100644 index 0000000..95ae84c --- /dev/null +++ b/telephony/mockril/Android.mk @@ -0,0 +1,30 @@ +# +# 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. +# +# + +LOCAL_PATH:=$(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_JAVA_LIBRARIES := core framework + +LOCAL_STATIC_JAVA_LIBRARIES := librilproto-java + +LOCAL_MODULE := mockrilcontroller + +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/telephony/mockril/src/com/android/internal/telephony/mockril/MockRilController.java b/telephony/mockril/src/com/android/internal/telephony/mockril/MockRilController.java new file mode 100644 index 0000000..a5139bd --- /dev/null +++ b/telephony/mockril/src/com/android/internal/telephony/mockril/MockRilController.java @@ -0,0 +1,135 @@ +/* + * 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.mockril; + +import android.os.Bundle; +import android.util.Log; + +import com.android.internal.communication.MsgHeader; +import com.android.internal.communication.Msg; +import com.android.internal.telephony.RilChannel; +import com.android.internal.telephony.ril_proto.RilCtrlCmds; +import com.android.internal.telephony.ril_proto.RilCmds; +import com.google.protobuf.micro.MessageMicro; + +import java.io.IOException; + +/** + * Contain a list of commands to control Mock RIL. Before using these commands the devices + * needs to be set with Mock RIL. Refer to hardware/ril/mockril/README.txt for details. + * + */ +public class MockRilController { + private static final String TAG = "MockRILController"; + private RilChannel mRilChannel = null; + private Msg mMessage = null; + + public MockRilController() throws IOException { + mRilChannel = RilChannel.makeRilChannel(); + } + + /** + * Close the channel after the communication is done. + * This method has to be called after the test is finished. + */ + public void closeChannel() { + mRilChannel.close(); + } + + /** + * Send commands and return true on success + * @param cmd for MsgHeader + * @param token for MsgHeader + * @param status for MsgHeader + * @param pbData for Msg data + * @return true if command is sent successfully, false if it fails + */ + private boolean sendCtrlCommand(int cmd, long token, int status, MessageMicro pbData) { + try { + Msg.send(mRilChannel, cmd, token, status, pbData); + } catch (IOException e) { + Log.v(TAG, "send command : %d failed: " + e.getStackTrace()); + return false; + } + return true; + } + + /** + * Get control response + * @return Msg if response is received, else return null. + */ + private Msg getCtrlResponse() { + Msg response = null; + try { + response = Msg.recv(mRilChannel); + } catch (IOException e) { + Log.v(TAG, "receive response for getRadioState() error: " + e.getStackTrace()); + return null; + } + return response; + } + + /** + * @return the radio state if it is valid, otherwise return -1 + */ + public int getRadioState() { + if (!sendCtrlCommand(RilCtrlCmds.CTRL_CMD_GET_RADIO_STATE, 0, 0, null)) { + return -1; + } + Msg response = getCtrlResponse(); + if (response == null) { + Log.v(TAG, "failed to get response"); + return -1; + } + response.printHeader(TAG); + RilCtrlCmds.CtrlRspRadioState resp = + response.getDataAs(RilCtrlCmds.CtrlRspRadioState.class); + int state = resp.getState(); + if ((state >= RilCmds.RADIOSTATE_OFF) && (state <= RilCmds.RADIOSTATE_NV_READY)) + return state; + else + return -1; + } + + /** + * Set the radio state of mock ril to the given state + * @param state for given radio state + * @return true if the state is set successful, false if it fails + */ + public boolean setRadioState(int state) { + RilCtrlCmds.CtrlReqRadioState req = new RilCtrlCmds.CtrlReqRadioState(); + if (state < 0 || state > RilCmds.RADIOSTATE_NV_READY) { + Log.v(TAG, "the give radio state is not valid."); + return false; + } + req.setState(state); + if (!sendCtrlCommand(RilCtrlCmds.CTRL_CMD_SET_RADIO_STATE, 0, 0, req)) { + Log.v(TAG, "send set radio state request failed."); + return false; + } + Msg response = getCtrlResponse(); + if (response == null) { + Log.v(TAG, "failed to get response for setRadioState"); + return false; + } + response.printHeader(TAG); + RilCtrlCmds.CtrlRspRadioState resp = + response.getDataAs(RilCtrlCmds.CtrlRspRadioState.class); + int curstate = resp.getState(); + return curstate == state; + } +} diff --git a/telephony/tests/telephonymockriltests/Android.mk b/telephony/tests/telephonymockriltests/Android.mk new file mode 100644 index 0000000..9731d0d --- /dev/null +++ b/telephony/tests/telephonymockriltests/Android.mk @@ -0,0 +1,14 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_STATIC_JAVA_LIBRARIES := mockrilcontroller + +LOCAL_JAVA_LIBRARIES := android.test.runner + +LOCAL_PACKAGE_NAME := TelephonyMockRilTests + +include $(BUILD_PACKAGE) diff --git a/telephony/tests/telephonymockriltests/AndroidManifest.xml b/telephony/tests/telephonymockriltests/AndroidManifest.xml new file mode 100644 index 0000000..63f44a2 --- /dev/null +++ b/telephony/tests/telephonymockriltests/AndroidManifest.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.telephonymockriltests"> + + <application> + <uses-library android:name="android.test.runner" /> + <activity android:label="TelephonyMockRilTest" + android:name="TelephonyMockRilTest"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> + </application> + + <instrumentation android:name=".TelephonyMockTestRunner" + android:targetPackage="com.android.telephonymockriltests" + android:label="Test runner for Telephony Tests Using Mock RIL" + /> + + <uses-permission android:name="android.permission.READ_PHONE_STATE" /> + <uses-permission android:name="android.permission.INTERNET" /> + +</manifest> diff --git a/telephony/tests/telephonymockriltests/src/com/android/telephonymockriltests/TelephonyMockTestRunner.java b/telephony/tests/telephonymockriltests/src/com/android/telephonymockriltests/TelephonyMockTestRunner.java new file mode 100644 index 0000000..78ee738 --- /dev/null +++ b/telephony/tests/telephonymockriltests/src/com/android/telephonymockriltests/TelephonyMockTestRunner.java @@ -0,0 +1,64 @@ +/* + * 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.telephonymockriltests; + +import android.os.Bundle; +import android.test.InstrumentationTestRunner; +import android.test.InstrumentationTestSuite; +import com.android.internal.telephony.mockril.MockRilController; +import android.util.Log; + +import com.android.telephonymockriltests.functional.SimpleTestUsingMockRil; + +import java.io.IOException; +import junit.framework.TestSuite; +import junit.framework.TestCase; + +/** + * Test runner for telephony tests that using Mock RIL + * + */ +public class TelephonyMockTestRunner extends InstrumentationTestRunner { + private static final String TAG="TelephonyMockTestRunner"; + public MockRilController mController; + + @Override + public TestSuite getAllTests() { + TestSuite suite = new InstrumentationTestSuite(this); + suite.addTestSuite(SimpleTestUsingMockRil.class); + return suite; + } + + @Override + public void onCreate(Bundle icicle) { + try { + mController = new MockRilController(); + } catch (IOException e) { + e.printStackTrace(); + TestCase.assertTrue("Create Mock RIl Controller failed", false); + } + TestCase.assertNotNull(mController); + super.onCreate(icicle); + } + + @Override + public void finish(int resultCode, Bundle results) { + if (mController != null) + mController.closeChannel(); + super.finish(resultCode, results); + } +} diff --git a/telephony/tests/telephonymockriltests/src/com/android/telephonymockriltests/functional/SimpleTestUsingMockRil.java b/telephony/tests/telephonymockriltests/src/com/android/telephonymockriltests/functional/SimpleTestUsingMockRil.java new file mode 100644 index 0000000..3ea1cf2 --- /dev/null +++ b/telephony/tests/telephonymockriltests/src/com/android/telephonymockriltests/functional/SimpleTestUsingMockRil.java @@ -0,0 +1,63 @@ +/* + * 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.telephonymockriltests.functional; + +import com.android.internal.telephony.mockril.MockRilController; +import android.test.InstrumentationTestCase; +import android.util.Log; + +import com.android.telephonymockriltests.TelephonyMockTestRunner; + +/** + * A simple test that using Mock RIL Controller + */ +public class SimpleTestUsingMockRil extends InstrumentationTestCase { + private static final String TAG = "SimpleTestUsingMockRil"; + private MockRilController mMockRilCtrl = null; + private TelephonyMockTestRunner mRunner; + + @Override + public void setUp() throws Exception { + super.setUp(); + mRunner = (TelephonyMockTestRunner)getInstrumentation(); + mMockRilCtrl = mRunner.mController; + assertNotNull(mMockRilCtrl); + } + + /** + * Get the current radio state of RIL + */ + public void testGetRadioState() { + int state = mMockRilCtrl.getRadioState(); + Log.v(TAG, "testGetRadioState: " + state); + assertTrue(state >= 0 && state <= 9); + } + + /** + * Set the current radio state of RIL + * and verify the radio state is set correctly + */ + public void testSetRadioState() { + for (int state = 0; state <= 9; state++) { + Log.v(TAG, "set radio state to be " + state); + assertTrue("set radio state: " + state + " failed.", + mMockRilCtrl.setRadioState(state)); + } + assertFalse("use an invalid radio state", mMockRilCtrl.setRadioState(-1)); + assertFalse("the radio state doesn't exist", mMockRilCtrl.setRadioState(10)); + } +} diff --git a/telephony/tests/telephonytests/Android.mk b/telephony/tests/telephonytests/Android.mk index 45e265a..98e4403 100644 --- a/telephony/tests/telephonytests/Android.mk +++ b/telephony/tests/telephonytests/Android.mk @@ -5,6 +5,8 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-subdir-java-files) +LOCAL_STATIC_JAVA_LIBRARIES := librilproto-java + LOCAL_JAVA_LIBRARIES := android.test.runner LOCAL_PACKAGE_NAME := FrameworksTelephonyTests diff --git a/telephony/tests/telephonytests/AndroidManifest.xml b/telephony/tests/telephonytests/AndroidManifest.xml index 6a97423..ba1d957 100644 --- a/telephony/tests/telephonytests/AndroidManifest.xml +++ b/telephony/tests/telephonytests/AndroidManifest.xml @@ -32,6 +32,13 @@ android:targetPackage="com.android.frameworks.telephonytests" android:label="Frameworks Telephony Tests"> </instrumentation> + + <instrumentation android:name=".TelephonyMockRilTestRunner" + android:targetPackage="com.android.frameworks.telephonytests" + android:label="Test Runner for Mock Ril Tests" + /> + <uses-permission android:name="android.permission.READ_PHONE_STATE" /> + <uses-permission android:name="android.permission.INTERNET" /> </manifest> diff --git a/telephony/tests/telephonytests/src/android/telephony/PhoneNumberWatcherTest.java b/telephony/tests/telephonytests/src/android/telephony/PhoneNumberWatcherTest.java deleted file mode 100644 index 88eaecd..0000000 --- a/telephony/tests/telephonytests/src/android/telephony/PhoneNumberWatcherTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2008 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; - -import android.telephony.PhoneNumberFormattingTextWatcher; -import android.test.suitebuilder.annotation.SmallTest; -import android.text.Selection; -import android.text.SpannableStringBuilder; -import android.text.TextWatcher; - -import junit.framework.TestCase; - -public class PhoneNumberWatcherTest extends TestCase { - @SmallTest - public void testHyphenation() throws Exception { - SpannableStringBuilder number = new SpannableStringBuilder(); - TextWatcher tw = new PhoneNumberFormattingTextWatcher(); - number.append("555-1212"); - // Move the cursor to the left edge - Selection.setSelection(number, 0); - tw.beforeTextChanged(number, 0, 0, 1); - // Insert an 8 at the beginning - number.insert(0, "8"); - tw.afterTextChanged(number); - assertEquals("855-512-12", number.toString()); - } - - @SmallTest - public void testHyphenDeletion() throws Exception { - SpannableStringBuilder number = new SpannableStringBuilder(); - TextWatcher tw = new PhoneNumberFormattingTextWatcher(); - number.append("555-1212"); - // Move the cursor to after the hyphen - Selection.setSelection(number, 4); - // Delete the hyphen - tw.beforeTextChanged(number, 3, 1, 0); - number.delete(3, 4); - tw.afterTextChanged(number); - // Make sure that it deleted the character before the hyphen - assertEquals("551-212", number.toString()); - - // Make sure it deals with left edge boundary case - number.insert(0, "-"); - Selection.setSelection(number, 1); - tw.beforeTextChanged(number, 0, 1, 0); - number.delete(0, 1); - tw.afterTextChanged(number); - // Make sure that it deleted the character before the hyphen - assertEquals("551-212", number.toString()); - } -} diff --git a/telephony/tests/telephonytests/src/com/android/frameworks/telephonytests/TelephonyMockRilTestRunner.java b/telephony/tests/telephonytests/src/com/android/frameworks/telephonytests/TelephonyMockRilTestRunner.java new file mode 100644 index 0000000..9192f57 --- /dev/null +++ b/telephony/tests/telephonytests/src/com/android/frameworks/telephonytests/TelephonyMockRilTestRunner.java @@ -0,0 +1,93 @@ +/* + * 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.frameworks.telephonytests; + +import android.os.Bundle; + +import android.test.InstrumentationTestRunner; +import android.test.InstrumentationTestSuite; +import android.util.Log; + +import java.io.IOException; + +import com.android.internal.telephony.RilChannel; +import com.android.internal.telephony.mockril.MockRilTest; + +import junit.framework.TestSuite; + +public class TelephonyMockRilTestRunner extends InstrumentationTestRunner { + + public RilChannel mMockRilChannel; + + @Override + public TestSuite getAllTests() { + log("getAllTests E"); + TestSuite suite = new InstrumentationTestSuite(this); + suite.addTestSuite(MockRilTest.class); + log("getAllTests X"); + return suite; + } + + @Override + public ClassLoader getLoader() { + log("getLoader EX"); + return TelephonyMockRilTestRunner.class.getClassLoader(); + } + + @Override + public void onCreate(Bundle icicle) { + log("onCreate E"); + try { + mMockRilChannel = RilChannel.makeRilChannel(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + log("onCreate X"); + + super.onCreate(icicle); + } + + @Override + public void onDestroy() { + // I've not seen this called + log("onDestroy EX"); + super.onDestroy(); + } + + @Override + public void onStart() { + // Called when the instrumentation thread is started. + // At the moment we don't need the thread so return + // which will shut down this unused thread. + log("onStart EX"); + super.onStart(); + } + + @Override + public void finish(int resultCode, Bundle results) { + // Called when complete so I ask the mMockRilChannel to quit. + log("finish E"); + mMockRilChannel.close(); + log("finish X"); + super.finish(resultCode, results); + } + + private void log(String s) { + Log.e("TelephonyMockRilTestRunner", s); + } +} diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java index 3a9c511..7011aeb 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java @@ -16,6 +16,8 @@ package com.android.internal.telephony; +import com.android.internal.telephony.GsmAlphabet; + import junit.framework.TestCase; import android.test.suitebuilder.annotation.LargeTest; @@ -51,7 +53,7 @@ public class GsmAlphabetTest extends TestCase { // '@' maps to char 0 assertEquals(0, GsmAlphabet.charToGsm('@')); - // `a (a with grave accent) maps to last GSM charater + // `a (a with grave accent) maps to last GSM character assertEquals(0x7f, GsmAlphabet.charToGsm('\u00e0')); // @@ -307,4 +309,26 @@ public class GsmAlphabetTest extends TestCase { assertEquals("a", GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1)); } + + @SmallTest + public void testGsm8BitUpackedWithEuckr() throws Exception { + // Some feature phones in Korea store contacts as euc-kr. + // Test this situations. + byte unpacked[]; + + // Test general alphabet strings. + unpacked = IccUtils.hexStringToBytes("61626320646566FF"); + assertEquals("abc def", + GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr")); + + // Test korean strings. + unpacked = IccUtils.hexStringToBytes("C5D7BDBAC6AEFF"); + assertEquals("\uD14C\uC2A4\uD2B8", + GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr")); + + // Test gsm Extented Characters. + unpacked = GsmAlphabet.stringToGsm8BitPacked(sGsmExtendedChars); + assertEquals(sGsmExtendedChars, + GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length, "euc-kr")); + } } diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java index 3103fc1..215c6ce 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java @@ -24,8 +24,6 @@ import com.android.internal.util.HexDump; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; -import android.util.Log; - public class GsmSmsTest extends AndroidTestCase { @SmallTest diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java index 2d6977c..7eb3df8 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java @@ -28,7 +28,7 @@ public class MccTableTest extends AndroidTestCase { @SmallTest public void testTimeZone() throws Exception { - assertEquals(MccTable.defaultTimeZoneForMcc(208), "Europe/Paris"); + assertEquals(MccTable.defaultTimeZoneForMcc(208), "ECT"); assertEquals(MccTable.defaultTimeZoneForMcc(232), "Europe/Vienna"); assertEquals(MccTable.defaultTimeZoneForMcc(655), "Africa/Johannesburg"); assertEquals(MccTable.defaultTimeZoneForMcc(440), "Asia/Tokyo"); diff --git a/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java index de59b81..c4a6f53 100644 --- a/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java @@ -20,10 +20,6 @@ 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 AndroidTestCase { @@ -503,4 +499,40 @@ public class PhoneNumberUtilsTest extends AndroidTestCase { assertTrue(PhoneNumberUtils.isVoiceMailNumber(mVoiceMailNumber)); */ } + + @SmallTest + public void testFormatNumberToE164() { + assertEquals("+16502910000", PhoneNumberUtils.formatNumberToE164("650 2910000", "us")); + assertNull(PhoneNumberUtils.formatNumberToE164("1234567", "us")); + assertEquals("+18004664114", PhoneNumberUtils.formatNumberToE164("800-GOOG-114", "us")); + } + + @SmallTest + public void testFormatNumber() { + assertEquals("(650) 291-0000", PhoneNumberUtils.formatNumber("650 2910000", "us")); + assertEquals("123-4567", PhoneNumberUtils.formatNumber("1234567", "us")); + assertEquals("(800) 466-4114", PhoneNumberUtils.formatNumber("800-GOOG-114", "us")); + + } + + @SmallTest + public void testNormalizeNumber() { + assertEquals("6502910000", PhoneNumberUtils.normalizeNumber("650 2910000")); + assertEquals("1234567", PhoneNumberUtils.normalizeNumber("12,3#4*567")); + assertEquals("8004664114", PhoneNumberUtils.normalizeNumber("800-GOOG-114")); + assertEquals("+16502910000", PhoneNumberUtils.normalizeNumber("+1 650 2910000")); + } + + @SmallTest + public void testFormatDailabeNumber() { + // Using the phoneNumberE164's country code + assertEquals("(650) 291-0000", + PhoneNumberUtils.formatNumber("6502910000", "+16502910000", "CN")); + // The phoneNumberE164 is null + assertEquals("(650) 291-0000", PhoneNumberUtils.formatNumber("6502910000", null, "US")); + // The given number has a country code. + assertEquals("+1 650-291-0000", PhoneNumberUtils.formatNumber("+16502910000", null, "CN")); + // The given number was formatted. + assertEquals("650-291-0000", PhoneNumberUtils.formatNumber("650-291-0000", null, "US")); + } } diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java new file mode 100644 index 0000000..d2e573c --- /dev/null +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2008 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; + +import android.telephony.PhoneNumberFormattingTextWatcher; +import android.test.AndroidTestCase; +import android.text.Editable; +import android.text.Selection; +import android.text.SpannableStringBuilder; +import android.text.TextWatcher; + +public class PhoneNumberWatcherTest extends AndroidTestCase { + public void testAppendChars() { + final String multiChars = "65012345"; + final String formatted1 = "(650) 123-45"; + TextWatcher textWatcher = getTextWatcher(); + SpannableStringBuilder number = new SpannableStringBuilder(); + // Append more than one chars + textWatcher.beforeTextChanged(number, 0, 0, multiChars.length()); + number.append(multiChars); + Selection.setSelection(number, number.length()); + textWatcher.onTextChanged(number, 0, 0, number.length()); + textWatcher.afterTextChanged(number); + assertEquals(formatted1, number.toString()); + assertEquals(formatted1.length(), Selection.getSelectionEnd(number)); + // Append one chars + final char appendChar = '6'; + final String formatted2 = "(650) 123-456"; + int len = number.length(); + textWatcher.beforeTextChanged(number, number.length(), 0, 1); + number.append(appendChar); + Selection.setSelection(number, number.length()); + textWatcher.onTextChanged(number, len, 0, 1); + textWatcher.afterTextChanged(number); + assertEquals(formatted2, number.toString()); + assertEquals(formatted2.length(), Selection.getSelectionEnd(number)); + } + + public void testRemoveLastChars() { + final String init = "65012345678"; + final String result1 = "(650) 123-4567"; + TextWatcher textWatcher = getTextWatcher(); + // Remove the last char. + SpannableStringBuilder number = new SpannableStringBuilder(init); + int len = number.length(); + textWatcher.beforeTextChanged(number, len - 1, 1, 0); + number.delete(len - 1, len); + Selection.setSelection(number, number.length()); + textWatcher.onTextChanged(number, number.length() - 1, 1, 0); + textWatcher.afterTextChanged(number); + assertEquals(result1, number.toString()); + assertEquals(result1.length(), Selection.getSelectionEnd(number)); + // Remove last 5 chars + final String result2 = "(650) 123"; + textWatcher.beforeTextChanged(number, number.length() - 4, 4, 0); + number.delete(number.length() - 5, number.length()); + Selection.setSelection(number, number.length()); + textWatcher.onTextChanged(number, number.length(), 4, 0); + textWatcher.afterTextChanged(number); + assertEquals(result2, number.toString()); + assertEquals(result2.length(), Selection.getSelectionEnd(number)); + } + + public void testInsertChars() { + final String init = "(650) 23"; + final String expected1 = "(650) 123"; + TextWatcher textWatcher = getTextWatcher(); + + // Insert one char + SpannableStringBuilder number = new SpannableStringBuilder(init); + textWatcher.beforeTextChanged(number, 4, 0, 1); + number.insert(4, "1"); // (6501) 23 + Selection.setSelection(number, 5); // make the cursor at right of 1 + textWatcher.onTextChanged(number, 4, 0, 1); + textWatcher.afterTextChanged(number); + assertEquals(expected1, number.toString()); + // the cursor should still at the right of '1' + assertEquals(7, Selection.getSelectionEnd(number)); + + // Insert multiple chars + final String expected2 = "(650) 145-6723"; + textWatcher.beforeTextChanged(number, 7, 0, 4); + number.insert(7, "4567"); // change to (650) 1456723 + Selection.setSelection(number, 11); // the cursor is at the right of '7'. + textWatcher.onTextChanged(number, 7, 0, 4); + textWatcher.afterTextChanged(number); + assertEquals(expected2, number.toString()); + // the cursor should be still at the right of '7' + assertEquals(12, Selection.getSelectionEnd(number)); + } + + public void testStopFormatting() { + final String init = "(650) 123"; + final String expected1 = "(650) 123 4"; + TextWatcher textWatcher = getTextWatcher(); + + // Append space + SpannableStringBuilder number = new SpannableStringBuilder(init); + textWatcher.beforeTextChanged(number, 9, 0, 2); + number.insert(9, " 4"); // (6501) 23 4 + Selection.setSelection(number, number.length()); // make the cursor at right of 4 + textWatcher.onTextChanged(number, 9, 0, 2); + textWatcher.afterTextChanged(number); + assertEquals(expected1, number.toString()); + // the cursor should still at the right of '1' + assertEquals(expected1.length(), Selection.getSelectionEnd(number)); + + // Delete a ')' + final String expected2 ="(650 123"; + textWatcher = getTextWatcher(); + number = new SpannableStringBuilder(init); + textWatcher.beforeTextChanged(number, 4, 1, 0); + number.delete(4, 5); // (6501 23 4 + Selection.setSelection(number, 5); // make the cursor at right of 1 + textWatcher.onTextChanged(number, 4, 1, 0); + textWatcher.afterTextChanged(number); + assertEquals(expected2, number.toString()); + // the cursor should still at the right of '1' + assertEquals(5, Selection.getSelectionEnd(number)); + + // Insert a hyphen + final String expected3 ="(650) 12-3"; + textWatcher = getTextWatcher(); + number = new SpannableStringBuilder(init); + textWatcher.beforeTextChanged(number, 8, 0, 1); + number.insert(8, "-"); // (650) 12-3 + Selection.setSelection(number, 9); // make the cursor at right of - + textWatcher.onTextChanged(number, 8, 0, 1); + textWatcher.afterTextChanged(number); + assertEquals(expected3, number.toString()); + // the cursor should still at the right of '-' + assertEquals(9, Selection.getSelectionEnd(number)); + } + + public void testRestartFormatting() { + final String init = "(650) 123"; + final String expected1 = "(650) 123 4"; + TextWatcher textWatcher = getTextWatcher(); + + // Append space + SpannableStringBuilder number = new SpannableStringBuilder(init); + textWatcher.beforeTextChanged(number, 9, 0, 2); + number.insert(9, " 4"); // (650) 123 4 + Selection.setSelection(number, number.length()); // make the cursor at right of 4 + textWatcher.onTextChanged(number, 9, 0, 2); + textWatcher.afterTextChanged(number); + assertEquals(expected1, number.toString()); + // the cursor should still at the right of '4' + assertEquals(expected1.length(), Selection.getSelectionEnd(number)); + + // Clear the current string, and start formatting again. + int len = number.length(); + textWatcher.beforeTextChanged(number, 0, len, 0); + number.delete(0, len); + textWatcher.onTextChanged(number, 0, len, 0); + textWatcher.afterTextChanged(number); + + final String expected2 = "(650) 123-4"; + number = new SpannableStringBuilder(init); + textWatcher.beforeTextChanged(number, 9, 0, 1); + number.insert(9, "4"); // (650) 1234 + Selection.setSelection(number, number.length()); // make the cursor at right of 4 + textWatcher.onTextChanged(number, 9, 0, 1); + textWatcher.afterTextChanged(number); + assertEquals(expected2, number.toString()); + // the cursor should still at the right of '4' + assertEquals(expected2.length(), Selection.getSelectionEnd(number)); + } + + public void testTextChangedByOtherTextWatcher() { + final TextWatcher cleanupTextWatcher = new TextWatcher() { + public void afterTextChanged(Editable s) { + s.clear(); + } + + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + } + + public void onTextChanged(CharSequence s, int start, int before, + int count) { + } + }; + final String init = "(650) 123"; + final String expected1 = ""; + TextWatcher textWatcher = getTextWatcher(); + + SpannableStringBuilder number = new SpannableStringBuilder(init); + textWatcher.beforeTextChanged(number, 5, 0, 1); + number.insert(5, "4"); // (6504) 123 + Selection.setSelection(number, 5); // make the cursor at right of 4 + textWatcher.onTextChanged(number, 5, 0, 1); + number.setSpan(cleanupTextWatcher, 0, number.length(), 0); + textWatcher.afterTextChanged(number); + assertEquals(expected1, number.toString()); + } + + private TextWatcher getTextWatcher() { + return new PhoneNumberFormattingTextWatcher("US"); + } +} diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java index db38ede..ef62d85 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java @@ -28,7 +28,7 @@ public class SimUtilsTest extends TestCase { public void testBasic() throws Exception { byte[] data, data2; - /* + /* * bcdToString() */ @@ -40,9 +40,13 @@ public class SimUtilsTest extends TestCase { assertEquals("0126045001448486", IccUtils.bcdToString(data, 1, data.length - 2)); // Stops on invalid BCD value - data = IccUtils.hexStringToBytes("98F062400510444868f2"); + data = IccUtils.hexStringToBytes("98E062400510444868f2"); assertEquals("890", IccUtils.bcdToString(data, 0, data.length)); + // skip the high nibble 'F' since some PLMNs have it + data = IccUtils.hexStringToBytes("98F062400510444868f2"); + assertEquals("890260450014484862", IccUtils.bcdToString(data, 0, data.length)); + /* * gsmBcdByteToInt() */ diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java index 427795b..8cb05cc 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java @@ -16,6 +16,8 @@ package com.android.internal.telephony; +import com.android.internal.telephony.Phone; + /** * Stub class used for unit tests */ @@ -32,7 +34,7 @@ public class TestPhoneNotifier implements PhoneNotifier { public void notifyCellLocation(Phone sender) { } - + public void notifySignalStrength(Phone sender) { } @@ -42,10 +44,14 @@ public class TestPhoneNotifier implements PhoneNotifier { public void notifyCallForwardingChanged(Phone sender) { } - public void notifyDataConnection(Phone sender, String reason) { + public void notifyDataConnection(Phone sender, String reason, String apnType) { + } + + public void notifyDataConnection(Phone sender, String reason, String apnType, + Phone.DataState state) { } - public void notifyDataConnectionFailed(Phone sender, String reason) { + public void notifyDataConnectionFailed(Phone sender, String reason, String apnType) { } public void notifyDataActivity(Phone sender) { diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMPhoneTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMPhoneTest.java index b96743a..485542b 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMPhoneTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMPhoneTest.java @@ -18,27 +18,21 @@ package com.android.internal.telephony.gsm; import android.os.AsyncResult; import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; import android.os.Message; -import android.os.Process; import android.telephony.ServiceState; import android.test.AndroidTestCase; import android.test.PerformanceTestCase; -import android.util.Log; import com.android.internal.telephony.Call; import com.android.internal.telephony.CallStateException; import com.android.internal.telephony.Connection; import com.android.internal.telephony.MmiCode; import com.android.internal.telephony.Phone; -import com.android.internal.telephony.TestPhoneNotifier; import com.android.internal.telephony.gsm.CallFailCause; import com.android.internal.telephony.gsm.GSMPhone; import com.android.internal.telephony.gsm.GSMTestHandler; import com.android.internal.telephony.gsm.GsmMmiCode; import com.android.internal.telephony.gsm.SuppServiceNotification; -import com.android.internal.telephony.test.SimulatedCommands; import com.android.internal.telephony.test.SimulatedRadioControl; import java.util.List; diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/mockril/MockRilTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/mockril/MockRilTest.java new file mode 100644 index 0000000..f0d5b31 --- /dev/null +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/mockril/MockRilTest.java @@ -0,0 +1,197 @@ +/* + * 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.mockril; + +import android.util.Log; +import android.test.InstrumentationTestCase; + +import java.io.IOException; +import java.nio.ByteBuffer; + +import com.android.internal.communication.MsgHeader; +import com.android.internal.communication.Msg; +import com.android.internal.telephony.RilChannel; +import com.android.internal.telephony.ril_proto.RilCtrlCmds; +import com.android.internal.telephony.ril_proto.RilCmds; + +import com.android.frameworks.telephonytests.TelephonyMockRilTestRunner; +import com.google.protobuf.micro.InvalidProtocolBufferMicroException; + +// Test suite for test ril +public class MockRilTest extends InstrumentationTestCase { + private static final String TAG = "MockRilTest"; + + RilChannel mMockRilChannel; + TelephonyMockRilTestRunner mRunner; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mRunner = (TelephonyMockRilTestRunner)getInstrumentation(); + mMockRilChannel = mRunner.mMockRilChannel; + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + static void log(String s) { + Log.v(TAG, s); + } + + /** + * Test protobuf serialization and deserialization + * @throws InvalidProtocolBufferMicroException + */ + public void testProtobufSerDes() throws InvalidProtocolBufferMicroException { + log("testProtobufSerdes E"); + + RilCtrlCmds.CtrlRspRadioState rs = new RilCtrlCmds.CtrlRspRadioState(); + assertTrue(String.format("expected rs.state == 0 was %d", rs.getState()), + rs.getState() == 0); + rs.setState(1); + assertTrue(String.format("expected rs.state == 1 was %d", rs.getState()), + rs.getState() == 1); + + byte[] rs_ser = rs.toByteArray(); + RilCtrlCmds.CtrlRspRadioState rsNew = RilCtrlCmds.CtrlRspRadioState.parseFrom(rs_ser); + assertTrue(String.format("expected rsNew.state == 1 was %d", rs.getState()), + rs.getState() == 1); + + log("testProtobufSerdes X"); + } + + /** + * Test echo command works using writeMsg & readMsg + */ + public void testEchoMsg() throws IOException { + log("testEchoMsg E"); + + MsgHeader mh = new MsgHeader(); + mh.setCmd(0); + mh.setToken(1); + mh.setStatus(2); + ByteBuffer data = ByteBuffer.allocate(3); + data.put((byte)3); + data.put((byte)4); + data.put((byte)5); + Msg.send(mMockRilChannel, mh, data); + + Msg respMsg = Msg.recv(mMockRilChannel); + assertTrue(String.format("expected mhd.header.cmd == 0 was %d",respMsg.getCmd()), + respMsg.getCmd() == 0); + assertTrue(String.format("expected mhd.header.token == 1 was %d",respMsg.getToken()), + respMsg.getToken() == 1); + assertTrue(String.format("expected mhd.header.status == 2 was %d", respMsg.getStatus()), + respMsg.getStatus() == 2); + assertTrue(String.format("expected mhd.data[0] == 3 was %d", respMsg.getData(0)), + respMsg.getData(0) == 3); + assertTrue(String.format("expected mhd.data[1] == 4 was %d", respMsg.getData(1)), + respMsg.getData(1) == 4); + assertTrue(String.format("expected mhd.data[2] == 5 was %d", respMsg.getData(2)), + respMsg.getData(2) == 5); + + log("testEchoMsg X"); + } + + /** + * Test get as + */ + public void testGetAs() { + log("testGetAs E"); + + // Use a message header as the protobuf data content + MsgHeader mh = new MsgHeader(); + mh.setCmd(12345); + mh.setToken(9876); + mh.setStatus(7654); + mh.setLengthData(4321); + byte[] data = mh.toByteArray(); + MsgHeader mhResult = Msg.getAs(MsgHeader.class, data); + + assertTrue(String.format("expected cmd == 12345 was %d", mhResult.getCmd()), + mhResult.getCmd() == 12345); + assertTrue(String.format("expected token == 9876 was %d", mhResult.getToken()), + mhResult.getToken() == 9876); + assertTrue(String.format("expected status == 7654 was %d", mhResult.getStatus()), + mhResult.getStatus() == 7654); + assertTrue(String.format("expected lengthData == 4321 was %d", mhResult.getLengthData()), + mhResult.getLengthData() == 4321); + + Msg msg = Msg.obtain(); + msg.setData(ByteBuffer.wrap(data)); + + mhResult = msg.getDataAs(MsgHeader.class); + + assertTrue(String.format("expected cmd == 12345 was %d", mhResult.getCmd()), + mhResult.getCmd() == 12345); + assertTrue(String.format("expected token == 9876 was %d", mhResult.getToken()), + mhResult.getToken() == 9876); + assertTrue(String.format("expected status == 7654 was %d", mhResult.getStatus()), + mhResult.getStatus() == 7654); + assertTrue(String.format("expected lengthData == 4321 was %d", mhResult.getLengthData()), + mhResult.getLengthData() == 4321); + + log("testGetAs X"); + } + + public void testGetRadioState() throws IOException { + log("testGetRadioState E"); + + Msg.send(mMockRilChannel, 1, 9876, 0, null); + + Msg resp = Msg.recv(mMockRilChannel); + //resp.printHeader("testGetRadioState"); + + assertTrue(String.format("expected cmd == 1 was %d", resp.getCmd()), + resp.getCmd() == 1); + assertTrue(String.format("expected token == 9876 was %d", resp.getToken()), + resp.getToken() == 9876); + assertTrue(String.format("expected status == 0 was %d", resp.getStatus()), + resp.getStatus() == 0); + + RilCtrlCmds.CtrlRspRadioState rsp = resp.getDataAs(RilCtrlCmds.CtrlRspRadioState.class); + + int state = rsp.getState(); + log("testGetRadioState state=" + state); + assertTrue(String.format("expected RadioState >= 0 && RadioState <= 9 was %d", state), + ((state >= 0) && (state <= 9))); + + log("testGetRadioState X"); + } + + public void testSetRadioState() throws IOException { + log("testSetRadioState E"); + + RilCtrlCmds.CtrlReqRadioState cmdrs = new RilCtrlCmds.CtrlReqRadioState(); + assertEquals(0, cmdrs.getState()); + + cmdrs.setState(RilCmds.RADIOSTATE_SIM_NOT_READY); + assertEquals(2, cmdrs.getState()); + + Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_SET_RADIO_STATE, 0, 0, cmdrs); + + Msg resp = Msg.recv(mMockRilChannel); + + RilCtrlCmds.CtrlRspRadioState rsp = resp.getDataAs(RilCtrlCmds.CtrlRspRadioState.class); + + int state = rsp.getState(); + log("get response for testSetRadioState: " + state); + assertTrue(RilCmds.RADIOSTATE_SIM_NOT_READY == state); + } +} |