Merge cherrypicks of ['googleplex-android-review.googlesource.com/39600574'] into 26Q2-release.

Change-Id: If5a05935eb51182efd54e77052617d52a607855b
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index 102c87f..db4c926 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -146,7 +146,8 @@
                 .setLabel(toTelecomDisconnectCauseLabel(context, telephonyDisconnectCause,
                         telephonyPreciseDisconnectCause, carrierConfig, featureFlags))
                 .setDescription(toTelecomDisconnectCauseDescription(
-                        context, telephonyDisconnectCause, phoneId, shouldTreatAsEmergency))
+                        context, telephonyDisconnectCause, phoneId, shouldTreatAsEmergency,
+                        carrierConfig))
                 .setReason(toTelecomDisconnectReason(
                         context, telephonyDisconnectCause, reason, phoneId))
                 .setTone(toTelecomDisconnectCauseTone(
@@ -304,6 +305,10 @@
                     carrierConfig)) {
                 return context.getResources().getString(R.string.callFailed_userBusy);
             }
+            if (doesCarrierClassifyDisconnectCauseAsNetworkBusyCause(telephonyDisconnectCause,
+                    carrierConfig)) {
+                return context.getResources().getString(R.string.callFailed_NetworkBusy);
+            }
             label = getLabelFromDisconnectCause(context, telephonyDisconnectCause);
         }
         return label;
