Merge "Added HTTP support for SDP files."
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 23ce088..0f4d866 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -2511,6 +2511,7 @@
         if (err != OK) {
             ALOGW("Failed to set scaling mode: %d", err);
         }
+        return err;
     }
     return OK;
 }
diff --git a/media/libstagefright/wifi-display/ANetworkSession.cpp b/media/libstagefright/wifi-display/ANetworkSession.cpp
index 62a6e7f..06f71f4 100644
--- a/media/libstagefright/wifi-display/ANetworkSession.cpp
+++ b/media/libstagefright/wifi-display/ANetworkSession.cpp
@@ -1091,7 +1091,6 @@
                                   clientSocket);
 
                             sp<Session> clientSession =
-                                // using socket sd as sessionID
                                 new Session(
                                         mNextSessionID++,
                                         Session::CONNECTED,
diff --git a/media/libstagefright/wifi-display/sink/RTPSink.cpp b/media/libstagefright/wifi-display/sink/RTPSink.cpp
index 7f4b66f..be54595 100644
--- a/media/libstagefright/wifi-display/sink/RTPSink.cpp
+++ b/media/libstagefright/wifi-display/sink/RTPSink.cpp
@@ -253,6 +253,8 @@
       mRTPPort(0),
       mRTPSessionID(0),
       mRTCPSessionID(0),
+      mRTPClientSessionID(0),
+      mRTCPClientSessionID(0),
       mFirstArrivalTimeUs(-1ll),
       mNumPacketsReceived(0ll),
       mRegression(1000),
@@ -260,6 +262,14 @@
 }
 
 RTPSink::~RTPSink() {
+    if (mRTCPClientSessionID != 0) {
+        mNetSession->destroySession(mRTCPClientSessionID);
+    }
+
+    if (mRTPClientSessionID != 0) {
+        mNetSession->destroySession(mRTPClientSessionID);
+    }
+
     if (mRTCPSessionID != 0) {
         mNetSession->destroySession(mRTCPSessionID);
     }
@@ -269,8 +279,8 @@
     }
 }
 
