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