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