Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bb4fb8ee authored by Joonhun Shin's avatar Joonhun Shin Committed by Android (Google) Code Review
Browse files

Merge "Disable satellite when cellular modem enabled in Idle state" into main

parents 1b8f1904 45859865
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -4825,6 +4825,17 @@ public class SatelliteController extends Handler {
        return getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL);
    }

    /**
     * Return whether the device allows to turn off satellite session for emergency call.
     *
     * @param subId Associated subscription ID
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public boolean turnOffSatelliteSessionForEmergencyCall(int subId) {
        return getConfigForSubId(subId).getBoolean(
                KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL);
    }

    private int getCarrierRoamingNtnConnectType(int subId) {
        return getConfigForSubId(subId).getInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT);
    }
+120 −5
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import android.os.RemoteException;
import android.os.SystemProperties;
import android.telephony.DropBoxManagerLoggerBackend;
import android.telephony.PersistentLogger;
import android.telephony.ServiceState;
import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.stub.ISatelliteGateway;
@@ -66,6 +67,7 @@ import com.android.internal.telephony.DeviceStateMonitor;
import com.android.internal.telephony.ExponentialBackoff;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
import com.android.internal.util.State;
@@ -124,6 +126,8 @@ public class SatelliteSessionController extends StateMachine {
    private static final int EVENT_SCREEN_STATE_CHANGED = 9;
    protected static final int EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT = 10;
    protected static final int EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT = 11;
    private static final int EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE = 12;
    private static final int EVENT_SERVICE_STATE_CHANGED = 13;

    private static final long REBIND_INITIAL_DELAY = 2 * 1000; // 2 seconds
    private static final long REBIND_MAXIMUM_DELAY = 64 * 1000; // 1 minute
@@ -277,13 +281,27 @@ public class SatelliteSessionController extends StateMachine {
            bindService();
        });

        Phone phone = mSatelliteController.getSatellitePhone();
        if (phone == null) {
            phone = SatelliteServiceUtils.getPhone();
        Phone satellitePhone = mSatelliteController.getSatellitePhone();
        if (satellitePhone == null) {
            satellitePhone = SatelliteServiceUtils.getPhone();
        }
        mDeviceStateMonitor = phone.getDeviceStateMonitor();
        mDeviceStateMonitor = satellitePhone.getDeviceStateMonitor();
        mSessionMetricsStats = SessionMetricsStats.getInstance();

        if (mFeatureFlags.carrierRoamingNbIotNtn()) {
            // Register to received Cellular service state
            for (Phone phone : PhoneFactory.getPhones()) {
                if (phone == null) continue;

                phone.registerForServiceStateChanged(
                        getHandler(), EVENT_SERVICE_STATE_CHANGED, null);
                if (DBG) {
                    plogd("SatelliteSessionController: registerForServiceStateChanged phoneId "
                            + phone.getPhoneId());
                }
            }
        }

        addState(mUnavailableState);
        addState(mPowerOffState);
        addState(mEnablingState);
@@ -547,9 +565,33 @@ public class SatelliteSessionController extends StateMachine {
        plogd("cleanUpResource");
        mIsDeviceAlignedWithSatellite = false;
        unregisterForScreenStateChanged();

        if (mFeatureFlags.carrierRoamingNbIotNtn()) {
            // Register to received Cellular service state
            for (Phone phone : PhoneFactory.getPhones()) {
                if (phone == null) continue;

                phone.unregisterForServiceStateChanged(getHandler());
                if (DBG) {
                    plogd("cleanUpResource: unregisterForServiceStateChanged phoneId "
                            + phone.getPhoneId());
                }
            }
        }

        quitNow();
    }

    /**
     * Uses this function to notify that cellular service state has changed
     *
     * @param serviceState The state of the cellular service.
     */
    @VisibleForTesting
    public void onCellularServiceStateChanged(ServiceState serviceState) {
        sendMessage(EVENT_SERVICE_STATE_CHANGED, new AsyncResult(null, serviceState, null));
    }

    private boolean isDemoMode() {
        return mIsDemoMode;
    }
@@ -790,8 +832,11 @@ public class SatelliteSessionController extends StateMachine {
            mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_IDLE;
            mIsSendingTriggeredDuringTransferringState.set(false);
            stopNbIotInactivityTimer();

            //Enable Cellular Modem scanning
            mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(true, null);
            Message onCompleted =
                    obtainMessage(EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE);
            mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(true, onCompleted);
            notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
        }

@@ -821,6 +866,18 @@ public class SatelliteSessionController extends StateMachine {
                case EVENT_SATELLITE_MODEM_STATE_CHANGED:
                    handleSatelliteModemStateChanged(msg);
                    break;
                case EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE:
                    handleEventEnableCellularModemWhileSatelliteModeIsOnDone();
                    break;
                case EVENT_SERVICE_STATE_CHANGED:
                    AsyncResult ar = (msg.obj != null) ? (AsyncResult) msg.obj : null;
                    if (ar == null || ar.result == null) {
                        plogd("IdleState: processing: can't access ServiceState");
                    } else {
                        ServiceState newServiceState = (ServiceState) ar.result;
                        handleEventServiceStateChanged(newServiceState);
                    }
                    break;
            }
            // Ignore all unexpected events.
            return HANDLED;
