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

Commit 7a59c650 authored by Hakjun Choi's avatar Hakjun Choi Committed by Android (Google) Code Review
Browse files

Merge "Create a device config indicates whether to send message in demo mode or not" into main

parents 29b39be0 01a5dab1
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ public class DatagramController {
    @NonNull private final PointingAppController mPointingAppController;
    @NonNull private final DatagramDispatcher mDatagramDispatcher;
    @NonNull private final DatagramReceiver mDatagramReceiver;

    public static final long MAX_DATAGRAM_ID = (long) Math.pow(2, 16);
    public static final int ROUNDING_UNIT = 10;
    public static final long SATELLITE_ALIGN_TIMEOUT = TimeUnit.SECONDS.toMillis(30);
@@ -403,6 +404,18 @@ public class DatagramController {
        }
    }

    /**
     * This API can be used by only CTS to override the cached value for the device overlay config
     * value : config_send_satellite_datagram_to_modem_in_demo_mode, which determines whether
     * outgoing satellite datagrams should be sent to modem in demo mode.
     *
     * @param shouldSendToModemInDemoMode Whether send datagram in demo mode should be sent to
     * satellite modem or not.
     */
    void setShouldSendDatagramToModemInDemoMode(boolean shouldSendToModemInDemoMode) {
        mDatagramDispatcher.setShouldSendDatagramToModemInDemoMode(shouldSendToModemInDemoMode);
    }

    private static void logd(@NonNull String log) {
        Rlog.d(TAG, log);
    }
+58 −3
Original line number Diff line number Diff line
@@ -17,12 +17,14 @@
package com.android.internal.telephony.satellite;

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

import static com.android.internal.telephony.satellite.DatagramController.ROUNDING_UNIT;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
@@ -32,6 +34,7 @@ import android.telephony.SubscriptionManager;
import android.telephony.satellite.SatelliteDatagram;
import android.telephony.satellite.SatelliteManager;

import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
@@ -41,6 +44,7 @@ import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;

