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