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