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