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> ¬ify);
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> ¬ify)
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