WifiDisplaySource.cpp revision bbe96f0f05a1f1a1b3cfec0d124cb0d63c1ebf2a
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 if (what == PlaybackSession::kWhatSessionDestroyed) {
297                disconnectClient2();
298            } else {
299                CHECK_EQ(what, PlaybackSession::kWhatBinaryData);
300
301                int32_t channel;
302                CHECK(msg->findInt32("channel", &channel));
303
304                sp<ABuffer> data;
305                CHECK(msg->findBuffer("data", &data));
306
307                CHECK_LE(channel, 0xffu);
308                CHECK_LE(data->size(), 0xffffu);
309
310                int32_t sessionID;
311                CHECK(msg->findInt32("sessionID", &sessionID));
312
313                char header[4];
314                header[0] = '$';
315                header[1] = channel;
316                header[2] = data->size() >> 8;
317                header[3] = data->size() & 0xff;
318
319                mNetSession->sendRequest(
320                        sessionID, header, sizeof(header));
321
322                mNetSession->sendRequest(
323                        sessionID, data->data(), data->size());
324            }
325            break;
326        }
327
328        case kWhatKeepAlive:
329        {
330            int32_t sessionID;
331            CHECK(msg->findInt32("sessionID", &sessionID));
332
333            if (mClientSessionID != sessionID) {
334                // Obsolete event, client is already gone.
335                break;
336            }
337
338            sendM16(sessionID);
339            break;
340        }
341
342#if REQUIRE_HDCP
343        case kWhatHDCPNotify:
344        {
345            int32_t msgCode, ext1, ext2;
346            CHECK(msg->findInt32("msg", &msgCode));
347            CHECK(msg->findInt32("ext1", &ext1));
348            CHECK(msg->findInt32("ext2", &ext2));
349
350            ALOGI("Saw HDCP notification code %d, ext1 %d, ext2 %d",
351                    msgCode, ext1, ext2);
352
353            switch (msgCode) {
354                case HDCPModule::HDCP_INITIALIZATION_COMPLETE:
355                {
356                    mHDCPInitializationComplete = true;
357
358                    if (mSetupTriggerDeferred) {
359                        mSetupTriggerDeferred = false;
360
361                        sendM5(mClientSessionID, false /* requestShutdown */);
362                    }
363                    break;
364                }
365
366                case HDCPModule::HDCP_SHUTDOWN_COMPLETE:
367                case HDCPModule::HDCP_SHUTDOWN_FAILED:
368                {
369                    // Ugly hack to make sure that the call to
370                    // HDCPObserver::notify is completely handled before
371                    // we clear the HDCP instance and unload the shared
372                    // library :(
373                    (new AMessage(kWhatFinishStop2, id()))->post(300000ll);
374                    break;
375                }
376
377                default:
378                {
379                    ALOGE("HDCP failure, shutting down.");
380
381                    mClient->onDisplayError(
382                            IRemoteDisplayClient::kDisplayErrorUnknown);
383                    break;
384                }
385            }
386            break;
387        }
388
389        case kWhatFinishStop2:
390        {
391            finishStop2();
392            break;
393        }
394#endif
395
396        default:
397            TRESPASS();
398    }
399}
400
401void WifiDisplaySource::registerResponseHandler(
402        int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func) {
403    ResponseID id;
404    id.mSessionID = sessionID;
405    id.mCSeq = cseq;
406    mResponseHandlers.add(id, func);
407}
408
409status_t WifiDisplaySource::sendM1(int32_t sessionID) {
410    AString request = "OPTIONS * RTSP/1.0\r\n";
411    AppendCommonResponse(&request, mNextCSeq);
412
413    request.append(
414            "Require: org.wfa.wfd1.0\r\n"
415            "\r\n");
416
417    status_t err =
418        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
419
420    if (err != OK) {
421        return err;
422    }
423
424    registerResponseHandler(
425            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM1Response);
426
427    ++mNextCSeq;
428
429    return OK;
430}
431
432status_t WifiDisplaySource::sendM3(int32_t sessionID) {
433    AString body =
434#if REQUIRE_HDCP
435        "wfd_content_protection\r\n"
436#endif
437        "wfd_video_formats\r\n"
438        "wfd_audio_codecs\r\n"
439        "wfd_client_rtp_ports\r\n";
440
441    AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
442    AppendCommonResponse(&request, mNextCSeq);
443
444    request.append("Content-Type: text/parameters\r\n");
445    request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
446    request.append("\r\n");
447    request.append(body);
448
449    status_t err =
450        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
451
452    if (err != OK) {
453        return err;
454    }
455
456    registerResponseHandler(
457            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM3Response);
458
459    ++mNextCSeq;
460
461    return OK;
462}
463
464status_t WifiDisplaySource::sendM4(int32_t sessionID) {
465    // wfd_video_formats:
466    // 1 byte "native"
467    // 1 byte "preferred-display-mode-supported" 0 or 1
468    // one or more avc codec structures
469    //   1 byte profile
470    //   1 byte level
471    //   4 byte CEA mask
472    //   4 byte VESA mask
473    //   4 byte HH mask
474    //   1 byte latency
475    //   2 byte min-slice-slice
476    //   2 byte slice-enc-params
477    //   1 byte framerate-control-support
478    //   max-hres (none or 2 byte)
479    //   max-vres (none or 2 byte)
480
481    CHECK_EQ(sessionID, mClientSessionID);
482
483    AString transportString = "UDP";
484
485    char val[PROPERTY_VALUE_MAX];
486    if (property_get("media.wfd.enable-tcp", val, NULL)
487            && (!strcasecmp("true", val) || !strcmp("1", val))) {
488        ALOGI("Using TCP transport.");
489        transportString = "TCP";
490    }
491
492    // For 720p60:
493    //   use "30 00 02 02 00000040 00000000 00000000 00 0000 0000 00 none none\r\n"
494    // For 720p30:
495    //   use "28 00 02 02 00000020 00000000 00000000 00 0000 0000 00 none none\r\n"
496    // For 720p24:
497    //   use "78 00 02 02 00008000 00000000 00000000 00 0000 0000 00 none none\r\n"
498    AString body = StringPrintf(
499        "wfd_video_formats: "
500        "78 00 02 02 00008000 00000000 00000000 00 0000 0000 00 none none\r\n"
501        "wfd_audio_codecs: AAC 00000001 00\r\n"  // 2 ch AAC 48kHz
502        "wfd_presentation_URL: rtsp://%s/wfd1.0/streamid=0 none\r\n"
503        "wfd_client_rtp_ports: RTP/AVP/%s;unicast 19000 0 mode=play\r\n",
504        mClientInfo.mLocalIP.c_str(), transportString.c_str());
505
506    AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
507    AppendCommonResponse(&request, mNextCSeq);
508
509    request.append("Content-Type: text/parameters\r\n");
510    request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
511    request.append("\r\n");
512    request.append(body);
513
514    status_t err =
515        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
516
517    if (err != OK) {
518        return err;
519    }
520
521    registerResponseHandler(
522            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM4Response);
523
524    ++mNextCSeq;
525
526    return OK;
527}
528
529status_t WifiDisplaySource::sendM5(int32_t sessionID, bool requestShutdown) {
530    AString body = "wfd_trigger_method: ";
531    if (requestShutdown) {
532        ALOGI("Sending TEARDOWN trigger.");
533        body.append("TEARDOWN");
534    } else {
535        body.append("SETUP");
536    }
537
538    body.append("\r\n");
539
540    AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
541    AppendCommonResponse(&request, mNextCSeq);
542
543    request.append("Content-Type: text/parameters\r\n");
544    request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
545    request.append("\r\n");
546    request.append(body);
547
548    status_t err =
549        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
550
551    if (err != OK) {
552        return err;
553    }
554
555    registerResponseHandler(
556            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM5Response);
557
558    ++mNextCSeq;
559
560    return OK;
561}
562
563status_t WifiDisplaySource::sendM16(int32_t sessionID) {
564    AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
565    AppendCommonResponse(&request, mNextCSeq);
566
567    CHECK_EQ(sessionID, mClientSessionID);
568    request.append(
569            StringPrintf("Session: %d\r\n", mClientInfo.mPlaybackSessionID));
570    request.append("\r\n");  // Empty body
571
572    status_t err =
573        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
574
575    if (err != OK) {
576        return err;
577    }
578
579    registerResponseHandler(
580            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM16Response);
581
582    ++mNextCSeq;
583
584    return OK;
585}
586
587status_t WifiDisplaySource::onReceiveM1Response(
588        int32_t sessionID, const sp<ParsedMessage> &msg) {
589    int32_t statusCode;
590    if (!msg->getStatusCode(&statusCode)) {
591        return ERROR_MALFORMED;
592    }
593
594    if (statusCode != 200) {
595        return ERROR_UNSUPPORTED;
596    }
597
598    return OK;
599}
600
601status_t WifiDisplaySource::onReceiveM3Response(
602        int32_t sessionID, const sp<ParsedMessage> &msg) {
603    int32_t statusCode;
604    if (!msg->getStatusCode(&statusCode)) {
605        return ERROR_MALFORMED;
606    }
607
608    if (statusCode != 200) {
609        return ERROR_UNSUPPORTED;
610    }
611
612    sp<Parameters> params =
613        Parameters::Parse(msg->getContent(), strlen(msg->getContent()));
614
615    if (params == NULL) {
616        return ERROR_MALFORMED;
617    }
618
619#if REQUIRE_HDCP
620    AString value;
621    if (!params->findParameter("wfd_content_protection", &value)) {
622        ALOGE("Sink doesn't appear to support content protection.");
623        return -EACCES;
624    }
625
626    if (value == "none") {
627        ALOGE("Sink does not support content protection.");
628        return -EACCES;
629    }
630
631    bool isHDCP2_0 = false;
632    if (value.startsWith("HDCP2.0 ")) {
633        isHDCP2_0 = true;
634    } else if (!value.startsWith("HDCP2.1 ")) {
635        return ERROR_MALFORMED;
636    }
637
638    int32_t hdcpPort;
639    if (!ParsedMessage::GetInt32Attribute(value.c_str() + 8, "port", &hdcpPort)
640            || hdcpPort < 1 || hdcpPort > 65535) {
641        return ERROR_MALFORMED;
642    }
643
644    mIsHDCP2_0 = isHDCP2_0;
645    mHDCPPort = hdcpPort;
646
647    status_t err = makeHDCP();
648    if (err != OK) {
649        ALOGE("Unable to instantiate HDCP component.");
650        return err;
651    }
652#endif
653
654    return sendM4(sessionID);
655}
656
657status_t WifiDisplaySource::onReceiveM4Response(
658        int32_t sessionID, const sp<ParsedMessage> &msg) {
659    int32_t statusCode;
660    if (!msg->getStatusCode(&statusCode)) {
661        return ERROR_MALFORMED;
662    }
663
664    if (statusCode != 200) {
665        return ERROR_UNSUPPORTED;
666    }
667
668#if REQUIRE_HDCP
669    if (!mHDCPInitializationComplete) {
670        ALOGI("Deferring SETUP trigger until HDCP initialization completes.");
671
672        mSetupTriggerDeferred = true;
673        return OK;
674    }
675#endif
676
677    return sendM5(sessionID, false /* requestShutdown */);
678}
679
680status_t WifiDisplaySource::onReceiveM5Response(
681        int32_t sessionID, const sp<ParsedMessage> &msg) {
682    int32_t statusCode;
683    if (!msg->getStatusCode(&statusCode)) {
684        return ERROR_MALFORMED;
685    }
686
687    if (statusCode != 200) {
688        return ERROR_UNSUPPORTED;
689    }
690
691    return OK;
692}
693
694status_t WifiDisplaySource::onReceiveM16Response(
695        int32_t sessionID, const sp<ParsedMessage> &msg) {
696    // If only the response was required to include a "Session:" header...
697
698    CHECK_EQ(sessionID, mClientSessionID);
699
700    if (mClientInfo.mPlaybackSession != NULL) {
701        mClientInfo.mPlaybackSession->updateLiveness();
702
703        scheduleKeepAlive(sessionID);
704    }
705
706    return OK;
707}
708
709void WifiDisplaySource::scheduleReaper() {
710    if (mReaperPending) {
711        return;
712    }
713
714    mReaperPending = true;
715    (new AMessage(kWhatReapDeadClients, id()))->post(kReaperIntervalUs);
716}
717
718void WifiDisplaySource::scheduleKeepAlive(int32_t sessionID) {
719    // We need to send updates at least 5 secs before the timeout is set to
720    // expire, make sure the timeout is greater than 5 secs to begin with.
721    CHECK_GT(kPlaybackSessionTimeoutUs, 5000000ll);
722
723    sp<AMessage> msg = new AMessage(kWhatKeepAlive, id());
724    msg->setInt32("sessionID", sessionID);
725    msg->post(kPlaybackSessionTimeoutUs - 5000000ll);
726}
727
728status_t WifiDisplaySource::onReceiveClientData(const sp<AMessage> &msg) {
729    int32_t sessionID;
730    CHECK(msg->findInt32("sessionID", &sessionID));
731
732    sp<RefBase> obj;
733    CHECK(msg->findObject("data", &obj));
734
735    sp<ParsedMessage> data =
736        static_cast<ParsedMessage *>(obj.get());
737
738    ALOGV("session %d received '%s'",
739          sessionID, data->debugString().c_str());
740
741    AString method;
742    AString uri;
743    data->getRequestField(0, &method);
744
745    int32_t cseq;
746    if (!data->findInt32("cseq", &cseq)) {
747        sendErrorResponse(sessionID, "400 Bad Request", -1 /* cseq */);
748        return ERROR_MALFORMED;
749    }
750
751    if (method.startsWith("RTSP/")) {
752        // This is a response.
753
754        ResponseID id;
755        id.mSessionID = sessionID;
756        id.mCSeq = cseq;
757
758        ssize_t index = mResponseHandlers.indexOfKey(id);
759
760        if (index < 0) {
761            ALOGW("Received unsolicited server response, cseq %d", cseq);
762            return ERROR_MALFORMED;
763        }
764
765        HandleRTSPResponseFunc func = mResponseHandlers.valueAt(index);
766        mResponseHandlers.removeItemsAt(index);
767
768        status_t err = (this->*func)(sessionID, data);
769
770        if (err != OK) {
771            ALOGW("Response handler for session %d, cseq %d returned "
772                  "err %d (%s)",
773                  sessionID, cseq, err, strerror(-err));
774
775            return err;
776        }
777
778        return OK;
779    }
780
781    AString version;
782    data->getRequestField(2, &version);
783    if (!(version == AString("RTSP/1.0"))) {
784        sendErrorResponse(sessionID, "505 RTSP Version not supported", cseq);
785        return ERROR_UNSUPPORTED;
786    }
787
788    status_t err;
789    if (method == "OPTIONS") {
790        err = onOptionsRequest(sessionID, cseq, data);
791    } else if (method == "SETUP") {
792        err = onSetupRequest(sessionID, cseq, data);
793    } else if (method == "PLAY") {
794        err = onPlayRequest(sessionID, cseq, data);
795    } else if (method == "PAUSE") {
796        err = onPauseRequest(sessionID, cseq, data);
797    } else if (method == "TEARDOWN") {
798        err = onTeardownRequest(sessionID, cseq, data);
799    } else if (method == "GET_PARAMETER") {
800        err = onGetParameterRequest(sessionID, cseq, data);
801    } else if (method == "SET_PARAMETER") {
802        err = onSetParameterRequest(sessionID, cseq, data);
803    } else {
804        sendErrorResponse(sessionID, "405 Method Not Allowed", cseq);
805
806        err = ERROR_UNSUPPORTED;
807    }
808
809    return err;
810}
811
812status_t WifiDisplaySource::onOptionsRequest(
813        int32_t sessionID,
814        int32_t cseq,
815        const sp<ParsedMessage> &data) {
816    int32_t playbackSessionID;
817    sp<PlaybackSession> playbackSession =
818        findPlaybackSession(data, &playbackSessionID);
819
820    if (playbackSession != NULL) {
821        playbackSession->updateLiveness();
822    }
823
824    AString response = "RTSP/1.0 200 OK\r\n";
825    AppendCommonResponse(&response, cseq);
826
827    response.append(
828            "Public: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, "
829            "GET_PARAMETER, SET_PARAMETER\r\n");
830
831    response.append("\r\n");
832
833    status_t err = mNetSession->sendRequest(sessionID, response.c_str());
834
835    if (err == OK) {
836        err = sendM3(sessionID);
837    }
838
839    return err;
840}
841
842status_t WifiDisplaySource::onSetupRequest(
843        int32_t sessionID,
844        int32_t cseq,
845        const sp<ParsedMessage> &data) {
846    CHECK_EQ(sessionID, mClientSessionID);
847    if (mClientInfo.mPlaybackSessionID != -1) {
848        // We only support a single playback session per client.
849        // This is due to the reversed keep-alive design in the wfd specs...
850        sendErrorResponse(sessionID, "400 Bad Request", cseq);
851        return ERROR_MALFORMED;
852    }
853
854    AString transport;
855    if (!data->findString("transport", &transport)) {
856        sendErrorResponse(sessionID, "400 Bad Request", cseq);
857        return ERROR_MALFORMED;
858    }
859
860    PlaybackSession::TransportMode transportMode =
861        PlaybackSession::TRANSPORT_UDP;
862
863    int clientRtp, clientRtcp;
864    if (transport.startsWith("RTP/AVP/TCP;")) {
865        AString interleaved;
866        if (ParsedMessage::GetAttribute(
867                    transport.c_str(), "interleaved", &interleaved)
868                && sscanf(interleaved.c_str(), "%d-%d",
869                          &clientRtp, &clientRtcp) == 2) {
870            transportMode = PlaybackSession::TRANSPORT_TCP_INTERLEAVED;
871        } else {
872            bool badRequest = false;
873
874            AString clientPort;
875            if (!ParsedMessage::GetAttribute(
876                        transport.c_str(), "client_port", &clientPort)) {
877                badRequest = true;
878            } else if (sscanf(clientPort.c_str(), "%d-%d",
879                              &clientRtp, &clientRtcp) == 2) {
880            } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) {
881                // No RTCP.
882                clientRtcp = -1;
883            } else {
884                badRequest = true;
885            }
886
887            if (badRequest) {
888                sendErrorResponse(sessionID, "400 Bad Request", cseq);
889                return ERROR_MALFORMED;
890            }
891
892            transportMode = PlaybackSession::TRANSPORT_TCP;
893        }
894    } else if (transport.startsWith("RTP/AVP;unicast;")
895            || transport.startsWith("RTP/AVP/UDP;unicast;")) {
896        bool badRequest = false;
897
898        AString clientPort;
899        if (!ParsedMessage::GetAttribute(
900                    transport.c_str(), "client_port", &clientPort)) {
901            badRequest = true;
902        } else if (sscanf(clientPort.c_str(), "%d-%d",
903                          &clientRtp, &clientRtcp) == 2) {
904        } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) {
905            // No RTCP.
906            clientRtcp = -1;
907        } else {
908            badRequest = true;
909        }
910
911        if (badRequest) {
912            sendErrorResponse(sessionID, "400 Bad Request", cseq);
913            return ERROR_MALFORMED;
914        }
915#if 1
916    // The older LG dongles doesn't specify client_port=xxx apparently.
917    } else if (transport == "RTP/AVP/UDP;unicast") {
918        clientRtp = 19000;
919        clientRtcp = -1;
920#endif
921    } else {
922        sendErrorResponse(sessionID, "461 Unsupported Transport", cseq);
923        return ERROR_UNSUPPORTED;
924    }
925
926    int32_t playbackSessionID = makeUniquePlaybackSessionID();
927
928    sp<AMessage> notify = new AMessage(kWhatPlaybackSessionNotify, id());
929    notify->setInt32("playbackSessionID", playbackSessionID);
930    notify->setInt32("sessionID", sessionID);
931
932    sp<PlaybackSession> playbackSession =
933        new PlaybackSession(
934                mNetSession, notify, mInterfaceAddr,
935#if REQUIRE_HDCP
936                mHDCP
937#else
938                NULL
939#endif
940                );
941
942    looper()->registerHandler(playbackSession);
943
944    AString uri;
945    data->getRequestField(1, &uri);
946
947    if (strncasecmp("rtsp://", uri.c_str(), 7)) {
948        sendErrorResponse(sessionID, "400 Bad Request", cseq);
949        return ERROR_MALFORMED;
950    }
951
952    if (!(uri.startsWith("rtsp://") && uri.endsWith("/wfd1.0/streamid=0"))) {
953        sendErrorResponse(sessionID, "404 Not found", cseq);
954        return ERROR_MALFORMED;
955    }
956
957    status_t err = playbackSession->init(
958            mClientInfo.mRemoteIP.c_str(),
959            clientRtp,
960            clientRtcp,
961            transportMode);
962
963    if (err != OK) {
964        looper()->unregisterHandler(playbackSession->id());
965        playbackSession.clear();
966    }
967
968    switch (err) {
969        case OK:
970            break;
971        case -ENOENT:
972            sendErrorResponse(sessionID, "404 Not Found", cseq);
973            return err;
974        default:
975            sendErrorResponse(sessionID, "403 Forbidden", cseq);
976            return err;
977    }
978
979    mClientInfo.mPlaybackSessionID = playbackSessionID;
980    mClientInfo.mPlaybackSession = playbackSession;
981
982    AString response = "RTSP/1.0 200 OK\r\n";
983    AppendCommonResponse(&response, cseq, playbackSessionID);
984
985    if (transportMode == PlaybackSession::TRANSPORT_TCP_INTERLEAVED) {
986        response.append(
987                StringPrintf(
988                    "Transport: RTP/AVP/TCP;interleaved=%d-%d;",
989                    clientRtp, clientRtcp));
990    } else {
991        int32_t serverRtp = playbackSession->getRTPPort();
992
993        AString transportString = "UDP";
994        if (transportMode == PlaybackSession::TRANSPORT_TCP) {
995            transportString = "TCP";
996        }
997
998        if (clientRtcp >= 0) {
999            response.append(
1000                    StringPrintf(
1001                        "Transport: RTP/AVP/%s;unicast;client_port=%d-%d;"
1002                        "server_port=%d-%d\r\n",
1003                        transportString.c_str(),
1004                        clientRtp, clientRtcp, serverRtp, serverRtp + 1));
1005        } else {
1006            response.append(
1007                    StringPrintf(
1008                        "Transport: RTP/AVP/%s;unicast;client_port=%d;"
1009                        "server_port=%d\r\n",
1010                        transportString.c_str(),
1011                        clientRtp, serverRtp));
1012        }
1013    }
1014
1015    response.append("\r\n");
1016
1017    err = mNetSession->sendRequest(sessionID, response.c_str());
1018
1019    if (err != OK) {
1020        return err;
1021    }
1022
1023    scheduleReaper();
1024    scheduleKeepAlive(sessionID);
1025
1026    return OK;
1027}
1028
1029status_t WifiDisplaySource::onPlayRequest(
1030        int32_t sessionID,
1031        int32_t cseq,
1032        const sp<ParsedMessage> &data) {
1033    int32_t playbackSessionID;
1034    sp<PlaybackSession> playbackSession =
1035        findPlaybackSession(data, &playbackSessionID);
1036
1037    if (playbackSession == NULL) {
1038        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1039        return ERROR_MALFORMED;
1040    }
1041
1042    ALOGI("Received PLAY request.");
1043
1044    status_t err = playbackSession->play();
1045    CHECK_EQ(err, (status_t)OK);
1046
1047    AString response = "RTSP/1.0 200 OK\r\n";
1048    AppendCommonResponse(&response, cseq, playbackSessionID);
1049    response.append("Range: npt=now-\r\n");
1050    response.append("\r\n");
1051
1052    err = mNetSession->sendRequest(sessionID, response.c_str());
1053
1054    if (err != OK) {
1055        return err;
1056    }
1057
1058    playbackSession->finishPlay();
1059
1060    return OK;
1061}
1062
1063status_t WifiDisplaySource::onPauseRequest(
1064        int32_t sessionID,
1065        int32_t cseq,
1066        const sp<ParsedMessage> &data) {
1067    int32_t playbackSessionID;
1068    sp<PlaybackSession> playbackSession =
1069        findPlaybackSession(data, &playbackSessionID);
1070
1071    if (playbackSession == NULL) {
1072        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1073        return ERROR_MALFORMED;
1074    }
1075
1076    status_t err = playbackSession->pause();
1077    CHECK_EQ(err, (status_t)OK);
1078
1079    AString response = "RTSP/1.0 200 OK\r\n";
1080    AppendCommonResponse(&response, cseq, playbackSessionID);
1081    response.append("\r\n");
1082
1083    err = mNetSession->sendRequest(sessionID, response.c_str());
1084
1085    return err;
1086}
1087
1088status_t WifiDisplaySource::onTeardownRequest(
1089        int32_t sessionID,
1090        int32_t cseq,
1091        const sp<ParsedMessage> &data) {
1092    ALOGI("Received TEARDOWN request.");
1093
1094    int32_t playbackSessionID;
1095    sp<PlaybackSession> playbackSession =
1096        findPlaybackSession(data, &playbackSessionID);
1097
1098    if (playbackSession == NULL) {
1099        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1100        return ERROR_MALFORMED;
1101    }
1102
1103    AString response = "RTSP/1.0 200 OK\r\n";
1104    AppendCommonResponse(&response, cseq, playbackSessionID);
1105    response.append("Connection: close\r\n");
1106    response.append("\r\n");
1107
1108    mNetSession->sendRequest(sessionID, response.c_str());
1109
1110    if (mStopReplyID != 0) {
1111        finishStop();
1112    } else {
1113        mClient->onDisplayError(IRemoteDisplayClient::kDisplayErrorUnknown);
1114    }
1115
1116    return OK;
1117}
1118
1119void WifiDisplaySource::finishStop() {
1120    ALOGV("finishStop");
1121
1122    disconnectClientAsync();
1123}
1124
1125void WifiDisplaySource::finishStopAfterDisconnectingClient() {
1126    ALOGV("finishStopAfterDisconnectingClient");
1127
1128#if REQUIRE_HDCP
1129    if (mHDCP != NULL) {
1130        ALOGI("Initiating HDCP shutdown.");
1131        mHDCP->shutdownAsync();
1132        return;
1133    }
1134#endif
1135
1136    finishStop2();
1137}
1138
1139void WifiDisplaySource::finishStop2() {
1140    ALOGV("finishStop2");
1141
1142#if REQUIRE_HDCP
1143    if (mHDCP != NULL) {
1144        mHDCP->setObserver(NULL);
1145        mHDCPObserver.clear();
1146        mHDCP.clear();
1147    }
1148#endif
1149
1150    if (mSessionID != 0) {
1151        mNetSession->destroySession(mSessionID);
1152        mSessionID = 0;
1153    }
1154
1155    ALOGI("We're stopped.");
1156
1157    status_t err = OK;
1158
1159    sp<AMessage> response = new AMessage;
1160    response->setInt32("err", err);
1161    response->postReply(mStopReplyID);
1162}
1163
1164status_t WifiDisplaySource::onGetParameterRequest(
1165        int32_t sessionID,
1166        int32_t cseq,
1167        const sp<ParsedMessage> &data) {
1168    int32_t playbackSessionID;
1169    sp<PlaybackSession> playbackSession =
1170        findPlaybackSession(data, &playbackSessionID);
1171
1172    if (playbackSession == NULL) {
1173        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1174        return ERROR_MALFORMED;
1175    }
1176
1177    playbackSession->updateLiveness();
1178
1179    AString response = "RTSP/1.0 200 OK\r\n";
1180    AppendCommonResponse(&response, cseq, playbackSessionID);
1181    response.append("\r\n");
1182
1183    status_t err = mNetSession->sendRequest(sessionID, response.c_str());
1184    return err;
1185}
1186
1187status_t WifiDisplaySource::onSetParameterRequest(
1188        int32_t sessionID,
1189        int32_t cseq,
1190        const sp<ParsedMessage> &data) {
1191    int32_t playbackSessionID;
1192    sp<PlaybackSession> playbackSession =
1193        findPlaybackSession(data, &playbackSessionID);
1194
1195    if (playbackSession == NULL) {
1196        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1197        return ERROR_MALFORMED;
1198    }
1199
1200    if (strstr(data->getContent(), "wfd_idr_request\r\n")) {
1201        playbackSession->requestIDRFrame();
1202    }
1203
1204    playbackSession->updateLiveness();
1205
1206    AString response = "RTSP/1.0 200 OK\r\n";
1207    AppendCommonResponse(&response, cseq, playbackSessionID);
1208    response.append("\r\n");
1209
1210    status_t err = mNetSession->sendRequest(sessionID, response.c_str());
1211    return err;
1212}
1213
1214// static
1215void WifiDisplaySource::AppendCommonResponse(
1216        AString *response, int32_t cseq, int32_t playbackSessionID) {
1217    time_t now = time(NULL);
1218    struct tm *now2 = gmtime(&now);
1219    char buf[128];
1220    strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2);
1221
1222    response->append("Date: ");
1223    response->append(buf);
1224    response->append("\r\n");
1225
1226    response->append("Server: Mine/1.0\r\n");
1227
1228    if (cseq >= 0) {
1229        response->append(StringPrintf("CSeq: %d\r\n", cseq));
1230    }
1231
1232    if (playbackSessionID >= 0ll) {
1233        response->append(
1234                StringPrintf(
1235                    "Session: %d;timeout=%lld\r\n",
1236                    playbackSessionID, kPlaybackSessionTimeoutSecs));
1237    }
1238}
1239
1240void WifiDisplaySource::sendErrorResponse(
1241        int32_t sessionID,
1242        const char *errorDetail,
1243        int32_t cseq) {
1244    AString response;
1245    response.append("RTSP/1.0 ");
1246    response.append(errorDetail);
1247    response.append("\r\n");
1248
1249    AppendCommonResponse(&response, cseq);
1250
1251    response.append("\r\n");
1252
1253    mNetSession->sendRequest(sessionID, response.c_str());
1254}
1255
1256int32_t WifiDisplaySource::makeUniquePlaybackSessionID() const {
1257    return rand();
1258}
1259
1260sp<WifiDisplaySource::PlaybackSession> WifiDisplaySource::findPlaybackSession(
1261        const sp<ParsedMessage> &data, int32_t *playbackSessionID) const {
1262    if (!data->findInt32("session", playbackSessionID)) {
1263        // XXX the older dongles do not always include a "Session:" header.
1264        *playbackSessionID = mClientInfo.mPlaybackSessionID;
1265        return mClientInfo.mPlaybackSession;
1266    }
1267
1268    if (*playbackSessionID != mClientInfo.mPlaybackSessionID) {
1269        return NULL;
1270    }
1271
1272    return mClientInfo.mPlaybackSession;
1273}
1274
1275void WifiDisplaySource::disconnectClientAsync() {
1276    ALOGV("disconnectClient");
1277
1278    if (mClientInfo.mPlaybackSession == NULL) {
1279        disconnectClient2();
1280        return;
1281    }
1282
1283    if (mClientInfo.mPlaybackSession != NULL) {
1284        ALOGV("Destroying PlaybackSession");
1285        mClientInfo.mPlaybackSession->destroyAsync();
1286    }
1287}
1288
1289void WifiDisplaySource::disconnectClient2() {
1290    ALOGV("disconnectClient2");
1291
1292    if (mClientInfo.mPlaybackSession != NULL) {
1293        looper()->unregisterHandler(mClientInfo.mPlaybackSession->id());
1294        mClientInfo.mPlaybackSession.clear();
1295    }
1296
1297    if (mClientSessionID != 0) {
1298        mNetSession->destroySession(mClientSessionID);
1299        mClientSessionID = 0;
1300    }
1301
1302    mClient->onDisplayDisconnected();
1303
1304    finishStopAfterDisconnectingClient();
1305}
1306
1307#if REQUIRE_HDCP
1308struct WifiDisplaySource::HDCPObserver : public BnHDCPObserver {
1309    HDCPObserver(const sp<AMessage> &notify);
1310
1311    virtual void notify(
1312            int msg, int ext1, int ext2, const Parcel *obj);
1313
1314private:
1315    sp<AMessage> mNotify;
1316
1317    DISALLOW_EVIL_CONSTRUCTORS(HDCPObserver);
1318};
1319
1320WifiDisplaySource::HDCPObserver::HDCPObserver(
1321        const sp<AMessage> &notify)
1322    : mNotify(notify) {
1323}
1324
1325void WifiDisplaySource::HDCPObserver::notify(
1326        int msg, int ext1, int ext2, const Parcel *obj) {
1327    sp<AMessage> notify = mNotify->dup();
1328    notify->setInt32("msg", msg);
1329    notify->setInt32("ext1", ext1);
1330    notify->setInt32("ext2", ext2);
1331    notify->post();
1332}
1333
1334status_t WifiDisplaySource::makeHDCP() {
1335    sp<IServiceManager> sm = defaultServiceManager();
1336    sp<IBinder> binder = sm->getService(String16("media.player"));
1337    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
1338    CHECK(service != NULL);
1339
1340    mHDCP = service->makeHDCP();
1341
1342    if (mHDCP == NULL) {
1343        return ERROR_UNSUPPORTED;
1344    }
1345
1346    sp<AMessage> notify = new AMessage(kWhatHDCPNotify, id());
1347    mHDCPObserver = new HDCPObserver(notify);
1348
1349    status_t err = mHDCP->setObserver(mHDCPObserver);
1350
1351    if (err != OK) {
1352        ALOGE("Failed to set HDCP observer.");
1353
1354        mHDCPObserver.clear();
1355        mHDCP.clear();
1356
1357        return err;
1358    }
1359
1360    ALOGI("Initiating HDCP negotiation w/ host %s:%d",
1361            mClientInfo.mRemoteIP.c_str(), mHDCPPort);
1362
1363    err = mHDCP->initAsync(mClientInfo.mRemoteIP.c_str(), mHDCPPort);
1364
1365    if (err != OK) {
1366        return err;
1367    }
1368
1369    return OK;
1370}
1371#endif
1372
1373}  // namespace android
1374
1375