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 String16 &opPackageName,
54        const sp<ANetworkSession> &netSession,
55        const sp<IRemoteDisplayClient> &client,
56        const char *path)
57    : mOpPackageName(opPackageName),
58      mState(INITIALIZED),
59      mNetSession(netSession),
60      mClient(client),
61      mSessionID(0),
62      mStopReplyID(NULL),
63      mChosenRTPPort(-1),
64      mUsingPCMAudio(false),
65      mClientSessionID(0),
66      mReaperPending(false),
67      mNextCSeq(1),
68      mUsingHDCP(false),
69      mIsHDCP2_0(false),
70      mHDCPPort(0),
71      mHDCPInitializationComplete(false),
72      mSetupTriggerDeferred(false),
73      mPlaybackSessionEstablished(false) {
74    if (path != NULL) {
75        mMediaPath.setTo(path);
76    }
77
78    mSupportedSourceVideoFormats.disableAll();
79
80    mSupportedSourceVideoFormats.setNativeResolution(
81            VideoFormats::RESOLUTION_CEA, 5);  // 1280x720 p30
82
83    // Enable all resolutions up to 1280x720p30
84    mSupportedSourceVideoFormats.enableResolutionUpto(
85            VideoFormats::RESOLUTION_CEA, 5,
86            VideoFormats::PROFILE_CHP,  // Constrained High Profile
87            VideoFormats::LEVEL_32);    // Level 3.2
88}
89
90WifiDisplaySource::~WifiDisplaySource() {
91}
92
93static status_t PostAndAwaitResponse(
94        const sp<AMessage> &msg, sp<AMessage> *response) {
95    status_t err = msg->postAndAwaitResponse(response);
96
97    if (err != OK) {
98        return err;
99    }
100
101    if (response == NULL || !(*response)->findInt32("err", &err)) {
102        err = OK;
103    }
104
105    return err;
106}
107
108status_t WifiDisplaySource::start(const char *iface) {
109    CHECK_EQ(mState, INITIALIZED);
110
111    sp<AMessage> msg = new AMessage(kWhatStart, this);
112    msg->setString("iface", iface);
113
114    sp<AMessage> response;
115    return PostAndAwaitResponse(msg, &response);
116}
117
118status_t WifiDisplaySource::stop() {
119    sp<AMessage> msg = new AMessage(kWhatStop, this);
120
121    sp<AMessage> response;
122    return PostAndAwaitResponse(msg, &response);
123}
124
125status_t WifiDisplaySource::pause() {
126    sp<AMessage> msg = new AMessage(kWhatPause, this);
127
128    sp<AMessage> response;
129    return PostAndAwaitResponse(msg, &response);
130}
131
132status_t WifiDisplaySource::resume() {
133    sp<AMessage> msg = new AMessage(kWhatResume, this);
134
135    sp<AMessage> response;
136    return PostAndAwaitResponse(msg, &response);
137}
138
139void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
140    switch (msg->what()) {
141        case kWhatStart:
142        {
143            sp<AReplyToken> replyID;
144            CHECK(msg->senderAwaitsResponse(&replyID));
145
146            AString iface;
147            CHECK(msg->findString("iface", &iface));
148
149            status_t err = OK;
150
151            ssize_t colonPos = iface.find(":");
152
153            unsigned long port;
154
155            if (colonPos >= 0) {
156                const char *s = iface.c_str() + colonPos + 1;
157
158                char *end;
159                port = strtoul(s, &end, 10);
160
161                if (end == s || *end != '\0' || port > 65535) {
162                    err = -EINVAL;
163                } else {
164                    iface.erase(colonPos, iface.size() - colonPos);
165                }
166            } else {
167                port = kWifiDisplayDefaultPort;
168            }
169
170            if (err == OK) {
171                if (inet_aton(iface.c_str(), &mInterfaceAddr) != 0) {
172                    sp<AMessage> notify = new AMessage(kWhatRTSPNotify, this);
173
174                    err = mNetSession->createRTSPServer(
175                            mInterfaceAddr, port, notify, &mSessionID);
176                } else {
177                    err = -EINVAL;
178                }
179            }
180
181            mState = AWAITING_CLIENT_CONNECTION;
182
183            sp<AMessage> response = new AMessage;
184            response->setInt32("err", err);
185            response->postReply(replyID);
186            break;
187        }
188
189        case kWhatRTSPNotify:
190        {
191            int32_t reason;
192            CHECK(msg->findInt32("reason", &reason));
193
194            switch (reason) {
195                case ANetworkSession::kWhatError:
196                {
197                    int32_t sessionID;
198                    CHECK(msg->findInt32("sessionID", &sessionID));
199
200                    int32_t err;
201                    CHECK(msg->findInt32("err", &err));
202
203                    AString detail;
204                    CHECK(msg->findString("detail", &detail));
205
206                    ALOGE("An error occurred in session %d (%d, '%s/%s').",
207                          sessionID,
208                          err,
209                          detail.c_str(),
210                          strerror(-err));
211
212                    mNetSession->destroySession(sessionID);
213
214                    if (sessionID == mClientSessionID) {
215                        mClientSessionID = 0;
216
217                        mClient->onDisplayError(
218                                IRemoteDisplayClient::kDisplayErrorUnknown);
219                    }
220                    break;
221                }
222
223                case ANetworkSession::kWhatClientConnected:
224                {
225                    int32_t sessionID;
226                    CHECK(msg->findInt32("sessionID", &sessionID));
227
228                    if (mClientSessionID > 0) {
229                        ALOGW("A client tried to connect, but we already "
230                              "have one.");
231
232                        mNetSession->destroySession(sessionID);
233                        break;
234                    }
235
236                    CHECK_EQ(mState, AWAITING_CLIENT_CONNECTION);
237
238                    CHECK(msg->findString("client-ip", &mClientInfo.mRemoteIP));
239                    CHECK(msg->findString("server-ip", &mClientInfo.mLocalIP));
240
241                    if (mClientInfo.mRemoteIP == mClientInfo.mLocalIP) {
242                        // Disallow connections from the local interface
243                        // for security reasons.
244                        mNetSession->destroySession(sessionID);
245                        break;
246                    }
247
248                    CHECK(msg->findInt32(
249                                "server-port", &mClientInfo.mLocalPort));
250                    mClientInfo.mPlaybackSessionID = -1;
251
252                    mClientSessionID = sessionID;
253
254                    ALOGI("We now have a client (%d) connected.", sessionID);
255
256                    mState = AWAITING_CLIENT_SETUP;
257
258                    status_t err = sendM1(sessionID);
259                    CHECK_EQ(err, (status_t)OK);
260                    break;
261                }
262
263                case ANetworkSession::kWhatData:
264                {
265                    status_t err = onReceiveClientData(msg);
266
267                    if (err != OK) {
268                        mClient->onDisplayError(
269                                IRemoteDisplayClient::kDisplayErrorUnknown);
270                    }
271
272#if 0
273                    // testing only.
274                    char val[PROPERTY_VALUE_MAX];
275                    if (property_get("media.wfd.trigger", val, NULL)) {
276                        if (!strcasecmp(val, "pause") && mState == PLAYING) {
277                            mState = PLAYING_TO_PAUSED;
278                            sendTrigger(mClientSessionID, TRIGGER_PAUSE);
279                        } else if (!strcasecmp(val, "play")
280                                    && mState == PAUSED) {
281                            mState = PAUSED_TO_PLAYING;
282                            sendTrigger(mClientSessionID, TRIGGER_PLAY);
283                        }
284                    }
285#endif
286                    break;
287                }
288
289                case ANetworkSession::kWhatNetworkStall:
290                {
291                    break;
292                }
293
294                default:
295                    TRESPASS();
296            }
297            break;
298        }
299
300        case kWhatStop:
301        {
302            CHECK(msg->senderAwaitsResponse(&mStopReplyID));
303
304            CHECK_LT(mState, AWAITING_CLIENT_TEARDOWN);
305
306            if (mState >= AWAITING_CLIENT_PLAY) {
307                // We have a session, i.e. a previous SETUP succeeded.
308
309                status_t err = sendTrigger(
310                        mClientSessionID, TRIGGER_TEARDOWN);
311
312                if (err == OK) {
313                    mState = AWAITING_CLIENT_TEARDOWN;
314
315                    (new AMessage(kWhatTeardownTriggerTimedOut, this))->post(
316                            kTeardownTriggerTimeouSecs * 1000000ll);
317
318                    break;
319                }
320
321                // fall through.
322            }
323
324            finishStop();
325            break;
326        }
327
328        case kWhatPause:
329        {
330            sp<AReplyToken> replyID;
331            CHECK(msg->senderAwaitsResponse(&replyID));
332
333            status_t err = OK;
334
335            if (mState != PLAYING) {
336                err = INVALID_OPERATION;
337            } else {
338                mState = PLAYING_TO_PAUSED;
339                sendTrigger(mClientSessionID, TRIGGER_PAUSE);
340            }
341
342            sp<AMessage> response = new AMessage;
343            response->setInt32("err", err);
344            response->postReply(replyID);
345            break;
346        }
347
348        case kWhatResume:
349        {
350            sp<AReplyToken> replyID;
351            CHECK(msg->senderAwaitsResponse(&replyID));
352
353            status_t err = OK;
354
355            if (mState != PAUSED) {
356                err = INVALID_OPERATION;
357            } else {
358                mState = PAUSED_TO_PLAYING;
359                sendTrigger(mClientSessionID, TRIGGER_PLAY);
360            }
361
362            sp<AMessage> response = new AMessage;
363            response->setInt32("err", err);
364            response->postReply(replyID);
365            break;
366        }
367
368        case kWhatReapDeadClients:
369        {
370            mReaperPending = false;
371
372            if (mClientSessionID == 0
373                    || mClientInfo.mPlaybackSession == NULL) {
374                break;
375            }
376
377            if (mClientInfo.mPlaybackSession->getLastLifesignUs()
378                    + kPlaybackSessionTimeoutUs < ALooper::GetNowUs()) {
379                ALOGI("playback session timed out, reaping.");
380
381                mNetSession->destroySession(mClientSessionID);
382                mClientSessionID = 0;
383
384                mClient->onDisplayError(
385                        IRemoteDisplayClient::kDisplayErrorUnknown);
386            } else {
387                scheduleReaper();
388            }
389            break;
390        }
391
392        case kWhatPlaybackSessionNotify:
393        {
394            int32_t playbackSessionID;
395            CHECK(msg->findInt32("playbackSessionID", &playbackSessionID));
396
397            int32_t what;
398            CHECK(msg->findInt32("what", &what));
399
400            if (what == PlaybackSession::kWhatSessionDead) {
401                ALOGI("playback session wants to quit.");
402
403                mClient->onDisplayError(
404                        IRemoteDisplayClient::kDisplayErrorUnknown);
405            } else if (what == PlaybackSession::kWhatSessionEstablished) {
406                mPlaybackSessionEstablished = true;
407
408                if (mClient != NULL) {
409                    if (!mSinkSupportsVideo) {
410                        mClient->onDisplayConnected(
411                                NULL,  // SurfaceTexture
412                                0, // width,
413                                0, // height,
414                                mUsingHDCP
415                                    ? IRemoteDisplayClient::kDisplayFlagSecure
416                                    : 0,
417                                0);
418                    } else {
419                        size_t width, height;
420
421                        CHECK(VideoFormats::GetConfiguration(
422                                    mChosenVideoResolutionType,
423                                    mChosenVideoResolutionIndex,
424                                    &width,
425                                    &height,
426                                    NULL /* framesPerSecond */,
427                                    NULL /* interlaced */));
428
429                        mClient->onDisplayConnected(
430                                mClientInfo.mPlaybackSession
431                                    ->getSurfaceTexture(),
432                                width,
433                                height,
434                                mUsingHDCP
435                                    ? IRemoteDisplayClient::kDisplayFlagSecure
436                                    : 0,
437                                playbackSessionID);
438                    }
439                }
440
441                finishPlay();
442
443                if (mState == ABOUT_TO_PLAY) {
444                    mState = PLAYING;
445                }
446            } else if (what == PlaybackSession::kWhatSessionDestroyed) {
447                disconnectClient2();
448            } else {
449                CHECK_EQ(what, PlaybackSession::kWhatBinaryData);
450
451                int32_t channel;
452                CHECK(msg->findInt32("channel", &channel));
453
454                sp<ABuffer> data;
455                CHECK(msg->findBuffer("data", &data));
456
457                CHECK_LE(channel, 0xffu);
458                CHECK_LE(data->size(), 0xffffu);
459
460                int32_t sessionID;
461                CHECK(msg->findInt32("sessionID", &sessionID));
462
463                char header[4];
464                header[0] = '$';
465                header[1] = channel;
466                header[2] = data->size() >> 8;
467                header[3] = data->size() & 0xff;
468
469                mNetSession->sendRequest(
470                        sessionID, header, sizeof(header));
471
472                mNetSession->sendRequest(
473                        sessionID, data->data(), data->size());
474            }
475            break;
476        }
477
478        case kWhatKeepAlive:
479        {
480            int32_t sessionID;
481            CHECK(msg->findInt32("sessionID", &sessionID));
482
483            if (mClientSessionID != sessionID) {
484                // Obsolete event, client is already gone.
485                break;
486            }
487
488            sendM16(sessionID);
489            break;
490        }
491
492        case kWhatTeardownTriggerTimedOut:
493        {
494            if (mState == AWAITING_CLIENT_TEARDOWN) {
495                ALOGI("TEARDOWN trigger timed out, forcing disconnection.");
496
497                CHECK(mStopReplyID != NULL);
498                finishStop();
499                break;
500            }
501            break;
502        }
503
504        case kWhatHDCPNotify:
505        {
506            int32_t msgCode, ext1, ext2;
507            CHECK(msg->findInt32("msg", &msgCode));
508            CHECK(msg->findInt32("ext1", &ext1));
509            CHECK(msg->findInt32("ext2", &ext2));
510
511            ALOGI("Saw HDCP notification code %d, ext1 %d, ext2 %d",
512                    msgCode, ext1, ext2);
513
514            switch (msgCode) {
515                case HDCPModule::HDCP_INITIALIZATION_COMPLETE:
516                {
517                    mHDCPInitializationComplete = true;
518
519                    if (mSetupTriggerDeferred) {
520                        mSetupTriggerDeferred = false;
521
522                        sendTrigger(mClientSessionID, TRIGGER_SETUP);
523                    }
524                    break;
525                }
526
527                case HDCPModule::HDCP_SHUTDOWN_COMPLETE:
528                case HDCPModule::HDCP_SHUTDOWN_FAILED:
529                {
530                    // Ugly hack to make sure that the call to
531                    // HDCPObserver::notify is completely handled before
532                    // we clear the HDCP instance and unload the shared
533                    // library :(
534                    (new AMessage(kWhatFinishStop2, this))->post(300000ll);
535                    break;
536                }
537
538                default:
539                {
540                    ALOGE("HDCP failure, shutting down.");
541
542                    mClient->onDisplayError(
543                            IRemoteDisplayClient::kDisplayErrorUnknown);
544                    break;
545                }
546            }
547            break;
548        }
549
550        case kWhatFinishStop2:
551        {
552            finishStop2();
553            break;
554        }
555
556        default:
557            TRESPASS();
558    }
559}
560
561void WifiDisplaySource::registerResponseHandler(
562        int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func) {
563    ResponseID id;
564    id.mSessionID = sessionID;
565    id.mCSeq = cseq;
566    mResponseHandlers.add(id, func);
567}
568
569status_t WifiDisplaySource::sendM1(int32_t sessionID) {
570    AString request = "OPTIONS * RTSP/1.0\r\n";
571    AppendCommonResponse(&request, mNextCSeq);
572
573    request.append(
574            "Require: org.wfa.wfd1.0\r\n"
575            "\r\n");
576
577    status_t err =
578        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
579
580    if (err != OK) {
581        return err;
582    }
583
584    registerResponseHandler(
585            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM1Response);
586
587    ++mNextCSeq;
588
589    return OK;
590}
591
592status_t WifiDisplaySource::sendM3(int32_t sessionID) {
593    AString body =
594        "wfd_content_protection\r\n"
595        "wfd_video_formats\r\n"
596        "wfd_audio_codecs\r\n"
597        "wfd_client_rtp_ports\r\n";
598
599    AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
600    AppendCommonResponse(&request, mNextCSeq);
601
602    request.append("Content-Type: text/parameters\r\n");
603    request.append(AStringPrintf("Content-Length: %d\r\n", body.size()));
604    request.append("\r\n");
605    request.append(body);
606
607    status_t err =
608        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
609
610    if (err != OK) {
611        return err;
612    }
613
614    registerResponseHandler(
615            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM3Response);
616
617    ++mNextCSeq;
618
619    return OK;
620}
621
622status_t WifiDisplaySource::sendM4(int32_t sessionID) {
623    CHECK_EQ(sessionID, mClientSessionID);
624
625    AString body;
626
627    if (mSinkSupportsVideo) {
628        body.append("wfd_video_formats: ");
629
630        VideoFormats chosenVideoFormat;
631        chosenVideoFormat.disableAll();
632        chosenVideoFormat.setNativeResolution(
633                mChosenVideoResolutionType, mChosenVideoResolutionIndex);
634        chosenVideoFormat.setProfileLevel(
635                mChosenVideoResolutionType, mChosenVideoResolutionIndex,
636                mChosenVideoProfile, mChosenVideoLevel);
637
638        body.append(chosenVideoFormat.getFormatSpec(true /* forM4Message */));
639        body.append("\r\n");
640    }
641
642    if (mSinkSupportsAudio) {
643        body.append(
644                AStringPrintf("wfd_audio_codecs: %s\r\n",
645                             (mUsingPCMAudio
646                                ? "LPCM 00000002 00" // 2 ch PCM 48kHz
647                                : "AAC 00000001 00")));  // 2 ch AAC 48kHz
648    }
649
650    body.append(
651            AStringPrintf(
652                "wfd_presentation_URL: rtsp://%s/wfd1.0/streamid=0 none\r\n",
653                mClientInfo.mLocalIP.c_str()));
654
655    body.append(
656            AStringPrintf(
657                "wfd_client_rtp_ports: %s\r\n", mWfdClientRtpPorts.c_str()));
658
659    AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
660    AppendCommonResponse(&request, mNextCSeq);
661
662    request.append("Content-Type: text/parameters\r\n");
663    request.append(AStringPrintf("Content-Length: %d\r\n", body.size()));
664    request.append("\r\n");
665    request.append(body);
666
667    status_t err =
668        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
669
670    if (err != OK) {
671        return err;
672    }
673
674    registerResponseHandler(
675            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM4Response);
676
677    ++mNextCSeq;
678
679    return OK;
680}
681
682status_t WifiDisplaySource::sendTrigger(
683        int32_t sessionID, TriggerType triggerType) {
684    AString body = "wfd_trigger_method: ";
685    switch (triggerType) {
686        case TRIGGER_SETUP:
687            body.append("SETUP");
688            break;
689        case TRIGGER_TEARDOWN:
690            ALOGI("Sending TEARDOWN trigger.");
691            body.append("TEARDOWN");
692            break;
693        case TRIGGER_PAUSE:
694            body.append("PAUSE");
695            break;
696        case TRIGGER_PLAY:
697            body.append("PLAY");
698            break;
699        default:
700            TRESPASS();
701    }
702
703    body.append("\r\n");
704
705    AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
706    AppendCommonResponse(&request, mNextCSeq);
707
708    request.append("Content-Type: text/parameters\r\n");
709    request.append(AStringPrintf("Content-Length: %d\r\n", body.size()));
710    request.append("\r\n");
711    request.append(body);
712
713    status_t err =
714        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
715
716    if (err != OK) {
717        return err;
718    }
719
720    registerResponseHandler(
721            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM5Response);
722
723    ++mNextCSeq;
724
725    return OK;
726}
727
728status_t WifiDisplaySource::sendM16(int32_t sessionID) {
729    AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
730    AppendCommonResponse(&request, mNextCSeq);
731
732    CHECK_EQ(sessionID, mClientSessionID);
733    request.append(
734            AStringPrintf("Session: %d\r\n", mClientInfo.mPlaybackSessionID));
735    request.append("\r\n");  // Empty body
736
737    status_t err =
738        mNetSession->sendRequest(sessionID, request.c_str(), request.size());
739
740    if (err != OK) {
741        return err;
742    }
743
744    registerResponseHandler(
745            sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM16Response);
746
747    ++mNextCSeq;
748
749    scheduleKeepAlive(sessionID);
750
751    return OK;
752}
753
754status_t WifiDisplaySource::onReceiveM1Response(
755        int32_t /* sessionID */, const sp<ParsedMessage> &msg) {
756    int32_t statusCode;
757    if (!msg->getStatusCode(&statusCode)) {
758        return ERROR_MALFORMED;
759    }
760
761    if (statusCode != 200) {
762        return ERROR_UNSUPPORTED;
763    }
764
765    return OK;
766}
767
768// sink_audio_list := ("LPCM"|"AAC"|"AC3" HEXDIGIT*8 HEXDIGIT*2)
769//                       (", " sink_audio_list)*
770static void GetAudioModes(const char *s, const char *prefix, uint32_t *modes) {
771    *modes = 0;
772
773    size_t prefixLen = strlen(prefix);
774
775    while (*s != '0') {
776        if (!strncmp(s, prefix, prefixLen) && s[prefixLen] == ' ') {
777            unsigned latency;
778            if (sscanf(&s[prefixLen + 1], "%08x %02x", modes, &latency) != 2) {
779                *modes = 0;
780            }
781
782            return;
783        }
784
785        const char *commaPos = strchr(s, ',');
786        if (commaPos != NULL) {
787            s = commaPos + 1;
788
789            while (isspace(*s)) {
790                ++s;
791            }
792        } else {
793            break;
794        }
795    }
796}
797
798status_t WifiDisplaySource::onReceiveM3Response(
799        int32_t sessionID, const sp<ParsedMessage> &msg) {
800    int32_t statusCode;
801    if (!msg->getStatusCode(&statusCode)) {
802        return ERROR_MALFORMED;
803    }
804
805    if (statusCode != 200) {
806        return ERROR_UNSUPPORTED;
807    }
808
809    sp<Parameters> params =
810        Parameters::Parse(msg->getContent(), strlen(msg->getContent()));
811
812    if (params == NULL) {
813        return ERROR_MALFORMED;
814    }
815
816    AString value;
817    if (!params->findParameter("wfd_client_rtp_ports", &value)) {
818        ALOGE("Sink doesn't report its choice of wfd_client_rtp_ports.");
819        return ERROR_MALFORMED;
820    }
821
822    unsigned port0 = 0, port1 = 0;
823    if (sscanf(value.c_str(),
824               "RTP/AVP/UDP;unicast %u %u mode=play",
825               &port0,
826               &port1) == 2
827        || sscanf(value.c_str(),
828               "RTP/AVP/TCP;unicast %u %u mode=play",
829               &port0,
830               &port1) == 2) {
831            if (port0 == 0 || port0 > 65535 || port1 != 0) {
832                ALOGE("Sink chose its wfd_client_rtp_ports poorly (%s)",
833                      value.c_str());
834
835                return ERROR_MALFORMED;
836            }
837    } else if (strcmp(value.c_str(), "RTP/AVP/TCP;interleaved mode=play")) {
838        ALOGE("Unsupported value for wfd_client_rtp_ports (%s)",
839              value.c_str());
840
841        return ERROR_UNSUPPORTED;
842    }
843
844    mWfdClientRtpPorts = value;
845    mChosenRTPPort = port0;
846
847    if (!params->findParameter("wfd_video_formats", &value)) {
848        ALOGE("Sink doesn't report its choice of wfd_video_formats.");
849        return ERROR_MALFORMED;
850    }
851
852    mSinkSupportsVideo = false;
853
854    if  (!(value == "none")) {
855        mSinkSupportsVideo = true;
856        if (!mSupportedSinkVideoFormats.parseFormatSpec(value.c_str())) {
857            ALOGE("Failed to parse sink provided wfd_video_formats (%s)",
858                  value.c_str());
859
860            return ERROR_MALFORMED;
861        }
862
863        if (!VideoFormats::PickBestFormat(
864                    mSupportedSinkVideoFormats,
865                    mSupportedSourceVideoFormats,
866                    &mChosenVideoResolutionType,
867                    &mChosenVideoResolutionIndex,
868                    &mChosenVideoProfile,
869                    &mChosenVideoLevel)) {
870            ALOGE("Sink and source share no commonly supported video "
871                  "formats.");
872
873            return ERROR_UNSUPPORTED;
874        }
875
876        size_t width, height, framesPerSecond;
877        bool interlaced;
878        CHECK(VideoFormats::GetConfiguration(
879                    mChosenVideoResolutionType,
880                    mChosenVideoResolutionIndex,
881                    &width,
882                    &height,
883                    &framesPerSecond,
884                    &interlaced));
885
886        ALOGI("Picked video resolution %zu x %zu %c%zu",
887              width, height, interlaced ? 'i' : 'p', framesPerSecond);
888
889        ALOGI("Picked AVC profile %d, level %d",
890              mChosenVideoProfile, mChosenVideoLevel);
891    } else {
892        ALOGI("Sink doesn't support video at all.");
893    }
894
895    if (!params->findParameter("wfd_audio_codecs", &value)) {
896        ALOGE("Sink doesn't report its choice of wfd_audio_codecs.");
897        return ERROR_MALFORMED;
898    }
899
900    mSinkSupportsAudio = false;
901
902    if  (!(value == "none")) {
903        mSinkSupportsAudio = true;
904
905        uint32_t modes;
906        GetAudioModes(value.c_str(), "AAC", &modes);
907
908        bool supportsAAC = (modes & 1) != 0;  // AAC 2ch 48kHz
909
910        GetAudioModes(value.c_str(), "LPCM", &modes);
911
912        bool supportsPCM = (modes & 2) != 0;  // LPCM 2ch 48kHz
913
914        if (supportsPCM
915                && property_get_bool("media.wfd.use-pcm-audio", false)) {
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, this))->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, this);
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, this);
1243    notify->setInt32("playbackSessionID", playbackSessionID);
1244    notify->setInt32("sessionID", sessionID);
1245
1246    sp<PlaybackSession> playbackSession =
1247        new PlaybackSession(
1248                mOpPackageName, 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                AStringPrintf(
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                    AStringPrintf(
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                    AStringPrintf(
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(mStopReplyID != NULL);
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(AStringPrintf("Server: %s\r\n", sUserAgent.c_str()));
1589
1590    if (cseq >= 0) {
1591        response->append(AStringPrintf("CSeq: %d\r\n", cseq));
1592    }
1593
1594    if (playbackSessionID >= 0ll) {
1595        response->append(
1596                AStringPrintf(
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    explicit 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, this);
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