DO NOT MERGE Ensure emergency calls dialed over IMS use CLIR suppression.

When dialing an emergency call, the framework will use the user's chosen
CLIR mode (network default, invocation (show caller ID to remote),
suppression (hide caller ID to remote).

This change ensures that the telephony framework will show the caller's
ID when an emergency call is dialed over IMS.

Test: Manual, unit test
Bug: 64049180, 65243662
Merged-In: Ic52caf4bc47045ac0d9b0d024882b30d057b3a16
Change-Id: Ic52caf4bc47045ac0d9b0d024882b30d057b3a16
(cherry picked from commit e2b25c138d61072f3532c69110c3713006dabf20)
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index 34fe7ee..c7a1e0e 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -111,6 +111,10 @@
         SharedPreferences getDefaultSharedPreferences(Context context);
     }
 
+    public interface PhoneNumberUtilsProxy {
+        boolean isEmergencyNumber(String number);
+    }
+
     private static final boolean DBG = true;
 
     // When true, dumps the state of ImsPhoneCallTracker after changes to foreground and background
@@ -596,6 +600,14 @@
         return PreferenceManager.getDefaultSharedPreferences(context);
     };
 
+    /**
+     * Default implementation for determining if a number is an emergency number.  Uses the real
+     * PhoneNumberUtils.
+     */
+    private PhoneNumberUtilsProxy mPhoneNumberUtilsProxy = (String string) -> {
+        return PhoneNumberUtils.isEmergencyNumber(string);
+    };
+
     // Callback fires when ImsManager MMTel Feature changes state
     private ImsServiceProxy.INotifyStatusChanged mNotifyStatusChangedCallback = () -> {
         try {
@@ -675,6 +687,15 @@
         mSharedPreferenceProxy = sharedPreferenceProxy;
     }
 
+    /**
+     * Test-only method used to mock out access to the phone number utils class.
+     * @param phoneNumberUtilsProxy
+     */
+    @VisibleForTesting
+    public void setPhoneNumberUtilsProxy(PhoneNumberUtilsProxy phoneNumberUtilsProxy) {
+        mPhoneNumberUtilsProxy = phoneNumberUtilsProxy;
+    }
+
     private PendingIntent createIncomingCallPendingIntent() {
         Intent intent = new Intent(ImsManager.ACTION_IMS_INCOMING_CALL);
         intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -797,9 +818,13 @@
     dial(String dialString, int clirMode, int videoState, Bundle intentExtras)
             throws CallStateException {
         boolean isPhoneInEcmMode = isPhoneInEcbMode();
-        boolean isEmergencyNumber = PhoneNumberUtils.isEmergencyNumber(dialString);
+        boolean isEmergencyNumber = mPhoneNumberUtilsProxy.isEmergencyNumber(dialString);
 
         if (DBG) log("dial clirMode=" + clirMode);
+        if (isEmergencyNumber) {
+            clirMode = CommandsInterface.CLIR_SUPPRESSION;
+            if (DBG) log("dial emergency call, set clirModIe=" + clirMode);
+        }
 
         // note that this triggers call state changed notif
         clearDisconnected();
@@ -995,7 +1020,7 @@
 
         // Always unmute when initiating a new call
         setMute(false);
-        int serviceType = PhoneNumberUtils.isEmergencyNumber(conn.getAddress()) ?
+        int serviceType = mPhoneNumberUtilsProxy.isEmergencyNumber(conn.getAddress()) ?
                 ImsCallProfile.SERVICE_TYPE_EMERGENCY : ImsCallProfile.SERVICE_TYPE_NORMAL;
         int callType = ImsCallProfile.getCallTypeFromVideoState(videoState);
         //TODO(vt): Is this sufficient?  At what point do we know the video state of the call?
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
index 7134677..e3f265a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
@@ -379,6 +379,45 @@
         assertEquals("clir_key0", mStringCaptor.getValue());
     }
 
+    /**
+     * Ensures for an emergency call that the dial method will default the CLIR to
+     * {@link CommandsInterface#CLIR_SUPPRESSION}, ensuring the caller's ID is shown.
+     */
+    @Test
+    @SmallTest
+    public void testEmergencyDialSuppressClir() {
+        mCTUT.setSharedPreferenceProxy((Context context) -> {
+            return mSharedPreferences;
+        });
+        // Mock implementation of phone number utils treats everything as an emergency.
+        mCTUT.setPhoneNumberUtilsProxy((String string) -> {
+            return true;
+        });
+        // Set preference to hide caller ID.
+        ArgumentCaptor<String> stringCaptor = ArgumentCaptor.forClass(String.class);
+        doReturn(CommandsInterface.CLIR_INVOCATION).when(mSharedPreferences).getInt(
+                stringCaptor.capture(), anyInt());
+
+        try {
+            mCTUT.dial("+17005554141", VideoProfile.STATE_AUDIO_ONLY, null);
+
+            ArgumentCaptor<ImsCallProfile> profileCaptor = ArgumentCaptor.forClass(
+                    ImsCallProfile.class);
+            verify(mImsManager, times(1)).makeCall(eq(0), eq(mImsCallProfile),
+                    eq(new String[]{"+17005554141"}), (ImsCall.Listener) any());
+
+            // Because this is an emergency call, we expect caller id to be visible now.
+            verify(mImsCallProfile).setCallExtraInt(ImsCallProfile.EXTRA_OIR,
+                    CommandsInterface.CLIR_SUPPRESSION);
+        } catch (CallStateException cse) {
+            cse.printStackTrace();
+            Assert.fail("unexpected exception thrown" + cse.getMessage());
+        } catch (ImsException ie) {
+            ie.printStackTrace();
+            Assert.fail("unexpected exception thrown" + ie.getMessage());
+        }
+    }
+
     @FlakyTest
     @Test
     @SmallTest