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