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