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