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