@@ -66,6 +70,8 @@ public class DatagramDispatcher extends Handler {

    private static AtomicLong mNextDatagramId = new AtomicLong(0);

    private AtomicBoolean mShouldSendDatagramToModemInDemoMode = null;

    private final Object mLock = new Object();

    @GuardedBy("mLock")
@@ -190,9 +196,14 @@ public class DatagramDispatcher extends Handler {
                        (SendSatelliteDatagramArgument) request.argument;
                onCompleted = obtainMessage(EVENT_SEND_SATELLITE_DATAGRAM_DONE, request);

                if (mIsDemoMode && !shouldSendDatagramToModemInDemoMode()) {
                    AsyncResult.forMessage(onCompleted, SATELLITE_RESULT_SUCCESS, null);
                    onCompleted.sendToTarget();
                } else {
                    SatelliteModemInterface.getInstance().sendSatelliteDatagram(argument.datagram,
                            argument.datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
                            argument.needFullScreenPointingUI, onCompleted);
                }
                break;
            }
            case EVENT_SEND_SATELLITE_DATAGRAM_DONE: {
@@ -621,6 +632,50 @@ public class DatagramDispatcher extends Handler {
        }
    }

    private boolean shouldSendDatagramToModemInDemoMode() {
        if (mShouldSendDatagramToModemInDemoMode != null) {
            return mShouldSendDatagramToModemInDemoMode.get();
        }

        try {
            mShouldSendDatagramToModemInDemoMode = new AtomicBoolean(
                    mContext.getResources().getBoolean(
                            R.bool.config_send_satellite_datagram_to_modem_in_demo_mode));
            return mShouldSendDatagramToModemInDemoMode.get();

        } catch (Resources.NotFoundException ex) {
            loge("shouldSendDatagramToModemInDemoMode: id= "
                    + R.bool.config_send_satellite_datagram_to_modem_in_demo_mode + ", ex=" + ex);
            return false;
        }
    }

    /**
     * This API can be used by only CTS to override the cached value for the device overlay config
     * value : config_send_satellite_datagram_to_modem_in_demo_mode, which determines whether
     * outgoing satellite datagrams should be sent to modem in demo mode.
     *
     * @param shouldSendToModemInDemoMode Whether send datagram in demo mode should be sent to
     * satellite modem or not. If it is null, the cache will be cleared.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    protected void setShouldSendDatagramToModemInDemoMode(
            @Nullable Boolean shouldSendToModemInDemoMode) {
        logd("setShouldSendDatagramToModemInDemoMode(" + (shouldSendToModemInDemoMode == null
                ? "null" : shouldSendToModemInDemoMode) + ")");

        if (shouldSendToModemInDemoMode == null) {
            mShouldSendDatagramToModemInDemoMode = null;
        } else {
            if (mShouldSendDatagramToModemInDemoMode == null) {
                mShouldSendDatagramToModemInDemoMode = new AtomicBoolean(
                        shouldSendToModemInDemoMode);
            } else {
                mShouldSendDatagramToModemInDemoMode.set(shouldSendToModemInDemoMode);
            }
        }
    }

    private static void logd(@NonNull String log) {
        Rlog.d(TAG, log);
    }
+25 −0
Original line number Diff line number Diff line
@@ -3358,6 +3358,31 @@ public class SatelliteController extends Handler {
        }
    }

    /**
     * This API can be used by only CTS to override the cached value for the device overlay config
     * value : config_send_satellite_datagram_to_modem_in_demo_mode, which determines whether
     * outgoing satellite datagrams should be sent to modem in demo mode.
     *
     * @param shouldSendToModemInDemoMode Whether send datagram in demo mode should be sent to
     * satellite modem or not.
     *
     * @return {@code true} if the operation is successful, {@code false} otherwise.
     */
    public boolean setShouldSendDatagramToModemInDemoMode(boolean shouldSendToModemInDemoMode) {
        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
            logd("setShouldSendDatagramToModemInDemoMode: oemEnabledSatelliteFlag is disabled");
            return false;
        }

        if (!isMockModemAllowed()) {
            logd("setShouldSendDatagramToModemInDemoMode: mock modem not allowed.");
            return false;
        }

        mDatagramController.setShouldSendDatagramToModemInDemoMode(shouldSendToModemInDemoMode);
        return true;
    }

    private static void logd(@NonNull String log) {
        Rlog.d(TAG, log);
    }
+115 −2
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -38,16 +40,19 @@ import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.os.AsyncResult;
import android.os.Looper;
import android.os.Message;
import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.telephony.satellite.SatelliteDatagram;
import android.telephony.satellite.SatelliteManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;

import com.android.internal.R;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyTest;
@@ -61,8 +66,12 @@ import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -88,6 +97,22 @@ public class DatagramDispatcherTest extends TelephonyTest {
    SatelliteDatagram mDatagram;
    InOrder mInOrder;

    private static final long TIMEOUT = 500;
    private List<Integer> mIntegerConsumerResult = new ArrayList<>();
    private Semaphore mIntegerConsumerSemaphore = new Semaphore(0);
    private Consumer<Integer> mIntegerConsumer = integer -> {
        logd("mIntegerConsumer: integer=" + integer);
        mIntegerConsumerResult.add(integer);
        try {
            mIntegerConsumerSemaphore.release();
        } catch (Exception ex) {
            loge("mIntegerConsumer: Got exception in releasing semaphore, ex=" + ex);
        }
    };

    private final int mConfigSendSatelliteDatagramToModemInDemoMode =
            R.bool.config_send_satellite_datagram_to_modem_in_demo_mode;

    @Before
    public void setUp() throws Exception {
        super.setUp(getClass().getSimpleName());
@@ -105,6 +130,7 @@ public class DatagramDispatcherTest extends TelephonyTest {
        replaceInstance(SatelliteSessionController.class, "sInstance", null,
                mMockSatelliteSessionController);

        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
        mDatagramDispatcherUT = DatagramDispatcher.make(mContext, Looper.myLooper(),
                mMockDatagramController);
        mTestDemoModeDatagramDispatcher = new TestDatagramDispatcher(mContext, Looper.myLooper(),
@@ -358,12 +384,13 @@ public class DatagramDispatcherTest extends TelephonyTest {
        doAnswer(invocation -> {
            Message message = (Message) invocation.getArguments()[3];
            mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
                            new AsyncResult(message.obj, null, null))
                    .sendToTarget();
                    new AsyncResult(message.obj, SatelliteManager.SATELLITE_RESULT_SUCCESS,
                            null)).sendToTarget();
            return null;
        }).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class),
                anyBoolean(), anyBoolean(), any(Message.class));
        mTestDemoModeDatagramDispatcher.setDemoMode(true);
        mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(true);
        replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[] {mPhone});

        mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE2, mDatagram,
