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