Loading src/java/com/android/internal/telephony/PhoneSwitcher.java +81 −10 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS; import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED; import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM; import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN; import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NONE; import static java.util.Arrays.copyOf; Loading Loading @@ -59,9 +60,13 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.TelephonyRegistryManager; import android.telephony.data.ApnSetting; import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsRegistrationAttributes; import android.telephony.ims.RegistrationManager; import android.telephony.ims.stub.ImsRegistrationImplBase; import android.util.LocalLog; import com.android.ims.ImsException; import com.android.ims.ImsManager; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.SubscriptionController.WatchedInt; Loading Loading @@ -170,6 +175,7 @@ public class PhoneSwitcher extends Handler { private final LocalLog mLocalLog; protected PhoneState[] mPhoneStates; protected int[] mPhoneSubscriptions; private boolean mIsRegisteredForImsRadioTechChange; @VisibleForTesting protected final CellularNetworkValidator mValidator; private int mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID; Loading Loading @@ -275,6 +281,8 @@ public class PhoneSwitcher extends Handler { public static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 117; private static final int EVENT_NETWORK_AVAILABLE = 118; private static final int EVENT_PROCESS_SIM_STATE_CHANGE = 119; @VisibleForTesting public static final int EVENT_IMS_RADIO_TECH_CHANGED = 120; // Depending on version of IRadioConfig, we need to send either RIL_REQUEST_ALLOW_DATA if it's // 1.0, or RIL_REQUEST_SET_PREFERRED_DATA if it's 1.1 or later. So internally mHalCommandToUse Loading @@ -294,6 +302,7 @@ public class PhoneSwitcher extends Handler { private Boolean mHasRegisteredDefaultNetworkChangeCallback = false; private ConnectivityManager mConnectivityManager; private int mImsRegistrationTech = REGISTRATION_TECH_NONE; private List<Set<CommandException.Error>> mCurrentDdsSwitchFailure; Loading @@ -316,6 +325,26 @@ public class PhoneSwitcher extends Handler { } } private RegistrationManager.RegistrationCallback mRegistrationCallback = new RegistrationManager.RegistrationCallback() { @Override public void onRegistered(ImsRegistrationAttributes attributes) { int imsRegistrationTech = attributes.getRegistrationTechnology(); if (imsRegistrationTech != mImsRegistrationTech) { mImsRegistrationTech = imsRegistrationTech; sendMessage(obtainMessage(EVENT_IMS_RADIO_TECH_CHANGED)); } } @Override public void onUnregistered(ImsReasonInfo info) { if (mImsRegistrationTech != REGISTRATION_TECH_NONE) { mImsRegistrationTech = REGISTRATION_TECH_NONE; sendMessage(obtainMessage(EVENT_IMS_RADIO_TECH_CHANGED)); } } }; private final DefaultNetworkCallback mDefaultNetworkCallback = new DefaultNetworkCallback(); /** Loading Loading @@ -394,6 +423,35 @@ public class PhoneSwitcher extends Handler { } } private void registerForImsRadioTechChange(Context context, int phoneId) { try { ImsManager.getInstance(context, phoneId).addRegistrationCallback( mRegistrationCallback, this::post); mIsRegisteredForImsRadioTechChange = true; } catch (ImsException imsException) { mIsRegisteredForImsRadioTechChange = false; } } private void registerForImsRadioTechChange() { // register for radio tech change to listen to radio tech handover. if (!mIsRegisteredForImsRadioTechChange) { for (int i = 0; i < mActiveModemCount; i++) { registerForImsRadioTechChange(mContext, i); } } } private void evaluateIfDataSwitchIsNeeded(String reason) { if (onEvaluate(REQUESTS_UNCHANGED, reason)) { logDataSwitchEvent(mPreferredDataSubId.get(), TelephonyEvent.EventState.EVENT_STATE_START, DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); registerDefaultNetworkChangeCallback(mPreferredDataSubId.get(), DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); } } @VisibleForTesting public PhoneSwitcher(int maxActivePhones, Context context, Looper looper) { super(looper); Loading Loading @@ -428,6 +486,7 @@ public class PhoneSwitcher extends Handler { } PhoneFactory.getPhone(i).getDataEnabledSettings().registerForDataEnabledChanged( this, EVENT_DATA_ENABLED_CHANGED, null); registerForImsRadioTechChange(context, i); } Set<CommandException.Error> ddsFailure = new HashSet<CommandException.Error>(); mCurrentDdsSwitchFailure.add(ddsFailure); Loading Loading @@ -590,11 +649,26 @@ public class PhoneSwitcher extends Handler { onEvaluate(REQUESTS_UNCHANGED, "EVENT_RADIO_AVAILABLE"); break; } case EVENT_IMS_RADIO_TECH_CHANGED: // register for radio tech change to listen to radio tech handover in case previous // attempt was not successful registerForImsRadioTechChange(); // If the phoneId in voice call didn't change, do nothing. if (!isPhoneInVoiceCallChanged()) { break; } evaluateIfDataSwitchIsNeeded("EVENT_IMS_RADIO_TECH_CHANGED"); break; case EVENT_PRECISE_CALL_STATE_CHANGED: { log("EVENT_PRECISE_CALL_STATE_CHANGED"); // register for radio tech change to listen to radio tech handover in case previous // attempt was not successful registerForImsRadioTechChange(); // If the phoneId in voice call didn't change, do nothing. if (!isPhoneInVoiceCallChanged()) break; if (!isPhoneInVoiceCallChanged()) { break; } if (!isAnyVoiceCallActiveOnDevice()) { for (int i = 0; i < mActiveModemCount; i++) { Loading @@ -621,16 +695,12 @@ public class PhoneSwitcher extends Handler { mEmergencyOverride.mPendingOriginatingCall = false; } } evaluateIfDataSwitchIsNeeded("EVENT_PRECISE_CALL_STATE_CHANGED"); break; } // fall through case EVENT_DATA_ENABLED_CHANGED: if (onEvaluate(REQUESTS_UNCHANGED, "EVENT_PRECISE_CALL_STATE_CHANGED")) { logDataSwitchEvent(mPreferredDataSubId.get(), TelephonyEvent.EventState.EVENT_STATE_START, DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); registerDefaultNetworkChangeCallback(mPreferredDataSubId.get(), DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); } evaluateIfDataSwitchIsNeeded("EVENT_DATA_ENABLED_CHANGED"); break; case EVENT_NETWORK_VALIDATION_DONE: { int subId = msg.arg1; Loading Loading @@ -775,6 +845,7 @@ public class PhoneSwitcher extends Handler { Set<CommandException.Error> ddsFailure = new HashSet<CommandException.Error>(); mCurrentDdsSwitchFailure.add(ddsFailure); registerForImsRadioTechChange(mContext, phoneId); } } Loading tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java +43 −0 Original line number Diff line number Diff line Loading @@ -23,11 +23,13 @@ import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_INACTIVE_ import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS; import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED; import static android.telephony.TelephonyManager.SIM_STATE_LOADED; import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM; import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN; import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_LTE; import static com.android.internal.telephony.PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS; import static com.android.internal.telephony.PhoneSwitcher.EVENT_DATA_ENABLED_CHANGED; import static com.android.internal.telephony.PhoneSwitcher.EVENT_IMS_RADIO_TECH_CHANGED; import static com.android.internal.telephony.PhoneSwitcher.EVENT_MULTI_SIM_CONFIG_CHANGED; import static com.android.internal.telephony.PhoneSwitcher.EVENT_PRECISE_CALL_STATE_CHANGED; Loading Loading @@ -636,6 +638,42 @@ public class PhoneSwitcherTest extends TelephonyTest { assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId()); } @Test @SmallTest public void testNonDefaultDataPhoneInCall_ImsCallOnCrossSIM_HandoverToLTE() throws Exception { initialize(); setAllPhonesInactive(); // Phone 0 has sub 1, phone 1 has sub 2. // Sub 1 is default data sub. // Both are active subscriptions are active sub, as they are in both active slots. setSlotIndexToSubId(0, 1); setSlotIndexToSubId(1, 2); setDefaultDataSubId(1); processAllMessages(); // Phone 0 should be the default data phoneId. assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId()); // Phone 1 has active IMS call on CROSS_SIM. And data of DEFAULT apn is enabled. This should // not trigger data switch. doReturn(mImsPhone).when(mPhone2).getImsPhone(); doReturn(true).when(mDataEnabledSettings2).isDataEnabled(ApnSetting.TYPE_DEFAULT); mockImsRegTech(1, REGISTRATION_TECH_CROSS_SIM); notifyPhoneAsInCall(mImsPhone); // Phone 0 should remain the default data phone. assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId()); // Phone 1 has has handed over the call to LTE. And data of DEFAULT apn is enabled. // This should trigger data switch. mockImsRegTech(1, REGISTRATION_TECH_LTE); notifyImsRegistrationTechChange(mPhone2); // Phone 1 should become the default data phone. assertEquals(1, mPhoneSwitcher.getPreferredDataPhoneId()); } @Test @SmallTest public void testNonDefaultDataPhoneInCall() throws Exception { Loading Loading @@ -1212,6 +1250,11 @@ public class PhoneSwitcherTest extends TelephonyTest { processAllMessages(); } private void notifyImsRegistrationTechChange(Phone phone) { mPhoneSwitcher.sendEmptyMessage(EVENT_IMS_RADIO_TECH_CHANGED); processAllMessages(); } private Message getEcbmRegistration(Phone phone) { ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class); ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class); Loading Loading
src/java/com/android/internal/telephony/PhoneSwitcher.java +81 −10 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS; import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED; import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM; import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN; import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NONE; import static java.util.Arrays.copyOf; Loading Loading @@ -59,9 +60,13 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.TelephonyRegistryManager; import android.telephony.data.ApnSetting; import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsRegistrationAttributes; import android.telephony.ims.RegistrationManager; import android.telephony.ims.stub.ImsRegistrationImplBase; import android.util.LocalLog; import com.android.ims.ImsException; import com.android.ims.ImsManager; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.SubscriptionController.WatchedInt; Loading Loading @@ -170,6 +175,7 @@ public class PhoneSwitcher extends Handler { private final LocalLog mLocalLog; protected PhoneState[] mPhoneStates; protected int[] mPhoneSubscriptions; private boolean mIsRegisteredForImsRadioTechChange; @VisibleForTesting protected final CellularNetworkValidator mValidator; private int mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID; Loading Loading @@ -275,6 +281,8 @@ public class PhoneSwitcher extends Handler { public static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 117; private static final int EVENT_NETWORK_AVAILABLE = 118; private static final int EVENT_PROCESS_SIM_STATE_CHANGE = 119; @VisibleForTesting public static final int EVENT_IMS_RADIO_TECH_CHANGED = 120; // Depending on version of IRadioConfig, we need to send either RIL_REQUEST_ALLOW_DATA if it's // 1.0, or RIL_REQUEST_SET_PREFERRED_DATA if it's 1.1 or later. So internally mHalCommandToUse Loading @@ -294,6 +302,7 @@ public class PhoneSwitcher extends Handler { private Boolean mHasRegisteredDefaultNetworkChangeCallback = false; private ConnectivityManager mConnectivityManager; private int mImsRegistrationTech = REGISTRATION_TECH_NONE; private List<Set<CommandException.Error>> mCurrentDdsSwitchFailure; Loading @@ -316,6 +325,26 @@ public class PhoneSwitcher extends Handler { } } private RegistrationManager.RegistrationCallback mRegistrationCallback = new RegistrationManager.RegistrationCallback() { @Override public void onRegistered(ImsRegistrationAttributes attributes) { int imsRegistrationTech = attributes.getRegistrationTechnology(); if (imsRegistrationTech != mImsRegistrationTech) { mImsRegistrationTech = imsRegistrationTech; sendMessage(obtainMessage(EVENT_IMS_RADIO_TECH_CHANGED)); } } @Override public void onUnregistered(ImsReasonInfo info) { if (mImsRegistrationTech != REGISTRATION_TECH_NONE) { mImsRegistrationTech = REGISTRATION_TECH_NONE; sendMessage(obtainMessage(EVENT_IMS_RADIO_TECH_CHANGED)); } } }; private final DefaultNetworkCallback mDefaultNetworkCallback = new DefaultNetworkCallback(); /** Loading Loading @@ -394,6 +423,35 @@ public class PhoneSwitcher extends Handler { } } private void registerForImsRadioTechChange(Context context, int phoneId) { try { ImsManager.getInstance(context, phoneId).addRegistrationCallback( mRegistrationCallback, this::post); mIsRegisteredForImsRadioTechChange = true; } catch (ImsException imsException) { mIsRegisteredForImsRadioTechChange = false; } } private void registerForImsRadioTechChange() { // register for radio tech change to listen to radio tech handover. if (!mIsRegisteredForImsRadioTechChange) { for (int i = 0; i < mActiveModemCount; i++) { registerForImsRadioTechChange(mContext, i); } } } private void evaluateIfDataSwitchIsNeeded(String reason) { if (onEvaluate(REQUESTS_UNCHANGED, reason)) { logDataSwitchEvent(mPreferredDataSubId.get(), TelephonyEvent.EventState.EVENT_STATE_START, DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); registerDefaultNetworkChangeCallback(mPreferredDataSubId.get(), DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); } } @VisibleForTesting public PhoneSwitcher(int maxActivePhones, Context context, Looper looper) { super(looper); Loading Loading @@ -428,6 +486,7 @@ public class PhoneSwitcher extends Handler { } PhoneFactory.getPhone(i).getDataEnabledSettings().registerForDataEnabledChanged( this, EVENT_DATA_ENABLED_CHANGED, null); registerForImsRadioTechChange(context, i); } Set<CommandException.Error> ddsFailure = new HashSet<CommandException.Error>(); mCurrentDdsSwitchFailure.add(ddsFailure); Loading Loading @@ -590,11 +649,26 @@ public class PhoneSwitcher extends Handler { onEvaluate(REQUESTS_UNCHANGED, "EVENT_RADIO_AVAILABLE"); break; } case EVENT_IMS_RADIO_TECH_CHANGED: // register for radio tech change to listen to radio tech handover in case previous // attempt was not successful registerForImsRadioTechChange(); // If the phoneId in voice call didn't change, do nothing. if (!isPhoneInVoiceCallChanged()) { break; } evaluateIfDataSwitchIsNeeded("EVENT_IMS_RADIO_TECH_CHANGED"); break; case EVENT_PRECISE_CALL_STATE_CHANGED: { log("EVENT_PRECISE_CALL_STATE_CHANGED"); // register for radio tech change to listen to radio tech handover in case previous // attempt was not successful registerForImsRadioTechChange(); // If the phoneId in voice call didn't change, do nothing. if (!isPhoneInVoiceCallChanged()) break; if (!isPhoneInVoiceCallChanged()) { break; } if (!isAnyVoiceCallActiveOnDevice()) { for (int i = 0; i < mActiveModemCount; i++) { Loading @@ -621,16 +695,12 @@ public class PhoneSwitcher extends Handler { mEmergencyOverride.mPendingOriginatingCall = false; } } evaluateIfDataSwitchIsNeeded("EVENT_PRECISE_CALL_STATE_CHANGED"); break; } // fall through case EVENT_DATA_ENABLED_CHANGED: if (onEvaluate(REQUESTS_UNCHANGED, "EVENT_PRECISE_CALL_STATE_CHANGED")) { logDataSwitchEvent(mPreferredDataSubId.get(), TelephonyEvent.EventState.EVENT_STATE_START, DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); registerDefaultNetworkChangeCallback(mPreferredDataSubId.get(), DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); } evaluateIfDataSwitchIsNeeded("EVENT_DATA_ENABLED_CHANGED"); break; case EVENT_NETWORK_VALIDATION_DONE: { int subId = msg.arg1; Loading Loading @@ -775,6 +845,7 @@ public class PhoneSwitcher extends Handler { Set<CommandException.Error> ddsFailure = new HashSet<CommandException.Error>(); mCurrentDdsSwitchFailure.add(ddsFailure); registerForImsRadioTechChange(mContext, phoneId); } } Loading
tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java +43 −0 Original line number Diff line number Diff line Loading @@ -23,11 +23,13 @@ import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_INACTIVE_ import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS; import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED; import static android.telephony.TelephonyManager.SIM_STATE_LOADED; import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM; import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN; import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_LTE; import static com.android.internal.telephony.PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS; import static com.android.internal.telephony.PhoneSwitcher.EVENT_DATA_ENABLED_CHANGED; import static com.android.internal.telephony.PhoneSwitcher.EVENT_IMS_RADIO_TECH_CHANGED; import static com.android.internal.telephony.PhoneSwitcher.EVENT_MULTI_SIM_CONFIG_CHANGED; import static com.android.internal.telephony.PhoneSwitcher.EVENT_PRECISE_CALL_STATE_CHANGED; Loading Loading @@ -636,6 +638,42 @@ public class PhoneSwitcherTest extends TelephonyTest { assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId()); } @Test @SmallTest public void testNonDefaultDataPhoneInCall_ImsCallOnCrossSIM_HandoverToLTE() throws Exception { initialize(); setAllPhonesInactive(); // Phone 0 has sub 1, phone 1 has sub 2. // Sub 1 is default data sub. // Both are active subscriptions are active sub, as they are in both active slots. setSlotIndexToSubId(0, 1); setSlotIndexToSubId(1, 2); setDefaultDataSubId(1); processAllMessages(); // Phone 0 should be the default data phoneId. assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId()); // Phone 1 has active IMS call on CROSS_SIM. And data of DEFAULT apn is enabled. This should // not trigger data switch. doReturn(mImsPhone).when(mPhone2).getImsPhone(); doReturn(true).when(mDataEnabledSettings2).isDataEnabled(ApnSetting.TYPE_DEFAULT); mockImsRegTech(1, REGISTRATION_TECH_CROSS_SIM); notifyPhoneAsInCall(mImsPhone); // Phone 0 should remain the default data phone. assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId()); // Phone 1 has has handed over the call to LTE. And data of DEFAULT apn is enabled. // This should trigger data switch. mockImsRegTech(1, REGISTRATION_TECH_LTE); notifyImsRegistrationTechChange(mPhone2); // Phone 1 should become the default data phone. assertEquals(1, mPhoneSwitcher.getPreferredDataPhoneId()); } @Test @SmallTest public void testNonDefaultDataPhoneInCall() throws Exception { Loading Loading @@ -1212,6 +1250,11 @@ public class PhoneSwitcherTest extends TelephonyTest { processAllMessages(); } private void notifyImsRegistrationTechChange(Phone phone) { mPhoneSwitcher.sendEmptyMessage(EVENT_IMS_RADIO_TECH_CHANGED); processAllMessages(); } private Message getEcbmRegistration(Phone phone) { ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class); ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class); Loading