-status_t RTPSink::init(bool useTCPInterleaving) {
-    if (useTCPInterleaving) {
+status_t RTPSink::init(bool usingTCPTransport, bool usingTCPInterleaving) {
+    if (usingTCPInterleaving) {
         return OK;
     }
 
@@ -280,8 +290,16 @@
     sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());
     for (clientRtp = 15550;; clientRtp += 2) {
         int32_t rtpSession;
-        status_t err = mNetSession->createUDPSession(
-                    clientRtp, rtpNotify, &rtpSession);
+        status_t err;
+        struct in_addr ifaceAddr;
+        if (usingTCPTransport) {
+            ifaceAddr.s_addr = INADDR_ANY;
+            err = mNetSession->createTCPDatagramSession(
+                        ifaceAddr, clientRtp, rtpNotify, &rtpSession);
+        } else {
+            err = mNetSession->createUDPSession(
+                        clientRtp, rtpNotify, &rtpSession);
+        }
 
         if (err != OK) {
             ALOGI("failed to create RTP socket on port %d", clientRtp);
@@ -289,8 +307,13 @@
         }
 
         int32_t rtcpSession;
-        err = mNetSession->createUDPSession(
-                clientRtp + 1, rtcpNotify, &rtcpSession);
+        if (usingTCPTransport) {
+            err = mNetSession->createTCPDatagramSession(
+                    ifaceAddr, clientRtp + 1, rtcpNotify, &rtcpSession);
+        } else {
+            err = mNetSession->createUDPSession(
+                    clientRtp + 1, rtcpNotify, &rtcpSession);
+        }
 
         if (err == OK) {
             mRTPPort = clientRtp;
@@ -367,6 +390,24 @@
                     break;
                 }
 
+                case ANetworkSession::kWhatClientConnected:
+                {
+                    int32_t sessionID;
+                    CHECK(msg->findInt32("sessionID", &sessionID));
+                    ALOGI("TCP session %d now connected", sessionID);
+
+                    int32_t serverPort;
+                    CHECK(msg->findInt32("server-port", &serverPort));
+
+                    if (serverPort == mRTPPort) {
+                        mRTPClientSessionID = sessionID;
+                    } else {
+                        CHECK_EQ(serverPort, mRTPPort + 1);
+                        mRTCPClientSessionID = sessionID;
+                    }
+                    break;
+                }
+
                 default:
                     TRESPASS();
             }
diff --git a/media/libstagefright/wifi-display/sink/RTPSink.h b/media/libstagefright/wifi-display/sink/RTPSink.h
index 6e40185..f9cbce9 100644
--- a/media/libstagefright/wifi-display/sink/RTPSink.h
+++ b/media/libstagefright/wifi-display/sink/RTPSink.h
@@ -48,7 +48,7 @@
     // If TCP interleaving is used, no UDP sockets are created, instead
     // incoming RTP/RTCP packets (arriving on the RTSP control connection)
     // are manually injected by WifiDisplaySink.
-    status_t init(bool useTCPInterleaving);
+    status_t init(bool usingTCPTransport, bool usingTCPInterleaving);
 
     status_t connect(
             const char *host, int32_t remoteRtpPort, int32_t remoteRtcpPort);
@@ -79,8 +79,12 @@
     KeyedVector<uint32_t, sp<Source> > mSources;
 
     int32_t mRTPPort;
-    int32_t mRTPSessionID;
-    int32_t mRTCPSessionID;
+
+    int32_t mRTPSessionID;   // in TCP unicast mode these are just server
+    int32_t mRTCPSessionID;  // sockets. No data is transferred through them.
+
+    int32_t mRTPClientSessionID;  // in TCP unicast mode
+    int32_t mRTCPClientSessionID;
 
     int64_t mFirstArrivalTimeUs;
     int64_t mNumPacketsReceived;
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index e542908..ede4e60 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -542,6 +542,18 @@
                 onFinishPlay2();
             } else if (what == Sender::kWhatSessionDead) {
                 notifySessionDead();
+            } else if (what == Sender::kWhatBinaryData) {
+                sp<AMessage> notify = mNotify->dup();
+                notify->setInt32("what", kWhatBinaryData);
+
+                int32_t channel;
+                CHECK(msg->findInt32("channel", &channel));
+                notify->setInt32("channel", channel);
+
+                sp<ABuffer> data;
+                CHECK(msg->findBuffer("data", &data));
+                notify->setBuffer("data", data);
+                notify->post();
             } else {
                 TRESPASS();
             }
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index 981d5f9..825ebc6 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -597,15 +597,6 @@
 status_t WifiDisplaySource::sendM4(int32_t sessionID) {
     CHECK_EQ(sessionID, mClientSessionID);
 
-    AString transportString = "UDP";
-
-    char val[PROPERTY_VALUE_MAX];
-    if (property_get("media.wfd.enable-tcp", val, NULL)
-            && (!strcasecmp("true", val) || !strcmp("1", val))) {
-        ALOGI("Using TCP transport.");
-        transportString = "TCP";
-    }
-
     AString body;
 
     if (mSinkSupportsVideo) {
@@ -630,11 +621,11 @@
 
     body.append(
             StringPrintf(
-                "wfd_presentation_URL: rtsp://%s/wfd1.0/streamid=0 none\r\n"
-                "wfd_client_rtp_ports: RTP/AVP/%s;unicast %d 0 mode=play\r\n",
-                mClientInfo.mLocalIP.c_str(),
-                transportString.c_str(),
-                mChosenRTPPort));
+                "wfd_presentation_URL: rtsp://%s/wfd1.0/streamid=0 none\r\n",
+                mClientInfo.mLocalIP.c_str()));
+
+    body.append(mWfdClientRtpPorts);
+    body.append("\r\n");
 
     AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
     AppendCommonResponse(&request, mNextCSeq);
@@ -797,18 +788,29 @@
         return ERROR_MALFORMED;
     }
 
-    unsigned port0, port1;
+    unsigned port0 = 0, port1 = 0;
     if (sscanf(value.c_str(),
                "RTP/AVP/UDP;unicast %u %u mode=play",
                &port0,
-               &port1) != 2
-        || port0 == 0 || port0 > 65535 || port1 != 0) {
-        ALOGE("Sink chose its wfd_client_rtp_ports poorly (%s)",
+               &port1) == 2
+        || sscanf(value.c_str(),
+               "RTP/AVP/TCP;unicast %u %u mode=play",
+               &port0,
+               &port1) == 2) {
+            if (port0 == 0 || port0 > 65535 || port1 != 0) {
+                ALOGE("Sink chose its wfd_client_rtp_ports poorly (%s)",
+                      value.c_str());
+
+                return ERROR_MALFORMED;
+            }
+    } else if (strcmp(value.c_str(), "RTP/AVP/TCP;interleaved mode=play")) {
+        ALOGE("Unsupported value for wfd_client_rtp_ports (%s)",
               value.c_str());
 
-        return ERROR_MALFORMED;
+        return ERROR_UNSUPPORTED;
     }
 
+    mWfdClientRtpPorts = value;
     mChosenRTPPort = port0;
 
     if (!params->findParameter("wfd_video_formats", &value)) {
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
index fec2c6d..724462c 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
@@ -119,6 +119,7 @@
 
     uint32_t mStopReplyID;
 
+    AString mWfdClientRtpPorts;
     int32_t mChosenRTPPort;  // extracted from "wfd_client_rtp_ports"
 
     bool mSinkSupportsVideo;