Loading src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java +50 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,7 @@ public class EmergencyStateTracker { private EmergencyRegistrationResult mLastEmergencyRegistrationResult; private boolean mIsEmergencyModeInProgress; private boolean mIsEmergencyCallStartedDuringEmergencySms; private boolean mIsWaitingForRadioOff; /** For emergency calls */ private final long mEcmExitTimeoutMs; Loading Loading @@ -268,6 +269,8 @@ public class EmergencyStateTracker { private static final int MSG_EXIT_SCBM = 4; @VisibleForTesting public static final int MSG_NEW_RINGING_CONNECTION = 5; @VisibleForTesting public static final int MSG_VOICE_REG_STATE_CHANGED = 6; private class MyHandler extends Handler { Loading Loading @@ -431,6 +434,16 @@ public class EmergencyStateTracker { handleNewRingingConnection(msg); break; } case MSG_VOICE_REG_STATE_CHANGED: { if (mIsWaitingForRadioOff && isPowerOff()) { unregisterForVoiceRegStateOrRatChanged(); if (mPhone != null) { turnOnRadioAndSwitchDds(mPhone, EMERGENCY_TYPE_CALL, mIsTestEmergencyNumber); } } break; } default: break; } Loading Loading @@ -643,6 +656,7 @@ public class EmergencyStateTracker { mOngoingConnection = null; mOngoingCallProperties = 0; sendEmergencyCallStateChange(mPhone, false); unregisterForVoiceRegStateOrRatChanged(); } if (wasActive && mActiveEmergencyCalls.isEmpty() Loading Loading @@ -1494,6 +1508,34 @@ public class EmergencyStateTracker { return result; } /** * Returns {@code true} if service states of all phones from PhoneFactory are radio off. */ private boolean isPowerOff() { for (Phone phone : mPhoneFactoryProxy.getPhones()) { ServiceState ss = phone.getServiceStateTracker().getServiceState(); if (ss.getState() != ServiceState.STATE_POWER_OFF) return false; } return true; } private void registerForVoiceRegStateOrRatChanged() { if (mIsWaitingForRadioOff) return; for (Phone phone : mPhoneFactoryProxy.getPhones()) { phone.getServiceStateTracker().registerForVoiceRegStateOrRatChanged(mHandler, MSG_VOICE_REG_STATE_CHANGED, null); } mIsWaitingForRadioOff = true; } private void unregisterForVoiceRegStateOrRatChanged() { if (!mIsWaitingForRadioOff) return; for (Phone phone : mPhoneFactoryProxy.getPhones()) { phone.getServiceStateTracker().unregisterForVoiceRegStateOrRatChanged(mHandler); } mIsWaitingForRadioOff = false; } /** * Returns {@code true} if airplane mode is on. */ Loading Loading @@ -1524,6 +1566,14 @@ public class EmergencyStateTracker { final SatelliteController satelliteController = SatelliteController.getInstance(); boolean needToTurnOffSatellite = satelliteController.isSatelliteEnabled(); if (isAirplaneModeOn && !isPowerOff() && !phone.getServiceStateTracker().getDesiredPowerState()) { // power off is delayed to disconnect data connections Rlog.i(TAG, "turnOnRadioAndSwitchDds: wait for the delayed power off"); registerForVoiceRegStateOrRatChanged(); return; } if (needToTurnOnRadio || needToTurnOffSatellite) { Rlog.i(TAG, "turnOnRadioAndSwitchDds: phoneId=" + phone.getPhoneId() + " for " + emergencyTypeToString(emergencyType)); Loading tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java +24 −0 Original line number Diff line number Diff line Loading @@ -3000,6 +3000,30 @@ public class EmergencyStateTrackerTest extends TelephonyTest { verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class)); } /** * Test that the EmergencyStateTracker waits for the delayed radio power off. */ @Test @SmallTest public void startEmergencyCall_delayedRadioOff_waitForRadioOff() { EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker( true /* isSuplDdsSwitchRequiredForEmergencyCall */); // Create test Phones and set radio on Phone testPhone = setupTestPhoneForEmergencyCall(false /* isRoaming */, true /* isRadioOn */); // Airplane mode is ON, but radio power state is still ON Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1); CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone, mTestConnection1, false); // Wait for the radio off for all phones verify(mSST, times(2)).registerForVoiceRegStateOrRatChanged(any(), anyInt(), any()); verify(mRadioOnHelper, never()).triggerRadioOnAndListen(any(), anyBoolean(), any(), anyBoolean(), eq(0)); } private EmergencyStateTracker setupEmergencyStateTracker( boolean isSuplDdsSwitchRequiredForEmergencyCall) { doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher(); Loading Loading
src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java +50 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,7 @@ public class EmergencyStateTracker { private EmergencyRegistrationResult mLastEmergencyRegistrationResult; private boolean mIsEmergencyModeInProgress; private boolean mIsEmergencyCallStartedDuringEmergencySms; private boolean mIsWaitingForRadioOff; /** For emergency calls */ private final long mEcmExitTimeoutMs; Loading Loading @@ -268,6 +269,8 @@ public class EmergencyStateTracker { private static final int MSG_EXIT_SCBM = 4; @VisibleForTesting public static final int MSG_NEW_RINGING_CONNECTION = 5; @VisibleForTesting public static final int MSG_VOICE_REG_STATE_CHANGED = 6; private class MyHandler extends Handler { Loading Loading @@ -431,6 +434,16 @@ public class EmergencyStateTracker { handleNewRingingConnection(msg); break; } case MSG_VOICE_REG_STATE_CHANGED: { if (mIsWaitingForRadioOff && isPowerOff()) { unregisterForVoiceRegStateOrRatChanged(); if (mPhone != null) { turnOnRadioAndSwitchDds(mPhone, EMERGENCY_TYPE_CALL, mIsTestEmergencyNumber); } } break; } default: break; } Loading Loading @@ -643,6 +656,7 @@ public class EmergencyStateTracker { mOngoingConnection = null; mOngoingCallProperties = 0; sendEmergencyCallStateChange(mPhone, false); unregisterForVoiceRegStateOrRatChanged(); } if (wasActive && mActiveEmergencyCalls.isEmpty() Loading Loading @@ -1494,6 +1508,34 @@ public class EmergencyStateTracker { return result; } /** * Returns {@code true} if service states of all phones from PhoneFactory are radio off. */ private boolean isPowerOff() { for (Phone phone : mPhoneFactoryProxy.getPhones()) { ServiceState ss = phone.getServiceStateTracker().getServiceState(); if (ss.getState() != ServiceState.STATE_POWER_OFF) return false; } return true; } private void registerForVoiceRegStateOrRatChanged() { if (mIsWaitingForRadioOff) return; for (Phone phone : mPhoneFactoryProxy.getPhones()) { phone.getServiceStateTracker().registerForVoiceRegStateOrRatChanged(mHandler, MSG_VOICE_REG_STATE_CHANGED, null); } mIsWaitingForRadioOff = true; } private void unregisterForVoiceRegStateOrRatChanged() { if (!mIsWaitingForRadioOff) return; for (Phone phone : mPhoneFactoryProxy.getPhones()) { phone.getServiceStateTracker().unregisterForVoiceRegStateOrRatChanged(mHandler); } mIsWaitingForRadioOff = false; } /** * Returns {@code true} if airplane mode is on. */ Loading Loading @@ -1524,6 +1566,14 @@ public class EmergencyStateTracker { final SatelliteController satelliteController = SatelliteController.getInstance(); boolean needToTurnOffSatellite = satelliteController.isSatelliteEnabled(); if (isAirplaneModeOn && !isPowerOff() && !phone.getServiceStateTracker().getDesiredPowerState()) { // power off is delayed to disconnect data connections Rlog.i(TAG, "turnOnRadioAndSwitchDds: wait for the delayed power off"); registerForVoiceRegStateOrRatChanged(); return; } if (needToTurnOnRadio || needToTurnOffSatellite) { Rlog.i(TAG, "turnOnRadioAndSwitchDds: phoneId=" + phone.getPhoneId() + " for " + emergencyTypeToString(emergencyType)); Loading
tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java +24 −0 Original line number Diff line number Diff line Loading @@ -3000,6 +3000,30 @@ public class EmergencyStateTrackerTest extends TelephonyTest { verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class)); } /** * Test that the EmergencyStateTracker waits for the delayed radio power off. */ @Test @SmallTest public void startEmergencyCall_delayedRadioOff_waitForRadioOff() { EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker( true /* isSuplDdsSwitchRequiredForEmergencyCall */); // Create test Phones and set radio on Phone testPhone = setupTestPhoneForEmergencyCall(false /* isRoaming */, true /* isRadioOn */); // Airplane mode is ON, but radio power state is still ON Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1); CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone, mTestConnection1, false); // Wait for the radio off for all phones verify(mSST, times(2)).registerForVoiceRegStateOrRatChanged(any(), anyInt(), any()); verify(mRadioOnHelper, never()).triggerRadioOnAndListen(any(), anyBoolean(), any(), anyBoolean(), eq(0)); } private EmergencyStateTracker setupEmergencyStateTracker( boolean isSuplDdsSwitchRequiredForEmergencyCall) { doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher(); Loading