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