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