Merge "Switch stacks when the current stack has limited service" into 24D1-dev
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 75d8622..e6b1adb 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -589,7 +589,7 @@
     <string name="onscreenManageConferenceText" msgid="4700574060601755137">"कॉन्फ़्रेंस प्रबंधित करें"</string>
     <string name="onscreenAudioText" msgid="7224226735052019986">"ऑडियो"</string>
     <string name="onscreenVideoCallText" msgid="1743992456126258698">"वीडियो कॉल"</string>
-    <string name="importSimEntry" msgid="3892354284082689894">"आयात करें"</string>
+    <string name="importSimEntry" msgid="3892354284082689894">"इंपोर्ट करें"</string>
     <string name="importAllSimEntries" msgid="2628391505643564007">"सभी आयात करें"</string>
     <string name="importingSimContacts" msgid="4995457122107888932">"सिम संपर्क आयात कर रहा है"</string>
     <string name="importToFDNfromContacts" msgid="5068664870738407341">"संपर्कों से आयात करें"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index df4d7c8..1afc0ff 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -482,8 +482,8 @@
     <string name="fdn_failed" msgid="216592346853420250">"FDN कार्य बिफल भयो।"</string>
     <string name="simContacts_emptyLoading" msgid="4989040293858675483">"SIM कार्ड पढ्दै..."</string>
     <string name="simContacts_empty" msgid="1135632055473689521">"तपाईँको SIM कार्डमा कुनै पनि सम्पर्क छैन।"</string>
-    <string name="simContacts_title" msgid="2714029230160136647">"सम्पर्कहरू आयात गर्न चयन गर्नुहोस्"</string>
-    <string name="simContacts_airplaneMode" msgid="4654884030631503808">"SIM कार्डबाट सम्पर्कहरू आयात गर्न हवाइजहाज मोड बन्द गर्नुहोस्।"</string>
+    <string name="simContacts_title" msgid="2714029230160136647">"कन्ट्याक्टहरू इम्पोर्ट गर्न चयन गर्नुहोस्"</string>
+    <string name="simContacts_airplaneMode" msgid="4654884030631503808">"SIM कार्डबाट कन्ट्याक्टहरू इम्पोर्ट गर्न हवाइजहाज मोड बन्द गर्नुहोस्।"</string>
     <string name="enable_pin" msgid="967674051730845376">"SIM PIN सक्षम/अक्षम गर्नुहोस्"</string>
     <string name="change_pin" msgid="3657869530942905790">"SIM को PIN परिवर्तन गर्नुहोस्"</string>
     <string name="enter_pin_text" msgid="3182311451978663356">"SIM PIN:"</string>
@@ -589,12 +589,12 @@
     <string name="onscreenManageConferenceText" msgid="4700574060601755137">"सम्मेलन प्रबन्ध गर्नुहोस्"</string>
     <string name="onscreenAudioText" msgid="7224226735052019986">"अडियो"</string>
     <string name="onscreenVideoCallText" msgid="1743992456126258698">"भिडियो कल"</string>
-    <string name="importSimEntry" msgid="3892354284082689894">"आयात गर्नुहोस्"</string>
-    <string name="importAllSimEntries" msgid="2628391505643564007">"सबै आयात गर्नुहोस्"</string>
-    <string name="importingSimContacts" msgid="4995457122107888932">"SIM सम्पर्कहरू आयात गर्दै"</string>
-    <string name="importToFDNfromContacts" msgid="5068664870738407341">"सम्पर्कहरूबाट आयात गर्नुहोस्"</string>
+    <string name="importSimEntry" msgid="3892354284082689894">"इम्पोर्ट गर्नुहोस्"</string>
+    <string name="importAllSimEntries" msgid="2628391505643564007">"सबै इम्पोर्ट गर्नुहोस्"</string>
+    <string name="importingSimContacts" msgid="4995457122107888932">"SIM कन्ट्याक्टहरू आयात गर्दै"</string>
+    <string name="importToFDNfromContacts" msgid="5068664870738407341">"कन्ट्याक्टबाट इम्पोर्ट गर्नुहोस्"</string>
     <string name="singleContactImportedMsg" msgid="3619804066300998934">"आयातित सम्पर्क"</string>
