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