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