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