-    <string name="failedToImportSingleContactMsg" msgid="228095510489830266">"सम्पर्क आयात गर्न असफल"</string>
+    <string name="failedToImportSingleContactMsg" msgid="228095510489830266">"सम्पर्क इम्पोर्ट गर्न असफल"</string>
     <string name="hac_mode_title" msgid="4127986689621125468">"श्रवणका लागि सहयोगी यन्त्रहरू"</string>
     <string name="hac_mode_summary" msgid="7774989500136009881">"श्रवण सहायता अनुकूलता खोल्नुहोस्"</string>
     <string name="rtt_mode_title" msgid="3075948111362818043">"द्रुत टेक्स्ट म्यासेज (RTT) कल"</string>
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index f410fad..70ebcdf 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -8784,12 +8784,18 @@
     }
 
     /**
-     * Returns the service state information on specified subscription.
+     * Returns the service state information on specified SIM slot.
      */
     @Override
-    public ServiceState getServiceStateForSubscriber(int subId,
-            boolean renounceFineLocationAccess, boolean renounceCoarseLocationAccess,
-            String callingPackage, String callingFeatureId) {
+    public ServiceState getServiceStateForSlot(int slotIndex, boolean renounceFineLocationAccess,
+            boolean renounceCoarseLocationAccess, String callingPackage, String callingFeatureId) {
+        Phone phone = PhoneFactory.getPhone(slotIndex);
+        if (phone == null) {
+            loge("getServiceStateForSlot retuning null for invalid slotIndex=" + slotIndex);
+            return null;
+        }
+
+        int subId = phone.getSubId();
         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                 mApp, subId, callingPackage, callingFeatureId, "getServiceStateForSubscriber")) {
             return null;
@@ -8808,7 +8814,7 @@
                                     .setCallingFeatureId(callingFeatureId)
                                     .setCallingPid(Binder.getCallingPid())
                                     .setCallingUid(Binder.getCallingUid())
-                                    .setMethod("getServiceStateForSubscriber")
+                                    .setMethod("getServiceStateForSlot")
                                     .setLogAsInfo(true)
                                     .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
                                     .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
@@ -8826,7 +8832,7 @@
                                     .setCallingFeatureId(callingFeatureId)
                                     .setCallingPid(Binder.getCallingPid())
                                     .setCallingUid(Binder.getCallingUid())
-                                    .setMethod("getServiceStateForSubscriber")
+                                    .setMethod("getServiceStateForSlot")
                                     .setLogAsInfo(true)
                                     .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
                                     .setMinSdkVersionForFine(Integer.MAX_VALUE)
@@ -8836,26 +8842,18 @@
                     coarseLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
         }
 
-        final Phone phone = getPhone(subId);
-        if (phone == null) {
-            return null;
-        }
-
         final long identity = Binder.clearCallingIdentity();
-
-        boolean isCallingPackageDataService = phone.getDataServicePackages()
-                .contains(callingPackage);
         try {
-            // isActiveSubId requires READ_PHONE_STATE, which we already check for above
             SubscriptionInfoInternal subInfo = getSubscriptionManagerService()
                     .getSubscriptionInfoInternal(subId);
-            if (subInfo == null || !subInfo.isActive()) {
-                Rlog.d(LOG_TAG, "getServiceStateForSubscriber returning null for inactive "
-                        + "subId=" + subId);
+            if (subInfo != null && !subInfo.isActive()) {
+                log("getServiceStateForSlot returning null for inactive subId=" + subId);
                 return null;
             }
 
             ServiceState ss = phone.getServiceState();
+            boolean isCallingPackageDataService = phone.getDataServicePackages()
+                    .contains(callingPackage);
 
             // Scrub out the location info in ServiceState depending on what level of access
             // the caller has.
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index fe65ce2..77bc32a 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -78,6 +78,7 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Predicate;
@@ -1715,6 +1716,35 @@
                             new AccountEntry(PhoneFactory.getDefaultPhone(), true /* emergency */,
                                     false /* isTest */));
                 }
