Merge "Add triggering pollPendingSatelliteDatagrams after successfully sending a callback back to sendSatelliteDatagram." into 24D1-dev
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramController.java b/src/java/com/android/internal/telephony/satellite/DatagramController.java
index 877eaf1..6783e38 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramController.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramController.java
@@ -35,6 +35,8 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 
@@ -59,6 +61,8 @@
     public static final int TIMEOUT_TYPE_DATAGRAM_WAIT_FOR_CONNECTED_STATE = 2;
     /** This type is used by CTS to override the time to wait for response of the send request */
     public static final int TIMEOUT_TYPE_WAIT_FOR_DATAGRAM_SENDING_RESPONSE = 3;
+    /** This type is used by CTS to override the time to datagram delay in demo mode */
+    public static final int TIMEOUT_TYPE_DATAGRAM_DELAY_IN_DEMO_MODE = 4;
     private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem";
     private static final boolean DEBUG = !"user".equals(Build.TYPE);
 
@@ -83,8 +87,8 @@
     private int mReceivePendingCount = 0;
     @GuardedBy("mLock")
     private int mReceiveErrorCode = SatelliteManager.SATELLITE_RESULT_SUCCESS;
-
-    private SatelliteDatagram mDemoModeDatagram;
+    @GuardedBy("mLock")
+    private final List<SatelliteDatagram> mDemoModeDatagramList;
     private boolean mIsDemoMode = false;
     private long mAlignTimeoutDuration = SATELLITE_ALIGN_TIMEOUT;
     private long mDatagramWaitTimeForConnectedState;
@@ -143,6 +147,7 @@
 
         mDatagramWaitTimeForConnectedState = getDatagramWaitForConnectedStateTimeoutMillis();
         mModemImageSwitchingDuration = getSatelliteModemImageSwitchingDurationMillis();
