Merge "Disable signal strength update if screen off" into main
diff --git a/src/java/com/android/internal/telephony/DeviceStateMonitor.java b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
index ecc6208..7bdf2ff 100644
--- a/src/java/com/android/internal/telephony/DeviceStateMonitor.java
+++ b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
@@ -22,6 +22,7 @@
 import static android.hardware.radio.V1_0.DeviceStateType.POWER_SAVE_MODE;
 import static android.telephony.TelephonyManager.HAL_SERVICE_NETWORK;
 
+import android.annotation.NonNull;
 import android.app.UiModeManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -47,6 +48,7 @@
 import android.view.Display;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.telephony.Rlog;
 
@@ -92,10 +94,14 @@
     private static final int NR_NSA_TRACKING_INDICATIONS_ALWAYS_ON = 2;
 
     private final Phone mPhone;
+    @NonNull
+    private final FeatureFlags mFeatureFlags;
 
     private final LocalLog mLocalLog = new LocalLog(64);
 
     private final RegistrantList mPhysicalChannelConfigRegistrants = new RegistrantList();
+    private final RegistrantList mSignalStrengthReportDecisionCallbackRegistrants =
+            new RegistrantList();
 
     private final NetworkRequest mWifiNetworkRequest =
             new NetworkRequest.Builder()
@@ -269,8 +275,9 @@
      *
      * @param phone Phone object
      */
-    public DeviceStateMonitor(Phone phone) {
+    public DeviceStateMonitor(Phone phone, @NonNull FeatureFlags featureFlags) {
         mPhone = phone;
+        mFeatureFlags = featureFlags;
         DisplayManager dm = (DisplayManager) phone.getContext().getSystemService(
                 Context.DISPLAY_SERVICE);
         dm.registerDisplayListener(mDisplayListener, null);
@@ -602,6 +609,15 @@
             // use a null message since we don't care of receiving response
             mPhone.mCi.getBarringInfo(null);
         }
+
+        // Determine whether to notify registrants about the non-terrestrial signal strength change.
+        if (mFeatureFlags.oemEnabledSatelliteFlag()) {
+            if (shouldEnableSignalStrengthReports()) {
+                mSignalStrengthReportDecisionCallbackRegistrants.notifyResult(true);
+            } else {
+                mSignalStrengthReportDecisionCallbackRegistrants.notifyResult(false);
+            }
+        }
     }
 
     /**
@@ -778,6 +794,33 @@
     }
 
     /**
+     * Register a callback to decide whether signal strength should be notified or not.
+     * @param h Handler to notify
+     * @param what msg.what when the message is delivered
+     * @param obj AsyncResult.userObj when the message is delivered
+     */
+    public void registerForSignalStrengthReportDecision(Handler h, int what, Object obj) {
+        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+            Rlog.d(TAG, "oemEnabledSatelliteFlag is disabled");
+            return;
+        }
+        Registrant r = new Registrant(h, what, obj);
+        mSignalStrengthReportDecisionCallbackRegistrants.add(r);
+    }
+
+    /**
+     * Register a callback to decide whether signal strength should be notified or not.
+     * @param h Handler to notify
+     */
+    public void unregisterForSignalStrengthReportDecision(Handler h) {
+        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+            Rlog.d(TAG, "oemEnabledSatelliteFlag is disabled");
+            return;
+        }
+        mSignalStrengthReportDecisionCallbackRegistrants.remove(h);
+    }
+
+    /**
      * @param msg Debug message
      * @param logIntoLocalLog True if log into the local log
      */
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 592c15e..6f30fb5 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -359,7 +359,7 @@
                 .inject(EmergencyNumberTracker.class.getName()).makeEmergencyNumberTracker(
                         this, this.mCi);
         mDeviceStateMonitor = mTelephonyComponentFactory.inject(DeviceStateMonitor.class.getName())
-                .makeDeviceStateMonitor(this);
+                .makeDeviceStateMonitor(this, mFeatureFlags);
 
         // DisplayInfoController creates an OverrideNetworkTypeController, which uses
         // DeviceStateMonitor so needs to be crated after it is instantiated.
diff --git a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
index cdeced8..8b832dd 100644
--- a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
+++ b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
@@ -406,8 +406,12 @@
         return new AppSmsManager(context);
     }
 