@@ -848,6 +905,58 @@ public class SatelliteSessionController extends StateMachine {
            }
        }

        private void handleEventEnableCellularModemWhileSatelliteModeIsOnDone() {
            if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
                Rlog.d(TAG, "handleEventEnableCellularModemWhileSatelliteModeIsOnDone: "
                        + "carrierRoamingNbIotNtn is disabled");
                return;
            }

            ServiceState serviceState = mSatelliteController.getSatellitePhone().getServiceState();
            if (serviceState == null) {
                plogd("handleEventEnableCellularModemWhileSatelliteModeIsOnDone: "
                        + "can't access ServiceState");
                return;
            }
            handleEventServiceStateChanged(serviceState);
        }

        private void handleEventServiceStateChanged(ServiceState serviceState) {
            boolean isInServiceOrEmergency =
                    serviceState.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
                    || serviceState.getDataRegState() == ServiceState.STATE_IN_SERVICE
                    || serviceState.isEmergencyOnly();
            if (!isInServiceOrEmergency) {
                plogd("handleEventServiceStateChanged: is not IN_SERVICE or EMERGENCY_ONLY");
                return;
            }

            // In emergency
            boolean isEmergency = mSatelliteController.getRequestIsEmergency();
            if (isEmergency) {
                boolean isEmergencyCommunicationEstablished = (mDatagramController == null)
                        ? false : mDatagramController.isEmergencyCommunicationEstablished();
                boolean isTurnOffAllowed =
                        mSatelliteController.turnOffSatelliteSessionForEmergencyCall(getSubId());
                if (isEmergencyCommunicationEstablished || !isTurnOffAllowed) {
                    logd("handleEventServiceStateChanged: "
                            + "can't disable emergency satellite session");
                    return;
                }
            }

            mSatelliteController.requestSatelliteEnabled(
                    false /*enableSatellite*/,
                    false /*enableDemoMode*/,
                    isEmergency /*isEmergency*/,
                    new IIntegerConsumer.Stub() {
                        @Override
                        public void accept(int result) {
                            plogd("requestSatelliteEnabled result=" + result);
                        }
                    });
        }

        private void handleEventDisableCellularModemWhileSatelliteModeIsOnDone(
                @NonNull AsyncResult result) {
            synchronized (mLock) {
@@ -1232,6 +1341,12 @@ public class SatelliteSessionController extends StateMachine {
            case EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT:
                whatString = "EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT";
                break;
            case EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE:
                whatString = "EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE";
                break;
            case EVENT_SERVICE_STATE_CHANGED:
                whatString = "EVENT_SERVICE_STATE_CHANGED";
                break;
            default:
                whatString = "UNKNOWN EVENT " + what;
        }
+86 −1
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.telephony.ServiceState;
import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.SatelliteManager;
import android.testing.AndroidTestingRunner;
@@ -104,6 +105,7 @@ public class SatelliteSessionControllerTest extends TelephonyTest {
    @Mock private DatagramReceiver mMockDatagramReceiver;
    @Mock private DatagramDispatcher mMockDatagramDispatcher;
    @Mock private DatagramController mMockDatagramController;
    @Mock private ServiceState mMockServiceState;

    @Captor ArgumentCaptor<Handler> mHandlerCaptor;
    @Captor ArgumentCaptor<Integer> mMsgCaptor;
@@ -216,6 +218,7 @@ public class SatelliteSessionControllerTest extends TelephonyTest {
        // Notify Screen off
        sendScreenStateChanged(mHandlerCaptor.getValue(), mMsgCaptor.getValue(), false);
        processAllMessages();
        clearInvocations(mMockSatelliteController);

        // Verify that the screen off inactivity timer is started.
        assertTrue(mTestSatelliteSessionController.isScreenOffInActivityTimerStarted());
@@ -283,6 +286,8 @@ public class SatelliteSessionControllerTest extends TelephonyTest {
        doNothing().when(mDeviceStateMonitor).registerForScreenStateChanged(
                eq(mTestSatelliteSessionController.getHandler()), anyInt(), any());
        when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
        when(mMockSatelliteController.turnOffSatelliteSessionForEmergencyCall(
                anyInt())).thenReturn(false);

        when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(false);
        when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
@@ -295,6 +300,7 @@ public class SatelliteSessionControllerTest extends TelephonyTest {

        // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
        assertNotNull(mTestSatelliteSessionController);
        mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
        assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
        setupDatagramTransferringState(true);

@@ -328,6 +334,8 @@ public class SatelliteSessionControllerTest extends TelephonyTest {
        doNothing().when(mDeviceStateMonitor).registerForScreenStateChanged(
                eq(mTestSatelliteSessionController.getHandler()), anyInt(), any());
        when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
        when(mMockSatelliteController.turnOffSatelliteSessionForEmergencyCall(
                anyInt())).thenReturn(false);

        when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
        when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
@@ -338,6 +346,7 @@ public class SatelliteSessionControllerTest extends TelephonyTest {

        // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
        assertNotNull(mTestSatelliteSessionController);
        mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
        assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
        setupDatagramTransferringState(true);

@@ -365,6 +374,76 @@ public class SatelliteSessionControllerTest extends TelephonyTest {
                mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
    }

    @Test
    public void testDisableSatelliteWhenCellularModemEnabledInIdleMode() {
        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
        doNothing().when(mDeviceStateMonitor).registerForScreenStateChanged(
                eq(mTestSatelliteSessionController.getHandler()), anyInt(), any());
        when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(false);
        when(mPhone.getServiceState()).thenReturn(mMockServiceState);

        // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
        assertNotNull(mTestSatelliteSessionController);
        mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
        assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());

        // Conditions for operation
        boolean isEmergency = true;
        // Cellular network is not IN_SERVICE and emergency only.
        // Satellite request is emergency and emergency communication was established.
        // Disabling satellite was not allowed
        when(mMockServiceState.getVoiceRegState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
        when(mMockServiceState.getDataRegState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
        when(mMockServiceState.isEmergencyOnly()).thenReturn(false);
        when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(isEmergency);
        when(mMockDatagramController.isEmergencyCommunicationEstablished()).thenReturn(true);
        when(mMockSatelliteController.turnOffSatelliteSessionForEmergencyCall(
                anyInt())).thenReturn(false);

        moveToIdleState();

        // Cellular network is not in STATE_IN_SERVICE or emergency only.
        // Should not disable satellite
        verify(mMockSatelliteController, never()).requestSatelliteEnabled(
                eq(false), eq(false), eq(isEmergency), any(IIntegerConsumer.Stub.class));

        // Notify cellular service is in STATE_IN_SERVICE.
        ServiceState serviceState = new ServiceState();
        serviceState.setVoiceRegState(ServiceState.STATE_IN_SERVICE);
        serviceState.setDataRegState(ServiceState.STATE_OUT_OF_SERVICE);
        serviceState.setEmergencyOnly(false);
        mTestSatelliteSessionController.onCellularServiceStateChanged(serviceState);
        processAllMessages();

        // Satellite is in emergency mode and emergency communication was established.
        // Should not disable satellite
        verify(mMockSatelliteController, never()).requestSatelliteEnabled(
                eq(false), eq(false), eq(isEmergency), any(IIntegerConsumer.Stub.class));

        // Satellite is in emergency mode but emergency communication was not established.
        // Disabling satellite was not allowed
        when(mMockDatagramController.isEmergencyCommunicationEstablished()).thenReturn(false);
        when(mMockSatelliteController.turnOffSatelliteSessionForEmergencyCall(
                anyInt())).thenReturn(false);
        mTestSatelliteSessionController.onCellularServiceStateChanged(serviceState);
        processAllMessages();

        // Should not disable satellite
        verify(mMockSatelliteController, never()).requestSatelliteEnabled(
                eq(false), eq(false), eq(isEmergency), any(IIntegerConsumer.Stub.class));

        // Satellite is in emergency mode but emergency communication was not established.
        // Disabling satellite was allowed
        when(mMockSatelliteController.turnOffSatelliteSessionForEmergencyCall(
                anyInt())).thenReturn(true);
        mTestSatelliteSessionController.onCellularServiceStateChanged(serviceState);
        processAllMessages();

        // Should disable satellite
        verify(mMockSatelliteController).requestSatelliteEnabled(
                eq(false), eq(false), eq(isEmergency), any(IIntegerConsumer.Stub.class));
    }

    @Test
    public void testStateTransition() {
        /**
@@ -1419,6 +1498,8 @@ public class SatelliteSessionControllerTest extends TelephonyTest {
    }

    private static class TestSatelliteSessionController extends SatelliteSessionController {
        boolean mSatelliteEnabledForNtnOnlySubscription = true;

        TestSatelliteSessionController(Context context, Looper looper, FeatureFlags featureFlags,
                boolean isSatelliteSupported,
                SatelliteModemInterface satelliteModemInterface) {
@@ -1450,7 +1531,11 @@ public class SatelliteSessionControllerTest extends TelephonyTest {
        }

        protected boolean isSatelliteEnabledForNtnOnlySubscription() {
            return true;
            return mSatelliteEnabledForNtnOnlySubscription;
        }

        void setSatelliteEnabledForNtnOnlySubscription(boolean enabled) {
            mSatelliteEnabledForNtnOnlySubscription = false;
        }
    }