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

Commit 4f3d8eb4 authored by Thomas Nguyen's avatar Thomas Nguyen Committed by Automerger Merge Worker
Browse files

Merge "Retry polling for pending datagrams in demo mode" into 24D1-dev am: 65683224

parents 1f608eb0 65683224
Loading
Loading
Loading
Loading
+38 −10
Original line number Diff line number Diff line
@@ -16,10 +16,13 @@

package com.android.internal.telephony.satellite;

import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_IDLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_OFF;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;

import android.annotation.NonNull;
import android.content.Context;
@@ -72,7 +75,7 @@ public class DatagramController {
    private int mSendSubId;
    @GuardedBy("mLock")
    private @SatelliteManager.SatelliteDatagramTransferState int mSendDatagramTransferState =
            SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
            SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
    @GuardedBy("mLock")
    private int mSendPendingCount = 0;
    @GuardedBy("mLock")
@@ -82,7 +85,7 @@ public class DatagramController {
    private int mReceiveSubId;
    @GuardedBy("mLock")
    private @SatelliteManager.SatelliteDatagramTransferState int mReceiveDatagramTransferState =
            SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
            SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
    @GuardedBy("mLock")
    private int mReceivePendingCount = 0;
    @GuardedBy("mLock")
@@ -132,7 +135,7 @@ public class DatagramController {
     *                              about datagram transfer state changes.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    protected DatagramController(@NonNull Context context, @NonNull Looper  looper,
    public DatagramController(@NonNull Context context, @NonNull Looper  looper,
            @NonNull PointingAppController pointingAppController) {
        mContext = context;
        mPointingAppController = pointingAppController;
@@ -188,6 +191,7 @@ public class DatagramController {
     * @param callback The callback to get {@link SatelliteManager.SatelliteResult} of the request.
     */
    public void pollPendingSatelliteDatagrams(int subId, @NonNull Consumer<Integer> callback) {
        logd("pollPendingSatelliteDatagrams");
        mDatagramReceiver.pollPendingSatelliteDatagrams(subId, callback);
    }

@@ -213,7 +217,6 @@ public class DatagramController {
    public void sendSatelliteDatagram(int subId, @SatelliteManager.DatagramType int datagramType,
            @NonNull SatelliteDatagram datagram, boolean needFullScreenPointingUI,
            @NonNull Consumer<Integer> callback) {
        pushDemoModeDatagram(datagramType, datagram);
        mDatagramDispatcher.sendSatelliteDatagram(subId, datagramType, datagram,
                needFullScreenPointingUI, callback);
    }
@@ -239,10 +242,10 @@ public class DatagramController {
            mSendDatagramTransferState = datagramTransferState;
            mSendPendingCount = sendPendingCount;
            mSendErrorCode = errorCode;

            notifyDatagramTransferStateChangedToSessionController();
            mPointingAppController.updateSendDatagramTransferState(mSendSubId,
                    mSendDatagramTransferState, mSendPendingCount, mSendErrorCode);
            retryPollPendingDatagramsInDemoMode();
        }
    }

@@ -271,6 +274,7 @@ public class DatagramController {
            notifyDatagramTransferStateChangedToSessionController();
            mPointingAppController.updateReceiveDatagramTransferState(mReceiveSubId,
                    mReceiveDatagramTransferState, mReceivePendingCount, mReceiveErrorCode);
            retryPollPendingDatagramsInDemoMode();
        }

        if (isPollingInIdleState()) {
@@ -300,9 +304,16 @@ public class DatagramController {
        mDatagramReceiver.onSatelliteModemStateChanged(state);
    }

    void setDeviceAlignedWithSatellite(boolean isAligned) {
    /**
     * Set whether the device is aligned with the satellite.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public void setDeviceAlignedWithSatellite(boolean isAligned) {
        mDatagramDispatcher.setDeviceAlignedWithSatellite(isAligned);
        mDatagramReceiver.setDeviceAlignedWithSatellite(isAligned);
        if (isAligned) {
            retryPollPendingDatagramsInDemoMode();
        }
    }

    @VisibleForTesting
@@ -332,14 +343,14 @@ public class DatagramController {
    public boolean isSendingInIdleState() {
        synchronized (mLock) {
            return (mSendDatagramTransferState
                    == SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
                    == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
        }
    }

    public boolean isPollingInIdleState() {
        synchronized (mLock) {
            return (mReceiveDatagramTransferState
                    == SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
                    == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
        }
    }

@@ -380,8 +391,8 @@ public class DatagramController {
     * @param datagramType datagram type, only DATAGRAM_TYPE_SOS_MESSAGE will be saved
     * @param datagram datagram The last datagram saved when sendSatelliteDatagramForDemo is called
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    protected void pushDemoModeDatagram(@SatelliteManager.DatagramType int datagramType,
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public void pushDemoModeDatagram(@SatelliteManager.DatagramType int datagramType,
            SatelliteDatagram datagram) {
        if (mIsDemoMode && datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) {
            synchronized (mLock) {
@@ -484,6 +495,23 @@ public class DatagramController {
        mDatagramDispatcher.setShouldSendDatagramToModemInDemoMode(shouldSendToModemInDemoMode);
    }

    private void retryPollPendingDatagramsInDemoMode() {
        synchronized (mLock) {
            if (mIsDemoMode && isSendingInIdleState() && isPollingInIdleState()
                    && !mDemoModeDatagramList.isEmpty()) {
                Consumer<Integer> internalCallback = new Consumer<Integer>() {
                    @Override
                    public void accept(Integer result) {
                        if (result != SATELLITE_RESULT_SUCCESS) {
                            logd("retryPollPendingDatagramsInDemoMode result: " + result);
                        }
                    }
                };
                pollPendingSatelliteDatagrams(DEFAULT_SUBSCRIPTION_ID, internalCallback);
            }
        }
    }

    private static void logd(@NonNull String log) {
        Rlog.d(TAG, log);
    }
+49 −27
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.internal.telephony.satellite;

import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;

import static com.android.internal.telephony.satellite.DatagramController.ROUNDING_UNIT;
@@ -62,7 +63,7 @@ public class DatagramDispatcher extends Handler {
    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 int EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT = 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;
@@ -238,7 +239,8 @@ public class DatagramDispatcher extends Handler {
                            break;
                        }
                    }
                    logd("EVENT_SEND_SATELLITE_DATAGRAM_DONE error: " + error);
                    logd("EVENT_SEND_SATELLITE_DATAGRAM_DONE error: " + error
                            + ", mIsDemoMode=" + mIsDemoMode);

                    /*
                     * The response should be ignored if either of the following hold
@@ -271,11 +273,7 @@ public class DatagramDispatcher extends Handler {
                                getPendingDatagramCount(), error);
                        mControllerMetricsStats.reportOutgoingDatagramSuccessCount(
                                argument.datagramType);
                        if (mIsDemoMode) {
                            sendMessageDelayed(
                                    obtainMessage(CMD_POLL_PENDING_SATELLITE_DATAGRAMS, request),
                                    getDemoTimeoutDuration());
                        }
                        startWaitForSimulatedPollDatagramsDelayTimer(request);
                        if (getPendingDatagramCount() > 0) {
                            // Send response for current datagram
                            argument.callback.accept(error);
@@ -323,13 +321,10 @@ public class DatagramDispatcher extends Handler {
                handleEventDatagramWaitForConnectedStateTimedOut();
                break;

            case CMD_POLL_PENDING_SATELLITE_DATAGRAMS:
                if (mIsDemoMode) {
            case EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT:
                request = (DatagramDispatcherHandlerRequest) msg.obj;
                    SendSatelliteDatagramArgument argument =
                            (SendSatelliteDatagramArgument) request.argument;
                    pollPendingSatelliteDatagrams(argument.subId);
                }
                handleEventWaitForSimulatedPollDatagramsDelayTimedOut(
                        (SendSatelliteDatagramArgument) request.argument);
                break;

            default:
@@ -413,8 +408,11 @@ public class DatagramDispatcher extends Handler {
        logd("setDemoMode: mIsDemoMode=" + mIsDemoMode);
    }

    /**
     * Set whether the device is aligned with the satellite.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    protected void setDeviceAlignedWithSatellite(boolean isAligned) {
    public void setDeviceAlignedWithSatellite(boolean isAligned) {
        synchronized (mLock) {
            mIsAligned = isAligned;
            logd("setDeviceAlignedWithSatellite: " + mIsAligned);
@@ -464,7 +462,7 @@ public class DatagramDispatcher extends Handler {
        mSendSatelliteDatagramRequest = null;
        SatelliteManager.SatelliteException exception =
                new SatelliteManager.SatelliteException(
                        SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
                        SATELLITE_RESULT_NOT_REACHABLE);
        Message message = obtainMessage(EVENT_SEND_SATELLITE_DATAGRAM_DONE, request);
        AsyncResult.forMessage(message, null, exception);
        message.sendToTarget();
@@ -646,6 +644,7 @@ public class DatagramDispatcher extends Handler {
        stopSatelliteAlignedTimer();
        stopDatagramWaitForConnectedStateTimer();
        stopWaitForDatagramSendingResponseTimer();
        stopWaitForSimulatedPollDatagramsDelayTimer();
        mIsDemoMode = false;
        mSendSatelliteDatagramRequest = null;
        mIsAligned = false;
@@ -703,12 +702,12 @@ public class DatagramDispatcher extends Handler {
            mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
                    SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
                    getPendingDatagramCount(),
                    SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
                    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);
                    SATELLITE_RESULT_NOT_REACHABLE);
        }
    }

@@ -811,15 +810,38 @@ public class DatagramDispatcher extends Handler {
        }
    }

    private void pollPendingSatelliteDatagrams(int subId) {
        logd("pollPendingSatelliteDatagrams");
    private void startWaitForSimulatedPollDatagramsDelayTimer(
            @NonNull DatagramDispatcherHandlerRequest request) {
        if (mIsDemoMode) {
            logd("startWaitForSimulatedPollDatagramsDelayTimer");
            sendMessageDelayed(
                    obtainMessage(EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT, request),
                    getDemoTimeoutDuration());
        } else {
            logd("Should not start WaitForSimulatedPollDatagramsDelayTimer in non-demo mode");
        }
    }

    private void stopWaitForSimulatedPollDatagramsDelayTimer() {
        removeMessages(EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT);
    }

    private void handleEventWaitForSimulatedPollDatagramsDelayTimedOut(
            @NonNull SendSatelliteDatagramArgument argument) {
        if (mIsDemoMode) {
            logd("handleEventWaitForSimulatedPollDatagramsDelayTimedOut");
            mDatagramController.pushDemoModeDatagram(argument.datagramType, argument.datagram);
            Consumer<Integer> internalCallback = new Consumer<Integer>() {
                @Override
                public void accept(Integer result) {
                    logd("pollPendingSatelliteDatagrams result: " + result);
                }
            };
        mDatagramController.pollPendingSatelliteDatagrams(subId, internalCallback);
            mDatagramController.pollPendingSatelliteDatagrams(argument.subId, internalCallback);
        } else {
            logd("Unexpected EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT in "
                    + "non-demo mode");
        }
    }

    long getDemoTimeoutDuration() {
+1 −1
Original line number Diff line number Diff line
@@ -743,7 +743,7 @@ public class DatagramReceiver extends Handler {
    }

    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    protected void setDeviceAlignedWithSatellite(boolean isAligned) {
    public void setDeviceAlignedWithSatellite(boolean isAligned) {
        synchronized (mLock) {
            mIsAligned = isAligned;
            logd("setDeviceAlignedWithSatellite: " + mIsAligned);
+189 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.telephony.satellite;

import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
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_RESULT_SUCCESS;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.os.Looper;
import android.telephony.satellite.SatelliteDatagram;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;

import com.android.internal.telephony.TelephonyTest;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.function.Consumer;

@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class DatagramControllerTest extends TelephonyTest {
    private static final String TAG = "DatagramControllerTest";

    private DatagramController mDatagramControllerUT;

    @Mock private DatagramReceiver mMockDatagramReceiver;
    @Mock private DatagramDispatcher mMockDatagramDispatcher;
    @Mock private PointingAppController mMockPointingAppController;
    @Mock private SatelliteSessionController mMockSatelliteSessionController;

    private static final int SUB_ID = 0;

    @Before
    public void setUp() throws Exception {
        super.setUp(getClass().getSimpleName());
        MockitoAnnotations.initMocks(this);
        logd(TAG + " Setup!");

        replaceInstance(DatagramDispatcher.class, "sInstance", null,
                mMockDatagramDispatcher);
        replaceInstance(DatagramReceiver.class, "sInstance", null,
                mMockDatagramReceiver);
        replaceInstance(SatelliteSessionController.class, "sInstance", null,
                mMockSatelliteSessionController);
        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
        mDatagramControllerUT = new DatagramController(
                mContext, Looper.myLooper(), mMockPointingAppController);

        // Move both send and receive to IDLE state
        mDatagramControllerUT.updateSendStatus(SUB_ID, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
                0, SATELLITE_RESULT_SUCCESS);
        mDatagramControllerUT.updateReceiveStatus(SUB_ID, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
                0, SATELLITE_RESULT_SUCCESS);
        pushDemoModeSosDatagram();
    }

    @After
    public void tearDown() throws Exception {
        logd(TAG + " tearDown");
        super.tearDown();
    }

    @Test
    public void testUpdateSendStatus() throws Exception {
        testUpdateSendStatus(true, SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING);
        testUpdateSendStatus(true, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
        testUpdateSendStatus(false, SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING);
    }

    @Test
    public void testUpdateReceiveStatus() throws Exception {
        testUpdateReceiveStatus(true, SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
        testUpdateReceiveStatus(true, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
        testUpdateReceiveStatus(false, SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
    }

    @Test
    public void testSetDeviceAlignedWithSatellite() throws Exception {
        testSetDeviceAlignedWithSatellite(true);
        testSetDeviceAlignedWithSatellite(false);
    }

    private void testUpdateSendStatus(boolean isDemoMode, int sendState) {
        mDatagramControllerUT.setDemoMode(isDemoMode);
        clearAllInvocations();

        int sendPendingCount = 1;
        int errorCode = SATELLITE_RESULT_SUCCESS;
        mDatagramControllerUT.updateSendStatus(SUB_ID, sendState, sendPendingCount, errorCode);

        verify(mMockSatelliteSessionController)
                .onDatagramTransferStateChanged(eq(sendState), anyInt());
        verify(mMockPointingAppController).updateSendDatagramTransferState(
                eq(SUB_ID), eq(sendState), eq(sendPendingCount), eq(errorCode));

        if (isDemoMode) {
            if (sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE) {
                verify(mMockDatagramReceiver).pollPendingSatelliteDatagrams(
                        anyInt(), any(Consumer.class));
            }
        } else {
            verify(mMockDatagramReceiver, never()).pollPendingSatelliteDatagrams(
                    anyInt(), any(Consumer.class));
        }
    }

    private void testUpdateReceiveStatus(boolean isDemoMode, int receiveState) {
        mDatagramControllerUT.setDemoMode(isDemoMode);
        clearAllInvocations();

        int receivePendingCount = 1;
        int errorCode = SATELLITE_RESULT_SUCCESS;
        mDatagramControllerUT.updateReceiveStatus(
                SUB_ID, receiveState, receivePendingCount, errorCode);

        verify(mMockSatelliteSessionController)
                .onDatagramTransferStateChanged(anyInt(), eq(receiveState));
        verify(mMockPointingAppController).updateReceiveDatagramTransferState(
                eq(SUB_ID), eq(receiveState), eq(receivePendingCount), eq(errorCode));

        if (isDemoMode && receiveState == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE) {
            verify(mMockDatagramReceiver).pollPendingSatelliteDatagrams(
                    anyInt(), any(Consumer.class));
        } else {
            verify(mMockDatagramReceiver, never()).pollPendingSatelliteDatagrams(
                    anyInt(), any(Consumer.class));
        }
    }

    private void testSetDeviceAlignedWithSatellite(boolean isAligned) {
        mDatagramControllerUT.setDemoMode(true);
        clearAllInvocations();

        mDatagramControllerUT.setDeviceAlignedWithSatellite(isAligned);
        verify(mMockDatagramDispatcher).setDeviceAlignedWithSatellite(eq(isAligned));
        verify(mMockDatagramReceiver).setDeviceAlignedWithSatellite(eq(isAligned));
        if (isAligned) {
            verify(mMockDatagramReceiver).pollPendingSatelliteDatagrams(
                    anyInt(), any(Consumer.class));
        } else {
            verify(mMockDatagramReceiver, never()).pollPendingSatelliteDatagrams(
                    anyInt(), any(Consumer.class));
        }
    }

    private void clearAllInvocations() {
        clearInvocations(mMockSatelliteSessionController);
        clearInvocations(mMockPointingAppController);
        clearInvocations(mMockDatagramReceiver);
        clearInvocations(mMockDatagramDispatcher);
    }

    private void pushDemoModeSosDatagram() {
        String testMessage = "This is a test datagram message";
        SatelliteDatagram datagram = new SatelliteDatagram(testMessage.getBytes());
        mDatagramControllerUT.setDemoMode(true);
        mDatagramControllerUT.pushDemoModeDatagram(DATAGRAM_TYPE_SOS_MESSAGE, datagram);
    }
}
+88 −72

File changed.

Preview size limit exceeded, changes collapsed.

Loading