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