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