summaryrefslogtreecommitdiffstats
path: root/telephony
diff options
context:
space:
mode:
Diffstat (limited to 'telephony')
-rw-r--r--telephony/java/android/telephony/CellLocation.java5
-rw-r--r--telephony/java/android/telephony/PhoneNumberUtils.java94
-rw-r--r--telephony/java/android/telephony/PhoneStateListener.java16
-rw-r--r--telephony/java/android/telephony/ServiceState.java33
-rw-r--r--telephony/java/android/telephony/SmsMessage.java6
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java11
-rw-r--r--telephony/java/android/telephony/cdma/CdmaCellLocation.java41
-rw-r--r--telephony/java/android/telephony/gsm/GsmCellLocation.java13
-rw-r--r--telephony/java/com/android/internal/telephony/BaseCommands.java8
-rw-r--r--telephony/java/com/android/internal/telephony/Call.java17
-rw-r--r--telephony/java/com/android/internal/telephony/CallerInfo.java33
-rw-r--r--telephony/java/com/android/internal/telephony/CommandException.java3
-rw-r--r--telephony/java/com/android/internal/telephony/DataConnection.java848
-rw-r--r--telephony/java/com/android/internal/telephony/DataConnectionTracker.java11
-rw-r--r--telephony/java/com/android/internal/telephony/DataLink.java40
-rw-r--r--telephony/java/com/android/internal/telephony/DataLinkInterface.java77
-rw-r--r--telephony/java/com/android/internal/telephony/DriverCall.java3
-rw-r--r--telephony/java/com/android/internal/telephony/EventLogTags.logtags55
-rw-r--r--telephony/java/com/android/internal/telephony/IccCard.java3
-rw-r--r--telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java8
-rw-r--r--telephony/java/com/android/internal/telephony/IccProvider.java146
-rw-r--r--telephony/java/com/android/internal/telephony/IccUtils.java2
-rw-r--r--telephony/java/com/android/internal/telephony/MccTable.java122
-rw-r--r--telephony/java/com/android/internal/telephony/Phone.java33
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneBase.java74
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneProxy.java46
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneSubInfo.java5
-rw-r--r--telephony/java/com/android/internal/telephony/RIL.java21
-rw-r--r--telephony/java/com/android/internal/telephony/RILConstants.java3
-rw-r--r--telephony/java/com/android/internal/telephony/RetryManager.java8
-rw-r--r--telephony/java/com/android/internal/telephony/SMSDispatcher.java8
-rw-r--r--telephony/java/com/android/internal/telephony/ServiceStateTracker.java7
-rw-r--r--telephony/java/com/android/internal/telephony/SmsMessageBase.java3
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyEventLog.java36
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyIntents.java16
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyProperties.java11
-rw-r--r--telephony/java/com/android/internal/telephony/WapPushOverSms.java40
-rw-r--r--telephony/java/com/android/internal/telephony/WspTypeDecoder.java5
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/CDMAPhone.java55
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/CdmaConnection.java34
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java294
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java293
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaInformationRecords.java2
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java3
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java125
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/EriInfo.java2
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/EriManager.java4
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java31
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/RuimRecords.java2
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java8
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java2
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/SmsMessage.java13
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/ApnSetting.java6
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GSMPhone.java35
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java26
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmConnection.java2
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java226
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java207
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java105
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/PdpConnection.java327
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java31
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java20
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SpnOverride.java16
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java2
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/VoiceMailConstants.java1
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java2
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java31
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/stk/StkService.java3
-rw-r--r--telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java48
-rw-r--r--telephony/tests/telephonytests/Android.mk (renamed from telephony/tests/TelephonyTest/Android.mk)2
-rw-r--r--telephony/tests/telephonytests/AndroidManifest.xml (renamed from telephony/tests/TelephonyTest/AndroidManifest.xml)9
-rw-r--r--telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java475
-rw-r--r--telephony/tests/telephonytests/src/android/telephony/PhoneNumberWatcherTest.java65
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/ATResponseParserTest.java113
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java176
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java310
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java252
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java87
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java79
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/SMSDispatcherTest.java105
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/SimPhoneBookTest.java106
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/SimSmsTest.java60
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java87
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/TelephonyUtilsTest.java219
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java53
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java887
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMPhoneTest.java1938
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMTestHandler.java118
-rw-r--r--telephony/tests/telephonytests/src/com/android/telephonytest/unit/CallerInfoUnitTest.java (renamed from telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java)0
-rw-r--r--telephony/tests/telephonytests/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java (renamed from telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java)0
90 files changed, 7368 insertions, 1640 deletions
diff --git a/telephony/java/android/telephony/CellLocation.java b/telephony/java/android/telephony/CellLocation.java
index f763d3f..2edfc23 100644
--- a/telephony/java/android/telephony/CellLocation.java
+++ b/telephony/java/android/telephony/CellLocation.java
@@ -79,6 +79,11 @@ public abstract class CellLocation {
public abstract void fillInNotifierBundle(Bundle bundle);
/**
+ * @hide
+ */
+ public abstract boolean isEmpty();
+
+ /**
* Return a new CellLocation object representing an unknown
* location, or null for unknown/none phone radio types.
*
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 1aa1c76..32e7176 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -207,6 +207,42 @@ public class PhoneNumberUtils
}
/**
+ * Extracts the network address portion and canonicalize.
+ *
+ * This function is equivalent to extractNetworkPortion(), except
+ * for allowing the PLUS character to occur at arbitrary positions
+ * in the address portion, not just the first position.
+ *
+ * @hide
+ */
+ public static String extractNetworkPortionAlt(String phoneNumber) {
+ if (phoneNumber == null) {
+ return null;
+ }
+
+ int len = phoneNumber.length();
+ StringBuilder ret = new StringBuilder(len);
+ boolean haveSeenPlus = false;
+
+ for (int i = 0; i < len; i++) {
+ char c = phoneNumber.charAt(i);
+ if (c == '+') {
+ if (haveSeenPlus) {
+ continue;
+ }
+ haveSeenPlus = true;
+ }
+ if (isDialable(c)) {
+ ret.append(c);
+ } else if (isStartsPostDial (c)) {
+ break;
+ }
+ }
+
+ return ret.toString();
+ }
+
+ /**
* Strips separators from a phone number string.
* @param phoneNumber phone number to strip.
* @return phone string stripped of separators.
@@ -342,6 +378,8 @@ public class PhoneNumberUtils
compareLoosely(String a, String b) {
int ia, ib;
int matched;
+ int numNonDialableCharsInA = 0;
+ int numNonDialableCharsInB = 0;
if (a == null || b == null) return a == b;
@@ -362,6 +400,7 @@ public class PhoneNumberUtils
if (!isDialable(ca)) {
ia--;
skipCmp = true;
+ numNonDialableCharsInA++;
}
cb = b.charAt(ib);
@@ -369,6 +408,7 @@ public class PhoneNumberUtils
if (!isDialable(cb)) {
ib--;
skipCmp = true;
+ numNonDialableCharsInB++;
}
if (!skipCmp) {
@@ -380,13 +420,16 @@ public class PhoneNumberUtils
}
if (matched < MIN_MATCH) {
- int aLen = a.length();
+ int effectiveALen = a.length() - numNonDialableCharsInA;
+ int effectiveBLen = b.length() - numNonDialableCharsInB;
- // if the input strings match, but their lengths < MIN_MATCH,
- // treat them as equal.
- if (aLen == b.length() && aLen == matched) {
+
+ // if the number of dialable chars in a and b match, but the matched chars < MIN_MATCH,
+ // treat them as equal (i.e. 404-04 and 40404)
+ if (effectiveALen == effectiveBLen && effectiveALen == matched) {
return true;
}
+
return false;
}
@@ -590,7 +633,7 @@ public class PhoneNumberUtils
*/
public static String
toCallerIDMinMatch(String phoneNumber) {
- String np = extractNetworkPortion(phoneNumber);
+ String np = extractNetworkPortionAlt(phoneNumber);
return internalGetStrippedReversed(np, MIN_MATCH);
}
@@ -603,7 +646,7 @@ public class PhoneNumberUtils
*/
public static String
getStrippedReversed(String phoneNumber) {
- String np = extractNetworkPortion(phoneNumber);
+ String np = extractNetworkPortionAlt(phoneNumber);
if (np == null) return null;
@@ -1017,8 +1060,8 @@ public class PhoneNumberUtils
* Breaks the given number down and formats it according to the rules
* for the country the number is from.
*
- * @param source the phone number to format
- * @return a locally acceptable formatting of the input, or the raw input if
+ * @param source The phone number to format
+ * @return A locally acceptable formatting of the input, or the raw input if
* formatting rules aren't known for the number
*/
public static String formatNumber(String source) {
@@ -1028,10 +1071,27 @@ public class PhoneNumberUtils
}
/**
+ * Formats the given number with the given formatting type. Currently
+ * {@link #FORMAT_NANP} and {@link #FORMAT_JAPAN} are supported as a formating type.
+ *
+ * @param source the phone number to format
+ * @param defaultFormattingType The default formatting rules to apply if the number does
+ * not begin with +<country_code>
+ * @return The phone number formatted with the given formatting type.
+ *
+ * @hide TODO:Shuold be unhidden.
+ */
+ public static String formatNumber(String source, int defaultFormattingType) {
+ SpannableStringBuilder text = new SpannableStringBuilder(source);
+ formatNumber(text, defaultFormattingType);
+ return text.toString();
+ }
+
+ /**
* Returns the phone number formatting type for the given locale.
*
* @param locale The locale of interest, usually {@link Locale#getDefault()}
- * @return the formatting type for the given locale, or FORMAT_UNKNOWN if the formatting
+ * @return The formatting type for the given locale, or FORMAT_UNKNOWN if the formatting
* rules are not known for the given locale
*/
public static int getFormatTypeForLocale(Locale locale) {
@@ -1041,7 +1101,8 @@ public class PhoneNumberUtils
}
/**
- * Formats a phone number in-place. Currently only supports NANP formatting.
+ * Formats a phone number in-place. Currently {@link #FORMAT_JAPAN} and {@link #FORMAT_NANP}
+ * is supported as a second argument.
*
* @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
@@ -1247,10 +1308,15 @@ public class PhoneNumberUtils
// Strip the separators from the number before comparing it
// to the list.
- number = extractNetworkPortion(number);
+ number = extractNetworkPortionAlt(number);
// retrieve the list of emergency numbers
- String numbers = SystemProperties.get("ro.ril.ecclist");
+ // check read-write ecclist property first
+ String numbers = SystemProperties.get("ril.ecclist");
+ if (TextUtils.isEmpty(numbers)) {
+ // then read-only ecclist property since old RIL only uses this
+ numbers = SystemProperties.get("ro.ril.ecclist");
+ }
if (!TextUtils.isEmpty(numbers)) {
// searches through the comma-separated list for a match,
@@ -1290,7 +1356,7 @@ public class PhoneNumberUtils
// Strip the separators from the number before comparing it
// to the list.
- number = extractNetworkPortion(number);
+ number = extractNetworkPortionAlt(number);
// compare tolerates null so we need to make sure that we
// don't return true when both are null.
@@ -1593,7 +1659,7 @@ public class PhoneNumberUtils
if (DBG) log("processPlusCodeWithinNanp,networkDialStr=" + networkDialStr);
// If there is a plus sign at the beginning of the dial string,
// Convert the plus sign to the default IDP since it's an international number
- if (networkDialStr != null &
+ if (networkDialStr != null &&
networkDialStr.charAt(0) == PLUS_SIGN_CHAR &&
networkDialStr.length() > 1) {
String newStr = networkDialStr.substring(1);
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 4f9cb2e..830af47 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -1,3 +1,19 @@
+/*
+ * 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 android.telephony;
import android.os.Bundle;
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 446bbc2..1f00885 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -115,6 +115,8 @@ public class ServiceState implements Parcelable {
private String mOperatorNumeric;
private boolean mIsManualNetworkSelection;
+ private boolean mIsEmergencyOnly;
+
//***** CDMA
private int mRadioTechnology;
private boolean mCssIndicator;
@@ -172,6 +174,7 @@ public class ServiceState implements Parcelable {
mCdmaDefaultRoamingIndicator = s.mCdmaDefaultRoamingIndicator;
mCdmaEriIconIndex = s.mCdmaEriIconIndex;
mCdmaEriIconMode = s.mCdmaEriIconMode;
+ mIsEmergencyOnly = s.mIsEmergencyOnly;
}
/**
@@ -192,6 +195,7 @@ public class ServiceState implements Parcelable {
mCdmaDefaultRoamingIndicator = in.readInt();
mCdmaEriIconIndex = in.readInt();
mCdmaEriIconMode = in.readInt();
+ mIsEmergencyOnly = in.readInt() != 0;
}
public void writeToParcel(Parcel out, int flags) {
@@ -209,6 +213,7 @@ public class ServiceState implements Parcelable {
out.writeInt(mCdmaDefaultRoamingIndicator);
out.writeInt(mCdmaEriIconIndex);
out.writeInt(mCdmaEriIconMode);
+ out.writeInt(mIsEmergencyOnly ? 1 : 0);
}
public int describeContents() {
@@ -252,6 +257,13 @@ public class ServiceState implements Parcelable {
/**
* @hide
*/
+ public boolean isEmergencyOnly() {
+ return mIsEmergencyOnly;
+ }
+
+ /**
+ * @hide
+ */
public int getCdmaRoamingIndicator(){
return this.mCdmaRoamingIndicator;
}
@@ -332,7 +344,8 @@ public class ServiceState implements Parcelable {
+ ((null == mOperatorAlphaShort) ? 0 : mOperatorAlphaShort.hashCode())
+ ((null == mOperatorNumeric) ? 0 : mOperatorNumeric.hashCode())
+ mCdmaRoamingIndicator
- + mCdmaDefaultRoamingIndicator);
+ + mCdmaDefaultRoamingIndicator
+ + (mIsEmergencyOnly ? 1 : 0));
}
@Override
@@ -361,7 +374,8 @@ public class ServiceState implements Parcelable {
&& equalsHandlesNulls(mSystemId, s.mSystemId)
&& equalsHandlesNulls(mCdmaRoamingIndicator, s.mCdmaRoamingIndicator)
&& equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
- s.mCdmaDefaultRoamingIndicator));
+ s.mCdmaDefaultRoamingIndicator)
+ && mIsEmergencyOnly == s.mIsEmergencyOnly);
}
@Override
@@ -422,7 +436,8 @@ public class ServiceState implements Parcelable {
+ " " + mNetworkId
+ " " + mSystemId
+ "RoamInd: " + mCdmaRoamingIndicator
- + "DefRoamInd: " + mCdmaDefaultRoamingIndicator);
+ + "DefRoamInd: " + mCdmaDefaultRoamingIndicator
+ + "EmergOnly: " + mIsEmergencyOnly);
}
public void setStateOutOfService() {
@@ -440,6 +455,7 @@ public class ServiceState implements Parcelable {
mCdmaDefaultRoamingIndicator = -1;
mCdmaEriIconIndex = -1;
mCdmaEriIconMode = -1;
+ mIsEmergencyOnly = false;
}
// TODO - can't this be combined with the above func..
@@ -458,6 +474,7 @@ public class ServiceState implements Parcelable {
mCdmaDefaultRoamingIndicator = -1;
mCdmaEriIconIndex = -1;
mCdmaEriIconMode = -1;
+ mIsEmergencyOnly = false;
}
public void setState(int state) {
@@ -468,6 +485,14 @@ public class ServiceState implements Parcelable {
mRoaming = roaming;
}
+
+ /**
+ * @hide
+ */
+ public void setEmergencyOnly(boolean emergencyOnly) {
+ mIsEmergencyOnly = emergencyOnly;
+ }
+
/**
* @hide
*/
@@ -546,6 +571,7 @@ public class ServiceState implements Parcelable {
mSystemId = m.getInt("systemId");
mCdmaRoamingIndicator = m.getInt("cdmaRoamingIndicator");
mCdmaDefaultRoamingIndicator = m.getInt("cdmaDefaultRoamingIndicator");
+ mIsEmergencyOnly = m.getBoolean("emergencyOnly");
}
/**
@@ -567,6 +593,7 @@ public class ServiceState implements Parcelable {
m.putInt("systemId", mSystemId);
m.putInt("cdmaRoamingIndicator", mCdmaRoamingIndicator);
m.putInt("cdmaDefaultRoamingIndicator", mCdmaDefaultRoamingIndicator);
+ m.putBoolean("emergencyOnly", Boolean.valueOf(mIsEmergencyOnly));
}
//***** CDMA
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index b8ea4c0..a284ea5 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -237,8 +237,8 @@ public class SmsMessage {
/*
* TODO(cleanup): It would make some sense if the result of
- * preprocessing a message to determine the proper encoding (ie
- * the resulting datastructure from calculateLength) could be
+ * preprocessing a message to determine the proper encoding (i.e.
+ * the resulting data structure from calculateLength) could be
* passed as an argument to the actual final encoding function.
* This would better ensure that the logic behind size calculation
* actually matched the encoding.
@@ -427,7 +427,7 @@ public class SmsMessage {
* @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.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 310fc7f..ab63017 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -46,7 +46,7 @@ import java.util.List;
* {@link android.content.Context#getSystemService
* Context.getSystemService(Context.TELEPHONY_SERVICE)}.
* <p>
- * Note that acess to some telephony information is
+ * Note that access to some telephony information is
* permission-protected. Your application cannot access the protected
* information unless it has the appropriate permissions declared in
* its manifest file. Where permissions apply, they are noted in the
@@ -203,7 +203,10 @@ public class TelephonyManager {
public CellLocation getCellLocation() {
try {
Bundle bundle = getITelephony().getCellLocation();
- return CellLocation.newFromBundle(bundle);
+ CellLocation cl = CellLocation.newFromBundle(bundle);
+ if (cl.isEmpty())
+ return null;
+ return cl;
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -353,7 +356,7 @@ public class TelephonyManager {
}
/**
- * Returns the ISO country code equivilent of the current registered
+ * Returns the ISO country code equivalent of the current registered
* operator's MCC (Mobile Country Code).
* <p>
* Availability: Only when user is registered to a network. Result may be
@@ -386,6 +389,8 @@ public class TelephonyManager {
public static final int NETWORK_TYPE_HSUPA = 9;
/** Current network is HSPA */
public static final int NETWORK_TYPE_HSPA = 10;
+ /** Current network is iDen */
+ public static final int NETWORK_TYPE_IDEN = 11;
/** Current network is EVDO revision B*/
public static final int NETWORK_TYPE_EVDO_B = 12;
diff --git a/telephony/java/android/telephony/cdma/CdmaCellLocation.java b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
index 7ef7747..84db830 100644
--- a/telephony/java/android/telephony/cdma/CdmaCellLocation.java
+++ b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
@@ -26,12 +26,17 @@ public class CdmaCellLocation extends CellLocation {
private int mBaseStationId = -1;
/**
+ * @hide
+ */
+ public final static int INVALID_LAT_LONG = Integer.MAX_VALUE;
+
+ /**
* Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
* It is represented in units of 0.25 seconds and ranges from -1296000
* to 1296000, both values inclusive (corresponding to a range of -90
* to +90 degrees). Integer.MAX_VALUE is considered invalid value.
*/
- private int mBaseStationLatitude = Integer.MAX_VALUE;
+ private int mBaseStationLatitude = INVALID_LAT_LONG;
/**
* Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
@@ -39,7 +44,7 @@ public class CdmaCellLocation extends CellLocation {
* to 2592000, both values inclusive (corresponding to a range of -180
* to +180 degrees). Integer.MAX_VALUE is considered invalid value.
*/
- private int mBaseStationLongitude = Integer.MAX_VALUE;
+ private int mBaseStationLongitude = INVALID_LAT_LONG;
private int mSystemId = -1;
private int mNetworkId = -1;
@@ -51,8 +56,8 @@ public class CdmaCellLocation extends CellLocation {
*/
public CdmaCellLocation() {
this.mBaseStationId = -1;
- this.mBaseStationLatitude = Integer.MAX_VALUE;
- this.mBaseStationLongitude = Integer.MAX_VALUE;
+ this.mBaseStationLatitude = INVALID_LAT_LONG;
+ this.mBaseStationLongitude = INVALID_LAT_LONG;
this.mSystemId = -1;
this.mNetworkId = -1;
}
@@ -60,12 +65,12 @@ public class CdmaCellLocation extends CellLocation {
/**
* Initialize the object from a bundle.
*/
- public CdmaCellLocation(Bundle bundleWithValues) {
- this.mBaseStationId = bundleWithValues.getInt("baseStationId");
- this.mBaseStationLatitude = bundleWithValues.getInt("baseStationLatitude");
- this.mBaseStationLongitude = bundleWithValues.getInt("baseStationLongitude");
- this.mSystemId = bundleWithValues.getInt("systemId");
- this.mNetworkId = bundleWithValues.getInt("networkId");
+ public CdmaCellLocation(Bundle bundle) {
+ this.mBaseStationId = bundle.getInt("baseStationId", mBaseStationId);
+ this.mBaseStationLatitude = bundle.getInt("baseStationLatitude", mBaseStationLatitude);
+ this.mBaseStationLongitude = bundle.getInt("baseStationLongitude", mBaseStationLongitude);
+ this.mSystemId = bundle.getInt("systemId", mSystemId);
+ this.mNetworkId = bundle.getInt("networkId", mNetworkId);
}
/**
@@ -108,8 +113,8 @@ public class CdmaCellLocation extends CellLocation {
*/
public void setStateInvalid() {
this.mBaseStationId = -1;
- this.mBaseStationLatitude = Integer.MAX_VALUE;
- this.mBaseStationLongitude = Integer.MAX_VALUE;
+ this.mBaseStationLatitude = INVALID_LAT_LONG;
+ this.mBaseStationLongitude = INVALID_LAT_LONG;
this.mSystemId = -1;
this.mNetworkId = -1;
}
@@ -199,6 +204,18 @@ public class CdmaCellLocation extends CellLocation {
bundleToFill.putInt("networkId", this.mNetworkId);
}
+ /**
+ * @hide
+ */
+ public boolean isEmpty() {
+ return (this.mBaseStationId == -1 &&
+ this.mBaseStationLatitude == INVALID_LAT_LONG &&
+ this.mBaseStationLongitude == INVALID_LAT_LONG &&
+ this.mSystemId == -1 &&
+ this.mNetworkId == -1);
+ }
+
+
}
diff --git a/telephony/java/android/telephony/gsm/GsmCellLocation.java b/telephony/java/android/telephony/gsm/GsmCellLocation.java
index 637a11c..fa1f985 100644
--- a/telephony/java/android/telephony/gsm/GsmCellLocation.java
+++ b/telephony/java/android/telephony/gsm/GsmCellLocation.java
@@ -38,8 +38,8 @@ public class GsmCellLocation extends CellLocation {
* Initialize the object from a bundle.
*/
public GsmCellLocation(Bundle bundle) {
- mLac = bundle.getInt("lac");
- mCid = bundle.getInt("cid");
+ mLac = bundle.getInt("lac", mLac);
+ mCid = bundle.getInt("cid", mCid);
}
/**
@@ -119,6 +119,11 @@ public class GsmCellLocation extends CellLocation {
m.putInt("lac", mLac);
m.putInt("cid", mCid);
}
-}
-
+ /**
+ * @hide
+ */
+ public boolean isEmpty() {
+ return (mLac == -1 && mCid == -1);
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/BaseCommands.java b/telephony/java/com/android/internal/telephony/BaseCommands.java
index 7421854..b962375 100644
--- a/telephony/java/com/android/internal/telephony/BaseCommands.java
+++ b/telephony/java/com/android/internal/telephony/BaseCommands.java
@@ -22,7 +22,6 @@ import android.os.RegistrantList;
import android.os.Registrant;
import android.os.Handler;
import android.os.AsyncResult;
-import android.provider.Checkin;
import android.util.Config;
import android.util.Log;
@@ -618,13 +617,6 @@ public abstract class BaseCommands implements CommandsInterface {
return;
}
- if (mContext != null &&
- newState == RadioState.RADIO_UNAVAILABLE &&
- oldState != RadioState.RADIO_OFF) {
- Checkin.updateStats(mContext.getContentResolver(),
- Checkin.Stats.Tag.PHONE_RADIO_RESETS, 1, 0.0);
- }
-
mRadioStateChangedRegistrants.notifyRegistrants();
if (mState.isAvailable() && !oldState.isAvailable()) {
diff --git a/telephony/java/com/android/internal/telephony/Call.java b/telephony/java/com/android/internal/telephony/Call.java
index b95dd11..4967ab8 100644
--- a/telephony/java/com/android/internal/telephony/Call.java
+++ b/telephony/java/com/android/internal/telephony/Call.java
@@ -18,6 +18,8 @@ package com.android.internal.telephony;
import java.util.List;
+import android.util.Log;
+
/**
* {@hide}
*/
@@ -54,6 +56,8 @@ public abstract class Call {
// merged, etc.
protected boolean isGeneric = false;
+ protected final String LOG_TAG = "Call";
+
/* Instance Methods */
/** Do not modify the List result!!! This list is not yours to keep
@@ -235,4 +239,17 @@ public abstract class Call {
public void setGeneric(boolean generic) {
isGeneric = generic;
}
+
+ /**
+ * Hangup call if it is alive
+ */
+ public void hangupIfAlive() {
+ if (getState().isAlive()) {
+ try {
+ hangup();
+ } catch (CallStateException ex) {
+ Log.w(LOG_TAG, " hangupIfActive: caught " + ex);
+ }
+ }
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index 01b1746..cf89848 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -22,6 +22,7 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.ContactsContract.PhoneLookup;
import android.provider.ContactsContract.CommonDataKinds.Phone;
+import static android.provider.ContactsContract.RawContacts;
import android.text.TextUtils;
import android.telephony.TelephonyManager;
import android.telephony.PhoneNumberUtils;
@@ -118,7 +119,6 @@ public class CallerInfo {
* number. The returned CallerInfo is null if no number is supplied.
*/
public static CallerInfo getCallerInfo(Context context, Uri contactRef, Cursor cursor) {
-
CallerInfo info = new CallerInfo();
info.photoResource = 0;
info.phoneLabel = null;
@@ -132,6 +132,9 @@ public class CallerInfo {
if (cursor != null) {
if (cursor.moveToFirst()) {
+ // TODO: photo_id is always available but not taken
+ // care of here. Maybe we should store it in the
+ // CallerInfo object as well.
int columnIndex;
@@ -160,10 +163,34 @@ public class CallerInfo {
}
}
- // Look for the person ID
- columnIndex = cursor.getColumnIndex(PhoneLookup._ID);
+ // Look for the person ID.
+
+ // TODO: This is pretty ugly now, see bug 2269240 for
+ // more details. With tel: URI the contact id is in
+ // col "_id" while when we use a
+ // content://contacts/data/phones URI, the contact id
+ // is col "contact_id". As a work around we use the
+ // type of the contact url to figure out which column
+ // we should look at to get the contact_id.
+
+ final String mimeType = context.getContentResolver().getType(contactRef);
+
+ columnIndex = -1;
+ if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ // content://com.android.contacts/data/phones URL
+ columnIndex = cursor.getColumnIndex(RawContacts.CONTACT_ID);
+ } else {
+ // content://com.android.contacts/phone_lookup URL
+ // TODO: mime type is null here so we cannot test
+ // if we have the right url type. phone_lookup URL
+ // should resolve to a mime type.
+ columnIndex = cursor.getColumnIndex(PhoneLookup._ID);
+ }
+
if (columnIndex != -1) {
info.person_id = cursor.getLong(columnIndex);
+ } else {
+ Log.e(TAG, "Column missing for " + contactRef);
}
// look for the custom ringtone, create from the string stored
diff --git a/telephony/java/com/android/internal/telephony/CommandException.java b/telephony/java/com/android/internal/telephony/CommandException.java
index d7adab3..94c544e 100644
--- a/telephony/java/com/android/internal/telephony/CommandException.java
+++ b/telephony/java/com/android/internal/telephony/CommandException.java
@@ -41,6 +41,7 @@ public class CommandException extends RuntimeException {
SUBSCRIPTION_NOT_AVAILABLE,
MODE_NOT_SUPPORTED,
FDN_CHECK_FAILURE,
+ ILLEGAL_SIM_OR_ME,
}
public CommandException(Error e) {
@@ -80,6 +81,8 @@ public class CommandException extends RuntimeException {
return new CommandException(Error.MODE_NOT_SUPPORTED);
case RILConstants.FDN_CHECK_FAILURE:
return new CommandException(Error.FDN_CHECK_FAILURE);
+ case RILConstants.ILLEGAL_SIM_OR_ME:
+ return new CommandException(Error.ILLEGAL_SIM_OR_ME);
default:
Log.e("GSM", "Unrecognized RIL errno " + ril_errno);
return new CommandException(Error.INVALID_RESPONSE);
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index 7809fed..1f8bbcf 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -16,43 +16,150 @@
package com.android.internal.telephony;
+import com.android.internal.telephony.gsm.ApnSetting;
+
+import com.android.internal.util.HierarchicalState;
+import com.android.internal.util.HierarchicalStateMachine;
+
import android.os.AsyncResult;
-import android.os.Handler;
import android.os.Message;
-import android.util.Log;
+import android.os.SystemProperties;
+import android.util.EventLog;
/**
* {@hide}
+ *
+ * DataConnection HierarchicalStateMachine.
+ *
+ * This is an abstract base class for representing a single data connection.
+ * Instances of this class such as <code>CdmaDataConnection</code> and
+ * <code>GsmDataConnection</code>, * represent a connection via the cellular network.
+ * There may be multiple data connections and all of them are managed by the
+ * <code>DataConnectionTracker</code>.
+ *
+ * Instances are asynchronous state machines and have two primary entry points
+ * <code>connect()</code> and <code>disconnect</code>. The message a parameter will be returned
+ * hen the operation completes. The <code>msg.obj</code> will contain an AsyncResult
+ * object and <code>AsyncResult.userObj</code> is the original <code>msg.obj</code>. if successful
+ * with the <code>AsyncResult.result == null</code> and <code>AsyncResult.exception == null</code>.
+ * If an error <code>AsyncResult.result = FailCause</code> and
+ * <code>AsyncResult.exception = new Exception()</code>.
+ *
+ * The other public methods are provided for debugging.
+ *
+ * Below is the state machine description for this class.
+ *
+ * DataConnection {
+ * + mDefaultState {
+ * EVENT_RESET { clearSettings, notifiyDisconnectCompleted, >mInactiveState }.
+ * EVENT_CONNECT { notifyConnectCompleted(FailCause.UNKNOWN) }.
+ * EVENT_DISCONNECT { notifyDisconnectCompleted }.
+ *
+ * // Ignored messages
+ * EVENT_SETUP_DATA_CONNECTION_DONE,
+ * EVENT_GET_LAST_FAIL_DONE,
+ * EVENT_DEACTIVATE_DONE.
+ * }
+ * ++ # mInactiveState
+ * e(doNotifications)
+ * x(clearNotifications) {
+ * EVENT_RESET { notifiyDisconnectCompleted }.
+ * EVENT_CONNECT {startConnecting, >mActivatingState }.
+ * }
+ * ++ mActivatingState {
+ * EVENT_DISCONNECT { %EVENT_DISCONNECT }.
+ * EVENT_SETUP_DATA_CONNECTION_DONE {
+ * if (SUCCESS) { notifyConnectCompleted(FailCause.NONE), >mActiveState }.
+ * if (ERR_BadCommand) {
+ * notifyConnectCompleted(FailCause.UNKNOWN), >mInactiveState }.
+ * if (ERR_BadDns) { tearDownData($DEACTIVATE_DONE), >mDisconnectingBadDnsState }.
+ * if (ERR_Other) { getLastDataCallFailCause($EVENT_GET_LAST_FAIL_DONE) }.
+ * if (ERR_Stale) {}.
+ * }
+ * EVENT_GET_LAST_FAIL_DONE { notifyConnectCompleted(result), >mInactive }.
+ * }
+ * ++ mActiveState {
+ * EVENT_DISCONNECT { tearDownData($EVENT_DEACTIVATE_DONE), >mDisconnecting }.
+ * }
+ * ++ mDisconnectingState {
+ * EVENT_DEACTIVATE_DONE { notifyDisconnectCompleted, >mInactiveState }.
+ * }
+ * ++ mDisconnectingBadDnsState {
+ * EVENT_DEACTIVATE_DONE { notifyConnectComplete(FailCause.UNKNOWN), >mInactiveState }.
+ * }
+ * }
*/
-public abstract class DataConnection extends Handler {
+public abstract class DataConnection extends HierarchicalStateMachine {
+ protected static final boolean DBG = true;
- // the inherited class
+ protected static Object mCountLock = new Object();
+ protected static int mCount;
- public enum State {
- ACTIVE, /* has active data connection */
- ACTIVATING, /* during connecting process */
- INACTIVE; /* has empty data connection */
+ /**
+ * Class returned by onSetupConnectionCompleted.
+ */
+ protected enum SetupResult {
+ ERR_BadCommand,
+ ERR_BadDns,
+ ERR_Other,
+ ERR_Stale,
+ SUCCESS;
+ public FailCause mFailCause;
+
+ @Override
public String toString() {
switch (this) {
- case ACTIVE:
- return "active";
- case ACTIVATING:
- return "setting up";
- default:
- return "inactive";
+ case ERR_BadCommand: return "Bad Command";
+ case ERR_BadDns: return "Bad DNS";
+ case ERR_Other: return "Other error";
+ case ERR_Stale: return "Stale command";
+ case SUCCESS: return "SUCCESS";
+ default: return "unknown";
}
}
+ }
- public boolean isActive() {
- return this == ACTIVE;
+ /**
+ * Used internally for saving connecting parameters.
+ */
+ protected static class ConnectionParams {
+ public ConnectionParams(ApnSetting apn, Message onCompletedMsg) {
+ this.apn = apn;
+ this.onCompletedMsg = onCompletedMsg;
}
- public boolean isInactive() {
- return this == INACTIVE;
+ public int tag;
+ public ApnSetting apn;
+ public Message onCompletedMsg;
+ }
+
+ /**
+ * An instance used for notification of blockingReset.
+ * TODO: Remove when blockingReset is removed.
+ */
+ class ResetSynchronouslyLock {
+ }
+
+ /**
+ * Used internally for saving disconnecting parameters.
+ */
+ protected static class DisconnectParams {
+ public DisconnectParams(Message onCompletedMsg) {
+ this.onCompletedMsg = onCompletedMsg;
+ }
+ public DisconnectParams(ResetSynchronouslyLock lockObj) {
+ this.lockObj = lockObj;
}
+
+ public int tag;
+ public Message onCompletedMsg;
+ public ResetSynchronouslyLock lockObj;
}
+ /**
+ * Returned as the reason for a connection failure.
+ */
public enum FailCause {
NONE,
OPERATOR_BARRED,
@@ -71,8 +178,7 @@ public abstract class DataConnection extends Handler {
GPRS_REGISTRATION_FAIL,
UNKNOWN,
- RADIO_NOT_AVAILABLE,
- RADIO_ERROR_RETRY;
+ RADIO_NOT_AVAILABLE;
public boolean isPermanentFail() {
return (this == OPERATOR_BARRED) || (this == MISSING_UKNOWN_APN) ||
@@ -128,117 +234,149 @@ public abstract class DataConnection extends Handler {
return "Data Network Registration Failure";
case RADIO_NOT_AVAILABLE:
return "Radio Not Available";
- case RADIO_ERROR_RETRY:
- return "Transient Radio Rrror";
default:
return "Unknown Data Error";
}
}
}
- // ***** Event codes
- protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = 1;
- protected static final int EVENT_GET_LAST_FAIL_DONE = 2;
- protected static final int EVENT_LINK_STATE_CHANGED = 3;
- protected static final int EVENT_DEACTIVATE_DONE = 4;
- protected static final int EVENT_FORCE_RETRY = 5;
+ // ***** Event codes for driving the state machine
+ protected static final int EVENT_RESET = 1;
+ protected static final int EVENT_CONNECT = 2;
+ protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = 3;
+ protected static final int EVENT_GET_LAST_FAIL_DONE = 4;
+ protected static final int EVENT_DEACTIVATE_DONE = 5;
+ protected static final int EVENT_DISCONNECT = 6;
//***** Tag IDs for EventLog
protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
-
//***** Member Variables
+ protected int mTag;
protected PhoneBase phone;
- protected Message onConnectCompleted;
- protected Message onDisconnect;
protected int cid;
protected String interfaceName;
protected String ipAddress;
protected String gatewayAddress;
protected String[] dnsServers;
- protected State state;
protected long createTime;
protected long lastFailTime;
protected FailCause lastFailCause;
protected static final String NULL_IP = "0.0.0.0";
Object userData;
- // receivedDisconnectReq is set when disconnect during activation
- protected boolean receivedDisconnectReq;
-
- /* Instance Methods */
- protected abstract void onSetupConnectionCompleted(AsyncResult ar);
-
- protected abstract void onDeactivated(AsyncResult ar);
-
- protected abstract void disconnect(Message msg);
-
- protected abstract void notifyFail(FailCause cause, Message onCompleted);
-
- protected abstract void notifyDisconnect(Message msg);
+ //***** Abstract methods
+ public abstract String toString();
- protected abstract void onLinkStateChanged(DataLink.LinkState linkState);
+ protected abstract void onConnect(ConnectionParams cp);
protected abstract FailCause getFailCauseFromRequest(int rilCause);
- public abstract String toString();
+ protected abstract boolean isDnsOk(String[] domainNameServers);
protected abstract void log(String s);
//***** Constructor
- protected DataConnection(PhoneBase phone) {
- super();
+ protected DataConnection(PhoneBase phone, String name) {
+ super(name);
+ if (DBG) log("DataConnection constructor E");
this.phone = phone;
- onConnectCompleted = null;
- onDisconnect = null;
this.cid = -1;
- receivedDisconnectReq = false;
this.dnsServers = new String[2];
clearSettings();
+
+ setDbg(false);
+ addState(mDefaultState);
+ addState(mInactiveState, mDefaultState);
+ addState(mActivatingState, mDefaultState);
+ addState(mActiveState, mDefaultState);
+ addState(mDisconnectingState, mDefaultState);
+ addState(mDisconnectingBadDnsState, mDefaultState);
+ setInitialState(mInactiveState);
+ if (DBG) log("DataConnection constructor X");
}
- protected void setHttpProxy(String httpProxy, String httpPort) {
- if (httpProxy == null || httpProxy.length() == 0) {
- phone.setSystemProperty("net.gprs.http-proxy", null);
- return;
+ /**
+ * TearDown the data connection.
+ *
+ * @param o will be returned in AsyncResult.userObj
+ * and is either a DisconnectParams or ConnectionParams.
+ */
+ private void tearDownData(Object o) {
+ if (phone.mCM.getRadioState().isOn()) {
+ if (DBG) log("tearDownData radio is on, call deactivateDataCall");
+ phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, o));
+ } else {
+ if (DBG) log("tearDownData radio is off sendMessage EVENT_DEACTIVATE_DONE immediately");
+ AsyncResult ar = new AsyncResult(o, null, null);
+ sendMessage(obtainMessage(EVENT_DEACTIVATE_DONE, ar));
}
+ }
- if (httpPort == null || httpPort.length() == 0) {
- httpPort = "8080"; // Default to port 8080
+ /**
+ * Send the connectionCompletedMsg.
+ *
+ * @param cp is the ConnectionParams
+ * @param cause
+ */
+ private void notifyConnectCompleted(ConnectionParams cp, FailCause cause) {
+ Message connectionCompletedMsg = cp.onCompletedMsg;
+ if (connectionCompletedMsg == null) {
+ return;
}
- phone.setSystemProperty("net.gprs.http-proxy",
- "http://" + httpProxy + ":" + httpPort + "/");
- }
+ long timeStamp = System.currentTimeMillis();
+ connectionCompletedMsg.arg1 = cid;
- public String getInterface() {
- return interfaceName;
- }
+ if (cause == FailCause.NONE) {
+ createTime = timeStamp;
+ AsyncResult.forMessage(connectionCompletedMsg);
+ } else {
+ lastFailCause = cause;
+ lastFailTime = timeStamp;
+ AsyncResult.forMessage(connectionCompletedMsg, cause, new Exception());
+ }
+ if (DBG) log("notifyConnection at " + timeStamp + " cause=" + cause);
- public String getIpAddress() {
- return ipAddress;
+ connectionCompletedMsg.sendToTarget();
}
- public String getGatewayAddress() {
- return gatewayAddress;
- }
+ /**
+ * Send ar.userObj if its a message, which is should be back to originator.
+ *
+ * @param dp is the DisconnectParams.
+ */
+ private void notifyDisconnectCompleted(DisconnectParams dp) {
+ if (DBG) log("NotifyDisconnectCompleted");
+
+ if (dp.onCompletedMsg != null) {
+ Message msg = dp.onCompletedMsg;
+ log(String.format("msg.what=%d msg.obj=%s",
+ msg.what, ((msg.obj instanceof String) ? (String) msg.obj : "<no-reason>")));
+ AsyncResult.forMessage(msg);
+ msg.sendToTarget();
+ }
+ if (dp.lockObj != null) {
+ synchronized(dp.lockObj) {
+ dp.lockObj.notify();
+ }
+ }
- public String[] getDnsServers() {
- return dnsServers;
+ clearSettings();
}
- public void clearSettings() {
- log("DataConnection.clearSettings()");
+ /**
+ * Clear all settings called when entering mInactiveState.
+ */
+ protected void clearSettings() {
+ if (DBG) log("clearSettings");
- this.state = State.INACTIVE;
this.createTime = -1;
this.lastFailTime = -1;
this.lastFailCause = FailCause.NONE;
- receivedDisconnectReq = false;
- onConnectCompleted = null;
interfaceName = null;
ipAddress = null;
gatewayAddress = null;
@@ -246,80 +384,548 @@ public abstract class DataConnection extends Handler {
dnsServers[1] = null;
}
- protected void onGetLastFailCompleted(AsyncResult ar) {
- if (receivedDisconnectReq) {
- // Don't bother reporting the error if there's already a
- // pending disconnect request, since DataConnectionTracker
- // has already updated its state.
- notifyDisconnect(onDisconnect);
+ /**
+ * Process setup completion.
+ *
+ * @param ar is the result
+ * @return SetupResult.
+ */
+ private SetupResult onSetupConnectionCompleted(AsyncResult ar) {
+ SetupResult result;
+ String[] response = ((String[]) ar.result);
+ ConnectionParams cp = (ConnectionParams) ar.userObj;
+
+ if (ar.exception != null) {
+ if (DBG) log("DataConnection Init failed " + ar.exception);
+
+ if (ar.exception instanceof CommandException
+ && ((CommandException) (ar.exception)).getCommandError()
+ == CommandException.Error.RADIO_NOT_AVAILABLE) {
+ result = SetupResult.ERR_BadCommand;
+ result.mFailCause = FailCause.RADIO_NOT_AVAILABLE;
+ } else {
+ result = SetupResult.ERR_Other;
+ }
+ } else if (cp.tag != mTag) {
+ if (DBG) {
+ log("BUG: onSetupConnectionCompleted is stale cp.tag=" + cp.tag + ", mtag=" + mTag);
+ }
+ result = SetupResult.ERR_Stale;
} else {
- FailCause cause = FailCause.UNKNOWN;
-
- if (ar.exception == null) {
- int rilFailCause = ((int[]) (ar.result))[0];
- cause = getFailCauseFromRequest(rilFailCause);
+// log("onSetupConnectionCompleted received " + response.length + " response strings:");
+// for (int i = 0; i < response.length; i++) {
+// log(" response[" + i + "]='" + response[i] + "'");
+// }
+ if (response.length >= 2) {
+ cid = Integer.parseInt(response[0]);
+ interfaceName = response[1];
+ if (response.length > 2) {
+ ipAddress = response[2];
+ 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;
+ }
+ } else {
+ result = SetupResult.SUCCESS;
+ }
+ } else {
+ result = SetupResult.ERR_Other;
}
- notifyFail(cause, onConnectCompleted);
}
+
+ if (DBG) log("DataConnection setup result='" + result + "' on cid=" + cid);
+ return result;
}
- protected void onForceRetry() {
- if (receivedDisconnectReq) {
- notifyDisconnect(onDisconnect);
- } else {
- notifyFail(FailCause.RADIO_ERROR_RETRY, onConnectCompleted);
+ /**
+ * The parent state for all other states.
+ */
+ private class DcDefaultState extends HierarchicalState {
+ @Override
+ protected boolean processMessage(Message msg) {
+ AsyncResult ar;
+
+ switch (msg.what) {
+ case EVENT_RESET:
+ if (DBG) log("DcDefaultState: msg.what=EVENT_RESET");
+ clearSettings();
+ if (msg.obj != null) {
+ notifyDisconnectCompleted((DisconnectParams) msg.obj);
+ }
+ transitionTo(mInactiveState);
+ break;
+
+ case EVENT_CONNECT:
+ if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected");
+ ConnectionParams cp = (ConnectionParams) msg.obj;
+ notifyConnectCompleted(cp, FailCause.UNKNOWN);
+ break;
+
+ case EVENT_DISCONNECT:
+ if (DBG) log("DcDefaultState: msg.what=EVENT_DISCONNECT");
+ notifyDisconnectCompleted((DisconnectParams) msg.obj);
+ break;
+
+ default:
+ if (DBG) {
+ log("DcDefaultState: shouldn't happen but ignore msg.what=" + msg.what);
+ }
+ break;
+ }
+
+ return true;
}
}
+ private DcDefaultState mDefaultState = new DcDefaultState();
+
+ /**
+ * The state machine is inactive and expects a EVENT_CONNECT.
+ */
+ private class DcInactiveState extends HierarchicalState {
+ private ConnectionParams mConnectionParams = null;
+ private FailCause mFailCause = null;
+ private DisconnectParams mDisconnectParams = null;
+
+ public void setEnterNotificationParams(ConnectionParams cp, FailCause cause) {
+ log("DcInactiveState: setEnterNoticationParams cp,cause");
+ mConnectionParams = cp;
+ mFailCause = cause;
+ }
- @Override
- public void handleMessage(Message msg) {
- AsyncResult ar;
+ public void setEnterNotificationParams(DisconnectParams dp) {
+ log("DcInactiveState: setEnterNoticationParams dp");
+ mDisconnectParams = dp;
+ }
- log("DataConnection.handleMessage()");
+ @Override protected void enter() {
+ mTag += 1;
+
+ /**
+ * Now that we've transitioned to Inactive state we
+ * can send notifications. Previously we sent the
+ * notifications in the processMessage handler but
+ * that caused a race condition because the synchronous
+ * call to isInactive.
+ */
+ if ((mConnectionParams != null) && (mFailCause != null)) {
+ log("DcInactiveState: enter notifyConnectCompleted");
+ notifyConnectCompleted(mConnectionParams, mFailCause);
+ }
+ if (mDisconnectParams != null) {
+ log("DcInactiveState: enter notifyDisconnectCompleted");
+ notifyDisconnectCompleted(mDisconnectParams);
+ }
+ }
- switch (msg.what) {
+ @Override protected void exit() {
+ // clear notifications
+ mConnectionParams = null;
+ mFailCause = null;
+ mDisconnectParams = null;
+ }
- case EVENT_SETUP_DATA_CONNECTION_DONE:
- onSetupConnectionCompleted((AsyncResult) msg.obj);
- break;
+ @Override protected boolean processMessage(Message msg) {
+ boolean retVal;
+
+ switch (msg.what) {
+ case EVENT_RESET:
+ if (DBG) {
+ log("DcInactiveState: msg.what=EVENT_RESET, ignore we're already reset");
+ }
+ if (msg.obj != null) {
+ notifyDisconnectCompleted((DisconnectParams) msg.obj);
+ }
+ retVal = true;
+ break;
+
+ case EVENT_CONNECT:
+ if (DBG) log("DcInactiveState msg.what=EVENT_CONNECT");
+ ConnectionParams cp = (ConnectionParams) msg.obj;
+ cp.tag = mTag;
+ onConnect(cp);
+ transitionTo(mActivatingState);
+ retVal = true;
+ break;
+
+ default:
+ if (DBG) log("DcInactiveState nothandled msg.what=" + msg.what);
+ retVal = false;
+ break;
+ }
+ return retVal;
+ }
+ }
+ private DcInactiveState mInactiveState = new DcInactiveState();
+
+ /**
+ * The state machine is activating a connection.
+ */
+ private class DcActivatingState extends HierarchicalState {
+ @Override protected boolean processMessage(Message msg) {
+ boolean retVal;
+ AsyncResult ar;
+ ConnectionParams cp;
+
+ switch (msg.what) {
+ case EVENT_DISCONNECT:
+ if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT");
+ deferMessage(msg);
+ retVal = true;
+ break;
+
+ case EVENT_SETUP_DATA_CONNECTION_DONE:
+ if (DBG) log("DcActivatingState msg.what=EVENT_SETUP_DATA_CONNECTION_DONE");
+
+ ar = (AsyncResult) msg.obj;
+ cp = (ConnectionParams) ar.userObj;
+
+ SetupResult result = onSetupConnectionCompleted(ar);
+ switch (result) {
+ case SUCCESS:
+ // All is well
+ mActiveState.setEnterNotificationParams(cp, FailCause.NONE);
+ transitionTo(mActiveState);
+ break;
+ case ERR_BadCommand:
+ // Vendor ril rejected the command and didn't connect.
+ // Transition to inactive but send notifications after
+ // we've entered the mInactive state.
+ mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
+ transitionTo(mInactiveState);
+ break;
+ case ERR_BadDns:
+ // Connection succeeded but DNS info is bad so disconnect
+ EventLog.writeEvent(EventLogTags.PDP_BAD_DNS_ADDRESS, dnsServers[0]);
+ tearDownData(cp);
+ transitionTo(mDisconnectingBadDnsState);
+ break;
+ case ERR_Other:
+ // Request the failure cause and process in this state
+ phone.mCM.getLastDataCallFailCause(
+ obtainMessage(EVENT_GET_LAST_FAIL_DONE, cp));
+ break;
+ case ERR_Stale:
+ // Request is stale, ignore.
+ break;
+ default:
+ throw new RuntimeException("Unkown SetupResult, should not happen");
+ }
+ retVal = true;
+ break;
+
+ case EVENT_GET_LAST_FAIL_DONE:
+ ar = (AsyncResult) msg.obj;
+ cp = (ConnectionParams) ar.userObj;
+ FailCause cause = FailCause.UNKNOWN;
+
+ if (cp.tag == mTag) {
+ if (DBG) log("DcActivatingState msg.what=EVENT_GET_LAST_FAIL_DONE");
+ if (ar.exception == null) {
+ int rilFailCause = ((int[]) (ar.result))[0];
+ cause = getFailCauseFromRequest(rilFailCause);
+ }
+ // Transition to inactive but send notifications after
+ // we've entered the mInactive state.
+ mInactiveState.setEnterNotificationParams(cp, cause);
+ transitionTo(mInactiveState);
+ } else {
+ if (DBG) {
+ log("DcActivatingState EVENT_GET_LAST_FAIL_DONE is stale cp.tag="
+ + cp.tag + ", mTag=" + mTag);
+ }
+ }
+
+ retVal = true;
+ break;
+
+ default:
+ if (DBG) log("DcActivatingState not handled msg.what=" + msg.what);
+ retVal = false;
+ break;
+ }
+ return retVal;
+ }
+ }
+ private DcActivatingState mActivatingState = new DcActivatingState();
+
+ /**
+ * The state machine is connected, expecting an EVENT_DISCONNECT.
+ */
+ private class DcActiveState extends HierarchicalState {
+ private ConnectionParams mConnectionParams = null;
+ private FailCause mFailCause = null;
+
+ public void setEnterNotificationParams(ConnectionParams cp, FailCause cause) {
+ log("DcInactiveState: setEnterNoticationParams cp,cause");
+ mConnectionParams = cp;
+ mFailCause = cause;
+ }
- case EVENT_FORCE_RETRY:
- onForceRetry();
- break;
+ @Override public void enter() {
+ /**
+ * Now that we've transitioned to Active state we
+ * can send notifications. Previously we sent the
+ * notifications in the processMessage handler but
+ * that caused a race condition because the synchronous
+ * call to isActive.
+ */
+ if ((mConnectionParams != null) && (mFailCause != null)) {
+ log("DcActiveState: enter notifyConnectCompleted");
+ notifyConnectCompleted(mConnectionParams, mFailCause);
+ }
+ }
- case EVENT_GET_LAST_FAIL_DONE:
- onGetLastFailCompleted((AsyncResult) msg.obj);
- break;
+ @Override protected void exit() {
+ // clear notifications
+ mConnectionParams = null;
+ mFailCause = null;
+ }
- case EVENT_LINK_STATE_CHANGED:
- ar = (AsyncResult) msg.obj;
- DataLink.LinkState ls = (DataLink.LinkState) ar.result;
- onLinkStateChanged(ls);
- break;
+ @Override protected boolean processMessage(Message msg) {
+ boolean retVal;
+
+ switch (msg.what) {
+ case EVENT_DISCONNECT:
+ if (DBG) log("DcActiveState msg.what=EVENT_DISCONNECT");
+ DisconnectParams dp = (DisconnectParams) msg.obj;
+ dp.tag = mTag;
+ tearDownData(dp);
+ transitionTo(mDisconnectingState);
+ retVal = true;
+ break;
+
+ default:
+ if (DBG) log("DcActiveState nothandled msg.what=" + msg.what);
+ retVal = false;
+ break;
+ }
+ return retVal;
+ }
+ }
+ private DcActiveState mActiveState = new DcActiveState();
+
+ /**
+ * The state machine is disconnecting.
+ */
+ private class DcDisconnectingState extends HierarchicalState {
+ @Override protected boolean processMessage(Message msg) {
+ boolean retVal;
+
+ switch (msg.what) {
+ case EVENT_DEACTIVATE_DONE:
+ if (DBG) log("DcDisconnectingState msg.what=EVENT_DEACTIVATE_DONE");
+ AsyncResult ar = (AsyncResult) msg.obj;
+ DisconnectParams dp = (DisconnectParams) ar.userObj;
+ if (dp.tag == mTag) {
+ // Transition to inactive but send notifications after
+ // we've entered the mInactive state.
+ mInactiveState.setEnterNotificationParams((DisconnectParams) ar.userObj);
+ transitionTo(mInactiveState);
+ } else {
+ if (DBG) log("DcDisconnectState EVENT_DEACTIVATE_DONE stale dp.tag="
+ + dp.tag + " mTag=" + mTag);
+ }
+ retVal = true;
+ break;
+
+ default:
+ if (DBG) log("DcDisconnectingState not handled msg.what=" + msg.what);
+ retVal = false;
+ break;
+ }
+ return retVal;
+ }
+ }
+ private DcDisconnectingState mDisconnectingState = new DcDisconnectingState();
+
+ /**
+ * The state machine is disconnecting after a bad dns setup
+ * was found in mInactivatingState.
+ */
+ private class DcDisconnectingBadDnsState extends HierarchicalState {
+ @Override protected boolean processMessage(Message msg) {
+ boolean retVal;
+
+ switch (msg.what) {
+ case EVENT_DEACTIVATE_DONE:
+ AsyncResult ar = (AsyncResult) msg.obj;
+ ConnectionParams cp = (ConnectionParams) ar.userObj;
+ if (cp.tag == mTag) {
+ if (DBG) log("DcDisconnectingBadDnsState msg.what=EVENT_DEACTIVATE_DONE");
+ // Transition to inactive but send notifications after
+ // we've entered the mInactive state.
+ mInactiveState.setEnterNotificationParams(cp, FailCause.UNKNOWN);
+ transitionTo(mInactiveState);
+ } else {
+ if (DBG) log("DcDisconnectingBadDnsState EVENT_DEACTIVE_DONE stale dp.tag="
+ + cp.tag + ", mTag=" + mTag);
+ }
+ retVal = true;
+ break;
+
+ default:
+ if (DBG) log("DcDisconnectingBadDnsState not handled msg.what=" + msg.what);
+ retVal = false;
+ break;
+ }
+ return retVal;
+ }
+ }
+ private DcDisconnectingBadDnsState mDisconnectingBadDnsState = new DcDisconnectingBadDnsState();
+
+ // ******* public interface
+
+ /**
+ * Disconnect from the network.
+ *
+ * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
+ * With AsyncResult.userObj set to the original msg.obj.
+ */
+ public void reset(Message onCompletedMsg) {
+ sendMessage(obtainMessage(EVENT_RESET, new DisconnectParams(onCompletedMsg)));
+ }
- case EVENT_DEACTIVATE_DONE:
- onDeactivated((AsyncResult) msg.obj);
- break;
+ /**
+ * Reset the connection and wait for it to complete.
+ * TODO: Remove when all callers only need the asynchronous
+ * reset defined above.
+ */
+ public void resetSynchronously() {
+ ResetSynchronouslyLock lockObj = new ResetSynchronouslyLock();
+ synchronized(lockObj) {
+ sendMessage(obtainMessage(EVENT_RESET, new DisconnectParams(lockObj)));
+ try {
+ lockObj.wait();
+ } catch (InterruptedException e) {
+ log("blockingReset: unexpected interrupted of wait()");
+ }
}
}
- public State getState() {
- log("DataConnection.getState()");
- return state;
+ /**
+ * Connect to the apn and return an AsyncResult in onCompletedMsg.
+ * Used for cellular networks that use Acess Point Names (APN) such
+ * as GSM networks.
+ *
+ * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
+ * With AsyncResult.userObj set to the original msg.obj,
+ * AsyncResult.result = FailCause and AsyncResult.exception = Exception().
+ * @param apn is the Acces Point Name to connect to
+ */
+ public void connect(Message onCompletedMsg, ApnSetting apn) {
+ sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apn, onCompletedMsg)));
+ }
+
+ /**
+ * Connect to the apn and return an AsyncResult in onCompletedMsg.
+ *
+ * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
+ * With AsyncResult.userObj set to the original msg.obj,
+ * AsyncResult.result = FailCause and AsyncResult.exception = Exception().
+ */
+ public void connect(Message onCompletedMsg) {
+ sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(null, onCompletedMsg)));
+ }
+
+ /**
+ * Disconnect from the network.
+ *
+ * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
+ * With AsyncResult.userObj set to the original msg.obj.
+ */
+ public void disconnect(Message onCompletedMsg) {
+ sendMessage(obtainMessage(EVENT_DISCONNECT, new DisconnectParams(onCompletedMsg)));
+ }
+
+ // ****** The following are used for debugging.
+
+ /**
+ * TODO: This should be an asynchronous call and we wouldn't
+ * have to use handle the notification in the DcInactiveState.enter.
+ *
+ * @return true if the state machine is in the inactive state.
+ */
+ public boolean isInactive() {
+ boolean retVal = getCurrentState() == mInactiveState;
+ return retVal;
+ }
+
+ /**
+ * TODO: This should be an asynchronous call and we wouldn't
+ * have to use handle the notification in the DcActiveState.enter.
+ *
+ * @return true if the state machine is in the active state.
+ */
+ public boolean isActive() {
+ boolean retVal = getCurrentState() == mActiveState;
+ return retVal;
+ }
+
+ /**
+ * @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.
+ */
+ public String getGatewayAddress() {
+ return gatewayAddress;
+ }
+
+ /**
+ * @return an array of associated DNS addresses.
+ */
+ public String[] getDnsServers() {
+ return dnsServers;
+ }
+
+ /**
+ * @return the current state as a string.
+ */
+ public String getStateAsString() {
+ String retVal = getCurrentState().getName();
+ return retVal;
}
+ /**
+ * @return the time of when this connection was created.
+ */
public long getConnectionTime() {
- log("DataConnection.getConnectionTime()");
return createTime;
}
+ /**
+ * @return the time of the last failure.
+ */
public long getLastFailTime() {
- log("DataConnection.getLastFailTime()");
return lastFailTime;
}
+ /**
+ * @return the last cause of failure.
+ */
public FailCause getLastFailCause() {
- log("DataConnection.getLastFailCause()");
return lastFailCause;
}
}
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 52c8b1f..3b9e6cc 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -19,7 +19,6 @@ package com.android.internal.telephony;
import android.app.PendingIntent;
import android.os.AsyncResult;
import android.os.Handler;
-import android.os.INetStatService;
import android.os.Message;
import android.os.RemoteException;
import android.provider.Settings;
@@ -101,6 +100,7 @@ public abstract class DataConnectionTracker extends Handler {
protected static final int EVENT_CDMA_OTA_PROVISION = 35;
protected static final int EVENT_RESTART_RADIO = 36;
protected static final int EVENT_SET_MASTER_DATA_ENABLE = 37;
+ protected static final int EVENT_RESET_DONE = 38;
/***** Constants *****/
@@ -171,7 +171,6 @@ public abstract class DataConnectionTracker extends Handler {
protected Handler mDataConnectionTracker = null;
- protected INetStatService netstat;
protected long txPkts, rxPkts, sentSinceLastRecv;
protected int netStatPollPeriod;
protected int mNoRecvPollCount = 0;
@@ -265,6 +264,7 @@ public abstract class DataConnectionTracker extends Handler {
protected abstract void onRadioOffOrNotAvailable();
protected abstract void onDataSetupComplete(AsyncResult ar);
protected abstract void onDisconnectDone(AsyncResult ar);
+ protected abstract void onResetDone(AsyncResult ar);
protected abstract void onVoiceCallStarted();
protected abstract void onVoiceCallEnded();
protected abstract void onCleanUpConnection(boolean tearDown, String reason);
@@ -331,6 +331,10 @@ public abstract class DataConnectionTracker extends Handler {
onSetDataEnabled(enabled);
break;
+ case EVENT_RESET_DONE:
+ onResetDone((AsyncResult) msg.obj);
+ break;
+
default:
Log.e("DATA", "Unidentified event = " + msg.what);
break;
@@ -440,10 +444,11 @@ public abstract class DataConnectionTracker extends Handler {
return Phone.APN_REQUEST_FAILED;
}
- if(DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = "
+ if (DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = "
+ isApnTypeActive(type) + " and state = " + state);
if (!isApnTypeAvailable(type)) {
+ if (DBG) Log.d(LOG_TAG, "type not available");
return Phone.APN_TYPE_NOT_AVAILABLE;
}
diff --git a/telephony/java/com/android/internal/telephony/DataLink.java b/telephony/java/com/android/internal/telephony/DataLink.java
deleted file mode 100644
index 8132d91..0000000
--- a/telephony/java/com/android/internal/telephony/DataLink.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony;
-
-import android.os.Handler;
-import android.os.Registrant;
-
-/**
- * Base class representing the data link layer (eg, PPP).
- *
- * {@hide}
- */
-public abstract class DataLink extends Handler implements DataLinkInterface {
-
- /** Registrant for link status change notifications. */
- protected Registrant mLinkChangeRegistrant;
- protected DataConnectionTracker dataConnection;
-
- protected DataLink(DataConnectionTracker dc) {
- dataConnection = dc;
- }
-
- public void setOnLinkChange(Handler h, int what, Object obj) {
- mLinkChangeRegistrant = new Registrant(h, what, obj);
- }
-}
diff --git a/telephony/java/com/android/internal/telephony/DataLinkInterface.java b/telephony/java/com/android/internal/telephony/DataLinkInterface.java
deleted file mode 100644
index e8148a8..0000000
--- a/telephony/java/com/android/internal/telephony/DataLinkInterface.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony;
-
-import android.database.Cursor;
-import android.os.Handler;
-
-/**
- * Data link interface.
- *
- * {@hide}
- */
-public interface DataLinkInterface {
- /**
- * Link state enumeration.
- *
- */
- enum LinkState {
- LINK_UNKNOWN,
- LINK_UP,
- LINK_DOWN,
- LINK_EXITED
- }
-
- /** Normal exit */
- final static int EXIT_OK = 0;
- /** Open failed */
- final static int EXIT_OPEN_FAILED = 7;
-
- /**
- * Sets the handler for link state change events.
- *
- * @param h Handler
- * @param what User-defined message code
- * @param obj User object
- */
- void setOnLinkChange(Handler h, int what, Object obj);
-
- /**
- * Sets up the data link.
- */
- void connect();
-
- /**
- * Tears down the data link.
- */
- void disconnect();
-
- /**
- * Returns the exit code for a data link failure.
- *
- * @return exit code
- */
- int getLastLinkExitCode();
-
- /**
- * Sets password information that may be required by the data link
- * (eg, PAP secrets).
- *
- * @param cursor cursor to carriers table
- */
- void setPasswordInfo(Cursor cursor);
-}
diff --git a/telephony/java/com/android/internal/telephony/DriverCall.java b/telephony/java/com/android/internal/telephony/DriverCall.java
index 2382441..663c284 100644
--- a/telephony/java/com/android/internal/telephony/DriverCall.java
+++ b/telephony/java/com/android/internal/telephony/DriverCall.java
@@ -74,8 +74,7 @@ public class DriverCall implements Comparable {
if (p.hasMore()) {
// Some lame implementations return strings
// like "NOT AVAILABLE" in the CLCC line
- ret.number = PhoneNumberUtils.extractNetworkPortion(
- p.nextString());
+ ret.number = PhoneNumberUtils.extractNetworkPortionAlt(p.nextString());
if (ret.number.length() == 0) {
ret.number = null;
diff --git a/telephony/java/com/android/internal/telephony/EventLogTags.logtags b/telephony/java/com/android/internal/telephony/EventLogTags.logtags
new file mode 100644
index 0000000..b06c27d
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/EventLogTags.logtags
@@ -0,0 +1,55 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package com.android.internal.telephony;
+
+# PDP Context has a bad DNS address
+50100 pdp_bad_dns_address (dns_address|3)
+
+# For data connection on PDP context, reached the data-out-without-data-in
+# packet count that triggers a countdown to radio restart
+50101 pdp_radio_reset_countdown_triggered (out_packet_count|1|1)
+
+# Radio restart - timed out with no incoming packets.
+50102 pdp_radio_reset (out_packet_count|1|1)
+
+# PDP context reset - timed out with no incoming packets.
+50103 pdp_context_reset (out_packet_count|1|1)
+
+# Reregister to data network - timed out with no incoming packets.
+50104 pdp_reregister_network (out_packet_count|1|1)
+
+# PDP Setup failures
+50105 pdp_setup_fail (cause|1|5), (cid|1|5), (network_type|1|5)
+
+# Call drops
+50106 call_drop (cause|1|5), (cid|1|5), (network_type|1|5)
+
+# Data network registration failed after successful voice registration
+50107 data_network_registration_fail (op_numeric|1|5), (cid|1|5)
+
+# Suspicious status of data connection while radio poweroff
+50108 data_network_status_on_radio_off (dc_state|3), (enable|1|5)
+
+# PDP drop caused by network
+50109 pdp_network_drop (cid|1|5), (network_type|1|5)
+
+# CDMA data network setup failure
+50110 cdma_data_setup_failed (cause|1|5), (cid|1|5), (network_type|1|5)
+
+# CDMA data network drop
+50111 cdma_data_drop (cid|1|5), (network_type|1|5)
+
+# GSM radio access technology switched
+50112 gsm_rat_switched (cid|1|5), (network_from|1|5), (network_to|1|5)
+
+# GSM data connection state transition
+50113 gsm_data_state_change (oldState|3), (newState|3)
+
+# GSM service state transition
+50114 gsm_service_state_change (oldState|1|5), (oldGprsState|1|5), (newState|1|5), (newGprsState|1|5)
+
+# CDMA data connection state transition
+50115 cdma_data_state_change (oldState|3), (newState|3)
+
+# CDMA service state transition
+50116 cdma_service_state_change (oldState|1|5), (oldDataState|1|5), (newState|1|5), (newDataState|1|5)
diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index 0f76633..d3a34ec 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -202,7 +202,7 @@ public abstract class IccCard {
/**
* Supply the ICC PIN to the ICC
*
- * When the operation is complete, onComplete will be sent to it's
+ * When the operation is complete, onComplete will be sent to its
* Handler.
*
* onComplete.obj will be an AsyncResult
@@ -468,6 +468,7 @@ public abstract class IccCard {
public void broadcastIccStateChangedIntent(String value, String reason) {
Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(Phone.PHONE_NAME_KEY, mPhone.getPhoneName());
intent.putExtra(INTENT_KEY_ICC_STATE, value);
intent.putExtra(INTENT_KEY_LOCKED_REASON, reason);
diff --git a/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
index 31cf6a7..9f8e57f 100644
--- a/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
@@ -22,10 +22,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.ServiceManager;
-import android.telephony.PhoneNumberUtils;
-import android.util.Log;
-import java.util.ArrayList;
import java.util.List;
/**
@@ -37,7 +34,7 @@ public abstract class IccPhoneBookInterfaceManager extends IIccPhoneBook.Stub {
protected PhoneBase phone;
protected AdnRecordCache adnCache;
- protected Object mLock = new Object();
+ protected final Object mLock = new Object();
protected int recordSize[];
protected boolean success;
protected List<AdnRecord> records;
@@ -80,8 +77,7 @@ public abstract class IccPhoneBookInterfaceManager extends IIccPhoneBook.Stub {
ar = (AsyncResult)msg.obj;
synchronized (mLock) {
if (ar.exception == null) {
- records = (List<AdnRecord>)
- ((ArrayList<AdnRecord>) ar.result);
+ records = (List<AdnRecord>) ar.result;
} else {
if(DBG) logd("Cannot load ADN records");
if (records != null) {
diff --git a/telephony/java/com/android/internal/telephony/IccProvider.java b/telephony/java/com/android/internal/telephony/IccProvider.java
index 8b54ca8..fa91457 100644
--- a/telephony/java/com/android/internal/telephony/IccProvider.java
+++ b/telephony/java/com/android/internal/telephony/IccProvider.java
@@ -19,8 +19,9 @@ package com.android.internal.telephony;
import android.content.ContentProvider;
import android.content.UriMatcher;
import android.content.ContentValues;
-import com.android.internal.database.ArrayListCursor;
+import android.database.AbstractCursor;
import android.database.Cursor;
+import android.database.CursorWindow;
import android.net.Uri;
import android.os.SystemProperties;
import android.os.RemoteException;
@@ -35,6 +36,149 @@ import com.android.internal.telephony.IccConstants;
import com.android.internal.telephony.AdnRecord;
import com.android.internal.telephony.IIccPhoneBook;
+/**
+ * XXX old code -- should be replaced with MatrixCursor.
+ * @deprecated This is has been replaced by MatrixCursor.
+*/
+class ArrayListCursor extends AbstractCursor {
+ private String[] mColumnNames;
+ private ArrayList<Object>[] mRows;
+
+ @SuppressWarnings({"unchecked"})
+ public ArrayListCursor(String[] columnNames, ArrayList<ArrayList> rows) {
+ int colCount = columnNames.length;
+ boolean foundID = false;
+ // Add an _id column if not in columnNames
+ for (int i = 0; i < colCount; ++i) {
+ if (columnNames[i].compareToIgnoreCase("_id") == 0) {
+ mColumnNames = columnNames;
+ foundID = true;
+ break;
+ }
+ }
+
+ if (!foundID) {
+ mColumnNames = new String[colCount + 1];
+ System.arraycopy(columnNames, 0, mColumnNames, 0, columnNames.length);
+ mColumnNames[colCount] = "_id";
+ }
+
+ int rowCount = rows.size();
+ mRows = new ArrayList[rowCount];
+
+ for (int i = 0; i < rowCount; ++i) {
+ mRows[i] = rows.get(i);
+ if (!foundID) {
+ mRows[i].add(i);
+ }
+ }
+ }
+
+ @Override
+ public void fillWindow(int position, CursorWindow window) {
+ if (position < 0 || position > getCount()) {
+ return;
+ }
+
+ window.acquireReference();
+ try {
+ int oldpos = mPos;
+ mPos = position - 1;
+ window.clear();
+ window.setStartPosition(position);
+ int columnNum = getColumnCount();
+ window.setNumColumns(columnNum);
+ while (moveToNext() && window.allocRow()) {
+ for (int i = 0; i < columnNum; i++) {
+ final Object data = mRows[mPos].get(i);
+ if (data != null) {
+ if (data instanceof byte[]) {
+ byte[] field = (byte[]) data;
+ if (!window.putBlob(field, mPos, i)) {
+ window.freeLastRow();
+ break;
+ }
+ } else {
+ String field = data.toString();
+ if (!window.putString(field, mPos, i)) {
+ window.freeLastRow();
+ break;
+ }
+ }
+ } else {
+ if (!window.putNull(mPos, i)) {
+ window.freeLastRow();
+ break;
+ }
+ }
+ }
+ }
+
+ mPos = oldpos;
+ } catch (IllegalStateException e){
+ // simply ignore it
+ } finally {
+ window.releaseReference();
+ }
+ }
+
+ @Override
+ public int getCount() {
+ return mRows.length;
+ }
+
+ @Override
+ public String[] getColumnNames() {
+ return mColumnNames;
+ }
+
+ @Override
+ public byte[] getBlob(int columnIndex) {
+ return (byte[]) mRows[mPos].get(columnIndex);
+ }
+
+ @Override
+ public String getString(int columnIndex) {
+ Object cell = mRows[mPos].get(columnIndex);
+ return (cell == null) ? null : cell.toString();
+ }
+
+ @Override
+ public short getShort(int columnIndex) {
+ Number num = (Number) mRows[mPos].get(columnIndex);
+ return num.shortValue();
+ }
+
+ @Override
+ public int getInt(int columnIndex) {
+ Number num = (Number) mRows[mPos].get(columnIndex);
+ return num.intValue();
+ }
+
+ @Override
+ public long getLong(int columnIndex) {
+ Number num = (Number) mRows[mPos].get(columnIndex);
+ return num.longValue();
+ }
+
+ @Override
+ public float getFloat(int columnIndex) {
+ Number num = (Number) mRows[mPos].get(columnIndex);
+ return num.floatValue();
+ }
+
+ @Override
+ public double getDouble(int columnIndex) {
+ Number num = (Number) mRows[mPos].get(columnIndex);
+ return num.doubleValue();
+ }
+
+ @Override
+ public boolean isNull(int columnIndex) {
+ return mRows[mPos].get(columnIndex) == null;
+ }
+}
+
/**
* {@hide}
diff --git a/telephony/java/com/android/internal/telephony/IccUtils.java b/telephony/java/com/android/internal/telephony/IccUtils.java
index 3e7094e..71936f1 100644
--- a/telephony/java/com/android/internal/telephony/IccUtils.java
+++ b/telephony/java/com/android/internal/telephony/IccUtils.java
@@ -397,7 +397,7 @@ public class IccUtils {
int bits = data[valueIndex++] & 0xFF;
int colorNumber = data[valueIndex++] & 0xFF;
int clutOffset = ((data[valueIndex++] & 0xFF) << 8)
- | data[valueIndex++];
+ | (data[valueIndex++] & 0xFF);
length = length - 6;
int[] colorIndexArray = getCLUT(data, clutOffset, colorNumber);
diff --git a/telephony/java/com/android/internal/telephony/MccTable.java b/telephony/java/com/android/internal/telephony/MccTable.java
index fc9de96..b73c2f7 100644
--- a/telephony/java/com/android/internal/telephony/MccTable.java
+++ b/telephony/java/com/android/internal/telephony/MccTable.java
@@ -24,6 +24,7 @@ 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;
@@ -106,7 +107,7 @@ mcc_table = [
(294, 'mk', 2, 'The Former Yugoslav Republic of Macedonia'),
(295, 'li', 2, 'Liechtenstein (Principality of)'),
(297, 'me', 2, 'Montenegro (Republic of)'),
- (302, 'ca', 2, '', '', 11, 'Canada'),
+ (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'),
@@ -179,8 +180,8 @@ mcc_table = [
(455, 'mo', 2, '"Macao, China"'),
(456, 'kh', 2, 'Cambodia (Kingdom of)'),
(457, 'la', 2, "Lao People's Democratic Republic"),
- (460, 'cn', 2, "China (People's Republic of)"),
- (461, 'cn', 2, "China (People's Republic of)"),
+ (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)"),
@@ -191,7 +192,7 @@ mcc_table = [
(514, 'tl', 2, 'Democratic Republic of Timor-Leste'),
(515, 'ph', 2, 'Philippines (Republic of the)'),
(520, 'th', 2, 'Thailand'),
- (525, 'sg', 2, 'Singapore', 'en', 11, 'Singapore (Republic of)'),
+ (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)'),
@@ -371,11 +372,13 @@ for i in range(len(orig_table)):
public final class MccTable
{
/**
- * AUTO GENERATED (by the Python code above)
- */
+ * 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",
@@ -389,23 +392,22 @@ public final class MccTable
"Europe/Vienna",
"Europe/Warsaw",
"Europe/Zurich",
- "Pacific/Auckland",
- "Singapore"
+ "Pacific/Auckland"
};
/**
- * AUTO GENERATED (by the Python code above)
- */
+ * AUTO GENERATED (by the Python code above)
+ */
private static final String[] LANG_STRINGS = {
- "", "cs", "de", "en", "es", "fr", "it", "ja", "nl"
+ "", "cs", "de", "en", "es", "fr", "it", "ja", "nl", "zh"
};
/**
- * 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.
- */
+ * 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,
@@ -434,25 +436,25 @@ public final class MccTable
};
/**
- * 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
- */
+ * 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, 0x6e6c6c48, 0x62650400, 0x66720495, 0x6d630400, 0x61640400,
- 0x65730484, 0x68750400, 0x62610400, 0x68720400, 0x72730400, 0x697404b6,
- 0x766104b6, 0x726f0400, 0x636804e2, 0x637a6ca1, 0x736b0400, 0x61746cc2,
- 0x67626c73, 0x67626c73, 0x646b0400, 0x73650400, 0x6e6f0400, 0x66690400,
+ 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, 0x706c04d0, 0x64656c52, 0x67690400, 0x70740400, 0x6c750400,
- 0x69650463, 0x69730400, 0x616c0400, 0x6d740400, 0x63790400, 0x67650400,
+ 0x6d640400, 0x706c04f0, 0x64656c72, 0x67690400, 0x70740400, 0x6c750400,
+ 0x69650483, 0x69730400, 0x616c0400, 0x6d740400, 0x63790400, 0x67650400,
0x616d0400, 0x62670400, 0x74720400, 0x666f0400, 0x67650400, 0x676c0400,
- 0x736d0400, 0x736c0400, 0x6d6b0400, 0x6c690400, 0x6d650400, 0x63615c00,
+ 0x736d0400, 0x736c0400, 0x6d6b0400, 0x6c690400, 0x6d650400, 0x63615e00,
0x706d0400, 0x75735e03, 0x75735e03, 0x75735e03, 0x75735e03, 0x75735e03,
0x75735e03, 0x75735e03, 0x70720400, 0x76690400, 0x6d780600, 0x6a6d0600,
0x67700400, 0x62620600, 0x61670600, 0x6b790600, 0x76670600, 0x626d0400,
@@ -463,11 +465,11 @@ public final class MccTable
0x6c620400, 0x6a6f0400, 0x73790400, 0x69710400, 0x6b770400, 0x73610400,
0x79650400, 0x6f6d0400, 0x70730400, 0x61650400, 0x696c0400, 0x62680400,
0x71610400, 0x6d6e0400, 0x6e700400, 0x61650400, 0x61650400, 0x69720400,
- 0x757a0400, 0x746a0400, 0x6b670400, 0x746d0400, 0x6a707427, 0x6a707427,
+ 0x757a0400, 0x746a0400, 0x6b670400, 0x746d0400, 0x6a707447, 0x6a707447,
0x6b720400, 0x766e0400, 0x686b0400, 0x6d6f0400, 0x6b680400, 0x6c610400,
- 0x636e0400, 0x636e0400, 0x74770400, 0x6b700400, 0x62640400, 0x6d760400,
- 0x6d790400, 0x61755c33, 0x69640400, 0x746c0400, 0x70680400, 0x74680400,
- 0x73675d03, 0x626e0400, 0x6e7a04f3, 0x6d700400, 0x67750400, 0x6e720400,
+ 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,
@@ -572,34 +574,36 @@ public final class MccTable
* @param mccmnc truncated imsi with just the MCC and MNC - MNC assumed to be from 4th to end
*/
public static void updateMccMncConfiguration(PhoneBase phone, String mccmnc) {
- int mcc, mnc;
-
- try {
- mcc = Integer.parseInt(mccmnc.substring(0,3));
- mnc = Integer.parseInt(mccmnc.substring(3));
- } catch (NumberFormatException e) {
- Log.e(LOG_TAG, "Error parsing IMSI");
- return;
- }
+ if (!TextUtils.isEmpty(mccmnc)) {
+ int mcc, mnc;
+
+ try {
+ mcc = Integer.parseInt(mccmnc.substring(0,3));
+ mnc = Integer.parseInt(mccmnc.substring(3));
+ } catch (NumberFormatException e) {
+ Log.e(LOG_TAG, "Error parsing IMSI");
+ return;
+ }
- Log.d(LOG_TAG, "updateMccMncConfiguration: mcc=" + mcc + ", mnc=" + mnc);
+ Log.d(LOG_TAG, "updateMccMncConfiguration: mcc=" + mcc + ", mnc=" + mnc);
- if (mcc != 0) {
- setTimezoneFromMccIfNeeded(phone, mcc);
- setLocaleFromMccIfNeeded(phone, mcc);
- setWifiChannelsFromMcc(phone, mcc);
- }
- try {
- Configuration config = ActivityManagerNative.getDefault().getConfiguration();
if (mcc != 0) {
- config.mcc = mcc;
+ setTimezoneFromMccIfNeeded(phone, mcc);
+ setLocaleFromMccIfNeeded(phone, mcc);
+ setWifiChannelsFromMcc(phone, mcc);
}
- if (mnc != 0) {
- config.mnc = mnc;
+ try {
+ Configuration config = ActivityManagerNative.getDefault().getConfiguration();
+ if (mcc != 0) {
+ config.mcc = mcc;
+ }
+ if (mnc != 0) {
+ config.mnc = mnc;
+ }
+ ActivityManagerNative.getDefault().updateConfiguration(config);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Can't update configuration", e);
}
- ActivityManagerNative.getDefault().updateConfiguration(config);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Can't update configuration", e);
}
}
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 24f08cb..f14ab70 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -28,7 +28,7 @@ import android.telephony.SignalStrength;
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.gsm.NetworkInfo;
-import com.android.internal.telephony.gsm.PdpConnection;
+import com.android.internal.telephony.gsm.GsmDataConnection;
import com.android.internal.telephony.test.SimulatedRadioControl;
import java.util.List;
@@ -1199,21 +1199,7 @@ public interface Phone {
void invokeOemRilRequestStrings(String[] strings, Message response);
/**
- * Get the current active PDP context list
- *
- * @deprecated
- * @param response <strong>On success</strong>, "response" bytes is
- * made available as:
- * (String[])(((AsyncResult)response.obj).result).
- * <strong>On failure</strong>,
- * (((AsyncResult)response.obj).result) == null and
- * (((AsyncResult)response.obj).exception) being an instance of
- * com.android.internal.telephony.gsm.CommandException
- */
- void getPdpContextList(Message response);
-
- /**
- * Get the current active Data Call list, substitutes getPdpContextList
+ * Get the current active Data Call list
*
* @param response <strong>On success</strong>, "response" bytes is
* made available as:
@@ -1226,19 +1212,11 @@ public interface Phone {
void getDataCallList(Message response);
/**
- * Get current mutiple PDP link status
- *
- * @deprecated
- * @return list of pdp link connections
- */
- List<PdpConnection> getCurrentPdpList ();
-
- /**
* Get current mutiple data connection status
*
* @return list of data connections
*/
- List<DataConnection> getCurrentDataConnectionList ();
+ List<DataConnection> getCurrentDataConnectionList();
/**
* Update the ServiceState CellLocation for current network registration.
@@ -1434,11 +1412,6 @@ public interface Phone {
/* CDMA support methods */
- /*
- * TODO(Moto) TODO(Teleca): can getCdmaMin, getEsn, getMeid use more generic calls
- * already defined getXxxx above?
- */
-
/**
* Retrieves the MIN for CDMA phones.
*/
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index eb406b7..a8f4143 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -35,7 +35,7 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.internal.R;
-import com.android.internal.telephony.gsm.PdpConnection;
+import com.android.internal.telephony.gsm.GsmDataConnection;
import com.android.internal.telephony.test.SimulatedRadioControl;
import java.util.List;
@@ -114,6 +114,7 @@ public abstract class PhoneBase extends Handler implements Phone {
boolean mDoesRilSendMultipleCallRing;
int mCallRingContinueToken = 0;
int mCallRingDelay;
+ public boolean mIsTheCurrentActivePhone = true;
/**
* Set a system property, unless we're in unit test mode
@@ -226,6 +227,8 @@ public abstract class PhoneBase extends Handler implements Phone {
public void dispose() {
synchronized(PhoneProxy.lockForRadioTechnologyChange) {
mCM.unSetOnCallRing(this);
+ mDataConnection.onCleanUpConnection(false, REASON_RADIO_TURNED_OFF);
+ mIsTheCurrentActivePhone = false;
}
}
@@ -582,7 +585,7 @@ public abstract class PhoneBase extends Handler implements Phone {
/**
* Utility code to set the system locale if it's not set already
- * @param langauge Two character language code desired
+ * @param language Two character language code desired
* @param country Two character country code desired
*
* {@hide}
@@ -691,32 +694,22 @@ public abstract class PhoneBase extends Handler implements Phone {
public void setTTYMode(int ttyMode, Message onComplete) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("setTTYMode");
}
public void queryTTYMode(Message onComplete) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
- }
-
- /**
- * This should only be called in GSM mode.
- * Only here for some backward compatibility
- * issues concerning the GSMPhone class.
- * @deprecated Always returns null.
- */
- public List<PdpConnection> getCurrentPdpList() {
- return null;
+ logUnexpectedCdmaMethodCall("queryTTYMode");
}
public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("enableEnhancedVoicePrivacy");
}
public void getEnhancedVoicePrivacy(Message onComplete) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("getEnhancedVoicePrivacy");
}
public void setBandMode(int bandMode, Message response) {
@@ -761,7 +754,7 @@ public abstract class PhoneBase extends Handler implements Phone {
* Returns the CDMA ERI icon index to display
*/
public int getCdmaEriIconIndex() {
- Log.e(LOG_TAG, "Error! getCdmaEriIconIndex should never be executed in GSM mode");
+ logUnexpectedCdmaMethodCall("getCdmaEriIconIndex");
return -1;
}
@@ -771,7 +764,7 @@ public abstract class PhoneBase extends Handler implements Phone {
* 1 - FLASHING
*/
public int getCdmaEriIconMode() {
- Log.e(LOG_TAG, "Error! getCdmaEriIconMode should never be executed in GSM mode");
+ logUnexpectedCdmaMethodCall("getCdmaEriIconMode");
return -1;
}
@@ -779,82 +772,82 @@ public abstract class PhoneBase extends Handler implements Phone {
* Returns the CDMA ERI text,
*/
public String getCdmaEriText() {
- Log.e(LOG_TAG, "Error! getCdmaEriText should never be executed in GSM mode");
+ logUnexpectedCdmaMethodCall("getCdmaEriText");
return "GSM nw, no ERI";
}
public String getCdmaMin() {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("getCdmaMin");
return null;
}
public boolean isMinInfoReady() {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("isMinInfoReady");
return false;
}
public String getCdmaPrlVersion(){
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("getCdmaPrlVersion");
return null;
}
public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("sendBurstDtmf");
}
public void exitEmergencyCallbackMode() {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("exitEmergencyCallbackMode");
}
public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("registerForCdmaOtaStatusChange");
}
public void unregisterForCdmaOtaStatusChange(Handler h) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("unregisterForCdmaOtaStatusChange");
}
public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("registerForSubscriptionInfoReady");
}
public void unregisterForSubscriptionInfoReady(Handler h) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("unregisterForSubscriptionInfoReady");
}
public boolean isOtaSpNumber(String dialStr) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("isOtaSpNumber");
return false;
}
public void registerForCallWaiting(Handler h, int what, Object obj){
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("registerForCallWaiting");
}
public void unregisterForCallWaiting(Handler h){
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("unregisterForCallWaiting");
}
public void registerForEcmTimerReset(Handler h, int what, Object obj) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("registerForEcmTimerReset");
}
public void unregisterForEcmTimerReset(Handler h) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("unregisterForEcmTimerReset");
}
public void registerForSignalInfo(Handler h, int what, Object obj) {
@@ -915,12 +908,12 @@ public abstract class PhoneBase extends Handler implements Phone {
public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("setOnEcbModeExitResponse");
}
public void unsetOnEcbModeExitResponse(Handler h){
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
- Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ logUnexpectedCdmaMethodCall("unsetOnEcbModeExitResponse");
}
public String getInterfaceName(String apnType) {
@@ -991,7 +984,7 @@ public abstract class PhoneBase extends Handler implements Phone {
}
/**
- * Notifiy registrants of a new ringing Connection.
+ * Notify registrants of a new ringing Connection.
* Subclasses of Phone probably want to replace this with a
* version scoped to their packages
*/
@@ -1024,4 +1017,13 @@ public abstract class PhoneBase extends Handler implements Phone {
+ " mCallRingContinueToken=" + mCallRingContinueToken);
}
}
+
+ /**
+ * Common error logger method for unexpected calls to CDMA-only methods.
+ */
+ private void logUnexpectedCdmaMethodCall(String name)
+ {
+ Log.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
+ "called, CDMAPhone inactive.");
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
index 77c7c28..e1511e6 100644
--- a/telephony/java/com/android/internal/telephony/PhoneProxy.java
+++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java
@@ -23,6 +23,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Message;
+import android.os.SystemProperties;
import android.preference.PreferenceManager;
import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
@@ -33,15 +34,13 @@ 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.PdpConnection;
+import com.android.internal.telephony.gsm.GsmDataConnection;
import com.android.internal.telephony.test.SimulatedRadioControl;
import java.util.List;
public class PhoneProxy extends Handler implements Phone {
public final static Object lockForRadioTechnologyChange = new Object();
-// private static boolean radioTechnologyChangeGsmToCdma = false;
-// private static boolean radioTechnologyChangeCdmaToGsm = false;
private Phone mActivePhone;
private String mOutgoingPhone;
@@ -50,12 +49,16 @@ public class PhoneProxy extends Handler implements Phone {
private IccPhoneBookInterfaceManagerProxy mIccPhoneBookInterfaceManagerProxy;
private PhoneSubInfoProxy mPhoneSubInfoProxy;
+ private boolean mResetModemOnRadioTechnologyChange = false;
+
private static final int EVENT_RADIO_TECHNOLOGY_CHANGED = 1;
private static final String LOG_TAG = "PHONE";
//***** Class Methods
public PhoneProxy(Phone phone) {
mActivePhone = phone;
+ mResetModemOnRadioTechnologyChange = SystemProperties.getBoolean(
+ TelephonyProperties.PROPERTY_RESET_ON_RADIO_TECH_CHANGE, false);
mIccSmsInterfaceManagerProxy = new IccSmsInterfaceManagerProxy(
phone.getIccSmsInterfaceManager());
mIccPhoneBookInterfaceManagerProxy = new IccPhoneBookInterfaceManagerProxy(
@@ -74,12 +77,15 @@ public class PhoneProxy extends Handler implements Phone {
mOutgoingPhone = ((PhoneBase)mActivePhone).getPhoneName();
logd("Switching phone from " + mOutgoingPhone + "Phone to " +
(mOutgoingPhone.equals("GSM") ? "CDMAPhone" : "GSMPhone") );
- boolean oldPowerState = false; //old power state to off
- if (mCommandsInterface.getRadioState().isOn()) {
- oldPowerState = true;
- logd("Setting Radio Power to Off");
- mCommandsInterface.setRadioPower(false, null);
+ boolean oldPowerState = false; // old power state to off
+ if (mResetModemOnRadioTechnologyChange) {
+ if (mCommandsInterface.getRadioState().isOn()) {
+ oldPowerState = true;
+ logd("Setting Radio Power to Off");
+ mCommandsInterface.setRadioPower(false, null);
+ }
}
+
if(mOutgoingPhone.equals("GSM")) {
logd("Make a new CDMAPhone and destroy the old GSMPhone.");
@@ -93,8 +99,6 @@ public class PhoneProxy extends Handler implements Phone {
//System.gc();
mActivePhone = PhoneFactory.getCdmaPhone();
- logd("Resetting Radio");
- mCommandsInterface.setRadioPower(oldPowerState, null);
((GSMPhone)oldPhone).removeReferences();
oldPhone = null;
} else {
@@ -111,12 +115,15 @@ public class PhoneProxy extends Handler implements Phone {
//System.gc();
mActivePhone = PhoneFactory.getGsmPhone();
- logd("Resetting Radio:");
- mCommandsInterface.setRadioPower(oldPowerState, null);
((CDMAPhone)oldPhone).removeReferences();
oldPhone = null;
}
+ if (mResetModemOnRadioTechnologyChange) {
+ logd("Resetting Radio");
+ mCommandsInterface.setRadioPower(oldPowerState, null);
+ }
+
//Set the new interfaces in the proxy's
mIccSmsInterfaceManagerProxy.setmIccSmsInterfaceManager(
mActivePhone.getIccSmsInterfaceManager());
@@ -127,6 +134,7 @@ public class PhoneProxy extends Handler implements Phone {
//Send an Intent to the PhoneApp that we had a radio technology change
Intent intent = new Intent(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(Phone.PHONE_NAME_KEY, mActivePhone.getPhoneName());
ActivityManagerNative.broadcastStickyIntent(intent, null);
break;
@@ -568,24 +576,10 @@ public class PhoneProxy extends Handler implements Phone {
mActivePhone.invokeOemRilRequestStrings(strings, response);
}
- /**
- * @deprecated
- */
- public void getPdpContextList(Message response) {
- mActivePhone.getPdpContextList(response);
- }
-
public void getDataCallList(Message response) {
mActivePhone.getDataCallList(response);
}
- /**
- * @deprecated
- */
- public List<PdpConnection> getCurrentPdpList() {
- return mActivePhone.getCurrentPdpList();
- }
-
public List<DataConnection> getCurrentDataConnectionList() {
return mActivePhone.getCurrentDataConnectionList();
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneSubInfo.java b/telephony/java/com/android/internal/telephony/PhoneSubInfo.java
index 19900c8..1ac2da3 100644
--- a/telephony/java/com/android/internal/telephony/PhoneSubInfo.java
+++ b/telephony/java/com/android/internal/telephony/PhoneSubInfo.java
@@ -39,6 +39,11 @@ public class PhoneSubInfo extends IPhoneSubInfo.Stub {
}
protected void finalize() {
+ try {
+ super.finalize();
+ } catch (Throwable throwable) {
+ Log.e(LOG_TAG, "Error while finalizing:", throwable);
+ }
Log.d(LOG_TAG, "PhoneSubInfo finalized");
}
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 7239889..3d410fd 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -208,7 +208,12 @@ public final class RIL extends BaseCommands implements CommandsInterface {
private static final boolean DBG = false;
static final boolean RILJ_LOGD = Config.LOGD;
static final boolean RILJ_LOGV = DBG ? Config.LOGD : Config.LOGV;
- static int WAKE_LOCK_TIMEOUT = 5000;
+
+ /**
+ * Wake lock timeout should be longer than the longest timeout in
+ * the vendor ril.
+ */
+ private static final int DEFAULT_WAKE_LOCK_TIMEOUT = 30000;
//***** Instance Variables
@@ -219,6 +224,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
RILReceiver mReceiver;
private Context mContext;
WakeLock mWakeLock;
+ int mWakeLockTimeout;
int mRequestMessagesPending;
// Is this the first radio state change?
@@ -603,6 +609,8 @@ public final class RIL extends BaseCommands implements CommandsInterface {
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
mWakeLock.setReferenceCounted(false);
+ mWakeLockTimeout = SystemProperties.getInt(TelephonyProperties.PROPERTY_WAKE_LOCK_TIMEOUT,
+ DEFAULT_WAKE_LOCK_TIMEOUT);
mRequestMessagesPending = 0;
mContext = context;
@@ -797,6 +805,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
rr.mp.writeString(address);
rr.mp.writeInt(clirMode);
+ rr.mp.writeInt(0); // UUS information is absent
if (uusInfo == null) {
rr.mp.writeInt(0); // UUS information is absent
@@ -2010,7 +2019,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
mSender.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
Message msg = mSender.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
- mSender.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT);
+ mSender.sendMessageDelayed(msg, mWakeLockTimeout);
}
}
@@ -2197,6 +2206,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
case RIL_REQUEST_SET_SMSC_ADDRESS: ret = responseVoid(p); break;
case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
case RIL_REQUEST_REPORT_SMS_MEMORY_STATUS: ret = responseVoid(p); break;
+ case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING: ret = responseVoid(p); break;
default:
throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest);
//break;
@@ -2997,10 +3007,9 @@ public final class RIL extends BaseCommands implements CommandsInterface {
numServiceCategories = p.readInt();
if (numServiceCategories == 0) {
- // TODO(Teleca) TODO(Moto): The logic of providing default
- // values should not be done by this transport layer. And
- // needs to be done by the vendor ril or application logic.
- // TODO(Google): Remove ASAP
+ // TODO: The logic of providing default values should
+ // not be done by this transport layer. And needs to
+ // be done by the vendor ril or application logic.
int numInts;
numInts = CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES * CDMA_BSI_NO_OF_INTS_STRUCT + 1;
response = new int[numInts];
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index be1fbf1..71a80e0 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -50,6 +50,9 @@ public interface RILConstants {
location */
int MODE_NOT_SUPPORTED = 13; /* HW does not support preferred network type */
int FDN_CHECK_FAILURE = 14; /* send operation barred error when FDN is enabled */
+ int ILLEGAL_SIM_OR_ME = 15; /* network selection failure due
+ to wrong SIM/ME and no
+ retries needed */
/* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */
int NETWORK_MODE_WCDMA_PREF = 0; /* GSM/WCDMA (WCDMA preferred) */
diff --git a/telephony/java/com/android/internal/telephony/RetryManager.java b/telephony/java/com/android/internal/telephony/RetryManager.java
index 385b191..779f358 100644
--- a/telephony/java/com/android/internal/telephony/RetryManager.java
+++ b/telephony/java/com/android/internal/telephony/RetryManager.java
@@ -153,13 +153,17 @@ public class RetryManager {
}
/**
- * Configure for using string which allow arbitary
+ * Configure for using string which allow arbitrary
* sequences of times. See class comments for the
* string format.
*
- * @return true if successfull
+ * @return true if successful
*/
public boolean configure(String configStr) {
+ // Strip quotes if present.
+ if ((configStr.startsWith("\"") && configStr.endsWith("\""))) {
+ configStr = configStr.substring(1, configStr.length()-1);
+ }
if (DBG) log("configure: '" + configStr + "'");
if (!TextUtils.isEmpty(configStr)) {
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
index 98d4b1d..ca526a5 100644
--- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -232,11 +232,11 @@ public abstract class SMSDispatcher extends Handler {
createWakelock();
- int check_period = Settings.Gservices.getInt(mResolver,
- Settings.Gservices.SMS_OUTGOING_CHECK_INTERVAL_MS,
+ int check_period = Settings.Secure.getInt(mResolver,
+ Settings.Secure.SMS_OUTGOING_CHECK_INTERVAL_MS,
DEFAULT_SMS_CHECK_PERIOD);
- int max_count = Settings.Gservices.getInt(mResolver,
- Settings.Gservices.SMS_OUTGOING_CEHCK_MAX_COUNT,
+ int max_count = Settings.Secure.getInt(mResolver,
+ Settings.Secure.SMS_OUTGOING_CHECK_MAX_COUNT,
DEFAULT_SMS_MAX_COUNT);
mCounter = new SmsCounter(max_count, check_period);
diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
index be4fdb4..706f260 100644
--- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -272,6 +272,13 @@ public abstract class ServiceStateTracker extends Handler {
protected abstract void updateSpnDisplay();
protected abstract void setPowerStateToDesired();
+ /**
+ * Clean up existing voice and data connection then turn off radio power.
+ *
+ * Hang up the existing voice calls to decrease call drop rate.
+ */
+ protected abstract void powerOffRadioSafely();
+
/** Cancel a pending (if any) pollState() operation */
protected void cancelPollState() {
// This will effectively cancel the rest of the poll requests.
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index 3c2f2ed..af6c5f8 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -21,6 +21,7 @@ import com.android.internal.telephony.SmsHeader;
import java.util.Arrays;
import static android.telephony.SmsMessage.MessageClass;
+import android.provider.Telephony;
/**
* Base class declaring the specific methods and members for SmsMessage.
@@ -386,7 +387,7 @@ public abstract class SmsMessageBase {
if (parts.length < 2) return;
emailFrom = parts[0];
emailBody = parts[1];
- isEmail = true;
+ isEmail = Telephony.Mms.isEmailAddress(emailFrom);
}
}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyEventLog.java b/telephony/java/com/android/internal/telephony/TelephonyEventLog.java
deleted file mode 100644
index 0f15cb6..0000000
--- a/telephony/java/com/android/internal/telephony/TelephonyEventLog.java
+++ /dev/null
@@ -1,36 +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;
-
-/* This class contains the details related to Telephony Event Logging */
-public final class TelephonyEventLog {
-
- /* Event log tags */
- public static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
- public static final int EVENT_LOG_RADIO_RESET_COUNTDOWN_TRIGGERED = 50101;
- public static final int EVENT_LOG_RADIO_RESET = 50102;
- public static final int EVENT_LOG_PDP_RESET = 50103;
- public static final int EVENT_LOG_REREGISTER_NETWORK = 50104;
- public static final int EVENT_LOG_RADIO_PDP_SETUP_FAIL = 50105;
- public static final int EVENT_LOG_CALL_DROP = 50106;
- public static final int EVENT_LOG_CGREG_FAIL = 50107;
- public static final int EVENT_LOG_DATA_STATE_RADIO_OFF = 50108;
- public static final int EVENT_LOG_PDP_NETWORK_DROP = 50109;
- public static final int EVENT_LOG_CDMA_DATA_SETUP_FAILED = 50110;
- public static final int EVENT_LOG_CDMA_DATA_DROP = 50111;
- public static final int EVENT_LOG_GSM_RAT_SWITCHED = 50112;
-}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 2216ec4..3355e8a 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -1,3 +1,19 @@
+/*
+ * 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;
/**
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 55ba149..a113787 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -136,4 +136,15 @@ public interface TelephonyProperties
* monotonically, regardless of reboots.
*/
static final String PROPERTY_CDMA_MSG_ID = "persist.radio.cdma.msgid";
+
+ /**
+ * Property to override DEFAULT_WAKE_LOCK_TIMEOUT
+ */
+ static final String PROPERTY_WAKE_LOCK_TIMEOUT = "ro.ril.wake_lock_timeout";
+
+ /**
+ * Set to true to indicate that the modem needs to be reset
+ * when there is a radio technology change.
+ */
+ static final String PROPERTY_RESET_ON_RADIO_TECH_CHANGE = "persist.radio.reset_on_switch";
}
diff --git a/telephony/java/com/android/internal/telephony/WapPushOverSms.java b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
index 9970940..a636a4b 100644
--- a/telephony/java/com/android/internal/telephony/WapPushOverSms.java
+++ b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
@@ -109,6 +109,7 @@ public class WapPushOverSms {
String mimeType = pduDecoder.getValueString();
if (mimeType == null) {
binaryContentType = (int)pduDecoder.getValue32();
+ // TODO we should have more generic way to map binaryContentType code to mimeType.
switch (binaryContentType) {
case WspTypeDecoder.CONTENT_TYPE_B_DRM_RIGHTS_XML:
mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_DRM_RIGHTS_XML;
@@ -128,6 +129,9 @@ public class WapPushOverSms {
case WspTypeDecoder.CONTENT_TYPE_B_MMS:
mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS;
break;
+ case WspTypeDecoder.CONTENT_TYPE_B_VND_DOCOMO_PF:
+ mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_VND_DOCOMO_PF;
+ break;
default:
if (Config.LOGD) {
Log.w(LOG_TAG,
@@ -148,6 +152,8 @@ public class WapPushOverSms {
binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO;
} else if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS)) {
binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_MMS;
+ } else if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_VND_DOCOMO_PF)) {
+ binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_VND_DOCOMO_PF;
} else {
if (Config.LOGD) Log.w(LOG_TAG, "Received PDU. Unknown Content-Type = " + mimeType);
return Intents.RESULT_SMS_HANDLED;
@@ -155,28 +161,31 @@ public class WapPushOverSms {
}
index += pduDecoder.getDecodedDataLength();
- int dataIndex = headerStartIndex + headerLength;
boolean dispatchedByApplication = false;
switch (binaryContentType) {
case WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO:
- dispatchWapPdu_PushCO(pdu, transactionId, pduType);
+ dispatchWapPdu_PushCO(pdu, transactionId, pduType, headerStartIndex, headerLength);
dispatchedByApplication = true;
break;
case WspTypeDecoder.CONTENT_TYPE_B_MMS:
- dispatchWapPdu_MMS(pdu, transactionId, pduType, dataIndex);
+ dispatchWapPdu_MMS(pdu, transactionId, pduType, headerStartIndex, headerLength);
dispatchedByApplication = true;
break;
default:
break;
}
if (dispatchedByApplication == false) {
- dispatchWapPdu_default(pdu, transactionId, pduType, mimeType, dataIndex);
+ dispatchWapPdu_default(pdu, transactionId, pduType, mimeType,
+ headerStartIndex, headerLength);
}
return Activity.RESULT_OK;
}
- private void dispatchWapPdu_default(
- byte[] pdu, int transactionId, int pduType, String mimeType, int dataIndex) {
+ private void dispatchWapPdu_default(byte[] pdu, int transactionId, int pduType,
+ String mimeType, int headerStartIndex, int headerLength) {
+ byte[] header = new byte[headerLength];
+ System.arraycopy(pdu, headerStartIndex, header, 0, header.length);
+ int dataIndex = headerStartIndex + headerLength;
byte[] data;
data = new byte[pdu.length - dataIndex];
@@ -186,31 +195,40 @@ public class WapPushOverSms {
intent.setType(mimeType);
intent.putExtra("transactionId", transactionId);
intent.putExtra("pduType", pduType);
+ intent.putExtra("header", header);
intent.putExtra("data", data);
mSmsDispatcher.dispatch(intent, "android.permission.RECEIVE_WAP_PUSH");
}
- private void dispatchWapPdu_PushCO(byte[] pdu, int transactionId, int pduType) {
+ private void dispatchWapPdu_PushCO(byte[] pdu, int transactionId, int pduType,
+ int headerStartIndex, int headerLength) {
+ byte[] header = new byte[headerLength];
+ System.arraycopy(pdu, headerStartIndex, header, 0, header.length);
+
Intent intent = new Intent(Intents.WAP_PUSH_RECEIVED_ACTION);
intent.setType(WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_CO);
intent.putExtra("transactionId", transactionId);
intent.putExtra("pduType", pduType);
+ intent.putExtra("header", header);
intent.putExtra("data", pdu);
mSmsDispatcher.dispatch(intent, "android.permission.RECEIVE_WAP_PUSH");
}
- private void dispatchWapPdu_MMS(byte[] pdu, int transactionId, int pduType, int dataIndex) {
- byte[] data;
-
- data = new byte[pdu.length - dataIndex];
+ private void dispatchWapPdu_MMS(byte[] pdu, int transactionId, int pduType,
+ int headerStartIndex, int headerLength) {
+ byte[] header = new byte[headerLength];
+ System.arraycopy(pdu, headerStartIndex, header, 0, header.length);
+ int dataIndex = headerStartIndex + headerLength;
+ byte[] data = new byte[pdu.length - dataIndex];
System.arraycopy(pdu, dataIndex, data, 0, data.length);
Intent intent = new Intent(Intents.WAP_PUSH_RECEIVED_ACTION);
intent.setType(WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS);
intent.putExtra("transactionId", transactionId);
intent.putExtra("pduType", pduType);
+ intent.putExtra("header", header);
intent.putExtra("data", data);
mSmsDispatcher.dispatch(intent, "android.permission.RECEIVE_MMS");
diff --git a/telephony/java/com/android/internal/telephony/WspTypeDecoder.java b/telephony/java/com/android/internal/telephony/WspTypeDecoder.java
index 3bbe0e1..336bc82 100644
--- a/telephony/java/com/android/internal/telephony/WspTypeDecoder.java
+++ b/telephony/java/com/android/internal/telephony/WspTypeDecoder.java
@@ -30,12 +30,16 @@ public class WspTypeDecoder {
public static final int PDU_TYPE_PUSH = 0x06;
public static final int PDU_TYPE_CONFIRMED_PUSH = 0x07;
+ // TODO we should have mapping between those binary code and mime type string.
+ // see http://www.openmobilealliance.org/tech/omna/omna-wsp-content-type.aspx
+
public static final int CONTENT_TYPE_B_DRM_RIGHTS_XML = 0x4a;
public static final int CONTENT_TYPE_B_DRM_RIGHTS_WBXML = 0x4b;
public static final int CONTENT_TYPE_B_PUSH_SI = 0x2e;
public static final int CONTENT_TYPE_B_PUSH_SL = 0x30;
public static final int CONTENT_TYPE_B_PUSH_CO = 0x32;
public static final int CONTENT_TYPE_B_MMS = 0x3e;
+ public static final int CONTENT_TYPE_B_VND_DOCOMO_PF = 0x0310;
public static final String CONTENT_MIME_TYPE_B_DRM_RIGHTS_XML =
"application/vnd.oma.drm.rights+xml";
@@ -45,6 +49,7 @@ public class WspTypeDecoder {
public static final String CONTENT_MIME_TYPE_B_PUSH_SL = "application/vnd.wap.slc";
public static final String CONTENT_MIME_TYPE_B_PUSH_CO = "application/vnd.wap.coc";
public static final String CONTENT_MIME_TYPE_B_MMS = "application/vnd.wap.mms-message";
+ public static final String CONTENT_MIME_TYPE_B_VND_DOCOMO_PF = "application/vnd.docomo.pf";
public static final int PARAMETER_ID_X_WAP_APPLICATION_ID = 0x2f;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index ea80ea4..0c591e4 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -205,10 +205,6 @@ public class CDMAPhone extends PhoneBase {
// Sets current entry in the telephony carrier table
updateCurrentCarrierInProvider(operatorNumeric);
- // Updates MCC MNC device configuration information
- MccTable.updateMccMncConfiguration(this, operatorNumeric);
-
-
// Notify voicemails.
notifier.notifyMessageWaitingChanged(this);
}
@@ -266,12 +262,6 @@ public class CDMAPhone extends PhoneBase {
}
public ServiceState getServiceState() {
- int roamInd = mSST.ss.getCdmaRoamingIndicator();
- int defRoamInd = mSST.ss.getCdmaDefaultRoamingIndicator();
-
- mSST.ss.setCdmaEriIconIndex(mEriManager.getCdmaEriIconIndex(roamInd, defRoamInd));
- mSST.ss.setCdmaEriIconMode(mEriManager.getCdmaEriIconMode(roamInd, defRoamInd));
-
return mSST.ss;
}
@@ -615,15 +605,7 @@ public class CDMAPhone extends PhoneBase {
public DataState getDataConnectionState() {
DataState ret = DataState.DISCONNECTED;
- if ((SystemProperties.get("adb.connected", "").length() > 0)
- && (SystemProperties.get("android.net.use-adb-networking", "")
- .length() > 0)) {
- // We're connected to an ADB host and we have USB networking
- // turned on. No matter what the radio state is,
- // we report data connected
-
- ret = DataState.CONNECTED;
- } else if (mSST == null) {
+ if (mSST == null) {
// Radio Technology Change is ongoning, dispose() and removeReferences() have
// already been called
@@ -719,13 +701,6 @@ public class CDMAPhone extends PhoneBase {
mSST.disableLocationUpdates();
}
- /**
- * @deprecated
- */
- public void getPdpContextList(Message response) {
- getDataCallList(response);
- }
-
public void getDataCallList(Message response) {
mCM.getDataCallList(response);
}
@@ -750,7 +725,7 @@ public class CDMAPhone extends PhoneBase {
public String getVoiceMailNumber() {
String number = null;
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
- // TODO(Moto): The default value of voicemail number should be read from a system property
+ // TODO: The default value of voicemail number should be read from a system property
number = sp.getString(VM_NUMBER_CDMA, "*86");
return number;
}
@@ -852,10 +827,6 @@ public class CDMAPhone extends PhoneBase {
}
void notifyServiceStateChanged(ServiceState ss) {
- // TODO this seems really inefficient. Can't we calc this when the fundamentals change and store in the
- // service state?
- ss.setCdmaEriIconIndex(this.getCdmaEriIconIndex());
- ss.setCdmaEriIconMode(this.getCdmaEriIconMode());
super.notifyServiceStateChangedP(ss);
}
@@ -1385,7 +1356,7 @@ public class CDMAPhone extends PhoneBase {
@Override
public boolean isOtaSpNumber(String dialStr){
boolean isOtaSpNum = false;
- String dialableStr = PhoneNumberUtils.extractNetworkPortion(dialStr);
+ String dialableStr = PhoneNumberUtils.extractNetworkPortionAlt(dialStr);
if (dialableStr != null) {
isOtaSpNum = isIs683OtaSpDialStr(dialableStr);
if (isOtaSpNum == false) {
@@ -1398,9 +1369,7 @@ public class CDMAPhone extends PhoneBase {
@Override
public int getCdmaEriIconIndex() {
- int roamInd = getServiceState().getCdmaRoamingIndicator();
- int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
- return mEriManager.getCdmaEriIconIndex(roamInd, defRoamInd);
+ return getServiceState().getCdmaEriIconIndex();
}
/**
@@ -1410,9 +1379,7 @@ public class CDMAPhone extends PhoneBase {
*/
@Override
public int getCdmaEriIconMode() {
- int roamInd = getServiceState().getCdmaRoamingIndicator();
- int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
- return mEriManager.getCdmaEriIconMode(roamInd, defRoamInd);
+ return getServiceState().getCdmaEriIconMode();
}
/**
@@ -1459,20 +1426,22 @@ public class CDMAPhone extends PhoneBase {
}
/**
- * Sets the "current" field in the telephony provider according to the build-time
- * operator numeric property
+ * Sets the "current" field in the telephony provider according to the
+ * build-time operator numeric property
*
* @return true for success; false otherwise.
*/
- // TODO(Moto): move this method into PhoneBase, since it looks identical to
- // the one in GsmPhone
- private boolean updateCurrentCarrierInProvider(String operatorNumeric) {
+ boolean updateCurrentCarrierInProvider(String operatorNumeric) {
if (!TextUtils.isEmpty(operatorNumeric)) {
try {
Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
ContentValues map = new ContentValues();
map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
getContext().getContentResolver().insert(uri, map);
+
+ // Updates MCC MNC device configuration information
+ MccTable.updateMccMncConfiguration(this, operatorNumeric);
+
return true;
} catch (SQLException e) {
Log.e(LOG_TAG, "Can't store current operator", e);
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index 81dec21..fbe455e 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -154,7 +154,7 @@ public class CdmaConnection extends Connection {
dialString = formatDialString(dialString);
Log.d(LOG_TAG, "[CDMAConn] CdmaConnection:formated dialString=" + dialString);
- this.address = PhoneNumberUtils.extractNetworkPortion(dialString);
+ this.address = PhoneNumberUtils.extractNetworkPortionAlt(dialString);
this.postDialString = PhoneNumberUtils.extractPostDialPortion(dialString);
index = -1;
@@ -592,8 +592,11 @@ public class CdmaConnection extends Connection {
if (!isIncoming) {
// outgoing calls only
processNextPostDialChar();
+ } else {
+ // Only release wake lock for incoming calls, for outgoing calls the wake lock
+ // will be released after any pause-dial is completed
+ releaseWakeLock();
}
- releaseWakeLock();
}
private void
@@ -688,6 +691,7 @@ public class CdmaConnection extends Connection {
Registrant postDialHandler;
if (postDialState == PostDialState.CANCELLED) {
+ releaseWakeLock();
//Log.v("CDMA", "##### processNextPostDialChar: postDialState == CANCELLED, bail");
return;
}
@@ -696,6 +700,9 @@ public class CdmaConnection extends Connection {
postDialString.length() <= nextPostDialChar) {
setPostDialState(PostDialState.COMPLETE);
+ // We were holding a wake lock until pause-dial was complete, so give it up now
+ releaseWakeLock();
+
// notifyMessage.arg1 is 0 on complete
c = 0;
} else {
@@ -770,19 +777,24 @@ public class CdmaConnection extends Connection {
}
/**
- * Set post dial state and acquire wake lock while switching to "started"
- * state, the wake lock will be released if state switches out of "started"
+ * Set post dial state and acquire wake lock while switching to "started" or "wait"
+ * state, the wake lock will be released if state switches out of "started" or "wait"
* state or after WAKE_LOCK_TIMEOUT_MILLIS.
* @param s new PostDialState
*/
private void setPostDialState(PostDialState s) {
- if (postDialState != PostDialState.STARTED
- && s == PostDialState.STARTED) {
- acquireWakeLock();
- Message msg = h.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
- h.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
- } else if (postDialState == PostDialState.STARTED
- && s != PostDialState.STARTED) {
+ if (s == PostDialState.STARTED ||
+ s == PostDialState.PAUSE) {
+ synchronized (mPartialWakeLock) {
+ if (mPartialWakeLock.isHeld()) {
+ h.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
+ } else {
+ acquireWakeLock();
+ }
+ Message msg = h.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
+ h.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
+ }
+ } else {
h.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
releaseWakeLock();
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
index 4588f36..95cb1c6 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -16,221 +16,87 @@
package com.android.internal.telephony.cdma;
-import android.os.*;
-import android.util.EventLog;
+import android.os.Message;
import android.util.Log;
-import com.android.internal.telephony.CommandException;
-import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.DataConnection;
-import com.android.internal.telephony.DataLink;
+import com.android.internal.telephony.gsm.ApnSetting;
+import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RILConstants;
-import com.android.internal.telephony.TelephonyEventLog;
/**
* {@hide}
- *
*/
public class CdmaDataConnection extends DataConnection {
private static final String LOG_TAG = "CDMA";
- private static final boolean DBG = true;
/** Fail cause of last Data Call activate from RIL_LastDataCallActivateFailCause */
private final static int PS_NET_DOWN_REASON_OPERATOR_DETERMINED_BARRING = 8;
- private final static int PS_NET_DOWN_REASON_UNKNOWN_APN = 27;
private final static int PS_NET_DOWN_REASON_AUTH_FAILED = 29;
private final static int PS_NET_DOWN_REASON_OPTION_NOT_SUPPORTED = 32;
private final static int PS_NET_DOWN_REASON_OPTION_UNSUBSCRIBED = 33;
-/** It is likely that the number of error codes listed below will be removed
- * in the foreseeable future. They have been added, but not agreed upon.
- *
- */
- private final static int PS_NET_DOWN_REASON_NOT_SPECIFIED = 0;
- private final static int PS_NET_DOWN_REASON_CLOSE_IN_PROGRESS = 1;
- private final static int PS_NET_DOWN_REASON_NW_INITIATED_TERMINATION = 2;
- private final static int PS_NET_DOWN_REASON_APP_PREEMPTED = 3;
- private final static int PS_NET_DOWN_REASON_LLC_SNDCP_FAILURE = 25;
- private final static int PS_NET_DOWN_REASON_INSUFFICIENT_RESOURCES = 26;
- private final static int PS_NET_DOWN_REASON_UNKNOWN_PDP = 28;
- private final static int PS_NET_DOWN_REASON_GGSN_REJECT = 30;
- private final static int PS_NET_DOWN_REASON_ACTIVATION_REJECT = 31;
- private final static int PS_NET_DOWN_REASON_OPTION_TEMP_OOO = 34;
- private final static int PS_NET_DOWN_REASON_NSAPI_ALREADY_USED = 35;
- private final static int PS_NET_DOWN_REASON_REGULAR_DEACTIVATION = 36;
- private final static int PS_NET_DOWN_REASON_QOS_NOT_ACCEPTED = 37;
- private final static int PS_NET_DOWN_REASON_NETWORK_FAILURE = 38;
- private final static int PS_NET_DOWN_REASON_UMTS_REATTACH_REQ = 39;
- private final static int PS_NET_DOWN_REASON_TFT_SEMANTIC_ERROR = 41;
- private final static int PS_NET_DOWN_REASON_TFT_SYNTAX_ERROR = 42;
- private final static int PS_NET_DOWN_REASON_UNKNOWN_PDP_CONTEXT = 43;
- private final static int PS_NET_DOWN_REASON_FILTER_SEMANTIC_ERROR = 44;
- private final static int PS_NET_DOWN_REASON_FILTER_SYNTAX_ERROR = 45;
- private final static int PS_NET_DOWN_REASON_PDP_WITHOUT_ACTIVE_TFT = 46;
- private final static int PS_NET_DOWN_REASON_INVALID_TRANSACTION_ID = 81;
- private final static int PS_NET_DOWN_REASON_MESSAGE_INCORRECT_SEMANTIC = 95;
- private final static int PS_NET_DOWN_REASON_INVALID_MANDATORY_INFO = 96;
- private final static int PS_NET_DOWN_REASON_MESSAGE_TYPE_UNSUPPORTED = 97;
- private final static int PS_NET_DOWN_REASON_MSG_TYPE_NONCOMPATIBLE_STATE = 98;
- private final static int PS_NET_DOWN_REASON_UNKNOWN_INFO_ELEMENT = 99;
- private final static int PS_NET_DOWN_REASON_CONDITIONAL_IE_ERROR = 100;
- private final static int PS_NET_DOWN_REASON_MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE = 101;
- private final static int PS_NET_DOWN_REASON_PROTOCOL_ERROR = 111;
- private final static int PS_NET_DOWN_REASON_APN_TYPE_CONFLICT = 112;
- private final static int PS_NET_DOWN_REASON_UNKNOWN_CAUSE_CODE = 113;
- private final static int PS_NET_DOWN_REASON_INTERNAL_MIN = 200;
- private final static int PS_NET_DOWN_REASON_INTERNAL_ERROR = 201;
- private final static int PS_NET_DOWN_REASON_INTERNAL_CALL_ENDED = 202;
- private final static int PS_NET_DOWN_REASON_INTERNAL_UNKNOWN_CAUSE_CODE = 203;
- private final static int PS_NET_DOWN_REASON_INTERNAL_MAX = 204;
- private final static int PS_NET_DOWN_REASON_CDMA_LOCK = 500;
- private final static int PS_NET_DOWN_REASON_INTERCEPT = 501;
- private final static int PS_NET_DOWN_REASON_REORDER = 502;
- private final static int PS_NET_DOWN_REASON_REL_SO_REJ = 503;
- private final static int PS_NET_DOWN_REASON_INCOM_CALL = 504;
- private final static int PS_NET_DOWN_REASON_ALERT_STOP = 505;
- private final static int PS_NET_DOWN_REASON_ACTIVATION = 506;
- private final static int PS_NET_DOWN_REASON_MAX_ACCESS_PROBE = 507;
- private final static int PS_NET_DOWN_REASON_CCS_NOT_SUPPORTED_BY_BS = 508;
- private final static int PS_NET_DOWN_REASON_NO_RESPONSE_FROM_BS = 509;
- private final static int PS_NET_DOWN_REASON_REJECTED_BY_BS = 510;
- private final static int PS_NET_DOWN_REASON_INCOMPATIBLE = 511;
- private final static int PS_NET_DOWN_REASON_ALREADY_IN_TC = 512;
- private final static int PS_NET_DOWN_REASON_USER_CALL_ORIG_DURING_GPS = 513;
- private final static int PS_NET_DOWN_REASON_USER_CALL_ORIG_DURING_SMS = 514;
- private final static int PS_NET_DOWN_REASON_NO_CDMA_SRV = 515;
- private final static int PS_NET_DOWN_REASON_CONF_FAILED = 1000;
- private final static int PS_NET_DOWN_REASON_INCOM_REJ = 1001;
- private final static int PS_NET_DOWN_REASON_NO_GW_SRV = 1002;
- private final static int PS_NET_DOWN_REASON_CD_GEN_OR_BUSY = 1500;
- private final static int PS_NET_DOWN_REASON_CD_BILL_OR_AUTH = 1501;
- private final static int PS_NET_DOWN_REASON_CHG_HDR = 1502;
- private final static int PS_NET_DOWN_REASON_EXIT_HDR = 1503;
- private final static int PS_NET_DOWN_REASON_HDR_NO_SESSION = 1504;
- private final static int PS_NET_DOWN_REASON_HDR_ORIG_DURING_GPS_FIX = 1505;
- private final static int PS_NET_DOWN_REASON_HDR_CS_TIMEOUT = 1506;
- private final static int PS_NET_DOWN_REASON_HDR_RELEASED_BY_CM = 1507;
- private final static int PS_NET_DOWN_REASON_CLIENT_END = 2000;
- private final static int PS_NET_DOWN_REASON_NO_SRV = 2001;
- private final static int PS_NET_DOWN_REASON_FADE = 2002;
- private final static int PS_NET_DOWN_REASON_REL_NORMAL = 2003;
- private final static int PS_NET_DOWN_REASON_ACC_IN_PROG = 2004;
- private final static int PS_NET_DOWN_REASON_ACC_FAIL = 2005;
- private final static int PS_NET_DOWN_REASON_REDIR_OR_HANDOFF = 2006;
-
- // ***** Instance Variables
// ***** Constructor
- CdmaDataConnection(CDMAPhone phone) {
- super(phone);
+ private CdmaDataConnection(CDMAPhone phone, String name) {
+ super(phone, name);
+ }
- if (DBG) log("CdmaDataConnection <constructor>");
+ /**
+ * Create the connection object
+ *
+ * @param phone
+ * @return CdmaDataConnection that was created.
+ */
+ static CdmaDataConnection makeDataConnection(CDMAPhone phone) {
+ synchronized (mCountLock) {
+ mCount += 1;
+ }
+ CdmaDataConnection cdmaDc = new CdmaDataConnection(phone, "CdmaDataConnection-" + mCount);
+ cdmaDc.start();
+ if (DBG) cdmaDc.log("Made " + cdmaDc.getName());
+ return cdmaDc;
}
/**
- * Setup a data connection
+ * Begin setting up a data connection, calls setupDataCall
+ * and the ConnectionParams will be returned with the
+ * EVENT_SETUP_DATA_CONNECTION_DONE AsyncResul.userObj.
*
- * @param onCompleted
- * notify success or not after down
+ * @param cp is the connection parameters
*/
- void connect(Message onCompleted) {
+ @Override
+ protected void onConnect(ConnectionParams cp) {
if (DBG) log("CdmaDataConnection Connecting...");
- state = State.ACTIVATING;
- onConnectCompleted = onCompleted;
createTime = -1;
lastFailTime = -1;
lastFailCause = FailCause.NONE;
- receivedDisconnectReq = false;
- phone.mCM.setupDataCall(Integer.toString(RILConstants.SETUP_DATA_TECH_CDMA),
- Integer.toString(RILConstants.DATA_PROFILE_DEFAULT), null, null,
- null, Integer.toString(RILConstants.SETUP_DATA_AUTH_PAP_CHAP),
- obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
- }
-
- private void tearDownData(Message msg) {
- if (phone.mCM.getRadioState().isOn()) {
- phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, msg));
- }
- }
-
- protected void disconnect(Message msg) {
- onDisconnect = msg;
- if (state == State.ACTIVE) {
- tearDownData(msg);
- } else if (state == State.ACTIVATING) {
- receivedDisconnectReq = true;
+ int dataProfile;
+ if ((cp.apn != null) && (cp.apn.types.length > 0) && (cp.apn.types[0] != null) &&
+ (cp.apn.types[0].equals(Phone.APN_TYPE_DUN))) {
+ if (DBG) log("CdmaDataConnection using DUN");
+ dataProfile = RILConstants.DATA_PROFILE_TETHERED;
} else {
- // state == INACTIVE. Nothing to do, so notify immediately.
- notifyDisconnect(msg);
- }
- }
-
-
- public String toString() {
- return "State=" + state + " create=" + createTime + " lastFail="
- + lastFailTime + " lastFailCause=" + lastFailCause;
- }
-
-
- protected void notifyFail(FailCause cause, Message onCompleted) {
- if (onCompleted == null) {
- return;
- }
- state = State.INACTIVE;
- lastFailCause = cause;
- lastFailTime = System.currentTimeMillis();
- onConnectCompleted = null;
-
- if(DBG) {
- log("Notify data connection fail at " + lastFailTime +
- " due to " + lastFailCause);
+ dataProfile = RILConstants.DATA_PROFILE_DEFAULT;
}
- AsyncResult.forMessage(onCompleted, cause, new Exception());
- onCompleted.sendToTarget();
- }
-
- protected void notifySuccess(Message onCompleted) {
- if (onCompleted == null) {
- return;
- }
-
- state = State.ACTIVE;
- createTime = System.currentTimeMillis();
- onConnectCompleted = null;
- onCompleted.arg1 = cid;
-
- if (DBG) log("Notify data connection success at " + createTime);
-
- AsyncResult.forMessage(onCompleted);
- onCompleted.sendToTarget();
- }
-
- protected void notifyDisconnect(Message msg) {
- if (DBG) log("Notify data connection disconnect");
-
- if (msg != null) {
- AsyncResult.forMessage(msg);
- msg.sendToTarget();
- }
- clearSettings();
+ // msg.obj will be returned in AsyncResult.userObj;
+ Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
+ msg.obj = cp;
+ phone.mCM.setupDataCall(Integer.toString(RILConstants.SETUP_DATA_TECH_CDMA),
+ Integer.toString(dataProfile), null, null,
+ null, Integer.toString(RILConstants.SETUP_DATA_AUTH_PAP_CHAP), msg);
}
- protected void onLinkStateChanged(DataLink.LinkState linkState) {
- switch (linkState) {
- case LINK_UP:
- notifySuccess(onConnectCompleted);
- break;
-
- case LINK_DOWN:
- case LINK_EXITED:
- phone.mCM.getLastDataCallFailCause(obtainMessage(EVENT_GET_LAST_FAIL_DONE));
- break;
- }
+ @Override
+ public String toString() {
+ return "State=" + getCurrentState().getName() + " create=" + createTime + " lastFail="
+ + lastFailTime + " lastFasilCause=" + lastFailCause;
}
+ @Override
protected FailCause getFailCauseFromRequest(int rilCause) {
FailCause cause;
@@ -253,73 +119,19 @@ public class CdmaDataConnection extends DataConnection {
return cause;
}
- protected void log(String s) {
- Log.d(LOG_TAG, "[CdmaDataConnection] " + s);
- }
-
@Override
- protected void onDeactivated(AsyncResult ar) {
- notifyDisconnect((Message) ar.userObj);
- if (DBG) log("CDMA Connection Deactivated");
+ protected boolean isDnsOk(String[] domainNameServers) {
+ if ((NULL_IP.equals(domainNameServers[0])
+ && NULL_IP.equals(domainNameServers[1])
+ && !((CDMAPhone) phone).isDnsCheckDisabled())) {
+ return false;
+ } else {
+ return true;
+ }
}
@Override
- protected void onSetupConnectionCompleted(AsyncResult ar) {
- if (ar.exception != null) {
- Log.e(LOG_TAG, "CdmaDataConnection Init failed " + ar.exception);
-
- if (receivedDisconnectReq) {
- // Don't bother reporting the error if there's already a
- // pending disconnect request, since DataConnectionTracker
- // has already updated its state.
- notifyDisconnect(onDisconnect);
- } else {
- if (ar.exception instanceof CommandException
- && ((CommandException) (ar.exception)).getCommandError()
- == CommandException.Error.RADIO_NOT_AVAILABLE) {
- notifyFail(FailCause.RADIO_NOT_AVAILABLE, onConnectCompleted);
- } else {
- phone.mCM.getLastDataCallFailCause(obtainMessage(EVENT_GET_LAST_FAIL_DONE));
- }
- }
- } else {
- if (receivedDisconnectReq) {
- // Don't bother reporting success if there's already a
- // pending disconnect request, since DataConnectionTracker
- // has already updated its state.
- tearDownData(onDisconnect);
- } else {
- String[] response = ((String[]) ar.result);
- cid = Integer.parseInt(response[0]);
-
- if (response.length > 2) {
- interfaceName = response[1];
- ipAddress = response[2];
- 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 (NULL_IP.equals(dnsServers[0]) && NULL_IP.equals(dnsServers[1])
- && !((CDMAPhone) phone).isDnsCheckDisabled()) {
- // Work around a race condition where QMI does not fill in DNS:
- // Deactivate PDP and let DataConnectionTracker retry.
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_BAD_DNS_ADDRESS,
- dnsServers[0]);
- phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_FORCE_RETRY));
- return;
- }
- }
-
- onLinkStateChanged(DataLink.LinkState.LINK_UP);
-
- if (DBG) log("CdmaDataConnection setup on cid = " + cid);
- }
- }
+ protected void log(String s) {
+ Log.d(LOG_TAG, "[" + getName() + "] " + s);
}
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 9bc5e8e..217e1e8 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -23,17 +23,18 @@ 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.INetStatService;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.preference.PreferenceManager;
-import android.provider.Checkin;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.telephony.cdma.CdmaCellLocation;
@@ -43,13 +44,14 @@ import android.util.Log;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.DataCallState;
-import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnection.FailCause;
+import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnectionTracker;
-import com.android.internal.telephony.RetryManager;
+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 com.android.internal.telephony.TelephonyEventLog;
import java.util.ArrayList;
@@ -76,9 +78,6 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
/** Currently active CdmaDataConnection */
private CdmaDataConnection mActiveDataConnection;
- /** mimic of GSM's mActiveApn */
- private boolean mIsApnActive = false;
-
private boolean mPendingRestartRadio = false;
private static final int TIME_DELAYED_TO_RESTART_RADIO =
SystemProperties.getInt("ro.cdma.timetoradiorestart", 60000);
@@ -104,8 +103,17 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
private static final String[] mSupportedApnTypes = {
Phone.APN_TYPE_DEFAULT,
Phone.APN_TYPE_MMS,
+ Phone.APN_TYPE_DUN,
+ Phone.APN_TYPE_HIPRI };
+
+ private static final String[] mDefaultApnTypes = {
+ Phone.APN_TYPE_DEFAULT,
+ Phone.APN_TYPE_MMS,
Phone.APN_TYPE_HIPRI };
+ // if we have no active Apn this is null
+ protected ApnSetting mActiveApn;
+
// Possibly promoate to base class, the only difference is
// the INTENT_RECONNECT_ALARM action is a different string.
// Do consider technology changes if it is promoted.
@@ -168,8 +176,6 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
p.mCM.registerForCdmaOtaProvision(this, EVENT_CDMA_OTA_PROVISION, null);
- this.netstat = INetStatService.Stub.asInterface(ServiceManager.getService("netstat"));
-
IntentFilter filter = new IntentFilter();
filter.addAction(INTENT_RECONNECT_ALARM);
filter.addAction(Intent.ACTION_SCREEN_ON);
@@ -189,8 +195,16 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
// and 2) whether the RIL will setup the baseband to auto-PS attach.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
+ boolean dataEnabledSetting = true;
+ try {
+ dataEnabledSetting = IConnectivityManager.Stub.asInterface(ServiceManager.
+ getService(Context.CONNECTIVITY_SERVICE)).getMobileDataEnabled();
+ } catch (Exception e) {
+ // nothing to do - use the old behavior and leave data on
+ }
dataEnabled[APN_DEFAULT_ID] =
- !sp.getBoolean(CDMAPhone.DATA_DISABLED_ON_BOOT_KEY, false);
+ !sp.getBoolean(CDMAPhone.DATA_DISABLED_ON_BOOT_KEY, false) &&
+ dataEnabledSetting;
if (dataEnabled[APN_DEFAULT_ID]) {
enabledCount++;
}
@@ -232,23 +246,15 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
protected void setState(State s) {
if (DBG) log ("setState: " + s);
if (state != s) {
- if (s == State.INITING) { // request Data connection context
- Checkin.updateStats(phone.getContext().getContentResolver(),
- Checkin.Stats.Tag.PHONE_CDMA_DATA_ATTEMPTED, 1, 0.0);
- }
-
- if (s == State.CONNECTED) { // pppd is up
- Checkin.updateStats(phone.getContext().getContentResolver(),
- Checkin.Stats.Tag.PHONE_CDMA_DATA_CONNECTED, 1, 0.0);
- }
+ EventLog.writeEvent(EventLogTags.CDMA_DATA_STATE_CHANGE,
+ state.toString(), s.toString());
+ state = s;
}
-
- state = s;
}
@Override
protected boolean isApnTypeActive(String type) {
- return (mIsApnActive && isApnTypeAvailable(type));
+ return mActiveApn != null && mActiveApn.canHandleType(type);
}
@Override
@@ -263,10 +269,9 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
protected String[] getActiveApnTypes() {
String[] result;
- if (mIsApnActive) {
- result = mSupportedApnTypes.clone();
+ if (mActiveApn != null) {
+ result = mActiveApn.types;
} else {
- // TODO - should this return an empty array? See GSM too.
result = new String[1];
result[0] = Phone.APN_TYPE_DEFAULT;
}
@@ -366,7 +371,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
* @param reason reason for the clean up.
*/
private void cleanUpConnection(boolean tearDown, String reason) {
- if (DBG) log("Clean up connection due to " + reason);
+ if (DBG) log("cleanUpConnection: reason: " + reason);
// Clear the reconnect alarm, if set.
if (mReconnectIntent != null) {
@@ -378,32 +383,33 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
setState(State.DISCONNECTING);
- for (DataConnection connBase : dataConnectionList) {
- CdmaDataConnection conn = (CdmaDataConnection) connBase;
-
+ boolean notificationDeferred = false;
+ for (DataConnection conn : dataConnectionList) {
if(conn != null) {
if (tearDown) {
- Message msg = obtainMessage(EVENT_DISCONNECT_DONE, reason);
- conn.disconnect(msg);
+ if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
+ conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE, reason));
+ notificationDeferred = true;
} else {
- conn.clearSettings();
+ if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
+ conn.resetSynchronously();
+ notificationDeferred = false;
}
}
}
stopNetStatPoll();
- if (!tearDown) {
- setState(State.IDLE);
- phone.notifyDataConnection(reason);
- mIsApnActive = false;
+ if (!notificationDeferred) {
+ if (DBG) log("cleanupConnection: !notificationDeferred");
+ gotoIdleAndNotifyDataConnection(reason);
}
}
private CdmaDataConnection findFreeDataConnection() {
for (DataConnection connBase : dataConnectionList) {
CdmaDataConnection conn = (CdmaDataConnection) connBase;
- if (conn.getState() == DataConnection.State.INACTIVE) {
+ if (conn.isInactive()) {
return conn;
}
}
@@ -411,7 +417,6 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
private boolean setupData(String reason) {
-
CdmaDataConnection conn = findFreeDataConnection();
if (conn == null) {
@@ -420,12 +425,19 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
mActiveDataConnection = conn;
- mIsApnActive = true;
+ String[] types;
+ if (mRequestedApnType.equals(Phone.APN_TYPE_DUN)) {
+ types = new String[1];
+ types[0] = Phone.APN_TYPE_DUN;
+ } else {
+ types = mDefaultApnTypes;
+ }
+ mActiveApn = new ApnSetting(0, "", "", "", "", "", "", "", "", "", "", 0, types);
Message msg = obtainMessage();
msg.what = EVENT_DATA_SETUP_COMPLETE;
msg.obj = reason;
- conn.connect(msg);
+ conn.connect(msg, mActiveApn);
setState(State.INITING);
phone.notifyDataConnection(reason);
@@ -481,79 +493,70 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
preTxPkts = txPkts;
preRxPkts = rxPkts;
- // check if netstat is still valid to avoid NullPointerException after NTC
- if (netstat != null) {
- try {
- txPkts = netstat.getMobileTxPackets();
- rxPkts = netstat.getMobileRxPackets();
- } catch (RemoteException e) {
- txPkts = 0;
- rxPkts = 0;
- }
+ txPkts = TrafficStats.getMobileTxPackets();
+ rxPkts = TrafficStats.getMobileRxPackets();
- //Log.d(LOG_TAG, "rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
+ //Log.d(LOG_TAG, "rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
- if (netStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
- sent = txPkts - preTxPkts;
- received = rxPkts - preRxPkts;
+ if (netStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
+ sent = txPkts - preTxPkts;
+ received = rxPkts - preRxPkts;
- if ( sent > 0 && received > 0 ) {
- sentSinceLastRecv = 0;
- newActivity = Activity.DATAINANDOUT;
- } else if (sent > 0 && received == 0) {
- if (phone.getState() == Phone.State.IDLE) {
- sentSinceLastRecv += sent;
- } else {
- sentSinceLastRecv = 0;
- }
- newActivity = Activity.DATAOUT;
- } else if (sent == 0 && received > 0) {
- sentSinceLastRecv = 0;
- newActivity = Activity.DATAIN;
- } else if (sent == 0 && received == 0) {
- newActivity = (activity == Activity.DORMANT) ? activity : Activity.NONE;
+ if ( sent > 0 && received > 0 ) {
+ sentSinceLastRecv = 0;
+ newActivity = Activity.DATAINANDOUT;
+ } else if (sent > 0 && received == 0) {
+ if (phone.getState() == Phone.State.IDLE) {
+ sentSinceLastRecv += sent;
} else {
sentSinceLastRecv = 0;
- newActivity = (activity == Activity.DORMANT) ? activity : Activity.NONE;
}
+ newActivity = Activity.DATAOUT;
+ } else if (sent == 0 && received > 0) {
+ sentSinceLastRecv = 0;
+ newActivity = Activity.DATAIN;
+ } else if (sent == 0 && received == 0) {
+ newActivity = (activity == Activity.DORMANT) ? activity : Activity.NONE;
+ } else {
+ sentSinceLastRecv = 0;
+ newActivity = (activity == Activity.DORMANT) ? activity : Activity.NONE;
+ }
- if (activity != newActivity) {
- activity = newActivity;
- phone.notifyDataActivity();
- }
+ if (activity != newActivity) {
+ activity = newActivity;
+ phone.notifyDataActivity();
}
+ }
- if (sentSinceLastRecv >= NUMBER_SENT_PACKETS_OF_HANG) {
- // Packets sent without ack exceeded threshold.
+ if (sentSinceLastRecv >= NUMBER_SENT_PACKETS_OF_HANG) {
+ // Packets sent without ack exceeded threshold.
- if (mNoRecvPollCount == 0) {
- EventLog.writeEvent(
- TelephonyEventLog.EVENT_LOG_RADIO_RESET_COUNTDOWN_TRIGGERED,
- sentSinceLastRecv);
- }
+ if (mNoRecvPollCount == 0) {
+ EventLog.writeEvent(
+ EventLogTags.PDP_RADIO_RESET_COUNTDOWN_TRIGGERED,
+ sentSinceLastRecv);
+ }
- if (mNoRecvPollCount < NO_RECV_POLL_LIMIT) {
- mNoRecvPollCount++;
- // Slow down the poll interval to let things happen
- netStatPollPeriod = POLL_NETSTAT_SLOW_MILLIS;
- } else {
- if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) +
- " pkts since last received");
- // We've exceeded the threshold. Restart the radio.
- netStatPollEnabled = false;
- stopNetStatPoll();
- restartRadio();
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_RESET,
- NO_RECV_POLL_LIMIT);
- }
+ if (mNoRecvPollCount < NO_RECV_POLL_LIMIT) {
+ mNoRecvPollCount++;
+ // Slow down the poll interval to let things happen
+ netStatPollPeriod = POLL_NETSTAT_SLOW_MILLIS;
} else {
- mNoRecvPollCount = 0;
- netStatPollPeriod = POLL_NETSTAT_MILLIS;
+ if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) +
+ " pkts since last received");
+ // We've exceeded the threshold. Restart the radio.
+ netStatPollEnabled = false;
+ stopNetStatPoll();
+ restartRadio();
+ EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, NO_RECV_POLL_LIMIT);
}
+ } else {
+ mNoRecvPollCount = 0;
+ netStatPollPeriod = POLL_NETSTAT_MILLIS;
+ }
- if (netStatPollEnabled) {
- mDataConnectionTracker.postDelayed(this, netStatPollPeriod);
- }
+ if (netStatPollEnabled) {
+ mDataConnectionTracker.postDelayed(this, netStatPollPeriod);
}
}
};
@@ -621,6 +624,13 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
setState(State.FAILED);
}
+ private void gotoIdleAndNotifyDataConnection(String reason) {
+ if (DBG) log("gotoIdleAndNotifyDataConnection: reason=" + reason);
+ setState(State.IDLE);
+ phone.notifyDataConnection(reason);
+ mActiveApn = null;
+ }
+
protected void onRecordsLoaded() {
if (state == State.FAILED) {
cleanUpConnection(false, null);
@@ -640,8 +650,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
*/
@Override
protected void onEnableNewApn() {
- // for cdma we only use this when default data is enabled..
- onTrySetupData(Phone.REASON_DATA_ENABLED);
+ cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
}
/**
@@ -730,7 +739,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
/**
- * @override com.android.internal.telephony.DataConnectionTracker
+ * Called when EVENT_DISCONNECT_DONE is received.
*/
protected void onDisconnectDone(AsyncResult ar) {
if(DBG) log("EVENT_DISCONNECT_DONE");
@@ -754,13 +763,27 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
phone.notifyDataConnection(reason);
- mIsApnActive = false;
+ mActiveApn = null;
if (retryAfterDisconnected(reason)) {
trySetupData(reason);
}
}
/**
+ * Called when EVENT_RESET_DONE is received so goto
+ * IDLE state and send notifications to those interested.
+ */
+ @Override
+ protected void onResetDone(AsyncResult ar) {
+ if (DBG) log("EVENT_RESET_DONE");
+ String reason = null;
+ if (ar.userObj instanceof String) {
+ reason = (String) ar.userObj;
+ }
+ gotoIdleAndNotifyDataConnection(reason);
+ }
+
+ /**
* @override com.android.internal.telephony.DataConnectionTracker
*/
protected void onVoiceCallStarted() {
@@ -801,7 +824,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
CdmaDataConnection dataConn;
for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) {
- dataConn = new CdmaDataConnection(mCdmaPhone);
+ dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone);
dataConnectionList.add(dataConn);
}
}
@@ -822,11 +845,9 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
mRetryMgr.resetRetryCount();
CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
- int bsid = (loc != null) ? loc.getBaseStationId() : -1;
-
- EventLog.List val = new EventLog.List(bsid,
+ EventLog.writeEvent(EventLogTags.CDMA_DATA_SETUP_FAILED,
+ loc != null ? loc.getBaseStationId() : -1,
TelephonyManager.getDefault().getNetworkType());
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CDMA_DATA_SETUP_FAILED, val);
}
trySetupData(Phone.REASON_CDMA_DATA_DETACHED);
}
@@ -865,13 +886,12 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
private void writeEventLogCdmaDataDrop() {
CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
- int bsid = (loc != null) ? loc.getBaseStationId() : -1;
- EventLog.List val = new EventLog.List(bsid,
+ EventLog.writeEvent(EventLogTags.CDMA_DATA_DROP,
+ loc != null ? loc.getBaseStationId() : -1,
TelephonyManager.getDefault().getNetworkType());
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CDMA_DATA_DROP, val);
}
- protected void onDataStateChanged (AsyncResult ar) {
+ protected void onDataStateChanged(AsyncResult ar) {
ArrayList<DataCallState> dataCallStates = (ArrayList<DataCallState>)(ar.result);
if (ar.exception != null) {
@@ -882,32 +902,46 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
if (state == State.CONNECTED) {
- if (dataCallStates.size() >= 1) {
- switch (dataCallStates.get(0).active) {
+ boolean isActiveOrDormantConnectionPresent = false;
+ int connectionState = DATA_CONNECTION_ACTIVE_PH_LINK_INACTIVE;
+
+ // Check for an active or dormant connection element in
+ // the DATA_CALL_LIST array
+ for (int index = 0; index < dataCallStates.size(); index++) {
+ connectionState = dataCallStates.get(index).active;
+ if (connectionState != DATA_CONNECTION_ACTIVE_PH_LINK_INACTIVE) {
+ isActiveOrDormantConnectionPresent = true;
+ break;
+ }
+ }
+
+ if (!isActiveOrDormantConnectionPresent) {
+ // No active or dormant connection
+ Log.i(LOG_TAG, "onDataStateChanged: No active connection"
+ + "state is CONNECTED, disconnecting/cleanup");
+ writeEventLogCdmaDataDrop();
+ cleanUpConnection(true, null);
+ return;
+ }
+
+ switch (connectionState) {
case DATA_CONNECTION_ACTIVE_PH_LINK_UP:
Log.v(LOG_TAG, "onDataStateChanged: active=LINK_ACTIVE && CONNECTED, ignore");
activity = Activity.NONE;
phone.notifyDataActivity();
+ startNetStatPoll();
break;
- case DATA_CONNECTION_ACTIVE_PH_LINK_INACTIVE:
- Log.v(LOG_TAG,
- "onDataStateChanged active=LINK_INACTIVE && CONNECTED, disconnecting/cleanup");
- writeEventLogCdmaDataDrop();
- cleanUpConnection(true, null);
- break;
+
case DATA_CONNECTION_ACTIVE_PH_LINK_DOWN:
Log.v(LOG_TAG, "onDataStateChanged active=LINK_DOWN && CONNECTED, dormant");
activity = Activity.DORMANT;
phone.notifyDataActivity();
+ stopNetStatPoll();
break;
+
default:
Log.v(LOG_TAG, "onDataStateChanged: IGNORE unexpected DataCallState.active="
- + dataCallStates.get(0).active);
- }
- } else {
- Log.v(LOG_TAG, "onDataStateChanged: network disconnected, clean up");
- writeEventLogCdmaDataDrop();
- cleanUpConnection(true, null);
+ + connectionState);
}
} else {
// TODO: Do we need to do anything?
@@ -954,6 +988,11 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
public void handleMessage (Message msg) {
+ if (!phone.mIsTheCurrentActivePhone) {
+ Log.d(LOG_TAG, "Ignore CDMA msgs since CDMA phone is inactive");
+ return;
+ }
+
switch (msg.what) {
case EVENT_RECORDS_LOADED:
onRecordsLoaded();
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaInformationRecords.java b/telephony/java/com/android/internal/telephony/cdma/CdmaInformationRecords.java
index 7402769..ce6530a 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaInformationRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaInformationRecords.java
@@ -74,7 +74,7 @@ public final class CdmaInformationRecords {
break;
case RIL_CDMA_T53_RELEASE_INFO_REC:
- // TODO(Moto): WHAT to do, for now fall through and throw exception
+ // TODO: WHAT to do, for now fall through and throw exception
default:
throw new RuntimeException("RIL_UNSOL_CDMA_INFO_REC: unsupported record. Got "
+ CdmaInformationRecords.idToString(id) + " ");
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index aee45bf..ed93aea 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -167,7 +167,8 @@ final class CdmaSMSDispatcher extends SMSDispatcher {
// not yet been handled and also do not correspond to the two
// kinds that are processed below.
if ((SmsEnvelope.TELESERVICE_WMT != teleService) &&
- (SmsEnvelope.TELESERVICE_WEMT != teleService)) {
+ (SmsEnvelope.TELESERVICE_WEMT != teleService) &&
+ (SmsEnvelope.MESSAGE_TYPE_BROADCAST != sms.getMessageType())) {
return Intents.RESULT_SMS_UNSUPPORTED;
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index e0c3a47..6c71584 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -29,7 +29,6 @@ import android.os.Registrant;
import android.os.RegistrantList;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.provider.Checkin;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.provider.Telephony.Intents;
@@ -45,10 +44,10 @@ 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.TelephonyEventLog;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
@@ -358,8 +357,8 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
if (ar.exception == null) {
String states[] = (String[])ar.result;
int baseStationId = -1;
- int baseStationLatitude = Integer.MAX_VALUE;
- int baseStationLongitude = Integer.MAX_VALUE;
+ int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
+ int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
int systemId = -1;
int networkId = -1;
@@ -374,6 +373,11 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
if (states[6] != null) {
baseStationLongitude = Integer.parseInt(states[6]);
}
+ // Some carriers only return lat-lngs of 0,0
+ if (baseStationLatitude == 0 && baseStationLongitude == 0) {
+ baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
+ baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
+ }
if (states[8] != null) {
systemId = Integer.parseInt(states[8]);
}
@@ -514,7 +518,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
synchronized(this) {
if (mPendingRadioPowerOffAfterDataOff) {
if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now.");
- cm.setRadioPower(false, null);
+ hangupAndPowerOff();
mPendingRadioPowerOffAfterDataOff = false;
}
}
@@ -537,38 +541,46 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
} else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
DataConnectionTracker dcTracker = phone.mDataConnection;
if (! dcTracker.isDataConnectionAsDesired()) {
-
- EventLog.List val = new EventLog.List(
+ EventLog.writeEvent(EventLogTags.DATA_NETWORK_STATUS_ON_RADIO_OFF,
dcTracker.getStateInString(),
- (dcTracker.getAnyDataEnabled() ? 1 : 0) );
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, val);
+ dcTracker.getAnyDataEnabled() ? 1 : 0);
}
- Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
- msg.arg1 = 1; // tearDown is true
- msg.obj = CDMAPhone.REASON_RADIO_TURNED_OFF;
- dcTracker.sendMessage(msg);
- synchronized(this) {
- if (!mPendingRadioPowerOffAfterDataOff) {
- DataConnectionTracker.State currentState = dcTracker.getState();
- if (currentState != DataConnectionTracker.State.CONNECTED
- && currentState != DataConnectionTracker.State.DISCONNECTING
- && currentState != DataConnectionTracker.State.INITING) {
- if (DBG) log("Data disconnected, turn off radio right away.");
- cm.setRadioPower(false, null);
- }
- else if (sendEmptyMessageDelayed(EVENT_SET_RADIO_POWER_OFF, 30000)) {
- if (DBG) {
- log("Wait up to 30 sec for data to disconnect, then turn off radio.");
- }
- mPendingRadioPowerOffAfterDataOff = true;
- } else {
- Log.w(LOG_TAG, "Cannot send delayed Msg, turn off radio right away.");
- cm.setRadioPower(false, null);
+ // If it's on and available and we want it off gracefully
+ powerOffRadioSafely();
+ } // Otherwise, we're in the desired state
+ }
+
+ @Override
+ protected void powerOffRadioSafely(){
+ // clean data connection
+ DataConnectionTracker dcTracker = phone.mDataConnection;
+
+ Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
+ msg.arg1 = 1; // tearDown is true
+ msg.obj = CDMAPhone.REASON_RADIO_TURNED_OFF;
+ dcTracker.sendMessage(msg);
+
+ synchronized(this) {
+ if (!mPendingRadioPowerOffAfterDataOff) {
+ DataConnectionTracker.State currentState = dcTracker.getState();
+ if (currentState != DataConnectionTracker.State.CONNECTED
+ && currentState != DataConnectionTracker.State.DISCONNECTING
+ && currentState != DataConnectionTracker.State.INITING) {
+ if (DBG) log("Data disconnected, turn off radio right away.");
+ hangupAndPowerOff();
+ }
+ else if (sendEmptyMessageDelayed(EVENT_SET_RADIO_POWER_OFF, 30000)) {
+ if (DBG) {
+ log("Wait up to 30 sec for data to disconnect, then turn off radio.");
}
+ mPendingRadioPowerOffAfterDataOff = true;
+ } else {
+ Log.w(LOG_TAG, "Cannot send delayed Msg, turn off radio right away.");
+ hangupAndPowerOff();
}
}
- } // Otherwise, we're in the desired state
+ }
}
@Override
@@ -597,6 +609,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
|| !TextUtils.equals(spn, curSpn)
|| !TextUtils.equals(plmn, curPlmn)) {
Intent intent = new Intent(Intents.SPN_STRINGS_UPDATED_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(Intents.EXTRA_SHOW_SPN, showSpn);
intent.putExtra(Intents.EXTRA_SPN, spn);
intent.putExtra(Intents.EXTRA_SHOW_PLMN, showPlmn);
@@ -654,8 +667,10 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
int registrationState = 4; //[0] registrationState
int radioTechnology = -1; //[3] radioTechnology
int baseStationId = -1; //[4] baseStationId
- int baseStationLatitude = Integer.MAX_VALUE; //[5] baseStationLatitude
- int baseStationLongitude = Integer.MAX_VALUE; //[6] baseStationLongitude
+ //[5] baseStationLatitude
+ int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
+ //[6] baseStationLongitude
+ int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
int cssIndicator = 0; //[7] init with 0, because it is treated as a boolean
int systemId = 0; //[8] systemId
int networkId = 0; //[9] networkId
@@ -681,6 +696,11 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
if (states[6] != null) {
baseStationLongitude = Integer.parseInt(states[6]);
}
+ // Some carriers only return lat-lngs of 0,0
+ if (baseStationLatitude == 0 && baseStationLongitude == 0) {
+ baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
+ baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
+ }
if (states[7] != null) {
cssIndicator = Integer.parseInt(states[7]);
}
@@ -819,6 +839,12 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
}
}
+ int roamingIndicator = newSS.getCdmaRoamingIndicator();
+ newSS.setCdmaEriIconIndex(phone.mEriManager.getCdmaEriIconIndex(roamingIndicator,
+ mDefaultRoamingIndicator));
+ newSS.setCdmaEriIconMode(phone.mEriManager.getCdmaEriIconMode(roamingIndicator,
+ mDefaultRoamingIndicator));
+
// NOTE: Some operator may require overriding mCdmaRoaming
// (set by the modem), depending on the mRoamingIndicator.
@@ -1001,6 +1027,14 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
+ // Add an event log when connection state changes
+ if (ss.getState() != newSS.getState() ||
+ cdmaDataConnectionState != newCdmaDataConnectionState) {
+ EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE,
+ ss.getState(), cdmaDataConnectionState,
+ newSS.getState(), newCdmaDataConnectionState);
+ }
+
ServiceState tss;
tss = ss;
ss = newSS;
@@ -1023,7 +1057,6 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
}
if (hasRegistered) {
- Checkin.updateStats(cr, Checkin.Stats.Tag.PHONE_CDMA_REGISTERED, 1, 0.0);
networkAttachedRegistrants.notifyRegistrants();
}
@@ -1453,10 +1486,10 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
*/
long gained = c.getTimeInMillis() - System.currentTimeMillis();
long timeSinceLastUpdate = SystemClock.elapsedRealtime() - mSavedAtTime;
- int nitzUpdateSpacing = Settings.Gservices.getInt(cr,
- Settings.Gservices.NITZ_UPDATE_SPACING, mNitzUpdateSpacing);
- int nitzUpdateDiff = Settings.Gservices.getInt(cr,
- Settings.Gservices.NITZ_UPDATE_DIFF, mNitzUpdateDiff);
+ int nitzUpdateSpacing = Settings.Secure.getInt(cr,
+ Settings.Secure.NITZ_UPDATE_SPACING, mNitzUpdateSpacing);
+ int nitzUpdateDiff = Settings.Secure.getInt(cr,
+ Settings.Secure.NITZ_UPDATE_DIFF, mNitzUpdateDiff);
if ((mSavedAtTime == 0) || (timeSinceLastUpdate > nitzUpdateSpacing)
|| (Math.abs(gained) > nitzUpdateDiff)) {
@@ -1512,6 +1545,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
(AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
alarm.setTimeZone(zoneId);
Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra("time-zone", zoneId);
phone.getContext().sendStickyBroadcast(intent);
}
@@ -1525,6 +1559,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
private void setAndBroadcastNetworkSetTime(long time) {
SystemClock.setCurrentTimeMillis(time);
Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra("time", time);
phone.getContext().sendStickyBroadcast(intent);
}
@@ -1600,9 +1635,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
* Returns IMSI as MCC + MNC + MIN
*/
String getImsi() {
- // TODO(Moto): When RUIM is enabled, IMSI will come from RUIM
- // not build-time props. Moto will provide implementation
- // for RUIM-ready case later.
+ // TODO: When RUIM is enabled, IMSI will come from RUIM not build-time props.
String operatorNumeric = SystemProperties.get(
TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "");
@@ -1632,11 +1665,19 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
if (mPendingRadioPowerOffAfterDataOff) {
if (DBG) log("Process pending request to turn radio off.");
removeMessages(EVENT_SET_RADIO_POWER_OFF);
- cm.setRadioPower(false, null);
+ hangupAndPowerOff();
mPendingRadioPowerOffAfterDataOff = false;
return true;
}
return false;
}
}
+
+ private void hangupAndPowerOff() {
+ // hang up all active voice calls
+ phone.mCT.ringingCall.hangupIfAlive();
+ phone.mCT.backgroundCall.hangupIfAlive();
+ phone.mCT.foregroundCall.hangupIfAlive();
+ cm.setRadioPower(false, null);
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/EriInfo.java b/telephony/java/com/android/internal/telephony/cdma/EriInfo.java
index 5c8e23e..3e5d37e 100644
--- a/telephony/java/com/android/internal/telephony/cdma/EriInfo.java
+++ b/telephony/java/com/android/internal/telephony/cdma/EriInfo.java
@@ -1,4 +1,6 @@
/*
+ * 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
diff --git a/telephony/java/com/android/internal/telephony/cdma/EriManager.java b/telephony/java/com/android/internal/telephony/cdma/EriManager.java
index 083fa0b..1bcc90a 100644
--- a/telephony/java/com/android/internal/telephony/cdma/EriManager.java
+++ b/telephony/java/com/android/internal/telephony/cdma/EriManager.java
@@ -1,4 +1,6 @@
/*
+ * 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
@@ -23,9 +25,9 @@ import android.util.Xml;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneBase;
-
import com.android.internal.util.XmlUtils;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
index 78e89d5..6e12f24 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
@@ -16,22 +16,10 @@
package com.android.internal.telephony.cdma;
-import android.content.pm.PackageManager;
-import android.os.AsyncResult;
-import android.os.Handler;
-import android.os.Looper;
import android.os.Message;
-import android.os.ServiceManager;
-import android.telephony.PhoneNumberUtils;
import android.util.Log;
-import com.android.internal.telephony.AdnRecord;
-import com.android.internal.telephony.AdnRecordCache;
import com.android.internal.telephony.IccPhoneBookInterfaceManager;
-import com.android.internal.telephony.PhoneProxy;
-
-import java.util.ArrayList;
-import java.util.List;
/**
* RuimPhoneBookInterfaceManager to provide an inter-process communication to
@@ -42,20 +30,6 @@ import java.util.List;
public class RuimPhoneBookInterfaceManager extends IccPhoneBookInterfaceManager {
static final String LOG_TAG = "CDMA";
-
- Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- AsyncResult ar;
-
- switch(msg.what) {
- default:
- mBaseHandler.handleMessage(msg);
- break;
- }
- }
- };
-
public RuimPhoneBookInterfaceManager(CDMAPhone phone) {
super(phone);
adnCache = phone.mRuimRecords.getAdnCache();
@@ -67,6 +41,11 @@ public class RuimPhoneBookInterfaceManager extends IccPhoneBookInterfaceManager
}
protected void finalize() {
+ try {
+ super.finalize();
+ } catch (Throwable throwable) {
+ Log.e(LOG_TAG, "Error while finalizing:", throwable);
+ }
if(DBG) Log.d(LOG_TAG, "RuimPhoneBookInterfaceManager finalized");
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
index b9ece8b..87b0c60 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
@@ -166,10 +166,8 @@ public final class RuimRecords extends IccRecords {
return null;
}
- // TODO(Moto): mncLength is not set anywhere.
if (mncLength != UNINITIALIZED && mncLength != UNKNOWN) {
// Length = length of MCC + length of MNC
- // TODO: change spec name
// length of mcc = 3 (3GPP2 C.S0005 - Section 2.3)
return mImsi.substring(0, 3 + mncLength);
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java
index 9439359..cfcfd98 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java
@@ -30,6 +30,7 @@ import com.android.internal.telephony.PhoneProxy;
import com.android.internal.telephony.SmsRawData;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import static android.telephony.SmsManager.STATUS_ON_ICC_FREE;
@@ -89,6 +90,11 @@ public class RuimSmsInterfaceManager extends IccSmsInterfaceManager {
}
protected void finalize() {
+ try {
+ super.finalize();
+ } catch (Throwable throwable) {
+ Log.e(LOG_TAG, "Error while finalizing:", throwable);
+ }
if(DBG) Log.d(LOG_TAG, "RuimSmsInterfaceManager finalized");
}
@@ -143,7 +149,7 @@ public class RuimSmsInterfaceManager extends IccSmsInterfaceManager {
public boolean copyMessageToIccEf(int status, byte[] pdu, byte[] smsc) {
//NOTE smsc not used in RUIM
if (DBG) log("copyMessageToIccEf: status=" + status + " ==> " +
- "pdu=("+ pdu + ")");
+ "pdu=("+ Arrays.toString(pdu) + ")");
enforceReceiveAndSend("Copying message to RUIM");
synchronized(mLock) {
mSuccess = false;
diff --git a/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java b/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java
index 4b88057..a149e72 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java
@@ -167,7 +167,7 @@ public class SignalToneUtil {
IS95_CONST_IR_SIG_TONE_ANSWER), ToneGenerator.TONE_CDMA_ANSWER);
hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_TONE, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN,
- IS95_CONST_IR_SIG_TONE_ABB_RE), ToneGenerator.TONE_CDMA_NETWORK_CALLWAITING);
+ IS95_CONST_IR_SIG_TONE_CALL_W), ToneGenerator.TONE_CDMA_NETWORK_CALLWAITING);
hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_TONE, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN,
IS95_CONST_IR_SIG_TONE_PIP), ToneGenerator.TONE_CDMA_PIP);
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 3e491d1..403b7a1 100755
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -458,11 +458,22 @@ public class SmsMessage extends SmsMessageBase {
* {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_VMN},
* {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WAP}
*/
- public int getTeleService() {
+ /* package */ int getTeleService() {
return mEnvelope.teleService;
}
/**
+ * Returns the message type of the message.
+ * @return the message type:
+ * {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#MESSAGE_TYPE_POINT_TO_POINT},
+ * {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#MESSAGE_TYPE_BROADCAST},
+ * {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#MESSAGE_TYPE_ACKNOWLEDGE},
+ */
+ /* package */ int getMessageType() {
+ return mEnvelope.messageType;
+ }
+
+ /**
* Decodes pdu to an empty SMS object.
* In the CDMA case the pdu is just an internal byte stream representation
* of the SMS Java-object.
diff --git a/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java b/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java
index 8d807fd..4cbfc87 100644
--- a/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java
+++ b/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java
@@ -32,12 +32,12 @@ public class ApnSetting {
String user;
String password;
int authType;
- String[] types;
+ public String[] types;
int id;
String numeric;
- ApnSetting(int id, String numeric, String carrier, String apn, String proxy, String port,
+ public ApnSetting(int id, String numeric, String carrier, String apn, String proxy, String port,
String mmsc, String mmsProxy, String mmsPort,
String user, String password, int authType, String[] types) {
this.id = id;
@@ -73,7 +73,7 @@ public class ApnSetting {
return sb.toString();
}
- boolean canHandleType(String type) {
+ public boolean canHandleType(String type) {
for (String t : types) {
// DEFAULT handles all, and HIPRI is handled by DEFAULT
if (t.equals(type) || t.equals(Phone.APN_TYPE_ALL) ||
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index b0de4f5..c7b1e5c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -294,15 +294,7 @@ public class GSMPhone extends PhoneBase {
public DataState getDataConnectionState() {
DataState ret = DataState.DISCONNECTED;
- if ((SystemProperties.get("adb.connected", "").length() > 0)
- && (SystemProperties.get("android.net.use-adb-networking", "")
- .length() > 0)) {
- // We're connected to an ADB host and we have USB networking
- // turned on. No matter what the radio state is,
- // we report data connected
-
- ret = DataState.CONNECTED;
- } else if (mSST == null) {
+ if (mSST == null) {
// Radio Technology Change is ongoning, dispose() and removeReferences() have
// already been called
@@ -735,7 +727,7 @@ public class GSMPhone extends PhoneBase {
}
// Only look at the Network portion for mmi
- String networkPortion = PhoneNumberUtils.extractNetworkPortion(newDialString);
+ String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString);
GsmMmiCode mmi = GsmMmiCode.newFromDialString(networkPortion, this);
if (LOCAL_DEBUG) Log.d(LOG_TAG,
"dialing w/ mmi '" + mmi + "'...");
@@ -1064,33 +1056,10 @@ public class GSMPhone extends PhoneBase {
return mCT.getMute();
}
- /**
- * @deprecated Do not use.
- */
- @Deprecated
- public void getPdpContextList(Message response) {
- getDataCallList(response);
- }
-
public void getDataCallList(Message response) {
mCM.getDataCallList(response);
}
- /**
- * @deprecated Do not use.
- */
- @Deprecated
- public List<PdpConnection> getCurrentPdpList() {
- ArrayList<DataConnection> connections = new ArrayList<DataConnection>();
- ArrayList<PdpConnection> pdp_list = new ArrayList<PdpConnection>();
-
- for(int n = 0; n < connections.size(); n++) {
- pdp_list.add((PdpConnection) connections.get(n));
- }
-
- return pdp_list;
- }
-
public List<DataConnection> getCurrentDataConnectionList () {
return mDataConnection.getAllDataConnections();
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java
index b82fefd..22fc13e 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java
@@ -16,11 +16,16 @@
package com.android.internal.telephony.gsm;
-import android.os.*;
-import android.telephony.gsm.GsmCellLocation;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.SystemProperties;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
+import android.telephony.gsm.GsmCellLocation;
import android.util.EventLog;
import android.util.Log;
@@ -29,14 +34,14 @@ import com.android.internal.telephony.CallTracker;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.DriverCall;
+import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.telephony.UUSInfo;
import com.android.internal.telephony.gsm.CallFailCause;
+import com.android.internal.telephony.gsm.GSMPhone;
import com.android.internal.telephony.gsm.GsmCall;
import com.android.internal.telephony.gsm.GsmConnection;
-import com.android.internal.telephony.gsm.GSMPhone;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.TelephonyEventLog;
-import com.android.internal.telephony.*;
import java.util.List;
import java.util.ArrayList;
@@ -878,13 +883,10 @@ public final class GsmCallTracker extends CallTracker {
causeCode == CallFailCause.QOS_NOT_AVAIL ||
causeCode == CallFailCause.BEARER_NOT_AVAIL ||
causeCode == CallFailCause.ERROR_UNSPECIFIED) {
- int cid = -1;
GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
- if (loc != null) cid = loc.getCid();
-
- EventLog.List val = new EventLog.List(causeCode, cid,
- TelephonyManager.getDefault().getNetworkType());
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CALL_DROP, val);
+ EventLog.writeEvent(EventLogTags.CALL_DROP,
+ causeCode, loc != null ? loc.getCid() : -1,
+ TelephonyManager.getDefault().getNetworkType());
}
for (int i = 0, s = droppedDuringPoll.size()
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
index 0024c9b..7dc2504 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
@@ -146,7 +146,7 @@ public class GsmConnection extends Connection {
this.dialString = dialString;
- this.address = PhoneNumberUtils.extractNetworkPortion(dialString);
+ this.address = PhoneNumberUtils.extractNetworkPortionAlt(dialString);
this.postDialString = PhoneNumberUtils.extractPostDialPortion(dialString);
index = -1;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
new file mode 100644
index 0000000..d893ec4
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.os.Message;
+import android.util.Log;
+import android.util.Patterns;
+
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.RILConstants;
+
+/**
+ * {@hide}
+ */
+public class GsmDataConnection extends DataConnection {
+
+ private static final String LOG_TAG = "GSM";
+
+ /** Fail cause of last PDP activate, from RIL_LastPDPActivateFailCause */
+ private static final int PDP_FAIL_OPERATOR_BARRED = 0x08;
+ private static final int PDP_FAIL_INSUFFICIENT_RESOURCES = 0x1A;
+ private static final int PDP_FAIL_MISSING_UKNOWN_APN = 0x1B;
+ private static final int PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C;
+ private static final int PDP_FAIL_USER_AUTHENTICATION = 0x1D;
+ private static final int PDP_FAIL_ACTIVATION_REJECT_GGSN = 0x1E;
+ private static final int PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F;
+ private static final int PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20;
+ private static final int PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21;
+ private static final int PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22;
+ private static final int PDP_FAIL_NSAPI_IN_USE = 0x23;
+ private static final int PDP_FAIL_PROTOCOL_ERRORS = 0x6F;
+ private static final int PDP_FAIL_ERROR_UNSPECIFIED = 0xffff;
+
+ private static final int PDP_FAIL_REGISTRATION_FAIL = -1;
+ private static final int PDP_FAIL_GPRS_REGISTRATION_FAIL = -2;
+
+ //***** Instance Variables
+ private ApnSetting apn;
+
+ //***** Constructor
+ private GsmDataConnection(GSMPhone phone, String name) {
+ super(phone, name);
+ }
+
+ /**
+ * Create the connection object
+ *
+ * @param phone
+ * @return GsmDataConnection that was created.
+ */
+ static GsmDataConnection makeDataConnection(GSMPhone phone) {
+ synchronized (mCountLock) {
+ mCount += 1;
+ }
+ GsmDataConnection gsmDc = new GsmDataConnection(phone, "GsmDataConnection-" + mCount);
+ gsmDc.start();
+ if (DBG) gsmDc.log("Made " + gsmDc.getName());
+ return gsmDc;
+ }
+
+ /**
+ * Begin setting up a data connection, calls setupDataCall
+ * and the ConnectionParams will be returned with the
+ * EVENT_SETUP_DATA_CONNECTION_DONE AsyncResul.userObj.
+ *
+ * @param cp is the connection parameters
+ */
+ @Override
+ protected
+ void onConnect(ConnectionParams cp) {
+ apn = cp.apn;
+
+ if (DBG) log("Connecting to carrier: '" + apn.carrier
+ + "' APN: '" + apn.apn
+ + "' proxy: '" + apn.proxy + "' port: '" + apn.port);
+
+ setHttpProxy (apn.proxy, apn.port);
+
+ createTime = -1;
+ lastFailTime = -1;
+ lastFailCause = FailCause.NONE;
+
+ // msg.obj will be returned in AsyncResult.userObj;
+ Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
+ msg.obj = cp;
+
+ int authType = apn.authType;
+ if (authType == -1) {
+ authType = (apn.user != null) ? RILConstants.SETUP_DATA_AUTH_PAP_CHAP :
+ RILConstants.SETUP_DATA_AUTH_NONE;
+ }
+ phone.mCM.setupDataCall(Integer.toString(RILConstants.SETUP_DATA_TECH_GSM),
+ Integer.toString(RILConstants.DATA_PROFILE_DEFAULT), apn.apn, apn.user,
+ apn.password, Integer.toString(authType), msg);
+ }
+
+ @Override
+ protected void clearSettings() {
+ super.clearSettings();
+ apn = null;
+ }
+
+ @Override
+ public String toString() {
+ return "State=" + getCurrentState().getName() + " Apn=" + apn +
+ " create=" + createTime + " lastFail=" + lastFailTime +
+ " lastFailCause=" + lastFailCause;
+ }
+
+ @Override
+ protected FailCause getFailCauseFromRequest(int rilCause) {
+ FailCause cause;
+
+ switch (rilCause) {
+ case PDP_FAIL_OPERATOR_BARRED:
+ cause = FailCause.OPERATOR_BARRED;
+ break;
+ case PDP_FAIL_INSUFFICIENT_RESOURCES:
+ cause = FailCause.INSUFFICIENT_RESOURCES;
+ break;
+ case PDP_FAIL_MISSING_UKNOWN_APN:
+ cause = FailCause.MISSING_UKNOWN_APN;
+ break;
+ case PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE:
+ cause = FailCause.UNKNOWN_PDP_ADDRESS;
+ break;
+ case PDP_FAIL_USER_AUTHENTICATION:
+ cause = FailCause.USER_AUTHENTICATION;
+ break;
+ case PDP_FAIL_ACTIVATION_REJECT_GGSN:
+ cause = FailCause.ACTIVATION_REJECT_GGSN;
+ break;
+ case PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED:
+ cause = FailCause.ACTIVATION_REJECT_UNSPECIFIED;
+ break;
+ case PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER:
+ cause = FailCause.SERVICE_OPTION_OUT_OF_ORDER;
+ break;
+ case PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED:
+ cause = FailCause.SERVICE_OPTION_NOT_SUPPORTED;
+ break;
+ case PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED:
+ cause = FailCause.SERVICE_OPTION_NOT_SUBSCRIBED;
+ break;
+ case PDP_FAIL_NSAPI_IN_USE:
+ cause = FailCause.NSAPI_IN_USE;
+ break;
+ case PDP_FAIL_PROTOCOL_ERRORS:
+ cause = FailCause.PROTOCOL_ERRORS;
+ break;
+ case PDP_FAIL_ERROR_UNSPECIFIED:
+ cause = FailCause.UNKNOWN;
+ break;
+ case PDP_FAIL_REGISTRATION_FAIL:
+ cause = FailCause.REGISTRATION_FAIL;
+ break;
+ case PDP_FAIL_GPRS_REGISTRATION_FAIL:
+ cause = FailCause.GPRS_REGISTRATION_FAIL;
+ break;
+ default:
+ cause = FailCause.UNKNOWN;
+ }
+ return cause;
+ }
+
+ @Override
+ protected boolean isDnsOk(String[] domainNameServers) {
+ if (NULL_IP.equals(dnsServers[0]) && NULL_IP.equals(dnsServers[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
+ // if Proxy is an IP-address.
+ // Otherwise, the default APN will not be restored anymore.
+ if (!apn.types[0].equals(Phone.APN_TYPE_MMS)
+ || !isIpAddress(apn.mmsProxy)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ protected void log(String s) {
+ Log.d(LOG_TAG, "[" + getName() + "] " + s);
+ }
+
+ public ApnSetting getApn() {
+ return this.apn;
+ }
+
+ private void setHttpProxy(String httpProxy, String httpPort) {
+ if (httpProxy == null || httpProxy.length() == 0) {
+ phone.setSystemProperty("net.gprs.http-proxy", null);
+ return;
+ }
+
+ if (httpPort == null || httpPort.length() == 0) {
+ httpPort = "8080"; // Default to port 8080
+ }
+
+ phone.setSystemProperty("net.gprs.http-proxy",
+ "http://" + httpProxy + ":" + httpPort + "/");
+ }
+
+ private boolean isIpAddress(String address) {
+ if (address == null) return false;
+
+ return Patterns.IP_ADDRESS.matcher(apn.mmsProxy).matches();
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 7b60474..cbfb550 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -27,18 +27,19 @@ 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.TrafficStats;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.AsyncResult;
-import android.os.INetStatService;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.preference.PreferenceManager;
-import android.provider.Checkin;
import android.provider.Settings;
import android.provider.Telephony;
import android.telephony.ServiceState;
@@ -53,7 +54,7 @@ import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RetryManager;
-import com.android.internal.telephony.TelephonyEventLog;
+import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.DataConnection.FailCause;
import java.io.IOException;
@@ -82,7 +83,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
//***** Instance Variables
- INetStatService netstat;
// Indicates baseband will not auto-attach
private boolean noAutoAttach = false;
@@ -126,8 +126,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
*/
private ArrayList<DataConnection> pdpList;
- /** Currently active PdpConnection */
- private PdpConnection mActivePdp;
+ /** Currently active DataConnection */
+ private GsmDataConnection mActivePdp;
/** Is packet service restricted by network */
private boolean mIsPsRestricted = false;
@@ -137,7 +137,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// TODO: Increase this to match the max number of simultaneous
// PDP contexts we plan to support.
/**
- * Pool size of PdpConnection objects.
+ * Pool size of DataConnection objects.
*/
private static final int PDP_CONNECTION_POOL_SIZE = 1;
@@ -218,8 +218,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
p.mSST.registerForPsRestrictedEnabled(this, EVENT_PS_RESTRICT_ENABLED, null);
p.mSST.registerForPsRestrictedDisabled(this, EVENT_PS_RESTRICT_DISABLED, null);
- this.netstat = INetStatService.Stub.asInterface(ServiceManager.getService("netstat"));
-
IntentFilter filter = new IntentFilter();
filter.addAction(INTENT_RECONNECT_ALARM);
filter.addAction(Intent.ACTION_SCREEN_ON);
@@ -244,7 +242,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// This preference tells us 1) initial condition for "dataEnabled",
// and 2) whether the RIL will setup the baseband to auto-PS attach.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
- dataEnabled[APN_DEFAULT_ID] = !sp.getBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, false);
+ boolean dataEnabledSetting = true;
+ try {
+ dataEnabledSetting = IConnectivityManager.Stub.asInterface(ServiceManager.
+ getService(Context.CONNECTIVITY_SERVICE)).getMobileDataEnabled();
+ } catch (Exception e) {
+ // nothing to do - use the old behavior and leave data on
+ }
+ dataEnabled[APN_DEFAULT_ID] = !sp.getBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, false) &&
+ dataEnabledSetting;
if (dataEnabled[APN_DEFAULT_ID]) {
enabledCount++;
}
@@ -301,21 +307,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void setState(State s) {
if (DBG) log ("setState: " + s);
if (state != s) {
- if (s == State.INITING) { // request PDP context
- Checkin.updateStats(
- phone.getContext().getContentResolver(),
- Checkin.Stats.Tag.PHONE_GPRS_ATTEMPTED, 1, 0.0);
- }
-
- if (s == State.CONNECTED) { // pppd is up
- Checkin.updateStats(
- phone.getContext().getContentResolver(),
- Checkin.Stats.Tag.PHONE_GPRS_CONNECTED, 1, 0.0);
- }
+ EventLog.writeEvent(EventLogTags.GSM_DATA_STATE_CHANGE, state.toString(), s.toString());
+ state = s;
}
- state = s;
-
if (state == State.FAILED) {
if (waitingApns != null)
waitingApns.clear(); // when teardown the connection and set to IDLE
@@ -382,7 +377,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
/**
- * Formerly this method was ArrayList<PdpConnection> getAllPdps()
+ * Formerly this method was ArrayList<GsmDataConnection> getAllPdps()
*/
public ArrayList<DataConnection> getAllDataConnections() {
ArrayList<DataConnection> pdps = (ArrayList<DataConnection>)pdpList.clone();
@@ -452,7 +447,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
waitingApns = buildWaitingApns();
if (waitingApns.isEmpty()) {
if (DBG) log("No APN found");
- notifyNoData(PdpConnection.FailCause.MISSING_UKNOWN_APN);
+ notifyNoData(GsmDataConnection.FailCause.MISSING_UKNOWN_APN);
return false;
} else {
log ("Create from allApns : " + apnListToString(allApns));
@@ -487,7 +482,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* there is no mechanism for abandoning an INITING/CONNECTING session,
* but would likely involve cancelling pending async requests or
* setting a flag or new state to ignore them when they came in
- * @param tearDown true if the underlying PdpConnection should be
+ * @param tearDown true if the underlying GsmDataConnection should be
* disconnected.
* @param reason reason for the clean up.
*/
@@ -504,21 +499,23 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
setState(State.DISCONNECTING);
+ boolean notificationDeferred = false;
for (DataConnection conn : pdpList) {
- PdpConnection pdp = (PdpConnection) conn;
if (tearDown) {
- Message msg = obtainMessage(EVENT_DISCONNECT_DONE, reason);
- pdp.disconnect(msg);
+ if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
+ conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE, reason));
+ notificationDeferred = true;
} else {
- pdp.clearSettings();
+ if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
+ conn.resetSynchronously();
+ notificationDeferred = false;
}
}
stopNetStatPoll();
- if (!tearDown) {
- setState(State.IDLE);
- phone.notifyDataConnection(reason);
- mActiveApn = null;
+ if (!notificationDeferred) {
+ if (DBG) log("cleanupConnection: !notificationDeferred");
+ gotoIdleAndNotifyDataConnection(reason);
}
}
@@ -564,10 +561,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return result;
}
- private PdpConnection findFreePdp() {
+ private GsmDataConnection findFreePdp() {
for (DataConnection conn : pdpList) {
- PdpConnection pdp = (PdpConnection) conn;
- if (pdp.getState() == DataConnection.State.INACTIVE) {
+ GsmDataConnection pdp = (GsmDataConnection) conn;
+ if (pdp.isInactive()) {
return pdp;
}
}
@@ -576,13 +573,13 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private boolean setupData(String reason) {
ApnSetting apn;
- PdpConnection pdp;
+ GsmDataConnection pdp;
apn = getNextApn();
if (apn == null) return false;
pdp = findFreePdp();
if (pdp == null) {
- if (DBG) log("setupData: No free PdpConnection found!");
+ if (DBG) log("setupData: No free GsmDataConnection found!");
return false;
}
mActiveApn = apn;
@@ -591,7 +588,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
Message msg = obtainMessage();
msg.what = EVENT_DATA_SETUP_COMPLETE;
msg.obj = reason;
- pdp.connect(apn, msg);
+ pdp.connect(msg, apn);
setState(State.INITING);
phone.notifyDataConnection(reason);
@@ -711,12 +708,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
Log.i(LOG_TAG, "PDP connection has dropped. Reconnecting");
// Add an event log when the network drops PDP
- int cid = -1;
GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
- if (loc != null) cid = loc.getCid();
- EventLog.List val = new EventLog.List(cid,
+ EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP,
+ loc != null ? loc.getCid() : -1,
TelephonyManager.getDefault().getNetworkType());
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val);
cleanUpConnection(true, null);
return;
@@ -734,12 +729,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
+ " Reconnecting");
// Log the network drop on the event log.
- int cid = -1;
GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
- if (loc != null) cid = loc.getCid();
- EventLog.List val = new EventLog.List(cid,
+ EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP,
+ loc != null ? loc.getCid() : -1,
TelephonyManager.getDefault().getNetworkType());
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val);
cleanUpConnection(true, null);
}
@@ -756,6 +749,13 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
mReregisterOnReconnectFailure = false;
}
+ private void gotoIdleAndNotifyDataConnection(String reason) {
+ if (DBG) log("gotoIdleAndNotifyDataConnection: reason=" + reason);
+ setState(State.IDLE);
+ phone.notifyDataConnection(reason);
+ mActiveApn = null;
+ }
+
/**
* This is a kludge to deal with the fact that
* the PDP state change notification doesn't always work
@@ -778,16 +778,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void doRecovery() {
if (state == State.CONNECTED) {
- int maxPdpReset = Settings.Gservices.getInt(mResolver,
- Settings.Gservices.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT,
+ int maxPdpReset = Settings.Secure.getInt(mResolver,
+ Settings.Secure.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT,
DEFAULT_MAX_PDP_RESET_FAIL);
if (mPdpResetCount < maxPdpReset) {
mPdpResetCount++;
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_RESET, sentSinceLastRecv);
+ EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, sentSinceLastRecv);
cleanUpConnection(true, Phone.REASON_PDP_RESET);
} else {
mPdpResetCount = 0;
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_REREGISTER_NETWORK, sentSinceLastRecv);
+ EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, sentSinceLastRecv);
mGsmPhone.mSST.reRegisterNetwork(null);
}
// TODO: Add increasingly drastic recovery steps, eg,
@@ -813,7 +813,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void restartRadio() {
Log.d(LOG_TAG, "************TURN OFF RADIO**************");
cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
- phone.mCM.setRadioPower(false, null);
+ mGsmPhone.mSST.powerOffRadioSafely();
/* Note: no need to call setRadioPower(true). Assuming the desired
* radio power state is still ON (as tracked by ServiceStateTracker),
* ServiceStateTracker will call setRadioPower when it receives the
@@ -838,13 +838,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
preTxPkts = txPkts;
preRxPkts = rxPkts;
- try {
- txPkts = netstat.getMobileTxPackets();
- rxPkts = netstat.getMobileRxPackets();
- } catch (RemoteException e) {
- txPkts = 0;
- rxPkts = 0;
- }
+ txPkts = TrafficStats.getMobileTxPackets();
+ rxPkts = TrafficStats.getMobileRxPackets();
//Log.d(LOG_TAG, "rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
@@ -880,19 +875,19 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
}
- int watchdogTrigger = Settings.Gservices.getInt(mResolver,
- Settings.Gservices.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
+ int watchdogTrigger = Settings.Secure.getInt(mResolver,
+ Settings.Secure.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
NUMBER_SENT_PACKETS_OF_HANG);
if (sentSinceLastRecv >= watchdogTrigger) {
// we already have NUMBER_SENT_PACKETS sent without ack
if (mNoRecvPollCount == 0) {
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_RESET_COUNTDOWN_TRIGGERED,
+ EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET_COUNTDOWN_TRIGGERED,
sentSinceLastRecv);
}
- int noRecvPollLimit = Settings.Gservices.getInt(mResolver,
- Settings.Gservices.PDP_WATCHDOG_ERROR_POLL_COUNT, NO_RECV_POLL_LIMIT);
+ int noRecvPollLimit = Settings.Secure.getInt(mResolver,
+ Settings.Secure.PDP_WATCHDOG_ERROR_POLL_COUNT, NO_RECV_POLL_LIMIT);
if (mNoRecvPollCount < noRecvPollLimit) {
// It's possible the PDP context went down and we weren't notified.
@@ -903,8 +898,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
mNoRecvPollCount++;
// Slow down the poll interval to let things happen
- netStatPollPeriod = Settings.Gservices.getInt(mResolver,
- Settings.Gservices.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS,
+ netStatPollPeriod = Settings.Secure.getInt(mResolver,
+ Settings.Secure.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS,
POLL_NETSTAT_SLOW_MILLIS);
} else {
if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) +
@@ -923,11 +918,11 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
} else {
mNoRecvPollCount = 0;
if (mIsScreenOn) {
- netStatPollPeriod = Settings.Gservices.getInt(mResolver,
- Settings.Gservices.PDP_WATCHDOG_POLL_INTERVAL_MS, POLL_NETSTAT_MILLIS);
+ netStatPollPeriod = Settings.Secure.getInt(mResolver,
+ Settings.Secure.PDP_WATCHDOG_POLL_INTERVAL_MS, POLL_NETSTAT_MILLIS);
} else {
- netStatPollPeriod = Settings.Gservices.getInt(mResolver,
- Settings.Gservices.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS,
+ netStatPollPeriod = Settings.Secure.getInt(mResolver,
+ Settings.Secure.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS,
POLL_NETSTAT_SCREEN_OFF_MILLIS);
}
}
@@ -941,10 +936,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void runPingTest () {
int status = -1;
try {
- String address = Settings.Gservices.getString(mResolver,
- Settings.Gservices.PDP_WATCHDOG_PING_ADDRESS);
- int deadline = Settings.Gservices.getInt(mResolver,
- Settings.Gservices.PDP_WATCHDOG_PING_DEADLINE, DEFAULT_PING_DEADLINE);
+ String address = Settings.Secure.getString(mResolver,
+ Settings.Secure.PDP_WATCHDOG_PING_ADDRESS);
+ int deadline = Settings.Secure.getInt(mResolver,
+ Settings.Secure.PDP_WATCHDOG_PING_DEADLINE, DEFAULT_PING_DEADLINE);
if (DBG) log("pinging " + address + " for " + deadline + "s");
if (address != null && !NULL_IP.equals(address)) {
Process p = Runtime.getRuntime()
@@ -960,7 +955,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (status == 0) {
// ping succeeded. False alarm. Reset netStatPoll.
// ("-1" for this event indicates a false alarm)
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_RESET, -1);
+ EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, -1);
mPdpResetCount = 0;
sendMessage(obtainMessage(EVENT_START_NETSTAT_POLL));
} else {
@@ -974,13 +969,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* seems like it deserves an error notification.
* Transient errors are ignored
*/
- private boolean shouldPostNotification(PdpConnection.FailCause cause) {
- boolean shouldPost = true;
- // TODO CHECK
- // if (dataLink != null) {
- // shouldPost = dataLink.getLastLinkExitCode() != DataLink.EXIT_OPEN_FAILED;
- //}
- return (shouldPost && cause != PdpConnection.FailCause.UNKNOWN);
+ private boolean shouldPostNotification(GsmDataConnection.FailCause cause) {
+ return (cause != GsmDataConnection.FailCause.UNKNOWN);
}
/**
@@ -1046,7 +1036,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
}
- private void notifyNoData(PdpConnection.FailCause lastFailCauseCode) {
+ private void notifyNoData(GsmDataConnection.FailCause lastFailCauseCode) {
setState(State.FAILED);
}
@@ -1069,7 +1059,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
mRetryMgr.resetRetryCount();
// TODO: To support simultaneous PDP contexts, this should really only call
- // cleanUpConnection if it needs to free up a PdpConnection.
+ // cleanUpConnection if it needs to free up a GsmDataConnection.
cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
}
@@ -1149,19 +1139,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// that the existing connection may service that type, in which
// case we should try the next type, etc.
} else {
- PdpConnection.FailCause cause;
- cause = (PdpConnection.FailCause) (ar.result);
+ GsmDataConnection.FailCause cause;
+ cause = (GsmDataConnection.FailCause) (ar.result);
if(DBG) log("PDP setup failed " + cause);
// Log this failure to the Event Logs.
if (cause.isEventLoggable()) {
- int cid = -1;
GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
- if (loc != null) cid = loc.getCid();
-
- EventLog.List val = new EventLog.List(
- cause.ordinal(), cid,
+ EventLog.writeEvent(EventLogTags.PDP_SETUP_FAIL,
+ cause.ordinal(), loc != null ? loc.getCid() : -1,
TelephonyManager.getDefault().getNetworkType());
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_PDP_SETUP_FAIL, val);
}
// No try for permanent failure
@@ -1188,6 +1174,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
}
+ /**
+ * Called when EVENT_DISCONNECT_DONE is received.
+ */
protected void onDisconnectDone(AsyncResult ar) {
String reason = null;
if(DBG) log("EVENT_DISCONNECT_DONE");
@@ -1202,6 +1191,19 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
}
+ /**
+ * Called when EVENT_RESET_DONE is received.
+ */
+ @Override
+ protected void onResetDone(AsyncResult ar) {
+ if (DBG) log("EVENT_RESET_DONE");
+ String reason = null;
+ if (ar.userObj instanceof String) {
+ reason = (String) ar.userObj;
+ }
+ gotoIdleAndNotifyDataConnection(reason);
+ }
+
protected void onPollPdp() {
if (state == State.CONNECTED) {
// only poll when connected
@@ -1259,9 +1261,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (cursor.getCount() > 0) {
allApns = createApnList(cursor);
// TODO: Figure out where this fits in. This basically just
- // writes the pap-secrets file. No longer tied to PdpConnection
+ // writes the pap-secrets file. No longer tied to GsmDataConnection
// object. Not used on current platform (no ppp).
- //PdpConnection pdp = pdpList.get(pdp_name);
+ //GsmDataConnection pdp = pdpList.get(pdp_name);
//if (pdp != null && pdp.dataLink != null) {
// pdp.dataLink.setPasswordInfo(cursor);
//}
@@ -1273,7 +1275,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (allApns.isEmpty()) {
if (DBG) log("No APN found for carrier: " + operator);
preferredApn = null;
- notifyNoData(PdpConnection.FailCause.MISSING_UKNOWN_APN);
+ notifyNoData(GsmDataConnection.FailCause.MISSING_UKNOWN_APN);
} else {
preferredApn = getPreferredApn();
Log.d(LOG_TAG, "Get PreferredAPN");
@@ -1289,14 +1291,14 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
DataConnection pdp;
for (int i = 0; i < PDP_CONNECTION_POOL_SIZE; i++) {
- pdp = new PdpConnection(mGsmPhone);
+ pdp = GsmDataConnection.makeDataConnection(mGsmPhone);
pdpList.add(pdp);
}
}
private void destroyAllPdpList() {
if(pdpList != null) {
- PdpConnection pdp;
+ GsmDataConnection pdp;
pdpList.removeAll(pdpList);
}
}
@@ -1361,7 +1363,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return result.toString();
}
- private void startDelayedRetry(PdpConnection.FailCause cause, String reason) {
+ private void startDelayedRetry(GsmDataConnection.FailCause cause, String reason) {
notifyNoData(cause);
reconnectAfterFail(cause, reason);
}
@@ -1417,6 +1419,12 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
public void handleMessage (Message msg) {
if (DBG) Log.d(LOG_TAG,"GSMDataConnTrack handleMessage "+msg);
+
+ if (!mGsmPhone.mIsTheCurrentActivePhone) {
+ Log.d(LOG_TAG, "Ignore GSM msgs since GSM phone is inactive");
+ return;
+ }
+
switch (msg.what) {
case EVENT_RECORDS_LOADED:
onRecordsLoaded();
@@ -1497,5 +1505,4 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void log(String s) {
Log.d(LOG_TAG, "[GsmDataConnectionTracker] " + s);
}
-
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index bc7b7fa..50b8eba 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -35,7 +35,6 @@ import android.os.Registrant;
import android.os.RegistrantList;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.provider.Checkin;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.provider.Telephony.Intents;
@@ -52,11 +51,11 @@ 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.TelephonyEventLog;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
@@ -103,7 +102,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
* Mark when service state is in emergency call only mode
*/
private boolean mEmergencyOnly = false;
- private boolean mNewEmergencyOnly = false;
private RegistrantList gprsAttachedRegistrants = new RegistrantList();
private RegistrantList gprsDetachedRegistrants = new RegistrantList();
@@ -507,12 +505,9 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
// Can't register data sevice while voice service is ok
// i.e. CREG is ok while CGREG is not
// possible a network or baseband side error
- int cid = -1;
GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
- if (loc != null) cid = loc.getCid();
-
- EventLog.List val = new EventLog.List(ss.getOperatorNumeric(), cid);
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CGREG_FAIL, val);
+ EventLog.writeEvent(EventLogTags.DATA_NETWORK_REGISTRATION_FAIL,
+ ss.getOperatorNumeric(), loc != null ? loc.getCid() : -1);
mReportedGprsNoReg = true;
}
mStartedGprsRegCheck = false;
@@ -543,32 +538,44 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
} else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
DataConnectionTracker dcTracker = phone.mDataConnection;
if (! dcTracker.isDataConnectionAsDesired()) {
-
- EventLog.List val = new EventLog.List(
- dcTracker.getStateInString(),
- (dcTracker.getAnyDataEnabled() ? 1 : 0) );
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, val);
+ EventLog.writeEvent(EventLogTags.DATA_NETWORK_STATUS_ON_RADIO_OFF,
+ dcTracker.getStateInString(), dcTracker.getAnyDataEnabled() ? 1 : 0);
}
- Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
- msg.arg1 = 1; // tearDown is true
- msg.obj = GSMPhone.REASON_RADIO_TURNED_OFF;
- dcTracker.sendMessage(msg);
-
- // poll data state up to 15 times, with a 100ms delay
- // totaling 1.5 sec. Normal data disable action will finish in 100ms.
- for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
- if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED
- && dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING) {
- Log.d(LOG_TAG, "Data shutdown complete.");
- break;
- }
- SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
- }
- // If it's on and available and we want it off..
- cm.setRadioPower(false, null);
+ // If it's on and available and we want it off gracefully
+ powerOffRadioSafely();
} // Otherwise, we're in the desired state
}
+ @Override
+ protected void powerOffRadioSafely() {
+ // clean data connection
+ DataConnectionTracker dcTracker = phone.mDataConnection;
+ Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
+ msg.arg1 = 1; // tearDown is true
+ msg.obj = GSMPhone.REASON_RADIO_TURNED_OFF;
+ dcTracker.sendMessage(msg);
+
+ // poll data state up to 15 times, with a 100ms delay
+ // totaling 1.5 sec. Normal data disable action will finish in 100ms.
+ for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
+ if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED
+ && dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING) {
+ Log.d(LOG_TAG, "Data shutdown complete.");
+ break;
+ }
+ SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
+ }
+
+ // hang up all active voice calls
+ if (phone.isInCall()) {
+ phone.mCT.ringingCall.hangupIfAlive();
+ phone.mCT.backgroundCall.hangupIfAlive();
+ phone.mCT.foregroundCall.hangupIfAlive();
+ }
+
+ cm.setRadioPower(false, null);
+ }
+
protected void updateSpnDisplay() {
int rule = phone.mSIMRecords.getDisplayRule(ss.getOperatorNumeric());
String spn = phone.mSIMRecords.getServiceProviderName();
@@ -583,12 +590,13 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
if (rule != curSpnRule
|| !TextUtils.equals(spn, curSpn)
|| !TextUtils.equals(plmn, curPlmn)) {
- boolean showSpn = mEmergencyOnly
- || (rule & SIMRecords.SPN_RULE_SHOW_SPN) == SIMRecords.SPN_RULE_SHOW_SPN;
+ boolean showSpn = !mEmergencyOnly
+ && (rule & SIMRecords.SPN_RULE_SHOW_SPN) == SIMRecords.SPN_RULE_SHOW_SPN;
boolean showPlmn =
(rule & SIMRecords.SPN_RULE_SHOW_PLMN) == SIMRecords.SPN_RULE_SHOW_PLMN;
Intent intent = new Intent(Intents.SPN_STRINGS_UPDATED_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(Intents.EXTRA_SHOW_SPN, showSpn);
intent.putExtra(Intents.EXTRA_SPN, spn);
intent.putExtra(Intents.EXTRA_SHOW_PLMN, showPlmn);
@@ -663,9 +671,9 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
newSS.setState (regCodeToServiceState(regState));
if (regState == 10 || regState == 12 || regState == 13 || regState == 14) {
- mNewEmergencyOnly = true;
+ mEmergencyOnly = true;
} else {
- mNewEmergencyOnly = false;
+ mEmergencyOnly = false;
}
// LAC and CID are -1 if not avail
@@ -732,6 +740,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
roaming = false;
}
newSS.setRoaming(roaming);
+ newSS.setEmergencyOnly(mEmergencyOnly);
pollStateDone();
}
}
@@ -877,7 +886,11 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
- boolean hasEmergencyOnlyChanged = mNewEmergencyOnly != mEmergencyOnly;
+ // Add an event log when connection state changes
+ if (ss.getState() != newSS.getState() || gprsState != newGPRSState) {
+ EventLog.writeEvent(EventLogTags.GSM_SERVICE_STATE_CHANGE,
+ ss.getState(), gprsState, newSS.getState(), newGPRSState);
+ }
ServiceState tss;
tss = ss;
@@ -890,9 +903,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
cellLoc = newCellLoc;
newCellLoc = tcl;
- mEmergencyOnly = mNewEmergencyOnly;
-
-
// Add an event log when network type switched
// TODO: we may add filtering to reduce the event logged,
// i.e. check preferred network setting, only switch to 2G, etc
@@ -900,8 +910,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
int cid = -1;
GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
if (loc != null) cid = loc.getCid();
- EventLog.List val = new EventLog.List(cid, networkType, newNetworkType);
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_GSM_RAT_SWITCHED, val);
+ EventLog.writeEvent(EventLogTags.GSM_RAT_SWITCHED, cid, networkType, newNetworkType);
Log.d(LOG_TAG,
"RAT switched " + networkTypeToString(networkType) + " -> "
+ networkTypeToString(newNetworkType) + " at cell " + cid);
@@ -918,14 +927,14 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
}
if (hasRegistered) {
- Checkin.updateStats(phone.getContext().getContentResolver(),
- Checkin.Stats.Tag.PHONE_GSM_REGISTERED, 1, 0.0);
networkAttachedRegistrants.notifyRegistrants();
}
if (hasChanged) {
String operatorNumeric;
+ updateSpnDisplay();
+
phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
ss.getOperatorAlphaLong());
@@ -994,10 +1003,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
phone.notifyServiceStateChanged(ss);
}
- if (hasChanged || hasEmergencyOnlyChanged) {
- updateSpnDisplay();
- }
-
if (hasGprsAttached) {
gprsAttachedRegistrants.notifyRegistrants();
}
@@ -1026,9 +1031,9 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
if (!mStartedGprsRegCheck && !mReportedGprsNoReg) {
mStartedGprsRegCheck = true;
- int check_period = Settings.Gservices.getInt(
+ int check_period = Settings.Secure.getInt(
phone.getContext().getContentResolver(),
- Settings.Gservices.GPRS_REGISTER_CHECK_PERIOD_MS,
+ Settings.Secure.GPRS_REGISTER_CHECK_PERIOD_MS,
DEFAULT_GPRS_CHECK_PERIOD_MILLIS);
sendMessageDelayed(obtainMessage(EVENT_CHECK_REPORT_GPRS),
check_period);
@@ -1554,6 +1559,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
(AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
alarm.setTimeZone(zoneId);
Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra("time-zone", zoneId);
phone.getContext().sendStickyBroadcast(intent);
}
@@ -1567,6 +1573,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
private void setAndBroadcastNetworkSetTime(long time) {
SystemClock.setCurrentTimeMillis(time);
Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra("time", time);
phone.getContext().sendStickyBroadcast(intent);
}
@@ -1617,7 +1624,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
notificationId = PS_NOTIFICATION;
break;
case CS_ENABLED:
- details = context.getText(com.android.internal.R.string.RestrictedOnAll);;
+ details = context.getText(com.android.internal.R.string.RestrictedOnAllVoice);;
break;
case CS_NORMAL_ENABLED:
details = context.getText(com.android.internal.R.string.RestrictedOnNormal);;
diff --git a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
deleted file mode 100644
index cb85002..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.gsm;
-
-import android.os.*;
-import android.text.util.Regex;
-import android.util.EventLog;
-import android.util.Log;
-
-import com.android.internal.telephony.CommandException;
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.DataConnection;
-import com.android.internal.telephony.DataLink;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.telephony.TelephonyEventLog;
-
-/**
- * {@hide}
- */
-public class PdpConnection extends DataConnection {
-
- private static final String LOG_TAG = "GSM";
- private static final boolean DBG = true;
-
- /** Fail cause of last PDP activate, from RIL_LastPDPActivateFailCause */
- private static final int PDP_FAIL_OPERATOR_BARRED = 0x08;
- private static final int PDP_FAIL_INSUFFICIENT_RESOURCES = 0x1A;
- private static final int PDP_FAIL_MISSING_UKNOWN_APN = 0x1B;
- private static final int PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C;
- private static final int PDP_FAIL_USER_AUTHENTICATION = 0x1D;
- private static final int PDP_FAIL_ACTIVATION_REJECT_GGSN = 0x1E;
- private static final int PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F;
- private static final int PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20;
- private static final int PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21;
- private static final int PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22;
- private static final int PDP_FAIL_NSAPI_IN_USE = 0x23;
- private static final int PDP_FAIL_PROTOCOL_ERRORS = 0x6F;
- private static final int PDP_FAIL_ERROR_UNSPECIFIED = 0xffff;
-
- private static final int PDP_FAIL_REGISTRATION_FAIL = -1;
- private static final int PDP_FAIL_GPRS_REGISTRATION_FAIL = -2;
-
- //***** Instance Variables
- private String pdp_name;
- private ApnSetting apn;
-
- //***** Constructor
- PdpConnection(GSMPhone phone) {
- super(phone);
- }
-
- /**
- * Setup PDP connection for provided apn
- * @param apn for this connection
- * @param onCompleted notify success or not after down
- */
- void connect(ApnSetting apn, Message onCompleted) {
- if (DBG) log("Connecting to carrier: '" + apn.carrier
- + "' APN: '" + apn.apn
- + "' proxy: '" + apn.proxy + "' port: '" + apn.port);
-
- setHttpProxy (apn.proxy, apn.port);
-
- state = State.ACTIVATING;
- this.apn = apn;
- onConnectCompleted = onCompleted;
- createTime = -1;
- lastFailTime = -1;
- lastFailCause = FailCause.NONE;
- receivedDisconnectReq = false;
-
- int authType = apn.authType;
- if (authType == -1) {
- authType = (apn.user != null) ? RILConstants.SETUP_DATA_AUTH_PAP_CHAP :
- RILConstants.SETUP_DATA_AUTH_NONE;
- }
- phone.mCM.setupDataCall(Integer.toString(RILConstants.SETUP_DATA_TECH_GSM),
- Integer.toString(RILConstants.DATA_PROFILE_DEFAULT), apn.apn, apn.user,
- apn.password, Integer.toString(authType),
- obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
- }
-
- private void tearDownData(Message msg) {
- if (phone.mCM.getRadioState().isOn()) {
- phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, msg));
- }
- }
-
- protected void disconnect(Message msg) {
- onDisconnect = msg;
- if (state == State.ACTIVE) {
- tearDownData(msg);
- } else if (state == State.ACTIVATING) {
- receivedDisconnectReq = true;
- } else {
- // state == INACTIVE. Nothing to do, so notify immediately.
- notifyDisconnect(msg);
- }
- }
-
- public void clearSettings() {
- super.clearSettings();
- apn = null;
- }
-
- public String toString() {
- return "State=" + state + " Apn=" + apn +
- " create=" + createTime + " lastFail=" + lastFailTime +
- " lastFailCause=" + lastFailCause;
- }
-
-
- protected void notifyFail(FailCause cause, Message onCompleted) {
- if (onCompleted == null) return;
-
- state = State.INACTIVE;
- lastFailCause = cause;
- lastFailTime = System.currentTimeMillis();
- onConnectCompleted = null;
-
- if (DBG) {
- log("Notify PDP fail at " + lastFailTime +
- " due to " + lastFailCause);
- }
-
- AsyncResult.forMessage(onCompleted, cause, new Exception());
- onCompleted.sendToTarget();
- }
-
- protected void notifySuccess(Message onCompleted) {
- if (onCompleted == null) {
- return;
- }
-
- state = State.ACTIVE;
- createTime = System.currentTimeMillis();
- onConnectCompleted = null;
- onCompleted.arg1 = cid;
-
- if (DBG) log("Notify PDP success at " + createTime);
-
- AsyncResult.forMessage(onCompleted);
- onCompleted.sendToTarget();
- }
-
- protected void notifyDisconnect(Message msg) {
- if (DBG) log("Notify PDP disconnect");
-
- if (msg != null) {
- AsyncResult.forMessage(msg);
- msg.sendToTarget();
- }
- clearSettings();
- }
-
- protected void onLinkStateChanged(DataLink.LinkState linkState) {
- switch (linkState) {
- case LINK_UP:
- notifySuccess(onConnectCompleted);
- break;
-
- case LINK_DOWN:
- case LINK_EXITED:
- phone.mCM.getLastPdpFailCause(
- obtainMessage (EVENT_GET_LAST_FAIL_DONE));
- break;
- }
- }
-
- protected FailCause getFailCauseFromRequest(int rilCause) {
- FailCause cause;
-
- switch (rilCause) {
- case PDP_FAIL_OPERATOR_BARRED:
- cause = FailCause.OPERATOR_BARRED;
- break;
- case PDP_FAIL_INSUFFICIENT_RESOURCES:
- cause = FailCause.INSUFFICIENT_RESOURCES;
- break;
- case PDP_FAIL_MISSING_UKNOWN_APN:
- cause = FailCause.MISSING_UKNOWN_APN;
- break;
- case PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE:
- cause = FailCause.UNKNOWN_PDP_ADDRESS;
- break;
- case PDP_FAIL_USER_AUTHENTICATION:
- cause = FailCause.USER_AUTHENTICATION;
- break;
- case PDP_FAIL_ACTIVATION_REJECT_GGSN:
- cause = FailCause.ACTIVATION_REJECT_GGSN;
- break;
- case PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED:
- cause = FailCause.ACTIVATION_REJECT_UNSPECIFIED;
- break;
- case PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER:
- cause = FailCause.SERVICE_OPTION_OUT_OF_ORDER;
- break;
- case PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED:
- cause = FailCause.SERVICE_OPTION_NOT_SUPPORTED;
- break;
- case PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED:
- cause = FailCause.SERVICE_OPTION_NOT_SUBSCRIBED;
- break;
- case PDP_FAIL_NSAPI_IN_USE:
- cause = FailCause.NSAPI_IN_USE;
- break;
- case PDP_FAIL_PROTOCOL_ERRORS:
- cause = FailCause.PROTOCOL_ERRORS;
- break;
- case PDP_FAIL_ERROR_UNSPECIFIED:
- cause = FailCause.UNKNOWN;
- break;
- case PDP_FAIL_REGISTRATION_FAIL:
- cause = FailCause.REGISTRATION_FAIL;
- break;
- case PDP_FAIL_GPRS_REGISTRATION_FAIL:
- cause = FailCause.GPRS_REGISTRATION_FAIL;
- break;
- default:
- cause = FailCause.UNKNOWN;
- }
- return cause;
- }
-
- protected void log(String s) {
- Log.d(LOG_TAG, "[PdpConnection] " + s);
- }
-
- @Override
- protected void onDeactivated(AsyncResult ar) {
- notifyDisconnect((Message) ar.userObj);
- if (DBG) log("PDP Connection Deactivated");
- }
-
- @Override
- protected void onSetupConnectionCompleted(AsyncResult ar) {
- if (ar.exception != null) {
- Log.e(LOG_TAG, "PDP Context Init failed " + ar.exception);
-
- if (receivedDisconnectReq) {
- // Don't bother reporting the error if there's already a
- // pending disconnect request, since DataConnectionTracker
- // has already updated its state.
- notifyDisconnect(onDisconnect);
- } else {
- if ( ar.exception instanceof CommandException &&
- ((CommandException) (ar.exception)).getCommandError()
- == CommandException.Error.RADIO_NOT_AVAILABLE) {
- notifyFail(FailCause.RADIO_NOT_AVAILABLE,
- onConnectCompleted);
- } else {
- phone.mCM.getLastPdpFailCause(
- obtainMessage(EVENT_GET_LAST_FAIL_DONE));
- }
- }
- } else {
- if (receivedDisconnectReq) {
- // Don't bother reporting success if there's already a
- // pending disconnect request, since DataConnectionTracker
- // has already updated its state.
- tearDownData(onDisconnect);
- } else {
- String[] response = ((String[]) ar.result);
- cid = Integer.parseInt(response[0]);
-
- if (response.length > 2) {
- interfaceName = response[1];
- ipAddress = response[2];
- 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 (NULL_IP.equals(dnsServers[0]) && NULL_IP.equals(dnsServers[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
- // if Proxy is an IP-address.
- // Otherwise, the default APN will not be restored anymore.
- if (!apn.types[0].equals(Phone.APN_TYPE_MMS)
- || !isIpAddress(apn.mmsProxy)) {
- EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_BAD_DNS_ADDRESS,
- dnsServers[0]);
- phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_FORCE_RETRY));
- return;
- }
- }
- }
-
- onLinkStateChanged(DataLink.LinkState.LINK_UP);
-
- if (DBG) log("PDP setup on cid = " + cid);
- }
- }
- }
-
- private boolean isIpAddress(String address) {
- if (address == null) return false;
-
- return Regex.IP_ADDRESS_PATTERN.matcher(apn.mmsProxy).matches();
- }
-
- public ApnSetting getApn() {
- return this.apn;
- }
-}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
index 076da6b..feb508a 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
@@ -16,22 +16,10 @@
package com.android.internal.telephony.gsm;
-import android.content.pm.PackageManager;
-import android.os.AsyncResult;
-import android.os.Handler;
-import android.os.Looper;
import android.os.Message;
-import android.os.ServiceManager;
-import android.telephony.PhoneNumberUtils;
import android.util.Log;
-import com.android.internal.telephony.AdnRecord;
-import com.android.internal.telephony.AdnRecordCache;
import com.android.internal.telephony.IccPhoneBookInterfaceManager;
-import com.android.internal.telephony.PhoneProxy;
-
-import java.util.ArrayList;
-import java.util.List;
/**
* SimPhoneBookInterfaceManager to provide an inter-process communication to
@@ -42,20 +30,6 @@ import java.util.List;
public class SimPhoneBookInterfaceManager extends IccPhoneBookInterfaceManager {
static final String LOG_TAG = "GSM";
-
- Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- AsyncResult ar;
-
- switch(msg.what) {
- default:
- mBaseHandler.handleMessage(msg);
- break;
- }
- }
- };
-
public SimPhoneBookInterfaceManager(GSMPhone phone) {
super(phone);
adnCache = phone.mSIMRecords.getAdnCache();
@@ -67,6 +41,11 @@ public class SimPhoneBookInterfaceManager extends IccPhoneBookInterfaceManager {
}
protected void finalize() {
+ try {
+ super.finalize();
+ } catch (Throwable throwable) {
+ Log.e(LOG_TAG, "Error while finalizing:", throwable);
+ }
if(DBG) Log.d(LOG_TAG, "SimPhoneBookInterfaceManager finalized");
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
index 875d8d0..2028ca4 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
@@ -25,10 +25,10 @@ import android.util.Log;
import com.android.internal.telephony.IccConstants;
import com.android.internal.telephony.IccSmsInterfaceManager;
import com.android.internal.telephony.IccUtils;
-import com.android.internal.telephony.PhoneProxy;
import com.android.internal.telephony.SmsRawData;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import static android.telephony.SmsManager.STATUS_ON_ICC_FREE;
@@ -65,8 +65,7 @@ public class SimSmsInterfaceManager 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)
@@ -88,6 +87,11 @@ public class SimSmsInterfaceManager extends IccSmsInterfaceManager {
}
protected void finalize() {
+ try {
+ super.finalize();
+ } catch (Throwable throwable) {
+ Log.e(LOG_TAG, "Error while finalizing:", throwable);
+ }
if(DBG) Log.d(LOG_TAG, "SimSmsInterfaceManager finalized");
}
@@ -106,7 +110,7 @@ public class SimSmsInterfaceManager extends IccSmsInterfaceManager {
updateMessageOnIccEf(int index, int status, byte[] pdu) {
if (DBG) log("updateMessageOnIccEf: index=" + index +
" status=" + status + " ==> " +
- "("+ pdu + ")");
+ "("+ Arrays.toString(pdu) + ")");
enforceReceiveAndSend("Updating message on SIM");
synchronized(mLock) {
mSuccess = false;
@@ -118,7 +122,7 @@ public class SimSmsInterfaceManager extends IccSmsInterfaceManager {
mPhone.mCM.deleteSmsOnSim(index, response);
} else {
byte[] record = makeSmsRecordData(status, pdu);
- ((SIMFileHandler)mPhone.getIccFileHandler()).updateEFLinearFixed(
+ mPhone.getIccFileHandler().updateEFLinearFixed(
IccConstants.EF_SMS,
index, record, null, response);
}
@@ -142,7 +146,8 @@ public class SimSmsInterfaceManager extends IccSmsInterfaceManager {
*/
public boolean copyMessageToIccEf(int status, byte[] pdu, byte[] smsc) {
if (DBG) log("copyMessageToIccEf: status=" + status + " ==> " +
- "pdu=("+ pdu + "), smsm=(" + smsc +")");
+ "pdu=("+ Arrays.toString(pdu) +
+ "), smsm=(" + Arrays.toString(smsc) +")");
enforceReceiveAndSend("Copying message to SIM");
synchronized(mLock) {
mSuccess = false;
@@ -175,8 +180,7 @@ public class SimSmsInterfaceManager extends IccSmsInterfaceManager {
"Reading messages from SIM");
synchronized(mLock) {
Message response = mHandler.obtainMessage(EVENT_LOAD_DONE);
- ((SIMFileHandler)mPhone.getIccFileHandler()).loadEFLinearFixedAll(IccConstants.EF_SMS,
- response);
+ mPhone.getIccFileHandler().loadEFLinearFixedAll(IccConstants.EF_SMS, response);
try {
mLock.wait();
diff --git a/telephony/java/com/android/internal/telephony/gsm/SpnOverride.java b/telephony/java/com/android/internal/telephony/gsm/SpnOverride.java
index 9ea30101..918c2d2 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SpnOverride.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SpnOverride.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.android.internal.telephony.gsm;
import java.io.File;
diff --git a/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
index 9caae3d..41e527c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
@@ -409,7 +409,7 @@ public class UsimPhoneBookManager extends Handler implements IccConstants {
case USIM_EFIAP_TAG:
case USIM_EFSNE_TAG:
data = tlv.getData();
- int efid = data[0] << 8 | data[1];
+ int efid = ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
val.put(tag, efid);
break;
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/VoiceMailConstants.java b/telephony/java/com/android/internal/telephony/gsm/VoiceMailConstants.java
index d4e1f72..0e49e35 100644
--- a/telephony/java/com/android/internal/telephony/gsm/VoiceMailConstants.java
+++ b/telephony/java/com/android/internal/telephony/gsm/VoiceMailConstants.java
@@ -28,6 +28,7 @@ import java.io.IOException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+
import com.android.internal.util.XmlUtils;
/**
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java b/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java
index bfde616..ce4c459 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java
@@ -203,7 +203,7 @@ class CommandParamsFactory extends Handler {
}
private void sendCmdParams(ResultCode resCode) {
- mCaller.sendMessageParamsDecoded(resCode, mCmdParams);
+ mCaller.sendMsgParamsDecoded(resCode, mCmdParams);
}
/**
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java b/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java
index 1cf38ed..a82177c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java
@@ -20,18 +20,18 @@ import com.android.internal.telephony.gsm.SIMFileHandler;
import com.android.internal.telephony.IccUtils;
import android.os.Handler;
-import android.os.HandlerState;
-import android.os.HandlerStateMachine;
+import com.android.internal.util.HierarchicalState;
+import com.android.internal.util.HierarchicalStateMachine;
import android.os.Message;
/**
* Class used for queuing raw ril messages, decoding them into CommanParams
* objects and sending the result back to the STK Service.
*/
-class RilMessageDecoder extends HandlerStateMachine {
+class RilMessageDecoder extends HierarchicalStateMachine {
// constants
- private static final int START = 1;
+ private static final int CMD_START = 1;
private static final int CMD_PARAMS_READY = 2;
// members
@@ -54,6 +54,7 @@ class RilMessageDecoder extends HandlerStateMachine {
public static synchronized RilMessageDecoder getInstance(Handler caller, SIMFileHandler fh) {
if (sInstance == null) {
sInstance = new RilMessageDecoder(caller, fh);
+ sInstance.start();
}
return sInstance;
}
@@ -65,7 +66,7 @@ class RilMessageDecoder extends HandlerStateMachine {
* @param rilMsg
*/
public void sendStartDecodingMessageParams(RilMessage rilMsg) {
- Message msg = obtainMessage(START);
+ Message msg = obtainMessage(CMD_START);
msg.obj = rilMsg;
sendMessage(msg);
}
@@ -76,7 +77,7 @@ class RilMessageDecoder extends HandlerStateMachine {
* @param resCode
* @param cmdParams
*/
- public void sendMessageParamsDecoded(ResultCode resCode, CommandParams cmdParams) {
+ public void sendMsgParamsDecoded(ResultCode resCode, CommandParams cmdParams) {
Message msg = obtainMessage(RilMessageDecoder.CMD_PARAMS_READY);
msg.arg1 = resCode.value();
msg.obj = cmdParams;
@@ -91,28 +92,31 @@ class RilMessageDecoder extends HandlerStateMachine {
private RilMessageDecoder(Handler caller, SIMFileHandler fh) {
super("RilMessageDecoder");
- setDbg(false);
+
+ addState(mStateStart);
+ addState(mStateCmdParamsReady);
setInitialState(mStateStart);
mCaller = caller;
mCmdParamsFactory = CommandParamsFactory.getInstance(this, fh);
}
- private class StateStart extends HandlerState {
- @Override public void processMessage(Message msg) {
- if (msg.what == START) {
+ private class StateStart extends HierarchicalState {
+ @Override protected boolean processMessage(Message msg) {
+ if (msg.what == CMD_START) {
if (decodeMessageParams((RilMessage)msg.obj)) {
transitionTo(mStateCmdParamsReady);
}
} else {
StkLog.d(this, "StateStart unexpected expecting START=" +
- START + " got " + msg.what);
+ CMD_START + " got " + msg.what);
}
+ return true;
}
}
- private class StateCmdParamsReady extends HandlerState {
- @Override public void processMessage(Message msg) {
+ private class StateCmdParamsReady extends HierarchicalState {
+ @Override protected boolean processMessage(Message msg) {
if (msg.what == CMD_PARAMS_READY) {
mCurrentRilMessage.mResCode = ResultCode.fromInt(msg.arg1);
mCurrentRilMessage.mData = msg.obj;
@@ -123,6 +127,7 @@ class RilMessageDecoder extends HandlerStateMachine {
+ CMD_PARAMS_READY + " got " + msg.what);
deferMessage(msg);
}
+ return true;
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java b/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java
index 9268037..29ed95c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java
@@ -467,8 +467,7 @@ public class StkService extends Handler implements AppInterface {
sInstance = new StkService(ci, sr, context, fh, sc);
StkLog.d(sInstance, "NEW sInstance");
} else if ((sr != null) && (mSimRecords != sr)) {
- StkLog.d(sInstance, String.format(
- "Reinitialize the Service with SIMRecords sr=0x%x.", sr));
+ StkLog.d(sInstance, "Reinitialize the Service with SIMRecords");
mSimRecords = sr;
// re-Register for SIM ready event.
diff --git a/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java b/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java
deleted file mode 100644
index 9e1af31..0000000
--- a/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.telephonytest;
-
-import junit.framework.TestSuite;
-
-import android.test.InstrumentationTestRunner;
-import android.test.InstrumentationTestSuite;
-
-/**
- * Instrumentation Test Runner for all Telephony unit tests.
- *
- * Running all tests:
- *
- * runtest telephony-unit
- * or
- * adb shell am instrument -w com.android.telephonytest/.TelephonyUnitTestRunner
- */
-
-public class TelephonyUnitTestRunner extends InstrumentationTestRunner {
-
- @Override
- public TestSuite getAllTests() {
- TestSuite suite = new InstrumentationTestSuite(this);
- suite.addTestSuite(com.android.telephonytest.unit.CallerInfoUnitTest.class);
- suite.addTestSuite(com.android.telephonytest.unit.PhoneNumberUtilsUnitTest.class);
- return suite;
- }
-
- @Override
- public ClassLoader getLoader() {
- return TelephonyUnitTestRunner.class.getClassLoader();
- }
-}
diff --git a/telephony/tests/TelephonyTest/Android.mk b/telephony/tests/telephonytests/Android.mk
index 1ef8448..45e265a 100644
--- a/telephony/tests/TelephonyTest/Android.mk
+++ b/telephony/tests/telephonytests/Android.mk
@@ -7,6 +7,6 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_PACKAGE_NAME := telephonytest
+LOCAL_PACKAGE_NAME := FrameworksTelephonyTests
include $(BUILD_PACKAGE)
diff --git a/telephony/tests/TelephonyTest/AndroidManifest.xml b/telephony/tests/telephonytests/AndroidManifest.xml
index b2a481b..6a97423 100644
--- a/telephony/tests/TelephonyTest/AndroidManifest.xml
+++ b/telephony/tests/telephonytests/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.telephonytest">
+ package="com.android.frameworks.telephonytests">
<application>
<uses-library android:name="android.test.runner" />
@@ -28,9 +28,10 @@
</intent-filter>
</activity>
</application>
- <instrumentation android:name=".TelephonyUnitTestRunner"
- android:targetPackage="com.android.telephonytest"
- android:label="Telephony unit tests InstrumentationRunner">
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.frameworks.telephonytests"
+ android:label="Frameworks Telephony Tests">
</instrumentation>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
+
</manifest>
diff --git a/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java
new file mode 100644
index 0000000..02590d3
--- /dev/null
+++ b/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java
@@ -0,0 +1,475 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.SpannableStringBuilder;
+import android.telephony.PhoneNumberUtils;
+
+import junit.framework.TestCase;
+
+public class PhoneNumberUtilsTest extends TestCase {
+
+ @SmallTest
+ public void testExtractNetworkPortion() throws Exception {
+ assertEquals(
+ "+17005554141",
+ PhoneNumberUtils.extractNetworkPortion("+17005554141")
+ );
+
+ assertEquals(
+ "+17005554141",
+ PhoneNumberUtils.extractNetworkPortion("+1 (700).555-4141")
+ );
+
+ assertEquals(
+ "17005554141",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-4141")
+ );
+
+ // This may seem wrong, but it's probably ok
+ assertEquals(
+ "17005554141*#",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-4141*#")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-41NN")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-41NN,1234")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-41NN;1234")
+ );
+
+ // An MMI string is unperterbed, even though it contains a
+ // (valid in this case) embedded +
+ assertEquals(
+ "**21**17005554141#",
+ PhoneNumberUtils.extractNetworkPortion("**21**+17005554141#")
+ //TODO this is the correct result, although the above
+ //result has been returned since change 31776
+ //"**21**+17005554141#"
+ );
+
+ assertEquals("", PhoneNumberUtils.extractNetworkPortion(""));
+
+ assertEquals("", PhoneNumberUtils.extractNetworkPortion(",1234"));
+
+ byte [] b = new byte[20];
+ b[0] = (byte) 0x81; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55;
+ b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xF0;
+ assertEquals("17005550020",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 7));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55;
+ b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xF0;
+ assertEquals("+17005550020",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 7));
+
+ byte[] bRet = PhoneNumberUtils.networkPortionToCalledPartyBCD("+17005550020");
+ assertEquals(7, bRet.length);
+ for (int i = 0; i < 7; i++) {
+ assertEquals(b[i], bRet[i]);
+ }
+
+ bRet = PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength("+17005550020");
+ assertEquals(8, bRet.length);
+ assertEquals(bRet[0], 7);
+ for (int i = 1; i < 8; i++) {
+ assertEquals(b[i - 1], bRet[i]);
+ }
+
+ bRet = PhoneNumberUtils.networkPortionToCalledPartyBCD("7005550020");
+ assertEquals("7005550020",
+ PhoneNumberUtils.calledPartyBCDToString(bRet, 0, bRet.length));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55;
+ b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xB0;
+ assertEquals("17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 7));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55;
+ b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xB0;
+ assertEquals("+17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 7));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x2A; b[2] = (byte) 0xB1;
+ assertEquals("*21#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 3));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x2B; b[2] = (byte) 0xB1;
+ assertEquals("#21#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 3));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x2A; b[2] = (byte) 0xB1;
+ assertEquals("*21#+",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 3));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0xAA; b[2] = (byte) 0x12; b[3] = (byte) 0xFB;
+ assertEquals("**21#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 4));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0xAA; b[2] = (byte) 0x12; b[3] = (byte) 0xFB;
+ assertEquals("**21#+",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 4));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x9A; b[2] = (byte) 0xA9; b[3] = (byte) 0x71;
+ b[4] = (byte) 0x00; b[5] = (byte) 0x55; b[6] = (byte) 0x05; b[7] = (byte) 0x20;
+ b[8] = (byte) 0xB0;
+ assertEquals("*99*17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 9));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x9A; b[2] = (byte) 0xA9; b[3] = (byte) 0x71;
+ b[4] = (byte) 0x00; b[5] = (byte) 0x55; b[6] = (byte) 0x05; b[7] = (byte) 0x20;
+ b[8] = (byte) 0xB0;
+ assertEquals("*99*+17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 9));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0xAA; b[2] = (byte) 0x12; b[3] = (byte) 0x1A;
+ b[4] = (byte) 0x07; b[5] = (byte) 0x50; b[6] = (byte) 0x55; b[7] = (byte) 0x00;
+ b[8] = (byte) 0x02; b[9] = (byte) 0xFB;
+ assertEquals("**21*17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 10));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0xAA; b[2] = (byte) 0x12; b[3] = (byte) 0x1A;
+ b[4] = (byte) 0x07; b[5] = (byte) 0x50; b[6] = (byte) 0x55; b[7] = (byte) 0x00;
+ b[8] = (byte) 0x02; b[9] = (byte) 0xFB;
+ assertEquals("**21*+17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 10));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x2A; b[2] = (byte) 0xA1; b[3] = (byte) 0x71;
+ b[4] = (byte) 0x00; b[5] = (byte) 0x55; b[6] = (byte) 0x05; b[7] = (byte) 0x20;
+ b[8] = (byte) 0xF0;
+ assertEquals("*21*17005550020",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 9));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x2A; b[2] = (byte) 0xB1; b[3] = (byte) 0x71;
+ b[4] = (byte) 0x00; b[5] = (byte) 0x55; b[6] = (byte) 0x05; b[7] = (byte) 0x20;
+ b[8] = (byte) 0xF0;
+ assertEquals("*21#+17005550020",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 9));
+
+ assertNull(PhoneNumberUtils.extractNetworkPortion(null));
+ assertNull(PhoneNumberUtils.extractPostDialPortion(null));
+ assertTrue(PhoneNumberUtils.compare(null, null));
+ assertFalse(PhoneNumberUtils.compare(null, "123"));
+ assertFalse(PhoneNumberUtils.compare("123", null));
+ assertNull(PhoneNumberUtils.toCallerIDMinMatch(null));
+ assertNull(PhoneNumberUtils.getStrippedReversed(null));
+ assertNull(PhoneNumberUtils.stringFromStringAndTOA(null, 1));
+ }
+
+ @SmallTest
+ public void testExtractNetworkPortionAlt() throws Exception {
+ assertEquals(
+ "+17005554141",
+ PhoneNumberUtils.extractNetworkPortionAlt("+17005554141")
+ );
+
+ assertEquals(
+ "+17005554141",
+ PhoneNumberUtils.extractNetworkPortionAlt("+1 (700).555-4141")
+ );
+
+ assertEquals(
+ "17005554141",
+ PhoneNumberUtils.extractNetworkPortionAlt("1 (700).555-4141")
+ );
+
+ // This may seem wrong, but it's probably ok
+ assertEquals(
+ "17005554141*#",
+ PhoneNumberUtils.extractNetworkPortionAlt("1 (700).555-4141*#")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortionAlt("1 (700).555-41NN")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortionAlt("1 (700).555-41NN,1234")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortionAlt("1 (700).555-41NN;1234")
+ );
+
+ // An MMI string is unperterbed, even though it contains a
+ // (valid in this case) embedded +
+ assertEquals(
+ "**21**+17005554141#",
+ PhoneNumberUtils.extractNetworkPortionAlt("**21**+17005554141#")
+ );
+
+ assertEquals(
+ "*31#+447966164208",
+ PhoneNumberUtils.extractNetworkPortionAlt("*31#+447966164208")
+ );
+
+ assertEquals(
+ "*31#+447966164208",
+ PhoneNumberUtils.extractNetworkPortionAlt("*31# (+44) 79 6616 4208")
+ );
+
+ assertEquals("", PhoneNumberUtils.extractNetworkPortionAlt(""));
+
+ assertEquals("", PhoneNumberUtils.extractNetworkPortionAlt(",1234"));
+
+ assertNull(PhoneNumberUtils.extractNetworkPortionAlt(null));
+ }
+
+ @SmallTest
+ public void testB() throws Exception {
+ assertEquals("", PhoneNumberUtils.extractPostDialPortion("+17005554141"));
+ assertEquals("", PhoneNumberUtils.extractPostDialPortion("+1 (700).555-4141"));
+ assertEquals("", PhoneNumberUtils.extractPostDialPortion("+1 (700).555-41NN"));
+ assertEquals(",1234", PhoneNumberUtils.extractPostDialPortion("+1 (700).555-41NN,1234"));
+ assertEquals(";1234", PhoneNumberUtils.extractPostDialPortion("+1 (700).555-41NN;1234"));
+ assertEquals(";1234,;N",
+ PhoneNumberUtils.extractPostDialPortion("+1 (700).555-41NN;1-2.34 ,;N"));
+ }
+
+ @SmallTest
+ public void testCompare() throws Exception {
+ // this is odd
+ assertFalse(PhoneNumberUtils.compare("", ""));
+
+ assertTrue(PhoneNumberUtils.compare("911", "911"));
+ assertFalse(PhoneNumberUtils.compare("911", "18005550911"));
+ assertTrue(PhoneNumberUtils.compare("5555", "5555"));
+ assertFalse(PhoneNumberUtils.compare("5555", "180055555555"));
+
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "+17005554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "+1 (700).555-4141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "+1 (700).555-4141,1234"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "17005554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "7005554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "5554141"));
+ assertTrue(PhoneNumberUtils.compare("17005554141", "5554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "01117005554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "0017005554141"));
+ assertTrue(PhoneNumberUtils.compare("17005554141", "0017005554141"));
+
+
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "**31#+17005554141"));
+
+ assertFalse(PhoneNumberUtils.compare("+1 999 7005554141", "+1 7005554141"));
+ assertTrue(PhoneNumberUtils.compare("011 1 7005554141", "7005554141"));
+
+ assertFalse(PhoneNumberUtils.compare("011 11 7005554141", "+17005554141"));
+
+ assertFalse(PhoneNumberUtils.compare("+17005554141", "7085882300"));
+
+ assertTrue(PhoneNumberUtils.compare("+44 207 792 3490", "0 207 792 3490"));
+
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "00 207 792 3490"));
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "011 207 792 3490"));
+
+ /***** FIXME's ******/
+ //
+ // MMI header should be ignored
+ assertFalse(PhoneNumberUtils.compare("+17005554141", "**31#17005554141"));
+
+ // It's too bad this is false
+ // +44 (0) 207 792 3490 is not a dialable number
+ // but it is commonly how European phone numbers are written
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "+44 (0) 207 792 3490"));
+
+ // The japanese international prefix, for example, messes us up
+ // But who uses a GSM phone in Japan?
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "010 44 207 792 3490"));
+
+ // The Australian one messes us up too
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "0011 44 207 792 3490"));
+
+ // The Russian trunk prefix messes us up, as does current
+ // Russian area codes (which bein with 0)
+
+ assertFalse(PhoneNumberUtils.compare("+7(095)9100766", "8(095)9100766"));
+
+ // 444 is not a valid country code, but
+ // matchIntlPrefixAndCC doesnt know this
+ assertTrue(PhoneNumberUtils.compare("+444 207 792 3490", "0 207 792 3490"));
+
+ // compare SMS short code
+ assertTrue(PhoneNumberUtils.compare("404-04", "40404"));
+ }
+
+
+ @SmallTest
+ public void testToCallerIDIndexable() throws Exception {
+ assertEquals("1414555", PhoneNumberUtils.toCallerIDMinMatch("17005554141"));
+ assertEquals("1414555", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-4141"));
+ assertEquals("1414555", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-4141,1234"));
+ assertEquals("1414555", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-4141;1234"));
+
+ //this seems wrong, or at least useless
+ assertEquals("NN14555", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-41NN"));
+
+ //<shrug> -- these are all not useful, but not terribly wrong
+ assertEquals("", PhoneNumberUtils.toCallerIDMinMatch(""));
+ assertEquals("0032", PhoneNumberUtils.toCallerIDMinMatch("2300"));
+ assertEquals("0032+", PhoneNumberUtils.toCallerIDMinMatch("+2300"));
+ assertEquals("#130#*", PhoneNumberUtils.toCallerIDMinMatch("*#031#"));
+ }
+
+ @SmallTest
+ public void testGetIndexable() throws Exception {
+ assertEquals("14145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-4141"));
+ assertEquals("14145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-4141,1234"));
+ assertEquals("14145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-4141;1234"));
+
+ //this seems wrong, or at least useless
+ assertEquals("NN145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-41NN"));
+
+ //<shrug> -- these are all not useful, but not terribly wrong
+ assertEquals("", PhoneNumberUtils.getStrippedReversed(""));
+ assertEquals("0032", PhoneNumberUtils.getStrippedReversed("2300"));
+ assertEquals("0032+", PhoneNumberUtils.getStrippedReversed("+2300"));
+ assertEquals("#130#*", PhoneNumberUtils.getStrippedReversed("*#031#"));
+ }
+
+ @SmallTest
+ public void testNanpFormatting() {
+ SpannableStringBuilder number = new SpannableStringBuilder();
+ number.append("8005551212");
+ PhoneNumberUtils.formatNanpNumber(number);
+ assertEquals("800-555-1212", number.toString());
+
+ number.clear();
+ number.append("800555121");
+ PhoneNumberUtils.formatNanpNumber(number);
+ assertEquals("800-555-121", number.toString());
+
+ number.clear();
+ number.append("555-1212");
+ PhoneNumberUtils.formatNanpNumber(number);
+ assertEquals("555-1212", number.toString());
+
+ number.clear();
+ number.append("800-55512");
+ PhoneNumberUtils.formatNanpNumber(number);
+ assertEquals("800-555-12", number.toString());
+
+ number.clear();
+ number.append("46645");
+ PhoneNumberUtils.formatNanpNumber(number);
+ assertEquals("46645", number.toString());
+ }
+
+ @SmallTest
+ public void testConvertKeypadLettersToDigits() {
+ assertEquals("1-800-4664-411",
+ PhoneNumberUtils.convertKeypadLettersToDigits("1-800-GOOG-411"));
+ assertEquals("18004664411",
+ PhoneNumberUtils.convertKeypadLettersToDigits("1800GOOG411"));
+ assertEquals("1-800-466-4411",
+ PhoneNumberUtils.convertKeypadLettersToDigits("1-800-466-4411"));
+ assertEquals("18004664411",
+ PhoneNumberUtils.convertKeypadLettersToDigits("18004664411"));
+ assertEquals("222-333-444-555-666-7777-888-9999",
+ PhoneNumberUtils.convertKeypadLettersToDigits(
+ "ABC-DEF-GHI-JKL-MNO-PQRS-TUV-WXYZ"));
+ assertEquals("222-333-444-555-666-7777-888-9999",
+ PhoneNumberUtils.convertKeypadLettersToDigits(
+ "abc-def-ghi-jkl-mno-pqrs-tuv-wxyz"));
+ assertEquals("(800) 222-3334",
+ PhoneNumberUtils.convertKeypadLettersToDigits("(800) ABC-DEFG"));
+ }
+
+ // To run this test, the device has to be registered with network
+ public void testCheckAndProcessPlusCode() {
+ assertEquals("0118475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+8475797000"));
+ assertEquals("18475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+18475797000"));
+ assertEquals("0111234567",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+1234567"));
+ assertEquals("01123456700000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+23456700000"));
+ assertEquals("01111875767800",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+11875767800"));
+ assertEquals("8475797000,18475231753",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,+18475231753"));
+ assertEquals("0118475797000,18475231753",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+8475797000,+18475231753"));
+ assertEquals("8475797000;0118469312345",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000;+8469312345"));
+ assertEquals("8475797000,0111234567",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,+1234567"));
+ assertEquals("847597000;01111875767000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("847597000;+11875767000"));
+ assertEquals("8475797000,,0118469312345",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,,+8469312345"));
+ assertEquals("8475797000;,0118469312345",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000;,+8469312345"));
+ assertEquals("8475797000,;18475231753",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,;+18475231753"));
+ assertEquals("8475797000;,01111875767000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000;,+11875767000"));
+ assertEquals("8475797000,;01111875767000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,;+11875767000"));
+ assertEquals("8475797000,,,01111875767000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,,,+11875767000"));
+ assertEquals("8475797000;,,01111875767000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000;,,+11875767000"));
+ assertEquals("+;,8475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+;,8475797000"));
+ assertEquals("8475797000,",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,"));
+ assertEquals("847+579-7000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("847+579-7000"));
+ assertEquals(",8475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode(",8475797000"));
+ assertEquals(";;8475797000,,",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode(";;8475797000,,"));
+ assertEquals("+this+is$weird;,+",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+this+is$weird;,+"));
+ assertEquals("",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCode(""));
+ assertNull(PhoneNumberUtils.cdmaCheckAndProcessPlusCode(null));
+ }
+
+ @SmallTest
+ public void testCheckAndProcessPlusCodeByNumberFormat() {
+ assertEquals("18475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+18475797000",
+ PhoneNumberUtils.FORMAT_NANP,PhoneNumberUtils.FORMAT_NANP));
+ assertEquals("+18475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+18475797000",
+ PhoneNumberUtils.FORMAT_NANP,PhoneNumberUtils.FORMAT_JAPAN));
+ assertEquals("+18475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+18475797000",
+ PhoneNumberUtils.FORMAT_NANP,PhoneNumberUtils.FORMAT_UNKNOWN));
+ assertEquals("+18475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+18475797000",
+ PhoneNumberUtils.FORMAT_JAPAN,PhoneNumberUtils.FORMAT_JAPAN));
+ assertEquals("+18475797000",
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+18475797000",
+ PhoneNumberUtils.FORMAT_UNKNOWN,PhoneNumberUtils.FORMAT_UNKNOWN));
+ }
+}
diff --git a/telephony/tests/telephonytests/src/android/telephony/PhoneNumberWatcherTest.java b/telephony/tests/telephonytests/src/android/telephony/PhoneNumberWatcherTest.java
new file mode 100644
index 0000000..88eaecd
--- /dev/null
+++ b/telephony/tests/telephonytests/src/android/telephony/PhoneNumberWatcherTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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/internal/telephony/ATResponseParserTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/ATResponseParserTest.java
new file mode 100644
index 0000000..81727e4
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/ATResponseParserTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class ATResponseParserTest extends TestCase {
+ @SmallTest
+ public void testBasic() throws Exception {
+ ATResponseParser p = new ATResponseParser("+CREG: 0");
+
+ assertEquals(0, p.nextInt());
+
+ assertFalse(p.hasMore());
+
+ try {
+ p.nextInt();
+ fail("exception expected");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+CREG: 0,1");
+ assertEquals(0, p.nextInt());
+ assertEquals(1, p.nextInt());
+ assertFalse(p.hasMore());
+
+ p = new ATResponseParser("+CREG: 0, 1");
+ assertEquals(0, p.nextInt());
+ assertEquals(1, p.nextInt());
+ assertFalse(p.hasMore());
+
+ p = new ATResponseParser("+CREG: 0, 1,");
+ assertEquals(0, p.nextInt());
+ assertEquals(1, p.nextInt());
+ // this seems odd but is probably OK
+ assertFalse(p.hasMore());
+ try {
+ p.nextInt();
+ fail("exception expected");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+CREG: 0, 1 ");
+ assertEquals(0, p.nextInt());
+ assertEquals(1, p.nextInt());
+ assertFalse(p.hasMore());
+
+ p = new ATResponseParser("0, 1 ");
+ // no prefix -> exception
+ try {
+ p.nextInt();
+ fail("exception expected");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+CREG: 0, 1, 5");
+ assertFalse(p.nextBoolean());
+ assertTrue(p.nextBoolean());
+ try {
+ // is this over-constraining?
+ p.nextBoolean();
+ fail("exception expected");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+CLCC: 1,0,2,0,0,\"+18005551212\",145");
+
+ assertEquals(1, p.nextInt());
+ assertFalse(p.nextBoolean());
+ assertEquals(2, p.nextInt());
+ assertEquals(0, p.nextInt());
+ assertEquals(0, p.nextInt());
+ assertEquals("+18005551212", p.nextString());
+ assertEquals(145, p.nextInt());
+ assertFalse(p.hasMore());
+
+ p = new ATResponseParser("+CLCC: 1,0,2,0,0,\"+18005551212,145");
+
+ assertEquals(1, p.nextInt());
+ assertFalse(p.nextBoolean());
+ assertEquals(2, p.nextInt());
+ assertEquals(0, p.nextInt());
+ assertEquals(0, p.nextInt());
+ try {
+ p.nextString();
+ fail("expected ex");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+FOO: \"\"");
+ assertEquals("", p.nextString());
+ }
+}
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java
new file mode 100644
index 0000000..8a4a285
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * {@hide}
+ */
+public class AdnRecordTest extends TestCase {
+
+ @SmallTest
+ public void testBasic() throws Exception {
+ AdnRecord adn;
+
+ //
+ // Typical record
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("566F696365204D61696C07918150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("+18056377243", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Empty records, empty strings
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
+
+ assertEquals("", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertTrue(adn.isEmpty());
+
+ //
+ // Record too short
+ //
+ adn = new AdnRecord(IccUtils.hexStringToBytes( "FF"));
+
+ assertEquals("", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertTrue(adn.isEmpty());
+
+ //
+ // TOA = 0xff ("control string")
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("566F696365204D61696C07FF8150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("18056377243", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // TOA = 0x81 (unknown)
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("566F696365204D61696C07818150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("18056377243", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Number Length is too long
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("566F696365204D61696C0F918150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Number Length is zero (invalid)
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("566F696365204D61696C00918150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Number Length is 2, first number byte is FF, TOA is international
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("566F696365204D61696C0291FF50367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Number Length is 2, first number digit is valid, TOA is international
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes("566F696365204D61696C0291F150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("+1", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // An extended record
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes(
+ "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+ assertTrue(adn.hasExtendedRecord());
+
+ adn.appendExtRecord(IccUtils.hexStringToBytes("0206092143658709ffffffffff"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678901234567890", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // An extended record with an invalid extension
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes(
+ "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+ assertTrue(adn.hasExtendedRecord());
+
+ adn.appendExtRecord(IccUtils.hexStringToBytes("0106092143658709ffffffffff"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // An extended record with an invalid extension
+ //
+ adn = new AdnRecord(
+ IccUtils.hexStringToBytes(
+ "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+ assertTrue(adn.hasExtendedRecord());
+
+ adn.appendExtRecord(IccUtils.hexStringToBytes("020B092143658709ffffffffff"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+ }
+}
+
+
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java
new file mode 100644
index 0000000..3a9c511
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import junit.framework.TestCase;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+public class GsmAlphabetTest extends TestCase {
+
+ private static final String sGsmExtendedChars = "{|}\\[~]\f\u20ac";
+
+ @SmallTest
+ public void test7bitWithHeader() throws Exception {
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 1;
+ concatRef.seqNumber = 2;
+ concatRef.msgCount = 2;
+ concatRef.isEightBits = true;
+ SmsHeader header = new SmsHeader();
+ header.concatRef = concatRef;
+
+ String message = "aaaaaaaaaabbbbbbbbbbcccccccccc";
+ byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message,
+ SmsHeader.toByteArray(header));
+ int septetCount = GsmAlphabet.countGsmSeptets(message, false);
+ String parsedMessage = GsmAlphabet.gsm7BitPackedToString(
+ userData, SmsHeader.toByteArray(header).length+2, septetCount, 1);
+ assertEquals(message, parsedMessage);
+ }
+
+ // TODO: This method should *really* be a series of individual test methods.
+ @LargeTest
+ public void testBasic() throws Exception {
+ // '@' maps to char 0
+ assertEquals(0, GsmAlphabet.charToGsm('@'));
+
+ // `a (a with grave accent) maps to last GSM charater
+ assertEquals(0x7f, GsmAlphabet.charToGsm('\u00e0'));
+
+ //
+ // These are the extended chars
+ // They should all return GsmAlphabet.GSM_EXTENDED_ESCAPE
+ //
+
+ for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
+ assertEquals(GsmAlphabet.GSM_EXTENDED_ESCAPE,
+ GsmAlphabet.charToGsm(sGsmExtendedChars.charAt(i)));
+
+ }
+
+ // euro symbol
+ assertEquals(GsmAlphabet.GSM_EXTENDED_ESCAPE,
+ GsmAlphabet.charToGsm('\u20ac'));
+
+ // An unmappable char (the 'cent' char) maps to a space
+ assertEquals(GsmAlphabet.charToGsm(' '),
+ GsmAlphabet.charToGsm('\u00a2'));
+
+ // unmappable = space = 1 septet
+ assertEquals(1, GsmAlphabet.countGsmSeptets('\u00a2'));
+
+ //
+ // Test extended table
+ //
+
+ for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
+ assertEquals(sGsmExtendedChars.charAt(i),
+ GsmAlphabet.gsmExtendedToChar(
+ GsmAlphabet.charToGsmExtended(sGsmExtendedChars.charAt(i))));
+
+ }
+
+ // Unmappable extended char
+ assertEquals(GsmAlphabet.charToGsm(' '),
+ GsmAlphabet.charToGsmExtended('@'));
+
+ //
+ // gsmToChar()
+ //
+
+ assertEquals('@', GsmAlphabet.gsmToChar(0));
+
+ // `a (a with grave accent) maps to last GSM charater
+ assertEquals('\u00e0', GsmAlphabet.gsmToChar(0x7f));
+
+ assertEquals('\uffff',
+ GsmAlphabet.gsmToChar(GsmAlphabet.GSM_EXTENDED_ESCAPE));
+
+ // Out-of-range/unmappable value
+ assertEquals(' ', GsmAlphabet.gsmToChar(0x80));
+
+ //
+ // gsmExtendedToChar()
+ //
+
+ assertEquals('{', GsmAlphabet.gsmExtendedToChar(0x28));
+
+ // No double-escapes
+ assertEquals(' ', GsmAlphabet.gsmExtendedToChar(
+ GsmAlphabet.GSM_EXTENDED_ESCAPE));
+
+ // Unmappable
+ assertEquals(' ', GsmAlphabet.gsmExtendedToChar(0));
+
+ //
+ // stringTo7BitPacked, gsm7BitPackedToString
+ //
+
+ byte[] packed;
+ StringBuilder testString = new StringBuilder(300);
+
+ // Check all alignment cases
+ for (int i = 0; i < 9; i++, testString.append('@')) {
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString());
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+ }
+
+ // Check full non-extended alphabet
+ for (int i = 0; i < 0x80; i++) {
+ char c;
+
+ if (i == GsmAlphabet.GSM_EXTENDED_ESCAPE) {
+ continue;
+ }
+
+ c = GsmAlphabet.gsmToChar(i);
+ testString.append(c);
+
+ // These are all non-extended chars, so it should be
+ // one septet per char
+ assertEquals(1, GsmAlphabet.countGsmSeptets(c));
+ }
+
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString());
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+
+ // Test extended chars too
+
+ testString.append(sGsmExtendedChars);
+
+ for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
+ // These are all extended chars, so it should be
+ // two septets per char
+ assertEquals(2, GsmAlphabet.countGsmSeptets(sGsmExtendedChars.charAt(i)));
+
+ }
+
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString());
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+
+ // stringTo7BitPacked handles up to 255 septets
+
+ testString.setLength(0);
+ for (int i = 0; i < 255; i++) {
+ testString.append('@');
+ }
+
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString());
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+
+ // > 255 septets throws runtime exception
+ testString.append('@');
+
+ try {
+ GsmAlphabet.stringToGsm7BitPacked(testString.toString());
+ fail("expected exception");
+ } catch (EncodeException ex) {
+ // exception expected
+ }
+
+ // Try 254 septets with 127 extended chars
+
+ testString.setLength(0);
+ for (int i = 0; i < (255 / 2); i++) {
+ testString.append('{');
+ }
+
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString());
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+
+ // > 255 septets throws runtime exception
+ testString.append('{');
+
+ try {
+ GsmAlphabet.stringToGsm7BitPacked(testString.toString());
+ fail("expected exception");
+ } catch (EncodeException ex) {
+ // exception expected
+ }
+
+ //
+ // 8 bit unpacked format
+ //
+ // Note: we compare hex strings here
+ // because Assert doesnt have array-comparisons
+
+ byte unpacked[];
+
+ unpacked = IccUtils.hexStringToBytes("566F696365204D61696C");
+ assertEquals("Voice Mail",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ assertEquals(IccUtils.bytesToHexString(unpacked),
+ IccUtils.bytesToHexString(
+ GsmAlphabet.stringToGsm8BitPacked("Voice Mail")));
+
+ unpacked = GsmAlphabet.stringToGsm8BitPacked(sGsmExtendedChars);
+ // two bytes for every extended char
+ assertEquals(2 * sGsmExtendedChars.length(), unpacked.length);
+ assertEquals(sGsmExtendedChars,
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // should be two bytes per extended char
+ assertEquals(2 * sGsmExtendedChars.length(), unpacked.length);
+
+ // Test truncation of unaligned extended chars
+ unpacked = new byte[3];
+ GsmAlphabet.stringToGsm8BitUnpackedField(sGsmExtendedChars, unpacked,
+ 0, unpacked.length);
+
+ // Should be one extended char and an 0xff at the end
+
+ assertEquals(0xff, 0xff & unpacked[2]);
+ assertEquals(sGsmExtendedChars.substring(0, 1),
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // Test truncation of normal chars
+ unpacked = new byte[3];
+ GsmAlphabet.stringToGsm8BitUnpackedField("abcd", unpacked,
+ 0, unpacked.length);
+
+ assertEquals("abc",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // Test truncation of mixed normal and extended chars
+ unpacked = new byte[3];
+ GsmAlphabet.stringToGsm8BitUnpackedField("a{cd", unpacked,
+ 0, unpacked.length);
+
+ assertEquals("a{",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // Test padding after normal char
+ unpacked = new byte[3];
+ GsmAlphabet.stringToGsm8BitUnpackedField("a", unpacked,
+ 0, unpacked.length);
+
+ assertEquals("a",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ assertEquals(0xff, 0xff & unpacked[1]);
+ assertEquals(0xff, 0xff & unpacked[2]);
+
+ // Test malformed input -- escape char followed by end of field
+ unpacked[0] = 0;
+ unpacked[1] = 0;
+ unpacked[2] = GsmAlphabet.GSM_EXTENDED_ESCAPE;
+
+ assertEquals("@@",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // non-zero offset
+ assertEquals("@",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
+
+ // test non-zero offset
+ unpacked[0] = 0;
+ GsmAlphabet.stringToGsm8BitUnpackedField("abcd", unpacked,
+ 1, unpacked.length - 1);
+
+
+ assertEquals(0, unpacked[0]);
+
+ assertEquals("ab",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
+
+ // test non-zero offset with truncated extended char
+ unpacked[0] = 0;
+
+ GsmAlphabet.stringToGsm8BitUnpackedField("a{", unpacked,
+ 1, unpacked.length - 1);
+
+ assertEquals(0, unpacked[0]);
+
+ assertEquals("a",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
+ }
+}
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
new file mode 100644
index 0000000..3103fc1
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.gsm.SmsMessage;
+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
+ public void testAddressing() throws Exception {
+ String pdu = "07914151551512f2040B916105551511f100006060605130308A04D4F29C0E";
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+ assertEquals("+14155551212", sms.getServiceCenterAddress());
+ assertEquals("+16505551111", sms.getOriginatingAddress());
+ assertEquals("Test", sms.getMessageBody());
+
+ pdu = "07914151551512f2040B916105551511f100036060924180008A0DA"
+ + "8695DAC2E8FE9296A794E07";
+ sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+ assertEquals("+14155551212", sms.getServiceCenterAddress());
+ assertEquals("+16505551111", sms.getOriginatingAddress());
+ assertEquals("(Subject)Test", sms.getMessageBody());
+ }
+
+ @SmallTest
+ public void testUdh() throws Exception {
+ String pdu = "07914140279510F6440A8111110301003BF56080207130138A8C0B05040B8423F"
+ + "000032A02010106276170706C69636174696F6E2F766E642E7761702E6D6D732D"
+ + "6D65737361676500AF848D0185B4848C8298524E453955304A6D7135514141426"
+ + "66C414141414D7741414236514141414141008D908918802B3135313232393737"
+ + "3638332F545950453D504C4D4E008A808E022B918805810306977F83687474703"
+ + "A2F2F36";
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+ SmsHeader header = sms.getUserDataHeader();
+ assertNotNull(header);
+ assertNotNull(header.concatRef);
+ assertEquals(header.concatRef.refNumber, 42);
+ assertEquals(header.concatRef.msgCount, 2);
+ assertEquals(header.concatRef.seqNumber, 1);
+ assertEquals(header.concatRef.isEightBits, true);
+ assertNotNull(header.portAddrs);
+ assertEquals(header.portAddrs.destPort, 2948);
+ assertEquals(header.portAddrs.origPort, 9200);
+ assertEquals(header.portAddrs.areEightBits, false);
+
+ pdu = "07914140279510F6440A8111110301003BF56080207130238A3B0B05040B8423F"
+ + "000032A0202362E3130322E3137312E3135302F524E453955304A6D7135514141"
+ + "42666C414141414D774141423651414141414100";
+ sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+ header = sms.getUserDataHeader();
+ assertNotNull(header);
+ assertNotNull(header.concatRef);
+ assertEquals(header.concatRef.refNumber, 42);
+ assertEquals(header.concatRef.msgCount, 2);
+ assertEquals(header.concatRef.seqNumber, 2);
+ assertEquals(header.concatRef.isEightBits, true);
+ assertNotNull(header.portAddrs);
+ assertEquals(header.portAddrs.destPort, 2948);
+ assertEquals(header.portAddrs.origPort, 9200);
+ assertEquals(header.portAddrs.areEightBits, false);
+ }
+
+ @SmallTest
+ public void testUcs2() throws Exception {
+ String pdu = "07912160130300F4040B914151245584F600087010807121352B1021220"
+ + "0A900AE00680065006C006C006F";
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+ assertEquals("\u2122\u00a9\u00aehello", sms.getMessageBody());
+ }
+
+ @SmallTest
+ public void testMultipart() throws Exception {
+ /*
+ * Multi-part text SMS with septet data.
+ */
+ String pdu = "07916163838408F6440B816105224431F700007060217175830AA0050003"
+ + "00020162B1582C168BC562B1582C168BC562B1582C168BC562B1582C"
+ + "168BC562B1582C168BC562B1582C168BC562B1582C168BC562B1582C"
+ + "168BC562B1582C168BC562B1582C168BC562B1582C168BC562B1582C"
+ + "168BC562B1582C168BC562B1582C168BC562B1582C168BC562B1582C"
+ + "168BC562B1582C168BC562B1582C168BC562B1582C168BC562";
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+ assertEquals(sms.getMessageBody(),
+ "1111111111111111111111111111111111111111"
+ + "1111111111111111111111111111111111111111"
+ + "1111111111111111111111111111111111111111"
+ + "111111111111111111111111111111111");
+
+ pdu = "07916163838408F6440B816105224431F700007060217185000A23050003"
+ + "00020262B1582C168BC96432994C2693C96432994C2693C96432990C";
+ sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+ assertEquals("1111111222222222222222222222", sms.getMessageBody());
+ }
+
+ @SmallTest
+ public void testCPHSVoiceMail() throws Exception {
+ // "set MWI flag"
+
+ String pdu = "07912160130310F20404D0110041006060627171118A0120";
+
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertTrue(sms.isReplace());
+ assertEquals("_@", sms.getOriginatingAddress());
+ assertEquals(" ", sms.getMessageBody());
+ assertTrue(sms.isMWISetMessage());
+
+ // "clear mwi flag"
+
+ pdu = "07912160130310F20404D0100041006021924193352B0120";
+
+ sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertTrue(sms.isMWIClearMessage());
+
+ // "clear MWI flag"
+
+ pdu = "07912160130310F20404D0100041006060627161058A0120";
+
+ sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertTrue(sms.isReplace());
+ assertEquals("\u0394@", sms.getOriginatingAddress());
+ assertEquals(" ", sms.getMessageBody());
+ assertTrue(sms.isMWIClearMessage());
+ }
+
+ @SmallTest
+ public void testCingularVoiceMail() throws Exception {
+ // "set MWI flag"
+
+ String pdu = "07912180958750F84401800500C87020026195702B06040102000200";
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertTrue(sms.isMWISetMessage());
+ assertTrue(sms.isMwiDontStore());
+
+ // "clear mwi flag"
+
+ pdu = "07912180958750F84401800500C07020027160112B06040102000000";
+ sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertTrue(sms.isMWIClearMessage());
+ assertTrue(sms.isMwiDontStore());
+ }
+
+ @SmallTest
+ public void testEmailGateway() throws Exception {
+ String pdu = "07914151551512f204038105f300007011103164638a28e6f71b50c687db" +
+ "7076d9357eb7412f7a794e07cdeb6275794c07bde8e5391d247e93f3";
+
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertEquals("+14155551212", sms.getServiceCenterAddress());
+ assertTrue(sms.isEmail());
+ assertEquals("foo@example.com", sms.getEmailFrom());
+ assertEquals("foo@example.com", sms.getDisplayOriginatingAddress());
+ // As of https://android-git.corp.google.com/g/#change,9324
+ // getPseudoSubject will always be empty, and any subject is not extracted.
+ assertEquals("", sms.getPseudoSubject());
+ assertEquals("test subject /test body", sms.getDisplayMessageBody());
+ assertEquals("test subject /test body", sms.getEmailBody());
+
+ // email gateway sms test, including gsm extended character set.
+ pdu = "07914151551512f204038105f400007011103105458a29e6f71b50c687db" +
+ "7076d9357eb741af0d0a442fcfe9c23739bfe16d289bdee6b5f1813629";
+
+ sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertEquals("+14155551212", sms.getServiceCenterAddress());
+ assertTrue(sms.isEmail());
+ assertEquals("foo@example.com", sms.getDisplayOriginatingAddress());
+ assertEquals("foo@example.com", sms.getEmailFrom());
+ assertEquals("{ testBody[^~\\] }", sms.getDisplayMessageBody());
+ assertEquals("{ testBody[^~\\] }", sms.getEmailBody());
+ }
+
+ @SmallTest
+ public void testExtendedCharacterTable() throws Exception {
+ String pdu = "07914151551512f2040B916105551511f100006080615131728A44D4F29C0E2" +
+ "AE3E96537B94C068DD16179784C2FCB41F4B0985D06B958ADD00FB0E94536AF9749" +
+ "74DA6D281BA00E95E26D509B946FC3DBF87A25D56A04";
+
+ SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
+
+ assertEquals("+14155551212", sms.getServiceCenterAddress());
+ assertEquals("+16505551111", sms.getOriginatingAddress());
+ assertEquals("Test extended character table .,-!?@~_\\/&\"';^|:()<{}>[]=%*+#",
+ sms.getMessageBody());
+ }
+
+ @SmallTest
+ public void testDecode() throws Exception {
+ byte[] septets = new byte[(7 * 128 + 7) / 8];
+
+ int bitOffset = 0;
+
+ for (int i = 0; i < 128; i++) {
+ int v;
+ if (i == 0x1b) {
+ // extended escape char
+ v = 0;
+ } else {
+ v = i;
+ }
+
+ int byteOffset = bitOffset / 8;
+ int shift = bitOffset % 8;
+
+ septets[byteOffset] |= v << shift;
+
+ if (shift > 1) {
+ septets[byteOffset + 1] = (byte) (v >> (8 - shift));
+ }
+
+ bitOffset += 7;
+ }
+
+ String decoded = GsmAlphabet.gsm7BitPackedToString(septets, 0, 128);
+ byte[] reEncoded = GsmAlphabet.stringToGsm7BitPacked(decoded);
+
+ // reEncoded has the count septets byte at the front
+ assertEquals(reEncoded.length, septets.length + 1);
+
+ for (int i = 0; i < septets.length; i++) {
+ assertEquals(reEncoded[i + 1], septets[i]);
+ }
+ }
+
+}
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
new file mode 100644
index 0000000..2d6977c
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.MccTable;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import android.util.Log;
+
+public class MccTableTest extends AndroidTestCase {
+ private final static String LOG_TAG = "GSM";
+
+ @SmallTest
+ public void testTimeZone() throws Exception {
+ assertEquals(MccTable.defaultTimeZoneForMcc(208), "Europe/Paris");
+ assertEquals(MccTable.defaultTimeZoneForMcc(232), "Europe/Vienna");
+ assertEquals(MccTable.defaultTimeZoneForMcc(655), "Africa/Johannesburg");
+ assertEquals(MccTable.defaultTimeZoneForMcc(440), "Asia/Tokyo");
+ assertEquals(MccTable.defaultTimeZoneForMcc(441), "Asia/Tokyo");
+ assertEquals(MccTable.defaultTimeZoneForMcc(525), "Asia/Singapore");
+ assertEquals(MccTable.defaultTimeZoneForMcc(240), null); // tz not defined, hence default
+ assertEquals(MccTable.defaultTimeZoneForMcc(0), null); // mcc not defined, hence default
+ assertEquals(MccTable.defaultTimeZoneForMcc(2000), null); // mcc not defined, hence default
+ }
+
+ @SmallTest
+ public void testCountryCode() throws Exception {
+ assertEquals(MccTable.countryCodeForMcc(270), "lu");
+ assertEquals(MccTable.countryCodeForMcc(202), "gr");
+ assertEquals(MccTable.countryCodeForMcc(750), "fk");
+ assertEquals(MccTable.countryCodeForMcc(646), "mg");
+ assertEquals(MccTable.countryCodeForMcc(314), "us");
+ assertEquals(MccTable.countryCodeForMcc(300), ""); // mcc not defined, hence default
+ assertEquals(MccTable.countryCodeForMcc(0), ""); // mcc not defined, hence default
+ assertEquals(MccTable.countryCodeForMcc(2000), ""); // mcc not defined, hence default
+ }
+
+ @SmallTest
+ public void testLang() throws Exception {
+ assertEquals(MccTable.defaultLanguageForMcc(311), "en");
+ assertEquals(MccTable.defaultLanguageForMcc(232), "de");
+ assertEquals(MccTable.defaultLanguageForMcc(230), "cs");
+ assertEquals(MccTable.defaultLanguageForMcc(204), "nl");
+ assertEquals(MccTable.defaultLanguageForMcc(274), null); // lang not defined, hence default
+ assertEquals(MccTable.defaultLanguageForMcc(0), null); // mcc not defined, hence default
+ assertEquals(MccTable.defaultLanguageForMcc(2000), null); // mcc not defined, hence default
+ }
+
+ @SmallTest
+ public void testSmDigits() throws Exception {
+ assertEquals(MccTable.smallestDigitsMccForMnc(312), 3);
+ assertEquals(MccTable.smallestDigitsMccForMnc(430), 2);
+ assertEquals(MccTable.smallestDigitsMccForMnc(365), 3);
+ assertEquals(MccTable.smallestDigitsMccForMnc(536), 2);
+ assertEquals(MccTable.smallestDigitsMccForMnc(352), 2); // sd not defined, hence default
+ assertEquals(MccTable.smallestDigitsMccForMnc(0), 2); // mcc not defined, hence default
+ assertEquals(MccTable.smallestDigitsMccForMnc(2000), 2); // mcc not defined, hence default
+ }
+
+ @SmallTest
+ public void testWifi() throws Exception {
+ assertEquals(MccTable.wifiChannelsForMcc(262), 13);
+ assertEquals(MccTable.wifiChannelsForMcc(234), 13);
+ assertEquals(MccTable.wifiChannelsForMcc(505), 11);
+ assertEquals(MccTable.wifiChannelsForMcc(313), 11);
+ assertEquals(MccTable.wifiChannelsForMcc(330), 0); // wifi not defined, hence default
+ assertEquals(MccTable.wifiChannelsForMcc(0), 0); // mcc not defined, hence default
+ assertEquals(MccTable.wifiChannelsForMcc(2000), 0); // mcc not defined, hence default
+
+ }
+}
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java
new file mode 100644
index 0000000..b63dc71
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.telephony;
+
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+import android.telephony.NeighboringCellInfo;
+import android.test. suitebuilder.annotation.SmallTest;
+
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_EDGE;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_GPRS;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
+
+public class NeighboringCellInfoTest extends AndroidTestCase {
+ @SmallTest
+ public void testConstructor() {
+ int rssi = 31;
+ NeighboringCellInfo nc;
+
+ nc = new NeighboringCellInfo(rssi, "FFFFFFF", NETWORK_TYPE_EDGE);
+ assertEquals(NETWORK_TYPE_EDGE, nc.getNetworkType());
+ assertEquals(rssi, nc.getRssi());
+ assertEquals(0xfff, nc.getLac());
+ assertEquals(0xffff, nc.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getPsc());
+
+ nc = new NeighboringCellInfo(rssi, "1FF", NETWORK_TYPE_UMTS);
+ assertEquals(NETWORK_TYPE_UMTS, nc.getNetworkType());
+ assertEquals(rssi, nc.getRssi());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getLac());
+ assertEquals(0x1ff, nc.getPsc());
+
+ nc = new NeighboringCellInfo(rssi, "1FF", NETWORK_TYPE_UNKNOWN);
+ assertEquals(NETWORK_TYPE_UNKNOWN, nc.getNetworkType());
+ assertEquals(rssi, nc.getRssi());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getLac());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getPsc());
+ }
+
+ @SmallTest
+ public void testParcel() {
+ int rssi = 20;
+
+ NeighboringCellInfo nc = new NeighboringCellInfo(rssi, "12345678", NETWORK_TYPE_GPRS);
+ assertEquals(NETWORK_TYPE_GPRS, nc.getNetworkType());
+ assertEquals(rssi, nc.getRssi());
+ assertEquals(0x1234, nc.getLac());
+ assertEquals(0x5678, nc.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getPsc());
+
+ Parcel p = Parcel.obtain();
+ p.setDataPosition(0);
+ nc.writeToParcel(p, 0);
+
+ p.setDataPosition(0);
+ NeighboringCellInfo nw = new NeighboringCellInfo(p);
+ assertEquals(NETWORK_TYPE_GPRS, nw.getNetworkType());
+ assertEquals(rssi, nw.getRssi());
+ assertEquals(0x1234, nw.getLac());
+ assertEquals(0x5678, nw.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nw.getPsc());
+ }
+}
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/SMSDispatcherTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/SMSDispatcherTest.java
new file mode 100644
index 0000000..8a66614
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/SMSDispatcherTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2007 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.test.suitebuilder.annotation.MediumTest;
+import com.android.internal.telephony.TestPhoneNotifier;
+import com.android.internal.telephony.gsm.SmsMessage;
+import com.android.internal.telephony.test.SimulatedCommands;
+import com.android.internal.telephony.test.SimulatedRadioControl;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.Suppress;
+
+import java.util.Iterator;
+
+/**
+ * {@hide}
+ */
+public class SMSDispatcherTest extends AndroidTestCase {
+ @MediumTest
+ public void testCMT1() throws Exception {
+ SmsMessage sms;
+ SmsHeader header;
+
+ String[] lines = new String[2];
+
+ lines[0] = "+CMT: ,158";
+ lines[1] = "07914140279510F6440A8111110301003BF56080426101748A8C0B05040B"
+ + "8423F000035502010106276170706C69636174696F6E2F766E642E776170"
+ + "2E6D6D732D6D65737361676500AF848D0185B4848C8298524F347839776F"
+ + "7547514D4141424C3641414141536741415A4B554141414141008D908918"
+ + "802B31363530323438363137392F545950453D504C4D4E008A808E028000"
+ + "88058103093A8083687474703A2F2F36";
+
+ sms = SmsMessage.newFromCMT(lines);
+ header = sms.getUserDataHeader();
+ assertNotNull(header);
+ assertNotNull(sms.getUserData());
+ assertNotNull(header.concatRef);
+ assertEquals(header.concatRef.refNumber, 85);
+ assertEquals(header.concatRef.msgCount, 2);
+ assertEquals(header.concatRef.seqNumber, 1);
+ assertEquals(header.concatRef.isEightBits, true);
+ assertNotNull(header.portAddrs);
+ assertEquals(header.portAddrs.destPort, 2948);
+ assertEquals(header.portAddrs.origPort, 9200);
+ assertEquals(header.portAddrs.areEightBits, false);
+ }
+
+ @MediumTest
+ public void testCMT2() throws Exception {
+ SmsMessage sms;
+ SmsHeader header;
+
+ String[] lines = new String[2];
+
+ lines[0] = "+CMT: ,77";
+ lines[1] = "07914140279510F6440A8111110301003BF56080426101848A3B0B05040B8423F"
+ + "00003550202362E3130322E3137312E3135302F524F347839776F7547514D4141"
+ + "424C3641414141536741415A4B55414141414100";
+
+ sms = SmsMessage.newFromCMT(lines);
+ header = sms.getUserDataHeader();
+ assertNotNull(header);
+ assertNotNull(sms.getUserData());
+ assertNotNull(header.concatRef);
+ assertEquals(header.concatRef.refNumber, 85);
+ assertEquals(header.concatRef.msgCount, 2);
+ assertEquals(header.concatRef.seqNumber, 2);
+ assertEquals(header.concatRef.isEightBits, true);
+ assertNotNull(header.portAddrs);
+ assertEquals(header.portAddrs.destPort, 2948);
+ assertEquals(header.portAddrs.origPort, 9200);
+ assertEquals(header.portAddrs.areEightBits, false);
+ }
+
+ @MediumTest
+ public void testEfRecord() throws Exception {
+ SmsMessage sms;
+
+ String s = "03029111000c9194981492631000f269206190022000a053e4534a05358bd3"
+ + "69f05804259da0219418a40641536a110a0aea408080604028180e888462c1"
+ + "50341c0f484432a1542c174c46b3e1743c9f9068442a994ea8946ac56ab95e"
+ + "b0986c46abd96eb89c6ec7ebf97ec0a070482c1a8fc8a472c96c3a9fd0a874"
+ + "4aad5aafd8ac76cbed7abfe0b0784c2e9bcfe8b47acd6ebbdff0b87c4eafdb"
+ + "eff8bc7ecfeffbffffffffffffffffffffffffffff";
+ byte[] data = IccUtils.hexStringToBytes(s);
+
+ sms = SmsMessage.createFromEfRecord(1, data);
+ assertNotNull(sms.getMessageBody());
+ }
+}
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/SimPhoneBookTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/SimPhoneBookTest.java
new file mode 100644
index 0000000..609e768
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/SimPhoneBookTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.ServiceManager;
+import android.test.suitebuilder.annotation.Suppress;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+@Suppress
+public class SimPhoneBookTest extends TestCase {
+
+ public void testBasic() throws Exception {
+ IIccPhoneBook simPhoneBook =
+ IIccPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));
+ assertNotNull(simPhoneBook);
+
+ int size[] = simPhoneBook.getAdnRecordsSize(IccConstants.EF_ADN);
+ assertNotNull(size);
+ assertEquals(3, size.length);
+ assertEquals(size[0] * size[2], size[1]);
+ assertTrue(size[2] >= 100);
+
+ List<AdnRecord> adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
+ // do it twice cause the second time shall read from cache only
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
+ assertNotNull(adnRecordList);
+
+ // Test for phone book update
+ int adnIndex, listIndex = 0;
+ AdnRecord originalAdn = null;
+ // We need to maintain the state of the SIM before and after the test.
+ // Since this test doesn't mock the SIM we try to get a valid ADN record,
+ // for 3 tries and if this fails, we bail out.
+ for (adnIndex = 3 ; adnIndex >= 1; adnIndex--) {
+ listIndex = adnIndex - 1; // listIndex is zero based.
+ originalAdn = adnRecordList.get(listIndex);
+ assertNotNull("Original Adn is Null.", originalAdn);
+ assertNotNull("Original Adn alpha tag is null.", originalAdn.getAlphaTag());
+ assertNotNull("Original Adn number is null.", originalAdn.getNumber());
+
+ if (originalAdn.getNumber().length() > 0 &&
+ originalAdn.getAlphaTag().length() > 0) {
+ break;
+ }
+ }
+ if (adnIndex == 0) return;
+
+ AdnRecord emptyAdn = new AdnRecord("", "");
+ AdnRecord firstAdn = new AdnRecord("John", "4085550101");
+ AdnRecord secondAdn = new AdnRecord("Andy", "6505550102");
+ String pin2 = null;
+
+ // udpate by index
+ boolean success = simPhoneBook.updateAdnRecordsInEfByIndex(IccConstants.EF_ADN,
+ firstAdn.getAlphaTag(), firstAdn.getNumber(), adnIndex, pin2);
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
+ AdnRecord tmpAdn = adnRecordList.get(listIndex);
+ assertTrue(success);
+ assertTrue(firstAdn.isEqual(tmpAdn));
+
+ // replace by search
+ success = simPhoneBook.updateAdnRecordsInEfBySearch(IccConstants.EF_ADN,
+ firstAdn.getAlphaTag(), firstAdn.getNumber(),
+ secondAdn.getAlphaTag(), secondAdn.getNumber(), pin2);
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
+ tmpAdn = adnRecordList.get(listIndex);
+ assertTrue(success);
+ assertFalse(firstAdn.isEqual(tmpAdn));
+ assertTrue(secondAdn.isEqual(tmpAdn));
+
+ // erase be search
+ success = simPhoneBook.updateAdnRecordsInEfBySearch(IccConstants.EF_ADN,
+ secondAdn.getAlphaTag(), secondAdn.getNumber(),
+ emptyAdn.getAlphaTag(), emptyAdn.getNumber(), pin2);
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
+ tmpAdn = adnRecordList.get(listIndex);
+ assertTrue(success);
+ assertTrue(tmpAdn.isEmpty());
+
+ // restore the orginial adn
+ success = simPhoneBook.updateAdnRecordsInEfByIndex(IccConstants.EF_ADN,
+ originalAdn.getAlphaTag(), originalAdn.getNumber(), adnIndex,
+ pin2);
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
+ tmpAdn = adnRecordList.get(listIndex);
+ assertTrue(success);
+ assertTrue(originalAdn.isEqual(tmpAdn));
+ }
+}
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/SimSmsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/SimSmsTest.java
new file mode 100644
index 0000000..1609680
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/SimSmsTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.ServiceManager;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+public class SimSmsTest extends TestCase {
+
+ @MediumTest
+ @Suppress // TODO: suppress this test for now since it doesn't work on the emulator
+ public void testBasic() throws Exception {
+
+ ISms sms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+ assertNotNull(sms);
+
+ List<SmsRawData> records = sms.getAllMessagesFromIccEf();
+ assertNotNull(records);
+ assertTrue(records.size() >= 0);
+
+ int firstNullIndex = -1;
+ int firstValidIndex = -1;
+ byte[] pdu = null;
+ for (int i = 0; i < records.size(); i++) {
+ SmsRawData data = records.get(i);
+ if (data != null && firstValidIndex == -1) {
+ firstValidIndex = i;
+ pdu = data.getBytes();
+ }
+ if (data == null && firstNullIndex == -1) {
+ firstNullIndex = i;
+ }
+ if (firstNullIndex != -1 && firstValidIndex != -1) {
+ break;
+ }
+ }
+ if (firstNullIndex == -1 || firstValidIndex == -1)
+ return;
+ assertNotNull(pdu);
+ }
+}
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java
new file mode 100644
index 0000000..db38ede
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.gsm.SimTlv;
+import com.android.internal.telephony.IccUtils;
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+
+public class SimUtilsTest extends TestCase {
+
+ @SmallTest
+ public void testBasic() throws Exception {
+ byte[] data, data2;
+
+ /*
+ * bcdToString()
+ */
+
+ // An EF[ICCID] record
+ data = IccUtils.hexStringToBytes("981062400510444868f2");
+ assertEquals("8901260450014484862", IccUtils.bcdToString(data, 0, data.length));
+
+ // skip the first and last bytes
+ assertEquals("0126045001448486", IccUtils.bcdToString(data, 1, data.length - 2));
+
+ // Stops on invalid BCD value
+ data = IccUtils.hexStringToBytes("98F062400510444868f2");
+ assertEquals("890", IccUtils.bcdToString(data, 0, data.length));
+
+ /*
+ * gsmBcdByteToInt()
+ */
+
+ assertEquals(98, IccUtils.gsmBcdByteToInt((byte) 0x89));
+
+ // Out of range is treated as 0
+ assertEquals(8, IccUtils.gsmBcdByteToInt((byte) 0x8c));
+
+ /*
+ * cdmaBcdByteToInt()
+ */
+
+ assertEquals(89, IccUtils.cdmaBcdByteToInt((byte) 0x89));
+
+ // Out of range is treated as 0
+ assertEquals(80, IccUtils.cdmaBcdByteToInt((byte) 0x8c));
+
+ /*
+ * adnStringFieldToString()
+ */
+
+
+ data = IccUtils.hexStringToBytes("00566f696365204d61696c07918150367742f3ffffffffffff");
+ // Again, skip prepended 0
+ // (this is an EF[ADN] record)
+ assertEquals("Voice Mail", IccUtils.adnStringFieldToString(data, 1, data.length - 15));
+
+ data = IccUtils.hexStringToBytes("809673539A5764002F004DFFFFFFFFFF");
+ // (this is from an EF[ADN] record)
+ assertEquals("\u9673\u539A\u5764/M", IccUtils.adnStringFieldToString(data, 0, data.length));
+
+ data = IccUtils.hexStringToBytes("810A01566fec6365204de0696cFFFFFF");
+ // (this is made up to test since I don't have a real one)
+ assertEquals("Vo\u00ECce M\u00E0il", IccUtils.adnStringFieldToString(data, 0, data.length));
+
+ data = IccUtils.hexStringToBytes("820505302D82d32d31");
+ // Example from 3GPP TS 11.11 V18.1.3.0 annex B
+ assertEquals("-\u0532\u0583-1", IccUtils.adnStringFieldToString(data, 0, data.length));
+ }
+
+}
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/TelephonyUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/TelephonyUtilsTest.java
new file mode 100644
index 0000000..3757017
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/TelephonyUtilsTest.java
@@ -0,0 +1,219 @@
+/**
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.RetryManager;
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class TelephonyUtilsTest extends TestCase {
+
+ /**
+ * After first creating the RetryManager
+ * isRetryNeeded should be false and the time 0
+ */
+ @SmallTest
+ public void testRetryManagerEmpty() throws Exception {
+ RetryManager rm = new RetryManager();
+
+ assertEquals(0, rm.getRetryCount());
+ assertFalse(rm.isRetryForever());
+ assertFalse(rm.isRetryNeeded());
+ assertEquals(0, rm.getRetryCount());
+ assertEquals(0, rm.getRetryTimer());
+
+ rm.increaseRetryCount();
+ assertFalse(rm.isRetryForever());
+ assertFalse(rm.isRetryNeeded());
+ assertEquals(0, rm.getRetryCount());
+ assertEquals(0, rm.getRetryTimer());
+
+ rm.setRetryCount(123);
+ assertFalse(rm.isRetryForever());
+ assertFalse(rm.isRetryNeeded());
+ assertEquals(0, rm.getRetryCount());
+ assertEquals(0, rm.getRetryTimer());
+
+ rm.retryForeverUsingLastTimeout();
+ assertTrue(rm.isRetryForever());
+ assertTrue(rm.isRetryNeeded());
+ assertEquals(0, rm.getRetryCount());
+ assertEquals(0, rm.getRetryTimer());
+
+ rm.setRetryCount(2);
+ assertFalse(rm.isRetryForever());
+ assertFalse(rm.isRetryNeeded());
+ assertEquals(0, rm.getRetryCount());
+ assertEquals(0, rm.getRetryTimer());
+ }
+
+ /**
+ * A simple test and that randomization is doing something.
+ */
+ @SmallTest
+ public void testRetryManagerSimplest() throws Exception {
+ RetryManager rm = new RetryManager();
+
+ assertTrue(rm.configure(1, 500, 10));
+ int loops = 10;
+ int count = 0;
+ for (int i = 0; i < loops; i++) {
+ assertTrue(rm.isRetryNeeded());
+ int time = rm.getRetryTimer();
+ assertTrue((time >= 500) && (time < 600));
+ if (time == 500) {
+ count++;
+ }
+ }
+ assertFalse(count == loops);
+ rm.increaseRetryCount();
+ assertFalse(rm.isRetryNeeded());
+ rm.setRetryCount(0);
+ assertTrue(rm.isRetryNeeded());
+ }
+
+ /**
+ * Test multiple values using simple configuration.
+ */
+ @SmallTest
+ public void testRetryManagerSimple() throws Exception {
+ RetryManager rm = new RetryManager();
+
+ assertTrue(rm.configure(3, 1000, 0));
+ assertTrue(rm.isRetryNeeded());
+ assertEquals(1000, rm.getRetryTimer());
+ assertEquals(rm.getRetryTimer(), 1000);
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ assertEquals(1000, rm.getRetryTimer());
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ assertEquals(1000, rm.getRetryTimer());
+ rm.increaseRetryCount();
+ assertFalse(rm.isRetryNeeded());
+ assertEquals(1000, rm.getRetryTimer());
+ }
+
+ /**
+ * Test string configuration, simplest
+ */
+ @SmallTest
+ public void testRetryManageSimpleString() throws Exception {
+ RetryManager rm = new RetryManager();
+
+ assertTrue(rm.configure("101"));
+ assertTrue(rm.isRetryNeeded());
+ assertEquals(101, rm.getRetryTimer());
+ rm.increaseRetryCount();
+ assertFalse(rm.isRetryNeeded());
+ }
+
+ /**
+ * Test infinite retires
+ */
+ @SmallTest
+ public void testRetryManageInfinite() throws Exception {
+ RetryManager rm = new RetryManager();
+
+ assertTrue(rm.configure("1000,2000,3000,max_retries=infinite"));
+ assertTrue(rm.isRetryNeeded());
+ assertEquals(1000, rm.getRetryTimer());
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ assertEquals(2000, rm.getRetryTimer());
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ // All others are 3000 and isRetryNeeded is always true
+ for (int i=0; i < 100; i++) {
+ assertEquals(3000, rm.getRetryTimer());
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ }
+ }
+
+ /**
+ * Test string configuration using all options and with quotes.
+ */
+ @SmallTest
+ public void testRetryManageString() throws Exception {
+ RetryManager rm = new RetryManager();
+ int time;
+
+ assertTrue(rm.configure(
+ "\"max_retries=4, default_randomization=100,1000, 2000 :200 , 3000\""));
+ assertTrue(rm.isRetryNeeded());
+ time = rm.getRetryTimer();
+ assertTrue((time >= 1000) && (time < 1100));
+
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ time = rm.getRetryTimer();
+ assertTrue((time >= 2000) && (time < 2200));
+
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ time = rm.getRetryTimer();
+ assertTrue((time >= 3000) && (time < 3100));
+
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ time = rm.getRetryTimer();
+ assertTrue((time >= 3000) && (time < 3100));
+
+ rm.increaseRetryCount();
+ assertFalse(rm.isRetryNeeded());
+ }
+
+ /**
+ * Test string configuration using all options.
+ */
+ @SmallTest
+ public void testRetryManageForever() throws Exception {
+ RetryManager rm = new RetryManager();
+ int time;
+
+ assertTrue(rm.configure("1000, 2000, 3000"));
+ assertTrue(rm.isRetryNeeded());
+ assertFalse(rm.isRetryForever());
+ assertEquals(0, rm.getRetryCount());
+ assertEquals(1000, rm.getRetryTimer());
+
+ rm.retryForeverUsingLastTimeout();
+ rm.increaseRetryCount();
+ rm.increaseRetryCount();
+ rm.increaseRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ assertTrue(rm.isRetryForever());
+ assertEquals(3, rm.getRetryCount());
+ assertEquals(3000, rm.getRetryTimer());
+
+ rm.setRetryCount(1);
+ assertTrue(rm.isRetryNeeded());
+ assertFalse(rm.isRetryForever());
+ assertEquals(1, rm.getRetryCount());
+ assertEquals(2000, rm.getRetryTimer());
+
+ rm.retryForeverUsingLastTimeout();
+ assertTrue(rm.isRetryNeeded());
+ assertTrue(rm.isRetryForever());
+ rm.resetRetryCount();
+ assertTrue(rm.isRetryNeeded());
+ assertFalse(rm.isRetryForever());
+ assertEquals(0, rm.getRetryCount());
+ assertEquals(1000, rm.getRetryTimer());
+ }
+}
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java
new file mode 100644
index 0000000..427795b
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+/**
+ * Stub class used for unit tests
+ */
+
+public class TestPhoneNotifier implements PhoneNotifier {
+ public TestPhoneNotifier() {
+ }
+
+ public void notifyPhoneState(Phone sender) {
+ }
+
+ public void notifyServiceState(Phone sender) {
+ }
+
+ public void notifyCellLocation(Phone sender) {
+ }
+
+ public void notifySignalStrength(Phone sender) {
+ }
+
+ public void notifyMessageWaitingChanged(Phone sender) {
+ }
+
+ public void notifyCallForwardingChanged(Phone sender) {
+ }
+
+ public void notifyDataConnection(Phone sender, String reason) {
+ }
+
+ public void notifyDataConnectionFailed(Phone sender, String reason) {
+ }
+
+ public void notifyDataActivity(Phone sender) {
+ }
+}
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java
new file mode 100644
index 0000000..58e73e0
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java
@@ -0,0 +1,887 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma.sms;
+
+import android.telephony.TelephonyManager;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.cdma.SmsMessage;
+import com.android.internal.telephony.cdma.sms.BearerData;
+import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
+import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails;
+import com.android.internal.util.BitwiseInputStream;
+import com.android.internal.util.BitwiseOutputStream;
+import com.android.internal.util.HexDump;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+
+public class CdmaSmsTest extends AndroidTestCase {
+ private final static String LOG_TAG = "XXX CdmaSmsTest XXX";
+
+ @SmallTest
+ public void testCdmaSmsAddrParsing() throws Exception {
+ CdmaSmsAddress addr = CdmaSmsAddress.parse("6502531000");
+ assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
+ assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+ assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+ assertEquals(addr.numberOfDigits, 10);
+ assertEquals(addr.origBytes.length, 10);
+ byte[] data = {6, 5, 10, 2, 5, 3, 1, 10, 10, 10};
+ for (int i = 0; i < data.length; i++) {
+ assertEquals(addr.origBytes[i], data[i]);
+ }
+ addr = CdmaSmsAddress.parse("(650) 253-1000");
+ assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
+ assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+ assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+ assertEquals(addr.numberOfDigits, 10);
+ assertEquals(addr.origBytes.length, 10);
+ byte[] data2 = {6, 5, 10, 2, 5, 3, 1, 10, 10, 10};
+ for (int i = 0; i < data2.length; i++) {
+ assertEquals(addr.origBytes[i], data2[i]);
+ }
+ addr = CdmaSmsAddress.parse("650.253.1000");
+ assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
+ assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+ assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+ assertEquals(addr.numberOfDigits, 10);
+ assertEquals(addr.origBytes.length, 10);
+ byte[] data5 = {6, 5, 10, 2, 5, 3, 1, 10, 10, 10};
+ for (int i = 0; i < data2.length; i++) {
+ assertEquals(addr.origBytes[i], data5[i]);
+ }
+ addr = CdmaSmsAddress.parse("(+886) 917 222 555");
+ assertEquals(addr.ton, CdmaSmsAddress.TON_INTERNATIONAL_OR_IP);
+ assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+ assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+ assertEquals(addr.numberOfDigits, 12);
+ assertEquals(addr.origBytes.length, 12);
+ byte[] data3 = {8, 8, 6, 9, 1, 7, 2, 2, 2, 5, 5, 5};
+ for (int i = 0; i < data3.length; i++) {
+ assertEquals(addr.origBytes[i], data3[i]);
+ }
+ addr = CdmaSmsAddress.parse("(650) *253-1000 #600");
+ byte[] data4 = {6, 5, 10, 11, 2, 5, 3, 1, 10, 10, 10, 12, 6, 10, 10};
+ for (int i = 0; i < data4.length; i++) {
+ assertEquals(addr.origBytes[i], data4[i]);
+ }
+ String input = "x@y.com,a@b.com";
+ addr = CdmaSmsAddress.parse(input);
+ assertEquals(addr.ton, CdmaSmsAddress.TON_NATIONAL_OR_EMAIL);
+ assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR);
+ assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK);
+ assertEquals(addr.numberOfDigits, 15);
+ assertEquals(addr.origBytes.length, 15);
+ assertEquals(new String(addr.origBytes), input);
+ addr = CdmaSmsAddress.parse("foo bar");
+ assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
+ assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR);
+ assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK);
+ assertEquals(addr.numberOfDigits, 6);
+ assertEquals(addr.origBytes.length, 6);
+ assertEquals(new String(addr.origBytes), "foobar");
+ addr = CdmaSmsAddress.parse("f\noo\tb a\rr");
+ assertEquals(new String(addr.origBytes), "foobar");
+ assertEquals(CdmaSmsAddress.parse("f\u0000oo bar"), null);
+ assertEquals(CdmaSmsAddress.parse("f\u0007oo bar"), null);
+ assertEquals(CdmaSmsAddress.parse("f\u0080oo bar"), null);
+ assertEquals(CdmaSmsAddress.parse("f\u1ECFboo\u001fbar"), null);
+ assertEquals(CdmaSmsAddress.parse("f\u0080oo bar"), null);
+ }
+
+ @SmallTest
+ public void testUserData7bitGsm() throws Exception {
+ String pdu = "00031040900112488ea794e074d69e1b7392c270326cde9e98";
+ BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
+ assertEquals("Test standard SMS", bearerData.userData.payloadStr);
+ }
+
+ @SmallTest
+ public void testUserData7bitAscii() throws Exception {
+ String pdu = "0003100160010610262d5ab500";
+ BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
+ assertEquals("bjjj", bearerData.userData.payloadStr);
+ }
+
+ @SmallTest
+ public void testUserData7bitAsciiTwo() throws Exception {
+ String pdu = "00031001d00109104539b4d052ebb3d0";
+ BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
+ assertEquals("SMS Rulz", bearerData.userData.payloadStr);
+ }
+
+ @SmallTest
+ public void testUserDataIa5() throws Exception {
+ String pdu = "00031002100109184539b4d052ebb3d0";
+ BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
+ assertEquals("SMS Rulz", bearerData.userData.payloadStr);
+ }
+
+ @SmallTest
+ public void testUserData7bitAsciiFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "Test standard SMS";
+ userData.msgEncoding = UserData.ENCODING_7BIT_ASCII;
+ userData.msgEncodingSet = true;
+ bearerData.userData = userData;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(BearerData.MESSAGE_TYPE_DELIVER, revBearerData.messageType);
+ assertEquals(0, revBearerData.messageId);
+ assertEquals(false, revBearerData.hasUserDataHeader);
+ assertEquals(userData.msgEncoding, revBearerData.userData.msgEncoding);
+ assertEquals(userData.payloadStr.length(), revBearerData.userData.numFields);
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "Test \u007f standard \u0000 SMS";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals("Test standard SMS", revBearerData.userData.payloadStr);
+ userData.payloadStr = "Test \n standard \r SMS";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ }
+
+ @SmallTest
+ public void testUserData7bitGsmFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "Test standard SMS";
+ userData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
+ userData.msgEncodingSet = true;
+ bearerData.userData = userData;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(BearerData.MESSAGE_TYPE_DELIVER, revBearerData.messageType);
+ assertEquals(0, revBearerData.messageId);
+ assertEquals(false, revBearerData.hasUserDataHeader);
+ assertEquals(userData.msgEncoding, revBearerData.userData.msgEncoding);
+ assertEquals(userData.payloadStr.length(), revBearerData.userData.numFields);
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "1234567";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "12345678901234567890123456789012345678901234567890" +
+ "12345678901234567890123456789012345678901234567890" +
+ "12345678901234567890123456789012345678901234567890" +
+ "1234567890";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "Test \u007f illegal \u0000 SMS chars";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals("Test illegal SMS chars", revBearerData.userData.payloadStr);
+ userData.payloadStr = "More @ testing\nis great^|^~woohoo";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 0xEE;
+ concatRef.msgCount = 2;
+ concatRef.seqNumber = 2;
+ concatRef.isEightBits = true;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+ byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
+ userData.userDataHeader = smsHeader;
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ SmsHeader decodedHeader = revBearerData.userData.userDataHeader;
+ assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
+ assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
+ assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
+ }
+
+ @SmallTest
+ public void testUserDataUtf16Feedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "\u0160u\u1E5B\u0301r\u1ECFg\uD835\uDC1At\u00E9\u4E002\u3042";
+ userData.msgEncoding = UserData.ENCODING_UNICODE_16;
+ userData.msgEncodingSet = true;
+ bearerData.userData = userData;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(BearerData.MESSAGE_TYPE_DELIVER, revBearerData.messageType);
+ assertEquals(0, revBearerData.messageId);
+ assertEquals(false, revBearerData.hasUserDataHeader);
+ assertEquals(userData.msgEncoding, revBearerData.userData.msgEncoding);
+ assertEquals(userData.payloadStr.length(), revBearerData.userData.numFields);
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.msgEncoding = UserData.ENCODING_OCTET;
+ userData.msgEncodingSet = false;
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(BearerData.MESSAGE_TYPE_DELIVER, revBearerData.messageType);
+ assertEquals(0, revBearerData.messageId);
+ assertEquals(false, revBearerData.hasUserDataHeader);
+ assertEquals(userData.msgEncoding, revBearerData.userData.msgEncoding);
+ assertEquals(userData.payloadStr.length(), revBearerData.userData.numFields);
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "1234567";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ userData.payloadStr = "";
+ revBearerData = BearerData.decode(BearerData.encode(bearerData));
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ }
+
+ @SmallTest
+ public void testMonolithicOne() throws Exception {
+ String pdu = "0003200010010410168d2002010503060812011101590501c706069706180000000701c108" +
+ "01c00901800a01e00b01030c01c00d01070e05039acc13880f018011020566";
+ BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
+ assertEquals(bearerData.messageType, BearerData.MESSAGE_TYPE_SUBMIT);
+ assertEquals(bearerData.messageId, 1);
+ assertEquals(bearerData.priority, BearerData.PRIORITY_EMERGENCY);
+ assertEquals(bearerData.privacy, BearerData.PRIVACY_CONFIDENTIAL);
+ assertEquals(bearerData.userAckReq, true);
+ assertEquals(bearerData.readAckReq, true);
+ assertEquals(bearerData.deliveryAckReq, true);
+ assertEquals(bearerData.reportReq, false);
+ assertEquals(bearerData.numberOfMessages, 3);
+ assertEquals(bearerData.alert, BearerData.ALERT_HIGH_PRIO);
+ assertEquals(bearerData.language, BearerData.LANGUAGE_HEBREW);
+ assertEquals(bearerData.callbackNumber.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+ assertEquals(bearerData.callbackNumber.numberMode,
+ CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+ assertEquals(bearerData.callbackNumber.ton, CdmaSmsAddress.TON_UNKNOWN);
+ assertEquals(bearerData.callbackNumber.numberPlan, CdmaSmsAddress.NUMBERING_PLAN_UNKNOWN);
+ assertEquals(bearerData.callbackNumber.numberOfDigits, 7);
+ assertEquals(bearerData.callbackNumber.address, "3598271");
+ assertEquals(bearerData.displayMode, BearerData.DISPLAY_MODE_USER);
+ assertEquals(bearerData.depositIndex, 1382);
+ assertEquals(bearerData.userResponseCode, 5);
+ assertEquals(bearerData.msgCenterTimeStamp.year, 2008);
+ assertEquals(bearerData.msgCenterTimeStamp.month, 11);
+ assertEquals(bearerData.msgCenterTimeStamp.monthDay, 1);
+ assertEquals(bearerData.msgCenterTimeStamp.hour, 11);
+ assertEquals(bearerData.msgCenterTimeStamp.minute, 1);
+ assertEquals(bearerData.msgCenterTimeStamp.second, 59);
+ assertEquals(bearerData.validityPeriodAbsolute, null);
+ assertEquals(bearerData.validityPeriodRelative, 193);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.year, 1997);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.month, 5);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.monthDay, 18);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.hour, 0);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.minute, 0);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.second, 0);
+ assertEquals(bearerData.deferredDeliveryTimeRelative, 199);
+ assertEquals(bearerData.hasUserDataHeader, false);
+ assertEquals(bearerData.userData.msgEncoding, UserData.ENCODING_7BIT_ASCII);
+ assertEquals(bearerData.userData.numFields, 2);
+ assertEquals(bearerData.userData.payloadStr, "hi");
+ }
+
+ @SmallTest
+ public void testMonolithicTwo() throws Exception {
+ String pdu = "0003200010010410168d200201050306081201110159050192060697061800000007013d0" +
+ "801c00901800a01e00b01030c01c00d01070e05039acc13880f018011020566";
+ BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
+ assertEquals(bearerData.messageType, BearerData.MESSAGE_TYPE_SUBMIT);
+ assertEquals(bearerData.messageId, 1);
+ assertEquals(bearerData.priority, BearerData.PRIORITY_EMERGENCY);
+ assertEquals(bearerData.privacy, BearerData.PRIVACY_CONFIDENTIAL);
+ assertEquals(bearerData.userAckReq, true);
+ assertEquals(bearerData.readAckReq, true);
+ assertEquals(bearerData.deliveryAckReq, true);
+ assertEquals(bearerData.reportReq, false);
+ assertEquals(bearerData.numberOfMessages, 3);
+ assertEquals(bearerData.alert, BearerData.ALERT_HIGH_PRIO);
+ assertEquals(bearerData.language, BearerData.LANGUAGE_HEBREW);
+ assertEquals(bearerData.callbackNumber.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
+ assertEquals(bearerData.callbackNumber.numberMode,
+ CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
+ assertEquals(bearerData.callbackNumber.ton, CdmaSmsAddress.TON_UNKNOWN);
+ assertEquals(bearerData.callbackNumber.numberPlan, CdmaSmsAddress.NUMBERING_PLAN_UNKNOWN);
+ assertEquals(bearerData.callbackNumber.numberOfDigits, 7);
+ assertEquals(bearerData.callbackNumber.address, "3598271");
+ assertEquals(bearerData.displayMode, BearerData.DISPLAY_MODE_USER);
+ assertEquals(bearerData.depositIndex, 1382);
+ assertEquals(bearerData.userResponseCode, 5);
+ assertEquals(bearerData.msgCenterTimeStamp.year, 2008);
+ assertEquals(bearerData.msgCenterTimeStamp.month, 11);
+ assertEquals(bearerData.msgCenterTimeStamp.monthDay, 1);
+ assertEquals(bearerData.msgCenterTimeStamp.hour, 11);
+ assertEquals(bearerData.msgCenterTimeStamp.minute, 1);
+ assertEquals(bearerData.msgCenterTimeStamp.second, 59);
+ assertEquals(bearerData.validityPeriodAbsolute, null);
+ assertEquals(bearerData.validityPeriodRelative, 61);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.year, 1997);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.month, 5);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.monthDay, 18);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.hour, 0);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.minute, 0);
+ assertEquals(bearerData.deferredDeliveryTimeAbsolute.second, 0);
+ assertEquals(bearerData.deferredDeliveryTimeRelative, 146);
+ assertEquals(bearerData.hasUserDataHeader, false);
+ assertEquals(bearerData.userData.msgEncoding, UserData.ENCODING_7BIT_ASCII);
+ assertEquals(bearerData.userData.numFields, 2);
+ assertEquals(bearerData.userData.payloadStr, "hi");
+ }
+
+ @SmallTest
+ public void testUserDataHeaderConcatRefFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 55;
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 0xEE;
+ concatRef.msgCount = 2;
+ concatRef.seqNumber = 2;
+ concatRef.isEightBits = true;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+ byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
+ SmsHeader decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
+ assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
+ assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
+ assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
+ assertEquals(decodedHeader.portAddrs, null);
+ UserData userData = new UserData();
+ userData.payloadStr = "User Data Header (UDH) feedback test";
+ userData.userDataHeader = smsHeader;
+ bearerData.userData = userData;
+ byte[] encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ decodedHeader = revBearerData.userData.userDataHeader;
+ assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
+ assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
+ assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
+ assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
+ assertEquals(decodedHeader.portAddrs, null);
+ }
+
+ @SmallTest
+ public void testUserDataHeaderIllegalConcatRef() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 55;
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 0x10;
+ concatRef.msgCount = 0;
+ concatRef.seqNumber = 2;
+ concatRef.isEightBits = true;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+ byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
+ SmsHeader decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef, null);
+ concatRef.isEightBits = false;
+ encodedHeader = SmsHeader.toByteArray(smsHeader);
+ decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef, null);
+ concatRef.msgCount = 1;
+ concatRef.seqNumber = 2;
+ encodedHeader = SmsHeader.toByteArray(smsHeader);
+ decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef, null);
+ concatRef.msgCount = 1;
+ concatRef.seqNumber = 0;
+ encodedHeader = SmsHeader.toByteArray(smsHeader);
+ decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef, null);
+ concatRef.msgCount = 2;
+ concatRef.seqNumber = 1;
+ encodedHeader = SmsHeader.toByteArray(smsHeader);
+ decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef.msgCount, 2);
+ assertEquals(decodedHeader.concatRef.seqNumber, 1);
+ }
+
+ @SmallTest
+ public void testUserDataHeaderMixedFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 42;
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 0x34;
+ concatRef.msgCount = 5;
+ concatRef.seqNumber = 2;
+ concatRef.isEightBits = false;
+ SmsHeader.PortAddrs portAddrs = new SmsHeader.PortAddrs();
+ portAddrs.destPort = 88;
+ portAddrs.origPort = 66;
+ portAddrs.areEightBits = false;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+ smsHeader.portAddrs = portAddrs;
+ byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
+ SmsHeader decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
+ assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
+ assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
+ assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
+ assertEquals(decodedHeader.portAddrs.destPort, portAddrs.destPort);
+ assertEquals(decodedHeader.portAddrs.origPort, portAddrs.origPort);
+ assertEquals(decodedHeader.portAddrs.areEightBits, portAddrs.areEightBits);
+ UserData userData = new UserData();
+ userData.payloadStr = "User Data Header (UDH) feedback test";
+ userData.userDataHeader = smsHeader;
+ bearerData.userData = userData;
+ byte[] encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ decodedHeader = revBearerData.userData.userDataHeader;
+ assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
+ assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
+ assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
+ assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
+ assertEquals(decodedHeader.portAddrs.destPort, portAddrs.destPort);
+ assertEquals(decodedHeader.portAddrs.origPort, portAddrs.origPort);
+ assertEquals(decodedHeader.portAddrs.areEightBits, portAddrs.areEightBits);
+ }
+
+ @SmallTest
+ public void testReplyOption() throws Exception {
+ String pdu1 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87450080a0180";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals("Test Acknowledgement 1", bd1.userData.payloadStr);
+ assertEquals(true, bd1.userAckReq);
+ assertEquals(false, bd1.deliveryAckReq);
+ assertEquals(false, bd1.readAckReq);
+ assertEquals(false, bd1.reportReq);
+ String pdu2 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87490080a0140";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals("Test Acknowledgement 2", bd2.userData.payloadStr);
+ assertEquals(false, bd2.userAckReq);
+ assertEquals(true, bd2.deliveryAckReq);
+ assertEquals(false, bd2.readAckReq);
+ assertEquals(false, bd2.reportReq);
+ String pdu3 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d874d0080a0120";
+ BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+ assertEquals("Test Acknowledgement 3", bd3.userData.payloadStr);
+ assertEquals(false, bd3.userAckReq);
+ assertEquals(false, bd3.deliveryAckReq);
+ assertEquals(true, bd3.readAckReq);
+ assertEquals(false, bd3.reportReq);
+ String pdu4 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87510080a0110";
+ BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
+ assertEquals("Test Acknowledgement 4", bd4.userData.payloadStr);
+ assertEquals(false, bd4.userAckReq);
+ assertEquals(false, bd4.deliveryAckReq);
+ assertEquals(false, bd4.readAckReq);
+ assertEquals(true, bd4.reportReq);
+ }
+
+ @SmallTest
+ public void testReplyOptionFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "test reply option";
+ bearerData.userData = userData;
+ bearerData.userAckReq = true;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(true, revBearerData.userAckReq);
+ assertEquals(false, revBearerData.deliveryAckReq);
+ assertEquals(false, revBearerData.readAckReq);
+ assertEquals(false, revBearerData.reportReq);
+ bearerData.userAckReq = false;
+ bearerData.deliveryAckReq = true;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(false, revBearerData.userAckReq);
+ assertEquals(true, revBearerData.deliveryAckReq);
+ assertEquals(false, revBearerData.readAckReq);
+ assertEquals(false, revBearerData.reportReq);
+ bearerData.deliveryAckReq = false;
+ bearerData.readAckReq = true;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(false, revBearerData.userAckReq);
+ assertEquals(false, revBearerData.deliveryAckReq);
+ assertEquals(true, revBearerData.readAckReq);
+ assertEquals(false, revBearerData.reportReq);
+ bearerData.readAckReq = false;
+ bearerData.reportReq = true;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(false, revBearerData.userAckReq);
+ assertEquals(false, revBearerData.deliveryAckReq);
+ assertEquals(false, revBearerData.readAckReq);
+ assertEquals(true, revBearerData.reportReq);
+ }
+
+ @SmallTest
+ public void testNumberOfMessages() throws Exception {
+ // Note that the message text below does not properly reflect
+ // the message count. The author of these messages was
+ // apparently unaware that the values are bcd encoded, and the
+ // values being tested against (not the ones in the message
+ // text) are actually correct.
+ String pdu1 = "000310409001124896a794e07595f69f199540ea759a0dc8e00b0163";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals("Test Voice mail 99", bd1.userData.payloadStr);
+ assertEquals(63, bd1.numberOfMessages);
+ String pdu2 = "00031040900113489ea794e07595f69f199540ea759a0988c0600b0164";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals("Test Voice mail 100", bd2.userData.payloadStr);
+ assertEquals(64, bd2.numberOfMessages);
+ }
+
+ @SmallTest
+ public void testCallbackNum() throws Exception {
+ String pdu1 = "00031040900112488ea794e070d436cb638bc5e035ce2f97900e06910431323334";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals("Test Callback nbr", bd1.userData.payloadStr);
+ assertEquals(CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR, bd1.callbackNumber.digitMode);
+ assertEquals(CdmaSmsAddress.TON_INTERNATIONAL_OR_IP, bd1.callbackNumber.ton);
+ assertEquals(CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK, bd1.callbackNumber.numberMode);
+ assertEquals(CdmaSmsAddress.NUMBERING_PLAN_ISDN_TELEPHONY, bd1.callbackNumber.numberPlan);
+ assertEquals("1234", bd1.callbackNumber.address);
+ }
+
+ @SmallTest
+ public void testCallbackNumDtmf() throws Exception {
+ String pdu1 = "00031002300109104539b4d052ebb3d00e07052d4c90a55080";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals("SMS Rulz", bd1.userData.payloadStr);
+ assertEquals(CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF, bd1.callbackNumber.digitMode);
+ assertEquals(CdmaSmsAddress.TON_UNKNOWN, bd1.callbackNumber.ton);
+ assertEquals(CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK, bd1.callbackNumber.numberMode);
+ assertEquals(CdmaSmsAddress.NUMBERING_PLAN_UNKNOWN, bd1.callbackNumber.numberPlan);
+ assertEquals("5099214001", bd1.callbackNumber.address);
+ }
+
+ @SmallTest
+ public void testCallbackNumFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "test callback number";
+ bearerData.userData = userData;
+ CdmaSmsAddress addr = new CdmaSmsAddress();
+ addr.digitMode = CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR;
+ addr.ton = CdmaSmsAddress.TON_NATIONAL_OR_EMAIL;
+ addr.numberMode = CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK;
+ addr.numberPlan = CdmaSmsAddress.NUMBERING_PLAN_UNKNOWN;
+ addr.address = "8005551212";
+ addr.numberOfDigits = (byte)addr.address.length();
+ bearerData.callbackNumber = addr;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ CdmaSmsAddress revAddr = revBearerData.callbackNumber;
+ assertEquals(addr.digitMode, revAddr.digitMode);
+ assertEquals(addr.ton, revAddr.ton);
+ assertEquals(addr.numberMode, revAddr.numberMode);
+ assertEquals(addr.numberPlan, revAddr.numberPlan);
+ assertEquals(addr.numberOfDigits, revAddr.numberOfDigits);
+ assertEquals(addr.address, revAddr.address);
+ addr.address = "8*55#1012";
+ addr.numberOfDigits = (byte)addr.address.length();
+ addr.digitMode = CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ revAddr = revBearerData.callbackNumber;
+ assertEquals(addr.digitMode, revAddr.digitMode);
+ assertEquals(addr.numberOfDigits, revAddr.numberOfDigits);
+ assertEquals(addr.address, revAddr.address);
+ }
+
+ @SmallTest
+ public void testPrivacyIndicator() throws Exception {
+ String pdu1 = "0003104090010c485f4194dfea34becf61b840090140";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.privacy, BearerData.PRIVACY_RESTRICTED);
+ String pdu2 = "0003104090010c485f4194dfea34becf61b840090180";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals(bd2.privacy, BearerData.PRIVACY_CONFIDENTIAL);
+ String pdu3 = "0003104090010c485f4194dfea34becf61b8400901c0";
+ BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+ assertEquals(bd3.privacy, BearerData.PRIVACY_SECRET);
+ }
+
+ @SmallTest
+ public void testPrivacyIndicatorFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "test privacy indicator";
+ bearerData.userData = userData;
+ bearerData.privacy = BearerData.PRIVACY_SECRET;
+ bearerData.privacyIndicatorSet = true;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
+ assertEquals(revBearerData.privacyIndicatorSet, true);
+ assertEquals(revBearerData.privacy, BearerData.PRIVACY_SECRET);
+ bearerData.privacy = BearerData.PRIVACY_RESTRICTED;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.privacy, BearerData.PRIVACY_RESTRICTED);
+ }
+
+ @SmallTest
+ public void testMsgDeliveryAlert() throws Exception {
+ String pdu1 = "0003104090010d4866a794e07055965b91d040300c0100";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.alert, 0);
+ assertEquals(bd1.userData.payloadStr, "Test Alert 0");
+ String pdu2 = "0003104090010d4866a794e07055965b91d140300c0140";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals(bd2.alert, 1);
+ assertEquals(bd2.userData.payloadStr, "Test Alert 1");
+ String pdu3 = "0003104090010d4866a794e07055965b91d240300c0180";
+ BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+ assertEquals(bd3.alert, 2);
+ assertEquals(bd3.userData.payloadStr, "Test Alert 2");
+ String pdu4 = "0003104090010d4866a794e07055965b91d340300c01c0";
+ BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
+ assertEquals(bd4.alert, 3);
+ assertEquals(bd4.userData.payloadStr, "Test Alert 3");
+ String pdu5 = "00031000000126114F4CBCFA20DB979F3C39F2A0C9976" +
+ "69ED979794187665E5D1028EFA7A6840E1062D3D39A900C028000";
+ BearerData bd5 = BearerData.decode(HexDump.hexStringToByteArray(pdu5));
+ assertEquals(bd5.alert, BearerData.ALERT_MEDIUM_PRIO);
+ assertEquals(bd5.userData.payloadStr, "test message delivery alert (with 8 bits)");
+ String pdu6 = "00031000000126114F4CBCFA20DB979F3C39F2A0C9976" +
+ "69ED979794187665E5D1028EFA7A6840C1062D3D39A900C00";
+ BearerData bd6 = BearerData.decode(HexDump.hexStringToByteArray(pdu6));
+ assertEquals(bd6.userData.payloadStr, "test message delivery alert (with 0 bits)");
+ assertEquals(bd6.alertIndicatorSet, false);
+ }
+
+ @SmallTest
+ public void testMiscParams() throws Exception {
+ String pdu1 = "00031002400109104539b4d052ebb3d00c0180";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.alert, BearerData.ALERT_MEDIUM_PRIO);
+ assertEquals(bd1.userData.payloadStr, "SMS Rulz");
+ String pdu2 = "00031002500109104539b4d052ebb3d00801800901c0";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals(bd2.priority, BearerData.PRIORITY_URGENT);
+ assertEquals(bd2.privacy, BearerData.PRIVACY_SECRET);
+ assertEquals(bd2.userData.payloadStr, "SMS Rulz");
+ String pdu3 = "00031002600109104539b4d052ebb3d00901400c01c0";
+ BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+ assertEquals(bd3.privacy, BearerData.PRIVACY_RESTRICTED);
+ assertEquals(bd3.alert, BearerData.ALERT_HIGH_PRIO);
+ assertEquals(bd3.userData.payloadStr, "SMS Rulz");
+ String pdu4 = "00031002700109104539b4d052ebb3d00f0105";
+ BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
+ assertEquals(bd4.displayMode, BearerData.DISPLAY_MODE_IMMEDIATE);
+ assertEquals(bd4.userData.payloadStr, "SMS Rulz");
+ }
+ @SmallTest
+ public void testMsgDeliveryAlertFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "test message delivery alert";
+ bearerData.userData = userData;
+ bearerData.alert = BearerData.ALERT_MEDIUM_PRIO;
+ bearerData.alertIndicatorSet = true;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
+ assertEquals(revBearerData.alertIndicatorSet, true);
+ assertEquals(revBearerData.alert, bearerData.alert);
+ bearerData.alert = BearerData.ALERT_HIGH_PRIO;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
+ assertEquals(revBearerData.alertIndicatorSet, true);
+ assertEquals(revBearerData.alert, bearerData.alert);
+ }
+
+ @SmallTest
+ public void testLanguageIndicator() throws Exception {
+ String pdu1 = "0003104090011748bea794e0731436ef3bd7c2e0352eef27a1c263fe58080d0101";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.userData.payloadStr, "Test Language indicator");
+ assertEquals(bd1.language, BearerData.LANGUAGE_ENGLISH);
+ String pdu2 = "0003104090011748bea794e0731436ef3bd7c2e0352eef27a1c263fe58080d0106";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals(bd2.userData.payloadStr, "Test Language indicator");
+ assertEquals(bd2.language, BearerData.LANGUAGE_CHINESE);
+ }
+
+ @SmallTest
+ public void testLanguageIndicatorFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "test language indicator";
+ bearerData.userData = userData;
+ bearerData.language = BearerData.LANGUAGE_ENGLISH;
+ bearerData.languageIndicatorSet = true;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
+ assertEquals(revBearerData.languageIndicatorSet, true);
+ assertEquals(revBearerData.language, bearerData.language);
+ bearerData.language = BearerData.LANGUAGE_KOREAN;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
+ assertEquals(revBearerData.languageIndicatorSet, true);
+ assertEquals(revBearerData.language, bearerData.language);
+ }
+
+ @SmallTest
+ public void testDisplayMode() throws Exception {
+ String pdu1 = "0003104090010c485f4194dfea34becf61b8400f0100";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.displayMode, BearerData.DISPLAY_MODE_IMMEDIATE);
+ String pdu2 = "0003104090010c485f4194dfea34becf61b8400f0140";
+ BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+ assertEquals(bd2.displayMode, BearerData.DISPLAY_MODE_DEFAULT);
+ String pdu3 = "0003104090010c485f4194dfea34becf61b8400f0180";
+ BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+ assertEquals(bd3.displayMode, BearerData.DISPLAY_MODE_USER);
+ }
+
+ @SmallTest
+ public void testDisplayModeFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 0;
+ bearerData.hasUserDataHeader = false;
+ UserData userData = new UserData();
+ userData.payloadStr = "test display mode";
+ bearerData.userData = userData;
+ bearerData.displayMode = BearerData.DISPLAY_MODE_IMMEDIATE;
+ bearerData.displayModeSet = true;
+ byte []encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
+ assertEquals(revBearerData.displayModeSet, true);
+ assertEquals(revBearerData.displayMode, bearerData.displayMode);
+ bearerData.displayMode = BearerData.DISPLAY_MODE_USER;
+ encodedSms = BearerData.encode(bearerData);
+ revBearerData = BearerData.decode(encodedSms);
+ assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
+ assertEquals(revBearerData.displayModeSet, true);
+ assertEquals(revBearerData.displayMode, bearerData.displayMode);
+ }
+
+ @SmallTest
+ public void testIs91() throws Exception {
+ String pdu1 = "000320001001070c2039acc13880";
+ BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+ assertEquals(bd1.callbackNumber.address, "3598271");
+ String pdu4 = "000320001001080c283c314724b34e";
+ BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
+ assertEquals(bd4.userData.payloadStr, "ABCDEFG");
+ }
+
+ @SmallTest
+ public void testUserDataHeaderWithEightCharMsg() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 55;
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 0xEE;
+ concatRef.msgCount = 2;
+ concatRef.seqNumber = 2;
+ concatRef.isEightBits = true;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+ UserData userData = new UserData();
+ userData.payloadStr = "01234567";
+ userData.userDataHeader = smsHeader;
+ bearerData.userData = userData;
+ byte[] encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
+ }
+
+ @SmallTest
+ public void testFragmentText() throws Exception {
+ boolean isCdmaPhone = (TelephonyManager.getDefault().getPhoneType() ==
+ TelephonyManager.PHONE_TYPE_CDMA);
+ // Valid 160 character ASCII text.
+ String text1 = "123456789012345678901234567890123456789012345678901234567890" +
+ "1234567890123456789012345678901234567890123456789012345678901234567890" +
+ "12345678901234567890123456789[";
+ TextEncodingDetails ted = SmsMessage.calculateLength(text1, false);
+ assertEquals(ted.msgCount, 1);
+ assertEquals(ted.codeUnitCount, 160);
+ assertEquals(ted.codeUnitSize, 1);
+ if (isCdmaPhone) {
+ ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text1);
+ assertEquals(fragments.size(), 1);
+ }
+
+ /*
+ This is not a valid test: we will never encode a single-segment
+ EMS message. Leaving this here, since we may try to support
+ this in the future.
+
+ // Valid 160 character GSM text -- the last character is
+ // non-ASCII, and so this will currently generate a singleton
+ // EMS message, which is not necessarily supported by Verizon.
+ String text2 = "123456789012345678901234567890123456789012345678901234567890" +
+ "1234567890123456789012345678901234567890123456789012345678901234567890" +
+ "12345678901234567890123456789\u00a3"; // Trailing pound-currency sign.
+ ted = SmsMessage.calculateLength(text2, false);
+ assertEquals(ted.msgCount, 1);
+ assertEquals(ted.codeUnitCount, 160);
+ assertEquals(ted.codeUnitSize, 1);
+ if (isCdmaPhone) {
+ ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text2);
+ assertEquals(fragments.size(), 1);
+ }
+ */
+
+ // *IF* we supported single-segment EMS, this text would result in a
+ // single fragment with 7-bit encoding. But we don't, so this text
+ // results in three fragments of 16-bit encoding.
+ String text2 = "123456789012345678901234567890123456789012345678901234567890" +
+ "1234567890123456789012345678901234567890123456789012345678901234567890" +
+ "12345678901234567890123456789\u00a3"; // Trailing pound-currency sign.
+ ted = SmsMessage.calculateLength(text2, false);
+ assertEquals(3, ted.msgCount);
+ assertEquals(160, ted.codeUnitCount);
+ assertEquals(3, ted.codeUnitSize);
+ if (isCdmaPhone) {
+ ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text2);
+ assertEquals(3, fragments.size());
+ }
+
+ }
+}
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
new file mode 100644
index 0000000..b96743a
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMPhoneTest.java
@@ -0,0 +1,1938 @@
+/*
+ * Copyright (C) 2007 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 GSMTestHandler.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.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;
+
+
+public class GSMPhoneTest extends AndroidTestCase implements PerformanceTestCase {
+ private SimulatedRadioControl mRadioControl;
+ private GSMPhone mGSMPhone;
+ private GSMTestHandler mGSMTestHandler;
+ private Handler mHandler;
+
+ private static final int EVENT_PHONE_STATE_CHANGED = 1;
+ private static final int EVENT_DISCONNECT = 2;
+ private static final int EVENT_RINGING = 3;
+ private static final int EVENT_CHANNEL_OPENED = 4;
+ private static final int EVENT_POST_DIAL = 5;
+ private static final int EVENT_DONE = 6;
+ private static final int EVENT_SSN = 7;
+ private static final int EVENT_MMI_INITIATE = 8;
+ private static final int EVENT_MMI_COMPLETE = 9;
+ private static final int EVENT_IN_SERVICE = 10;
+ private static final int SUPP_SERVICE_FAILED = 11;
+ private static final int SERVICE_STATE_CHANGED = 12;
+ private static final int EVENT_OEM_RIL_MESSAGE = 13;
+ public static final int ANY_MESSAGE = -1;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mGSMTestHandler = new GSMTestHandler(mContext);
+
+ mGSMTestHandler.start();
+ synchronized (mGSMTestHandler) {
+ do {
+ mGSMTestHandler.wait();
+ } while (mGSMTestHandler.getGSMPhone() == null);
+ }
+
+ mGSMPhone = mGSMTestHandler.getGSMPhone();
+ mRadioControl = mGSMTestHandler.getSimulatedCommands();
+
+ mHandler = mGSMTestHandler.getHandler();
+ mGSMPhone.registerForPreciseCallStateChanged(mHandler, EVENT_PHONE_STATE_CHANGED, null);
+ mGSMPhone.registerForNewRingingConnection(mHandler, EVENT_RINGING, null);
+ mGSMPhone.registerForDisconnect(mHandler, EVENT_DISCONNECT, null);
+
+ mGSMPhone.setOnPostDialCharacter(mHandler, EVENT_POST_DIAL, null);
+
+ mGSMPhone.registerForSuppServiceNotification(mHandler, EVENT_SSN, null);
+ mGSMPhone.registerForMmiInitiate(mHandler, EVENT_MMI_INITIATE, null);
+ mGSMPhone.registerForMmiComplete(mHandler, EVENT_MMI_COMPLETE, null);
+ mGSMPhone.registerForSuppServiceFailed(mHandler, SUPP_SERVICE_FAILED, null);
+
+ mGSMPhone.registerForServiceStateChanged(mHandler, SERVICE_STATE_CHANGED, null);
+
+ // wait until we get phone in both voice and data service
+ Message msg;
+ ServiceState state;
+
+ do {
+ msg = mGSMTestHandler.waitForMessage(SERVICE_STATE_CHANGED);
+ assertNotNull("Message Time Out", msg);
+ state = (ServiceState) ((AsyncResult) msg.obj).result;
+ } while (state.getState() != ServiceState.STATE_IN_SERVICE);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mRadioControl.shutdown();
+
+ mGSMPhone.unregisterForPreciseCallStateChanged(mHandler);
+ mGSMPhone.unregisterForNewRingingConnection(mHandler);
+ mGSMPhone.unregisterForDisconnect(mHandler);
+ mGSMPhone.setOnPostDialCharacter(mHandler, 0, null);
+ mGSMPhone.unregisterForSuppServiceNotification(mHandler);
+ mGSMPhone.unregisterForMmiInitiate(mHandler);
+ mGSMPhone.unregisterForMmiComplete(mHandler);
+
+ mGSMPhone = null;
+ mRadioControl = null;
+ mHandler = null;
+ mGSMTestHandler.cleanup();
+
+ super.tearDown();
+ }
+
+ // These test can only be run once.
+ public int startPerformance(Intermediates intermediates) {
+ return 1;
+ }
+
+ public boolean isPerformanceOnly() {
+ return false;
+ }
+
+
+ //This test is causing the emulator screen to turn off. I don't understand
+ //why, but I'm removing it until we can figure it out.
+ public void brokenTestGeneral() throws Exception {
+ Connection cn;
+ Message msg;
+ AsyncResult ar;
+
+ // IDLE state
+
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+ assertFalse(mGSMPhone.canConference());
+
+ // One DIALING connection
+
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ mGSMPhone.dial("+13125551212");
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_PHONE_STATE_CHANGED);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.DIALING, mGSMPhone.getForegroundCall().getState());
+ assertTrue(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ /*do {
+ mGSMTestHandler.waitForMessage(ANY_MESSAGE);
+ } while (mGSMPhone.getForegroundCall().getConnections().size() == 0);*/
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DIALING,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ cn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ assertTrue(!cn.isIncoming());
+ assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());
+
+ assertEquals(Connection.DisconnectCause.NOT_DISCONNECTED, cn.getDisconnectCause());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // One ALERTING connection
+
+ mRadioControl.progressConnectingCallState();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getForegroundCall().getState() != Call.State.ALERTING);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ALERTING, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ cn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ assertTrue(!cn.isIncoming());
+ assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());
+ assertFalse(mGSMPhone.canConference());
+
+ // One ACTIVE connection
+
+ mRadioControl.progressConnectingCallState();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);
+
+ cn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ assertTrue(!cn.isIncoming());
+ assertEquals(Connection.PostDialState.COMPLETE, cn.getPostDialState());
+ assertFalse(mGSMPhone.canConference());
+
+ // One disconnected connection
+ mGSMPhone.getForegroundCall().hangup();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);
+
+ assertFalse(mGSMPhone.canConference());
+
+ cn = mGSMPhone.getForegroundCall().getEarliestConnection();
+
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ // Back to idle state
+
+ mGSMPhone.clearDisconnected();
+
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // cn left over from before phone.clearDisconnected();
+
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ // One ringing (INCOMING) call
+
+ mRadioControl.triggerRing("18005551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ ar = (AsyncResult) msg.obj;
+ cn = (Connection) ar.result;
+ assertTrue(cn.isRinging());
+ assertEquals(mGSMPhone.getRingingCall(), cn.getCall());
+
+ assertEquals(1, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.INCOMING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getRingingCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getRingingCall().getEarliestConnectTime());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ cn = mGSMPhone.getRingingCall().getConnections().get(0);
+ assertTrue(cn.isIncoming());
+ assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // One mobile terminated active call
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getConnections().size() == 1);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);
+
+ cn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ assertTrue(cn.isIncoming());
+ assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // One disconnected (local hangup) call
+
+ try {
+ Connection conn;
+ conn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ conn.hangup();
+ } catch (CallStateException ex) {
+ ex.printStackTrace();
+ fail("unexpected ex");
+ }
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);
+
+ cn = mGSMPhone.getForegroundCall().getEarliestConnection();
+
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // Back to idle state
+
+ mGSMPhone.clearDisconnected();
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // cn left over from before phone.clearDisconnected();
+
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ // One ringing call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getConnections().isEmpty());
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(1, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.INCOMING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getRingingCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getRingingCall().getEarliestConnectTime());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // One rejected call
+ mGSMPhone.rejectCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.IDLE);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(1, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getRingingCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getRingingCall().getEarliestConnectTime());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ cn = mGSMPhone.getRingingCall().getEarliestConnection();
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // Back to idle state
+
+ mGSMPhone.clearDisconnected();
+
+ assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ assertFalse(mGSMPhone.canConference());
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ // One ringing call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getConnections().isEmpty());
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ cn = mGSMPhone.getRingingCall().getEarliestConnection();
+
+ // Ringing call disconnects
+
+ mRadioControl.triggerHangupForeground();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.IDLE);
+
+ assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());
+
+ // One Ringing Call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.RINGING);
+
+
+ cn = mGSMPhone.getRingingCall().getEarliestConnection();
+
+ // One answered call
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.OFFHOOK);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // one holding call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);
+
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // one active call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getBackgroundCall().getState() == Call.State.HOLDING);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // One disconnected call in the foreground slot
+
+ mRadioControl.triggerHangupAll();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.IDLE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Connection.DisconnectCause.NORMAL, cn.getDisconnectCause());
+
+ // Test missed calls
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.RINGING);
+
+ mGSMPhone.rejectCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (msg.what != EVENT_DISCONNECT);
+
+ ar = (AsyncResult) msg.obj;
+ cn = (Connection) ar.result;
+
+ assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getRingingCall().getState());
+
+ // Test incoming not missed calls
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.RINGING);
+
+ cn = mGSMPhone.getRingingCall().getEarliestConnection();
+
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.OFFHOOK);
+
+ assertEquals(Connection.DisconnectCause.NOT_DISCONNECTED, cn.getDisconnectCause());
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+
+ try {
+ mGSMPhone.getForegroundCall().hangup();
+ } catch (CallStateException ex) {
+ ex.printStackTrace();
+ fail("unexpected ex");
+ }
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState()
+ != Call.State.DISCONNECTED);
+
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+
+ //
+ // Test held and hangup held calls
+ //
+
+ // One ALERTING call
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.OFFHOOK);
+
+ assertTrue(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ mRadioControl.progressConnectingCallState();
+ mRadioControl.progressConnectingCallState();
+
+ // One ACTIVE call
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ // One ACTIVE call, one ringing call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.RINGING);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ // One HOLDING call, one ACTIVE call
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.OFFHOOK);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertTrue(mGSMPhone.canConference());
+
+ // Conference the two
+ mGSMPhone.conference();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertTrue(mGSMPhone.getForegroundCall().isMultiparty());
+ assertFalse(mGSMPhone.canConference());
+
+ // Hold the multiparty call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getBackgroundCall().getState() != Call.State.HOLDING);
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertTrue(mGSMPhone.getBackgroundCall().isMultiparty());
+ assertFalse(mGSMPhone.canConference());
+
+ // Multiparty call on hold, call waiting added
+
+ mRadioControl.triggerRing("18005558355");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.RINGING);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertTrue(mGSMPhone.getBackgroundCall().isMultiparty());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertFalse(mGSMPhone.canConference());
+
+ // Hangup conference call, ringing call still around
+ mGSMPhone.getBackgroundCall().hangup();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.DISCONNECTED);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getBackgroundCall().getState());
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ // Reject waiting call
+ mGSMPhone.rejectCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.IDLE);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ }
+
+ public void testOutgoingCallFailImmediately() throws Exception {
+ Message msg;
+
+ // Test outgoing call fail-immediately edge case
+ // This happens when a call terminated before ever appearing in a
+ // call list
+ // This should land the immediately-failing call in the
+ // ForegroundCall list as an IDLE call
+ mRadioControl.setNextDialFailImmediately(true);
+
+ Connection cn = mGSMPhone.dial("+13125551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Connection.DisconnectCause.NORMAL, cn.getDisconnectCause());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+ }
+
+ public void testHangupOnOutgoing() throws Exception {
+ Connection cn;
+ Message msg;
+
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ // Test 1: local hangup in "DIALING" state
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getForegroundCall().getState() != Call.State.DIALING);
+
+ cn = mGSMPhone.getForegroundCall().getEarliestConnection();
+
+ mGSMPhone.getForegroundCall().hangup();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+
+ // Test 2: local hangup in "ALERTING" state
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.OFFHOOK);
+
+ mRadioControl.progressConnectingCallState();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getForegroundCall().getState() != Call.State.ALERTING);
+
+ cn = mGSMPhone.getForegroundCall().getEarliestConnection();
+
+ mGSMPhone.getForegroundCall().hangup();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+
+ // Test 3: local immediate hangup before GSM index is
+ // assigned (CallTracker.hangupPendingMO case)
+
+ mRadioControl.pauseResponses();
+
+ cn = mGSMPhone.dial("+13125551212");
+
+ cn.hangup();
+
+ mRadioControl.resumeResponses();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+
+ assertEquals(Connection.DisconnectCause.LOCAL,
+ mGSMPhone.getForegroundCall().getEarliestConnection().getDisconnectCause());
+ }
+
+ public void testHangupOnChannelClose() throws Exception {
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getConnections().isEmpty());
+
+ mRadioControl.shutdown();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ mGSMPhone.clearDisconnected();
+ } while (!mGSMPhone.getForegroundCall().getConnections().isEmpty());
+ }
+
+ public void testIncallMmiCallDeflection() throws Exception {
+ Message msg;
+
+ // establish an active call
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // establish a ringing (WAITING) call
+
+ mRadioControl.triggerRing("18005551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 0 followed by SEND: release all held calls
+ // or sets UDUB for a waiting call.
+ mGSMPhone.handleInCallMmiCommands("0");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getState() == Call.State.WAITING);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // change the active call to holding call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);
+
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 0 followed by SEND: release all held calls
+ // or sets UDUB for a waiting call.
+ mGSMPhone.handleInCallMmiCommands("0");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.HOLDING);
+
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ public void testIncallMmiCallWaiting() throws Exception {
+ Message msg;
+
+ // establish an active call
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // establish a ringing (WAITING) call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ msg = mGSMTestHandler.waitForMessage(ANY_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+ } while (msg.what != EVENT_RINGING);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 1 followed by SEND: release all active calls
+ // (if any exist) and accepts the other (held or waiting) call.
+
+ mGSMPhone.handleInCallMmiCommands("1");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getState() == Call.State.WAITING);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+
+ // change the active call to holding call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 1 followed by SEND: release all active calls
+ // (if any exist) and accepts the other (held or waiting) call.
+ mGSMPhone.handleInCallMmiCommands("1");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+
+ // at this point, the active call with number==18005551212 should
+ // have the gsm index of 2
+
+ mRadioControl.triggerRing("16505550100");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering "12" followed by SEND: release the call with
+ // gsm index equals to 2.
+ mGSMPhone.handleInCallMmiCommands("12");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.OFFHOOK);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // at this point, the call with number==16505550100 should
+ // have the gsm index of 1
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE ||
+ mGSMPhone.getBackgroundCall().getState() != Call.State.HOLDING);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // at this point, the active call with number==13125551212 should
+ // have the gsm index of 2
+
+ // Simulate entering "11" followed by SEND: release the call with
+ // gsm index equals to 1. This should not be allowed, and a
+ // Supplementary Service notification must be received.
+ mGSMPhone.handleInCallMmiCommands("11");
+
+ msg = mGSMTestHandler.waitForMessage(SUPP_SERVICE_FAILED);
+ assertNotNull("Message Time Out", msg);
+ assertFalse("IncallMmiCallWaiting: command should not work on holding call", msg == null);
+
+ // Simulate entering "12" followed by SEND: release the call with
+ // gsm index equals to 2.
+ mGSMPhone.handleInCallMmiCommands("12");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 1 followed by SEND: release all active calls
+ // (if any exist) and accepts the other (held or waiting) call.
+ mGSMPhone.handleInCallMmiCommands("1");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("16505550100",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+
+ // Simulate entering "11" followed by SEND: release the call with
+ // gsm index equals to 1.
+ mGSMPhone.handleInCallMmiCommands("11");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ public void testIncallMmiCallHold() throws Exception {
+ Message msg;
+
+ // establish an active call
+ mGSMPhone.dial("13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // establish a ringing (WAITING) call
+
+ mRadioControl.triggerRing("18005551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // simulate entering 2 followed by SEND: place all active calls
+ // (if any exist) on hold and accepts the other (held or waiting)
+ // call
+
+ mGSMPhone.handleInCallMmiCommands("2");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getState() == Call.State.WAITING);
+
+
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("13125551212",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());
+
+ // swap the active and holding calls
+ mGSMPhone.handleInCallMmiCommands("2");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_PHONE_STATE_CHANGED);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("13125551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());
+
+ // merge the calls
+ mGSMPhone.conference();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ assertEquals(2, mGSMPhone.getForegroundCall().getConnections().size());
+
+ // at this point, we have an active conference call, with
+ // call(1) = 13125551212 and call(2) = 18005551212
+
+ // Simulate entering "23" followed by SEND: places all active call
+ // on hold except call 3. This should fail and a supplementary service
+ // failed notification should be received.
+
+ mGSMPhone.handleInCallMmiCommands("23");
+
+ msg = mGSMTestHandler.waitForMessage(SUPP_SERVICE_FAILED);
+ assertNotNull("Message Time Out", msg);
+ assertFalse("IncallMmiCallHold: separate should have failed!", msg == null);
+
+ // Simulate entering "21" followed by SEND: places all active call
+ // on hold except call 1.
+ mGSMPhone.handleInCallMmiCommands("21");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("13125551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());
+ }
+
+ public void testIncallMmiMultipartyServices() throws Exception {
+ // establish an active call
+ mGSMPhone.dial("13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // dial another call
+ mGSMPhone.dial("18005551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ mGSMPhone.handleInCallMmiCommands("3");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals("13125551212",
+ mGSMPhone.getForegroundCall().getConnections().get(1).getAddress());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ public void testCallIndex() throws Exception {
+ Message msg;
+
+ // establish the first call
+ mGSMPhone.dial("16505550100");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ String baseNumber = "1650555010";
+
+ for (int i = 1; i < 6; i++) {
+ String number = baseNumber + i;
+
+ mGSMPhone.dial(number);
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ if (mGSMPhone.getBackgroundCall().getConnections().size() >= 5) {
+ break;
+ }
+
+ mGSMPhone.conference();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("16505550105",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // create an incoming call, this call should have the call index
+ // of 7
+ mRadioControl.triggerRing("18005551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // hangup the background call and accept the ringing call
+ mGSMPhone.getBackgroundCall().hangup();
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getState() != Call.State.IDLE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("16505550105",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());
+
+ mGSMPhone.handleInCallMmiCommands("17");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("16505550105",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).
+ getAddress());
+
+ mGSMPhone.handleInCallMmiCommands("1");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ mGSMPhone.handleInCallMmiCommands("16");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ public void testPostDialSequences() throws Exception {
+ Message msg;
+ AsyncResult ar;
+ Connection cn;
+
+ mGSMPhone.dial("+13125551212,1234;5N8xx");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(',', msg.arg1);
+ assertEquals("1234;5N8", cn.getRemainingPostDialString());
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('1', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('2', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('3', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('4', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(';', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.WAIT, cn.getPostDialState());
+ assertEquals(Connection.PostDialState.WAIT, ar.userObj);
+ cn.proceedAfterWaitChar();
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('5', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertEquals('N', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.WILD, cn.getPostDialState());
+ assertEquals(Connection.PostDialState.WILD, ar.userObj);
+ cn.proceedAfterWildChar(",6;7");
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(',', msg.arg1);
+ assertEquals("6;78", cn.getRemainingPostDialString());
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('6', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(';', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.WAIT, cn.getPostDialState());
+ assertEquals(Connection.PostDialState.WAIT, ar.userObj);
+ cn.proceedAfterWaitChar();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('7', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('8', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+ // Bogus chars at end should be ignored
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(0, msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.COMPLETE,
+ cn.getPostDialState());
+ assertEquals(Connection.PostDialState.COMPLETE, ar.userObj);
+ }
+
+ public void testPostDialCancel() throws Exception {
+ Message msg;
+ AsyncResult ar;
+ Connection cn;
+
+ mGSMPhone.dial("+13125551212,N");
+ mRadioControl.progressConnectingToActive();
+
+ mRadioControl.progressConnectingToActive();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(',', msg.arg1);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertEquals('N', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.WILD, cn.getPostDialState());
+ cn.cancelPostDial();
+
+ assertEquals(Connection.PostDialState.CANCELLED, cn.getPostDialState());
+ }
+
+ public void testOutgoingCallFail() throws Exception {
+ Message msg;
+ /*
+ * normal clearing
+ */
+
+ mRadioControl.setNextCallFailCause(CallFailCause.NORMAL_CLEARING);
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ Connection cn = mGSMPhone.dial("+13125551212");
+
+ mRadioControl.progressConnectingCallState();
+
+ // I'm just progressing the call state to
+ // ensure getCurrentCalls() gets processed...
+ // Normally these failure conditions would happen in DIALING
+ // not ALERTING
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (cn.getState() == Call.State.DIALING);
+
+
+ mRadioControl.triggerHangupAll();
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Connection.DisconnectCause.NORMAL, cn.getDisconnectCause());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ /*
+ * busy
+ */
+
+ mRadioControl.setNextCallFailCause(CallFailCause.USER_BUSY);
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ cn = mGSMPhone.dial("+13125551212");
+
+ mRadioControl.progressConnectingCallState();
+
+ // I'm just progressing the call state to
+ // ensure getCurrentCalls() gets processed...
+ // Normally these failure conditions would happen in DIALING
+ // not ALERTING
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (cn.getState() == Call.State.DIALING);
+
+
+ mRadioControl.triggerHangupAll();
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Connection.DisconnectCause.BUSY, cn.getDisconnectCause());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ /*
+ * congestion
+ */
+
+ mRadioControl.setNextCallFailCause(CallFailCause.NO_CIRCUIT_AVAIL);
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ cn = mGSMPhone.dial("+13125551212");
+
+ mRadioControl.progressConnectingCallState();
+
+ // I'm just progressing the call state to
+ // ensure getCurrentCalls() gets processed...
+ // Normally these failure conditions would happen in DIALING
+ // not ALERTING
+ do {
+ msg = mGSMTestHandler.waitForMessage(ANY_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+ } while (cn.getState() == Call.State.DIALING);
+
+
+ mRadioControl.triggerHangupAll();
+
+ // Unlike the while loops above, this one waits
+ // for a "phone state changed" message back to "idle"
+ do {
+ msg = mGSMTestHandler.waitForMessage(ANY_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+ } while (!(msg.what == EVENT_PHONE_STATE_CHANGED
+ && mGSMPhone.getState() == Phone.State.IDLE));
+
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Connection.DisconnectCause.CONGESTION, cn.getDisconnectCause());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+ }
+
+ public void testSSNotification() throws Exception {
+ // MO
+ runTest(0, SuppServiceNotification.MO_CODE_UNCONDITIONAL_CF_ACTIVE);
+ runTest(0, SuppServiceNotification.MO_CODE_CALL_IS_WAITING);
+ runTest(0, SuppServiceNotification.MO_CODE_CALL_DEFLECTED);
+
+ // MT
+ runTest(1, SuppServiceNotification.MT_CODE_FORWARDED_CALL);
+ runTest(1, SuppServiceNotification.MT_CODE_CALL_CONNECTED_ECT);
+ runTest(1, SuppServiceNotification.MT_CODE_ADDITIONAL_CALL_FORWARDED);
+ }
+
+ private void runTest(int type, int code) {
+ Message msg;
+
+ mRadioControl.triggerSsn(type, code);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_SSN);
+ assertNotNull("Message Time Out", msg);
+ AsyncResult ar = (AsyncResult) msg.obj;
+
+ assertNull(ar.exception);
+
+ SuppServiceNotification notification =
+ (SuppServiceNotification) ar.result;
+
+ assertEquals(type, notification.notificationType);
+ assertEquals(code, notification.code);
+ }
+
+ public void testUssd() throws Exception {
+ // Quick hack to work around a race condition in this test:
+ // We may initiate a USSD MMI before GSMPhone receives its initial
+ // GSMTestHandler.EVENT_RADIO_OFF_OR_NOT_AVAILABLE event. When the phone sees this
+ // event, it will cancel the just issued USSD MMI, which we don't
+ // want. So sleep a little first.
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {
+ // do nothing
+ }
+
+ verifyNormal();
+ verifyCancel();
+ varifyNetworkInitiated();
+ }
+
+ private void varifyNetworkInitiated() {
+ Message msg;
+ AsyncResult ar;
+ MmiCode mmi;
+
+ // Receive an incoming NOTIFY
+ mRadioControl.triggerIncomingUssd("0", "NOTIFY message");
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertFalse(mmi.isUssdRequest());
+
+ // Receive a REQUEST and send response
+ mRadioControl.triggerIncomingUssd("1", "REQUEST Message");
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertTrue(mmi.isUssdRequest());
+
+ mGSMPhone.sendUssdResponse("## TEST: TEST_GSMPhone responding...");
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ GsmMmiCode gsmMmi = (GsmMmiCode) mmi;
+ assertTrue(gsmMmi.isPendingUSSD());
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertNull(ar.exception);
+ assertFalse(mmi.isUssdRequest());
+
+ // Receive a REQUEST and cancel
+ mRadioControl.triggerIncomingUssd("1", "REQUEST Message");
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertTrue(mmi.isUssdRequest());
+
+ mmi.cancel();
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertNull(ar.exception);
+ assertEquals(MmiCode.State.CANCELLED, mmi.getState());
+
+ List mmiList = mGSMPhone.getPendingMmiCodes();
+ assertEquals(0, mmiList.size());
+ }
+
+ private void verifyNormal() throws CallStateException {
+ Message msg;
+ AsyncResult ar;
+ MmiCode mmi;
+
+ mGSMPhone.dial("#646#");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
+ assertNotNull("Message Time Out", msg);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+ assertEquals(MmiCode.State.COMPLETE, mmi.getState());
+ }
+
+
+ private void verifyCancel() throws CallStateException {
+ /**
+ * This case makes an assumption that dial() will add the USSD
+ * to the "pending MMI codes" list before it returns. This seems
+ * like reasonable semantics. It also assumes that the USSD
+ * request in question won't complete until we get back to the
+ * event loop, thus cancel() is safe.
+ */
+ Message msg;
+
+ mGSMPhone.dial("#646#");
+
+ List<? extends MmiCode> pendingMmis = mGSMPhone.getPendingMmiCodes();
+
+ assertEquals(1, pendingMmis.size());
+
+ MmiCode mmi = pendingMmis.get(0);
+ assertTrue(mmi.isCancelable());
+ mmi.cancel();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
+ assertNotNull("Message Time Out", msg);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+
+ AsyncResult ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertEquals(MmiCode.State.CANCELLED, mmi.getState());
+ }
+
+ public void testRilHooks() throws Exception {
+ //
+ // These test cases all assume the RIL OEM hooks
+ // just echo back their input
+ //
+
+ Message msg;
+ AsyncResult ar;
+
+ // null byte array
+
+ mGSMPhone.invokeOemRilRequestRaw(null, mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertNull(ar.result);
+ assertNull(ar.exception);
+
+ // empty byte array
+
+ mGSMPhone.invokeOemRilRequestRaw(new byte[0], mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertEquals(0, ((byte[]) (ar.result)).length);
+ assertNull(ar.exception);
+
+ // byte array with data
+
+ mGSMPhone.invokeOemRilRequestRaw("Hello".getBytes("utf-8"),
+ mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertEquals("Hello", new String(((byte[]) (ar.result)), "utf-8"));
+ assertNull(ar.exception);
+
+ // null strings
+
+ mGSMPhone.invokeOemRilRequestStrings(null, mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertNull(ar.result);
+ assertNull(ar.exception);
+
+ // empty byte array
+
+ mGSMPhone.invokeOemRilRequestStrings(new String[0],
+ mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertEquals(0, ((String[]) (ar.result)).length);
+ assertNull(ar.exception);
+
+ // Strings with data
+
+ String s[] = new String[1];
+
+ s[0] = "Hello";
+
+ mGSMPhone.invokeOemRilRequestStrings(s, mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertEquals("Hello", ((String[]) (ar.result))[0]);
+ assertEquals(1, ((String[]) (ar.result)).length);
+ assertNull(ar.exception);
+ }
+
+ public void testMmi() throws Exception {
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ // "valid" MMI sequences
+ runValidMmi("*#67#", false);
+ runValidMmi("##43*11#", false);
+ runValidMmi("#33*1234*11#", false);
+ runValidMmi("*21*6505551234**5#", false);
+ runValidMmi("**03**1234*4321*4321#", false);
+ // pound string
+ runValidMmi("5308234092307540923#", true);
+ // short code
+ runValidMmi("22", true);
+ // as part of call setup
+ runValidMmiWithConnect("*31#6505551234");
+
+ // invalid MMI sequences
+ runNotMmi("6505551234");
+ runNotMmi("1234#*12#34566654");
+ runNotMmi("*#*#12#*");
+ }
+
+ private void runValidMmi(String dialString, boolean cancelable) throws CallStateException {
+ Connection c = mGSMPhone.dial(dialString);
+ assertNull(c);
+ Message msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
+ assertNotNull("Message Time Out", msg);
+ // Should not be cancelable.
+ AsyncResult ar = (AsyncResult) msg.obj;
+ MmiCode mmi = (MmiCode) ar.result;
+ assertEquals(cancelable, mmi.isCancelable());
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ }
+
+ private void runValidMmiWithConnect(String dialString) throws CallStateException {
+ mRadioControl.pauseResponses();
+
+ Connection c = mGSMPhone.dial(dialString);
+ assertNotNull(c);
+
+ hangup(c);
+ }
+
+ private void hangup(Connection cn) throws CallStateException {
+ cn.hangup();
+
+ mRadioControl.resumeResponses();
+ assertNotNull(mGSMTestHandler.waitForMessage(EVENT_DISCONNECT));
+
+ }
+
+ private void runNotMmi(String dialString) throws CallStateException {
+ mRadioControl.pauseResponses();
+
+ Connection c = mGSMPhone.dial(dialString);
+ assertNotNull(c);
+
+ hangup(c);
+ }
+}
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMTestHandler.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMTestHandler.java
new file mode 100644
index 0000000..fb8a5d9
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/GSMTestHandler.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.content.Context;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.internal.telephony.gsm.GSMPhone;
+import com.android.internal.telephony.test.SimulatedCommands;
+import com.android.internal.telephony.TestPhoneNotifier;
+
+/**
+ * This class creates a HandlerThread which waits for the various messages.
+ */
+public class GSMTestHandler extends HandlerThread implements Handler.Callback {
+
+ private Handler mHandler;
+ private Message mCurrentMessage;
+
+ private Boolean mMsgConsumed;
+ private SimulatedCommands sc;
+ private GSMPhone mGSMPhone;
+ private Context mContext;
+
+ private static final int FAIL_TIMEOUT_MILLIS = 5 * 1000;
+
+ public GSMTestHandler(Context context) {
+ super("GSMPhoneTest");
+ mMsgConsumed = false;
+ mContext = context;
+ }
+
+ @Override
+ protected void onLooperPrepared() {
+ sc = new SimulatedCommands();
+ mGSMPhone = new GSMPhone(mContext, sc, new TestPhoneNotifier(), true);
+ mHandler = new Handler(getLooper(), this);
+ synchronized (this) {
+ notifyAll();
+ }
+ }
+
+ public boolean handleMessage(Message msg) {
+ synchronized (this) {
+ mCurrentMessage = msg;
+ this.notifyAll();
+ while(!mMsgConsumed) {
+ try {
+ this.wait();
+ } catch (InterruptedException e) {}
+ }
+ mMsgConsumed = false;
+ }
+ return true;
+ }
+
+
+ public void cleanup() {
+ Looper looper = getLooper();
+ if (looper != null) looper.quit();
+ mHandler = null;
+ }
+
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ public SimulatedCommands getSimulatedCommands() {
+ return sc;
+ }
+
+ public GSMPhone getGSMPhone() {
+ return mGSMPhone;
+ }
+
+ public Message waitForMessage(int code) {
+ Message msg;
+ while(true) {
+ msg = null;
+ synchronized (this) {
+ try {
+ this.wait(FAIL_TIMEOUT_MILLIS);
+ } catch (InterruptedException e) {
+ }
+
+ // Check if timeout has occurred.
+ if (mCurrentMessage != null) {
+ // Consume the message
+ msg = Message.obtain();
+ msg.copyFrom(mCurrentMessage);
+ mCurrentMessage = null;
+ mMsgConsumed = true;
+ this.notifyAll();
+ }
+ }
+ if (msg == null || code == GSMPhoneTest.ANY_MESSAGE || msg.what == code) return msg;
+ }
+ }
+}
diff --git a/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java b/telephony/tests/telephonytests/src/com/android/telephonytest/unit/CallerInfoUnitTest.java
index 0f24f15..0f24f15 100644
--- a/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java
+++ b/telephony/tests/telephonytests/src/com/android/telephonytest/unit/CallerInfoUnitTest.java
diff --git a/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java b/telephony/tests/telephonytests/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java
index 2d3c548..2d3c548 100644
--- a/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java
+++ b/telephony/tests/telephonytests/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java