+        mDemoModeDatagramList = new ArrayList<>();
     }
 
     /**
@@ -208,7 +213,7 @@
     public void sendSatelliteDatagram(int subId, @SatelliteManager.DatagramType int datagramType,
             @NonNull SatelliteDatagram datagram, boolean needFullScreenPointingUI,
             @NonNull Consumer<Integer> callback) {
-        setDemoModeDatagram(datagramType, datagram);
+        pushDemoModeDatagram(datagramType, datagram);
         mDatagramDispatcher.sendSatelliteDatagram(subId, datagramType, datagram,
                 needFullScreenPointingUI, callback);
     }
@@ -349,14 +354,25 @@
         mDatagramReceiver.setDemoMode(isDemoMode);
 
         if (!isDemoMode) {
-            mDemoModeDatagram = null;
+            synchronized (mLock) {
+                mDemoModeDatagramList.clear();
+            }
+            setDeviceAlignedWithSatellite(false);
         }
+        logd("setDemoMode: mIsDemoMode=" + mIsDemoMode);
     }
 
     /** Get the last sent datagram for demo mode */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    public SatelliteDatagram getDemoModeDatagram() {
-        return mDemoModeDatagram;
+    public SatelliteDatagram popDemoModeDatagram() {
+        if (!mIsDemoMode) {
+            return null;
+        }
+
+        synchronized (mLock) {
+            logd("popDemoModeDatagram");
+            return mDemoModeDatagramList.size() > 0 ? mDemoModeDatagramList.remove(0) : null;
+        }
     }
 
     /**
@@ -365,10 +381,13 @@
      * @param datagram datagram The last datagram saved when sendSatelliteDatagramForDemo is called
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
-    protected void setDemoModeDatagram(@SatelliteManager.DatagramType int datagramType,
+    protected void pushDemoModeDatagram(@SatelliteManager.DatagramType int datagramType,
             SatelliteDatagram datagram) {
-        if (mIsDemoMode &&  datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) {
-            mDemoModeDatagram = datagram;
+        if (mIsDemoMode && datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) {
+            synchronized (mLock) {
+                mDemoModeDatagramList.add(datagram);
+                logd("pushDemoModeDatagram size=" + mDemoModeDatagramList.size());
+            }
         }
     }
 
@@ -419,6 +438,8 @@
             }
         } else if (timeoutType == TIMEOUT_TYPE_WAIT_FOR_DATAGRAM_SENDING_RESPONSE) {
             mDatagramDispatcher.setWaitTimeForDatagramSendingResponse(reset, timeoutMillis);
+        } else if (timeoutType == TIMEOUT_TYPE_DATAGRAM_DELAY_IN_DEMO_MODE) {
+            mDatagramDispatcher.setTimeoutDatagramDelayInDemoMode(reset, timeoutMillis);
         } else {
             loge("Invalid timeout type " + timeoutType);
             return false;
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index 5cac1dd..83caf2e 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -45,6 +45,7 @@
 import java.util.LinkedHashMap;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Consumer;
@@ -61,7 +62,8 @@
     private static final int EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMED_OUT = 4;
     private static final int EVENT_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMED_OUT = 5;
     private static final int EVENT_ABORT_SENDING_SATELLITE_DATAGRAMS_DONE = 6;
-
+    private static final int CMD_POLL_PENDING_SATELLITE_DATAGRAMS = 7;
+    private static final Long TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE = TimeUnit.SECONDS.toMillis(10);
     @NonNull private static DatagramDispatcher sInstance;
     @NonNull private final Context mContext;
     @NonNull private final DatagramController mDatagramController;
@@ -76,6 +78,7 @@
     private AtomicBoolean mShouldSendDatagramToModemInDemoMode = null;
 
     private final Object mLock = new Object();
+    private long mDemoTimeoutDuration = TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE;
 
     @GuardedBy("mLock")
     private boolean mSendingDatagramInProgress;
@@ -196,7 +199,9 @@
 
         switch(msg.what) {
             case CMD_SEND_SATELLITE_DATAGRAM: {
-                logd("CMD_SEND_SATELLITE_DATAGRAM");
+                logd("CMD_SEND_SATELLITE_DATAGRAM mIsDemoMode=" + mIsDemoMode
+                        + ", shouldSendDatagramToModemInDemoMode="
+                        + shouldSendDatagramToModemInDemoMode());
                 request = (DatagramDispatcherHandlerRequest) msg.obj;
                 SendSatelliteDatagramArgument argument =
                         (SendSatelliteDatagramArgument) request.argument;
@@ -205,7 +210,7 @@
                 synchronized (mLock) {
                     if (mIsDemoMode && !shouldSendDatagramToModemInDemoMode()) {
                         AsyncResult.forMessage(onCompleted, SATELLITE_RESULT_SUCCESS, null);
-                        onCompleted.sendToTarget();
+                        sendMessageDelayed(onCompleted, getDemoTimeoutDuration());
                     } else {
                         SatelliteModemInterface.getInstance().sendSatelliteDatagram(
                                 argument.datagram,
@@ -266,7 +271,11 @@
                                 getPendingDatagramCount(), error);
                         mControllerMetricsStats.reportOutgoingDatagramSuccessCount(
                                 argument.datagramType);
-
+                        if (mIsDemoMode) {
+                            sendMessageDelayed(
+                                    obtainMessage(CMD_POLL_PENDING_SATELLITE_DATAGRAMS, request),
+                                    getDemoTimeoutDuration());
+                        }
                         if (getPendingDatagramCount() > 0) {
                             // Send response for current datagram
                             argument.callback.accept(error);
@@ -314,6 +323,15 @@
                 handleEventDatagramWaitForConnectedStateTimedOut();
                 break;
 
+            case CMD_POLL_PENDING_SATELLITE_DATAGRAMS:
+                if (mIsDemoMode) {
+                    request = (DatagramDispatcherHandlerRequest) msg.obj;
+                    SendSatelliteDatagramArgument argument =
+                            (SendSatelliteDatagramArgument) request.argument;
+                    pollPendingSatelliteDatagrams(argument.subId);
+                }
+                break;
+
             default:
                 logw("DatagramDispatcherHandler: unexpected message code: " + msg.what);
                 break;
@@ -392,15 +410,15 @@
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     protected void setDemoMode(boolean isDemoMode) {
         mIsDemoMode = isDemoMode;
+        logd("setDemoMode: mIsDemoMode=" + mIsDemoMode);
     }
 
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     protected void setDeviceAlignedWithSatellite(boolean isAligned) {
-        if (mIsDemoMode) {
-            synchronized (mLock) {
-                mIsAligned = isAligned;
-                if (isAligned) handleEventSatelliteAligned();
-            }
+        synchronized (mLock) {
+            mIsAligned = isAligned;
+            logd("setDeviceAlignedWithSatellite: " + mIsAligned);
+            if (isAligned && mIsDemoMode) handleEventSatelliteAligned();
         }
     }
 
@@ -435,12 +453,15 @@
                 mSendSatelliteDatagramRequest = null;
                 AsyncResult.forMessage(message, null, null);
                 message.sendToTarget();
+                logd("handleEventSatelliteAligned: EVENT_SEND_SATELLITE_DATAGRAM_DONE");
             }
         }
     }
 
     private void handleEventSatelliteAlignedTimeout(
             @NonNull DatagramDispatcherHandlerRequest request) {
+        logd("handleEventSatelliteAlignedTimeout");
+        mSendSatelliteDatagramRequest = null;
         SatelliteManager.SatelliteException exception =
                 new SatelliteManager.SatelliteException(
                         SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
@@ -608,6 +629,7 @@
 
     @GuardedBy("mLock")
     private void cleanUpResources() {
+        logd("cleanUpResources");
         mSendingDatagramInProgress = false;
         if (getPendingDatagramCount() > 0) {
             mDatagramController.updateSendStatus(
@@ -789,6 +811,36 @@
         }
     }
 
+    private void pollPendingSatelliteDatagrams(int subId) {
+        logd("pollPendingSatelliteDatagrams");
+        Consumer<Integer> internalCallback = new Consumer<Integer>() {
+            @Override
+            public void accept(Integer result) {
+                logd("pollPendingSatelliteDatagrams result: " + result);
+            }
+        };
+        mDatagramController.pollPendingSatelliteDatagrams(subId, internalCallback);
+    }
+
+    long getDemoTimeoutDuration() {
+        return mDemoTimeoutDuration;
+    }
+
+    /**
+     * This API is used by CTS tests to override the mDemoTimeoutDuration.
+     */
+    void setTimeoutDatagramDelayInDemoMode(boolean reset, long timeoutMillis) {
+        if (!mIsDemoMode) {
+            return;
+        }
+        if (reset) {
+            mDemoTimeoutDuration = TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE;
+        } else {
+            mDemoTimeoutDuration = timeoutMillis;
+        }
+        logd("setTimeoutDatagramDelayInDemoMode " + mDemoTimeoutDuration + " reset=" + reset);
+    }
+
     private static void logd(@NonNull String log) {
         Rlog.d(TAG, log);
     }
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
index c267fd7..6c52a8c 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
@@ -439,7 +439,7 @@
                         "pollPendingSatelliteDatagrams");
 
                 if (mIsDemoMode && error == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
-                    SatelliteDatagram datagram = mDatagramController.getDemoModeDatagram();
+                    SatelliteDatagram datagram = mDatagramController.popDemoModeDatagram();
                     final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(
                             request.subId, mContext);
                     SatelliteDatagramListenerHandler listenerHandler =
@@ -744,11 +744,10 @@
 
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     protected void setDeviceAlignedWithSatellite(boolean isAligned) {
-        if (mIsDemoMode) {
-            synchronized (mLock) {
-                mIsAligned = isAligned;
-                if (isAligned) handleEventSatelliteAligned();
-            }
+        synchronized (mLock) {
+            mIsAligned = isAligned;
+            logd("setDeviceAlignedWithSatellite: " + mIsAligned);
+            if (isAligned && mIsDemoMode) handleEventSatelliteAligned();
         }
     }
 
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 2c12939..1c59798 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -3213,6 +3213,7 @@
     private void setDemoModeEnabled(boolean enabled) {
         mIsDemoModeEnabled = enabled;
         mDatagramController.setDemoMode(mIsDemoModeEnabled);
+        logd("setDemoModeEnabled: mIsDemoModeEnabled=" + mIsDemoModeEnabled);
     }
 
     private boolean isMockModemAllowed() {
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 37ff69a..79f1928 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -89,6 +89,7 @@
             (int) TimeUnit.SECONDS.toMillis(180);
     private static final long TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS =
             TimeUnit.SECONDS.toMillis(60);
+    private static final Long TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE = TimeUnit.SECONDS.toMillis(10);
 
     private DatagramDispatcher mDatagramDispatcherUT;
     private TestDatagramDispatcher mTestDemoModeDatagramDispatcher;
@@ -409,6 +410,8 @@
                 true, mResultListener::offer);
 
         processAllMessages();
+        moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+        processAllMessages();
 
         mInOrder.verify(mMockDatagramController)
                 .updateSendStatus(eq(SUB_ID),
@@ -484,6 +487,8 @@
                 true, mResultListener::offer);
 
         processAllMessages();
+        moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+        processAllMessages();
 
         mInOrder.verify(mMockDatagramController)
                 .updateSendStatus(eq(SUB_ID),
@@ -597,6 +602,11 @@
         mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
                 true, mIntegerConsumer);
         processAllMessages();
+        moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+        processAllMessages();
+
+        verify(mMockDatagramController).pollPendingSatelliteDatagrams(anyInt(), any());
+
         waitForIntegerConsumerResult(1);
         assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS,
                 (int) mIntegerConsumerResult.get(0));
@@ -609,6 +619,11 @@
         mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
                 true, mIntegerConsumer);
         processAllMessages();
