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