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