Merge "Fixed the aggresive data call setup"
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 53d4cb5..3fd30a9 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -1659,7 +1659,13 @@
// Setting SS Roaming (general)
if (mIsSubscriptionFromRuim) {
- mNewSS.setVoiceRoaming(isRoamingBetweenOperators(mNewSS.getVoiceRoaming(), mNewSS));
+ boolean isRoamingBetweenOperators = isRoamingBetweenOperators(
+ mNewSS.getVoiceRoaming(), mNewSS);
+ if (isRoamingBetweenOperators != mNewSS.getVoiceRoaming()) {
+ log("isRoamingBetweenOperators=" + isRoamingBetweenOperators
+ + ". Override CDMA voice roaming to " + isRoamingBetweenOperators);
+ mNewSS.setVoiceRoaming(isRoamingBetweenOperators);
+ }
}
/**
* For CDMA, voice and data should have the same roaming status.
@@ -1672,15 +1678,25 @@
final boolean isVoiceInService =
(mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE);
if (isVoiceInService) {
- mNewSS.setDataRoaming(mNewSS.getVoiceRoaming());
+ boolean isVoiceRoaming = mNewSS.getVoiceRoaming();
+ if (mNewSS.getDataRoaming() != isVoiceRoaming) {
+ log("Data roaming != Voice roaming. Override data roaming to "
+ + isVoiceRoaming);
+ mNewSS.setDataRoaming(isVoiceRoaming);
+ }
} else {
/**
* As per VoiceRegStateResult from radio types.hal the TSB58
* Roaming Indicator shall be sent if device is registered
* on a CDMA or EVDO system.
*/
- mNewSS.setDataRoaming(
- !isRoamIndForHomeSystem(Integer.toString(mRoamingIndicator)));
+ boolean isRoamIndForHomeSystem = isRoamIndForHomeSystem(
+ Integer.toString(mRoamingIndicator));
+ if (mNewSS.getDataRoaming() == isRoamIndForHomeSystem) {
+ log("isRoamIndForHomeSystem=" + isRoamIndForHomeSystem
+ + ", override data roaming to " + !isRoamIndForHomeSystem);
+ mNewSS.setDataRoaming(!isRoamIndForHomeSystem);
+ }
}
}
@@ -1885,6 +1901,9 @@
mNewReasonDataDenied = dataRegStateResult.reasonDataDenied;
mNewMaxDataCalls = dataRegStateResult.maxDataCalls;
mDataRoaming = regCodeIsRoaming(regState);
+ // Save the data roaming state reported by modem registration before resource
+ // overlay or carrier config possibly overrides it.
+ mNewSS.setDataRoamingFromRegistration(mDataRoaming);
if (DBG) {
log("handlPollStateResultMessage: GsmSST setDataRegState=" + dataRegState
@@ -1893,7 +1912,11 @@
}
} else if (mPhone.isPhoneTypeCdma()) {
- mNewSS.setDataRoaming(regCodeIsRoaming(regState));
+ boolean isDataRoaming = regCodeIsRoaming(regState);
+ mNewSS.setDataRoaming(isDataRoaming);
+ // Save the data roaming state reported by modem registration before resource
+ // overlay or carrier config possibly overrides it.
+ mNewSS.setDataRoamingFromRegistration(isDataRoaming);
if (DBG) {
log("handlPollStateResultMessage: cdma setDataRegState=" + dataRegState
@@ -1918,11 +1941,15 @@
}
// voice roaming state in done while handling EVENT_POLL_STATE_REGISTRATION_CDMA
- mNewSS.setDataRoaming(regCodeIsRoaming(regState));
+ boolean isDataRoaming = regCodeIsRoaming(regState);
+ mNewSS.setDataRoaming(isDataRoaming);
+ // Save the data roaming state reported by modem registration before resource
+ // overlay or carrier config possibly overrides it.
+ mNewSS.setDataRoamingFromRegistration(isDataRoaming);
if (DBG) {
- log("handlPollStateResultMessage: CdmaLteSST setDataRegState=" + dataRegState
- + " regState=" + regState
- + " dataRadioTechnology=" + newDataRat);
+ log("handlPollStateResultMessage: CdmaLteSST setDataRegState="
+ + dataRegState + " regState=" + regState + " dataRadioTechnology="
+ + newDataRat);
}
}
@@ -2012,10 +2039,9 @@
*/
private boolean isRoamIndForHomeSystem(String roamInd) {
// retrieve the carrier-specified list of ERIs for home system
- log("isRoamIndForHomeSystem: " + Resources.getSystem()
- .getConfiguration().toString());
String[] homeRoamIndicators = Resources.getSystem()
.getStringArray(com.android.internal.R.array.config_cdma_home_system);
+ log("isRoamIndForHomeSystem: homeRoamIndicators=" + Arrays.toString(homeRoamIndicators));
if (homeRoamIndicators != null) {
// searches through the comma-separated list for a match,
@@ -2056,10 +2082,6 @@
*/
boolean roaming = (mGsmRoaming || mDataRoaming);
- // Save the data roaming state reported by modem registration before resource overlay or
- // carrier config possibly overrides it.
- mNewSS.setDataRoamingFromRegistration(roaming);
-
if (mGsmRoaming && !isOperatorConsideredRoaming(mNewSS)
&& (isSameNamedOperators(mNewSS) || isOperatorConsideredNonRoaming(mNewSS))) {
log("updateRoamingState: resource override set non roaming.isSameNamedOperators="
@@ -2097,9 +2119,6 @@
mNewSS.setVoiceRoaming(roaming);
mNewSS.setDataRoaming(roaming);
} else {
- // Save the roaming state before carrier config possibly overrides it.
- mNewSS.setDataRoamingFromRegistration(mNewSS.getDataRoaming());
-
CarrierConfigManager configLoader = (CarrierConfigManager)
mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
if (configLoader != null) {
diff --git a/src/java/com/android/internal/telephony/dataconnection/ApnSetting.java b/src/java/com/android/internal/telephony/dataconnection/ApnSetting.java
index 0ce1991..ce8318d 100644
--- a/src/java/com/android/internal/telephony/dataconnection/ApnSetting.java
+++ b/src/java/com/android/internal/telephony/dataconnection/ApnSetting.java
@@ -24,6 +24,7 @@
import android.telephony.ServiceState;
import android.text.TextUtils;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RILConstants;
@@ -33,6 +34,7 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
/**
* This class represents a apn setting for create PDP link
@@ -42,6 +44,7 @@
static final String LOG_TAG = "ApnSetting";
private static final boolean DBG = false;
+ private static final boolean VDBG = false;
static final String V2_FORMAT_REGEX = "^\\[ApnSettingV2\\]\\s*";
static final String V3_FORMAT_REGEX = "^\\[ApnSettingV3\\]\\s*";
@@ -544,6 +547,116 @@
&& mvnoMatchData.equals(other.mvnoMatchData);
}
+ /**
+ * Compare two APN settings
+ *
+ * Note: This method does not compare 'id', 'bearer', 'bearerBitmask'. We only use this for
+ * determining if tearing a data call is needed when conditions change. See
+ * cleanUpConnectionsOnUpdatedApns in DcTracker.
+ *
+ * @param o the other object to compare
+ * @param isDataRoaming True if the device is on data roaming
+ * @return True if the two APN settings are same
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public boolean equals(Object o, boolean isDataRoaming) {
+ if (!(o instanceof ApnSetting)) {
+ return false;
+ }
+
+ ApnSetting other = (ApnSetting) o;
+
+ return carrier.equals(other.carrier)
+ && numeric.equals(other.numeric)
+ && apn.equals(other.apn)
+ && proxy.equals(other.proxy)
+ && mmsc.equals(other.mmsc)
+ && mmsProxy.equals(other.mmsProxy)
+ && TextUtils.equals(mmsPort, other.mmsPort)
+ && port.equals(other.port)
+ && TextUtils.equals(user, other.user)
+ && TextUtils.equals(password, other.password)
+ && authType == other.authType
+ && Arrays.deepEquals(types, other.types)
+ && typesBitmap == other.typesBitmap
+ && (isDataRoaming || protocol.equals(other.protocol))
+ && (!isDataRoaming || roamingProtocol.equals(other.roamingProtocol))
+ && carrierEnabled == other.carrierEnabled
+ && profileId == other.profileId
+ && modemCognitive == other.modemCognitive
+ && maxConns == other.maxConns
+ && waitTime == other.waitTime
+ && maxConnsTime == other.maxConnsTime
+ && mtu == other.mtu
+ && mvnoType.equals(other.mvnoType)
+ && mvnoMatchData.equals(other.mvnoMatchData);
+ }
+
+ /**
+ * Check if neither mention DUN and are substantially similar
+ *
+ * @param other The other APN settings to compare
+ * @return True if two APN settings are similar
+ */
+ public boolean similar(ApnSetting other) {
+ return (!this.canHandleType(PhoneConstants.APN_TYPE_DUN)
+ && !other.canHandleType(PhoneConstants.APN_TYPE_DUN)
+ && Objects.equals(this.apn, other.apn)
+ && !typeSameAny(this, other)
+ && xorEquals(this.proxy, other.proxy)
+ && xorEquals(this.port, other.port)
+ && xorEquals(this.protocol, other.protocol)
+ && xorEquals(this.roamingProtocol, other.roamingProtocol)
+ && this.carrierEnabled == other.carrierEnabled
+ && this.bearerBitmask == other.bearerBitmask
+ && this.profileId == other.profileId
+ && Objects.equals(this.mvnoType, other.mvnoType)
+ && Objects.equals(this.mvnoMatchData, other.mvnoMatchData)
+ && xorEquals(this.mmsc, other.mmsc)
+ && xorEquals(this.mmsProxy, other.mmsProxy)
+ && xorEquals(this.mmsPort, other.mmsPort));
+ }
+
+ // check whether the types of two APN same (even only one type of each APN is same)
+ private boolean typeSameAny(ApnSetting first, ApnSetting second) {
+ if (VDBG) {
+ StringBuilder apnType1 = new StringBuilder(first.apn + ": ");
+ for (int index1 = 0; index1 < first.types.length; index1++) {
+ apnType1.append(first.types[index1]);
+ apnType1.append(",");
+ }
+
+ StringBuilder apnType2 = new StringBuilder(second.apn + ": ");
+ for (int index1 = 0; index1 < second.types.length; index1++) {
+ apnType2.append(second.types[index1]);
+ apnType2.append(",");
+ }
+ Rlog.d(LOG_TAG, "APN1: is " + apnType1);
+ Rlog.d(LOG_TAG, "APN2: is " + apnType2);
+ }
+
+ for (int index1 = 0; index1 < first.types.length; index1++) {
+ for (int index2 = 0; index2 < second.types.length; index2++) {
+ if (first.types[index1].equals(PhoneConstants.APN_TYPE_ALL)
+ || second.types[index2].equals(PhoneConstants.APN_TYPE_ALL)
+ || first.types[index1].equals(second.types[index2])) {
+ if (VDBG) Rlog.d(LOG_TAG, "typeSameAny: return true");
+ return true;
+ }
+ }
+ }
+
+ if (VDBG) Rlog.d(LOG_TAG, "typeSameAny: return false");
+ return false;
+ }
+
+ // equal or one is not specified
+ private boolean xorEquals(String first, String second) {
+ return (Objects.equals(first, second)
+ || TextUtils.isEmpty(first)
+ || TextUtils.isEmpty(second));
+ }
+
// Helper function to convert APN string into a 32-bit bitmask.
private static int getApnBitmask(String apn) {
switch (apn) {
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 6aaacd7..feb9fe0 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -500,21 +500,12 @@
discReason = RILConstants.DEACTIVATE_REASON_PDP_RESET;
}
}
- if (mPhone.mCi.getRadioState().isOn()
- || (mPhone.getServiceState().getRilDataRadioTechnology()
- == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN )) {
- String str = "tearDownData radio is on, call deactivateDataCall";
- if (DBG) log(str);
- if (apnContext != null) apnContext.requestLog(str);
- mPhone.mCi.deactivateDataCall(mCid, discReason,
- obtainMessage(EVENT_DEACTIVATE_DONE, mTag, 0, o));
- } else {
- String str = "tearDownData radio is off sendMessage EVENT_DEACTIVATE_DONE immediately";
- if (DBG) log(str);
- if (apnContext != null) apnContext.requestLog(str);
- AsyncResult ar = new AsyncResult(o, null, null);
- sendMessage(obtainMessage(EVENT_DEACTIVATE_DONE, mTag, 0, ar));
- }
+
+ String str = "tearDownData. mCid=" + mCid + ", reason=" + discReason;
+ if (DBG) log(str);
+ if (apnContext != null) apnContext.requestLog(str);
+ mPhone.mCi.deactivateDataCall(mCid, discReason,
+ obtainMessage(EVENT_DEACTIVATE_DONE, mTag, 0, o));
}
private void notifyAllWithEvent(ApnContext alreadySent, int event, String reason) {
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index ffffe97..b8ebd1a 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -101,7 +101,6 @@
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map.Entry;
-import java.util.Objects;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -3371,7 +3370,7 @@
int j = i + 1;
while (j < mAllApnSettings.size()) {
second = mAllApnSettings.get(j);
- if (apnsSimilar(first, second)) {
+ if (first.similar(second)) {
ApnSetting newApn = mergeApns(first, second);
mAllApnSettings.set(i, newApn);
first = newApn;
@@ -3384,66 +3383,6 @@
}
}
- //check whether the types of two APN same (even only one type of each APN is same)
- private boolean apnTypeSameAny(ApnSetting first, ApnSetting second) {
- if(VDBG) {
- StringBuilder apnType1 = new StringBuilder(first.apn + ": ");
- for(int index1 = 0; index1 < first.types.length; index1++) {
- apnType1.append(first.types[index1]);
- apnType1.append(",");
- }
-
- StringBuilder apnType2 = new StringBuilder(second.apn + ": ");
- for(int index1 = 0; index1 < second.types.length; index1++) {
- apnType2.append(second.types[index1]);
- apnType2.append(",");
- }
- log("APN1: is " + apnType1);
- log("APN2: is " + apnType2);
- }
-
- for(int index1 = 0; index1 < first.types.length; index1++) {
- for(int index2 = 0; index2 < second.types.length; index2++) {
- if(first.types[index1].equals(PhoneConstants.APN_TYPE_ALL) ||
- second.types[index2].equals(PhoneConstants.APN_TYPE_ALL) ||
- first.types[index1].equals(second.types[index2])) {
- if(VDBG)log("apnTypeSameAny: return true");
- return true;
- }
- }
- }
-
- if(VDBG)log("apnTypeSameAny: return false");
- return false;
- }
-
- // Check if neither mention DUN and are substantially similar
- private boolean apnsSimilar(ApnSetting first, ApnSetting second) {
- return (!first.canHandleType(PhoneConstants.APN_TYPE_DUN)
- && !second.canHandleType(PhoneConstants.APN_TYPE_DUN)
- && Objects.equals(first.apn, second.apn)
- && !apnTypeSameAny(first, second)
- && xorEquals(first.proxy, second.proxy)
- && xorEquals(first.port, second.port)
- && xorEquals(first.protocol, second.protocol)
- && xorEquals(first.roamingProtocol, second.roamingProtocol)
- && first.carrierEnabled == second.carrierEnabled
- && first.bearerBitmask == second.bearerBitmask
- && first.profileId == second.profileId
- && Objects.equals(first.mvnoType, second.mvnoType)
- && Objects.equals(first.mvnoMatchData, second.mvnoMatchData)
- && xorEquals(first.mmsc, second.mmsc)
- && xorEquals(first.mmsProxy, second.mmsProxy)
- && xorEquals(first.mmsPort, second.mmsPort));
- }
-
- // equal or one is not specified
- private boolean xorEquals(String first, String second) {
- return (Objects.equals(first, second) ||
- TextUtils.isEmpty(first) ||
- TextUtils.isEmpty(second));
- }
-
private ApnSetting mergeApns(ApnSetting dest, ApnSetting src) {
int id = dest.id;
ArrayList<String> resultTypes = new ArrayList<String>();
@@ -4382,6 +4321,23 @@
}
}
+ private boolean containsAllApns(ArrayList<ApnSetting> oldApnList,
+ ArrayList<ApnSetting> newApnList) {
+ for (ApnSetting newApnSetting : newApnList) {
+ boolean canHandle = false;
+ for (ApnSetting oldApnSetting : oldApnList) {
+ // Make sure at least one of the APN from old list can cover the new APN
+ if (oldApnSetting.equals(newApnSetting,
+ mPhone.getServiceState().getDataRoamingFromRegistration())) {
+ canHandle = true;
+ break;
+ }
+ }
+ if (!canHandle) return false;
+ }
+ return true;
+ }
+
private void cleanUpConnectionsOnUpdatedApns(boolean tearDown, String reason) {
if (DBG) log("cleanUpConnectionsOnUpdatedApns: tearDown=" + tearDown);
if (mAllApnSettings != null && mAllApnSettings.isEmpty()) {
@@ -4395,7 +4351,10 @@
if (VDBG) log("new waitingApns:" + waitingApns);
if ((currentWaitingApns != null)
&& ((waitingApns.size() != currentWaitingApns.size())
- || (!currentWaitingApns.containsAll(waitingApns)))) {
+ // Check if the existing waiting APN list can cover the newly built APN
+ // list. If yes, then we don't need to tear down the existing data call.
+ // TODO: We probably need to rebuild APN list when roaming status changes.
+ || !containsAllApns(currentWaitingApns, waitingApns))) {
if (VDBG) log("new waiting apn is different for " + apnContext);
apnContext.setWaitingApns(waitingApns);
if (!apnContext.isDisconnected()) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java
index d22fe6f..3624ec1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java
@@ -749,4 +749,67 @@
}
}
}
-}
+
+ @Test
+ @SmallTest
+ public void testEqualsRoamingProtocol() throws Exception {
+ ApnSetting apn1 = new ApnSetting(
+ 1234,
+ "310260",
+ "",
+ "ims",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ -1,
+ new String[]{"ims"},
+ "IPV6",
+ "",
+ true,
+ 0,
+ 131071,
+ 0,
+ false,
+ 0,
+ 0,
+ 0,
+ 1440,
+ "",
+ "");
+
+ ApnSetting apn2 = new ApnSetting(
+ 1235,
+ "310260",
+ "",
+ "ims",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ -1,
+ new String[]{"ims"},
+ "IPV6",
+ "IPV6",
+ true,
+ 0,
+ 131072,
+ 0,
+ false,
+ 0,
+ 0,
+ 0,
+ 1440,
+ "",
+ "");
+
+ assertTrue(apn1.equals(apn2, false));
+ assertFalse(apn1.equals(apn2, true));
+ }
+}
\ No newline at end of file