-    public DeviceStateMonitor makeDeviceStateMonitor(Phone phone) {
-        return new DeviceStateMonitor(phone);
+    /**
+     * Create a DeviceStateMonitor.
+     */
+    public DeviceStateMonitor makeDeviceStateMonitor(Phone phone,
+            @NonNull FeatureFlags featureFlags) {
+        return new DeviceStateMonitor(phone, featureFlags);
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 044bfd4..896063f 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -74,6 +74,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DeviceStateMonitor;
 import com.android.internal.telephony.IIntegerConsumer;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.flags.FeatureFlags;
@@ -146,7 +147,7 @@
     private static final int EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE = 33;
     private static final int EVENT_NTN_SIGNAL_STRENGTH_CHANGED = 34;
     private static final int CMD_START_SENDING_NTN_SIGNAL_STRENGTH = 35;
-    private static final int EVENT_START_SENDING_NTN_SIGNAL_STRENGTH_DONE = 36;
+    private static final int EVENT_UPDATE_SIGNAL_STRENGTH_REPORTING = 36;
 
     @NonNull private static SatelliteController sInstance;
     @NonNull private final Context mContext;
@@ -159,6 +160,7 @@
     @NonNull private final SubscriptionManagerService mSubscriptionManagerService;
     private final CommandsInterface mCi;
     private ContentResolver mContentResolver = null;
+    private final DeviceStateMonitor mDSM;
 
     private final Object mRadioStateLock = new Object();
 
@@ -299,6 +301,7 @@
         mFeatureFlags = featureFlags;
         Phone phone = SatelliteServiceUtils.getPhone();
         mCi = phone.mCi;
+        mDSM = phone.getDeviceStateMonitor();
         // Create the SatelliteModemInterface singleton, which is used to manage connections
         // to the satellite service and HAL interface.
         mSatelliteModemInterface = SatelliteModemInterface.make(mContext, this);
@@ -353,6 +356,8 @@
                         handleCarrierConfigChanged(slotIndex, subId, carrierId, specificCarrierId);
         mCarrierConfigManager.registerCarrierConfigChangeListener(
                         new HandlerExecutor(new Handler(looper)), mCarrierConfigChangeListener);
+        mDSM.registerForSignalStrengthReportDecision(this, CMD_START_SENDING_NTN_SIGNAL_STRENGTH,
+                null);
     }
 
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@@ -1129,26 +1134,29 @@
             }
 
             case CMD_START_SENDING_NTN_SIGNAL_STRENGTH: {
-                logd("CMD_START_SENDING_NTN_SIGNAL_STRENGTH");
-                request = (SatelliteControllerHandlerRequest) msg.obj;
-                boolean startSendingNtnSignalStrength =  (boolean) request.argument;
-                if (mSatelliteModemInterface.isSatelliteServiceSupported()) {
-                    onCompleted = obtainMessage(EVENT_START_SENDING_NTN_SIGNAL_STRENGTH_DONE,
-                            request);
-                    if (startSendingNtnSignalStrength) {
-                        mSatelliteModemInterface.startSendingNtnSignalStrength(onCompleted);
-                    } else {
-                        mSatelliteModemInterface.stopSendingNtnSignalStrength(onCompleted);
-                    }
+                ar = (AsyncResult) msg.obj;
+                boolean shouldReport = (boolean) ar.result;
+                logd("CMD_START_SENDING_NTN_SIGNAL_STRENGTH: shouldReport=" + shouldReport);
+                request = new SatelliteControllerHandlerRequest(shouldReport,
+                        SatelliteServiceUtils.getPhone());
+                if (SATELLITE_RESULT_SUCCESS != evaluateOemSatelliteRequestAllowed(true)) {
+                    return;
+                }
+                onCompleted = obtainMessage(EVENT_UPDATE_SIGNAL_STRENGTH_REPORTING,
+                        request);
+                if (shouldReport) {
+                    mSatelliteModemInterface.startSendingNtnSignalStrength(onCompleted);
+                } else {
+                    mSatelliteModemInterface.stopSendingNtnSignalStrength(onCompleted);
                 }
                 break;
             }
 
-            case EVENT_START_SENDING_NTN_SIGNAL_STRENGTH_DONE: {
+            case EVENT_UPDATE_SIGNAL_STRENGTH_REPORTING: {
                 ar = (AsyncResult) msg.obj;
                 request = (SatelliteControllerHandlerRequest) ar.userObj;
                 int errorCode =  SatelliteServiceUtils.getSatelliteError(ar,
-                        "EVENT_START_SENDING_NTN_SIGNAL_STRENGTH_DONE");
+                        "EVENT_UPDATE_SIGNAL_STRENGTH_REPORTING");
                 if (errorCode != SATELLITE_RESULT_SUCCESS) {
                     loge(((boolean) request.argument ? "startSendingNtnSignalStrength"
                             : "stopSendingNtnSignalStrength") + "returns " + errorCode);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/DeviceStateMonitorTest.java b/tests/telephonytests/src/com/android/internal/telephony/DeviceStateMonitorTest.java
index 28a37f7..018759a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/DeviceStateMonitorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/DeviceStateMonitorTest.java
@@ -20,7 +20,9 @@
 import static android.hardware.radio.V1_0.DeviceStateType.POWER_SAVE_MODE;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
@@ -30,6 +32,7 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import static java.util.Arrays.asList;
 
@@ -40,22 +43,31 @@
 import android.hardware.radio.V1_5.IndicationFilter;
 import android.net.ConnectivityManager;
 import android.net.TetheringManager;
+import android.os.AsyncResult;
 import android.os.BatteryManager;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
+import com.android.internal.telephony.flags.FeatureFlags;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Map;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
 
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
@@ -114,6 +126,7 @@
 
     private static final int STATE_OFF = 0;
     private static final int STATE_ON = 1;
+    private static final long TIMEOUT = 500;
 
     // The keys are the single IndicationFilter flags,
     // The values are the array of states, when one state turn on, the corresponding
@@ -135,6 +148,9 @@
     UiModeManager mUiModeManager;
 
     private DeviceStateMonitor mDSM;
+    private TestSatelliteController mSatelliteControllerUT;
+
+    @Mock private FeatureFlags mFeatureFlags;
 
     // Given a stateType, return the event type that can change the state
     private int state2Event(@StateType int stateType) {
@@ -162,11 +178,12 @@
     @Before
     public void setUp() throws Exception {
         super.setUp(getClass().getSimpleName());
+        MockitoAnnotations.initMocks(this);
         mUiModeManager = mock(UiModeManager.class);
         mContextFixture.setSystemService(Context.UI_MODE_SERVICE, mUiModeManager);
         // We don't even need a mock executor, we just need to not throw.
         doReturn(null).when(mContextFixture.getTestDouble()).getMainExecutor();
-        mDSM = new DeviceStateMonitor(mPhone);
+        mDSM = new DeviceStateMonitor(mPhone, mFeatureFlags);
 
         // Initialize with ALL states off
         updateAllStatesToOff();
@@ -177,6 +194,7 @@
 
     @After
     public void tearDown() throws Exception {
+        mSatelliteControllerUT = null;
         mDSM = null;
         super.tearDown();
     }
@@ -453,4 +471,160 @@
         verify(mSimulatedCommandsVerifier).setUnsolResponseFilter(
                 eq(INDICATION_FILTERS_MINIMUM), nullable(Message.class));
     }
+
+    @Test
+    public void testRegisterForSignalStrengthReportDecisionWithFeatureEnabled() {
+        logd("testRegisterForSignalStrengthReportDecisionWithFeatureEnabled()");
+        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+        mSatelliteControllerUT = new TestSatelliteController(Looper.myLooper(), mDSM);
+
+        updateState(STATE_TYPE_RADIO_OFF_OR_NOT_AVAILABLE, 0);
+        updateState(STATE_TYPE_SCREEN, STATE_OFF);
+        mSatelliteControllerUT.resetCount();
+        sEventDeviceStatusChanged.drainPermits();
+
+        updateState(STATE_TYPE_SCREEN, STATE_ON);
+        assertTrue(waitForEventDeviceStatusChanged());
+        assertEquals(0, mSatelliteControllerUT.getStartEventCount());
+        assertEquals(1, mSatelliteControllerUT.getStopEventCount());
+        mSatelliteControllerUT.resetCount();
+
+        mSatelliteControllerUT.resetCount();
+        updateState(STATE_TYPE_SCREEN, STATE_OFF);
+        assertTrue(waitForEventDeviceStatusChanged());
+        assertEquals(0, mSatelliteControllerUT.getStartEventCount());
+        assertEquals(1, mSatelliteControllerUT.getStopEventCount());
+        mSatelliteControllerUT.resetCount();
+
+        updateState(STATE_TYPE_RADIO_ON, 0);
+        assertTrue(waitForEventDeviceStatusChanged());
+        assertEquals(0, mSatelliteControllerUT.getStartEventCount());
+        assertEquals(1, mSatelliteControllerUT.getStopEventCount());
+        mSatelliteControllerUT.resetCount();
+
+        updateState(STATE_TYPE_SCREEN, STATE_ON);
+        assertTrue(waitForEventDeviceStatusChanged());
+        assertEquals(1, mSatelliteControllerUT.getStartEventCount());
+        assertEquals(0, mSatelliteControllerUT.getStopEventCount());
+        mSatelliteControllerUT.resetCount();
+
+        updateState(STATE_TYPE_RADIO_OFF_OR_NOT_AVAILABLE, 0);
+        assertTrue(waitForEventDeviceStatusChanged());
+        assertEquals(0, mSatelliteControllerUT.getStartEventCount());
+        assertEquals(1, mSatelliteControllerUT.getStopEventCount());
+    }
+
+    @Test
+    public void testRegisterForSignalStrengthReportDecisionWithFeatureDisabled() {
+        logd("testRegisterForSignalStrengthReportDecisionWithFeatureDisabled()");
+        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
+        mSatelliteControllerUT = new TestSatelliteController(Looper.myLooper(), mDSM);
+
+        updateState(STATE_TYPE_RADIO_OFF_OR_NOT_AVAILABLE, 0);
+        updateState(STATE_TYPE_SCREEN, STATE_OFF);
+        mSatelliteControllerUT.resetCount();
+        sEventDeviceStatusChanged.drainPermits();
+
+
+        /* Sending stop ntn signal strength as radio is off */
+        updateState(STATE_TYPE_SCREEN, STATE_ON);
+        assertFalse(waitForEventDeviceStatusChanged());
+        assertEquals(0, mSatelliteControllerUT.getStartEventCount());
+        assertEquals(0, mSatelliteControllerUT.getStopEventCount());
+
+        updateState(STATE_TYPE_SCREEN, STATE_OFF);
+        assertFalse(waitForEventDeviceStatusChanged());
+        assertEquals(0, mSatelliteControllerUT.getStartEventCount());
+        assertEquals(0, mSatelliteControllerUT.getStopEventCount());
+
+        updateState(STATE_TYPE_RADIO_ON, 0);
+        assertFalse(waitForEventDeviceStatusChanged());
+        assertEquals(0, mSatelliteControllerUT.getStartEventCount());
+        assertEquals(0, mSatelliteControllerUT.getStopEventCount());
+
+        updateState(STATE_TYPE_SCREEN, STATE_ON);
+        assertFalse(waitForEventDeviceStatusChanged());
+        assertEquals(0, mSatelliteControllerUT.getStartEventCount());
+        assertEquals(0, mSatelliteControllerUT.getStopEventCount());
+
+        updateState(STATE_TYPE_RADIO_OFF_OR_NOT_AVAILABLE, 0);
+        assertFalse(waitForEventDeviceStatusChanged());
+        assertEquals(0, mSatelliteControllerUT.getStartEventCount());
+        assertEquals(0, mSatelliteControllerUT.getStopEventCount());
+    }
+
+    private static Semaphore sEventDeviceStatusChanged = new Semaphore(0);
+    private boolean waitForEventDeviceStatusChanged() {
+        try {
+            if (!sEventDeviceStatusChanged.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) {
+                logd("Time out to receive EVENT_DEVICE_STATUS_CHANGED");
+                return false;
+            }
+        } catch (Exception ex) {
+            logd("waitForEventDeviceStatusChanged: ex=" + ex);
+            return false;
+        }
+        return true;
+    }
+
+    private static class TestSatelliteController extends Handler {
+        public static final int EVENT_DEVICE_STATUS_CHANGED = 35;
+        private final DeviceStateMonitor mDsm;
+        private int mStartEventCount;
+        private int mStopEventCount;
+
+        TestSatelliteController(Looper looper, DeviceStateMonitor dsm) {
+            super(looper);
+            mDsm = dsm;
+            mDsm.registerForSignalStrengthReportDecision(this, EVENT_DEVICE_STATUS_CHANGED, null);
+        }
+
+        /**
+         * Resets the count of occurred events.
+         */
+        public void resetCount() {
+            mStartEventCount = 0;
+            mStopEventCount = 0;
+        }
+
+        public int getStartEventCount() {
+            return mStartEventCount;
+        }
+
+        public int getStopEventCount() {
+            return mStopEventCount;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+                case EVENT_DEVICE_STATUS_CHANGED: {
+                    logd("EVENT_DEVICE_STATUS_CHANGED");
+                    AsyncResult ar = (AsyncResult) msg.obj;
+                    boolean shouldReport = (boolean) ar.result;
+                    if (shouldReport) {
+                        startSendingNtnSignalStrength();
+                    } else {
+                        stopSendingNtnSignalStrength();
+                    }
+                    try {
+                        sEventDeviceStatusChanged.release();
+                    } catch (Exception ex) {
+                        logd("waitForEventDeviceStatusChanged: ex=" + ex);
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+        }
+
+        private void startSendingNtnSignalStrength() {
+            mStartEventCount++;
+        }
+
+        private void stopSendingNtnSignalStrength() {
+            mStopEventCount++;
+        }
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index e1162ea..3ed20a7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -611,7 +611,7 @@
         doReturn(mCarrierActionAgent).when(mTelephonyComponentFactory)
                 .makeCarrierActionAgent(nullable(Phone.class));
         doReturn(mDeviceStateMonitor).when(mTelephonyComponentFactory)
-                .makeDeviceStateMonitor(nullable(Phone.class));
+                .makeDeviceStateMonitor(nullable(Phone.class), any(FeatureFlags.class));
         doReturn(mAccessNetworksManager).when(mTelephonyComponentFactory)
                 .makeAccessNetworksManager(nullable(Phone.class), any(Looper.class));
         doReturn(mNitzStateMachine).when(mTelephonyComponentFactory)
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
index 0354c0d..2feb34d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -2231,6 +2231,84 @@
                 semaphore, 0, "testRegisterForNtnSignalStrengthChanged"));
     }
 
+    @Test
+    public void testSendingNtnSignalStrengthWithFeatureEnabled() {
+        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+
+        int expectedResult = SATELLITE_RESULT_SUCCESS;
+        // startSendingNtnSignalStrength() is requested when screen on event comes.
+        reset(mMockSatelliteModemInterface);
+        doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+        setUpResponseForRequestIsSatelliteSupported(true, expectedResult);
+        setUpResponseForRequestIsSatelliteProvisioned(true, expectedResult);
+        verifySatelliteSupported(true, expectedResult);
+        verifySatelliteProvisioned(true, expectedResult);
+        setUpResponseForStartSendingNtnSignalStrength(expectedResult);
+        sendCmdStartSendingNtnSignalStrengthChangedEvent(true);
+        processAllMessages();
+        verify(mMockSatelliteModemInterface, times(1))
+                .startSendingNtnSignalStrength(any(Message.class));
+
+        // stopSendingNtnSignalStrength() is requested when screen off event comes.
+        reset(mMockSatelliteModemInterface);
+        setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+        setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+        doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+        setUpResponseForStopSendingNtnSignalStrength(expectedResult);
+        sendCmdStartSendingNtnSignalStrengthChangedEvent(false);
+        processAllMessages();
+        verify(mMockSatelliteModemInterface, times(1))
+                .stopSendingNtnSignalStrength(any(Message.class));
+
+        // startSendingNtnSignalStrength() is requested but received fail from the service.
+        reset(mMockSatelliteModemInterface);
+        doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+        setUpResponseForStartSendingNtnSignalStrength(SATELLITE_RESULT_INVALID_MODEM_STATE);
+        sendCmdStartSendingNtnSignalStrengthChangedEvent(true);
+        processAllMessages();
+        verify(mMockSatelliteModemInterface, times(1))
+                .startSendingNtnSignalStrength(any(Message.class));
+
+        // stopSendingNtnSignalStrength() is requested but received fail from the service.
+        reset(mMockSatelliteModemInterface);
+        doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+        setUpResponseForStopSendingNtnSignalStrength(SATELLITE_RESULT_NO_RESOURCES);
+        sendCmdStartSendingNtnSignalStrengthChangedEvent(false);
+        processAllMessages();
+        verify(mMockSatelliteModemInterface, times(1))
+                .stopSendingNtnSignalStrength(any(Message.class));
+    }
+
+    @Test
+    public void testSendingNtnSignalStrengthWithFeatureDisabled() {
+        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
+
+        int expectedResult = SATELLITE_RESULT_SUCCESS;
+        // startSendingNtnSignalStrength() is requested when screen on event comes.
+        reset(mMockSatelliteModemInterface);
+        doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+        setUpResponseForRequestIsSatelliteSupported(true, expectedResult);
+        setUpResponseForRequestIsSatelliteProvisioned(true, expectedResult);
+        verifySatelliteSupported(false, SATELLITE_RESULT_NOT_SUPPORTED);
+        verifySatelliteProvisioned(false, SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
+        setUpResponseForStartSendingNtnSignalStrength(expectedResult);
+        sendCmdStartSendingNtnSignalStrengthChangedEvent(true);
+        processAllMessages();
+        verify(mMockSatelliteModemInterface, never())
+                .startSendingNtnSignalStrength(any(Message.class));
+
+        // stopSendingNtnSignalStrength() is requested when screen off event comes.
+        reset(mMockSatelliteModemInterface);
+        setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+        setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+        doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+        setUpResponseForStopSendingNtnSignalStrength(expectedResult);
+        sendCmdStartSendingNtnSignalStrengthChangedEvent(false);
+        processAllMessages();
+        verify(mMockSatelliteModemInterface, never())
+                .stopSendingNtnSignalStrength(any(Message.class));
+    }
+
     private void resetSatelliteControllerUTEnabledState() {
         logd("resetSatelliteControllerUTEnabledState");
         setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
@@ -2524,6 +2602,30 @@
         }).when(mMockPointingAppController).stopSatelliteTransmissionUpdates(any(Message.class));
     }
 
+    private void setUpResponseForStartSendingNtnSignalStrength(
+            @SatelliteManager.SatelliteResult int error) {
+        SatelliteException exception = (error == SATELLITE_RESULT_SUCCESS)
+                ? null : new SatelliteException(error);
+        doAnswer(invocation -> {
+            Message message = (Message) invocation.getArguments()[0];
+            AsyncResult.forMessage(message, null, exception);
+            message.sendToTarget();
+            return null;
+        }).when(mMockSatelliteModemInterface).startSendingNtnSignalStrength(any(Message.class));
+    }
+
+    private void setUpResponseForStopSendingNtnSignalStrength(
+            @SatelliteManager.SatelliteResult int error) {
+        SatelliteException exception = (error == SATELLITE_RESULT_SUCCESS)
+                ? null : new SatelliteException(error);
+        doAnswer(invocation -> {
+            Message message = (Message) invocation.getArguments()[0];
+            AsyncResult.forMessage(message, null, exception);
+            message.sendToTarget();
+            return null;
+        }).when(mMockSatelliteModemInterface).stopSendingNtnSignalStrength(any(Message.class));
+    }
+
     private boolean waitForRequestIsSatelliteSupportedResult(int expectedNumberOfEvents) {
         for (int i = 0; i < expectedNumberOfEvents; i++) {
             try {
@@ -2728,6 +2830,23 @@
         msg.sendToTarget();
     }
 
+    private void sendCmdStartSendingNtnSignalStrengthChangedEvent(boolean shouldReport) {
+        Message msg = mSatelliteControllerUT.obtainMessage(
+                35 /* CMD_START_SENDING_NTN_SIGNAL_STRENGTH */);
+        msg.obj = new AsyncResult(null, shouldReport, null);
+        msg.sendToTarget();
+    }
+
+    private void sendStartSendingNtnSignalStrengthChangedEvent(
+            @NtnSignalStrength.NtnSignalStrengthLevel int ntnSignalStrengthLevel,
+            Throwable exception) {
+        Message msg = mSatelliteControllerUT.obtainMessage(
+                36 /* EVENT_START_SENDING_NTN_SIGNAL_STRENGTH_DONE */);
+        msg.obj = new AsyncResult(null, new NtnSignalStrength(ntnSignalStrengthLevel),
+                exception);
+        msg.sendToTarget();
+    }
+
     private void setRadioPower(boolean on) {
         mSimulatedCommands.setRadioPower(on, false, false, null);
     }