WifiDisplaySource.cpp revision ef7d3793fa9bbfb25253626ede9a020ee9280a17
1/*
2 * Copyright 2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "WifiDisplaySource"
19#include <utils/Log.h>
20
21#include "WifiDisplaySource.h"
22#include "PlaybackSession.h"
23#include "Parameters.h"
24#include "ParsedMessage.h"
25
26#include <binder/IServiceManager.h>
27#include <gui/ISurfaceTexture.h>
28#include <media/IHDCP.h>
29#include <media/IMediaPlayerService.h>
30#include <media/IRemoteDisplayClient.h>
31#include <media/stagefright/foundation/ABuffer.h>
32#include <media/stagefright/foundation/ADebug.h>
33#include <media/stagefright/foundation/AMessage.h>
34#include <media/stagefright/MediaErrors.h>
35
36#include <arpa/inet.h>
37#include <cutils/properties.h>
38
39namespace android {
40
41WifiDisplaySource::WifiDisplaySource(
42        const sp<ANetworkSession> &netSession,
43        const sp<IRemoteDisplayClient> &client)
44    : mNetSession(netSession),
45      mClient(client),
46      mSessionID(0),
47      mStopReplyID(0),
48      mClientSessionID(0),
49      mReaperPending(false),
50      mNextCSeq(1)
51#if REQUIRE_HDCP
52      ,mIsHDCP2_0(false)
53      ,mHDCPPort(0)
54      ,mHDCPInitializationComplete(false)
55      ,mSetupTriggerDeferred(false)
56#endif
57{
58}
59
60WifiDisplaySource::~WifiDisplaySource() {
61}
62
63status_t WifiDisplaySource::start(const char *iface) {
64    sp<AMessage> msg = new AMessage(kWhatStart, id());
65    msg->setString("iface", iface);
66
67    sp<AMessage> response;
68    status_t err = msg->postAndAwaitResponse(&response);
69
70    if (err != OK) {
71        return err;
72    }
73
74    if (!response->findInt32("err", &err)) {
75        err = OK;
76    }
77
78    return err;
79}
80
81status_t WifiDisplaySource::stop() {
82    sp<AMessage> msg = new AMessage(kWhatStop, id());
83
84    sp<AMessage> response;
85    status_t err = msg->postAndAwaitResponse(&response);
86
87    if (err != OK) {
88        return err;
89    }
90
91    if (!response->findInt32("err", &err)) {
92        err = OK;
93    }
94
95    return err;
96}
97
98void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
99    switch (msg->what()) {
100        case kWhatStart:
101        {
102            uint32_t replyID;
103            CHECK(msg->senderAwaitsResponse(&replyID));
104
105            AString iface;
106            CHECK(msg->findString("iface", &iface));
107
108            status_t err = OK;
109
110            ssize_t colonPos = iface.find(":");
111
112            unsigned long port;
113
114            if (colonPos >= 0) {
115                const char *s = iface.c_str() + colonPos + 1;
116
117                char *end;
118                port = strtoul(s, &end, 10);
119
120                if (end == s || *end != '\0' || port > 65535) {
121                    err = -EINVAL;
122                } else {
123                    iface.erase(colonPos, iface.size() - colonPos);
124                }
125            } else {
126                port = kWifiDisplayDefaultPort;
127            }
128
129            if (err == OK) {
130                if (inet_aton(iface.c_str(), &mInterfaceAddr) != 0) {
131                    sp<AMessage> notify = new AMessage(kWhatRTSPNotify, id());
132
133                    err = mNetSession->createRTSPServer(
134                            mInterfaceAddr, port, notify, &mSessionID);
135                } else {
136                    err = -EINVAL;
137                }
138            }
139
140            sp<AMessage> response = new AMessage;
141            response->setInt32("err", err);
142            response->postReply(replyID);
143            break;
144        }
145
146        case kWhatRTSPNotify:
147        {
148            int32_t reason;
149            CHECK(msg->findInt32("reason", &reason));
150
151            switch (reason) {
152                case ANetworkSession::kWhatError:
153                {
154                    int32_t sessionID;
155                    CHECK(msg->findInt32("sessionID", &sessionID));
156
157                    int32_t err;
158                    CHECK(msg->findInt32("err", &err));
159
160                    AString detail;
161                    CHECK(msg->findString("detail", &detail));
162
163                    ALOGE("An error occurred in session %d (%d, '%s/%s').",
164                          sessionID,
165                          err,
166                          detail.c_str(),
167                          strerror(-err));
168
169                    mNetSession->destroySession(sessionID);
170
171                    if (sessionID == mClientSessionID) {
172                        mClientSessionID = 0;
173
174                        mClient->onDisplayError(
175                                IRemoteDisplayClient::kDisplayErrorUnknown);
176                    }
177                    break;
178                }
179
180                case ANetworkSession::kWhatClientConnected:
181                {
182                    int32_t sessionID;
183                    CHECK(msg->findInt32("sessionID", &sessionID));
184
185                    if (mClientSessionID > 0) {
186                        ALOGW("A client tried to connect, but we already "
187                              "have one.");
188
189                        mNetSession->destroySession(sessionID);
190                        break;
191                    }
192
193                    CHECK(msg->findString("client-ip", &mClientInfo.mRemoteIP));
194                    CHECK(msg->findString("server-ip", &mClientInfo.mLocalIP));
195
196                    if (mClientInfo.mRemoteIP == mClientInfo.mLocalIP) {
197                        // Disallow connections from the local interface
198                        // for security reasons.
199                        mNetSession->destroySession(sessionID);
200                        break;
201                    }
202
203                    CHECK(msg->findInt32(
204                                "server-port", &mClientInfo.mLocalPort));
205                    mClientInfo.mPlaybackSessionID = -1;
206
207                    mClientSessionID = sessionID;
208
209                    ALOGI("We now have a client (%d) connected.", sessionID);
210
211                    status_t err = sendM1(sessionID);
212                    CHECK_EQ(err, (status_t)OK);
213                    break;
214                }
215
216                case ANetworkSession::kWhatData:
217                {
218                    status_t err = onReceiveClientData(msg);
219
220                    if (err != OK) {
221                        mClient->onDisplayError(
222                                IRemoteDisplayClient::kDisplayErrorUnknown);
223                    }
224                    break;
225                }
226
227                default:
228                    TRESPASS();
229            }
230            break;
231        }
232
233        case kWhatStop:
234        {
235            CHECK(msg->senderAwaitsResponse(&mStopReplyID));
236
237            if (mClientSessionID != 0
238                    && mClientInfo.mPlaybackSessionID != -1) {
239                status_t err = sendM5(
240                        mClientSessionID, true /* requestShutdown */);
241
242                if (err == OK) {
243                    break;
244                }
245            }
246
247            finishStop();
248            break;
249        }
250
251        case kWhatReapDeadClients:
252        {
253            mReaperPending = false;
254
255            if (mClientSessionID == 0
256                    || mClientInfo.mPlaybackSession == NULL) {
257                break;
258            }
259
260            if (mClientInfo.mPlaybackSession->getLastLifesignUs()
261                    + kPlaybackSessionTimeoutUs < ALooper::GetNowUs()) {
262                ALOGI("playback session timed out, reaping.");
263
264                mNetSession->destroySession(mClientSessionID);
265                mClientSessionID = 0;
266
267                mClient->onDisplayError(
268                        IRemoteDisplayClient::kDisplayErrorUnknown);
269            } else {
270                scheduleReaper();
271            }
272            break;
273        }
274
275        case kWhatPlaybackSessionNotify:
276        {
277            int32_t playbackSessionID;
278            CHECK(msg->findInt32("playbackSessionID", &playbackSessionID));
279
280            int32_t what;
281            CHECK(msg->findInt32("what", &what));
282
283            if (what == PlaybackSession::kWhatSessionDead) {
284                ALOGI("playback session wants to quit.");
285
286                mClient->onDisplayError(
287                        IRemoteDisplayClient::kDisplayErrorUnknown);
288            } else if (what == PlaybackSession::kWhatSessionEstablished) {
289                if (mClient != NULL) {
290                    mClient->onDisplayConnected(
291                            mClientInfo.mPlaybackSession->getSurfaceTexture(),
292                            mClientInfo.mPlaybackSession->width(),
293                            mClientInfo.mPlaybackSession->height(),
294                            0 /* flags */);
295                }
296            } else {
297                CHECK_EQ(what, PlaybackSession::kWhatBinaryData);
298
299                int32_t channel;
300                CHECK(msg->findInt32("channel", &channel));
301
302                sp<ABuffer> data;
303                CHECK(msg->findBuffer("data", &data));
304
305                CHECK_LE(channel, 0xffu);
306                CHECK_LE(data->size(), 0xffffu);
307
308                int32_t sessionID;
309                CHECK(msg->findInt32("sessionID", &sessionID));
310
311                char header[4];
312                header[0] = '$';
313                header[1] = channel;
314                header[2] = data->size() >> 8;
315                header[3] = data->size() & 0xff;
316
317                mNetSession->sendRequest(
318                        sessionID, header, sizeof(header));
319
320                mNetSession->sendRequest(
321                        sessionID, data->data(), data->size());
322            }
323            break;
324        }
325
326        case kWhatKeepAlive:
327        {
328            int32_t sessionID;
329            CHECK(msg->findInt32("sessionID", &sessionID));
330
331            if (mClientSessionID != sessionID) {
332                // Obsolete event, client is already gone.
333                break;
334            }
335
336            sendM16(sessionID);
337            break;
338        }
339
340#if REQUIRE_HDCP
341        case kWhatHDCPNotify:
342        {
343            int32_t msgCode, ext1, ext2;
344            CHECK(msg->findInt32("msg", &msgCode));
345            CHECK(msg->findInt32("ext1", &ext1));
346            CHECK(msg->findInt32("ext2", &ext2));
347
348            ALOGI("Saw HDCP notification code %d, ext1 %d, ext2 %d",
349                    msgCode, ext1, ext2);
350
351            switch (msgCode) {
352                case HDCPModule::HDCP_INITIALIZATION_COMPLETE:
353                {
354                    mHDCPInitializationComplete = true;
355
356                    if (mSetupTriggerDeferred) {
357                        mSetupTriggerDeferred = false;
358
359                        sendM5(mClientSessionID, false /* requestShutdown */);
360                    }
361                    break;
362                }
363
364                case HDCPModule::HDCP_SHUTDOWN_COMPLETE:
365                case HDCPModule::HDCP_SHUTDOWN_FAILED:
366                {
367                    // Ugly hack to make sure that the call to
368                    // HDCPObserver::notify is completely handled before
369                    // we clear the HDCP instance and unload the shared
370                    // library :(
371                    (new AMessage(kWhatFinishStop2, id()))->post(300000ll);
372                    break;
373                }
374
375                default:
376                {
377                    ALOGE("HDCP failure, shutting down.");
378
379                    mClient->onDisplayError(
380                            IRemoteDisplayClient::kDisplayErrorUnknown);
381                    break;
382                }
383            }
384            break;
385        }
386
387        case kWhatFinishStop2:
388        {
389            finishStop2();
390            break;
391        }
392#endif
393
394        default:
395            TRESPASS();
396    }
397}
398
399void WifiDisplaySource::registerResponseHandler(
400        int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func) {
401    ResponseID id;
402    id.mSessionID = sessionID;
403    id.mCSeq = cseq;
404    mResponseHandlers.add(id, func);
405}
406
407status_t WifiDisplaySource::sendM1(int32_t sessionID) {
408    AString request = "OPTIONS * RTSP/1.0\r\n";
409    AppendCommonResponse(&request, mNextCSeq);
410
411    request.append(
412            "Require: org.wfa.wfd1.0\r\n"
413            "\r\n");
414
415    status_t err =
416        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
417
418    if (err != OK) {
419        return err;
420    }
421
422    registerResponseHandler(
423            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM1Response);
424
425    ++mNextCSeq;
426
427    return OK;
428}
429
430status_t WifiDisplaySource::sendM3(int32_t sessionID) {
431    AString body =
432#if REQUIRE_HDCP
433        "wfd_content_protection\r\n"
434#endif
435        "wfd_video_formats\r\n"
436        "wfd_audio_codecs\r\n"
437        "wfd_client_rtp_ports\r\n";
438
439    AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
440    AppendCommonResponse(&request, mNextCSeq);
441
442    request.append("Content-Type: text/parameters\r\n");
443    request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
444    request.append("\r\n");
445    request.append(body);
446
447    status_t err =
448        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
449
450    if (err != OK) {
451        return err;
452    }
453
454    registerResponseHandler(
455            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM3Response);
456
457    ++mNextCSeq;
458
459    return OK;
460}
461
462status_t WifiDisplaySource::sendM4(int32_t sessionID) {
463    // wfd_video_formats:
464    // 1 byte "native"
465    // 1 byte "preferred-display-mode-supported" 0 or 1
466    // one or more avc codec structures
467    //   1 byte profile
468    //   1 byte level
469    //   4 byte CEA mask
470    //   4 byte VESA mask
471    //   4 byte HH mask
472    //   1 byte latency
473    //   2 byte min-slice-slice
474    //   2 byte slice-enc-params
475    //   1 byte framerate-control-support
476    //   max-hres (none or 2 byte)
477    //   max-vres (none or 2 byte)
478
479    CHECK_EQ(sessionID, mClientSessionID);
480
481    AString transportString = "UDP";
482
483    char val[PROPERTY_VALUE_MAX];
484    if (property_get("media.wfd.enable-tcp", val, NULL)
485            && (!strcasecmp("true", val) || !strcmp("1", val))) {
486        ALOGI("Using TCP transport.");
487        transportString = "TCP";
488    }
489
490    // For 720p60:
491    //   use "30 00 02 02 00000040 00000000 00000000 00 0000 0000 00 none none\r\n"
492    // For 720p30:
493    //   use "28 00 02 02 00000020 00000000 00000000 00 0000 0000 00 none none\r\n"
494    // For 720p24:
495    //   use "78 00 02 02 00008000 00000000 00000000 00 0000 0000 00 none none\r\n"
496    AString body = StringPrintf(
497        "wfd_video_formats: "
498        "78 00 02 02 00008000 00000000 00000000 00 0000 0000 00 none none\r\n"
499        "wfd_audio_codecs: AAC 00000001 00\r\n"  // 2 ch AAC 48kHz
500        "wfd_presentation_URL: rtsp://%s:%d/wfd1.0/streamid=0 none\r\n"
501        "wfd_client_rtp_ports: RTP/AVP/%s;unicast 19000 0 mode=play\r\n",
502        mClientInfo.mLocalIP.c_str(), mClientInfo.mLocalPort,
503        transportString.c_str());
504
505    AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
506    AppendCommonResponse(&request, mNextCSeq);
507
508    request.append("Content-Type: text/parameters\r\n");
509    request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
510    request.append("\r\n");
511    request.append(body);
512
513    status_t err =
514        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
515
516    if (err != OK) {
517        return err;
518    }
519
520    registerResponseHandler(
521            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM4Response);
522
523    ++mNextCSeq;
524
525    return OK;
526}
527
528status_t WifiDisplaySource::sendM5(int32_t sessionID, bool requestShutdown) {
529    AString body = "wfd_trigger_method: ";
530    if (requestShutdown) {
531        ALOGI("Sending TEARDOWN trigger.");
532        body.append("TEARDOWN");
533    } else {
534        body.append("SETUP");
535    }
536
537    body.append("\r\n");
538
539    AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
540    AppendCommonResponse(&request, mNextCSeq);
541
542    request.append("Content-Type: text/parameters\r\n");
543    request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
544    request.append("\r\n");
545    request.append(body);
546
547    status_t err =
548        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
549
550    if (err != OK) {
551        return err;
552    }
553
554    registerResponseHandler(
555            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM5Response);
556
557    ++mNextCSeq;
558
559    return OK;
560}
561
562status_t WifiDisplaySource::sendM16(int32_t sessionID) {
563    AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
564    AppendCommonResponse(&request, mNextCSeq);
565
566    CHECK_EQ(sessionID, mClientSessionID);
567    request.append(
568            StringPrintf("Session: %d\r\n", mClientInfo.mPlaybackSessionID));
569    request.append("\r\n");  // Empty body
570
571    status_t err =
572        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
573
574    if (err != OK) {
575        return err;
576    }
577
578    registerResponseHandler(
579            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM16Response);
580
581    ++mNextCSeq;
582
583    return OK;
584}
585
586status_t WifiDisplaySource::onReceiveM1Response(
587        int32_t sessionID, const sp<ParsedMessage> &msg) {
588    int32_t statusCode;
589    if (!msg->getStatusCode(&statusCode)) {
590        return ERROR_MALFORMED;
591    }
592
593    if (statusCode != 200) {
594        return ERROR_UNSUPPORTED;
595    }
596
597    return OK;
598}
599
600status_t WifiDisplaySource::onReceiveM3Response(
601        int32_t sessionID, const sp<ParsedMessage> &msg) {
602    int32_t statusCode;
603    if (!msg->getStatusCode(&statusCode)) {
604        return ERROR_MALFORMED;
605    }
606
607    if (statusCode != 200) {
608        return ERROR_UNSUPPORTED;
609    }
610
611    sp<Parameters> params =
612        Parameters::Parse(msg->getContent(), strlen(msg->getContent()));
613
614    if (params == NULL) {
615        return ERROR_MALFORMED;
616    }
617
618#if REQUIRE_HDCP
619    AString value;
620    if (!params->findParameter("wfd_content_protection", &value)) {
621        ALOGE("Sink doesn't appear to support content protection.");
622        return -EACCES;
623    }
624
625    if (value == "none") {
626        ALOGE("Sink does not support content protection.");
627        return -EACCES;
628    }
629
630    bool isHDCP2_0 = false;
631    if (value.startsWith("HDCP2.0 ")) {
632        isHDCP2_0 = true;
633    } else if (!value.startsWith("HDCP2.1 ")) {
634        return ERROR_MALFORMED;
635    }
636
637    int32_t hdcpPort;
638    if (!ParsedMessage::GetInt32Attribute(value.c_str() + 8, "port", &hdcpPort)
639            || hdcpPort < 1 || hdcpPort > 65535) {
640        return ERROR_MALFORMED;
641    }
642
643    mIsHDCP2_0 = isHDCP2_0;
644    mHDCPPort = hdcpPort;
645
646    status_t err = makeHDCP();
647    if (err != OK) {
648        ALOGE("Unable to instantiate HDCP component.");
649        return err;
650    }
651#endif
652
653    return sendM4(sessionID);
654}
655
656status_t WifiDisplaySource::onReceiveM4Response(
657        int32_t sessionID, const sp<ParsedMessage> &msg) {
658    int32_t statusCode;
659    if (!msg->getStatusCode(&statusCode)) {
660        return ERROR_MALFORMED;
661    }
662
663    if (statusCode != 200) {
664        return ERROR_UNSUPPORTED;
665    }
666
667#if REQUIRE_HDCP
668    if (!mHDCPInitializationComplete) {
669        ALOGI("Deferring SETUP trigger until HDCP initialization completes.");
670
671        mSetupTriggerDeferred = true;
672        return OK;
673    }
674#endif
675
676    return sendM5(sessionID, false /* requestShutdown */);
677}
678
679status_t WifiDisplaySource::onReceiveM5Response(
680        int32_t sessionID, const sp<ParsedMessage> &msg) {
681    int32_t statusCode;
682    if (!msg->getStatusCode(&statusCode)) {
683        return ERROR_MALFORMED;
684    }
685
686    if (statusCode != 200) {
687        return ERROR_UNSUPPORTED;
688    }
689
690    return OK;
691}
692
693status_t WifiDisplaySource::onReceiveM16Response(
694        int32_t sessionID, const sp<ParsedMessage> &msg) {
695    // If only the response was required to include a "Session:" header...
696
697    CHECK_EQ(sessionID, mClientSessionID);
698
699    if (mClientInfo.mPlaybackSession != NULL) {
700        mClientInfo.mPlaybackSession->updateLiveness();
701
702        scheduleKeepAlive(sessionID);
703    }
704
705    return OK;
706}
707
708void WifiDisplaySource::scheduleReaper() {
709    if (mReaperPending) {
710        return;
711    }
712
713    mReaperPending = true;
714    (new AMessage(kWhatReapDeadClients, id()))->post(kReaperIntervalUs);
715}
716
717void WifiDisplaySource::scheduleKeepAlive(int32_t sessionID) {
718    // We need to send updates at least 5 secs before the timeout is set to
719    // expire, make sure the timeout is greater than 5 secs to begin with.
720    CHECK_GT(kPlaybackSessionTimeoutUs, 5000000ll);
721
722    sp<AMessage> msg = new AMessage(kWhatKeepAlive, id());
723    msg->setInt32("sessionID", sessionID);
724    msg->post(kPlaybackSessionTimeoutUs - 5000000ll);
725}
726
727status_t WifiDisplaySource::onReceiveClientData(const sp<AMessage> &msg) {
728    int32_t sessionID;
729    CHECK(msg->findInt32("sessionID", &sessionID));
730
731    sp<RefBase> obj;
732    CHECK(msg->findObject("data", &obj));
733
734    sp<ParsedMessage> data =
735        static_cast<ParsedMessage *>(obj.get());
736
737    ALOGV("session %d received '%s'",
738          sessionID, data->debugString().c_str());
739
740    AString method;
741    AString uri;
742    data->getRequestField(0, &method);
743
744    int32_t cseq;
745    if (!data->findInt32("cseq", &cseq)) {
746        sendErrorResponse(sessionID, "400 Bad Request", -1 /* cseq */);
747        return ERROR_MALFORMED;
748    }
749
750    if (method.startsWith("RTSP/")) {
751        // This is a response.
752
753        ResponseID id;
754        id.mSessionID = sessionID;
755        id.mCSeq = cseq;
756
757        ssize_t index = mResponseHandlers.indexOfKey(id);
758
759        if (index < 0) {
760            ALOGW("Received unsolicited server response, cseq %d", cseq);
761            return ERROR_MALFORMED;
762        }
763
764        HandleRTSPResponseFunc func = mResponseHandlers.valueAt(index);
765        mResponseHandlers.removeItemsAt(index);
766
767        status_t err = (this->*func)(sessionID, data);
768
769        if (err != OK) {
770            ALOGW("Response handler for session %d, cseq %d returned "
771                  "err %d (%s)",
772                  sessionID, cseq, err, strerror(-err));
773
774            return err;
775        }
776
777        return OK;
778    }
779
780    AString version;
781    data->getRequestField(2, &version);
782    if (!(version == AString("RTSP/1.0"))) {
783        sendErrorResponse(sessionID, "505 RTSP Version not supported", cseq);
784        return ERROR_UNSUPPORTED;
785    }
786
787    status_t err;
788    if (method == "OPTIONS") {
789        err = onOptionsRequest(sessionID, cseq, data);
790    } else if (method == "SETUP") {
791        err = onSetupRequest(sessionID, cseq, data);
792    } else if (method == "PLAY") {
793        err = onPlayRequest(sessionID, cseq, data);
794    } else if (method == "PAUSE") {
795        err = onPauseRequest(sessionID, cseq, data);
796    } else if (method == "TEARDOWN") {
797        err = onTeardownRequest(sessionID, cseq, data);
798    } else if (method == "GET_PARAMETER") {
799        err = onGetParameterRequest(sessionID, cseq, data);
800    } else if (method == "SET_PARAMETER") {
801        err = onSetParameterRequest(sessionID, cseq, data);
802    } else {
803        sendErrorResponse(sessionID, "405 Method Not Allowed", cseq);
804
805        err = ERROR_UNSUPPORTED;
806    }
807
808    return err;
809}
810
811status_t WifiDisplaySource::onOptionsRequest(
812        int32_t sessionID,
813        int32_t cseq,
814        const sp<ParsedMessage> &data) {
815    int32_t playbackSessionID;
816    sp<PlaybackSession> playbackSession =
817        findPlaybackSession(data, &playbackSessionID);
818
819    if (playbackSession != NULL) {
820        playbackSession->updateLiveness();
821    }
822
823    AString response = "RTSP/1.0 200 OK\r\n";
824    AppendCommonResponse(&response, cseq);
825
826    response.append(
827            "Public: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, "
828            "GET_PARAMETER, SET_PARAMETER\r\n");
829
830    response.append("\r\n");
831
832    status_t err = mNetSession->sendRequest(sessionID, response.c_str());
833
834    if (err == OK) {
835        err = sendM3(sessionID);
836    }
837
838    return err;
839}
840
841status_t WifiDisplaySource::onSetupRequest(
842        int32_t sessionID,
843        int32_t cseq,
844        const sp<ParsedMessage> &data) {
845    CHECK_EQ(sessionID, mClientSessionID);
846    if (mClientInfo.mPlaybackSessionID != -1) {
847        // We only support a single playback session per client.
848        // This is due to the reversed keep-alive design in the wfd specs...
849        sendErrorResponse(sessionID, "400 Bad Request", cseq);
850        return ERROR_MALFORMED;
851    }
852
853    AString transport;
854    if (!data->findString("transport", &transport)) {
855        sendErrorResponse(sessionID, "400 Bad Request", cseq);
856        return ERROR_MALFORMED;
857    }
858
859    PlaybackSession::TransportMode transportMode =
860        PlaybackSession::TRANSPORT_UDP;
861
862    int clientRtp, clientRtcp;
863    if (transport.startsWith("RTP/AVP/TCP;")) {
864        AString interleaved;
865        if (ParsedMessage::GetAttribute(
866                    transport.c_str(), "interleaved", &interleaved)
867                && sscanf(interleaved.c_str(), "%d-%d",
868                          &clientRtp, &clientRtcp) == 2) {
869            transportMode = PlaybackSession::TRANSPORT_TCP_INTERLEAVED;
870        } else {
871            bool badRequest = false;
872
873            AString clientPort;
874            if (!ParsedMessage::GetAttribute(
875                        transport.c_str(), "client_port", &clientPort)) {
876                badRequest = true;
877            } else if (sscanf(clientPort.c_str(), "%d-%d",
878                              &clientRtp, &clientRtcp) == 2) {
879            } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) {
880                // No RTCP.
881                clientRtcp = -1;
882            } else {
883                badRequest = true;
884            }
885
886            if (badRequest) {
887                sendErrorResponse(sessionID, "400 Bad Request", cseq);
888                return ERROR_MALFORMED;
889            }
890
891            transportMode = PlaybackSession::TRANSPORT_TCP;
892        }
893    } else if (transport.startsWith("RTP/AVP;unicast;")
894            || transport.startsWith("RTP/AVP/UDP;unicast;")) {
895        bool badRequest = false;
896
897        AString clientPort;
898        if (!ParsedMessage::GetAttribute(
899                    transport.c_str(), "client_port", &clientPort)) {
900            badRequest = true;
901        } else if (sscanf(clientPort.c_str(), "%d-%d",
902                          &clientRtp, &clientRtcp) == 2) {
903        } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) {
904            // No RTCP.
905            clientRtcp = -1;
906        } else {
907            badRequest = true;
908        }
909
910        if (badRequest) {
911            sendErrorResponse(sessionID, "400 Bad Request", cseq);
912            return ERROR_MALFORMED;
913        }
914#if 1
915    // The older LG dongles doesn't specify client_port=xxx apparently.
916    } else if (transport == "RTP/AVP/UDP;unicast") {
917        clientRtp = 19000;
918        clientRtcp = -1;
919#endif
920    } else {
921        sendErrorResponse(sessionID, "461 Unsupported Transport", cseq);
922        return ERROR_UNSUPPORTED;
923    }
924
925    int32_t playbackSessionID = makeUniquePlaybackSessionID();
926
927    sp<AMessage> notify = new AMessage(kWhatPlaybackSessionNotify, id());
928    notify->setInt32("playbackSessionID", playbackSessionID);
929    notify->setInt32("sessionID", sessionID);
930
931    sp<PlaybackSession> playbackSession =
932        new PlaybackSession(
933                mNetSession, notify, mInterfaceAddr,
934#if REQUIRE_HDCP
935                mHDCP
936#else
937                NULL
938#endif
939                );
940
941    looper()->registerHandler(playbackSession);
942
943    AString uri;
944    data->getRequestField(1, &uri);
945
946    if (strncasecmp("rtsp://", uri.c_str(), 7)) {
947        sendErrorResponse(sessionID, "400 Bad Request", cseq);
948        return ERROR_MALFORMED;
949    }
950
951    if (!(uri.startsWith("rtsp://") && uri.endsWith("/wfd1.0/streamid=0"))) {
952        sendErrorResponse(sessionID, "404 Not found", cseq);
953        return ERROR_MALFORMED;
954    }
955
956    status_t err = playbackSession->init(
957            mClientInfo.mRemoteIP.c_str(),
958            clientRtp,
959            clientRtcp,
960            transportMode);
961
962    if (err != OK) {
963        looper()->unregisterHandler(playbackSession->id());
964        playbackSession.clear();
965    }
966
967    switch (err) {
968        case OK:
969            break;
970        case -ENOENT:
971            sendErrorResponse(sessionID, "404 Not Found", cseq);
972            return err;
973        default:
974            sendErrorResponse(sessionID, "403 Forbidden", cseq);
975            return err;
976    }
977
978    mClientInfo.mPlaybackSessionID = playbackSessionID;
979    mClientInfo.mPlaybackSession = playbackSession;
980
981    AString response = "RTSP/1.0 200 OK\r\n";
982    AppendCommonResponse(&response, cseq, playbackSessionID);
983
984    if (transportMode == PlaybackSession::TRANSPORT_TCP_INTERLEAVED) {
985        response.append(
986                StringPrintf(
987                    "Transport: RTP/AVP/TCP;interleaved=%d-%d;",
988                    clientRtp, clientRtcp));
989    } else {
990        int32_t serverRtp = playbackSession->getRTPPort();
991
992        AString transportString = "UDP";
993        if (transportMode == PlaybackSession::TRANSPORT_TCP) {
994            transportString = "TCP";
995        }
996
997        if (clientRtcp >= 0) {
998            response.append(
999                    StringPrintf(
1000                        "Transport: RTP/AVP/%s;unicast;client_port=%d-%d;"
1001                        "server_port=%d-%d\r\n",
1002                        transportString.c_str(),
1003                        clientRtp, clientRtcp, serverRtp, serverRtp + 1));
1004        } else {
1005            response.append(
1006                    StringPrintf(
1007                        "Transport: RTP/AVP/%s;unicast;client_port=%d;"
1008                        "server_port=%d\r\n",
1009                        transportString.c_str(),
1010                        clientRtp, serverRtp));
1011        }
1012    }
1013
1014    response.append("\r\n");
1015
1016    err = mNetSession->sendRequest(sessionID, response.c_str());
1017
1018    if (err != OK) {
1019        return err;
1020    }
1021
1022    scheduleReaper();
1023    scheduleKeepAlive(sessionID);
1024
1025    return OK;
1026}
1027
1028status_t WifiDisplaySource::onPlayRequest(
1029        int32_t sessionID,
1030        int32_t cseq,
1031        const sp<ParsedMessage> &data) {
1032    int32_t playbackSessionID;
1033    sp<PlaybackSession> playbackSession =
1034        findPlaybackSession(data, &playbackSessionID);
1035
1036    if (playbackSession == NULL) {
1037        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1038        return ERROR_MALFORMED;
1039    }
1040
1041    ALOGI("Received PLAY request.");
1042
1043    status_t err = playbackSession->play();
1044    CHECK_EQ(err, (status_t)OK);
1045
1046    AString response = "RTSP/1.0 200 OK\r\n";
1047    AppendCommonResponse(&response, cseq, playbackSessionID);
1048    response.append("Range: npt=now-\r\n");
1049    response.append("\r\n");
1050
1051    err = mNetSession->sendRequest(sessionID, response.c_str());
1052
1053    if (err != OK) {
1054        return err;
1055    }
1056
1057    playbackSession->finishPlay();
1058
1059    return OK;
1060}
1061
1062status_t WifiDisplaySource::onPauseRequest(
1063        int32_t sessionID,
1064        int32_t cseq,
1065        const sp<ParsedMessage> &data) {
1066    int32_t playbackSessionID;
1067    sp<PlaybackSession> playbackSession =
1068        findPlaybackSession(data, &playbackSessionID);
1069
1070    if (playbackSession == NULL) {
1071        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1072        return ERROR_MALFORMED;
1073    }
1074
1075    status_t err = playbackSession->pause();
1076    CHECK_EQ(err, (status_t)OK);
1077
1078    AString response = "RTSP/1.0 200 OK\r\n";
1079    AppendCommonResponse(&response, cseq, playbackSessionID);
1080    response.append("\r\n");
1081
1082    err = mNetSession->sendRequest(sessionID, response.c_str());
1083
1084    return err;
1085}
1086
1087status_t WifiDisplaySource::onTeardownRequest(
1088        int32_t sessionID,
1089        int32_t cseq,
1090        const sp<ParsedMessage> &data) {
1091    ALOGI("Received TEARDOWN request.");
1092
1093    int32_t playbackSessionID;
1094    sp<PlaybackSession> playbackSession =
1095        findPlaybackSession(data, &playbackSessionID);
1096
1097    if (playbackSession == NULL) {
1098        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1099        return ERROR_MALFORMED;
1100    }
1101
1102    AString response = "RTSP/1.0 200 OK\r\n";
1103    AppendCommonResponse(&response, cseq, playbackSessionID);
1104    response.append("Connection: close\r\n");
1105    response.append("\r\n");
1106
1107    mNetSession->sendRequest(sessionID, response.c_str());
1108
1109    if (mStopReplyID != 0) {
1110        finishStop();
1111    } else {
1112        mClient->onDisplayError(IRemoteDisplayClient::kDisplayErrorUnknown);
1113    }
1114
1115    return OK;
1116}
1117
1118void WifiDisplaySource::finishStop() {
1119    ALOGV("finishStop");
1120
1121#if REQUIRE_HDCP
1122    if (mHDCP != NULL) {
1123        ALOGI("Initiating HDCP shutdown.");
1124        mHDCP->shutdownAsync();
1125        return;
1126    }
1127#endif
1128
1129    finishStop2();
1130}
1131
1132void WifiDisplaySource::finishStop2() {
1133    ALOGV("finishStop2");
1134
1135#if REQUIRE_HDCP
1136    mHDCP->setObserver(NULL);
1137    mHDCPObserver.clear();
1138    mHDCP.clear();
1139#endif
1140
1141    disconnectClient();
1142
1143    if (mSessionID != 0) {
1144        mNetSession->destroySession(mSessionID);
1145        mSessionID = 0;
1146    }
1147
1148    ALOGV("finishStop2 completed.");
1149
1150    status_t err = OK;
1151
1152    sp<AMessage> response = new AMessage;
1153    response->setInt32("err", err);
1154    response->postReply(mStopReplyID);
1155}
1156
1157status_t WifiDisplaySource::onGetParameterRequest(
1158        int32_t sessionID,
1159        int32_t cseq,
1160        const sp<ParsedMessage> &data) {
1161    int32_t playbackSessionID;
1162    sp<PlaybackSession> playbackSession =
1163        findPlaybackSession(data, &playbackSessionID);
1164
1165    if (playbackSession == NULL) {
1166        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1167        return ERROR_MALFORMED;
1168    }
1169
1170    playbackSession->updateLiveness();
1171
1172    AString response = "RTSP/1.0 200 OK\r\n";
1173    AppendCommonResponse(&response, cseq, playbackSessionID);
1174    response.append("\r\n");
1175
1176    status_t err = mNetSession->sendRequest(sessionID, response.c_str());
1177    return err;
1178}
1179
1180status_t WifiDisplaySource::onSetParameterRequest(
1181        int32_t sessionID,
1182        int32_t cseq,
1183        const sp<ParsedMessage> &data) {
1184    int32_t playbackSessionID;
1185    sp<PlaybackSession> playbackSession =
1186        findPlaybackSession(data, &playbackSessionID);
1187
1188    if (playbackSession == NULL) {
1189        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1190        return ERROR_MALFORMED;
1191    }
1192
1193    if (strstr(data->getContent(), "wfd_idr_request\r\n")) {
1194        playbackSession->requestIDRFrame();
1195    }
1196
1197    playbackSession->updateLiveness();
1198
1199    AString response = "RTSP/1.0 200 OK\r\n";
1200    AppendCommonResponse(&response, cseq, playbackSessionID);
1201    response.append("\r\n");
1202
1203    status_t err = mNetSession->sendRequest(sessionID, response.c_str());
1204    return err;
1205}
1206
1207// static
1208void WifiDisplaySource::AppendCommonResponse(
1209        AString *response, int32_t cseq, int32_t playbackSessionID) {
1210    time_t now = time(NULL);
1211    struct tm *now2 = gmtime(&now);
1212    char buf[128];
1213    strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2);
1214
1215    response->append("Date: ");
1216    response->append(buf);
1217    response->append("\r\n");
1218
1219    response->append("Server: Mine/1.0\r\n");
1220
1221    if (cseq >= 0) {
1222        response->append(StringPrintf("CSeq: %d\r\n", cseq));
1223    }
1224
1225    if (playbackSessionID >= 0ll) {
1226        response->append(
1227                StringPrintf(
1228                    "Session: %d;timeout=%lld\r\n",
1229                    playbackSessionID, kPlaybackSessionTimeoutSecs));
1230    }
1231}
1232
1233void WifiDisplaySource::sendErrorResponse(
1234        int32_t sessionID,
1235        const char *errorDetail,
1236        int32_t cseq) {
1237    AString response;
1238    response.append("RTSP/1.0 ");
1239    response.append(errorDetail);
1240    response.append("\r\n");
1241
1242    AppendCommonResponse(&response, cseq);
1243
1244    response.append("\r\n");
1245
1246    mNetSession->sendRequest(sessionID, response.c_str());
1247}
1248
1249int32_t WifiDisplaySource::makeUniquePlaybackSessionID() const {
1250    return rand();
1251}
1252
1253sp<WifiDisplaySource::PlaybackSession> WifiDisplaySource::findPlaybackSession(
1254        const sp<ParsedMessage> &data, int32_t *playbackSessionID) const {
1255    if (!data->findInt32("session", playbackSessionID)) {
1256        // XXX the older dongles do not always include a "Session:" header.
1257        *playbackSessionID = mClientInfo.mPlaybackSessionID;
1258        return mClientInfo.mPlaybackSession;
1259    }
1260
1261    if (*playbackSessionID != mClientInfo.mPlaybackSessionID) {
1262        return NULL;
1263    }
1264
1265    return mClientInfo.mPlaybackSession;
1266}
1267
1268void WifiDisplaySource::disconnectClient() {
1269    if (mClientInfo.mPlaybackSession != NULL) {
1270        sp<PlaybackSession> playbackSession = mClientInfo.mPlaybackSession;
1271        mClientInfo.mPlaybackSession.clear();
1272
1273        ALOGI("Destroying PlaybackSession");
1274        playbackSession->destroy();
1275        looper()->unregisterHandler(playbackSession->id());
1276    }
1277
1278    if (mClientSessionID != 0) {
1279        mNetSession->destroySession(mClientSessionID);
1280        mClientSessionID = 0;
1281    }
1282
1283    mClient->onDisplayDisconnected();
1284}
1285
1286#if REQUIRE_HDCP
1287struct WifiDisplaySource::HDCPObserver : public BnHDCPObserver {
1288    HDCPObserver(const sp<AMessage> &notify);
1289
1290    virtual void notify(
1291            int msg, int ext1, int ext2, const Parcel *obj);
1292
1293private:
1294    sp<AMessage> mNotify;
1295
1296    DISALLOW_EVIL_CONSTRUCTORS(HDCPObserver);
1297};
1298
1299WifiDisplaySource::HDCPObserver::HDCPObserver(
1300        const sp<AMessage> &notify)
1301    : mNotify(notify) {
1302}
1303
1304void WifiDisplaySource::HDCPObserver::notify(
1305        int msg, int ext1, int ext2, const Parcel *obj) {
1306    sp<AMessage> notify = mNotify->dup();
1307    notify->setInt32("msg", msg);
1308    notify->setInt32("ext1", ext1);
1309    notify->setInt32("ext2", ext2);
1310    notify->post();
1311}
1312
1313status_t WifiDisplaySource::makeHDCP() {
1314    sp<IServiceManager> sm = defaultServiceManager();
1315    sp<IBinder> binder = sm->getService(String16("media.player"));
1316    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
1317    CHECK(service != NULL);
1318
1319    mHDCP = service->makeHDCP();
1320
1321    if (mHDCP == NULL) {
1322        return ERROR_UNSUPPORTED;
1323    }
1324
1325    sp<AMessage> notify = new AMessage(kWhatHDCPNotify, id());
1326    mHDCPObserver = new HDCPObserver(notify);
1327
1328    status_t err = mHDCP->setObserver(mHDCPObserver);
1329
1330    if (err != OK) {
1331        ALOGE("Failed to set HDCP observer.");
1332
1333        mHDCPObserver.clear();
1334        mHDCP.clear();
1335
1336        return err;
1337    }
1338
1339    ALOGI("Initiating HDCP negotiation w/ host %s:%d",
1340            mClientInfo.mRemoteIP.c_str(), mHDCPPort);
1341
1342    err = mHDCP->initAsync(mClientInfo.mRemoteIP.c_str(), mHDCPPort);
1343
1344    if (err != OK) {
1345        return err;
1346    }
1347
1348    return OK;
1349}
1350#endif
1351
1352}  // namespace android
1353
1354