aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/java/com/android/internal/telephony/PhoneSwitcher.java91
-rw-r--r--src/java/com/android/internal/telephony/dataconnection/DataConnection.java28
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java23
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java30
4 files changed, 109 insertions, 63 deletions
diff --git a/src/java/com/android/internal/telephony/PhoneSwitcher.java b/src/java/com/android/internal/telephony/PhoneSwitcher.java
index 7bd24ee80..638da48ec 100644
--- a/src/java/com/android/internal/telephony/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/PhoneSwitcher.java
@@ -17,8 +17,6 @@
package com.android.internal.telephony;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.telephony.PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE;
-import static android.telephony.PhoneStateListener.LISTEN_PRECISE_CALL_STATE;
import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
import static android.telephony.SubscriptionManager.INVALID_PHONE_INDEX;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -50,7 +48,6 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.PhoneCapability;
import android.telephony.PhoneStateListener;
-import android.telephony.PreciseCallState;
import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -223,15 +220,17 @@ public class PhoneSwitcher extends Handler {
// mEmergencyOverride, start the countdown to remove the override using the message
// EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE. The only exception to this is if the device moves to
// ECBM, which is detected by EVENT_EMERGENCY_TOGGLE.
- private static final int EVENT_PHONE_IN_CALL_CHANGED = 109;
+ @VisibleForTesting
+ public static final int EVENT_PRECISE_CALL_STATE_CHANGED = 109;
private static final int EVENT_NETWORK_VALIDATION_DONE = 110;
private static final int EVENT_REMOVE_DEFAULT_NETWORK_CHANGE_CALLBACK = 111;
private static final int EVENT_MODEM_COMMAND_DONE = 112;
private static final int EVENT_MODEM_COMMAND_RETRY = 113;
- private static final int EVENT_DATA_ENABLED_CHANGED = 114;
+ @VisibleForTesting
+ public static final int EVENT_DATA_ENABLED_CHANGED = 114;
// An emergency call is about to be originated and requires the DDS to be overridden.
- // Uses EVENT_PHONE_IN_CALL_CHANGED message to start countdown to finish override defined in
- // mEmergencyOverride. If EVENT_PHONE_IN_CALL_CHANGED does not come in
+ // Uses EVENT_PRECISE_CALL_STATE_CHANGED message to start countdown to finish override defined
+ // in mEmergencyOverride. If EVENT_PRECISE_CALL_STATE_CHANGED does not come in
// DEFAULT_DATA_OVERRIDE_TIMEOUT_MS milliseconds, then the override will be removed.
private static final int EVENT_OVERRIDE_DDS_FOR_EMERGENCY = 115;
// If it exists, remove the current mEmergencyOverride DDS override.
@@ -315,6 +314,22 @@ public class PhoneSwitcher extends Handler {
mValidator = CellularNetworkValidator.getInstance();
}
+ private boolean isPhoneInVoiceCallChanged() {
+ int oldPhoneIdInVoiceCall = mPhoneIdInVoiceCall;
+ // If there's no active call, the value will become INVALID_PHONE_INDEX
+ // and internet data will be switched back to system selected or user selected
+ // subscription.
+ mPhoneIdInVoiceCall = SubscriptionManager.INVALID_PHONE_INDEX;
+ for (Phone phone : mPhones) {
+ if (isCallActive(phone) || isCallActive(phone.getImsPhone())) {
+ mPhoneIdInVoiceCall = phone.getPhoneId();
+ break;
+ }
+ }
+
+ return (mPhoneIdInVoiceCall != oldPhoneIdInVoiceCall);
+ }
+
@VisibleForTesting
public PhoneSwitcher(int maxActivePhones, int numPhones, Context context,
SubscriptionController subscriptionController, Looper looper, ITelephonyRegistry tr,
@@ -335,58 +350,25 @@ public class PhoneSwitcher extends Handler {
public void onPhoneCapabilityChanged(PhoneCapability capability) {
onPhoneCapabilityChangedInternal(capability);
}
-
- @Override
- public void onPreciseCallStateChanged(PreciseCallState callState) {
- int oldPhoneIdInVoiceCall = mPhoneIdInVoiceCall;
- // If there's no active call, the value will become INVALID_PHONE_INDEX
- // and internet data will be switched back to system selected or user selected
- // subscription.
- mPhoneIdInVoiceCall = SubscriptionManager.INVALID_PHONE_INDEX;
- for (Phone phone : mPhones) {
- if (isCallActive(phone) || isCallActive(phone.getImsPhone())) {
- mPhoneIdInVoiceCall = phone.getPhoneId();
- break;
- }
- }
-
- if (mPhoneIdInVoiceCall != oldPhoneIdInVoiceCall) {
- log("mPhoneIdInVoiceCall changed from" + oldPhoneIdInVoiceCall
- + " to " + mPhoneIdInVoiceCall);
-
- // Switches and listens to the updated voice phone.
- Phone dataPhone = findPhoneById(mPhoneIdInVoiceCall);
- if (dataPhone != null && dataPhone.getDataEnabledSettings() != null) {
- dataPhone.getDataEnabledSettings()
- .registerForDataEnabledChanged(getInstance(),
- EVENT_DATA_ENABLED_CHANGED, null);
- }
-
- Phone oldDataPhone = findPhoneById(oldPhoneIdInVoiceCall);
- if (oldDataPhone != null && oldDataPhone.getDataEnabledSettings() != null) {
- oldDataPhone.getDataEnabledSettings()
- .unregisterForDataEnabledChanged(getInstance());
- }
-
- Message msg = PhoneSwitcher.this.obtainMessage(EVENT_PHONE_IN_CALL_CHANGED);
- msg.sendToTarget();
- }
- }
};
mValidator = CellularNetworkValidator.getInstance();
- TelephonyManager telephonyManager =
- (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
- telephonyManager.listen(mPhoneStateListener, LISTEN_PHONE_CAPABILITY_CHANGE
- | LISTEN_PRECISE_CALL_STATE);
-
mActivePhoneRegistrants = new RegistrantList();
mPhoneStates = new PhoneState[numPhones];
for (int i = 0; i < numPhones; i++) {
mPhoneStates[i] = new PhoneState();
if (mPhones[i] != null) {
mPhones[i].registerForEmergencyCallToggle(this, EVENT_EMERGENCY_TOGGLE, null);
+ // TODO (b/135566422): combine register for both GsmCdmaPhone and ImsPhone.
+ mPhones[i].registerForPreciseCallStateChanged(
+ this, EVENT_PRECISE_CALL_STATE_CHANGED, null);
+ if (mPhones[i].getImsPhone() != null) {
+ mPhones[i].getImsPhone().registerForPreciseCallStateChanged(
+ this, EVENT_PRECISE_CALL_STATE_CHANGED, null);
+ }
+ mPhones[i].getDataEnabledSettings().registerForDataEnabledChanged(
+ this, EVENT_DATA_ENABLED_CHANGED, null);
}
}
@@ -510,7 +492,10 @@ public class PhoneSwitcher extends Handler {
onEvaluate(REQUESTS_UNCHANGED, "EVENT_RADIO_AVAILABLE");
break;
}
- case EVENT_PHONE_IN_CALL_CHANGED: {
+ case EVENT_PRECISE_CALL_STATE_CHANGED: {
+ // If the phoneId in voice call didn't change, do nothing.
+ if (!isPhoneInVoiceCallChanged()) break;
+
// Only handle this event if we are currently waiting for the emergency call
// associated with the override request to start or end.
if (mEmergencyOverride != null && mEmergencyOverride.mPendingOriginatingCall) {
@@ -529,7 +514,7 @@ public class PhoneSwitcher extends Handler {
}
// fall through
case EVENT_DATA_ENABLED_CHANGED:
- if (onEvaluate(REQUESTS_UNCHANGED, "EVENT_PHONE_IN_CALL_CHANGED")) {
+ if (onEvaluate(REQUESTS_UNCHANGED, "EVENT_PRECISE_CALL_STATE_CHANGED")) {
logDataSwitchEvent(mOpptDataSubId,
TelephonyEvent.EventState.EVENT_STATE_START,
DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL);
@@ -601,8 +586,8 @@ public class PhoneSwitcher extends Handler {
Message msg2 = obtainMessage(EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE);
// Make sure that if we never get an incall indication that we remove the override.
sendMessageDelayed(msg2, DEFAULT_DATA_OVERRIDE_TIMEOUT_MS);
- // Wait for call to end and EVENT_PHONE_IN_CALL_CHANGED to be called, then start
- // timer to remove DDS emergency override.
+ // Wait for call to end and EVENT_PRECISE_CALL_STATE_CHANGED to be called, then
+ // start timer to remove DDS emergency override.
if (!onEvaluate(REQUESTS_UNCHANGED, "emer_override_dds")) {
// Nothing changed as a result of override, so no modem command was sent. Treat
// as success.
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 9d4e39aac..20ccee8c9 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -1131,14 +1131,28 @@ public class DataConnection extends StateMachine {
* @return True if this data connection should only be used for unmetered purposes.
*/
private boolean isUnmeteredUseOnly() {
- // The data connection can only be unmetered used only if all requests' reasons are
- // unmetered.
+ // If this data connection is on IWLAN, then it's unmetered and can be used by everyone.
+ // Should not be for unmetered used only.
+ if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
+ return false;
+ }
+
+ // If data is enabled, this data connection can't be for unmetered used only because
+ // everyone should be able to use it.
+ if (mPhone.getDataEnabledSettings().isDataEnabled()) {
+ return false;
+ }
+
+ // If the device is roaming and data roaming it turned on, then this data connection can't
+ // be for unmetered use only.
+ if (mDct.getDataRoamingEnabled() && mPhone.getServiceState().getDataRoaming()) {
+ return false;
+ }
+
+ // The data connection can only be unmetered used only if all attached APN contexts
+ // attached to this data connection are unmetered.
for (ApnContext apnContext : mApnContexts.keySet()) {
- DataConnectionReasons dataConnectionReasons = new DataConnectionReasons();
- boolean isDataAllowed = mDct.isDataAllowed(apnContext, DcTracker.REQUEST_TYPE_NORMAL,
- dataConnectionReasons);
- if (!isDataAllowed || !dataConnectionReasons.contains(
- DataConnectionReasons.DataAllowedReasonType.UNMETERED_APN)) {
+ if (ApnSettingUtils.isMeteredApnType(apnContext.getApnTypeBitmask(), mPhone)) {
return false;
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java
index 3be7dfd33..b154d3586 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java
@@ -16,6 +16,9 @@
package com.android.internal.telephony;
+import static com.android.internal.telephony.PhoneSwitcher.EVENT_DATA_ENABLED_CHANGED;
+import static com.android.internal.telephony.PhoneSwitcher.EVENT_PRECISE_CALL_STATE_CHANGED;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -565,8 +568,16 @@ public class PhoneSwitcherTest extends TelephonyTest {
setAllPhonesInactive();
// Initialization done.
- // Phone2 has active call. So data switch to it.
+ // Phone2 has active call, but data is turned off. So no data switching should happen.
+ notifyDataEnabled(false);
notifyPhoneAsInCall(mPhone2);
+ verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
+ waitABit();
+ assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
+ assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
+
+ // Phone2 has active call. So data switch to it.
+ notifyDataEnabled(true);
verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
@@ -863,13 +874,19 @@ public class PhoneSwitcherTest extends TelephonyTest {
private void notifyPhoneAsInCall(Phone phone) {
doReturn(mActiveCall).when(phone).getForegroundCall();
- mPhoneSwitcher.mPhoneStateListener.onPreciseCallStateChanged(null);
+ mPhoneSwitcher.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
waitABit();
}
private void notifyPhoneAsInactive(Phone phone) {
doReturn(mInactiveCall).when(phone).getForegroundCall();
- mPhoneSwitcher.mPhoneStateListener.onPreciseCallStateChanged(null);
+ mPhoneSwitcher.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
+ waitABit();
+ }
+
+ private void notifyDataEnabled(boolean dataEnabled) {
+ doReturn(dataEnabled).when(mDataEnabledSettings).isDataEnabled(anyInt());
+ mPhoneSwitcher.sendEmptyMessage(EVENT_DATA_ENABLED_CHANGED);
waitABit();
}
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 b7fe4ca90..601bb653e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
@@ -343,6 +343,12 @@ public class DataConnectionTest extends TelephonyTest {
return (long) method.invoke(mDc, response);
}
+ private boolean isUnmeteredUseOnly() throws Exception {
+ Method method = DataConnection.class.getDeclaredMethod("isUnmeteredUseOnly");
+ method.setAccessible(true);
+ return (boolean) method.invoke(mDc);
+ }
+
private SetupResult setLinkProperties(DataCallResponse response,
LinkProperties linkProperties)
throws Exception {
@@ -902,4 +908,28 @@ public class DataConnectionTest extends TelephonyTest {
public void testStartNattKeepaliveFailCondensed() throws Exception {
checkStartNattKeepaliveFail(true);
}
+
+ @Test
+ @SmallTest
+ public void testIsUnmeteredUseOnly() throws Exception {
+ Field field = DataConnection.class.getDeclaredField("mTransportType");
+ field.setAccessible(true);
+ field.setInt(mDc, AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
+
+ assertFalse(isUnmeteredUseOnly());
+
+ field = DataConnection.class.getDeclaredField("mTransportType");
+ field.setAccessible(true);
+ field.setInt(mDc, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+
+ doReturn(false).when(mDataEnabledSettings).isDataEnabled();
+ doReturn(false).when(mServiceState).getDataRoaming();
+ doReturn(ApnSetting.TYPE_MMS).when(mApnContext).getApnTypeBitmask();
+
+ mContextFixture.getCarrierConfigBundle().putStringArray(
+ CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
+ new String[] { "default" });
+
+ assertTrue(isUnmeteredUseOnly());
+ }
}