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