Support new satellite datagram transfer state for NB IOT

Bug: 300483339
Test: SMS, MMS, call with live network.
atest SatelliteSessionControllerTest
atest DatagramDispatcherTest DatagramReceiverTest
atest SatelliteSOSMessageRecommenderTest
atest SatelliteControllerTest
atest SatelliteManagerTestOnMockService

Change-Id: Ib17e797aaac708e50a80550b05b8991ac6815562
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramController.java b/src/java/com/android/internal/telephony/satellite/DatagramController.java
index d790ca9..32acdcf 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramController.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramController.java
@@ -315,16 +315,14 @@
     public boolean isSendingInIdleState() {
         synchronized (mLock) {
             return (mSendDatagramTransferState
-                    == SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE)
-                    && (mDatagramDispatcher.getPendingDatagramCount() == 0);
+                    == SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
         }
     }
 
     public boolean isPollingInIdleState() {
         synchronized (mLock) {
             return (mReceiveDatagramTransferState
-                    == SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE)
-                    && !mDatagramReceiver.isPollingPending();
+                    == SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
         }
     }
 
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index b8d9ef4..591114b 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -359,7 +359,9 @@
 
             if (mDatagramController.needsWaitingForSatelliteConnected()) {
                 logd("sendSatelliteDatagram: wait for satellite connected");
-                SatelliteSessionController.getInstance().onSatelliteDatagramsTransferRequested();
+                mDatagramController.updateSendStatus(subId,
+                        SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+                        getPendingDatagramCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
                 startDatagramWaitForConnectedStateTimer();
             } else if (!mSendingDatagramInProgress && mDatagramController.isPollingInIdleState()) {
                 // Modem can be busy receiving datagrams, so send datagram only when modem is
@@ -645,9 +647,16 @@
     private void handleEventDatagramWaitForConnectedStateTimedOut() {
         logw("Timed out to wait for satellite connected before sending datagrams");
         synchronized (mLock) {
+            // Update send status
+            mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+                    SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
+                    getPendingDatagramCount(),
+                    SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
+            mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+                    SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+                    0, SatelliteManager.SATELLITE_RESULT_SUCCESS);
             abortSendingPendingDatagrams(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
                     SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
-            SatelliteSessionController.getInstance().onDatagramWaitForConnectedStateTimerTimedOut();
         }
     }
 
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
index cd98f43..35c78eb 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
@@ -602,16 +602,6 @@
         pollPendingSatelliteDatagramsInternal(subId, callback);
     }
 
-    /**
-     * Check if DatagramReceiver is waiting for satellite modem connected to a satellite network
-     * before pushing down the poll request to modem.
-     */
-    public boolean isPollingPending() {
-        synchronized (mLock) {
-            return (mPendingPollSatelliteDatagramsRequest != null);
-        }
-    }
-
     private void handleSatelliteConnectedEvent() {
         synchronized (mLock) {
             if (isDatagramWaitForConnectedStateTimerStarted()) {
@@ -645,7 +635,10 @@
             synchronized (mLock) {
                 mPendingPollSatelliteDatagramsRequest = new DatagramReceiverHandlerRequest(
                         callback, SatelliteServiceUtils.getPhone(), subId);
-                SatelliteSessionController.getInstance().onSatelliteDatagramsTransferRequested();
+                mDatagramController.updateReceiveStatus(subId,
+                        SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+                        mDatagramController.getReceivePendingCount(),
+                        SatelliteManager.SATELLITE_RESULT_SUCCESS);
                 startDatagramWaitForConnectedStateTimer();
             }
             return;
@@ -874,11 +867,24 @@
             }
 
             logw("Timed out to wait for satellite connected before polling datagrams");
+            mDatagramController.updateReceiveStatus(mPendingPollSatelliteDatagramsRequest.subId,
+                    SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
+                    mDatagramController.getReceivePendingCount(),
+                    SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
+
+            mDatagramController.updateReceiveStatus(mPendingPollSatelliteDatagramsRequest.subId,
+                    SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+                    mDatagramController.getReceivePendingCount(),
+                    SatelliteManager.SATELLITE_RESULT_SUCCESS);
+
+            reportMetrics(null, SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
+            mControllerMetricsStats.reportIncomingDatagramCount(
+                    SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
+
             Consumer<Integer> callback =
                     (Consumer<Integer>) mPendingPollSatelliteDatagramsRequest.argument;
             callback.accept(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
             mPendingPollSatelliteDatagramsRequest = null;
-            SatelliteSessionController.getInstance().onDatagramWaitForConnectedStateTimerTimedOut();
         }
     }
 
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 050dfbc..01ba435 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -2514,7 +2514,6 @@
                 loge("handleEventSatelliteModemStateChanged: mSatelliteSessionController is null");
             }
         }
-        mDatagramController.onSatelliteModemStateChanged(state);
     }
 
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
index d84ceeb..d0497eb 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.telephony.satellite;
 
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS;
@@ -23,6 +24,7 @@
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -97,10 +99,8 @@
     private static final int EVENT_LISTENING_TIMER_TIMEOUT = 2;
     private static final int EVENT_SATELLITE_ENABLED_STATE_CHANGED = 3;
     private static final int EVENT_SATELLITE_MODEM_STATE_CHANGED = 4;
-    private static final int EVENT_SATELLITE_DATAGRAMS_TRANSFER_REQUESTED = 5;
-    private static final int EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE = 6;
-    protected static final int EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT = 7;
-    private static final int EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMER_TIMED_OUT = 8;
+    private static final int EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE = 5;
+    protected static final int EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT = 6;
 
     private static final long REBIND_INITIAL_DELAY = 2 * 1000; // 2 seconds
     private static final long REBIND_MAXIMUM_DELAY = 64 * 1000; // 1 minute
@@ -137,6 +137,7 @@
     @GuardedBy("mLock")
     @NonNull private boolean mIsDisableCellularModemInProgress = false;
     @NonNull private final SatelliteController mSatelliteController;
+    @NonNull private final DatagramController mDatagramController;
 
     /**
      * @return The singleton instance of SatelliteSessionController.
@@ -188,6 +189,7 @@
         mContext = context;
         mSatelliteModemInterface = satelliteModemInterface;
         mSatelliteController = SatelliteController.getInstance();
+        mDatagramController = DatagramController.getInstance();
         mSatelliteStayAtListeningFromSendingMillis = getSatelliteStayAtListeningFromSendingMillis();
         mSatelliteStayAtListeningFromReceivingMillis =
                 getSatelliteStayAtListeningFromReceivingMillis();
@@ -255,26 +257,6 @@
     }
 
     /**
-     * {@link DatagramDispatcher} and {@link DatagramReceiver} use this function to notify
-     * {@link SatelliteSessionController} that it has received a request to send satellite
-     * datagrams or poll pending satellite datagrams.
-     */
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    public void onSatelliteDatagramsTransferRequested() {
-        sendMessage(EVENT_SATELLITE_DATAGRAMS_TRANSFER_REQUESTED);
-    }
-
-    /**
-     * {@link DatagramDispatcher} and {@link DatagramReceiver} use this function to notify
-     * {@link SatelliteSessionController} that the datagram wait for connected state timer has
-     * timed out.
-     */
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    public void onDatagramWaitForConnectedStateTimerTimedOut() {
-        sendMessage(EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMER_TIMED_OUT);
-    }
-
-    /**
      * {@link SatelliteController} uses this function to notify {@link SatelliteSessionController}
      * that the satellite modem state has changed.
      *
@@ -407,6 +389,7 @@
         public void enter() {
             if (DBG) logd("Entering UnavailableState");
             mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE;
+            notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE);
         }
 
         @Override
@@ -483,9 +466,6 @@
                 case EVENT_SATELLITE_ENABLED_STATE_CHANGED:
                     handleSatelliteEnabledStateChanged(!(boolean) msg.obj, "IdleState");
                     break;
-                case EVENT_SATELLITE_DATAGRAMS_TRANSFER_REQUESTED:
-                    disableCellularModemWhileSatelliteModeIsOn();
-                    break;
                 case EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE:
                     handleEventDisableCellularModemWhileSatelliteModeIsOnDone(
                             (AsyncResult) msg.obj);
@@ -505,6 +485,15 @@
                 } else {
                     transitionTo(mTransferringState);
                 }
+            } else if ((datagramTransferState.sendState
+                    == SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT)
+                    || (datagramTransferState.receiveState
+                    == SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT)) {
+                if (mSatelliteController.isSatelliteAttachRequired()) {
+                    disableCellularModemWhileSatelliteModeIsOn();
+                } else {
+                    loge("Unexpected transferring state received for non-NB-IOT NTN");
+                }
             }
         }
 
@@ -694,11 +683,8 @@
                 case EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT:
                     transitionTo(mIdleState);
                     break;
-                case EVENT_SATELLITE_DATAGRAMS_TRANSFER_REQUESTED:
-                    stopNbIotInactivityTimer();
-                    break;
-                case EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMER_TIMED_OUT:
-                    startNbIotInactivityTimer();
+                case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED:
+                    handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj);
                     break;
             }
             // Ignore all unexpected events.
@@ -711,6 +697,20 @@
                 transitionTo(mConnectedState);
             }
         }
+
+        private void handleEventDatagramTransferStateChanged(
+                @NonNull DatagramTransferState datagramTransferState) {
+            if (datagramTransferState.sendState
+                    == SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT
+                    || datagramTransferState.receiveState
+                    == SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT) {
+                stopNbIotInactivityTimer();
+            } else if (datagramTransferState.sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
+                    && datagramTransferState.receiveState
+                    == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE) {
+                startNbIotInactivityTimer();
+            }
+        }
     }
 
     private class ConnectedState extends State {
@@ -786,18 +786,12 @@
             case EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE:
                 whatString = "EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE";
                 break;
-            case EVENT_SATELLITE_DATAGRAMS_TRANSFER_REQUESTED:
-                whatString = "EVENT_SATELLITE_DATAGRAMS_TRANSFER_REQUESTED";
-                break;
             case EVENT_SATELLITE_MODEM_STATE_CHANGED:
                 whatString = "EVENT_SATELLITE_MODEM_STATE_CHANGED";
                 break;
             case EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT:
                 whatString = "EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT";
                 break;
-            case EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMER_TIMED_OUT:
-                whatString = "EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMER_TIMED_OUT";
-                break;
             default:
                 whatString = "UNKNOWN EVENT " + what;
         }
@@ -813,6 +807,8 @@
     }
 
     private void notifyStateChangedEvent(@SatelliteManager.SatelliteModemState int state) {
+        mDatagramController.onSatelliteModemStateChanged(state);
+
         List<ISatelliteStateCallback> toBeRemoved = new ArrayList<>();
         mListeners.values().forEach(listener -> {
             try {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
index c5f1c45..e80978d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -42,6 +42,7 @@
 import android.os.AsyncResult;
 import android.os.Looper;
 import android.os.Message;
+import android.telephony.SubscriptionManager;
 import android.telephony.satellite.SatelliteDatagram;
 import android.telephony.satellite.SatelliteManager;
 import android.testing.AndroidTestingRunner;
@@ -149,8 +150,10 @@
                 true, mResultListener::offer);
         processAllMessages();
         mInOrder.verify(mMockDatagramController).needsWaitingForSatelliteConnected();
+        mInOrder.verify(mMockDatagramController).updateSendStatus(eq(SUB_ID),
+                eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT), eq(1),
+                eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
         mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState();
-        verify(mMockSatelliteSessionController).onSatelliteDatagramsTransferRequested();
         verifyZeroInteractions(mMockSatelliteModemInterface);
         assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
 
@@ -196,7 +199,14 @@
         moveTimeForward(DatagramController.DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT);
         processAllMessages();
         verifyZeroInteractions(mMockSatelliteModemInterface);
-        verifyZeroInteractions(mMockDatagramController);
+        mInOrder.verify(mMockDatagramController)
+                .updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
+                        eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED), eq(1),
+                        eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE));
+        mInOrder.verify(mMockDatagramController)
+                .updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
+                        eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+                        eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
         assertEquals(1, mResultListener.size());
         assertThat(mResultListener.peek()).isEqualTo(
                 SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
index 18f89db..9fe85ef 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
@@ -168,6 +168,9 @@
         mDatagramReceiverUT.pollPendingSatelliteDatagrams(SUB_ID, mResultListener::offer);
         processAllMessages();
         mInOrder.verify(mMockDatagramController).needsWaitingForSatelliteConnected();
+        mInOrder.verify(mMockDatagramController).updateReceiveStatus(eq(SUB_ID),
+                eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT), eq(0),
+                eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
         mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState();
         verifyZeroInteractions(mMockSatelliteModemInterface);
         assertTrue(mDatagramReceiverUT.isDatagramWaitForConnectedStateTimerStarted());
@@ -199,6 +202,12 @@
 
         moveTimeForward(DatagramController.DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT);
         processAllMessages();
+        mInOrder.verify(mMockDatagramController).updateReceiveStatus(eq(SUB_ID),
+                eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED), eq(0),
+                eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE));
+        mInOrder.verify(mMockDatagramController).updateReceiveStatus(eq(SUB_ID),
+                eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+                eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
         verifyZeroInteractions(mMockSatelliteModemInterface);
         assertEquals(1, mResultListener.size());
         assertThat(mResultListener.peek()).isEqualTo(
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
index 888b014..50c6c24 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
@@ -21,12 +21,15 @@
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
@@ -420,6 +423,9 @@
                 mTestSatelliteStateCallback, 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);
 
         moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
         processAllMessages();
@@ -437,6 +443,9 @@
         assertSuccessfulModemStateChangedCallback(
                 mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
         assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+        clearInvocations(mMockDatagramController);
 
         // Power on the modem.
         mTestSatelliteSessionController.onSatelliteEnabledStateChanged(true);
@@ -447,6 +456,9 @@
                 mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
         assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
         assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+        clearInvocations(mMockDatagramController);
 
         // Start sending datagrams
         mTestSatelliteSessionController.onDatagramTransferStateChanged(
@@ -467,6 +479,9 @@
                 mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
         assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
         assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+        clearInvocations(mMockDatagramController);
 
         // Start sending datagrams
         mTestSatelliteSessionController.onDatagramTransferStateChanged(
@@ -478,6 +493,9 @@
                 SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
         assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
         assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+        clearInvocations(mMockDatagramController);
 
         // Sending datagrams failed
         mTestSatelliteSessionController.onDatagramTransferStateChanged(
@@ -490,6 +508,9 @@
                 SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
         assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
         assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+        clearInvocations(mMockDatagramController);
 
         // Start sending datagrams again
         mTestSatelliteSessionController.onDatagramTransferStateChanged(
@@ -502,6 +523,9 @@
                 SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
         assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
         assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+        clearInvocations(mMockDatagramController);
 
         // Sending datagrams is successful and done.
         mTestSatelliteSessionController.onDatagramTransferStateChanged(
@@ -514,6 +538,9 @@
                 SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
         assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
         assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+        clearInvocations(mMockDatagramController);
 
         // Start receiving datagrams
         mTestSatelliteSessionController.onDatagramTransferStateChanged(
@@ -526,6 +553,9 @@
                 SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
         assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
         assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+        clearInvocations(mMockDatagramController);
 
         // Receiving datagrams is successful and done.
         mTestSatelliteSessionController.onDatagramTransferStateChanged(
@@ -537,6 +567,9 @@
                 SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
         assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
         assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+        clearInvocations(mMockDatagramController);
 
         // Wait for timeout
         moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
@@ -547,15 +580,23 @@
                 SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
         assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
         assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+        clearInvocations(mMockDatagramController);
 
         // Start sending datagrams
-        mTestSatelliteSessionController.onSatelliteDatagramsTransferRequested();
+        mTestSatelliteSessionController.onDatagramTransferStateChanged(
+                SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+                SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
         processAllMessages();
 
         // SatelliteSessionController should move to NOT_CONNECTED state.
         assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
                 SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
         assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+        clearInvocations(mMockDatagramController);
 
         // Satellite modem is connected to a satellite network.
         mTestSatelliteSessionController.onSatelliteModemStateChanged(
@@ -566,6 +607,9 @@
         assertSuccessfulModemStateChangedCallback(
                 mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
         assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+        clearInvocations(mMockDatagramController);
 
         // Satellite modem is disconnected from the satellite network.
         mTestSatelliteSessionController.onSatelliteModemStateChanged(
@@ -576,6 +620,9 @@
         assertSuccessfulModemStateChangedCallback(
                 mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
         assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+        clearInvocations(mMockDatagramController);
 
         // Satellite modem is connected to a satellite network.
         mTestSatelliteSessionController.onSatelliteModemStateChanged(
@@ -586,6 +633,9 @@
         assertSuccessfulModemStateChangedCallback(
                 mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
         assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+        clearInvocations(mMockDatagramController);
 
         // Power off the modem.
         mTestSatelliteSessionController.onSatelliteEnabledStateChanged(false);
@@ -595,6 +645,9 @@
         assertSuccessfulModemStateChangedCallback(
                 mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
         assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+        clearInvocations(mMockDatagramController);
 
         // Power on the modem.
         mTestSatelliteSessionController.onSatelliteEnabledStateChanged(true);
@@ -605,6 +658,9 @@
         assertSuccessfulModemStateChangedCallback(
                 mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
         assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+        verify(mMockDatagramController).onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+        clearInvocations(mMockDatagramController);
 
         // Satellite modem is connected to a satellite network.
         mTestSatelliteSessionController.onSatelliteModemStateChanged(
@@ -629,7 +685,9 @@
         mSatelliteModemInterface.setErrorCode(SatelliteManager.SATELLITE_RESULT_MODEM_ERROR);
 
         // Start sending datagrams
-        mTestSatelliteSessionController.onSatelliteDatagramsTransferRequested();
+        mTestSatelliteSessionController.onDatagramTransferStateChanged(
+                SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+                SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
         processAllMessages();
 
         // SatelliteSessionController should stay at IDLE state because it failed to disable
@@ -687,7 +745,9 @@
         assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
 
         // Start sending datagrams and the NB-IOT inactivity timer should be stopped.
-        mTestSatelliteSessionController.onSatelliteDatagramsTransferRequested();
+        mTestSatelliteSessionController.onDatagramTransferStateChanged(
+                SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+                SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
         moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
         processAllMessages();
 
@@ -697,7 +757,12 @@
 
         // Transferring datagram failed because satellite failed to connect to a satellite network.
         // The NB-IOT inactivity timer should be started.
-        mTestSatelliteSessionController.onDatagramWaitForConnectedStateTimerTimedOut();
+        mTestSatelliteSessionController.onDatagramTransferStateChanged(
+                SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
+                SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+        mTestSatelliteSessionController.onDatagramTransferStateChanged(
+                SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+                SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
         processAllMessages();
         assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());