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