+        moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+        processAllMessages();
+
+        verify(mMockDatagramController, times(2)).pollPendingSatelliteDatagrams(anyInt(), any());
+
         waitForIntegerConsumerResult(1);
         assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS,
                 (int) mIntegerConsumerResult.get(0));
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 3a42881..5a1a8f7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
@@ -323,10 +323,10 @@
         // Checks invalid case only as SatelliteController does not exist in unit test
         mTestDemoModeDatagramReceiver.setDemoMode(true);
         mTestDemoModeDatagramReceiver.setDeviceAlignedWithSatellite(true);
-        when(mMockDatagramController.getDemoModeDatagram()).thenReturn(mDatagram);
+        when(mMockDatagramController.popDemoModeDatagram()).thenReturn(mDatagram);
         mTestDemoModeDatagramReceiver.pollPendingSatelliteDatagrams(SUB_ID, mResultListener::offer);
         processAllMessages();
-        verify(mMockDatagramController, times(1)).getDemoModeDatagram();
+        verify(mMockDatagramController, times(1)).popDemoModeDatagram();
         verify(mMockDatagramController)
                 .updateReceiveStatus(eq(SUB_ID),
                         eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING),
@@ -353,10 +353,10 @@
         mTestDemoModeDatagramReceiver.setDemoMode(true);
         mTestDemoModeDatagramReceiver.setDuration(TEST_EXPIRE_TIMER_SATELLITE_ALIGN);
         mTestDemoModeDatagramReceiver.setDeviceAlignedWithSatellite(false);
-        when(mMockDatagramController.getDemoModeDatagram()).thenReturn(mDatagram);
+        when(mMockDatagramController.popDemoModeDatagram()).thenReturn(mDatagram);
         mTestDemoModeDatagramReceiver.pollPendingSatelliteDatagrams(SUB_ID, mResultListener::offer);
         processAllMessages();
-        verify(mMockDatagramController, never()).getDemoModeDatagram();
+        verify(mMockDatagramController, never()).popDemoModeDatagram();
         verify(mMockDatagramController)
                 .updateReceiveStatus(eq(SUB_ID),
                         eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING),