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

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

Merge "Idle mode scanning for terrestrial network when P2P SMS or ESOS mode...

Merge "Idle mode scanning for terrestrial network when P2P SMS or ESOS mode inactivity timer expired" into main
parents 705eb5d4 70f83924
Loading
Loading
Loading
Loading
+32 −4
Original line number Diff line number Diff line
@@ -29,8 +29,11 @@ import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUP
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_NIDD_APN_NAME_STRING;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.SubscriptionManager.SATELLITE_ATTACH_ENABLED_FOR_CARRIER;
import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS;
@@ -2390,6 +2393,12 @@ public class SatelliteController extends Handler {

        DemoSimulator.getInstance().setDeviceAlignedWithSatellite(isAligned);
        mDatagramController.setDeviceAlignedWithSatellite(isAligned);
        if (mSatelliteSessionController != null) {
            mSatelliteSessionController.setDeviceAlignedWithSatellite(isAligned);
        } else {
            ploge("setDeviceAlignedWithSatellite: mSatelliteSessionController"
                    + " is not initialized yet");
        }
    }

    /**
@@ -4339,11 +4348,14 @@ public class SatelliteController extends Handler {
                    KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL,
                    KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT,
                    KEY_SATELLITE_ESOS_SUPPORTED_BOOL,
                    KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL,
                    KEY_SATELLITE_NIDD_APN_NAME_STRING,
                    KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
                    KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT,
                    KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT,
                    KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT
                    KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
                    KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
                    KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT
            );
        }
        if (config == null || config.isEmpty()) {
@@ -4474,7 +4486,23 @@ public class SatelliteController extends Handler {
                .getBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL);
    }

    private boolean isSatelliteEsosSupported(int subId) {
    /**
     * Return whether the device support P2P SMS mode from carrier config.
     *
     * @param subId Associated subscription ID
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public boolean isSatelliteRoamingP2pSmSSupported(int subId) {
        return getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL);
    }

    /**
     * Return whether the device support ESOS mode from carrier config.
     *
     * @param subId Associated subscription ID
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public boolean isSatelliteEsosSupported(int subId) {
        return getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL);
    }

@@ -4995,7 +5023,7 @@ public class SatelliteController extends Handler {
        synchronized (mSatelliteViaOemProvisionLock) {
            plogd("persistOemEnabledSatelliteProvisionStatus: isProvisioned=" + isProvisioned);
            if (mFeatureFlags.carrierRoamingNbIotNtn()) {
                int subId = SatelliteServiceUtils.getOemBasedNonTerrestrialSubscriptionId(mContext);
                int subId = SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext);
                if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
                    try {
                        mSubscriptionManagerService.setIsSatelliteProvisionedForNonIpDatagram(subId,
@@ -5026,7 +5054,7 @@ public class SatelliteController extends Handler {
        plogd("getPersistedOemEnabledSatelliteProvisionStatus:");
        synchronized (mSatelliteViaOemProvisionLock) {
            if (mFeatureFlags.carrierRoamingNbIotNtn()) {
                int subId = SatelliteServiceUtils.getOemBasedNonTerrestrialSubscriptionId(mContext);
                int subId = SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext);
                if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
                    return mSubscriptionManagerService.isSatelliteProvisionedForNonIpDatagram(
                            subId);
+2 −2
Original line number Diff line number Diff line
@@ -348,7 +348,7 @@ public class SatelliteServiceUtils {
     * @return ID of the subscription that supports OEM-based satellite if any,
     * return {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} otherwise.
     */
    public static int getOemBasedNonTerrestrialSubscriptionId(@NonNull Context context) {
    public static int getNtnOnlySubscriptionId(@NonNull Context context) {
        List<SubscriptionInfo> infoList =
                SubscriptionManagerService.getInstance().getAllSubInfoList(
                        context.getOpPackageName(), null);
@@ -358,7 +358,7 @@ public class SatelliteServiceUtils {
                .mapToInt(SubscriptionInfo::getSubscriptionId)
                .findFirst()
                .orElse(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
        logd("getOemBasedNonTerrestrialSubscriptionId: subId=" + subId);
        logd("getNtnOnlySubscriptionId: subId=" + subId);
        return subId;
    }

+146 −6
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.internal.telephony.satellite;

import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED;
@@ -113,15 +115,17 @@ public class SatelliteSessionController extends StateMachine {
    private static final int EVENT_SATELLITE_ENABLEMENT_FAILED = 8;
    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 long REBIND_INITIAL_DELAY = 2 * 1000; // 2 seconds
    private static final long REBIND_MAXIMUM_DELAY = 64 * 1000; // 1 minute
    private static final int REBIND_MULTIPLIER = 2;
    private static final int DEFAULT_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC = 30;
    private static final int DEFAULT_P2P_SMS_INACTIVITY_TIMEOUT_SEC = 180;
    private static final int DEFAULT_ESOS_INACTIVITY_TIMEOUT_SEC = 600;

    @NonNull private final ExponentialBackoff mExponentialBackoff;
    @NonNull private final Object mLock = new Object();
    @NonNull private final Phone mPhone;
    @Nullable
    private ISatelliteGateway mSatelliteGatewayService;
    private String mSatelliteGatewayServicePackageName = "";
@@ -155,6 +159,8 @@ public class SatelliteSessionController extends StateMachine {
    private boolean mIsDemoMode = false;
    // Interested in screen off, so use default value true
    boolean mIsScreenOn = true;
    private boolean mIsDeviceAlignedWithSatellite = false;

    @GuardedBy("mLock")
    @NonNull private boolean mIsDisableCellularModemInProgress = false;
    @NonNull private final SatelliteController mSatelliteController;
@@ -256,8 +262,11 @@ public class SatelliteSessionController extends StateMachine {
            bindService();
        });

        mPhone = SatelliteServiceUtils.getPhone();
        mDeviceStateMonitor = mPhone.getDeviceStateMonitor();
        Phone phone = mSatelliteController.getSatellitePhone();
        if (phone == null) {
            phone = SatelliteServiceUtils.getPhone();
        }
        mDeviceStateMonitor = phone.getDeviceStateMonitor();

        addState(mUnavailableState);
        addState(mPowerOffState);
@@ -469,6 +478,29 @@ public class SatelliteSessionController extends StateMachine {
        mIsDemoMode = isDemoMode;
    }

    /**
     * Notify whether the device is aligned with the satellite
     *
     * @param isAligned {@code true} Device is aligned with the satellite,
     *                  {@code false} otherwise.
     */
    public void setDeviceAlignedWithSatellite(boolean isAligned) {
        if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
            plogd("setDeviceAlignedWithSatellite: carrierRoamingNbIotNtn is disabled");
            return;
        }

        mIsDeviceAlignedWithSatellite = isAligned;

        if (mIsDeviceAlignedWithSatellite) {
            stopCarrierRoamingNbIotInactivityTimer();
        } else {
            if (mCurrentState == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED) {
                evaluateStartingCarrierRoamingNbIotInactivityTimer();
            }
        }
    }

    /**
     * Get whether state machine is in enabling state.
     *
@@ -485,6 +517,7 @@ public class SatelliteSessionController extends StateMachine {
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    public void cleanUpResource() {
        if (DBG) plogd("cleanUpResource");
        mIsDeviceAlignedWithSatellite = false;
        unregisterForScreenStateChanged();
    }

@@ -929,11 +962,14 @@ public class SatelliteSessionController extends StateMachine {
            mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED;
            notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
            startNbIotInactivityTimer();
            evaluateStartingCarrierRoamingNbIotInactivityTimer();
        }

        @Override
        public void exit() {
            if (DBG) plogd("Exiting NotConnectedState");

            stopCarrierRoamingNbIotInactivityTimer();
        }

        @Override
@@ -947,6 +983,8 @@ public class SatelliteSessionController extends StateMachine {
                case EVENT_SATELLITE_MODEM_STATE_CHANGED:
                    handleEventSatelliteModemStateChanged(msg.arg1);
                    break;
                case EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT:
                    // fall through
                case EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT:
                    transitionTo(mIdleState);
                    break;
@@ -981,13 +1019,17 @@ public class SatelliteSessionController extends StateMachine {
                    || datagramTransferState.receiveState
                    == SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT) {
                stopNbIotInactivityTimer();
                stopCarrierRoamingNbIotInactivityTimer();
            } else if (datagramTransferState.sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
                    && datagramTransferState.receiveState
                    == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE) {
                startNbIotInactivityTimer();
                evaluateStartingCarrierRoamingNbIotInactivityTimer();
            } else if (isSending(datagramTransferState.sendState)
                    || isReceiving(datagramTransferState.receiveState)) {
                restartNbIotInactivityTimer();
                stopCarrierRoamingNbIotInactivityTimer();
                evaluateStartingCarrierRoamingNbIotInactivityTimer();
            }
        }
    }
@@ -1092,6 +1134,9 @@ public class SatelliteSessionController extends StateMachine {
            case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT:
                whatString = "EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT";
                break;
            case EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT:
                whatString = "EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT";
                break;
            default:
                whatString = "UNKNOWN EVENT " + what;
        }
@@ -1106,6 +1151,15 @@ public class SatelliteSessionController extends StateMachine {
        }
    }

    private int getSubId() {
        Phone phone = mSatelliteController.getSatellitePhone();
        if (phone == null) {
            return SatelliteServiceUtils.getPhone().getSubId();
        }

        return phone.getSubId();
    }

    private void notifyStateChangedEvent(@SatelliteManager.SatelliteModemState int state) {
        mDatagramController.onSatelliteModemStateChanged(state);

@@ -1324,17 +1378,85 @@ public class SatelliteSessionController extends StateMachine {
    }

    private int getScreenOffInactivityTimeoutDurationSec() {
        PersistableBundle config = mSatelliteController.getPersistableBundle(
                mPhone.getSubId());
        PersistableBundle config = mSatelliteController.getPersistableBundle(getSubId());

        return config.getInt(KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
                DEFAULT_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC);
    }

    private int getP2pSmsInactivityTimeoutDurationSec() {
        PersistableBundle config = mSatelliteController.getPersistableBundle(getSubId());

        return config.getInt(KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
                DEFAULT_P2P_SMS_INACTIVITY_TIMEOUT_SEC);
    }

    private int getEsosInactivityTimeoutDurationSec() {
        PersistableBundle config = mSatelliteController.getPersistableBundle(getSubId());

        return config.getInt(KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
                DEFAULT_ESOS_INACTIVITY_TIMEOUT_SEC);
    }

    private void evaluateStartingCarrierRoamingNbIotInactivityTimer() {
        if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
            plogd("evaluateStartingCarrierRoamingNbIotInactivityTimer: "
                    + "carrierRoamingNbIotNtn is disabled");
            return;
        }

        int subId = getSubId();
        if (!mSatelliteController.isSatelliteRoamingP2pSmSSupported(subId)
                && !mSatelliteController.isSatelliteEsosSupported(subId)) {
            plogd("evaluateStartingCarrierRoamingNbIotInactivityTimer: "
                    + "device does not support P2P SMS and ESOS are disabled");
            return;
        }

        if (mIsDeviceAlignedWithSatellite) {
            plogd("evaluateStartingCarrierRoamingNbIotInactivityTimer: "
                    + "can't start inactivity timer due to device aligned satellite");
            return;
        }

        if (hasMessages(EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT)) {
            plogd("evaluateStartingCarrierRoamingNbIotInactivityTimer: already started");
            return;
        }

        int timeOutMillis;
        if (mSatelliteController.getRequestIsEmergency()) {
            timeOutMillis = getEsosInactivityTimeoutDurationSec() * 1000;
        } else if (mSatelliteController.isInCarrierRoamingNbIotNtn()) {
            timeOutMillis = getP2pSmsInactivityTimeoutDurationSec() * 1000;
        } else {
            plogd("evaluateStartingCarrierRoamingNbIotInactivityTimer: "
                    + "can't start inactivity timer device is in not P2P SMS and ESOS mode");
            return;
        }

        DatagramController datagramController = DatagramController.getInstance();
        if (datagramController.isSendingInIdleState()
                && datagramController.isPollingInIdleState()) {
            sendMessageDelayed(EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT,
                    timeOutMillis);
            plogd("evaluateStartingCarrierRoamingNbIotInactivityTimer: start inactivity timer "
                    + timeOutMillis);
        } else {
            plogd("evaluateStartingCarrierRoamingNbIotInactivityTimer: "
                    + "can't start inactivity timer");
        }
    }

    private void stopCarrierRoamingNbIotInactivityTimer() {
        removeMessages(EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT);
        plogd("stopCarrierRoamingNbIotInactivityTimer:");
    }

    private void handleEventScreenOffInactivityTimerTimedOut() {
        plogd("handleEventScreenOffInactivityTimerTimedOut: request disable satellite");

        mSatelliteController.requestSatelliteEnabled(mPhone.getSubId(),
        mSatelliteController.requestSatelliteEnabled(getSubId(),
                false /*enableSatellite*/,
                false /*enableDemoMode*/,
                mSatelliteController.getRequestIsEmergency() /*isEmergency*/,
@@ -1384,6 +1506,12 @@ public class SatelliteSessionController extends StateMachine {
    }

    private void startNbIotInactivityTimer() {
        if (!isSatelliteEnabledForNtnOnlySubscription()) {
            plogd("startNbIotInactivityTimer: Can't start timer "
                    + "because satellite was not enabled for OEM based NB IOT");
            return;
        }

        if (isNbIotInactivityTimerStarted()) {
            plogd("NB IOT inactivity timer is already started");
            return;
@@ -1406,6 +1534,18 @@ public class SatelliteSessionController extends StateMachine {
        return hasMessages(EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT);
    }

    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    protected boolean isSatelliteEnabledForNtnOnlySubscription() {
        if (SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext)
                != getSubId()) {
            plogd("isSatelliteEnabledForOemBasedNbIot: highest priority satellite subscription "
                    + "is not NTN-only subscription");
            return false;
        }

        return true;
    }

    private boolean isSatellitePersistentLoggingEnabled(
            @NonNull Context context, @NonNull FeatureFlags featureFlags) {
        if (featureFlags.satellitePersistentLogging()) {
+103 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.internal.telephony.satellite;

import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED;
@@ -94,6 +96,8 @@ public class SatelliteSessionControllerTest extends TelephonyTest {
    private static final String STATE_NOT_CONNECTED = "NotConnectedState";
    private static final String STATE_CONNECTED = "ConnectedState";
    private static final int SCREEN_OFF_INACTIVITY_TIMEOUT_SEC = 30;
    private static final int P2P_SMS_INACTIVITY_TIMEOUT_SEC = 180;
    private static final int ESOS_INACTIVITY_TIMEOUT_SEC = 600;
    private TestSatelliteModemInterface mSatelliteModemInterface;
    private TestSatelliteSessionController mTestSatelliteSessionController;
    private TestSatelliteModemStateCallback mTestSatelliteModemStateCallback;
@@ -125,6 +129,10 @@ public class SatelliteSessionControllerTest extends TelephonyTest {

        when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
        when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(false);
        when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
                anyInt())).thenReturn(false);
        when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(false);
        when(mMockSatelliteController.getSatellitePhone()).thenReturn(mPhone);
        mSatelliteModemInterface = new TestSatelliteModemInterface(
                mContext, mMockSatelliteController, Looper.myLooper(), mFeatureFlags);
        mTestSatelliteSessionController = new TestSatelliteSessionController(mContext,
@@ -271,6 +279,94 @@ public class SatelliteSessionControllerTest extends TelephonyTest {
        assertFalse(mTestSatelliteSessionController.isScreenOffInActivityTimerStarted());
    }

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

        when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(false);
        when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
                anyInt())).thenReturn(true);
        when(mMockSatelliteController.isInCarrierRoamingNbIotNtn()).thenReturn(true);
        PersistableBundle bundle = new PersistableBundle();
        bundle.putInt(KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
                P2P_SMS_INACTIVITY_TIMEOUT_SEC);
        when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);

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

        moveToNotConnectedState();

        // Verify that the P2P SMS inactivity timer is started.
        assertTrue(mTestSatelliteSessionController.isCarrierRoamingNbIotInActivityTimerStarted());

        mTestSatelliteSessionController.setDeviceAlignedWithSatellite(true);

        // Verify that the P2P SMS inactivity timer is stopped.
        assertFalse(mTestSatelliteSessionController.isCarrierRoamingNbIotInActivityTimerStarted());

        mTestSatelliteSessionController.setDeviceAlignedWithSatellite(false);

        // Verify that the P2P SMS inactivity timer is started.
        assertTrue(mTestSatelliteSessionController.isCarrierRoamingNbIotInActivityTimerStarted());

        // Time shift to cause timeout
        moveTimeForward(P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000);
        processAllMessages();

        // SatelliteSessionController should move to IDLE state.
        assertSuccessfulModemStateChangedCallback(
                mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
    }

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

        when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
        when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
        PersistableBundle bundle = new PersistableBundle();
        bundle.putInt(KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
                ESOS_INACTIVITY_TIMEOUT_SEC);
        when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);

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

        moveToNotConnectedState();

        // Verify that the ESOS inactivity timer is started.
        assertTrue(mTestSatelliteSessionController.isCarrierRoamingNbIotInActivityTimerStarted());

        mTestSatelliteSessionController.setDeviceAlignedWithSatellite(true);

        // Verify that the ESOS inactivity timer is stopped.
        assertFalse(mTestSatelliteSessionController.isCarrierRoamingNbIotInActivityTimerStarted());

        mTestSatelliteSessionController.setDeviceAlignedWithSatellite(false);

        // Verify that the ESOS inactivity timer is started.
        assertTrue(mTestSatelliteSessionController.isCarrierRoamingNbIotInActivityTimerStarted());

        // Time shift to cause timeout
        moveTimeForward(ESOS_INACTIVITY_TIMEOUT_SEC * 1000);
        processAllMessages();

        // SatelliteSessionController should move to IDLE state.
        assertSuccessfulModemStateChangedCallback(
                mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
    }

    @Test
    public void testStateTransition() {
        /**
@@ -1230,7 +1326,6 @@ public class SatelliteSessionControllerTest extends TelephonyTest {
        assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
                SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
        assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
        assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
        verify(mMockDatagramController).onSatelliteModemStateChanged(
                SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
        clearInvocations(mMockDatagramController);
@@ -1352,6 +1447,13 @@ public class SatelliteSessionControllerTest extends TelephonyTest {
            return hasMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
        }

        boolean isCarrierRoamingNbIotInActivityTimerStarted() {
            return hasMessages(EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT);
        }

        protected boolean isSatelliteEnabledForNtnOnlySubscription() {
            return true;
        }
    }

    private static class TestSatelliteModemStateCallback extends ISatelliteModemStateCallback.Stub {