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