Handle SIP authentication response for BYE.

Bug: 5159669
Change-Id: I029684334500d4d0db176783084c9b7d1db87e40
diff --git a/voip/java/android/net/sip/SipSession.java b/voip/java/android/net/sip/SipSession.java
index 5ba1626..e03cf9f 100644
--- a/voip/java/android/net/sip/SipSession.java
+++ b/voip/java/android/net/sip/SipSession.java
@@ -63,6 +63,9 @@
         /** When an OPTIONS request is sent. */
         public static final int PINGING = 9;
 
+        /** When ending a call. @hide */
+        public static final int ENDING_CALL = 10;
+
         /** Not defined. */
         public static final int NOT_DEFINED = 101;
 
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 48d9b17..3b3cbf3 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -98,6 +98,7 @@
     private static final String THREAD_POOL_SIZE = "1";
     private static final int EXPIRY_TIME = 3600; // in seconds
     private static final int CANCEL_CALL_TIMER = 3; // in seconds
+    private static final int END_CALL_TIMER = 3; // in seconds
     private static final int KEEPALIVE_TIMEOUT = 3; // in seconds
     private static final int INCALL_KEEPALIVE_INTERVAL = 10; // in seconds
     private static final long WAKE_LOCK_HOLDING_TIME = 500; // in milliseconds
@@ -756,6 +757,9 @@
                 case SipSession.State.IN_CALL:
                     processed = inCall(evt);
                     break;
+                case SipSession.State.ENDING_CALL:
+                    processed = endingCall(evt);
+                    break;
                 default:
                     processed = false;
                 }
@@ -1230,8 +1234,10 @@
             // OK retransmission is handled in SipStack
             if (END_CALL == evt) {
                 // rfc3261#section-15.1.1
+                mState = SipSession.State.ENDING_CALL;
                 mSipHelper.sendBye(mDialog);
-                endCallNormally();
+                mProxy.onCallEnded(this);
+                startSessionTimer(END_CALL_TIMER);
                 return true;
             } else if (isRequestEvent(Request.INVITE, evt)) {
                 // got Re-INVITE
@@ -1260,6 +1266,28 @@
             return false;
         }
 
+        private boolean endingCall(EventObject evt) throws SipException {
+            if (expectResponse(Request.BYE, evt)) {
+                ResponseEvent event = (ResponseEvent) evt;
+                Response response = event.getResponse();
+
+                int statusCode = response.getStatusCode();
+                switch (statusCode) {
+                    case Response.UNAUTHORIZED:
+                    case Response.PROXY_AUTHENTICATION_REQUIRED:
+                        if (handleAuthentication(event)) {
+                            return true;
+                        } else {
+                            // can't authenticate; pass through to end session
+                        }
+                }
+                cancelSessionTimer();
+                reset();
+                return true;
+            }
+            return false;
+        }
+
         // timeout in seconds
         private void startSessionTimer(int timeout) {
             if (timeout > 0) {