• 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         const 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         if (supportsPCM
915                 && property_get_bool("media.wfd.use-pcm-audio", false)) {
916             ALOGI("Using PCM audio.");
917             mUsingPCMAudio = true;
918         } else if (supportsAAC) {
919             ALOGI("Using AAC audio.");
920             mUsingPCMAudio = false;
921         } else if (supportsPCM) {
922             ALOGI("Using PCM audio.");
923             mUsingPCMAudio = true;
924         } else {
925             ALOGI("Sink doesn't support an audio format we do.");
926             return ERROR_UNSUPPORTED;
927         }
928     } else {
929         ALOGI("Sink doesn't support audio at all.");
930     }
931 
932     if (!mSinkSupportsVideo && !mSinkSupportsAudio) {
933         ALOGE("Sink supports neither video nor audio...");
934         return ERROR_UNSUPPORTED;
935     }
936 
937     mUsingHDCP = false;
938     if (!params->findParameter("wfd_content_protection", &value)) {
939         ALOGI("Sink doesn't appear to support content protection.");
940     } else if (value == "none") {
941         ALOGI("Sink does not support content protection.");
942     } else {
943         mUsingHDCP = true;
944 
945         bool isHDCP2_0 = false;
946         if (value.startsWith("HDCP2.0 ")) {
947             isHDCP2_0 = true;
948         } else if (!value.startsWith("HDCP2.1 ")) {
949             ALOGE("malformed wfd_content_protection: '%s'", value.c_str());
950 
951             return ERROR_MALFORMED;
952         }
953 
954         int32_t hdcpPort;
955         if (!ParsedMessage::GetInt32Attribute(
956                     value.c_str() + 8, "port", &hdcpPort)
957                 || hdcpPort < 1 || hdcpPort > 65535) {
958             return ERROR_MALFORMED;
959         }
960 
961         mIsHDCP2_0 = isHDCP2_0;
962         mHDCPPort = hdcpPort;
963 
964         status_t err = makeHDCP();
965         if (err != OK) {
966             ALOGE("Unable to instantiate HDCP component. "
967                   "Not using HDCP after all.");
968 
969             mUsingHDCP = false;
970         }
971     }
972 
973     return sendM4(sessionID);
974 }
975 
onReceiveM4Response(int32_t sessionID,const sp<ParsedMessage> & msg)976 status_t WifiDisplaySource::onReceiveM4Response(
977         int32_t sessionID, const sp<ParsedMessage> &msg) {
978     int32_t statusCode;
979     if (!msg->getStatusCode(&statusCode)) {
980         return ERROR_MALFORMED;
981     }
982 
983     if (statusCode != 200) {
984         return ERROR_UNSUPPORTED;
985     }
986 
987     if (mUsingHDCP && !mHDCPInitializationComplete) {
988         ALOGI("Deferring SETUP trigger until HDCP initialization completes.");
989 
990         mSetupTriggerDeferred = true;
991         return OK;
992     }
993 
994     return sendTrigger(sessionID, TRIGGER_SETUP);
995 }
996 
onReceiveM5Response(int32_t,const sp<ParsedMessage> & msg)997 status_t WifiDisplaySource::onReceiveM5Response(
998         int32_t /* sessionID */, const sp<ParsedMessage> &msg) {
999     int32_t statusCode;
1000     if (!msg->getStatusCode(&statusCode)) {
1001         return ERROR_MALFORMED;
1002     }
1003 
1004     if (statusCode != 200) {
1005         return ERROR_UNSUPPORTED;
1006     }
1007 
1008     return OK;
1009 }
1010 
onReceiveM16Response(int32_t sessionID,const sp<ParsedMessage> &)1011 status_t WifiDisplaySource::onReceiveM16Response(
1012         int32_t sessionID, const sp<ParsedMessage> & /* msg */) {
1013     // If only the response was required to include a "Session:" header...
1014 
1015     CHECK_EQ(sessionID, mClientSessionID);
1016 
1017     if (mClientInfo.mPlaybackSession != NULL) {
1018         mClientInfo.mPlaybackSession->updateLiveness();
1019     }
1020 
1021     return OK;
1022 }
1023 
scheduleReaper()1024 void WifiDisplaySource::scheduleReaper() {
1025     if (mReaperPending) {
1026         return;
1027     }
1028 
1029     mReaperPending = true;
1030     (new AMessage(kWhatReapDeadClients, this))->post(kReaperIntervalUs);
1031 }
1032 
scheduleKeepAlive(int32_t sessionID)1033 void WifiDisplaySource::scheduleKeepAlive(int32_t sessionID) {
1034     // We need to send updates at least 5 secs before the timeout is set to
1035     // expire, make sure the timeout is greater than 5 secs to begin with.
1036     CHECK_GT(kPlaybackSessionTimeoutUs, 5000000ll);
1037 
1038     sp<AMessage> msg = new AMessage(kWhatKeepAlive, this);
1039     msg->setInt32("sessionID", sessionID);
1040     msg->post(kPlaybackSessionTimeoutUs - 5000000ll);
1041 }
1042 
onReceiveClientData(const sp<AMessage> & msg)1043 status_t WifiDisplaySource::onReceiveClientData(const sp<AMessage> &msg) {
1044     int32_t sessionID;
1045     CHECK(msg->findInt32("sessionID", &sessionID));
1046 
1047     sp<RefBase> obj;
1048     CHECK(msg->findObject("data", &obj));
1049 
1050     sp<ParsedMessage> data =
1051         static_cast<ParsedMessage *>(obj.get());
1052 
1053     ALOGV("session %d received '%s'",
1054           sessionID, data->debugString().c_str());
1055 
1056     AString method;
1057     AString uri;
1058     data->getRequestField(0, &method);
1059 
1060     int32_t cseq;
1061     if (!data->findInt32("cseq", &cseq)) {
1062         sendErrorResponse(sessionID, "400 Bad Request", -1 /* cseq */);
1063         return ERROR_MALFORMED;
1064     }
1065 
1066     if (method.startsWith("RTSP/")) {
1067         // This is a response.
1068 
1069         ResponseID id;
1070         id.mSessionID = sessionID;
1071         id.mCSeq = cseq;
1072 
1073         ssize_t index = mResponseHandlers.indexOfKey(id);
1074 
1075         if (index < 0) {
1076             ALOGW("Received unsolicited server response, cseq %d", cseq);
1077             return ERROR_MALFORMED;
1078         }
1079 
1080         HandleRTSPResponseFunc func = mResponseHandlers.valueAt(index);
1081         mResponseHandlers.removeItemsAt(index);
1082 
1083         status_t err = (this->*func)(sessionID, data);
1084 
1085         if (err != OK) {
1086             ALOGW("Response handler for session %d, cseq %d returned "
1087                   "err %d (%s)",
1088                   sessionID, cseq, err, strerror(-err));
1089 
1090             return err;
1091         }
1092 
1093         return OK;
1094     }
1095 
1096     AString version;
1097     data->getRequestField(2, &version);
1098     if (!(version == AString("RTSP/1.0"))) {
1099         sendErrorResponse(sessionID, "505 RTSP Version not supported", cseq);
1100         return ERROR_UNSUPPORTED;
1101     }
1102 
1103     status_t err;
1104     if (method == "OPTIONS") {
1105         err = onOptionsRequest(sessionID, cseq, data);
1106     } else if (method == "SETUP") {
1107         err = onSetupRequest(sessionID, cseq, data);
1108     } else if (method == "PLAY") {
1109         err = onPlayRequest(sessionID, cseq, data);
1110     } else if (method == "PAUSE") {
1111         err = onPauseRequest(sessionID, cseq, data);
1112     } else if (method == "TEARDOWN") {
1113         err = onTeardownRequest(sessionID, cseq, data);
1114     } else if (method == "GET_PARAMETER") {
1115         err = onGetParameterRequest(sessionID, cseq, data);
1116     } else if (method == "SET_PARAMETER") {
1117         err = onSetParameterRequest(sessionID, cseq, data);
1118     } else {
1119         sendErrorResponse(sessionID, "405 Method Not Allowed", cseq);
1120 
1121         err = ERROR_UNSUPPORTED;
1122     }
1123 
1124     return err;
1125 }
1126 
onOptionsRequest(int32_t sessionID,int32_t cseq,const sp<ParsedMessage> & data)1127 status_t WifiDisplaySource::onOptionsRequest(
1128         int32_t sessionID,
1129         int32_t cseq,
1130         const sp<ParsedMessage> &data) {
1131     int32_t playbackSessionID;
1132     sp<PlaybackSession> playbackSession =
1133         findPlaybackSession(data, &playbackSessionID);
1134 
1135     if (playbackSession != NULL) {
1136         playbackSession->updateLiveness();
1137     }
1138 
1139     AString response = "RTSP/1.0 200 OK\r\n";
1140     AppendCommonResponse(&response, cseq);
1141 
1142     response.append(
1143             "Public: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, "
1144             "GET_PARAMETER, SET_PARAMETER\r\n");
1145 
1146     response.append("\r\n");
1147 
1148     status_t err = mNetSession->sendRequest(sessionID, response.c_str());
1149 
1150     if (err == OK) {
1151         err = sendM3(sessionID);
1152     }
1153 
1154     return err;
1155 }
1156 
onSetupRequest(int32_t sessionID,int32_t cseq,const sp<ParsedMessage> & data)1157 status_t WifiDisplaySource::onSetupRequest(
1158         int32_t sessionID,
1159         int32_t cseq,
1160         const sp<ParsedMessage> &data) {
1161     CHECK_EQ(sessionID, mClientSessionID);
1162     if (mClientInfo.mPlaybackSessionID != -1) {
1163         // We only support a single playback session per client.
1164         // This is due to the reversed keep-alive design in the wfd specs...
1165         sendErrorResponse(sessionID, "400 Bad Request", cseq);
1166         return ERROR_MALFORMED;
1167     }
1168 
1169     AString transport;
1170     if (!data->findString("transport", &transport)) {
1171         sendErrorResponse(sessionID, "400 Bad Request", cseq);
1172         return ERROR_MALFORMED;
1173     }
1174 
1175     RTPSender::TransportMode rtpMode = RTPSender::TRANSPORT_UDP;
1176 
1177     int clientRtp, clientRtcp;
1178     if (transport.startsWith("RTP/AVP/TCP;")) {
1179         AString interleaved;
1180         if (ParsedMessage::GetAttribute(
1181                     transport.c_str(), "interleaved", &interleaved)
1182                 && sscanf(interleaved.c_str(), "%d-%d",
1183                           &clientRtp, &clientRtcp) == 2) {
1184             rtpMode = RTPSender::TRANSPORT_TCP_INTERLEAVED;
1185         } else {
1186             bool badRequest = false;
1187 
1188             AString clientPort;
1189             if (!ParsedMessage::GetAttribute(
1190                         transport.c_str(), "client_port", &clientPort)) {
1191                 badRequest = true;
1192             } else if (sscanf(clientPort.c_str(), "%d-%d",
1193                               &clientRtp, &clientRtcp) == 2) {
1194             } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) {
1195                 // No RTCP.
1196                 clientRtcp = -1;
1197             } else {
1198                 badRequest = true;
1199             }
1200 
1201             if (badRequest) {
1202                 sendErrorResponse(sessionID, "400 Bad Request", cseq);
1203                 return ERROR_MALFORMED;
1204             }
1205 
1206             rtpMode = RTPSender::TRANSPORT_TCP;
1207         }
1208     } else if (transport.startsWith("RTP/AVP;unicast;")
1209             || transport.startsWith("RTP/AVP/UDP;unicast;")) {
1210         bool badRequest = false;
1211 
1212         AString clientPort;
1213         if (!ParsedMessage::GetAttribute(
1214                     transport.c_str(), "client_port", &clientPort)) {
1215             badRequest = true;
1216         } else if (sscanf(clientPort.c_str(), "%d-%d",
1217                           &clientRtp, &clientRtcp) == 2) {
1218         } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) {
1219             // No RTCP.
1220             clientRtcp = -1;
1221         } else {
1222             badRequest = true;
1223         }
1224 
1225         if (badRequest) {
1226             sendErrorResponse(sessionID, "400 Bad Request", cseq);
1227             return ERROR_MALFORMED;
1228         }
1229 #if 1
1230     // The older LG dongles doesn't specify client_port=xxx apparently.
1231     } else if (transport == "RTP/AVP/UDP;unicast") {
1232         clientRtp = 19000;
1233         clientRtcp = -1;
1234 #endif
1235     } else {
1236         sendErrorResponse(sessionID, "461 Unsupported Transport", cseq);
1237         return ERROR_UNSUPPORTED;
1238     }
1239 
1240     int32_t playbackSessionID = makeUniquePlaybackSessionID();
1241 
1242     sp<AMessage> notify = new AMessage(kWhatPlaybackSessionNotify, this);
1243     notify->setInt32("playbackSessionID", playbackSessionID);
1244     notify->setInt32("sessionID", sessionID);
1245 
1246     sp<PlaybackSession> playbackSession =
1247         new PlaybackSession(
1248                 mOpPackageName, mNetSession, notify, mInterfaceAddr, mHDCP, mMediaPath.c_str());
1249 
1250     looper()->registerHandler(playbackSession);
1251 
1252     AString uri;
1253     data->getRequestField(1, &uri);
1254 
1255     if (strncasecmp("rtsp://", uri.c_str(), 7)) {
1256         sendErrorResponse(sessionID, "400 Bad Request", cseq);
1257         return ERROR_MALFORMED;
1258     }
1259 
1260     if (!(uri.startsWith("rtsp://") && uri.endsWith("/wfd1.0/streamid=0"))) {
1261         sendErrorResponse(sessionID, "404 Not found", cseq);
1262         return ERROR_MALFORMED;
1263     }
1264 
1265     RTPSender::TransportMode rtcpMode = RTPSender::TRANSPORT_UDP;
1266     if (clientRtcp < 0) {
1267         rtcpMode = RTPSender::TRANSPORT_NONE;
1268     }
1269 
1270     status_t err = playbackSession->init(
1271             mClientInfo.mRemoteIP.c_str(),
1272             clientRtp,
1273             rtpMode,
1274             clientRtcp,
1275             rtcpMode,
1276             mSinkSupportsAudio,
1277             mUsingPCMAudio,
1278             mSinkSupportsVideo,
1279             mChosenVideoResolutionType,
1280             mChosenVideoResolutionIndex,
1281             mChosenVideoProfile,
1282             mChosenVideoLevel);
1283 
1284     if (err != OK) {
1285         looper()->unregisterHandler(playbackSession->id());
1286         playbackSession.clear();
1287     }
1288 
1289     switch (err) {
1290         case OK:
1291             break;
1292         case -ENOENT:
1293             sendErrorResponse(sessionID, "404 Not Found", cseq);
1294             return err;
1295         default:
1296             sendErrorResponse(sessionID, "403 Forbidden", cseq);
1297             return err;
1298     }
1299 
1300     mClientInfo.mPlaybackSessionID = playbackSessionID;
1301     mClientInfo.mPlaybackSession = playbackSession;
1302 
1303     AString response = "RTSP/1.0 200 OK\r\n";
1304     AppendCommonResponse(&response, cseq, playbackSessionID);
1305 
1306     if (rtpMode == RTPSender::TRANSPORT_TCP_INTERLEAVED) {
1307         response.append(
1308                 AStringPrintf(
1309                     "Transport: RTP/AVP/TCP;interleaved=%d-%d;",
1310                     clientRtp, clientRtcp));
1311     } else {
1312         int32_t serverRtp = playbackSession->getRTPPort();
1313 
1314         AString transportString = "UDP";
1315         if (rtpMode == RTPSender::TRANSPORT_TCP) {
1316             transportString = "TCP";
1317         }
1318 
1319         if (clientRtcp >= 0) {
1320             response.append(
1321                     AStringPrintf(
1322                         "Transport: RTP/AVP/%s;unicast;client_port=%d-%d;"
1323                         "server_port=%d-%d\r\n",
1324                         transportString.c_str(),
1325                         clientRtp, clientRtcp, serverRtp, serverRtp + 1));
1326         } else {
1327             response.append(
1328                     AStringPrintf(
1329                         "Transport: RTP/AVP/%s;unicast;client_port=%d;"
1330                         "server_port=%d\r\n",
1331                         transportString.c_str(),
1332                         clientRtp, serverRtp));
1333         }
1334     }
1335 
1336     response.append("\r\n");
1337 
1338     err = mNetSession->sendRequest(sessionID, response.c_str());
1339 
1340     if (err != OK) {
1341         return err;
1342     }
1343 
1344     mState = AWAITING_CLIENT_PLAY;
1345 
1346     scheduleReaper();
1347     scheduleKeepAlive(sessionID);
1348 
1349     return OK;
1350 }
1351 
onPlayRequest(int32_t sessionID,int32_t cseq,const sp<ParsedMessage> & data)1352 status_t WifiDisplaySource::onPlayRequest(
1353         int32_t sessionID,
1354         int32_t cseq,
1355         const sp<ParsedMessage> &data) {
1356     int32_t playbackSessionID;
1357     sp<PlaybackSession> playbackSession =
1358         findPlaybackSession(data, &playbackSessionID);
1359 
1360     if (playbackSession == NULL) {
1361         sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1362         return ERROR_MALFORMED;
1363     }
1364 
1365     if (mState != AWAITING_CLIENT_PLAY
1366      && mState != PAUSED_TO_PLAYING
1367      && mState != PAUSED) {
1368         ALOGW("Received PLAY request but we're in state %d", mState);
1369 
1370         sendErrorResponse(
1371                 sessionID, "455 Method Not Valid in This State", cseq);
1372 
1373         return INVALID_OPERATION;
1374     }
1375 
1376     ALOGI("Received PLAY request.");
1377     if (mPlaybackSessionEstablished) {
1378         finishPlay();
1379     } else {
1380         ALOGI("deferring PLAY request until session established.");
1381     }
1382 
1383     AString response = "RTSP/1.0 200 OK\r\n";
1384     AppendCommonResponse(&response, cseq, playbackSessionID);
1385     response.append("Range: npt=now-\r\n");
1386     response.append("\r\n");
1387 
1388     status_t err = mNetSession->sendRequest(sessionID, response.c_str());
1389 
1390     if (err != OK) {
1391         return err;
1392     }
1393 
1394     if (mState == PAUSED_TO_PLAYING || mPlaybackSessionEstablished) {
1395         mState = PLAYING;
1396         return OK;
1397     }
1398 
1399     CHECK_EQ(mState, AWAITING_CLIENT_PLAY);
1400     mState = ABOUT_TO_PLAY;
1401 
1402     return OK;
1403 }
1404 
finishPlay()1405 void WifiDisplaySource::finishPlay() {
1406     const sp<PlaybackSession> &playbackSession =
1407         mClientInfo.mPlaybackSession;
1408 
1409     status_t err = playbackSession->play();
1410     CHECK_EQ(err, (status_t)OK);
1411 }
1412 
onPauseRequest(int32_t sessionID,int32_t cseq,const sp<ParsedMessage> & data)1413 status_t WifiDisplaySource::onPauseRequest(
1414         int32_t sessionID,
1415         int32_t cseq,
1416         const sp<ParsedMessage> &data) {
1417     int32_t playbackSessionID;
1418     sp<PlaybackSession> playbackSession =
1419         findPlaybackSession(data, &playbackSessionID);
1420 
1421     if (playbackSession == NULL) {
1422         sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1423         return ERROR_MALFORMED;
1424     }
1425 
1426     ALOGI("Received PAUSE request.");
1427 
1428     if (mState != PLAYING_TO_PAUSED && mState != PLAYING) {
1429         return INVALID_OPERATION;
1430     }
1431 
1432     status_t err = playbackSession->pause();
1433     CHECK_EQ(err, (status_t)OK);
1434 
1435     AString response = "RTSP/1.0 200 OK\r\n";
1436     AppendCommonResponse(&response, cseq, playbackSessionID);
1437     response.append("\r\n");
1438 
1439     err = mNetSession->sendRequest(sessionID, response.c_str());
1440 
1441     if (err != OK) {
1442         return err;
1443     }
1444 
1445     mState = PAUSED;
1446 
1447     return err;
1448 }
1449 
onTeardownRequest(int32_t sessionID,int32_t cseq,const sp<ParsedMessage> & data)1450 status_t WifiDisplaySource::onTeardownRequest(
1451         int32_t sessionID,
1452         int32_t cseq,
1453         const sp<ParsedMessage> &data) {
1454     ALOGI("Received TEARDOWN request.");
1455 
1456     int32_t playbackSessionID;
1457     sp<PlaybackSession> playbackSession =
1458         findPlaybackSession(data, &playbackSessionID);
1459 
1460     if (playbackSession == NULL) {
1461         sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1462         return ERROR_MALFORMED;
1463     }
1464 
1465     AString response = "RTSP/1.0 200 OK\r\n";
1466     AppendCommonResponse(&response, cseq, playbackSessionID);
1467     response.append("Connection: close\r\n");
1468     response.append("\r\n");
1469 
1470     mNetSession->sendRequest(sessionID, response.c_str());
1471 
1472     if (mState == AWAITING_CLIENT_TEARDOWN) {
1473         CHECK(mStopReplyID != NULL);
1474         finishStop();
1475     } else {
1476         mClient->onDisplayError(IRemoteDisplayClient::kDisplayErrorUnknown);
1477     }
1478 
1479     return OK;
1480 }
1481 
finishStop()1482 void WifiDisplaySource::finishStop() {
1483     ALOGV("finishStop");
1484 
1485     mState = STOPPING;
1486 
1487     disconnectClientAsync();
1488 }
1489 
finishStopAfterDisconnectingClient()1490 void WifiDisplaySource::finishStopAfterDisconnectingClient() {
1491     ALOGV("finishStopAfterDisconnectingClient");
1492 
1493     if (mHDCP != NULL) {
1494         ALOGI("Initiating HDCP shutdown.");
1495         mHDCP->shutdownAsync();
1496         return;
1497     }
1498 
1499     finishStop2();
1500 }
1501 
finishStop2()1502 void WifiDisplaySource::finishStop2() {
1503     ALOGV("finishStop2");
1504 
1505     if (mHDCP != NULL) {
1506         mHDCP->setObserver(NULL);
1507         mHDCPObserver.clear();
1508         mHDCP.clear();
1509     }
1510 
1511     if (mSessionID != 0) {
1512         mNetSession->destroySession(mSessionID);
1513         mSessionID = 0;
1514     }
1515 
1516     ALOGI("We're stopped.");
1517     mState = STOPPED;
1518 
1519     status_t err = OK;
1520 
1521     sp<AMessage> response = new AMessage;
1522     response->setInt32("err", err);
1523     response->postReply(mStopReplyID);
1524 }
1525 
onGetParameterRequest(int32_t sessionID,int32_t cseq,const sp<ParsedMessage> & data)1526 status_t WifiDisplaySource::onGetParameterRequest(
1527         int32_t sessionID,
1528         int32_t cseq,
1529         const sp<ParsedMessage> &data) {
1530     int32_t playbackSessionID;
1531     sp<PlaybackSession> playbackSession =
1532         findPlaybackSession(data, &playbackSessionID);
1533 
1534     if (playbackSession == NULL) {
1535         sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1536         return ERROR_MALFORMED;
1537     }
1538 
1539     playbackSession->updateLiveness();
1540 
1541     AString response = "RTSP/1.0 200 OK\r\n";
1542     AppendCommonResponse(&response, cseq, playbackSessionID);
1543     response.append("\r\n");
1544 
1545     status_t err = mNetSession->sendRequest(sessionID, response.c_str());
1546     return err;
1547 }
1548 
onSetParameterRequest(int32_t sessionID,int32_t cseq,const sp<ParsedMessage> & data)1549 status_t WifiDisplaySource::onSetParameterRequest(
1550         int32_t sessionID,
1551         int32_t cseq,
1552         const sp<ParsedMessage> &data) {
1553     int32_t playbackSessionID;
1554     sp<PlaybackSession> playbackSession =
1555         findPlaybackSession(data, &playbackSessionID);
1556 
1557     if (playbackSession == NULL) {
1558         sendErrorResponse(sessionID, "454 Session Not Found", cseq);
1559         return ERROR_MALFORMED;
1560     }
1561 
1562     if (strstr(data->getContent(), "wfd_idr_request\r\n")) {
1563         playbackSession->requestIDRFrame();
1564     }
1565 
1566     playbackSession->updateLiveness();
1567 
1568     AString response = "RTSP/1.0 200 OK\r\n";
1569     AppendCommonResponse(&response, cseq, playbackSessionID);
1570     response.append("\r\n");
1571 
1572     status_t err = mNetSession->sendRequest(sessionID, response.c_str());
1573     return err;
1574 }
1575 
1576 // static
AppendCommonResponse(AString * response,int32_t cseq,int32_t playbackSessionID)1577 void WifiDisplaySource::AppendCommonResponse(
1578         AString *response, int32_t cseq, int32_t playbackSessionID) {
1579     time_t now = time(NULL);
1580     struct tm *now2 = gmtime(&now);
1581     char buf[128];
1582     strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2);
1583 
1584     response->append("Date: ");
1585     response->append(buf);
1586     response->append("\r\n");
1587 
1588     response->append(AStringPrintf("Server: %s\r\n", sUserAgent.c_str()));
1589 
1590     if (cseq >= 0) {
1591         response->append(AStringPrintf("CSeq: %d\r\n", cseq));
1592     }
1593 
1594     if (playbackSessionID >= 0ll) {
1595         response->append(
1596                 AStringPrintf(
1597                     "Session: %d;timeout=%lld\r\n",
1598                     playbackSessionID, kPlaybackSessionTimeoutSecs));
1599     }
1600 }
1601 
sendErrorResponse(int32_t sessionID,const char * errorDetail,int32_t cseq)1602 void WifiDisplaySource::sendErrorResponse(
1603         int32_t sessionID,
1604         const char *errorDetail,
1605         int32_t cseq) {
1606     AString response;
1607     response.append("RTSP/1.0 ");
1608     response.append(errorDetail);
1609     response.append("\r\n");
1610 
1611     AppendCommonResponse(&response, cseq);
1612 
1613     response.append("\r\n");
1614 
1615     mNetSession->sendRequest(sessionID, response.c_str());
1616 }
1617 
makeUniquePlaybackSessionID() const1618 int32_t WifiDisplaySource::makeUniquePlaybackSessionID() const {
1619     return rand();
1620 }
1621 
findPlaybackSession(const sp<ParsedMessage> & data,int32_t * playbackSessionID) const1622 sp<WifiDisplaySource::PlaybackSession> WifiDisplaySource::findPlaybackSession(
1623         const sp<ParsedMessage> &data, int32_t *playbackSessionID) const {
1624     if (!data->findInt32("session", playbackSessionID)) {
1625         // XXX the older dongles do not always include a "Session:" header.
1626         *playbackSessionID = mClientInfo.mPlaybackSessionID;
1627         return mClientInfo.mPlaybackSession;
1628     }
1629 
1630     if (*playbackSessionID != mClientInfo.mPlaybackSessionID) {
1631         return NULL;
1632     }
1633 
1634     return mClientInfo.mPlaybackSession;
1635 }
1636 
disconnectClientAsync()1637 void WifiDisplaySource::disconnectClientAsync() {
1638     ALOGV("disconnectClient");
1639 
1640     if (mClientInfo.mPlaybackSession == NULL) {
1641         disconnectClient2();
1642         return;
1643     }
1644 
1645     if (mClientInfo.mPlaybackSession != NULL) {
1646         ALOGV("Destroying PlaybackSession");
1647         mClientInfo.mPlaybackSession->destroyAsync();
1648     }
1649 }
1650 
disconnectClient2()1651 void WifiDisplaySource::disconnectClient2() {
1652     ALOGV("disconnectClient2");
1653 
1654     if (mClientInfo.mPlaybackSession != NULL) {
1655         looper()->unregisterHandler(mClientInfo.mPlaybackSession->id());
1656         mClientInfo.mPlaybackSession.clear();
1657     }
1658 
1659     if (mClientSessionID != 0) {
1660         mNetSession->destroySession(mClientSessionID);
1661         mClientSessionID = 0;
1662     }
1663 
1664     mClient->onDisplayDisconnected();
1665 
1666     finishStopAfterDisconnectingClient();
1667 }
1668 
1669 struct WifiDisplaySource::HDCPObserver : public BnHDCPObserver {
1670     explicit HDCPObserver(const sp<AMessage> &notify);
1671 
1672     virtual void notify(
1673             int msg, int ext1, int ext2, const Parcel *obj);
1674 
1675 private:
1676     sp<AMessage> mNotify;
1677 
1678     DISALLOW_EVIL_CONSTRUCTORS(HDCPObserver);
1679 };
1680 
HDCPObserver(const sp<AMessage> & notify)1681 WifiDisplaySource::HDCPObserver::HDCPObserver(
1682         const sp<AMessage> &notify)
1683     : mNotify(notify) {
1684 }
1685 
notify(int msg,int ext1,int ext2,const Parcel *)1686 void WifiDisplaySource::HDCPObserver::notify(
1687         int msg, int ext1, int ext2, const Parcel * /* obj */) {
1688     sp<AMessage> notify = mNotify->dup();
1689     notify->setInt32("msg", msg);
1690     notify->setInt32("ext1", ext1);
1691     notify->setInt32("ext2", ext2);
1692     notify->post();
1693 }
1694 
makeHDCP()1695 status_t WifiDisplaySource::makeHDCP() {
1696     sp<IServiceManager> sm = defaultServiceManager();
1697     sp<IBinder> binder = sm->getService(String16("media.player"));
1698 
1699     sp<IMediaPlayerService> service =
1700         interface_cast<IMediaPlayerService>(binder);
1701 
1702     CHECK(service != NULL);
1703 
1704     mHDCP = service->makeHDCP(true /* createEncryptionModule */);
1705 
1706     if (mHDCP == NULL) {
1707         return ERROR_UNSUPPORTED;
1708     }
1709 
1710     sp<AMessage> notify = new AMessage(kWhatHDCPNotify, this);
1711     mHDCPObserver = new HDCPObserver(notify);
1712 
1713     status_t err = mHDCP->setObserver(mHDCPObserver);
1714 
1715     if (err != OK) {
1716         ALOGE("Failed to set HDCP observer.");
1717 
1718         mHDCPObserver.clear();
1719         mHDCP.clear();
1720 
1721         return err;
1722     }
1723 
1724     ALOGI("Initiating HDCP negotiation w/ host %s:%d",
1725             mClientInfo.mRemoteIP.c_str(), mHDCPPort);
1726 
1727     err = mHDCP->initAsync(mClientInfo.mRemoteIP.c_str(), mHDCPPort);
1728 
1729     if (err != OK) {
1730         return err;
1731     }
1732 
1733     return OK;
1734 }
1735 
1736 }  // namespace android
1737 
1738