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