Loading src/java/com/android/internal/telephony/imsphone/ImsPhone.java +72 −32 Original line number Original line Diff line number Diff line Loading @@ -60,6 +60,7 @@ import android.os.RegistrantList; import android.os.ResultReceiver; import android.os.ResultReceiver; import android.os.SystemProperties; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserHandle; import android.telephony.AccessNetworkConstants; import android.telephony.CarrierConfigManager; import android.telephony.CarrierConfigManager; import android.telephony.NetworkRegistrationInfo; import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneNumberUtils; import android.telephony.PhoneNumberUtils; Loading Loading @@ -92,9 +93,11 @@ import com.android.internal.telephony.MmiCode; import com.android.internal.telephony.Phone; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.PhoneNotifier; import com.android.internal.telephony.PhoneNotifier; import com.android.internal.telephony.ServiceStateTracker; import com.android.internal.telephony.TelephonyComponentFactory; import com.android.internal.telephony.TelephonyComponentFactory; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyProperties; import com.android.internal.telephony.TelephonyProperties; import com.android.internal.telephony.dataconnection.TransportManager; import com.android.internal.telephony.gsm.GsmMmiCode; import com.android.internal.telephony.gsm.GsmMmiCode; import com.android.internal.telephony.gsm.SuppServiceNotification; import com.android.internal.telephony.gsm.SuppServiceNotification; import com.android.internal.telephony.uicc.IccRecords; import com.android.internal.telephony.uicc.IccRecords; Loading @@ -120,7 +123,8 @@ public class ImsPhone extends ImsPhoneBase { private static final int EVENT_SET_CLIR_DONE = EVENT_LAST + 5; private static final int EVENT_SET_CLIR_DONE = EVENT_LAST + 5; private static final int EVENT_GET_CLIR_DONE = EVENT_LAST + 6; private static final int EVENT_GET_CLIR_DONE = EVENT_LAST + 6; private static final int EVENT_DEFAULT_PHONE_DATA_STATE_CHANGED = EVENT_LAST + 7; private static final int EVENT_DEFAULT_PHONE_DATA_STATE_CHANGED = EVENT_LAST + 7; private static final int EVENT_SERVICE_STATE_CHANGED = EVENT_LAST + 8; @VisibleForTesting public static final int EVENT_SERVICE_STATE_CHANGED = EVENT_LAST + 8; private static final int EVENT_VOICE_CALL_ENDED = EVENT_LAST + 9; private static final int EVENT_VOICE_CALL_ENDED = EVENT_LAST + 9; static final int RESTART_ECM_TIMER = 0; // restart Ecm timer static final int RESTART_ECM_TIMER = 0; // restart Ecm timer Loading Loading @@ -1497,25 +1501,16 @@ public class ImsPhone extends ImsPhoneBase { if (VDBG) logd("EVENT_SERVICE_STATE_CHANGED"); if (VDBG) logd("EVENT_SERVICE_STATE_CHANGED"); ar = (AsyncResult) msg.obj; ar = (AsyncResult) msg.obj; ServiceState newServiceState = (ServiceState) ar.result; ServiceState newServiceState = (ServiceState) ar.result; // only update if roaming status changed updateRoamingState(newServiceState); if (mRoaming != newServiceState.getRoaming()) { if (DBG) logd("Roaming state changed - " + mRoaming); // Update WFC mode only if voice or data is in service. // The STATE_IN_SERVICE is checked to prevent wifi calling mode change // when phone moves from roaming to no service. boolean isInService = (newServiceState.getVoiceRegState() == ServiceState.STATE_IN_SERVICE || newServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE); updateRoamingState(newServiceState.getRoaming(), isInService); } break; break; case EVENT_VOICE_CALL_ENDED: case EVENT_VOICE_CALL_ENDED: if (DBG) logd("Voice call ended. Handle pending updateRoamingState."); if (DBG) logd("Voice call ended. Handle pending updateRoamingState."); mCT.unregisterForVoiceCallEnded(this); mCT.unregisterForVoiceCallEnded(this); // only update if roaming status changed // Get the current unmodified ServiceState from the tracker, as it has more info boolean newRoaming = getCurrentRoaming(); // about the cell roaming state. if (mRoaming != newRoaming) { ServiceStateTracker sst = getDefaultPhone().getServiceStateTracker(); updateRoamingState(newRoaming, true); if (sst != null) { updateRoamingState(sst.mSS); } } break; break; Loading Loading @@ -1888,27 +1883,72 @@ public class ImsPhone extends ImsPhoneBase { return mCT.getVtDataUsage(perUidStats); return mCT.getVtDataUsage(perUidStats); } } private void updateRoamingState(boolean newRoaming, boolean isInService) { /** * Update roaming state and WFC mode in the following situations: * 1) voice is in service. * 2) data is in service and it is not IWLAN (if in legacy mode). * @param ss non-null ServiceState */ private void updateRoamingState(ServiceState ss) { if (ss == null) { loge("updateRoamingState: null ServiceState!"); return; } boolean newRoamingState = ss.getRoaming(); // Do not recalculate if there is no change to state. if (mRoaming == newRoamingState) { return; } boolean isInService = (ss.getVoiceRegState() == ServiceState.STATE_IN_SERVICE || ss.getDataRegState() == ServiceState.STATE_IN_SERVICE); // If we are not IN_SERVICE for voice or data, ignore change roaming state, as we always // move to home in this case. if (!isInService) { logi("updateRoamingState: we are OUT_OF_SERVICE, ignoring roaming change."); return; } // We ignore roaming changes when moving to IWLAN because it always sets the roaming // mode to home and masks the actual cellular roaming status if voice is not registered. If // we just moved to IWLAN because WFC roaming mode is IWLAN preferred and WFC home mode is // cell preferred, we can get into a condition where the modem keeps bouncing between // IWLAN->cell->IWLAN->cell... if (isCsNotInServiceAndPsWwanReportingWlan(ss)) { logi("updateRoamingState: IWLAN masking roaming, ignore roaming change."); return; } if (mCT.getState() == PhoneConstants.State.IDLE) { if (mCT.getState() == PhoneConstants.State.IDLE) { if (DBG) logd("updateRoamingState now: " + newRoaming); if (DBG) logd("updateRoamingState now: " + newRoamingState); mRoaming = newRoaming; mRoaming = newRoamingState; if (isInService) { ImsManager imsManager = ImsManager.getInstance(mContext, mPhoneId); ImsManager imsManager = ImsManager.getInstance(mContext, mPhoneId); imsManager.setWfcMode(imsManager.getWfcMode(newRoaming), newRoaming); imsManager.setWfcMode(imsManager.getWfcMode(newRoamingState), newRoamingState); } else { } else { if (DBG) Rlog.d(LOG_TAG, "updateRoamingState service state is OUT_OF_SERVICE"); if (DBG) logd("updateRoamingState postponed: " + newRoamingState); } mCT.registerForVoiceCallEnded(this, EVENT_VOICE_CALL_ENDED, null); } else { if (DBG) logd("updateRoamingState postponed: " + newRoaming); mCT.registerForVoiceCallEnded(this, EVENT_VOICE_CALL_ENDED, null); } } } } private boolean getCurrentRoaming() { /** TelephonyManager tm = (TelephonyManager) mContext * In legacy mode, data registration will report IWLAN when we are using WLAN for data, .getSystemService(Context.TELEPHONY_SERVICE); * effectively masking the true roaming state of the device if voice is not registered. return tm.isNetworkRoaming(getSubId()); * * @return true if we are reporting not in service for CS domain over WWAN transport and WLAN * for PS domain over WWAN transport. */ private boolean isCsNotInServiceAndPsWwanReportingWlan(ServiceState ss) { TransportManager tm = mDefaultPhone.getTransportManager(); // We can not get into this condition if we are in AP-Assisted mode. if (tm == null || !tm.isInLegacyMode()) { return false; } NetworkRegistrationInfo csInfo = ss.getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); NetworkRegistrationInfo psInfo = ss.getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); // We will return roaming state correctly if the CS domain is in service because // ss.getRoaming() returns isVoiceRoaming||isDataRoaming result and isDataRoaming==false // when the modem reports IWLAN RAT. return psInfo != null && csInfo != null && !csInfo.isInService() && psInfo.getAccessNetworkTechnology() == TelephonyManager.NETWORK_TYPE_IWLAN; } } @Override @Override Loading tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java +164 −0 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static com.android.internal.telephony.TelephonyTestUtils.waitForMs; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Matchers.any; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyChar; import static org.mockito.Matchers.anyChar; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyInt; Loading Loading @@ -643,4 +644,167 @@ public class ImsPhoneTest extends TelephonyTest { assertEquals(messageNotification, assertEquals(messageNotification, intent.getValue().getStringExtra(Phone.EXTRA_KEY_NOTIFICATION_MESSAGE)); intent.getValue().getStringExtra(Phone.EXTRA_KEY_NOTIFICATION_MESSAGE)); } } @Test @SmallTest public void testRoamingDuplicateMessages() throws Exception { doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState(); //roaming - data registration only on LTE Message m = getServiceStateChangedMessage(getServiceStateDataOnly( ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.STATE_IN_SERVICE, true)); // Inject the message synchronously instead of waiting for the thread to do it. mImsPhoneUT.handleMessage(m); verify(mImsManager, times(1)).setWfcMode(anyInt(), eq(true)); // Send a duplicate message mImsPhoneUT.handleMessage(m); m.recycle(); // setWfcMode should not be called again. verify(mImsManager, times(1)).setWfcMode(anyInt(), anyBoolean()); } @Test @SmallTest public void testRoamingToOutOfService() throws Exception { doReturn(true).when(mTransportManager).isInLegacyMode(); doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState(); //roaming - data registration only on LTE Message m = getServiceStateChangedMessage(getServiceStateDataOnly( ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.STATE_IN_SERVICE, true)); // Inject the message synchronously instead of waiting for the thread to do it. mImsPhoneUT.handleMessage(m); m.recycle(); verify(mImsManager, times(1)).setWfcMode(anyInt(), eq(true)); // move to out of service m = getServiceStateChangedMessage(getServiceStateOutOfService()); mImsPhoneUT.handleMessage(m); m.recycle(); // setWfcMode should not be called again, out_of_service should not trigger move out of // roaming. verify(mImsManager, times(1)).setWfcMode(anyInt(), anyBoolean()); } @Test @SmallTest public void testRoamingChangeForLteInLegacyMode() throws Exception { doReturn(true).when(mTransportManager).isInLegacyMode(); doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState(); //roaming - data registration only on LTE Message m = getServiceStateChangedMessage(getServiceStateDataOnly( ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.STATE_IN_SERVICE, true)); // Inject the message synchronously instead of waiting for the thread to do it. mImsPhoneUT.handleMessage(m); m.recycle(); verify(mImsManager, times(1)).setWfcMode(anyInt(), eq(true)); // not roaming - data registration on LTE m = getServiceStateChangedMessage(getServiceStateDataOnly( ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.STATE_IN_SERVICE, false)); mImsPhoneUT.handleMessage(m); m.recycle(); verify(mImsManager, times(1)).setWfcMode(anyInt(), eq(false)); } @Test @SmallTest public void testDataOnlyRoamingCellToIWlanInLegacyMode() throws Exception { doReturn(true).when(mTransportManager).isInLegacyMode(); doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState(); //roaming - data registration only on LTE Message m = getServiceStateChangedMessage(getServiceStateDataOnly( ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.STATE_IN_SERVICE, true)); // Inject the message synchronously instead of waiting for the thread to do it. mImsPhoneUT.handleMessage(m); m.recycle(); verify(mImsManager, times(1)).setWfcMode(anyInt(), eq(true)); // not roaming - data registration onto IWLAN m = getServiceStateChangedMessage(getServiceStateDataOnly( ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN, ServiceState.STATE_IN_SERVICE, false)); mImsPhoneUT.handleMessage(m); m.recycle(); // Verify that it hasn't been called again. verify(mImsManager, times(1)).setWfcMode(anyInt(), anyBoolean()); } @Test @SmallTest public void testCellVoiceDataChangeToWlanInLegacyMode() throws Exception { doReturn(true).when(mTransportManager).isInLegacyMode(); doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState(); //roaming - voice/data registration on LTE ServiceState ss = getServiceStateDataAndVoice( ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.STATE_IN_SERVICE, true); Message m = getServiceStateChangedMessage(ss); // Inject the message synchronously instead of waiting for the thread to do it. mImsPhoneUT.handleMessage(m); verify(mImsManager, times(1)).setWfcMode(anyInt(), eq(true)); // roaming - voice LTE, data registration onto IWLAN modifyServiceStateData(ss, ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN, ServiceState.STATE_IN_SERVICE, false); mImsPhoneUT.handleMessage(m); m.recycle(); // Verify that it hasn't been called again. verify(mImsManager, times(1)).setWfcMode(anyInt(), anyBoolean()); } private ServiceState getServiceStateDataAndVoice(int rat, int regState, boolean isRoaming) { ServiceState ss = new ServiceState(); ss.setStateOutOfService(); ss.setDataRegState(regState); ss.setDataRoaming(isRoaming); ss.setRilDataRadioTechnology(rat); ss.setVoiceRegState(regState); ss.setVoiceRoaming(isRoaming); ss.setRilVoiceRadioTechnology(rat); return ss; } private ServiceState getServiceStateDataOnly(int rat, int regState, boolean isRoaming) { ServiceState ss = new ServiceState(); ss.setStateOutOfService(); ss.setDataRegState(regState); ss.setDataRoaming(isRoaming); ss.setRilDataRadioTechnology(rat); return ss; } private ServiceState modifyServiceStateData(ServiceState ss, int rat, int regState, boolean isRoaming) { ss.setStateOutOfService(); ss.setDataRegState(regState); ss.setDataRoaming(isRoaming); ss.setRilDataRadioTechnology(rat); return ss; } private ServiceState getServiceStateOutOfService() { ServiceState ss = new ServiceState(); ss.setStateOutOfService(); return ss; } private Message getServiceStateChangedMessage(ServiceState ss) { Message m = Message.obtain(mImsPhoneUT.getHandler(), ImsPhone.EVENT_SERVICE_STATE_CHANGED); m.obj = AsyncResult.forMessage(m, ss, null); return m; } } } Loading
src/java/com/android/internal/telephony/imsphone/ImsPhone.java +72 −32 Original line number Original line Diff line number Diff line Loading @@ -60,6 +60,7 @@ import android.os.RegistrantList; import android.os.ResultReceiver; import android.os.ResultReceiver; import android.os.SystemProperties; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserHandle; import android.telephony.AccessNetworkConstants; import android.telephony.CarrierConfigManager; import android.telephony.CarrierConfigManager; import android.telephony.NetworkRegistrationInfo; import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneNumberUtils; import android.telephony.PhoneNumberUtils; Loading Loading @@ -92,9 +93,11 @@ import com.android.internal.telephony.MmiCode; import com.android.internal.telephony.Phone; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.PhoneNotifier; import com.android.internal.telephony.PhoneNotifier; import com.android.internal.telephony.ServiceStateTracker; import com.android.internal.telephony.TelephonyComponentFactory; import com.android.internal.telephony.TelephonyComponentFactory; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyProperties; import com.android.internal.telephony.TelephonyProperties; import com.android.internal.telephony.dataconnection.TransportManager; import com.android.internal.telephony.gsm.GsmMmiCode; import com.android.internal.telephony.gsm.GsmMmiCode; import com.android.internal.telephony.gsm.SuppServiceNotification; import com.android.internal.telephony.gsm.SuppServiceNotification; import com.android.internal.telephony.uicc.IccRecords; import com.android.internal.telephony.uicc.IccRecords; Loading @@ -120,7 +123,8 @@ public class ImsPhone extends ImsPhoneBase { private static final int EVENT_SET_CLIR_DONE = EVENT_LAST + 5; private static final int EVENT_SET_CLIR_DONE = EVENT_LAST + 5; private static final int EVENT_GET_CLIR_DONE = EVENT_LAST + 6; private static final int EVENT_GET_CLIR_DONE = EVENT_LAST + 6; private static final int EVENT_DEFAULT_PHONE_DATA_STATE_CHANGED = EVENT_LAST + 7; private static final int EVENT_DEFAULT_PHONE_DATA_STATE_CHANGED = EVENT_LAST + 7; private static final int EVENT_SERVICE_STATE_CHANGED = EVENT_LAST + 8; @VisibleForTesting public static final int EVENT_SERVICE_STATE_CHANGED = EVENT_LAST + 8; private static final int EVENT_VOICE_CALL_ENDED = EVENT_LAST + 9; private static final int EVENT_VOICE_CALL_ENDED = EVENT_LAST + 9; static final int RESTART_ECM_TIMER = 0; // restart Ecm timer static final int RESTART_ECM_TIMER = 0; // restart Ecm timer Loading Loading @@ -1497,25 +1501,16 @@ public class ImsPhone extends ImsPhoneBase { if (VDBG) logd("EVENT_SERVICE_STATE_CHANGED"); if (VDBG) logd("EVENT_SERVICE_STATE_CHANGED"); ar = (AsyncResult) msg.obj; ar = (AsyncResult) msg.obj; ServiceState newServiceState = (ServiceState) ar.result; ServiceState newServiceState = (ServiceState) ar.result; // only update if roaming status changed updateRoamingState(newServiceState); if (mRoaming != newServiceState.getRoaming()) { if (DBG) logd("Roaming state changed - " + mRoaming); // Update WFC mode only if voice or data is in service. // The STATE_IN_SERVICE is checked to prevent wifi calling mode change // when phone moves from roaming to no service. boolean isInService = (newServiceState.getVoiceRegState() == ServiceState.STATE_IN_SERVICE || newServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE); updateRoamingState(newServiceState.getRoaming(), isInService); } break; break; case EVENT_VOICE_CALL_ENDED: case EVENT_VOICE_CALL_ENDED: if (DBG) logd("Voice call ended. Handle pending updateRoamingState."); if (DBG) logd("Voice call ended. Handle pending updateRoamingState."); mCT.unregisterForVoiceCallEnded(this); mCT.unregisterForVoiceCallEnded(this); // only update if roaming status changed // Get the current unmodified ServiceState from the tracker, as it has more info boolean newRoaming = getCurrentRoaming(); // about the cell roaming state. if (mRoaming != newRoaming) { ServiceStateTracker sst = getDefaultPhone().getServiceStateTracker(); updateRoamingState(newRoaming, true); if (sst != null) { updateRoamingState(sst.mSS); } } break; break; Loading Loading @@ -1888,27 +1883,72 @@ public class ImsPhone extends ImsPhoneBase { return mCT.getVtDataUsage(perUidStats); return mCT.getVtDataUsage(perUidStats); } } private void updateRoamingState(boolean newRoaming, boolean isInService) { /** * Update roaming state and WFC mode in the following situations: * 1) voice is in service. * 2) data is in service and it is not IWLAN (if in legacy mode). * @param ss non-null ServiceState */ private void updateRoamingState(ServiceState ss) { if (ss == null) { loge("updateRoamingState: null ServiceState!"); return; } boolean newRoamingState = ss.getRoaming(); // Do not recalculate if there is no change to state. if (mRoaming == newRoamingState) { return; } boolean isInService = (ss.getVoiceRegState() == ServiceState.STATE_IN_SERVICE || ss.getDataRegState() == ServiceState.STATE_IN_SERVICE); // If we are not IN_SERVICE for voice or data, ignore change roaming state, as we always // move to home in this case. if (!isInService) { logi("updateRoamingState: we are OUT_OF_SERVICE, ignoring roaming change."); return; } // We ignore roaming changes when moving to IWLAN because it always sets the roaming // mode to home and masks the actual cellular roaming status if voice is not registered. If // we just moved to IWLAN because WFC roaming mode is IWLAN preferred and WFC home mode is // cell preferred, we can get into a condition where the modem keeps bouncing between // IWLAN->cell->IWLAN->cell... if (isCsNotInServiceAndPsWwanReportingWlan(ss)) { logi("updateRoamingState: IWLAN masking roaming, ignore roaming change."); return; } if (mCT.getState() == PhoneConstants.State.IDLE) { if (mCT.getState() == PhoneConstants.State.IDLE) { if (DBG) logd("updateRoamingState now: " + newRoaming); if (DBG) logd("updateRoamingState now: " + newRoamingState); mRoaming = newRoaming; mRoaming = newRoamingState; if (isInService) { ImsManager imsManager = ImsManager.getInstance(mContext, mPhoneId); ImsManager imsManager = ImsManager.getInstance(mContext, mPhoneId); imsManager.setWfcMode(imsManager.getWfcMode(newRoaming), newRoaming); imsManager.setWfcMode(imsManager.getWfcMode(newRoamingState), newRoamingState); } else { } else { if (DBG) Rlog.d(LOG_TAG, "updateRoamingState service state is OUT_OF_SERVICE"); if (DBG) logd("updateRoamingState postponed: " + newRoamingState); } mCT.registerForVoiceCallEnded(this, EVENT_VOICE_CALL_ENDED, null); } else { if (DBG) logd("updateRoamingState postponed: " + newRoaming); mCT.registerForVoiceCallEnded(this, EVENT_VOICE_CALL_ENDED, null); } } } } private boolean getCurrentRoaming() { /** TelephonyManager tm = (TelephonyManager) mContext * In legacy mode, data registration will report IWLAN when we are using WLAN for data, .getSystemService(Context.TELEPHONY_SERVICE); * effectively masking the true roaming state of the device if voice is not registered. return tm.isNetworkRoaming(getSubId()); * * @return true if we are reporting not in service for CS domain over WWAN transport and WLAN * for PS domain over WWAN transport. */ private boolean isCsNotInServiceAndPsWwanReportingWlan(ServiceState ss) { TransportManager tm = mDefaultPhone.getTransportManager(); // We can not get into this condition if we are in AP-Assisted mode. if (tm == null || !tm.isInLegacyMode()) { return false; } NetworkRegistrationInfo csInfo = ss.getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); NetworkRegistrationInfo psInfo = ss.getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); // We will return roaming state correctly if the CS domain is in service because // ss.getRoaming() returns isVoiceRoaming||isDataRoaming result and isDataRoaming==false // when the modem reports IWLAN RAT. return psInfo != null && csInfo != null && !csInfo.isInService() && psInfo.getAccessNetworkTechnology() == TelephonyManager.NETWORK_TYPE_IWLAN; } } @Override @Override Loading
tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java +164 −0 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static com.android.internal.telephony.TelephonyTestUtils.waitForMs; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Matchers.any; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyChar; import static org.mockito.Matchers.anyChar; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyInt; Loading Loading @@ -643,4 +644,167 @@ public class ImsPhoneTest extends TelephonyTest { assertEquals(messageNotification, assertEquals(messageNotification, intent.getValue().getStringExtra(Phone.EXTRA_KEY_NOTIFICATION_MESSAGE)); intent.getValue().getStringExtra(Phone.EXTRA_KEY_NOTIFICATION_MESSAGE)); } } @Test @SmallTest public void testRoamingDuplicateMessages() throws Exception { doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState(); //roaming - data registration only on LTE Message m = getServiceStateChangedMessage(getServiceStateDataOnly( ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.STATE_IN_SERVICE, true)); // Inject the message synchronously instead of waiting for the thread to do it. mImsPhoneUT.handleMessage(m); verify(mImsManager, times(1)).setWfcMode(anyInt(), eq(true)); // Send a duplicate message mImsPhoneUT.handleMessage(m); m.recycle(); // setWfcMode should not be called again. verify(mImsManager, times(1)).setWfcMode(anyInt(), anyBoolean()); } @Test @SmallTest public void testRoamingToOutOfService() throws Exception { doReturn(true).when(mTransportManager).isInLegacyMode(); doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState(); //roaming - data registration only on LTE Message m = getServiceStateChangedMessage(getServiceStateDataOnly( ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.STATE_IN_SERVICE, true)); // Inject the message synchronously instead of waiting for the thread to do it. mImsPhoneUT.handleMessage(m); m.recycle(); verify(mImsManager, times(1)).setWfcMode(anyInt(), eq(true)); // move to out of service m = getServiceStateChangedMessage(getServiceStateOutOfService()); mImsPhoneUT.handleMessage(m); m.recycle(); // setWfcMode should not be called again, out_of_service should not trigger move out of // roaming. verify(mImsManager, times(1)).setWfcMode(anyInt(), anyBoolean()); } @Test @SmallTest public void testRoamingChangeForLteInLegacyMode() throws Exception { doReturn(true).when(mTransportManager).isInLegacyMode(); doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState(); //roaming - data registration only on LTE Message m = getServiceStateChangedMessage(getServiceStateDataOnly( ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.STATE_IN_SERVICE, true)); // Inject the message synchronously instead of waiting for the thread to do it. mImsPhoneUT.handleMessage(m); m.recycle(); verify(mImsManager, times(1)).setWfcMode(anyInt(), eq(true)); // not roaming - data registration on LTE m = getServiceStateChangedMessage(getServiceStateDataOnly( ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.STATE_IN_SERVICE, false)); mImsPhoneUT.handleMessage(m); m.recycle(); verify(mImsManager, times(1)).setWfcMode(anyInt(), eq(false)); } @Test @SmallTest public void testDataOnlyRoamingCellToIWlanInLegacyMode() throws Exception { doReturn(true).when(mTransportManager).isInLegacyMode(); doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState(); //roaming - data registration only on LTE Message m = getServiceStateChangedMessage(getServiceStateDataOnly( ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.STATE_IN_SERVICE, true)); // Inject the message synchronously instead of waiting for the thread to do it. mImsPhoneUT.handleMessage(m); m.recycle(); verify(mImsManager, times(1)).setWfcMode(anyInt(), eq(true)); // not roaming - data registration onto IWLAN m = getServiceStateChangedMessage(getServiceStateDataOnly( ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN, ServiceState.STATE_IN_SERVICE, false)); mImsPhoneUT.handleMessage(m); m.recycle(); // Verify that it hasn't been called again. verify(mImsManager, times(1)).setWfcMode(anyInt(), anyBoolean()); } @Test @SmallTest public void testCellVoiceDataChangeToWlanInLegacyMode() throws Exception { doReturn(true).when(mTransportManager).isInLegacyMode(); doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState(); //roaming - voice/data registration on LTE ServiceState ss = getServiceStateDataAndVoice( ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.STATE_IN_SERVICE, true); Message m = getServiceStateChangedMessage(ss); // Inject the message synchronously instead of waiting for the thread to do it. mImsPhoneUT.handleMessage(m); verify(mImsManager, times(1)).setWfcMode(anyInt(), eq(true)); // roaming - voice LTE, data registration onto IWLAN modifyServiceStateData(ss, ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN, ServiceState.STATE_IN_SERVICE, false); mImsPhoneUT.handleMessage(m); m.recycle(); // Verify that it hasn't been called again. verify(mImsManager, times(1)).setWfcMode(anyInt(), anyBoolean()); } private ServiceState getServiceStateDataAndVoice(int rat, int regState, boolean isRoaming) { ServiceState ss = new ServiceState(); ss.setStateOutOfService(); ss.setDataRegState(regState); ss.setDataRoaming(isRoaming); ss.setRilDataRadioTechnology(rat); ss.setVoiceRegState(regState); ss.setVoiceRoaming(isRoaming); ss.setRilVoiceRadioTechnology(rat); return ss; } private ServiceState getServiceStateDataOnly(int rat, int regState, boolean isRoaming) { ServiceState ss = new ServiceState(); ss.setStateOutOfService(); ss.setDataRegState(regState); ss.setDataRoaming(isRoaming); ss.setRilDataRadioTechnology(rat); return ss; } private ServiceState modifyServiceStateData(ServiceState ss, int rat, int regState, boolean isRoaming) { ss.setStateOutOfService(); ss.setDataRegState(regState); ss.setDataRoaming(isRoaming); ss.setRilDataRadioTechnology(rat); return ss; } private ServiceState getServiceStateOutOfService() { ServiceState ss = new ServiceState(); ss.setStateOutOfService(); return ss; } private Message getServiceStateChangedMessage(ServiceState ss) { Message m = Message.obtain(mImsPhoneUT.getHandler(), ImsPhone.EVENT_SERVICE_STATE_CHANGED); m.obj = AsyncResult.forMessage(m, ss, null); return m; } } }