WifiDisplaySource.cpp revision 3a9682a86ead84d6f60d3f3aa01b2b4d34af983d
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(mWfdClientRtpPorts);
639    body.append("\r\n");
640
641    AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
642    AppendCommonResponse(&request, mNextCSeq);
643
644    request.append("Content-Type: text/parameters\r\n");
645    request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
646    request.append("\r\n");
647    request.append(body);
648
649    status_t err =
650        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
651
652    if (err != OK) {
653        return err;
654    }
655
656    registerResponseHandler(
657            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM4Response);
658
659    ++mNextCSeq;
660
661    return OK;
662}
663
664status_t WifiDisplaySource::sendTrigger(
665        int32_t sessionID, TriggerType triggerType) {
666    AString body = "wfd_trigger_method: ";
667    switch (triggerType) {
668        case TRIGGER_SETUP:
669            body.append("SETUP");
670            break;
671        case TRIGGER_TEARDOWN:
672            ALOGI("Sending TEARDOWN trigger.");
673            body.append("TEARDOWN");
674            break;
675        case TRIGGER_PAUSE:
676            body.append("PAUSE");
677            break;
678        case TRIGGER_PLAY:
679            body.append("PLAY");
680            break;
681        default:
682            TRESPASS();
683    }
684
685    body.append("\r\n");
686
687    AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
688    AppendCommonResponse(&request, mNextCSeq);
689
690    request.append("Content-Type: text/parameters\r\n");
691    request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
692    request.append("\r\n");
693    request.append(body);
694
695    status_t err =
696        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
697
698    if (err != OK) {
699        return err;
700    }
701
702    registerResponseHandler(
703            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM5Response);
704
705    ++mNextCSeq;
706
707    return OK;
708}
709
710status_t WifiDisplaySource::sendM16(int32_t sessionID) {
711    AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
712    AppendCommonResponse(&request, mNextCSeq);
713
714    CHECK_EQ(sessionID, mClientSessionID);
715    request.append(
716            StringPrintf("Session: %d\r\n", mClientInfo.mPlaybackSessionID));
717    request.append("\r\n");  // Empty body
718
719    status_t err =
720        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
721
722    if (err != OK) {
723        return err;
724    }
725
726    registerResponseHandler(
727            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM16Response);
728
729    ++mNextCSeq;
730
731    return OK;
732}
733
734status_t WifiDisplaySource::onReceiveM1Response(
735        int32_t sessionID, const sp<ParsedMessage> &msg) {
736    int32_t statusCode;
737    if (!msg->getStatusCode(&statusCode)) {
738        return ERROR_MALFORMED;
739    }
740
741    if (statusCode != 200) {
742        return ERROR_UNSUPPORTED;
743    }
744
745    return OK;
746}
747
748// sink_audio_list := ("LPCM"|"AAC"|"AC3" HEXDIGIT*8 HEXDIGIT*2)
749//                       (", " sink_audio_list)*
750static void GetAudioModes(const char *s, const char *prefix, uint32_t *modes) {
751    *modes = 0;
752
753    size_t prefixLen = strlen(prefix);
754
755    while (*s != '0') {
756        if (!strncmp(s, prefix, prefixLen) && s[prefixLen] == ' ') {
757            unsigned latency;
758            if (sscanf(&s[prefixLen + 1], "%08x %02x", modes, &latency) != 2) {
759                *modes = 0;
760            }
761
762            return;
763        }
764
765        char *commaPos = strchr(s, ',');
766        if (commaPos != NULL) {
767            s = commaPos + 1;
768
769            while (isspace(*s)) {
770                ++s;
771            }
772        } else {
773            break;
774        }
775    }
776}
777
778status_t WifiDisplaySource::onReceiveM3Response(
779        int32_t sessionID, const sp<ParsedMessage> &msg) {
780    int32_t statusCode;
781    if (!msg->getStatusCode(&statusCode)) {
782        return ERROR_MALFORMED;
783    }
784
785    if (statusCode != 200) {
786        return ERROR_UNSUPPORTED;
787    }
788
789    sp<Parameters> params =
790        Parameters::Parse(msg->getContent(), strlen(msg->getContent()));
791
792    if (params == NULL) {
793        return ERROR_MALFORMED;
794    }
795
796    AString value;
797    if (!params->findParameter("wfd_client_rtp_ports", &value)) {
798        ALOGE("Sink doesn't report its choice of wfd_client_rtp_ports.");
799        return ERROR_MALFORMED;
800    }
801
802    unsigned port0 = 0, port1 = 0;
803    if (sscanf(value.c_str(),
804               "RTP/AVP/UDP;unicast %u %u mode=play",
805               &port0,
806               &port1) == 2
807        || sscanf(value.c_str(),
808               "RTP/AVP/TCP;unicast %u %u mode=play",
809               &port0,
810               &port1) == 2) {
811            if (port0 == 0 || port0 > 65535 || port1 != 0) {
812                ALOGE("Sink chose its wfd_client_rtp_ports poorly (%s)",
813                      value.c_str());
814
815                return ERROR_MALFORMED;
816            }
817    } else if (strcmp(value.c_str(), "RTP/AVP/TCP;interleaved mode=play")) {
818        ALOGE("Unsupported value for wfd_client_rtp_ports (%s)",
819              value.c_str());
820
821        return ERROR_UNSUPPORTED;
822    }
823
824    mWfdClientRtpPorts = value;
825    mChosenRTPPort = port0;
826
827    if (!params->findParameter("wfd_video_formats", &value)) {
828        ALOGE("Sink doesn't report its choice of wfd_video_formats.");
829        return ERROR_MALFORMED;
830    }
831
832    mSinkSupportsVideo = false;
833
834    if  (!(value == "none")) {
835        mSinkSupportsVideo = true;
836        if (!mSupportedSinkVideoFormats.parseFormatSpec(value.c_str())) {
837            ALOGE("Failed to parse sink provided wfd_video_formats (%s)",
838                  value.c_str());
839
840            return ERROR_MALFORMED;
841        }
842
843        if (!VideoFormats::PickBestFormat(
844                    mSupportedSinkVideoFormats,
845                    mSupportedSourceVideoFormats,
846                    &mChosenVideoResolutionType,
847                    &mChosenVideoResolutionIndex)) {
848            ALOGE("Sink and source share no commonly supported video "
849                  "formats.");
850
851            return ERROR_UNSUPPORTED;
852        }
853
854        size_t width, height, framesPerSecond;
855        bool interlaced;
856        CHECK(VideoFormats::GetConfiguration(
857                    mChosenVideoResolutionType,
858                    mChosenVideoResolutionIndex,
859                    &width,
860                    &height,
861                    &framesPerSecond,
862                    &interlaced));
863
864        ALOGI("Picked video resolution %u x %u %c%u",
865              width, height, interlaced ? 'i' : 'p', framesPerSecond);
866    } else {
867        ALOGI("Sink doesn't support video at all.");
868    }
869
870    if (!params->findParameter("wfd_audio_codecs", &value)) {
871        ALOGE("Sink doesn't report its choice of wfd_audio_codecs.");
872        return ERROR_MALFORMED;
873    }
874
875    mSinkSupportsAudio = false;
876
877    if  (!(value == "none")) {
878        mSinkSupportsAudio = true;
879
880        uint32_t modes;
881        GetAudioModes(value.c_str(), "AAC", &modes);
882
883        bool supportsAAC = (modes & 1) != 0;  // AAC 2ch 48kHz
884
885        GetAudioModes(value.c_str(), "LPCM", &modes);
886
887        bool supportsPCM = (modes & 2) != 0;  // LPCM 2ch 48kHz
888
889        char val[PROPERTY_VALUE_MAX];
890        if (supportsPCM
891                && property_get("media.wfd.use-pcm-audio", val, NULL)
892                && (!strcasecmp("true", val) || !strcmp("1", val))) {
893            ALOGI("Using PCM audio.");
894            mUsingPCMAudio = true;
895        } else if (supportsAAC) {
896            ALOGI("Using AAC audio.");
897            mUsingPCMAudio = false;
898        } else if (supportsPCM) {
899            ALOGI("Using PCM audio.");
900            mUsingPCMAudio = true;
901        } else {
902            ALOGI("Sink doesn't support an audio format we do.");
903            return ERROR_UNSUPPORTED;
904        }
905    } else {
906        ALOGI("Sink doesn't support audio at all.");
907    }
908
909    if (!mSinkSupportsVideo && !mSinkSupportsAudio) {
910        ALOGE("Sink supports neither video nor audio...");
911        return ERROR_UNSUPPORTED;
912    }
913
914    mUsingHDCP = false;
915    if (!params->findParameter("wfd_content_protection", &value)) {
916        ALOGI("Sink doesn't appear to support content protection.");
917    } else if (value == "none") {
918        ALOGI("Sink does not support content protection.");
919    } else {
920        mUsingHDCP = true;
921
922        bool isHDCP2_0 = false;
923        if (value.startsWith("HDCP2.0 ")) {
924            isHDCP2_0 = true;
925        } else if (!value.startsWith("HDCP2.1 ")) {
926            ALOGE("malformed wfd_content_protection: '%s'", value.c_str());
927
928            return ERROR_MALFORMED;
929        }
930
931        int32_t hdcpPort;
932        if (!ParsedMessage::GetInt32Attribute(
933                    value.c_str() + 8, "port", &hdcpPort)
934                || hdcpPort < 1 || hdcpPort > 65535) {
935            return ERROR_MALFORMED;
936        }
937
938        mIsHDCP2_0 = isHDCP2_0;
939        mHDCPPort = hdcpPort;
940
941        status_t err = makeHDCP();
942        if (err != OK) {
943            ALOGE("Unable to instantiate HDCP component. "
944                  "Not using HDCP after all.");
945
946            mUsingHDCP = false;
947        }
948    }
949
950    return sendM4(sessionID);
951}
952
953status_t WifiDisplaySource::onReceiveM4Response(
954        int32_t sessionID, const sp<ParsedMessage> &msg) {
955    int32_t statusCode;
956    if (!msg->getStatusCode(&statusCode)) {
957        return ERROR_MALFORMED;
958    }
959
960    if (statusCode != 200) {
961        return ERROR_UNSUPPORTED;
962    }
963
964    if (mUsingHDCP && !mHDCPInitializationComplete) {
965        ALOGI("Deferring SETUP trigger until HDCP initialization completes.");
966
967        mSetupTriggerDeferred = true;
968        return OK;
969    }
970
971    return sendTrigger(sessionID, TRIGGER_SETUP);
972}
973
974status_t WifiDisplaySource::onReceiveM5Response(
975        int32_t sessionID, const sp<ParsedMessage> &msg) {
976    int32_t statusCode;
977    if (!msg->getStatusCode(&statusCode)) {
978        return ERROR_MALFORMED;
979    }
980
981    if (statusCode != 200) {
982        return ERROR_UNSUPPORTED;
983    }
984
985    return OK;
986}
987
988status_t WifiDisplaySource::onReceiveM16Response(
989        int32_t sessionID, const sp<ParsedMessage> &msg) {
990    // If only the response was required to include a "Session:" header...
991
992    CHECK_EQ(sessionID, mClientSessionID);
993
994    if (mClientInfo.mPlaybackSession != NULL) {
995        mClientInfo.mPlaybackSession->updateLiveness();
996
997        scheduleKeepAlive(sessionID);
998    }
999
1000    return OK;
1001}
1002
1003void WifiDisplaySource::scheduleReaper() {
1004    if (mReaperPending) {
1005        return;
1006    }
1007
1008    mReaperPending = true;
1009    (new AMessage(kWhatReapDeadClients, id()))->post(kReaperIntervalUs);
1010}
1011
1012void WifiDisplaySource::scheduleKeepAlive(int32_t sessionID) {
1013    // We need to send updates at least 5 secs before the timeout is set to
1014    // expire, make sure the timeout is greater than 5 secs to begin with.
1015    CHECK_GT(kPlaybackSessionTimeoutUs, 5000000ll);
1016
1017    sp<AMessage> msg = new AMessage(kWhatKeepAlive, id());
1018    msg->setInt32("sessionID", sessionID);
1019    msg->post(kPlaybackSessionTimeoutUs - 5000000ll);
1020}
1021
1022status_t WifiDisplaySource::onReceiveClientData(const sp<AMessage> &msg) {
1023    int32_t sessionID;
1024    CHECK(msg->findInt32("sessionID", &sessionID));
1025
1026    sp<RefBase> obj;
1027    CHECK(msg->findObject("data", &obj));
1028
1029    sp<ParsedMessage> data =
1030        static_cast<ParsedMessage *>(obj.get());
1031
1032    ALOGV("session %d received '%s'",
1033          sessionID, data->debugString().c_str());
1034
1035    AString method;
1036    AString uri;
1037    data->getRequestField(0, &method);
1038
1039    int32_t cseq;
1040    if (!data->findInt32("cseq", &cseq)) {
1041        sendErrorResponse(sessionID, "400 Bad Request", -1 /* cseq */);
1042        return ERROR_MALFORMED;
1043    }
1044
1045    if (method.startsWith("RTSP/")) {
1046        // This is a response.
1047
1048        ResponseID id;
1049        id.mSessionID = sessionID;
1050        id.mCSeq = cseq;
1051
1052        ssize_t index = mResponseHandlers.indexOfKey(id);
1053
1054        if (index < 0) {
1055            ALOGW("Received unsolicited server response, cseq %d", cseq);
1056            return ERROR_MALFORMED;
1057        }
1058
1059        HandleRTSPResponseFunc func = mResponseHandlers.valueAt(index);
1060        mResponseHandlers.removeItemsAt(index);
1061
1062        status_t err = (this->*func)(sessionID, data);
1063
1064        if (err != OK) {
1065            ALOGW("Response handler for session %d, cseq %d returned "
1066                  "err %d (%s)",
1067                  sessionID, cseq, err, strerror(-err));
1068
1069            return err;
1070        }
1071
1072        return OK;
1073    }
1074
1075    AString version;
1076    data->getRequestField(2, &version);
1077    if (!(version == AString("RTSP/1.0"))) {
1078        sendErrorResponse(sessionID, "505 RTSP Version not supported", cseq);
1079        return ERROR_UNSUPPORTED;
1080    }
1081
1082    status_t err;
1083    if (method == "OPTIONS") {
1084        err = onOptionsRequest(sessionID, cseq, data);
1085    } else if (method == "SETUP") {
1086        err = onSetupRequest(sessionID, cseq, data);
1087    } else if (method == "PLAY") {
1088        err = onPlayRequest(sessionID, cseq, data);
1089    } else if (method == "PAUSE") {
1090        err = onPauseRequest(sessionID, cseq, data);
1091    } else if (method == "TEARDOWN") {
1092        err = onTeardownRequest(sessionID, cseq, data);
1093    } else if (method == "GET_PARAMETER") {
1094        err = onGetParameterRequest(sessionID, cseq, data);
1095    } else if (method == "SET_PARAMETER") {
1096        err = onSetParameterRequest(sessionID, cseq, data);
1097    } else {
1098        sendErrorResponse(sessionID, "405 Method Not Allowed", cseq);
1099
1100        err = ERROR_UNSUPPORTED;
1101    }
1102
1103    return err;
1104}
1105
1106status_t WifiDisplaySource::onOptionsRequest(
1107        int32_t sessionID,
1108        int32_t cseq,
1109        const sp<ParsedMessage> &data) {
1110    int32_t playbackSessionID;
1111    sp<PlaybackSession> playbackSession =
1112        findPlaybackSession(data, &playbackSessionID);
1113
1114    if (playbackSession != NULL) {
1115        playbackSession->updateLiveness();
1116    }
1117
1118    AString response = "RTSP/1.0 200 OK\r\n";
1119    AppendCommonResponse(&response, cseq);
1120
1121    response.append(
1122            "Public: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, "
1123            "GET_PARAMETER, SET_PARAMETER\r\n");
1124
1125    response.append("\r\n");
1126
1127    status_t err = mNetSession->sendRequest(sessionID, response.c_str());
1128
1129    if (err == OK) {
1130        err = sendM3(sessionID);
1131    }
1132
1133    return err;
1134}
1135
1136status_t WifiDisplaySource::onSetupRequest(
1137        int32_t sessionID,
1138        int32_t cseq,
1139        const sp<ParsedMessage> &data) {
1140    CHECK_EQ(sessionID, mClientSessionID);
1141    if (mClientInfo.mPlaybackSessionID != -1) {
1142        // We only support a single playback session per client.
1143        // This is due to the reversed keep-alive design in the wfd specs...
1144        sendErrorResponse(sessionID, "400 Bad Request", cseq);
1145        return ERROR_MALFORMED;
1146    }
1147
1148    AString transport;
1149    if (!data->findString("transport", &transport)) {
1150        sendErrorResponse(sessionID, "400 Bad Request", cseq);
1151        return ERROR_MALFORMED;
1152    }
1153
1154    RTPSender::TransportMode rtpMode = RTPSender::TRANSPORT_UDP;
1155
1156    int clientRtp, clientRtcp;
1157    if (transport.startsWith("RTP/AVP/TCP;")) {
1158        AString interleaved;
1159        if (ParsedMessage::GetAttribute(
1160                    transport.c_str(), "interleaved", &interleaved)
1161                && sscanf(interleaved.c_str(), "%d-%d",
1162                          &clientRtp, &clientRtcp) == 2) {
1163            rtpMode = RTPSender::TRANSPORT_TCP_INTERLEAVED;
1164        } else {
1165            bool badRequest = false;
1166
1167            AString clientPort;
1168            if (!ParsedMessage::GetAttribute(
1169                        transport.c_str(), "client_port", &clientPort)) {
1170                badRequest = true;
1171            } else if (sscanf(clientPort.c_str(), "%d-%d",
1172                              &clientRtp, &clientRtcp) == 2) {
1173            } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) {
1174                // No RTCP.
1175                clientRtcp = -1;
1176            } else {
1177                badRequest = true;
1178            }
1179
1180            if (badRequest) {
1181                sendErrorResponse(sessionID, "400 Bad Request", cseq);
1182                return ERROR_MALFORMED;
1183            }
1184
1185            rtpMode = RTPSender::TRANSPORT_TCP;
1186        }
1187    } else if (transport.startsWith("RTP/AVP;unicast;")
1188            || transport.startsWith("RTP/AVP/UDP;unicast;")) {
1189        bool badRequest = false;
1190
1191        AString clientPort;
1192        if (!ParsedMessage::GetAttribute(
1193                    transport.c_str(), "client_port", &clientPort)) {
1194            badRequest = true;
1195        } else if (sscanf(clientPort.c_str(), "%d-%d",
1196                          &clientRtp, &clientRtcp) == 2) {
1197        } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) {
1198            // No RTCP.
1199            clientRtcp = -1;
1200        } else {
1201            badRequest = true;
1202        }
1203
1204        if (badRequest) {
1205            sendErrorResponse(sessionID, "400 Bad Request", cseq);
1206            return ERROR_MALFORMED;
1207        }
1208#if 1
1209    // The older LG dongles doesn't specify client_port=xxx apparently.
1210    } else if (transport == "RTP/AVP/UDP;unicast") {
1211        clientRtp = 19000;
1212        clientRtcp = -1;
1213#endif
1214    } else {
1215        sendErrorResponse(sessionID, "461 Unsupported Transport", cseq);
1216        return ERROR_UNSUPPORTED;
1217    }
1218
1219    int32_t playbackSessionID = makeUniquePlaybackSessionID();
1220
1221    sp<AMessage> notify = new AMessage(kWhatPlaybackSessionNotify, id());
1222    notify->setInt32("playbackSessionID", playbackSessionID);
1223    notify->setInt32("sessionID", sessionID);
1224
1225    sp<PlaybackSession> playbackSession =
1226        new PlaybackSession(
1227                mNetSession, notify, mInterfaceAddr, mHDCP, mMediaPath.c_str());
1228
1229    looper()->registerHandler(playbackSession);
1230
1231    AString uri;
1232    data->getRequestField(1, &uri);
1233
1234    if (strncasecmp("rtsp://", uri.c_str(), 7)) {
1235        sendErrorResponse(sessionID, "400 Bad Request", cseq);
1236        return ERROR_MALFORMED;
1237    }
1238
1239    if (!(uri.startsWith("rtsp://") && uri.endsWith("/wfd1.0/streamid=0"))) {
1240        sendErrorResponse(sessionID, "404 Not found", cseq);
1241        return ERROR_MALFORMED;
1242    }
1243
1244    RTPSender::TransportMode rtcpMode = RTPSender::TRANSPORT_UDP;
1245    if (clientRtcp < 0) {
1246        rtcpMode = RTPSender::TRANSPORT_NONE;
1247    }
1248
1249    status_t err = playbackSession->init(
1250            mClientInfo.mRemoteIP.c_str(),
1251            clientRtp,
1252            rtpMode,
1253            clientRtcp,
1254            rtcpMode,
1255            mSinkSupportsAudio,
1256            mUsingPCMAudio,
1257            mSinkSupportsVideo,
1258            mChosenVideoResolutionType,
1259            mChosenVideoResolutionIndex);
1260
1261    if (err != OK) {
1262        looper()->unregisterHandler(playbackSession->id());
1263        playbackSession.clear();
1264    }
1265
1266    switch (err) {
1267        case OK:
1268            break;
1269        case -ENOENT:
1270            sendErrorResponse(sessionID, "404 Not Found", cseq);
1271            return err;
1272        default:
1273            sendErrorResponse(sessionID, "403 Forbidden", cseq);
1274            return err;
1275    }
1276
1277    mClientInfo.mPlaybackSessionID = playbackSessionID;
1278    mClientInfo.mPlaybackSession = playbackSession;
1279
1280    AString response = "RTSP/1.0 200 OK\r\n";
1281    AppendCommonResponse(&response, cseq, playbackSessionID);
1282
1283    if (rtpMode == RTPSender::TRANSPORT_TCP_INTERLEAVED) {
1284        response.append(
1285                StringPrintf(
1286                    "Transport: RTP/AVP/TCP;interleaved=%d-%d;",
1287                    clientRtp, clientRtcp));
1288    } else {
1289        int32_t serverRtp = playbackSession->getRTPPort();
1290
1291        AString transportString = "UDP";
1292        if (rtpMode == RTPSender::TRANSPORT_TCP) {
1293            transportString = "TCP";
1294        }
1295
1296        if (clientRtcp >= 0) {
1297            response.append(
1298                    StringPrintf(
1299                        "Transport: RTP/AVP/%s;unicast;client_port=%d-%d;"
1300                        "server_port=%d-%d\r\n",
1301                        transportString.c_str(),
1302                        clientRtp, clientRtcp, serverRtp, serverRtp + 1));
1303        } else {
1304            response.append(
1305                    StringPrintf(
1306                        "Transport: RTP/AVP/%s;unicast;client_port=%d;"
1307                        "server_port=%d\r\n",
1308                        transportString.c_str(),
1309                        clientRtp, serverRtp));
1310        }
1311    }
1312
1313    response.append("\r\n");
1314
1315    err = mNetSession->sendRequest(sessionID, response.c_str());
1316
1317    if (err != OK) {
1318        return err;
1319    }
1320
1321    mState = AWAITING_CLIENT_PLAY;
1322
1323    scheduleReaper();
1324    scheduleKeepAlive(sessionID);
1325
1326    return OK;
1327}
1328
1329status_t WifiDisplaySource::onPlayRequest(
1330        int32_t sessionID,
1331        int32_t cseq,
1332        const sp<ParsedMessage> &data) {
1333    int32_t playbackSessionID;
1334    sp<PlaybackSession> playbackSession =
1335        findPlaybackSession(data, &playbackSessionID);
1336
1337    if (playbackSession == NULL) {
1338        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1339        return ERROR_MALFORMED;
1340    }
1341
1342    if (mState != AWAITING_CLIENT_PLAY) {
1343        ALOGW("Received PLAY request but we're in state %d", mState);
1344
1345        sendErrorResponse(
1346                sessionID, "455 Method Not Valid in This State", cseq);
1347
1348        return INVALID_OPERATION;
1349    }
1350
1351    ALOGI("Received PLAY request.");
1352    if (mPlaybackSessionEstablished) {
1353        finishPlay();
1354    } else {
1355        ALOGI("deferring PLAY request until session established.");
1356    }
1357
1358    AString response = "RTSP/1.0 200 OK\r\n";
1359    AppendCommonResponse(&response, cseq, playbackSessionID);
1360    response.append("Range: npt=now-\r\n");
1361    response.append("\r\n");
1362
1363    status_t err = mNetSession->sendRequest(sessionID, response.c_str());
1364
1365    if (err != OK) {
1366        return err;
1367    }
1368
1369    if (mState == PAUSED_TO_PLAYING) {
1370        mState = PLAYING;
1371        return OK;
1372    }
1373
1374    CHECK_EQ(mState, AWAITING_CLIENT_PLAY);
1375    mState = ABOUT_TO_PLAY;
1376
1377    return OK;
1378}
1379
1380void WifiDisplaySource::finishPlay() {
1381    const sp<PlaybackSession> &playbackSession =
1382        mClientInfo.mPlaybackSession;
1383
1384    status_t err = playbackSession->play();
1385    CHECK_EQ(err, (status_t)OK);
1386}
1387
1388status_t WifiDisplaySource::onPauseRequest(
1389        int32_t sessionID,
1390        int32_t cseq,
1391        const sp<ParsedMessage> &data) {
1392    int32_t playbackSessionID;
1393    sp<PlaybackSession> playbackSession =
1394        findPlaybackSession(data, &playbackSessionID);
1395
1396    if (playbackSession == NULL) {
1397        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1398        return ERROR_MALFORMED;
1399    }
1400
1401    ALOGI("Received PAUSE request.");
1402
1403    if (mState != PLAYING_TO_PAUSED) {
1404        return INVALID_OPERATION;
1405    }
1406
1407    status_t err = playbackSession->pause();
1408    CHECK_EQ(err, (status_t)OK);
1409
1410    AString response = "RTSP/1.0 200 OK\r\n";
1411    AppendCommonResponse(&response, cseq, playbackSessionID);
1412    response.append("\r\n");
1413
1414    err = mNetSession->sendRequest(sessionID, response.c_str());
1415
1416    if (err != OK) {
1417        return err;
1418    }
1419
1420    mState = PAUSED;
1421
1422    return err;
1423}
1424
1425status_t WifiDisplaySource::onTeardownRequest(
1426        int32_t sessionID,
1427        int32_t cseq,
1428        const sp<ParsedMessage> &data) {
1429    ALOGI("Received TEARDOWN request.");
1430
1431    int32_t playbackSessionID;
1432    sp<PlaybackSession> playbackSession =
1433        findPlaybackSession(data, &playbackSessionID);
1434
1435    if (playbackSession == NULL) {
1436        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1437        return ERROR_MALFORMED;
1438    }
1439
1440    AString response = "RTSP/1.0 200 OK\r\n";
1441    AppendCommonResponse(&response, cseq, playbackSessionID);
1442    response.append("Connection: close\r\n");
1443    response.append("\r\n");
1444
1445    mNetSession->sendRequest(sessionID, response.c_str());
1446
1447    if (mState == AWAITING_CLIENT_TEARDOWN) {
1448        CHECK_NE(mStopReplyID, 0);
1449        finishStop();
1450    } else {
1451        mClient->onDisplayError(IRemoteDisplayClient::kDisplayErrorUnknown);
1452    }
1453
1454    return OK;
1455}
1456
1457void WifiDisplaySource::finishStop() {
1458    ALOGV("finishStop");
1459
1460    mState = STOPPING;
1461
1462    disconnectClientAsync();
1463}
1464
1465void WifiDisplaySource::finishStopAfterDisconnectingClient() {
1466    ALOGV("finishStopAfterDisconnectingClient");
1467
1468    if (mHDCP != NULL) {
1469        ALOGI("Initiating HDCP shutdown.");
1470        mHDCP->shutdownAsync();
1471        return;
1472    }
1473
1474    finishStop2();
1475}
1476
1477void WifiDisplaySource::finishStop2() {
1478    ALOGV("finishStop2");
1479
1480    if (mHDCP != NULL) {
1481        mHDCP->setObserver(NULL);
1482        mHDCPObserver.clear();
1483        mHDCP.clear();
1484    }
1485
1486    if (mSessionID != 0) {
1487        mNetSession->destroySession(mSessionID);
1488        mSessionID = 0;
1489    }
1490
1491    ALOGI("We're stopped.");
1492    mState = STOPPED;
1493
1494    status_t err = OK;
1495
1496    sp<AMessage> response = new AMessage;
1497    response->setInt32("err", err);
1498    response->postReply(mStopReplyID);
1499}
1500
1501status_t WifiDisplaySource::onGetParameterRequest(
1502        int32_t sessionID,
1503        int32_t cseq,
1504        const sp<ParsedMessage> &data) {
1505    int32_t playbackSessionID;
1506    sp<PlaybackSession> playbackSession =
1507        findPlaybackSession(data, &playbackSessionID);
1508
1509    if (playbackSession == NULL) {
1510        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1511        return ERROR_MALFORMED;
1512    }
1513
1514    playbackSession->updateLiveness();
1515
1516    AString response = "RTSP/1.0 200 OK\r\n";
1517    AppendCommonResponse(&response, cseq, playbackSessionID);
1518    response.append("\r\n");
1519
1520    status_t err = mNetSession->sendRequest(sessionID, response.c_str());
1521    return err;
1522}
1523
1524status_t WifiDisplaySource::onSetParameterRequest(
1525        int32_t sessionID,
1526        int32_t cseq,
1527        const sp<ParsedMessage> &data) {
1528    int32_t playbackSessionID;
1529    sp<PlaybackSession> playbackSession =
1530        findPlaybackSession(data, &playbackSessionID);
1531
1532    if (playbackSession == NULL) {
1533        sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1534        return ERROR_MALFORMED;
1535    }
1536
1537    if (strstr(data->getContent(), "wfd_idr_request\r\n")) {
1538        playbackSession->requestIDRFrame();
1539    }
1540
1541    playbackSession->updateLiveness();
1542
1543    AString response = "RTSP/1.0 200 OK\r\n";
1544    AppendCommonResponse(&response, cseq, playbackSessionID);
1545    response.append("\r\n");
1546
1547    status_t err = mNetSession->sendRequest(sessionID, response.c_str());
1548    return err;
1549}
1550
1551// static
1552void WifiDisplaySource::AppendCommonResponse(
1553        AString *response, int32_t cseq, int32_t playbackSessionID) {
1554    time_t now = time(NULL);
1555    struct tm *now2 = gmtime(&now);
1556    char buf[128];
1557    strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2);
1558
1559    response->append("Date: ");
1560    response->append(buf);
1561    response->append("\r\n");
1562
1563    response->append(StringPrintf("Server: %s\r\n", sUserAgent.c_str()));
1564
1565    if (cseq >= 0) {
1566        response->append(StringPrintf("CSeq: %d\r\n", cseq));
1567    }
1568
1569    if (playbackSessionID >= 0ll) {
1570        response->append(
1571                StringPrintf(
1572                    "Session: %d;timeout=%lld\r\n",
1573                    playbackSessionID, kPlaybackSessionTimeoutSecs));
1574    }
1575}
1576
1577void WifiDisplaySource::sendErrorResponse(
1578        int32_t sessionID,
1579        const char *errorDetail,
1580        int32_t cseq) {
1581    AString response;
1582    response.append("RTSP/1.0 ");
1583    response.append(errorDetail);
1584    response.append("\r\n");
1585
1586    AppendCommonResponse(&response, cseq);
1587
1588    response.append("\r\n");
1589
1590    mNetSession->sendRequest(sessionID, response.c_str());
1591}
1592
1593int32_t WifiDisplaySource::makeUniquePlaybackSessionID() const {
1594    return rand();
1595}
1596
1597sp<WifiDisplaySource::PlaybackSession> WifiDisplaySource::findPlaybackSession(
1598        const sp<ParsedMessage> &data, int32_t *playbackSessionID) const {
1599    if (!data->findInt32("session", playbackSessionID)) {
1600        // XXX the older dongles do not always include a "Session:" header.
1601        *playbackSessionID = mClientInfo.mPlaybackSessionID;
1602        return mClientInfo.mPlaybackSession;
1603    }
1604
1605    if (*playbackSessionID != mClientInfo.mPlaybackSessionID) {
1606        return NULL;
1607    }
1608
1609    return mClientInfo.mPlaybackSession;
1610}
1611
1612void WifiDisplaySource::disconnectClientAsync() {
1613    ALOGV("disconnectClient");
1614
1615    if (mClientInfo.mPlaybackSession == NULL) {
1616        disconnectClient2();
1617        return;
1618    }
1619
1620    if (mClientInfo.mPlaybackSession != NULL) {
1621        ALOGV("Destroying PlaybackSession");
1622        mClientInfo.mPlaybackSession->destroyAsync();
1623    }
1624}
1625
1626void WifiDisplaySource::disconnectClient2() {
1627    ALOGV("disconnectClient2");
1628
1629    if (mClientInfo.mPlaybackSession != NULL) {
1630        looper()->unregisterHandler(mClientInfo.mPlaybackSession->id());
1631        mClientInfo.mPlaybackSession.clear();
1632    }
1633
1634    if (mClientSessionID != 0) {
1635        mNetSession->destroySession(mClientSessionID);
1636        mClientSessionID = 0;
1637    }
1638
1639    mClient->onDisplayDisconnected();
1640
1641    finishStopAfterDisconnectingClient();
1642}
1643
1644struct WifiDisplaySource::HDCPObserver : public BnHDCPObserver {
1645    HDCPObserver(const sp<AMessage> &notify);
1646
1647    virtual void notify(
1648            int msg, int ext1, int ext2, const Parcel *obj);
1649
1650private:
1651    sp<AMessage> mNotify;
1652
1653    DISALLOW_EVIL_CONSTRUCTORS(HDCPObserver);
1654};
1655
1656WifiDisplaySource::HDCPObserver::HDCPObserver(
1657        const sp<AMessage> &notify)
1658    : mNotify(notify) {
1659}
1660
1661void WifiDisplaySource::HDCPObserver::notify(
1662        int msg, int ext1, int ext2, const Parcel *obj) {
1663    sp<AMessage> notify = mNotify->dup();
1664    notify->setInt32("msg", msg);
1665    notify->setInt32("ext1", ext1);
1666    notify->setInt32("ext2", ext2);
1667    notify->post();
1668}
1669
1670status_t WifiDisplaySource::makeHDCP() {
1671    sp<IServiceManager> sm = defaultServiceManager();
1672    sp<IBinder> binder = sm->getService(String16("media.player"));
1673
1674    sp<IMediaPlayerService> service =
1675        interface_cast<IMediaPlayerService>(binder);
1676
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