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