+
+                // In some very rare cases, when setting the default voice sub in
+                // SubscriptionManagerService, the phone accounts here have not yet been built.
+                // So calling setUserSelectedOutgoingPhoneAccount in SubscriptionManagerService
+                // becomes a no-op. The workaround here is to reconcile and make sure the
+                // outgoing phone account is properly set in telecom.
+                int defaultVoiceSubId = SubscriptionManager.getDefaultVoiceSubscriptionId();
+                if (SubscriptionManager.isValidSubscriptionId(defaultVoiceSubId)) {
+                    PhoneAccountHandle defaultVoiceAccountHandle =
+                            getPhoneAccountHandleForSubId(defaultVoiceSubId);
+                    if (defaultVoiceAccountHandle != null) {
+                        PhoneAccountHandle currentAccount = mTelecomManager
+                                .getUserSelectedOutgoingPhoneAccount();
+                        // In some rare cases, the current phone account could be non-telephony
+                        // phone account. We do not override in this case.
+                        boolean wasPreviousAccountSameComponentOrUnset = currentAccount == null
+                                || Objects.equals(defaultVoiceAccountHandle.getComponentName(),
+                                currentAccount.getComponentName());
+
+                        // Set the phone account again if it's out-of-sync.
+                        if (!defaultVoiceAccountHandle.equals(currentAccount)
+                                && wasPreviousAccountSameComponentOrUnset) {
+                            Log.d(this, "setupAccounts: Re-setup phone account "
+                                    + "again for default voice sub " + defaultVoiceSubId);
+                            mTelecomManager.setUserSelectedOutgoingPhoneAccount(
+                                    defaultVoiceAccountHandle);
+                        }
+                    }
+                }
             }
 
             // Add a fake account entry.
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 565393d..3a05c6d 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -2574,6 +2574,8 @@
 
             mIsEmergencyCallPending = true;
             mEmergencyConnection = (TelephonyConnection) resultConnection;
+            handleEmergencyCallStartedForSatelliteSOSMessageRecommender(mEmergencyConnection,
+                    phone);
         }
 
         CompletableFuture<Void> maybeHoldFuture =
@@ -4642,6 +4644,8 @@
         }
         connection.addTelephonyConnectionListener(mEmergencyConnectionSatelliteListener);
         mSatelliteSOSMessageRecommender.onEmergencyCallStarted(connection);
+        mSatelliteSOSMessageRecommender.onEmergencyCallConnectionStateChanged(
+                connection.getTelecomCallId(), connection.STATE_DIALING);
     }
 
     /**
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index e76c11c..3470d4a 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -2177,7 +2177,7 @@
                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
         verify(mEmergencyStateTracker)
                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
-        verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
+        verify(mSatelliteSOSMessageRecommender, times(2)).onEmergencyCallStarted(any());
         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
 
         android.telecom.Connection tc = connectionCaptor.getValue();
@@ -2216,7 +2216,7 @@
                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
         verify(mEmergencyStateTracker)
                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
-        verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
+        verify(mSatelliteSOSMessageRecommender, times(2)).onEmergencyCallStarted(any());
         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
 
         android.telecom.Connection tc = connectionCaptor.getValue();
@@ -2260,7 +2260,7 @@
                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
         verify(mEmergencyStateTracker)
                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
-        verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
+        verify(mSatelliteSOSMessageRecommender, times(2)).onEmergencyCallStarted(any());
         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
 
         android.telecom.Connection tc = connectionCaptor.getValue();
@@ -2408,7 +2408,7 @@
 
         listener.onDisconnect(0);
 
-        verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
+        verify(mSatelliteSOSMessageRecommender, times(2)).onEmergencyCallStarted(any());
 
         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
 
@@ -2611,7 +2611,7 @@
                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
         verify(mEmergencyStateTracker)
                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
-        verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
+        verify(mSatelliteSOSMessageRecommender, times(2)).onEmergencyCallStarted(any());
         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
 
         android.telecom.Connection tc = connectionCaptor.getValue();
@@ -3340,7 +3340,7 @@
                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
         verify(mEmergencyStateTracker)
                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
-        verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
+        verify(mSatelliteSOSMessageRecommender, times(2)).onEmergencyCallStarted(any());
         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
         verify(mPhone0).dial(anyString(), any(), any());
 
@@ -3369,7 +3369,7 @@
 
         verify(mEmergencyStateTracker, times(0)).onEmergencyCallStateChanged(
                 any(), eq(c));
-        verify(mSatelliteSOSMessageRecommender, times(0))
+        verify(mSatelliteSOSMessageRecommender, times(2))
                 .onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
 
         c.setActive();
@@ -3393,7 +3393,7 @@
         // state change not notified any more after CONNECTED once
         verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
                 any(), eq(c));
-        verify(mSatelliteSOSMessageRecommender, times(1))
+        verify(mSatelliteSOSMessageRecommender, times(3))
                 .onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
 
         // state change to ACTIVE again
@@ -3405,7 +3405,7 @@
         // state change not notified any more after CONNECTED once
         verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
                 any(), eq(c));
-        verify(mSatelliteSOSMessageRecommender, times(1))
+        verify(mSatelliteSOSMessageRecommender, times(3))
                 .onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
 
         // SRVCC happens
@@ -3427,7 +3427,7 @@
         // state change not notified
         verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
                 any(), eq(c));
-        verify(mSatelliteSOSMessageRecommender, times(1))
+        verify(mSatelliteSOSMessageRecommender, times(3))
                 .onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
     }