Merge "Add support for downgrade to audio when data limit is reached." into nyc-mr1-dev
diff --git a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
index 2cc4336..993ac6d 100755
--- a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
@@ -298,9 +298,10 @@
//we should have failed in !canDial() above before we get here
throw new CallStateException("cannot dial in current state");
}
-
+ boolean isEmergencyCall = PhoneNumberUtils.isLocalEmergencyNumber(mPhone.getContext(),
+ dialString);
mPendingMO = new GsmCdmaConnection(mPhone, checkForTestEmergencyNumber(dialString),
- this, mForegroundCall);
+ this, mForegroundCall, isEmergencyCall);
mHangupPendingMO = false;
if ( mPendingMO.getAddress() == null || mPendingMO.getAddress().length() == 0
@@ -411,7 +412,7 @@
}
mPendingMO = new GsmCdmaConnection(mPhone, checkForTestEmergencyNumber(dialString),
- this, mForegroundCall);
+ this, mForegroundCall, isEmergencyCall);
mHangupPendingMO = false;
if ( mPendingMO.getAddress() == null || mPendingMO.getAddress().length() == 0
@@ -454,12 +455,13 @@
//CDMA
private Connection dialThreeWay(String dialString) {
if (!mForegroundCall.isIdle()) {
- // Check data call
+ // Check data call and possibly set mIsInEmergencyCall
disableDataCallInEmergencyCall(dialString);
// Attach the new connection to foregroundCall
mPendingMO = new GsmCdmaConnection(mPhone,
- checkForTestEmergencyNumber(dialString), this, mForegroundCall);
+ checkForTestEmergencyNumber(dialString), this, mForegroundCall,
+ mIsInEmergencyCall);
// Some network need a empty flash before sending the normal one
m3WayCallFlashDelay = mPhone.getContext().getResources()
.getInteger(com.android.internal.R.integer.config_cdma_3waycall_flash_delay);
diff --git a/src/java/com/android/internal/telephony/GsmCdmaConnection.java b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
index a195bd1..1530ada 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaConnection.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
@@ -71,6 +71,8 @@
private PowerManager.WakeLock mPartialWakeLock;
+ private boolean mIsEmergencyCall = false;
+
// The cached delay to be used between DTMF tones fetched from carrier config.
private int mDtmfToneDelay = 0;
@@ -116,7 +118,7 @@
//***** Constructors
- /** This is probably an MT call that we first saw in a CLCC response */
+ /** This is probably an MT call that we first saw in a CLCC response or a hand over. */
public GsmCdmaConnection (GsmCdmaPhone phone, DriverCall dc, GsmCdmaCallTracker ct, int index) {
super(phone.getPhoneType());
createWakeLock(phone.getContext());
@@ -126,7 +128,7 @@
mHandler = new MyHandler(mOwner.getLooper());
mAddress = dc.number;
-
+ mIsEmergencyCall = PhoneNumberUtils.isLocalEmergencyNumber(phone.getContext(), mAddress);
mIsIncoming = dc.isMT;
mCreateTime = System.currentTimeMillis();
mCnapName = dc.name;
@@ -144,7 +146,7 @@
/** This is an MO call, created when dialing */
public GsmCdmaConnection (GsmCdmaPhone phone, String dialString, GsmCdmaCallTracker ct,
- GsmCdmaCall parent) {
+ GsmCdmaCall parent, boolean isEmergencyCall) {
super(phone.getPhoneType());
createWakeLock(phone.getContext());
acquireWakeLock();
@@ -155,13 +157,16 @@
if (isPhoneTypeGsm()) {
mDialString = dialString;
} else {
- Rlog.d(LOG_TAG, "[GsmCdmaConn] GsmCdmaConnection: dialString=" + maskDialString(dialString));
+ Rlog.d(LOG_TAG, "[GsmCdmaConn] GsmCdmaConnection: dialString=" +
+ maskDialString(dialString));
dialString = formatDialString(dialString);
Rlog.d(LOG_TAG,
- "[GsmCdmaConn] GsmCdmaConnection:formated dialString=" + maskDialString(dialString));
+ "[GsmCdmaConn] GsmCdmaConnection:formated dialString=" +
+ maskDialString(dialString));
}
mAddress = PhoneNumberUtils.extractNetworkPortionAlt(dialString);
+ mIsEmergencyCall = isEmergencyCall;
mPostDialString = PhoneNumberUtils.extractPostDialPortion(dialString);
mIndex = -1;
@@ -491,45 +496,49 @@
int serviceState = phone.getServiceState().getState();
UiccCardApplication cardApp = phone.getUiccCardApplication();
AppState uiccAppState = (cardApp != null) ? cardApp.getState() :
- AppState.APPSTATE_UNKNOWN;
+ AppState.APPSTATE_UNKNOWN;
if (serviceState == ServiceState.STATE_POWER_OFF) {
return DisconnectCause.POWER_OFF;
- } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
- || serviceState == ServiceState.STATE_EMERGENCY_ONLY ) {
- return DisconnectCause.OUT_OF_SERVICE;
- } else {
- if (isPhoneTypeGsm()) {
- if (uiccAppState != AppState.APPSTATE_READY) {
+ }
+ if (!mIsEmergencyCall) {
+ // Only send OUT_OF_SERVICE if it is not an emergency call. We can still
+ // technically be in STATE_OUT_OF_SERVICE or STATE_EMERGENCY_ONLY during
+ // an emergency call and when it ends, we do not want to mistakenly generate
+ // an OUT_OF_SERVICE disconnect cause during normal call ending.
+ if ((serviceState == ServiceState.STATE_OUT_OF_SERVICE
+ || serviceState == ServiceState.STATE_EMERGENCY_ONLY)) {
+ return DisconnectCause.OUT_OF_SERVICE;
+ }
+ // If we are placing an emergency call and the SIM is currently PIN/PUK
+ // locked the AppState will always not be equal to APPSTATE_READY.
+ if (uiccAppState != AppState.APPSTATE_READY) {
+ if (isPhoneTypeGsm()) {
return DisconnectCause.ICC_ERROR;
- } else if (causeCode == CallFailCause.ERROR_UNSPECIFIED) {
- if (phone.mSST.mRestrictedState.isCsRestricted()) {
- return DisconnectCause.CS_RESTRICTED;
- } else if (phone.mSST.mRestrictedState.isCsEmergencyRestricted()) {
- return DisconnectCause.CS_RESTRICTED_EMERGENCY;
- } else if (phone.mSST.mRestrictedState.isCsNormalRestricted()) {
- return DisconnectCause.CS_RESTRICTED_NORMAL;
- } else {
- return DisconnectCause.ERROR_UNSPECIFIED;
+ } else { // CDMA
+ if (phone.mCdmaSubscriptionSource ==
+ CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM) {
+ return DisconnectCause.ICC_ERROR;
}
- } else if (causeCode == CallFailCause.NORMAL_CLEARING) {
- return DisconnectCause.NORMAL;
- } else {
- // If nothing else matches, report unknown call drop reason
- // to app, not NORMAL call end.
- return DisconnectCause.ERROR_UNSPECIFIED;
- }
- } else {
- if (phone.mCdmaSubscriptionSource ==
- CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM
- && uiccAppState != AppState.APPSTATE_READY) {
- return DisconnectCause.ICC_ERROR;
- } else if (causeCode==CallFailCause.NORMAL_CLEARING) {
- return DisconnectCause.NORMAL;
- } else {
- return DisconnectCause.ERROR_UNSPECIFIED;
}
}
}
+ if (isPhoneTypeGsm()) {
+ if (causeCode == CallFailCause.ERROR_UNSPECIFIED) {
+ if (phone.mSST.mRestrictedState.isCsRestricted()) {
+ return DisconnectCause.CS_RESTRICTED;
+ } else if (phone.mSST.mRestrictedState.isCsEmergencyRestricted()) {
+ return DisconnectCause.CS_RESTRICTED_EMERGENCY;
+ } else if (phone.mSST.mRestrictedState.isCsNormalRestricted()) {
+ return DisconnectCause.CS_RESTRICTED_NORMAL;
+ }
+ }
+ }
+ if (causeCode == CallFailCause.NORMAL_CLEARING) {
+ return DisconnectCause.NORMAL;
+ }
+ // If nothing else matches, report unknown call drop reason
+ // to app, not NORMAL call end.
+ return DisconnectCause.ERROR_UNSPECIFIED;
}
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 0919af1..834548b 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -409,6 +409,9 @@
networkType, NETWORK_TYPE, TelephonyManager.getNetworkTypeName(networkType));
mNetworkInfo.setRoaming(ss.getDataRoaming());
mNetworkInfo.setIsAvailable(true);
+ // The network should be by default metered until we find it has NET_CAPABILITY_NOT_METERED
+ // capability.
+ mNetworkInfo.setMetered(true);
addState(mDefaultState);
addState(mInactiveState, mDefaultState);
@@ -947,6 +950,10 @@
if (!mApnSetting.isMetered(mPhone.getContext(), mPhone.getSubId(),
mPhone.getServiceState().getDataRoaming())) {
result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ mNetworkInfo.setMetered(false);
+ } else {
+ result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ mNetworkInfo.setMetered(true);
}
result.maybeMarkCapabilitiesRestricted();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
index 90d2687..df9a7ab 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
@@ -57,7 +57,8 @@
@Test @SmallTest
public void testFormatDialString(){
connection = new GsmCdmaConnection(mPhone, String.format(
- "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null);
+ "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null,
+ false /*isEmergencyCall*/);
/* case 1: If PAUSE/WAIT sequence at the end, ignore them */
String formattedDialStr = connection.formatDialString(
String.format("+1 (700).555-41NN1234%c", PhoneNumberUtils.PAUSE));
@@ -72,7 +73,8 @@
@Test @SmallTest
public void testSanityGSM() {
connection = new GsmCdmaConnection(mPhone, String.format(
- "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null);
+ "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null,
+ false /*isEmergencyCall*/);
logd("Testing initial state of GsmCdmaConnection");
assertEquals(GsmCdmaCall.State.IDLE, connection.getState());
assertEquals(Connection.PostDialState.NOT_STARTED, connection.getPostDialState());
@@ -89,7 +91,8 @@
public void testSanityCDMA() {
doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mPhone).getPhoneType();
connection = new GsmCdmaConnection(mPhone, String.format(
- "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null);
+ "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null,
+ false /*isEmergencyCall*/);
logd("Testing initial state of GsmCdmaConnection");
assertEquals(GsmCdmaCall.State.IDLE, connection.getState());
assertEquals(Connection.PostDialState.NOT_STARTED, connection.getPostDialState());
@@ -106,7 +109,8 @@
@Test @SmallTest
public void testConnectionStateUpdate() {
connection = new GsmCdmaConnection(mPhone, String.format(
- "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null);
+ "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null,
+ false /*isEmergencyCall*/);
logd("Update the connection state from idle to active");
mDC.state = DriverCall.State.ACTIVE;
connection.update(mDC);
@@ -123,7 +127,8 @@
public void testCDMAPostDialPause() {
doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mPhone).getPhoneType();
connection = new GsmCdmaConnection(mPhone, String.format(
- "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null);
+ "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null,
+ false /*isEmergencyCall*/);
logd("Mock connection state from alerting to active ");
mDC.state = DriverCall.State.ALERTING;
connection.update(mDC);
@@ -139,7 +144,8 @@
@Test @MediumTest
public void testGSMPostDialPause() {
connection = new GsmCdmaConnection(mPhone, String.format(
- "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null);
+ "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null,
+ false /*isEmergencyCall*/);
logd("Mock connection state from alerting to active ");
mDC.state = DriverCall.State.ALERTING;
connection.update(mDC);
@@ -157,7 +163,8 @@
public void testPostDialWait() {
doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mPhone).getPhoneType();
connection = new GsmCdmaConnection(mPhone,
- String.format("+1 (700).555-41NN%c1234", PhoneNumberUtils.WAIT),mCT,null);
+ String.format("+1 (700).555-41NN%c1234", PhoneNumberUtils.WAIT),mCT,null,
+ false /*isEmergencyCall*/);
logd("Mock connection state transition from alerting to active ");
mDC.state = DriverCall.State.ALERTING;
connection.update(mDC);
@@ -173,7 +180,8 @@
@Test @SmallTest
public void testHangUpConnection() {
connection = new GsmCdmaConnection(mPhone, String.format(
- "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null);
+ "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null,
+ false /*isEmergencyCall*/);
mDC.state = DriverCall.State.ACTIVE;
connection.update(mDC);
logd("Hangup the connection locally");
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
index 4bccdd9..0f2192b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
@@ -16,10 +16,13 @@
package com.android.internal.telephony.dataconnection;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
+import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
import android.test.suitebuilder.annotation.SmallTest;
@@ -32,15 +35,20 @@
import com.android.internal.util.IState;
import com.android.internal.util.StateMachine;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
@@ -246,4 +254,47 @@
AsyncResult ar = new AsyncResult(null, response, null);
assertEquals(RetryManager.NO_RETRY, getSuggestedRetryDelay(ar));
}
+
+ private NetworkInfo getNetworkInfo() throws Exception {
+ Field f = DataConnection.class.getDeclaredField("mNetworkInfo");
+ f.setAccessible(true);
+ return (NetworkInfo) f.get(mDc);
+ }
+
+ private NetworkCapabilities getCopyNetworkCapabilities() throws Exception {
+ Method method = DataConnection.class.getDeclaredMethod("getCopyNetworkCapabilities");
+ method.setAccessible(true);
+ return (NetworkCapabilities) method.invoke(mDc);
+ }
+
+ @Test
+ @SmallTest
+ public void testMeteredCapability() throws Exception {
+
+ mContextFixture.getCarrierConfigBundle().
+ putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
+ new String[] {"default"});
+
+ testConnectEvent();
+
+ assertTrue(getNetworkInfo().isMetered());
+ assertFalse(getCopyNetworkCapabilities().
+ hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
+ }
+
+ @Test
+ @SmallTest
+ public void testNonMeteredCapability() throws Exception {
+
+ doReturn(1).when(mPhone).getSubId();
+ mContextFixture.getCarrierConfigBundle().
+ putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
+ new String[] {"mms"});
+
+ testConnectEvent();
+
+ assertFalse(getNetworkInfo().isMetered());
+ assertTrue(getCopyNetworkCapabilities().
+ hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
+ }
}
\ No newline at end of file