Adding emergency call start/end indications in ImsPhone.

This is needed to correctly support emergency callback mode.

Bug: 23704763
Change-Id: I1983987b75e055d8acf99b9e628bbcabbd41c911
diff --git a/src/java/com/android/internal/telephony/PhoneBase.java b/src/java/com/android/internal/telephony/PhoneBase.java
index 928edef..e52e5ff 100644
--- a/src/java/com/android/internal/telephony/PhoneBase.java
+++ b/src/java/com/android/internal/telephony/PhoneBase.java
@@ -792,6 +792,9 @@
        mHandoverRegistrants.notifyRegistrants(ar);
     }
 
+    protected void setIsInEmergencyCall() {
+    }
+
     public void migrateFrom(PhoneBase from) {
         migrate(mHandoverRegistrants, from.mHandoverRegistrants);
         migrate(mPreciseCallStateRegistrants, from.mPreciseCallStateRegistrants);
@@ -803,6 +806,9 @@
         migrate(mMmiRegistrants, from.mMmiRegistrants);
         migrate(mUnknownConnectionRegistrants, from.mUnknownConnectionRegistrants);
         migrate(mSuppServiceFailedRegistrants, from.mSuppServiceFailedRegistrants);
+        if (from.isInEmergencyCall()) {
+            setIsInEmergencyCall();
+        }
     }
 
     public void migrate(RegistrantList to, RegistrantList from) {
diff --git a/src/java/com/android/internal/telephony/cdma/CDMAPhone.java b/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 11a739c..c3beb73 100644
--- a/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -1082,6 +1082,11 @@
     }
 
     @Override
+    protected void setIsInEmergencyCall() {
+        mCT.setIsInEmergencyCall();
+    }
+
+    @Override
     public boolean isInEcm() {
         return mIsPhoneInEcmState;
     }
@@ -1152,7 +1157,7 @@
         }
     }
 
-    protected void notifyEmergencyCallRegistrants(boolean started) {
+    public void notifyEmergencyCallRegistrants(boolean started) {
         mEmergencyCallToggledRegistrants.notifyResult(started ? 1 : 0);
     }
 
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/src/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
index f5a5658..b9234a5 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
@@ -529,6 +529,8 @@
         boolean needsPollDelay = false;
         boolean unknownConnectionAppeared = false;
 
+        boolean noConnectionExists = true;
+
         for (int i = 0, curDC = 0, dcSize = polledCalls.size()
                 ; i < mConnections.length; i++) {
             CdmaConnection conn = mConnections[i];
@@ -545,6 +547,10 @@
                 }
             }
 
+            if (conn != null || dc != null) {
+                noConnectionExists = false;
+            }
+
             if (DBG_POLL) log("poll: conn[i=" + i + "]=" +
                     conn+", dc=" + dc);
 
@@ -607,7 +613,6 @@
                             newUnknown = mConnections[i];
                         }
                     }
-                    checkAndEnableDataCallAfterEmergencyCallDropped();
                 }
                 hasNonHangupStateChanged = true;
             } else if (conn != null && dc == null) {
@@ -689,6 +694,12 @@
             }
         }
 
+        // Safety check so that obj is not stuck with mIsInEmergencyCall set to true (and data
+        // disabled). This should never happen though.
+        if (noConnectionExists) {
+            checkAndEnableDataCallAfterEmergencyCallDropped();
+        }
+
         // This is the first poll after an ATD.
         // We expect the pending call to appear in the list
         // If it does not, we land here
@@ -1137,12 +1148,15 @@
     private void disableDataCallInEmergencyCall(String dialString) {
         if (PhoneNumberUtils.isLocalEmergencyNumber(mPhone.getContext(), dialString)) {
             if (Phone.DEBUG_PHONE) log("disableDataCallInEmergencyCall");
-            mIsInEmergencyCall = true;
-            mPhone.mDcTracker.setInternalDataEnabled(false);
-            mPhone.notifyEmergencyCallRegistrants(true);
+            setIsInEmergencyCall();
         }
     }
 
+    protected void setIsInEmergencyCall() {
+        mIsInEmergencyCall = true;
+        mPhone.mDcTracker.setInternalDataEnabled(false);
+        mPhone.notifyEmergencyCallRegistrants(true);
+    }
     /**
      * Check and enable data call after an emergency call is dropped if it's
      * not in ECM
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index 877c82f..a9d43fd 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -366,7 +366,8 @@
             }
 
             mPendingMO = new ImsPhoneConnection(mPhone,
-                    checkForTestEmergencyNumber(dialString), this, mForegroundCall);
+                    checkForTestEmergencyNumber(dialString), this, mForegroundCall,
+                    isEmergencyNumber);
         }
         addConnection(mPendingMO);
 
@@ -943,10 +944,26 @@
 
     private synchronized void removeConnection(ImsPhoneConnection conn) {
         mConnections.remove(conn);
+        // If not emergency call is remaining, notify emergency call registrants
+        if (mIsInEmergencyCall) {
+            boolean isEmergencyCallInList = false;
+            // if no emergency calls pending, set this to false
+            for (ImsPhoneConnection imsPhoneConnection : mConnections) {
+                if (imsPhoneConnection != null && imsPhoneConnection.isEmergency() == true) {
+                    isEmergencyCallInList = true;
+                    break;
+                }
+            }
+
+            mIsInEmergencyCall = isEmergencyCallInList;
+        }
     }
 
     private synchronized void addConnection(ImsPhoneConnection conn) {
         mConnections.add(conn);
+        if (conn.isEmergency()) {
+            mIsInEmergencyCall = true;
+        }
     }
 
     private void processCallStateChange(ImsCall imsCall, ImsPhoneCall.State state, int cause) {
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
index cd6ca99..9e5ea9a 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
@@ -87,6 +87,8 @@
     // The cached delay to be used between DTMF tones fetched from carrier config.
     private int mDtmfToneDelay = 0;
 
+    private boolean mIsEmergency = false;
+
     //***** Event Constants
     private static final int EVENT_DTMF_DONE = 1;
     private static final int EVENT_PAUSE_DONE = 2;
@@ -170,7 +172,7 @@
     /** This is an MO call, created when dialing */
     /*package*/
     ImsPhoneConnection(ImsPhone phone, String dialString, ImsPhoneCallTracker ct,
-            ImsPhoneCall parent) {
+            ImsPhoneCall parent, boolean isEmergency) {
         createWakeLock(phone.getContext());
         acquireWakeLock();
 
@@ -193,6 +195,8 @@
         mParent = parent;
         parent.attachFake(this, ImsPhoneCall.State.DIALING);
 
+        mIsEmergency = isEmergency;
+
         fetchDtmfToneDelay(phone);
     }
 
@@ -876,5 +880,13 @@
         sb.append("]");
         return sb.toString();
     }
+
+    /**
+     * Indicates whether current phone connection is emergency or not
+     * @return boolean: true if emergency, false otherwise
+     */
+    protected boolean isEmergency() {
+        return mIsEmergency;
+    }
 }