Loading flags/data.aconfig +6 −3 Original line number Diff line number Diff line Loading @@ -25,10 +25,13 @@ flag { # OWNER=linggm TARGET=24Q3 flag { name: "auto_data_switch_rat_ss" name: "auto_data_switch_uses_data_enabled" namespace: "telephony" description: "Whether switch for better rat and signal strength" bug:"260928808" description: "Separately consider the backup phone's data allowed and data enabled." bug: "338552223" metadata { purpose: PURPOSE_BUGFIX } } # OWNER=linggm TARGET=24Q2 Loading src/java/com/android/internal/telephony/Phone.java +2 −2 Original line number Diff line number Diff line Loading @@ -4922,8 +4922,8 @@ public abstract class Phone extends Handler implements PhoneInternalInterface { /** * @return The data settings manager */ public @Nullable DataSettingsManager getDataSettingsManager() { if (mDataNetworkController == null) return null; @NonNull public DataSettingsManager getDataSettingsManager() { return mDataNetworkController.getDataSettingsManager(); } Loading src/java/com/android/internal/telephony/data/AutoDataSwitchController.java +72 −84 Original line number Diff line number Diff line Loading @@ -473,6 +473,7 @@ public class AutoDataSwitchController extends Handler { @Override public void handleMessage(@NonNull Message msg) { AsyncResult ar; Object obj; int phoneId; switch (msg.what) { case EVENT_SERVICE_STATE_CHANGED: Loading @@ -491,20 +492,14 @@ public class AutoDataSwitchController extends Handler { onSignalStrengthChanged(phoneId); break; case EVENT_EVALUATE_AUTO_SWITCH: if (sFeatureFlags.autoDataSwitchRatSs()) { Object obj = mScheduledEventsToExtras.get(EVENT_EVALUATE_AUTO_SWITCH); obj = mScheduledEventsToExtras.get(EVENT_EVALUATE_AUTO_SWITCH); if (obj instanceof EvaluateEventExtra extra) { mScheduledEventsToExtras.remove(EVENT_EVALUATE_AUTO_SWITCH); onEvaluateAutoDataSwitch(extra.evaluateReason); } } else { int reason = (int) msg.obj; onEvaluateAutoDataSwitch(reason); } break; case EVENT_STABILITY_CHECK_PASSED: if (sFeatureFlags.autoDataSwitchRatSs()) { Object obj = mScheduledEventsToExtras.get(EVENT_STABILITY_CHECK_PASSED); obj = mScheduledEventsToExtras.get(EVENT_STABILITY_CHECK_PASSED); if (obj instanceof StabilityEventExtra extra) { int targetPhoneId = extra.targetPhoneId; boolean needValidation = extra.needValidation; Loading @@ -513,13 +508,6 @@ public class AutoDataSwitchController extends Handler { mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED); mPhoneSwitcherCallback.onRequireValidation(targetPhoneId, needValidation); } } else { int targetPhoneId = msg.arg1; boolean needValidation = msg.arg2 == 1; log("require validation on phone " + targetPhoneId + (needValidation ? "" : " no") + " need to pass"); mPhoneSwitcherCallback.onRequireValidation(targetPhoneId, needValidation); } break; case EVENT_SUBSCRIPTIONS_CHANGED: onSubscriptionsChanged(); Loading Loading @@ -643,16 +631,10 @@ public class AutoDataSwitchController extends Handler { ? mAutoDataSwitchAvailabilityStabilityTimeThreshold << mAutoSwitchValidationFailedCount : 0; if (sFeatureFlags.autoDataSwitchRatSs()) { if (!mScheduledEventsToExtras.containsKey(EVENT_EVALUATE_AUTO_SWITCH)) { scheduleEventWithTimer(EVENT_EVALUATE_AUTO_SWITCH, new EvaluateEventExtra(reason), delayMs); } } else { if (!hasMessages(EVENT_EVALUATE_AUTO_SWITCH)) { sendMessageDelayed(obtainMessage(EVENT_EVALUATE_AUTO_SWITCH, reason), delayMs); } } } /** Loading Loading @@ -700,13 +682,33 @@ public class AutoDataSwitchController extends Handler { return; } DataEvaluation internetEvaluation; if (sFeatureFlags.autoDataSwitchUsesDataEnabled()) { if (!defaultDataPhone.isUserDataEnabled()) { mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX, EVALUATION_REASON_DATA_SETTINGS_CHANGED); log(debugMessage.append( ", immediately back to default as user turns off default").toString()); return; } else if (!(internetEvaluation = backupDataPhone.getDataNetworkController() .getInternetEvaluation(false/*ignoreExistingNetworks*/)) .isSubsetOf(DataEvaluation.DataDisallowedReason.NOT_IN_SERVICE)) { mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone( DEFAULT_PHONE_INDEX, EVALUATION_REASON_DATA_SETTINGS_CHANGED); log(debugMessage.append( ", immediately back to default because backup ") .append(internetEvaluation).toString()); return; } } else { if (!defaultDataPhone.isUserDataEnabled() || !backupDataPhone.isDataAllowed()) { mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX, EVALUATION_REASON_DATA_SETTINGS_CHANGED); log(debugMessage.append(", immediately back to default as user turns off settings") .toString()); log(debugMessage.append( ", immediately back to default as user turns off settings").toString()); return; } } boolean backToDefault = false; boolean isForPerformance = false; Loading Loading @@ -915,12 +917,15 @@ public class AutoDataSwitchController extends Handler { } if (secondaryDataPhone != null) { // check auto switch feature enabled if (secondaryDataPhone.isDataAllowed()) { // check internet data is allowed on the candidate DataEvaluation internetEvaluation = secondaryDataPhone.getDataNetworkController() .getInternetEvaluation(false/*ignoreExistingNetworks*/); if (!internetEvaluation.containsDisallowedReasons()) { return new StabilityEventExtra(phoneId, isForPerformance, mRequirePingTestBeforeSwitch); } else { debugMessage.append(", but candidate's data is not allowed"); debugMessage.append(", but candidate's data is not allowed ") .append(internetEvaluation); } } } Loading @@ -932,8 +937,7 @@ public class AutoDataSwitchController extends Handler { * @return {@code true} If the feature of switching base on RAT and signal strength is enabled. */ private boolean isRatSignalStrengthBasedSwitchEnabled() { return sFeatureFlags.autoDataSwitchRatSs() && mScoreTolerance >= 0 && mAutoDataSwitchPerformanceStabilityTimeThreshold >= 0; return mScoreTolerance >= 0 && mAutoDataSwitchPerformanceStabilityTimeThreshold >= 0; } /** Loading @@ -953,8 +957,6 @@ public class AutoDataSwitchController extends Handler { */ private void startStabilityCheck(int targetPhoneId, boolean isForPerformance, boolean needValidation) { String combinationIdentifier = targetPhoneId + "" + needValidation; if (sFeatureFlags.autoDataSwitchRatSs()) { StabilityEventExtra eventExtras = (StabilityEventExtra) mScheduledEventsToExtras.getOrDefault(EVENT_STABILITY_CHECK_PASSED, new StabilityEventExtra(INVALID_PHONE_INDEX, false /*need validation*/, Loading @@ -976,16 +978,6 @@ public class AutoDataSwitchController extends Handler { log("startStabilityCheck: " + (delayMs != -1 ? "scheduling " : "already scheduled ") + eventExtras); } else if (!hasEqualMessages(EVENT_STABILITY_CHECK_PASSED, combinationIdentifier)) { removeMessages(EVENT_STABILITY_CHECK_PASSED); sendMessageDelayed(obtainMessage(EVENT_STABILITY_CHECK_PASSED, targetPhoneId, needValidation ? 1 : 0, combinationIdentifier), mAutoDataSwitchAvailabilityStabilityTimeThreshold); log("startStabilityCheck: targetPhoneId=" + targetPhoneId + " isForPerformance=" + isForPerformance + " needValidation=" + needValidation); } } /** Loading Loading @@ -1075,7 +1067,6 @@ public class AutoDataSwitchController extends Handler { private void cancelAnyPendingSwitch() { mSelectedTargetPhoneId = INVALID_PHONE_INDEX; resetFailedCount(); if (sFeatureFlags.autoDataSwitchRatSs()) { if (mScheduledEventsToExtras.containsKey(EVENT_STABILITY_CHECK_PASSED)) { if (mEventsToAlarmListener.containsKey(EVENT_STABILITY_CHECK_PASSED)) { mAlarmManager.cancel(mEventsToAlarmListener.get(EVENT_STABILITY_CHECK_PASSED)); Loading @@ -1085,9 +1076,6 @@ public class AutoDataSwitchController extends Handler { removeMessages(EVENT_STABILITY_CHECK_PASSED); mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED); } } else { removeMessages(EVENT_STABILITY_CHECK_PASSED); } mPhoneSwitcherCallback.onRequireCancelAnyPendingAutoSwitchValidation(); } Loading src/java/com/android/internal/telephony/data/DataNetworkController.java +22 −7 Original line number Diff line number Diff line Loading @@ -1482,6 +1482,19 @@ public class DataNetworkController extends Handler { * still allowed in this case. */ public boolean isInternetDataAllowed(boolean ignoreExistingNetworks) { return !getInternetEvaluation(ignoreExistingNetworks).containsDisallowedReasons(); } /** * @param ignoreExistingNetworks {@code true} to skip the existing network check. * @return The internet evaluation result. * For example, if SIM is absent, or airplane mode is on, then data is NOT allowed. * This API does not reflect the currently internet data network status. It's possible there is * no internet data due to weak cellular signal or network side issue, but internet data is * still allowed in this case. */ @NonNull public DataEvaluation getInternetEvaluation(boolean ignoreExistingNetworks) { TelephonyNetworkRequest internetRequest = new TelephonyNetworkRequest( new NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) Loading @@ -1493,7 +1506,7 @@ public class DataNetworkController extends Handler { && mDataNetworkList.stream().anyMatch( dataNetwork -> internetRequest.canBeSatisfiedBy( dataNetwork.getNetworkCapabilities()))) { return true; return new DataEvaluation(DataEvaluationReason.EXTERNAL_QUERY); } // If no existing network can satisfy the request, then check if we can possibly setup Loading @@ -1501,17 +1514,19 @@ public class DataNetworkController extends Handler { DataEvaluation evaluation = evaluateNetworkRequest(internetRequest, DataEvaluationReason.EXTERNAL_QUERY); if (evaluation.containsOnly(DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK)) { // If the only failed reason is only single network allowed, then check if the request // can trump the current network. return internetRequest.getPriority() > mDataNetworkList.stream() if (evaluation.containsOnly(DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK) && internetRequest.getPriority() > mDataNetworkList.stream() .map(DataNetwork::getPriority) .max(Comparator.comparing(Integer::valueOf)) .orElse(0); .orElse(0)) { // If the only failed reason is only single network allowed, then check if the request // can trump the current network. evaluation.addDataAllowedReason(DataAllowedReason.NORMAL); } return !evaluation.containsDisallowedReasons(); return evaluation; } /** * @return {@code true} if internet is unmetered. */ Loading tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java +28 −10 Original line number Diff line number Diff line Loading @@ -93,8 +93,10 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { private TelephonyDisplayInfo mGoodTelephonyDisplayInfo; private TelephonyDisplayInfo mBadTelephonyDisplayInfo; private int mDefaultDataSub; private DataEvaluation mDataEvaluation; private AutoDataSwitchController mAutoDataSwitchControllerUT; private Map<Integer, AlarmManager.OnAlarmListener> mEventsToAlarmListener; private Map<Integer, Object> mScheduledEventsToExtras; @Before public void setUp() throws Exception { super.setUp(getClass().getSimpleName()); Loading Loading @@ -137,6 +139,8 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { doAnswer(invocation -> phone.getSubId() == mDefaultDataSub) .when(phone).isUserDataEnabled(); } mDataEvaluation = new DataEvaluation(DataEvaluation.DataEvaluationReason.EXTERNAL_QUERY); doReturn(mDataEvaluation).when(mDataNetworkController).getInternetEvaluation(anyBoolean()); doReturn(new int[]{SUB_1, SUB_2}).when(mSubscriptionManagerService) .getActiveSubIdList(true); doAnswer(invocation -> { Loading Loading @@ -184,9 +188,12 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { mAutoDataSwitchControllerUT, mMockedAlarmManager); mEventsToAlarmListener = getPrivateField(mAutoDataSwitchControllerUT, "mEventsToAlarmListener", Map.class); mScheduledEventsToExtras = getPrivateField(mAutoDataSwitchControllerUT, "mScheduledEventsToExtras", Map.class); doReturn(true).when(mFeatureFlags).autoDataSwitchAllowRoaming(); doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag(); doReturn(true).when(mFeatureFlags).autoDataSwitchUsesDataEnabled(); } @After Loading Loading @@ -240,7 +247,10 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { prepareIdealUsesNonDdsCondition(); processAllFutureMessages(); clearInvocations(mMockedPhoneSwitcherCallback); doReturn(false).when(mPhone2).isDataAllowed(); mDataEvaluation.addDataDisallowedReason(DataEvaluation.DataDisallowedReason .NO_SUITABLE_DATA_PROFILE); doReturn(mDataEvaluation) .when(mDataNetworkController).getInternetEvaluation(anyBoolean()); mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED); processAllFutureMessages(); Loading Loading @@ -350,7 +360,6 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Test public void testRoaming_same_roaming_condition_uses_rat_signalStrength() { doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs(); // On primary phone // 1. Both roaming, user allow roaming on both phone, uses RAT score to decide switch. prepareIdealUsesNonDdsCondition(); Loading @@ -375,7 +384,6 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Test public void testCancelSwitch_onPrimary_rat_signalStrength() { doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs(); // 4.1.1 Display info and signal strength on secondary phone became bad, // but primary is still OOS, so still switch to the secondary. prepareIdealUsesNonDdsCondition(); Loading Loading @@ -467,7 +475,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { prepareIdealUsesNonDdsCondition(); // 2.2 Auto switch feature is disabled, no need validation clearInvocations(mCellularNetworkValidator); doReturn(false).when(mPhone2).isDataAllowed(); mDataEvaluation.addDataDisallowedReason(DataEvaluation.DataDisallowedReason.DATA_DISABLED); mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED); processAllFutureMessages(); Loading @@ -483,11 +491,13 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { verify(mMockedPhoneSwitcherCallback).onRequireValidation(DEFAULT_PHONE_INDEX, false/*needValidation*/); clearInvocations(mMockedPhoneSwitcherCallback); prepareIdealUsesNonDdsCondition(); } @Test public void testOnNonDdsSwitchBackToPrimary_rat_signalStrength() { doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs(); prepareIdealUsesNonDdsCondition(); processAllFutureMessages(); doReturn(PHONE_2).when(mPhoneSwitcher).getPreferredDataPhoneId(); Loading Loading @@ -536,10 +546,16 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Test public void testStabilityCheckOverride_basic() { // Disable RAT + signalStrength base switching. doReturn(-1).when(mDataConfigManager).getAutoDataSwitchScoreTolerance(); mAutoDataSwitchControllerUT = new AutoDataSwitchController(mContext, Looper.myLooper(), mPhoneSwitcher, mFeatureFlags, mMockedPhoneSwitcherCallback); // Starting stability check for switching to non-DDS prepareIdealUsesNonDdsCondition(); processAllMessages(); processAllFutureMessages(); clearInvocations(mMockedPhoneSwitcherCallback); // Switch success, but the previous stability check is still pending doReturn(PHONE_2).when(mPhoneSwitcher).getPreferredDataPhoneId(); Loading @@ -557,7 +573,6 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Test public void testStabilityCheckOverride_uses_rat_signalStrength() { doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs(); // Switching due to availability first. prepareIdealUsesNonDdsCondition(); Loading @@ -578,6 +593,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { public void testValidationFailedRetry() { prepareIdealUsesNonDdsCondition(); clearInvocations(mMockedPhoneSwitcherCallback); for (int i = 0; i < MAX_RETRY; i++) { mAutoDataSwitchControllerUT.evaluateRetryOnValidationFailed(); processAllFutureMessages(); Loading Loading @@ -730,7 +746,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { // 4.2 Auto switch feature is enabled doReturn(true).when(mPhone2).getDataRoamingEnabled(); doReturn(true).when(mPhone2).isDataAllowed(); mDataEvaluation.addDataAllowedReason(DataEvaluation.DataAllowedReason.NORMAL); // 5. No default network mAutoDataSwitchControllerUT.updateDefaultNetworkCapabilities(null /*networkCapabilities*/); Loading Loading @@ -783,10 +799,12 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Override public void processAllFutureMessages() { if (mFeatureFlags.autoDataSwitchRatSs() && mEventsToAlarmListener.containsKey(EVENT_STABILITY_CHECK_PASSED)) { if (mScheduledEventsToExtras.containsKey(EVENT_STABILITY_CHECK_PASSED)) { mEventsToAlarmListener.get(EVENT_STABILITY_CHECK_PASSED).onAlarm(); } if (mScheduledEventsToExtras.containsKey(EVENT_EVALUATE_AUTO_SWITCH)) { mEventsToAlarmListener.get(EVENT_EVALUATE_AUTO_SWITCH).onAlarm(); } super.processAllFutureMessages(); } } Loading
flags/data.aconfig +6 −3 Original line number Diff line number Diff line Loading @@ -25,10 +25,13 @@ flag { # OWNER=linggm TARGET=24Q3 flag { name: "auto_data_switch_rat_ss" name: "auto_data_switch_uses_data_enabled" namespace: "telephony" description: "Whether switch for better rat and signal strength" bug:"260928808" description: "Separately consider the backup phone's data allowed and data enabled." bug: "338552223" metadata { purpose: PURPOSE_BUGFIX } } # OWNER=linggm TARGET=24Q2 Loading
src/java/com/android/internal/telephony/Phone.java +2 −2 Original line number Diff line number Diff line Loading @@ -4922,8 +4922,8 @@ public abstract class Phone extends Handler implements PhoneInternalInterface { /** * @return The data settings manager */ public @Nullable DataSettingsManager getDataSettingsManager() { if (mDataNetworkController == null) return null; @NonNull public DataSettingsManager getDataSettingsManager() { return mDataNetworkController.getDataSettingsManager(); } Loading
src/java/com/android/internal/telephony/data/AutoDataSwitchController.java +72 −84 Original line number Diff line number Diff line Loading @@ -473,6 +473,7 @@ public class AutoDataSwitchController extends Handler { @Override public void handleMessage(@NonNull Message msg) { AsyncResult ar; Object obj; int phoneId; switch (msg.what) { case EVENT_SERVICE_STATE_CHANGED: Loading @@ -491,20 +492,14 @@ public class AutoDataSwitchController extends Handler { onSignalStrengthChanged(phoneId); break; case EVENT_EVALUATE_AUTO_SWITCH: if (sFeatureFlags.autoDataSwitchRatSs()) { Object obj = mScheduledEventsToExtras.get(EVENT_EVALUATE_AUTO_SWITCH); obj = mScheduledEventsToExtras.get(EVENT_EVALUATE_AUTO_SWITCH); if (obj instanceof EvaluateEventExtra extra) { mScheduledEventsToExtras.remove(EVENT_EVALUATE_AUTO_SWITCH); onEvaluateAutoDataSwitch(extra.evaluateReason); } } else { int reason = (int) msg.obj; onEvaluateAutoDataSwitch(reason); } break; case EVENT_STABILITY_CHECK_PASSED: if (sFeatureFlags.autoDataSwitchRatSs()) { Object obj = mScheduledEventsToExtras.get(EVENT_STABILITY_CHECK_PASSED); obj = mScheduledEventsToExtras.get(EVENT_STABILITY_CHECK_PASSED); if (obj instanceof StabilityEventExtra extra) { int targetPhoneId = extra.targetPhoneId; boolean needValidation = extra.needValidation; Loading @@ -513,13 +508,6 @@ public class AutoDataSwitchController extends Handler { mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED); mPhoneSwitcherCallback.onRequireValidation(targetPhoneId, needValidation); } } else { int targetPhoneId = msg.arg1; boolean needValidation = msg.arg2 == 1; log("require validation on phone " + targetPhoneId + (needValidation ? "" : " no") + " need to pass"); mPhoneSwitcherCallback.onRequireValidation(targetPhoneId, needValidation); } break; case EVENT_SUBSCRIPTIONS_CHANGED: onSubscriptionsChanged(); Loading Loading @@ -643,16 +631,10 @@ public class AutoDataSwitchController extends Handler { ? mAutoDataSwitchAvailabilityStabilityTimeThreshold << mAutoSwitchValidationFailedCount : 0; if (sFeatureFlags.autoDataSwitchRatSs()) { if (!mScheduledEventsToExtras.containsKey(EVENT_EVALUATE_AUTO_SWITCH)) { scheduleEventWithTimer(EVENT_EVALUATE_AUTO_SWITCH, new EvaluateEventExtra(reason), delayMs); } } else { if (!hasMessages(EVENT_EVALUATE_AUTO_SWITCH)) { sendMessageDelayed(obtainMessage(EVENT_EVALUATE_AUTO_SWITCH, reason), delayMs); } } } /** Loading Loading @@ -700,13 +682,33 @@ public class AutoDataSwitchController extends Handler { return; } DataEvaluation internetEvaluation; if (sFeatureFlags.autoDataSwitchUsesDataEnabled()) { if (!defaultDataPhone.isUserDataEnabled()) { mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX, EVALUATION_REASON_DATA_SETTINGS_CHANGED); log(debugMessage.append( ", immediately back to default as user turns off default").toString()); return; } else if (!(internetEvaluation = backupDataPhone.getDataNetworkController() .getInternetEvaluation(false/*ignoreExistingNetworks*/)) .isSubsetOf(DataEvaluation.DataDisallowedReason.NOT_IN_SERVICE)) { mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone( DEFAULT_PHONE_INDEX, EVALUATION_REASON_DATA_SETTINGS_CHANGED); log(debugMessage.append( ", immediately back to default because backup ") .append(internetEvaluation).toString()); return; } } else { if (!defaultDataPhone.isUserDataEnabled() || !backupDataPhone.isDataAllowed()) { mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX, EVALUATION_REASON_DATA_SETTINGS_CHANGED); log(debugMessage.append(", immediately back to default as user turns off settings") .toString()); log(debugMessage.append( ", immediately back to default as user turns off settings").toString()); return; } } boolean backToDefault = false; boolean isForPerformance = false; Loading Loading @@ -915,12 +917,15 @@ public class AutoDataSwitchController extends Handler { } if (secondaryDataPhone != null) { // check auto switch feature enabled if (secondaryDataPhone.isDataAllowed()) { // check internet data is allowed on the candidate DataEvaluation internetEvaluation = secondaryDataPhone.getDataNetworkController() .getInternetEvaluation(false/*ignoreExistingNetworks*/); if (!internetEvaluation.containsDisallowedReasons()) { return new StabilityEventExtra(phoneId, isForPerformance, mRequirePingTestBeforeSwitch); } else { debugMessage.append(", but candidate's data is not allowed"); debugMessage.append(", but candidate's data is not allowed ") .append(internetEvaluation); } } } Loading @@ -932,8 +937,7 @@ public class AutoDataSwitchController extends Handler { * @return {@code true} If the feature of switching base on RAT and signal strength is enabled. */ private boolean isRatSignalStrengthBasedSwitchEnabled() { return sFeatureFlags.autoDataSwitchRatSs() && mScoreTolerance >= 0 && mAutoDataSwitchPerformanceStabilityTimeThreshold >= 0; return mScoreTolerance >= 0 && mAutoDataSwitchPerformanceStabilityTimeThreshold >= 0; } /** Loading @@ -953,8 +957,6 @@ public class AutoDataSwitchController extends Handler { */ private void startStabilityCheck(int targetPhoneId, boolean isForPerformance, boolean needValidation) { String combinationIdentifier = targetPhoneId + "" + needValidation; if (sFeatureFlags.autoDataSwitchRatSs()) { StabilityEventExtra eventExtras = (StabilityEventExtra) mScheduledEventsToExtras.getOrDefault(EVENT_STABILITY_CHECK_PASSED, new StabilityEventExtra(INVALID_PHONE_INDEX, false /*need validation*/, Loading @@ -976,16 +978,6 @@ public class AutoDataSwitchController extends Handler { log("startStabilityCheck: " + (delayMs != -1 ? "scheduling " : "already scheduled ") + eventExtras); } else if (!hasEqualMessages(EVENT_STABILITY_CHECK_PASSED, combinationIdentifier)) { removeMessages(EVENT_STABILITY_CHECK_PASSED); sendMessageDelayed(obtainMessage(EVENT_STABILITY_CHECK_PASSED, targetPhoneId, needValidation ? 1 : 0, combinationIdentifier), mAutoDataSwitchAvailabilityStabilityTimeThreshold); log("startStabilityCheck: targetPhoneId=" + targetPhoneId + " isForPerformance=" + isForPerformance + " needValidation=" + needValidation); } } /** Loading Loading @@ -1075,7 +1067,6 @@ public class AutoDataSwitchController extends Handler { private void cancelAnyPendingSwitch() { mSelectedTargetPhoneId = INVALID_PHONE_INDEX; resetFailedCount(); if (sFeatureFlags.autoDataSwitchRatSs()) { if (mScheduledEventsToExtras.containsKey(EVENT_STABILITY_CHECK_PASSED)) { if (mEventsToAlarmListener.containsKey(EVENT_STABILITY_CHECK_PASSED)) { mAlarmManager.cancel(mEventsToAlarmListener.get(EVENT_STABILITY_CHECK_PASSED)); Loading @@ -1085,9 +1076,6 @@ public class AutoDataSwitchController extends Handler { removeMessages(EVENT_STABILITY_CHECK_PASSED); mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED); } } else { removeMessages(EVENT_STABILITY_CHECK_PASSED); } mPhoneSwitcherCallback.onRequireCancelAnyPendingAutoSwitchValidation(); } Loading
src/java/com/android/internal/telephony/data/DataNetworkController.java +22 −7 Original line number Diff line number Diff line Loading @@ -1482,6 +1482,19 @@ public class DataNetworkController extends Handler { * still allowed in this case. */ public boolean isInternetDataAllowed(boolean ignoreExistingNetworks) { return !getInternetEvaluation(ignoreExistingNetworks).containsDisallowedReasons(); } /** * @param ignoreExistingNetworks {@code true} to skip the existing network check. * @return The internet evaluation result. * For example, if SIM is absent, or airplane mode is on, then data is NOT allowed. * This API does not reflect the currently internet data network status. It's possible there is * no internet data due to weak cellular signal or network side issue, but internet data is * still allowed in this case. */ @NonNull public DataEvaluation getInternetEvaluation(boolean ignoreExistingNetworks) { TelephonyNetworkRequest internetRequest = new TelephonyNetworkRequest( new NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) Loading @@ -1493,7 +1506,7 @@ public class DataNetworkController extends Handler { && mDataNetworkList.stream().anyMatch( dataNetwork -> internetRequest.canBeSatisfiedBy( dataNetwork.getNetworkCapabilities()))) { return true; return new DataEvaluation(DataEvaluationReason.EXTERNAL_QUERY); } // If no existing network can satisfy the request, then check if we can possibly setup Loading @@ -1501,17 +1514,19 @@ public class DataNetworkController extends Handler { DataEvaluation evaluation = evaluateNetworkRequest(internetRequest, DataEvaluationReason.EXTERNAL_QUERY); if (evaluation.containsOnly(DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK)) { // If the only failed reason is only single network allowed, then check if the request // can trump the current network. return internetRequest.getPriority() > mDataNetworkList.stream() if (evaluation.containsOnly(DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK) && internetRequest.getPriority() > mDataNetworkList.stream() .map(DataNetwork::getPriority) .max(Comparator.comparing(Integer::valueOf)) .orElse(0); .orElse(0)) { // If the only failed reason is only single network allowed, then check if the request // can trump the current network. evaluation.addDataAllowedReason(DataAllowedReason.NORMAL); } return !evaluation.containsDisallowedReasons(); return evaluation; } /** * @return {@code true} if internet is unmetered. */ Loading
tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java +28 −10 Original line number Diff line number Diff line Loading @@ -93,8 +93,10 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { private TelephonyDisplayInfo mGoodTelephonyDisplayInfo; private TelephonyDisplayInfo mBadTelephonyDisplayInfo; private int mDefaultDataSub; private DataEvaluation mDataEvaluation; private AutoDataSwitchController mAutoDataSwitchControllerUT; private Map<Integer, AlarmManager.OnAlarmListener> mEventsToAlarmListener; private Map<Integer, Object> mScheduledEventsToExtras; @Before public void setUp() throws Exception { super.setUp(getClass().getSimpleName()); Loading Loading @@ -137,6 +139,8 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { doAnswer(invocation -> phone.getSubId() == mDefaultDataSub) .when(phone).isUserDataEnabled(); } mDataEvaluation = new DataEvaluation(DataEvaluation.DataEvaluationReason.EXTERNAL_QUERY); doReturn(mDataEvaluation).when(mDataNetworkController).getInternetEvaluation(anyBoolean()); doReturn(new int[]{SUB_1, SUB_2}).when(mSubscriptionManagerService) .getActiveSubIdList(true); doAnswer(invocation -> { Loading Loading @@ -184,9 +188,12 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { mAutoDataSwitchControllerUT, mMockedAlarmManager); mEventsToAlarmListener = getPrivateField(mAutoDataSwitchControllerUT, "mEventsToAlarmListener", Map.class); mScheduledEventsToExtras = getPrivateField(mAutoDataSwitchControllerUT, "mScheduledEventsToExtras", Map.class); doReturn(true).when(mFeatureFlags).autoDataSwitchAllowRoaming(); doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag(); doReturn(true).when(mFeatureFlags).autoDataSwitchUsesDataEnabled(); } @After Loading Loading @@ -240,7 +247,10 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { prepareIdealUsesNonDdsCondition(); processAllFutureMessages(); clearInvocations(mMockedPhoneSwitcherCallback); doReturn(false).when(mPhone2).isDataAllowed(); mDataEvaluation.addDataDisallowedReason(DataEvaluation.DataDisallowedReason .NO_SUITABLE_DATA_PROFILE); doReturn(mDataEvaluation) .when(mDataNetworkController).getInternetEvaluation(anyBoolean()); mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED); processAllFutureMessages(); Loading Loading @@ -350,7 +360,6 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Test public void testRoaming_same_roaming_condition_uses_rat_signalStrength() { doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs(); // On primary phone // 1. Both roaming, user allow roaming on both phone, uses RAT score to decide switch. prepareIdealUsesNonDdsCondition(); Loading @@ -375,7 +384,6 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Test public void testCancelSwitch_onPrimary_rat_signalStrength() { doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs(); // 4.1.1 Display info and signal strength on secondary phone became bad, // but primary is still OOS, so still switch to the secondary. prepareIdealUsesNonDdsCondition(); Loading Loading @@ -467,7 +475,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { prepareIdealUsesNonDdsCondition(); // 2.2 Auto switch feature is disabled, no need validation clearInvocations(mCellularNetworkValidator); doReturn(false).when(mPhone2).isDataAllowed(); mDataEvaluation.addDataDisallowedReason(DataEvaluation.DataDisallowedReason.DATA_DISABLED); mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED); processAllFutureMessages(); Loading @@ -483,11 +491,13 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { verify(mMockedPhoneSwitcherCallback).onRequireValidation(DEFAULT_PHONE_INDEX, false/*needValidation*/); clearInvocations(mMockedPhoneSwitcherCallback); prepareIdealUsesNonDdsCondition(); } @Test public void testOnNonDdsSwitchBackToPrimary_rat_signalStrength() { doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs(); prepareIdealUsesNonDdsCondition(); processAllFutureMessages(); doReturn(PHONE_2).when(mPhoneSwitcher).getPreferredDataPhoneId(); Loading Loading @@ -536,10 +546,16 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Test public void testStabilityCheckOverride_basic() { // Disable RAT + signalStrength base switching. doReturn(-1).when(mDataConfigManager).getAutoDataSwitchScoreTolerance(); mAutoDataSwitchControllerUT = new AutoDataSwitchController(mContext, Looper.myLooper(), mPhoneSwitcher, mFeatureFlags, mMockedPhoneSwitcherCallback); // Starting stability check for switching to non-DDS prepareIdealUsesNonDdsCondition(); processAllMessages(); processAllFutureMessages(); clearInvocations(mMockedPhoneSwitcherCallback); // Switch success, but the previous stability check is still pending doReturn(PHONE_2).when(mPhoneSwitcher).getPreferredDataPhoneId(); Loading @@ -557,7 +573,6 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Test public void testStabilityCheckOverride_uses_rat_signalStrength() { doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs(); // Switching due to availability first. prepareIdealUsesNonDdsCondition(); Loading @@ -578,6 +593,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { public void testValidationFailedRetry() { prepareIdealUsesNonDdsCondition(); clearInvocations(mMockedPhoneSwitcherCallback); for (int i = 0; i < MAX_RETRY; i++) { mAutoDataSwitchControllerUT.evaluateRetryOnValidationFailed(); processAllFutureMessages(); Loading Loading @@ -730,7 +746,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { // 4.2 Auto switch feature is enabled doReturn(true).when(mPhone2).getDataRoamingEnabled(); doReturn(true).when(mPhone2).isDataAllowed(); mDataEvaluation.addDataAllowedReason(DataEvaluation.DataAllowedReason.NORMAL); // 5. No default network mAutoDataSwitchControllerUT.updateDefaultNetworkCapabilities(null /*networkCapabilities*/); Loading Loading @@ -783,10 +799,12 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Override public void processAllFutureMessages() { if (mFeatureFlags.autoDataSwitchRatSs() && mEventsToAlarmListener.containsKey(EVENT_STABILITY_CHECK_PASSED)) { if (mScheduledEventsToExtras.containsKey(EVENT_STABILITY_CHECK_PASSED)) { mEventsToAlarmListener.get(EVENT_STABILITY_CHECK_PASSED).onAlarm(); } if (mScheduledEventsToExtras.containsKey(EVENT_EVALUATE_AUTO_SWITCH)) { mEventsToAlarmListener.get(EVENT_EVALUATE_AUTO_SWITCH).onAlarm(); } super.processAllFutureMessages(); } }