@@ -646,11 +651,16 @@
      */
     private static CharSequence toTelecomDisconnectCauseDescription(
             Context context, int telephonyDisconnectCause, int phoneId,
-            boolean shouldTreatAsEmergency) {
+            boolean shouldTreatAsEmergency, PersistableBundle carrierConfig) {
         if (context == null ) {
             return "";
         }
 
+        if (doesCarrierClassifyDisconnectCauseAsNetworkBusyCause(telephonyDisconnectCause,
+                carrierConfig)) {
+            return context.getResources().getString(R.string.callFailed_NetworkBusy);
+        }
+
         Integer resourceId = null;
         switch (telephonyDisconnectCause) {
             case android.telephony.DisconnectCause.CALL_BARRED:
@@ -994,6 +1004,28 @@
         return false;
     }
 
+    /**
+     * Helper method that examines the carrierConfig KEY_DISCONNECT_CAUSE_NETWORK_BUSY_INT_ARRAY
+     * containing the DisconnectCauses that are classified as Network Busy.
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public static boolean doesCarrierClassifyDisconnectCauseAsNetworkBusyCause(
+            int telephonyDisconnectCause, PersistableBundle carrierConfig) {
+        if (carrierConfig == null) {
+            return false;
+        }
+        int[] networkBusyArray = carrierConfig.getIntArray(
+                CarrierConfigManager.KEY_DISCONNECT_CAUSE_NETWORK_BUSY_INT_ARRAY);
+        if (networkBusyArray != null) {
+            for (int networkBusy : networkBusyArray) {
+                if (networkBusy == telephonyDisconnectCause) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     private static PersistableBundle getCarrierConfigBundle(int phoneId) {
         Phone phone = PhoneFactory.getPhone(phoneId);
         PersistableBundle config;
diff --git a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
index 31d7440..5597e93 100644
--- a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
+++ b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
@@ -19,11 +19,11 @@
 import static android.media.ToneGenerator.TONE_PROP_PROMPT;
 import static android.media.ToneGenerator.TONE_SUP_BUSY;
 
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.TestCase.assertEquals;
-
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
 import android.content.res.Configuration;
@@ -186,6 +186,87 @@
     }
 
     /**
+     * Assert that when a cause is in the KEY_DISCONNECT_CAUSE_NETWORK_BUSY_INT_ARRAY, the returned
+     * label and description are callFailed_NetworkBusy.
+     */
+    @Test
+    public void
+            testToTelecomDisconnectCause_returnsNetworkBusyLabelAndDescription() {
+        int telephonyCause = DisconnectCause.IMS_ACCESS_BLOCKED;
+
+        PersistableBundle carrierConfig = new PersistableBundle();
+        carrierConfig.putIntArray(
+                CarrierConfigManager.KEY_DISCONNECT_CAUSE_NETWORK_BUSY_INT_ARRAY,
+                new int[]{telephonyCause});
+
+        android.telecom.DisconnectCause tcCause =
+                DisconnectCauseUtil.toTelecomDisconnectCause(telephonyCause,
+                        CallFailCause.NOT_VALID, "reason", PHONE_ID, null, carrierConfig,
+                        mFeatureFlags, false);
+
+        Resources r = getResourcesForLocale(InstrumentationRegistry.getTargetContext(), Locale.US);
+        assertEquals(r.getString(R.string.callFailed_NetworkBusy), tcCause.getLabel().toString());
+        assertEquals(
+                r.getString(R.string.callFailed_NetworkBusy), tcCause.getDescription().toString());
+    }
+
+    /**
+     * Assert that when a cause is NOT in the KEY_DISCONNECT_CAUSE_NETWORK_BUSY_INT_ARRAY, it does
+     * not return the NetworkBusy label.
+     */
+    @Test
+    public void testToTelecomDisconnectCause_withoutNetworkBusyConfig_returnsStandardLabel() {
+        int telephonyCause = DisconnectCause.IMS_ACCESS_BLOCKED;
+
+        PersistableBundle carrierConfig = new PersistableBundle();
+        // Array exists but does not contain our cause
+        carrierConfig.putIntArray(
+                CarrierConfigManager.KEY_DISCONNECT_CAUSE_NETWORK_BUSY_INT_ARRAY,
+                new int[] {DisconnectCause.POWER_OFF});
+
+        android.telecom.DisconnectCause tcCause =
+                DisconnectCauseUtil.toTelecomDisconnectCause(
+                        telephonyCause,
+                        CallFailCause.NOT_VALID,
+                        "reason",
+                        PHONE_ID,
+                        null,
+                        carrierConfig,
+                        mFeatureFlags,
+                        false);
+
+        Resources r = getResourcesForLocale(InstrumentationRegistry.getTargetContext(), Locale.US);
+        assertNotEquals(
+                r.getString(R.string.callFailed_NetworkBusy), tcCause.getLabel().toString());
+    }
+
+    @Test
+    public void testDoesCarrierClassifyDisconnectCauseAsNetworkBusyCause_CauseInArrayReturnsTrue() {
+        int telephonyCause = DisconnectCause.IMS_ACCESS_BLOCKED;
+        PersistableBundle config = new PersistableBundle();
+        config.putIntArray(
+                CarrierConfigManager.KEY_DISCONNECT_CAUSE_NETWORK_BUSY_INT_ARRAY,
+                new int[]{telephonyCause});
+
+        assertTrue(DisconnectCauseUtil.doesCarrierClassifyDisconnectCauseAsNetworkBusyCause(
+                telephonyCause, config));
+    }
+
+    @Test
+    public void
+            testDoesCarrierClassifyDisconnectCauseAsNetworkBusyCause_CauseNotInArrayReturnsFalse() {
+        int telephonyCause = DisconnectCause.IMS_ACCESS_BLOCKED;
+        PersistableBundle config = new PersistableBundle();
+        config.putIntArray(
+                CarrierConfigManager.KEY_DISCONNECT_CAUSE_NETWORK_BUSY_INT_ARRAY,
+                new int[] {DisconnectCause.POWER_OFF});
+
+        assertFalse(
+                DisconnectCauseUtil.doesCarrierClassifyDisconnectCauseAsNetworkBusyCause(
+                        telephonyCause, config));
+    }
+
+    /**
      * Ensure the helper doesCarrierClassifyDisconnectCauseAsBusyCause does not hit a NPE if a
      * NULL carrier config is passed in.
      */