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