@@ -446,6 +473,82 @@ public class DatagramDispatcherTest extends TelephonyTest {
                        eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
    }

    @Test
    public void testSendSatelliteDatagramToModemInDemoMode()
            throws Exception {
        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);

        doAnswer(invocation -> {
            Message message = (Message) invocation.getArguments()[3];
            mTestDemoModeDatagramDispatcher.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
                            new AsyncResult(message.obj, null, null))
                    .sendToTarget();
            return null;
        }).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class),
                anyBoolean(), anyBoolean(), any(Message.class));
        mTestDemoModeDatagramDispatcher.setDemoMode(true);
        mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(true);
        mIntegerConsumerSemaphore.drainPermits();

        // Test when overlay config config_send_satellite_datagram_to_modem_in_demo_mode is true
        mTestDemoModeDatagramDispatcher.setShouldSendDatagramToModemInDemoMode(null);
        mContextFixture.putBooleanResource(mConfigSendSatelliteDatagramToModemInDemoMode, true);
        mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
                true, mIntegerConsumer);
        processAllMessages();
        waitForIntegerConsumerResult(1);
        assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS,
                (int) mIntegerConsumerResult.get(0));
        mIntegerConsumerResult.clear();
        verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
                any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));

        // Test when overlay config config_send_satellite_datagram_to_modem_in_demo_mode is false
        reset(mMockSatelliteModemInterface);
        mTestDemoModeDatagramDispatcher.setShouldSendDatagramToModemInDemoMode(null);
        mContextFixture.putBooleanResource(mConfigSendSatelliteDatagramToModemInDemoMode, false);
        mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
                true, mIntegerConsumer);
        processAllMessages();
        waitForIntegerConsumerResult(1);
        assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS,
                (int) mIntegerConsumerResult.get(0));
        mIntegerConsumerResult.clear();
        verify(mMockSatelliteModemInterface, never()).sendSatelliteDatagram(
                any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));

        // Send datagram one more time
        reset(mMockSatelliteModemInterface);
        mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
                true, mIntegerConsumer);
        processAllMessages();
        waitForIntegerConsumerResult(1);
        assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS,
                (int) mIntegerConsumerResult.get(0));
        mIntegerConsumerResult.clear();
        verify(mMockSatelliteModemInterface, never()).sendSatelliteDatagram(
                any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));

        mTestDemoModeDatagramDispatcher.setDemoMode(false);
        mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(false);
        mTestDemoModeDatagramDispatcher.setShouldSendDatagramToModemInDemoMode(null);
    }

    private boolean waitForIntegerConsumerResult(int expectedNumberOfEvents) {
        for (int i = 0; i < expectedNumberOfEvents; i++) {
            try {
                if (!mIntegerConsumerSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) {
                    loge("Timeout to receive IIntegerConsumer() callback");
                    return false;
                }
            } catch (Exception ex) {
                loge("waitForIIntegerConsumerResult: Got exception=" + ex);
                return false;
            }
        }
        return true;
    }

    private static class TestDatagramDispatcher extends DatagramDispatcher {
        private long mLong = SATELLITE_ALIGN_TIMEOUT;

@@ -469,8 +572,18 @@ public class DatagramDispatcherTest extends TelephonyTest {
            return mLong;
        }

        @Override
        protected void setShouldSendDatagramToModemInDemoMode(
                @Nullable Boolean shouldSendToModemInDemoMode) {
            super.setShouldSendDatagramToModemInDemoMode(shouldSendToModemInDemoMode);
        }

        public void setDuration(long duration) {
            mLong = duration;
        }
    }

    private static void loge(String message) {
        Rlog.e(TAG, message);
    }
}