Add satellite modem state logic for calls

For emergency calls, turn off the satellite modem and retry.
For normal calls, return an error.

Test: unit tests, CTS
Test: manual verify normal call and fake emergency call
Bug: 278578254
Change-Id: I3f2ce290148049dd0b7b945c634ae68afb2caf91
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 16d27b3..02c413e 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -1063,6 +1063,7 @@
 
         boolean needToTurnOnRadio = (isEmergencyNumber && (!isRadioOn() || isAirplaneModeOn))
                 || isRadioPowerDownOnBluetooth();
+        boolean needToTurnOffSatellite = isSatelliteBlockingCall(isEmergencyNumber);
 
         // Get the right phone object from the account data passed in.
         final Phone phone = getPhoneForAccount(request.getAccountHandle(), isEmergencyNumber,
@@ -1080,7 +1081,7 @@
             }
         }
 
-        if (needToTurnOnRadio) {
+        if (needToTurnOnRadio || needToTurnOffSatellite) {
             final Uri resultHandle = handle;
             final int originalPhoneType = phone.getPhoneType();
             final Connection resultConnection = getTelephonyConnection(request, numberToDial,
@@ -1134,8 +1135,9 @@
                         // We should be able to make emergency calls at any time after the radio has
                         // been powered on and isn't in the UNAVAILABLE state, even if it is
                         // reporting the OUT_OF_SERVICE state.
-                        return (phone.getState() == PhoneConstants.State.OFFHOOK)
-                            || phone.getServiceStateTracker().isRadioOn();
+                        return phone.getState() == PhoneConstants.State.OFFHOOK
+                                || (phone.getServiceStateTracker().isRadioOn()
+                                && !mSatelliteController.isSatelliteEnabled());
                     } else {
                         SubscriptionInfoInternal subInfo = SubscriptionManagerService
                                 .getInstance().getSubscriptionInfoInternal(phone.getSubId());
@@ -1144,10 +1146,11 @@
                         // if it is a test emergency number and we have to wait for the device
                         // to move IN_SERVICE before the call can take place over normal
                         // routing.
-                        return (phone.getState() == PhoneConstants.State.OFFHOOK)
+                        return phone.getState() == PhoneConstants.State.OFFHOOK
                                 // Do not wait for voice in service on opportunistic SIMs.
-                                || (subInfo != null && subInfo.isOpportunistic())
-                                || serviceState == ServiceState.STATE_IN_SERVICE;
+                                || subInfo != null && subInfo.isOpportunistic()
+                                || (serviceState == ServiceState.STATE_IN_SERVICE
+                                && !isSatelliteBlockingCall(isEmergencyNumber));
                     }
                 }
             }, isEmergencyNumber && !isTestEmergencyNumber, phone, isTestEmergencyNumber,
@@ -1324,11 +1327,19 @@
                 });
             }
         } else {
-            Log.w(this, "onCreateOutgoingConnection, failed to turn on radio");
-            closeOrDestroyConnection(originalConnection,
-                    mDisconnectCauseFactory.toTelecomDisconnectCause(
-                            android.telephony.DisconnectCause.POWER_OFF,
-                            "Failed to turn on radio."));
+            if (isSatelliteBlockingCall(isEmergencyNumber)) {
+                Log.w(LOG_TAG, "handleOnComplete, failed to turn off satellite modem");
+                closeOrDestroyConnection(originalConnection,
+                        mDisconnectCauseFactory.toTelecomDisconnectCause(
+                                android.telephony.DisconnectCause.SATELLITE_ENABLED,
+                                "Failed to turn off satellite modem."));
+            } else {
+                Log.w(LOG_TAG, "handleOnComplete, failed to turn on radio");
+                closeOrDestroyConnection(originalConnection,
+                        mDisconnectCauseFactory.toTelecomDisconnectCause(
+                                android.telephony.DisconnectCause.POWER_OFF,
+                                "Failed to turn on radio."));
+            }
             mIsEmergencyCallPending = false;
         }
     }
@@ -1491,14 +1502,6 @@
             }
         }
 
-        if (!isSatelliteStateValid(isEmergencyNumber)) {
-            Log.d(this, "onCreateOutgoingConnection, cannot make call in satellite mode.");
-            return Connection.createFailedConnection(
-                    mDisconnectCauseFactory.toTelecomDisconnectCause(
-                            android.telephony.DisconnectCause.SATELLITE_ENABLED,
-                            "Call failed because satellite modem is enabled."));
-        }
-
         final boolean isTtyModeEnabled = mDeviceState.isTtyModeEnabled(this);
         if (VideoProfile.isVideo(request.getVideoState()) && isTtyModeEnabled
                 && !isEmergencyNumber) {
@@ -1977,11 +1980,11 @@
         return result;
     }
 
-    private boolean isSatelliteStateValid(boolean isEmergencyNumber) {
+    private boolean isSatelliteBlockingCall(boolean isEmergencyNumber) {
         if (isEmergencyNumber) {
-            return !mSatelliteController.isSatelliteEnabled();
+            return mSatelliteController.isSatelliteEnabled();
         } else {
-            return !mSatelliteController.isDemoModeEnabled();
+            return mSatelliteController.isDemoModeEnabled();
         }
     }
 
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index 90fc0a9..4f9b879 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -1297,6 +1297,42 @@
     }
 
     /**
+     * Test that the TelephonyConnectionService successfully turns satellite off before placing the
+     * emergency call.
+     */
+    @Test
+    @SmallTest
+    public void testCreateOutgoingEmergencyConnection_exitingSatellite_placeCall() {
+        when(mSatelliteController.isSatelliteEnabled()).thenReturn(true);
+        Phone testPhone = setupConnectionServiceInApm();
+
+        ArgumentCaptor<RadioOnStateListener.Callback> callback =
+                ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
+        verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
+                eq(testPhone), eq(false), eq(0));
+
+        assertFalse(callback.getValue()
+                .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
+        when(mSST.isRadioOn()).thenReturn(true);
+        assertFalse(callback.getValue()
+                .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
+        when(mSatelliteController.isSatelliteEnabled()).thenReturn(false);
+        assertTrue(callback.getValue()
+                .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
+
+        callback.getValue().onComplete(null, true);
+
+        try {
+            doAnswer(invocation -> null).when(mContext).startActivity(any());
+            verify(testPhone).dial(anyString(), any(), any());
+        } catch (CallStateException e) {
+            // This shouldn't happen
+            fail();
+        }
+        verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), any());
+    }
+
+    /**
      * Test that the TelephonyConnectionService does not perform a DDS switch when the carrier
      * supports control-plane fallback.
      */