Loading src/java/com/android/internal/telephony/PhoneSwitcher.java +38 −53 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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, Loading @@ -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); } } Loading Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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. Loading tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java +20 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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)); Loading Loading @@ -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(); } Loading Loading
src/java/com/android/internal/telephony/PhoneSwitcher.java +38 −53 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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, Loading @@ -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); } } Loading Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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. Loading
tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java +20 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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)); Loading Loading @@ -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(); } Loading