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