Fix the unhold issue especially if one is behind NAT.

+call startAudio() when call is established.

Change-Id: Ib6a1e34017fb83007ce275da1991058e8b803833
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index 45e6ccd..c0f2993 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -633,6 +633,18 @@
             }
 
             @Override
+            public void onCallEstablished(SipAudioCall call) {
+                call.startAudio();
+                onChanged(call);
+            }
+
+            @Override
+            public void onCallHeld(SipAudioCall call) {
+                call.startAudio();
+                onChanged(call);
+            }
+
+            @Override
             public void onChanged(SipAudioCall call) {
                 synchronized (SipPhone.class) {
                     Call.State newState = getCallStateFrom(call);
@@ -652,7 +664,6 @@
                             }
                             foregroundCall.switchWith(ringingCall);
                         }
-                        if (newState == Call.State.ACTIVE) call.startAudio();
                         setState(newState);
                     }
                     mOwner.onConnectionStateChanged(SipConnection.this);
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 7cf0613..81d4dfc 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -86,6 +86,8 @@
     void decode(int tick);
 
 private:
+    bool isNatAddress(struct sockaddr_storage *addr);
+
     enum {
         NORMAL = 0,
         SEND_ONLY = 1,
@@ -316,6 +318,16 @@
         sizeof(mRemote));
 }
 
+bool AudioStream::isNatAddress(struct sockaddr_storage *addr) {
+    if (addr->ss_family != AF_INET) return false;
+    struct sockaddr_in *s4 = (struct sockaddr_in *)addr;
+    unsigned char *d = (unsigned char *) &s4->sin_addr;
+    if ((d[0] == 10)
+        || ((d[0] == 172) && (d[1] & 0x10))
+        || ((d[0] == 192) && (d[1] == 168))) return true;
+    return false;
+}
+
 void AudioStream::decode(int tick)
 {
     char c;
@@ -363,8 +375,21 @@
             MSG_TRUNC | MSG_DONTWAIT) >> 1;
     } else {
         __attribute__((aligned(4))) uint8_t buffer[2048];
-        length = recv(mSocket, buffer, sizeof(buffer),
-            MSG_TRUNC | MSG_DONTWAIT);
+        struct sockaddr_storage src_addr;
+        socklen_t addrlen;
+        length = recvfrom(mSocket, buffer, sizeof(buffer),
+            MSG_TRUNC|MSG_DONTWAIT, (sockaddr*)&src_addr, &addrlen);
+
+        // The following if clause is for fixing the target address if
+        // proxy server did not replace the NAT address with its media
+        // port in SDP. Although it is proxy server's responsibility for
+        // replacing the connection address with correct one, we will change
+        // the target address as we detect the difference for now until we
+        // know the best way to get rid of this issue.
+        if ((memcmp((void*)&src_addr, (void*)&mRemote, addrlen) != 0) &&
+            isNatAddress(&mRemote)) {
+            memcpy((void*)&mRemote, (void*)&src_addr, addrlen);
+        }
 
         // Do we need to check SSRC, sequence, and timestamp? They are not
         // reliable but at least they can be used to identify duplicates?