Add prototype of terminate() which supports override terminate reason code.

When ImsCall#termiante(int) is called with a reason code, the modem will
only actually disconnect the call for some disconnect reasons.

Adding an override of that method which allows the caller to specify an
override which is reported as the actual disconnect reason in the
onCallSessionTerminated callback in ImsPhoneCallTracker.

Bug: 30702393
Change-Id: I006046c03630e9d010424591f3bbb7d46da3a76f
diff --git a/src/java/com/android/ims/ImsCall.java b/src/java/com/android/ims/ImsCall.java
index 266245d..7461458 100644
--- a/src/java/com/android/ims/ImsCall.java
+++ b/src/java/com/android/ims/ImsCall.java
@@ -562,6 +562,15 @@
     private ImsCallSessionListenerProxy mImsCallSessionListenerProxy;
 
     /**
+     * When calling {@link #terminate(int, int)}, an override for the termination reason which the
+     * modem returns.
+     *
+     * Necessary because passing in an unexpected {@link ImsReasonInfo} reason code to
+     * {@link #terminate(int)} will cause the modem to ignore the terminate request.
+     */
+    private int mOverrideReason = ImsReasonInfo.CODE_UNSPECIFIED;
+
+    /**
      * Create an IMS call object.
      *
      * @param context the context for accessing system services
@@ -1145,6 +1154,12 @@
         }
     }
 
+    public void terminate(int reason, int overrideReason) throws ImsException {
+        logi("terminate :: reason=" + reason + " ; overrideReadon=" + overrideReason);
+        mOverrideReason = overrideReason;
+        terminate(reason);
+    }
+
     /**
      * Terminates an IMS call (e.g. user initiated).
      *
@@ -2207,6 +2222,12 @@
                 return;
             }
 
+            if (mOverrideReason != ImsReasonInfo.CODE_UNSPECIFIED) {
+                logi("callSessionTerminated :: overrideReasonInfo=" + mOverrideReason);
+                reasonInfo = new ImsReasonInfo(mOverrideReason, reasonInfo.getExtraCode(),
+                        reasonInfo.getExtraMessage());
+            }
+
             // Process the termination first.  If we are in the midst of establishing a conference
             // call, we may bury this callback until we are done.  If there so no conference
             // call, the code after this function will be a NOOP.