WifiDisplaySource.cpp revision ef7d3793fa9bbfb25253626ede9a020ee9280a17
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:%d/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(), mClientInfo.mLocalPort, 503 transportString.c_str()); 504 505 AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 506 AppendCommonResponse(&request, mNextCSeq); 507 508 request.append("Content-Type: text/parameters\r\n"); 509 request.append(StringPrintf("Content-Length: %d\r\n", body.size())); 510 request.append("\r\n"); 511 request.append(body); 512 513 status_t err = 514 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 515 516 if (err != OK) { 517 return err; 518 } 519 520 registerResponseHandler( 521 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM4Response); 522 523 ++mNextCSeq; 524 525 return OK; 526} 527 528status_t WifiDisplaySource::sendM5(int32_t sessionID, bool requestShutdown) { 529 AString body = "wfd_trigger_method: "; 530 if (requestShutdown) { 531 ALOGI("Sending TEARDOWN trigger."); 532 body.append("TEARDOWN"); 533 } else { 534 body.append("SETUP"); 535 } 536 537 body.append("\r\n"); 538 539 AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 540 AppendCommonResponse(&request, mNextCSeq); 541 542 request.append("Content-Type: text/parameters\r\n"); 543 request.append(StringPrintf("Content-Length: %d\r\n", body.size())); 544 request.append("\r\n"); 545 request.append(body); 546 547 status_t err = 548 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 549 550 if (err != OK) { 551 return err; 552 } 553 554 registerResponseHandler( 555 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM5Response); 556 557 ++mNextCSeq; 558 559 return OK; 560} 561 562status_t WifiDisplaySource::sendM16(int32_t sessionID) { 563 AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 564 AppendCommonResponse(&request, mNextCSeq); 565 566 CHECK_EQ(sessionID, mClientSessionID); 567 request.append( 568 StringPrintf("Session: %d\r\n", mClientInfo.mPlaybackSessionID)); 569 request.append("\r\n"); // Empty body 570 571 status_t err = 572 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 573 574 if (err != OK) { 575 return err; 576 } 577 578 registerResponseHandler( 579 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM16Response); 580 581 ++mNextCSeq; 582 583 return OK; 584} 585 586status_t WifiDisplaySource::onReceiveM1Response( 587 int32_t sessionID, const sp<ParsedMessage> &msg) { 588 int32_t statusCode; 589 if (!msg->getStatusCode(&statusCode)) { 590 return ERROR_MALFORMED; 591 } 592 593 if (statusCode != 200) { 594 return ERROR_UNSUPPORTED; 595 } 596 597 return OK; 598} 599 600status_t WifiDisplaySource::onReceiveM3Response( 601 int32_t sessionID, const sp<ParsedMessage> &msg) { 602 int32_t statusCode; 603 if (!msg->getStatusCode(&statusCode)) { 604 return ERROR_MALFORMED; 605 } 606 607 if (statusCode != 200) { 608 return ERROR_UNSUPPORTED; 609 } 610 611 sp<Parameters> params = 612 Parameters::Parse(msg->getContent(), strlen(msg->getContent())); 613 614 if (params == NULL) { 615 return ERROR_MALFORMED; 616 } 617 618#if REQUIRE_HDCP 619 AString value; 620 if (!params->findParameter("wfd_content_protection", &value)) { 621 ALOGE("Sink doesn't appear to support content protection."); 622 return -EACCES; 623 } 624 625 if (value == "none") { 626 ALOGE("Sink does not support content protection."); 627 return -EACCES; 628 } 629 630 bool isHDCP2_0 = false; 631 if (value.startsWith("HDCP2.0 ")) { 632 isHDCP2_0 = true; 633 } else if (!value.startsWith("HDCP2.1 ")) { 634 return ERROR_MALFORMED; 635 } 636 637 int32_t hdcpPort; 638 if (!ParsedMessage::GetInt32Attribute(value.c_str() + 8, "port", &hdcpPort) 639 || hdcpPort < 1 || hdcpPort > 65535) { 640 return ERROR_MALFORMED; 641 } 642 643 mIsHDCP2_0 = isHDCP2_0; 644 mHDCPPort = hdcpPort; 645 646 status_t err = makeHDCP(); 647 if (err != OK) { 648 ALOGE("Unable to instantiate HDCP component."); 649 return err; 650 } 651#endif 652 653 return sendM4(sessionID); 654} 655 656status_t WifiDisplaySource::onReceiveM4Response( 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#if REQUIRE_HDCP 668 if (!mHDCPInitializationComplete) { 669 ALOGI("Deferring SETUP trigger until HDCP initialization completes."); 670 671 mSetupTriggerDeferred = true; 672 return OK; 673 } 674#endif 675 676 return sendM5(sessionID, false /* requestShutdown */); 677} 678 679status_t WifiDisplaySource::onReceiveM5Response( 680 int32_t sessionID, const sp<ParsedMessage> &msg) { 681 int32_t statusCode; 682 if (!msg->getStatusCode(&statusCode)) { 683 return ERROR_MALFORMED; 684 } 685 686 if (statusCode != 200) { 687 return ERROR_UNSUPPORTED; 688 } 689 690 return OK; 691} 692 693status_t WifiDisplaySource::onReceiveM16Response( 694 int32_t sessionID, const sp<ParsedMessage> &msg) { 695 // If only the response was required to include a "Session:" header... 696 697 CHECK_EQ(sessionID, mClientSessionID); 698 699 if (mClientInfo.mPlaybackSession != NULL) { 700 mClientInfo.mPlaybackSession->updateLiveness(); 701 702 scheduleKeepAlive(sessionID); 703 } 704 705 return OK; 706} 707 708void WifiDisplaySource::scheduleReaper() { 709 if (mReaperPending) { 710 return; 711 } 712 713 mReaperPending = true; 714 (new AMessage(kWhatReapDeadClients, id()))->post(kReaperIntervalUs); 715} 716 717void WifiDisplaySource::scheduleKeepAlive(int32_t sessionID) { 718 // We need to send updates at least 5 secs before the timeout is set to 719 // expire, make sure the timeout is greater than 5 secs to begin with. 720 CHECK_GT(kPlaybackSessionTimeoutUs, 5000000ll); 721 722 sp<AMessage> msg = new AMessage(kWhatKeepAlive, id()); 723 msg->setInt32("sessionID", sessionID); 724 msg->post(kPlaybackSessionTimeoutUs - 5000000ll); 725} 726 727status_t WifiDisplaySource::onReceiveClientData(const sp<AMessage> &msg) { 728 int32_t sessionID; 729 CHECK(msg->findInt32("sessionID", &sessionID)); 730 731 sp<RefBase> obj; 732 CHECK(msg->findObject("data", &obj)); 733 734 sp<ParsedMessage> data = 735 static_cast<ParsedMessage *>(obj.get()); 736 737 ALOGV("session %d received '%s'", 738 sessionID, data->debugString().c_str()); 739 740 AString method; 741 AString uri; 742 data->getRequestField(0, &method); 743 744 int32_t cseq; 745 if (!data->findInt32("cseq", &cseq)) { 746 sendErrorResponse(sessionID, "400 Bad Request", -1 /* cseq */); 747 return ERROR_MALFORMED; 748 } 749 750 if (method.startsWith("RTSP/")) { 751 // This is a response. 752 753 ResponseID id; 754 id.mSessionID = sessionID; 755 id.mCSeq = cseq; 756 757 ssize_t index = mResponseHandlers.indexOfKey(id); 758 759 if (index < 0) { 760 ALOGW("Received unsolicited server response, cseq %d", cseq); 761 return ERROR_MALFORMED; 762 } 763 764 HandleRTSPResponseFunc func = mResponseHandlers.valueAt(index); 765 mResponseHandlers.removeItemsAt(index); 766 767 status_t err = (this->*func)(sessionID, data); 768 769 if (err != OK) { 770 ALOGW("Response handler for session %d, cseq %d returned " 771 "err %d (%s)", 772 sessionID, cseq, err, strerror(-err)); 773 774 return err; 775 } 776 777 return OK; 778 } 779 780 AString version; 781 data->getRequestField(2, &version); 782 if (!(version == AString("RTSP/1.0"))) { 783 sendErrorResponse(sessionID, "505 RTSP Version not supported", cseq); 784 return ERROR_UNSUPPORTED; 785 } 786 787 status_t err; 788 if (method == "OPTIONS") { 789 err = onOptionsRequest(sessionID, cseq, data); 790 } else if (method == "SETUP") { 791 err = onSetupRequest(sessionID, cseq, data); 792 } else if (method == "PLAY") { 793 err = onPlayRequest(sessionID, cseq, data); 794 } else if (method == "PAUSE") { 795 err = onPauseRequest(sessionID, cseq, data); 796 } else if (method == "TEARDOWN") { 797 err = onTeardownRequest(sessionID, cseq, data); 798 } else if (method == "GET_PARAMETER") { 799 err = onGetParameterRequest(sessionID, cseq, data); 800 } else if (method == "SET_PARAMETER") { 801 err = onSetParameterRequest(sessionID, cseq, data); 802 } else { 803 sendErrorResponse(sessionID, "405 Method Not Allowed", cseq); 804 805 err = ERROR_UNSUPPORTED; 806 } 807 808 return err; 809} 810 811status_t WifiDisplaySource::onOptionsRequest( 812 int32_t sessionID, 813 int32_t cseq, 814 const sp<ParsedMessage> &data) { 815 int32_t playbackSessionID; 816 sp<PlaybackSession> playbackSession = 817 findPlaybackSession(data, &playbackSessionID); 818 819 if (playbackSession != NULL) { 820 playbackSession->updateLiveness(); 821 } 822 823 AString response = "RTSP/1.0 200 OK\r\n"; 824 AppendCommonResponse(&response, cseq); 825 826 response.append( 827 "Public: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, " 828 "GET_PARAMETER, SET_PARAMETER\r\n"); 829 830 response.append("\r\n"); 831 832 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 833 834 if (err == OK) { 835 err = sendM3(sessionID); 836 } 837 838 return err; 839} 840 841status_t WifiDisplaySource::onSetupRequest( 842 int32_t sessionID, 843 int32_t cseq, 844 const sp<ParsedMessage> &data) { 845 CHECK_EQ(sessionID, mClientSessionID); 846 if (mClientInfo.mPlaybackSessionID != -1) { 847 // We only support a single playback session per client. 848 // This is due to the reversed keep-alive design in the wfd specs... 849 sendErrorResponse(sessionID, "400 Bad Request", cseq); 850 return ERROR_MALFORMED; 851 } 852 853 AString transport; 854 if (!data->findString("transport", &transport)) { 855 sendErrorResponse(sessionID, "400 Bad Request", cseq); 856 return ERROR_MALFORMED; 857 } 858 859 PlaybackSession::TransportMode transportMode = 860 PlaybackSession::TRANSPORT_UDP; 861 862 int clientRtp, clientRtcp; 863 if (transport.startsWith("RTP/AVP/TCP;")) { 864 AString interleaved; 865 if (ParsedMessage::GetAttribute( 866 transport.c_str(), "interleaved", &interleaved) 867 && sscanf(interleaved.c_str(), "%d-%d", 868 &clientRtp, &clientRtcp) == 2) { 869 transportMode = PlaybackSession::TRANSPORT_TCP_INTERLEAVED; 870 } else { 871 bool badRequest = false; 872 873 AString clientPort; 874 if (!ParsedMessage::GetAttribute( 875 transport.c_str(), "client_port", &clientPort)) { 876 badRequest = true; 877 } else if (sscanf(clientPort.c_str(), "%d-%d", 878 &clientRtp, &clientRtcp) == 2) { 879 } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) { 880 // No RTCP. 881 clientRtcp = -1; 882 } else { 883 badRequest = true; 884 } 885 886 if (badRequest) { 887 sendErrorResponse(sessionID, "400 Bad Request", cseq); 888 return ERROR_MALFORMED; 889 } 890 891 transportMode = PlaybackSession::TRANSPORT_TCP; 892 } 893 } else if (transport.startsWith("RTP/AVP;unicast;") 894 || transport.startsWith("RTP/AVP/UDP;unicast;")) { 895 bool badRequest = false; 896 897 AString clientPort; 898 if (!ParsedMessage::GetAttribute( 899 transport.c_str(), "client_port", &clientPort)) { 900 badRequest = true; 901 } else if (sscanf(clientPort.c_str(), "%d-%d", 902 &clientRtp, &clientRtcp) == 2) { 903 } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) { 904 // No RTCP. 905 clientRtcp = -1; 906 } else { 907 badRequest = true; 908 } 909 910 if (badRequest) { 911 sendErrorResponse(sessionID, "400 Bad Request", cseq); 912 return ERROR_MALFORMED; 913 } 914#if 1 915 // The older LG dongles doesn't specify client_port=xxx apparently. 916 } else if (transport == "RTP/AVP/UDP;unicast") { 917 clientRtp = 19000; 918 clientRtcp = -1; 919#endif 920 } else { 921 sendErrorResponse(sessionID, "461 Unsupported Transport", cseq); 922 return ERROR_UNSUPPORTED; 923 } 924 925 int32_t playbackSessionID = makeUniquePlaybackSessionID(); 926 927 sp<AMessage> notify = new AMessage(kWhatPlaybackSessionNotify, id()); 928 notify->setInt32("playbackSessionID", playbackSessionID); 929 notify->setInt32("sessionID", sessionID); 930 931 sp<PlaybackSession> playbackSession = 932 new PlaybackSession( 933 mNetSession, notify, mInterfaceAddr, 934#if REQUIRE_HDCP 935 mHDCP 936#else 937 NULL 938#endif 939 ); 940 941 looper()->registerHandler(playbackSession); 942 943 AString uri; 944 data->getRequestField(1, &uri); 945 946 if (strncasecmp("rtsp://", uri.c_str(), 7)) { 947 sendErrorResponse(sessionID, "400 Bad Request", cseq); 948 return ERROR_MALFORMED; 949 } 950 951 if (!(uri.startsWith("rtsp://") && uri.endsWith("/wfd1.0/streamid=0"))) { 952 sendErrorResponse(sessionID, "404 Not found", cseq); 953 return ERROR_MALFORMED; 954 } 955 956 status_t err = playbackSession->init( 957 mClientInfo.mRemoteIP.c_str(), 958 clientRtp, 959 clientRtcp, 960 transportMode); 961 962 if (err != OK) { 963 looper()->unregisterHandler(playbackSession->id()); 964 playbackSession.clear(); 965 } 966 967 switch (err) { 968 case OK: 969 break; 970 case -ENOENT: 971 sendErrorResponse(sessionID, "404 Not Found", cseq); 972 return err; 973 default: 974 sendErrorResponse(sessionID, "403 Forbidden", cseq); 975 return err; 976 } 977 978 mClientInfo.mPlaybackSessionID = playbackSessionID; 979 mClientInfo.mPlaybackSession = playbackSession; 980 981 AString response = "RTSP/1.0 200 OK\r\n"; 982 AppendCommonResponse(&response, cseq, playbackSessionID); 983 984 if (transportMode == PlaybackSession::TRANSPORT_TCP_INTERLEAVED) { 985 response.append( 986 StringPrintf( 987 "Transport: RTP/AVP/TCP;interleaved=%d-%d;", 988 clientRtp, clientRtcp)); 989 } else { 990 int32_t serverRtp = playbackSession->getRTPPort(); 991 992 AString transportString = "UDP"; 993 if (transportMode == PlaybackSession::TRANSPORT_TCP) { 994 transportString = "TCP"; 995 } 996 997 if (clientRtcp >= 0) { 998 response.append( 999 StringPrintf( 1000 "Transport: RTP/AVP/%s;unicast;client_port=%d-%d;" 1001 "server_port=%d-%d\r\n", 1002 transportString.c_str(), 1003 clientRtp, clientRtcp, serverRtp, serverRtp + 1)); 1004 } else { 1005 response.append( 1006 StringPrintf( 1007 "Transport: RTP/AVP/%s;unicast;client_port=%d;" 1008 "server_port=%d\r\n", 1009 transportString.c_str(), 1010 clientRtp, serverRtp)); 1011 } 1012 } 1013 1014 response.append("\r\n"); 1015 1016 err = mNetSession->sendRequest(sessionID, response.c_str()); 1017 1018 if (err != OK) { 1019 return err; 1020 } 1021 1022 scheduleReaper(); 1023 scheduleKeepAlive(sessionID); 1024 1025 return OK; 1026} 1027 1028status_t WifiDisplaySource::onPlayRequest( 1029 int32_t sessionID, 1030 int32_t cseq, 1031 const sp<ParsedMessage> &data) { 1032 int32_t playbackSessionID; 1033 sp<PlaybackSession> playbackSession = 1034 findPlaybackSession(data, &playbackSessionID); 1035 1036 if (playbackSession == NULL) { 1037 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 1038 return ERROR_MALFORMED; 1039 } 1040 1041 ALOGI("Received PLAY request."); 1042 1043 status_t err = playbackSession->play(); 1044 CHECK_EQ(err, (status_t)OK); 1045 1046 AString response = "RTSP/1.0 200 OK\r\n"; 1047 AppendCommonResponse(&response, cseq, playbackSessionID); 1048 response.append("Range: npt=now-\r\n"); 1049 response.append("\r\n"); 1050 1051 err = mNetSession->sendRequest(sessionID, response.c_str()); 1052 1053 if (err != OK) { 1054 return err; 1055 } 1056 1057 playbackSession->finishPlay(); 1058 1059 return OK; 1060} 1061 1062status_t WifiDisplaySource::onPauseRequest( 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 status_t err = playbackSession->pause(); 1076 CHECK_EQ(err, (status_t)OK); 1077 1078 AString response = "RTSP/1.0 200 OK\r\n"; 1079 AppendCommonResponse(&response, cseq, playbackSessionID); 1080 response.append("\r\n"); 1081 1082 err = mNetSession->sendRequest(sessionID, response.c_str()); 1083 1084 return err; 1085} 1086 1087status_t WifiDisplaySource::onTeardownRequest( 1088 int32_t sessionID, 1089 int32_t cseq, 1090 const sp<ParsedMessage> &data) { 1091 ALOGI("Received TEARDOWN request."); 1092 1093 int32_t playbackSessionID; 1094 sp<PlaybackSession> playbackSession = 1095 findPlaybackSession(data, &playbackSessionID); 1096 1097 if (playbackSession == NULL) { 1098 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 1099 return ERROR_MALFORMED; 1100 } 1101 1102 AString response = "RTSP/1.0 200 OK\r\n"; 1103 AppendCommonResponse(&response, cseq, playbackSessionID); 1104 response.append("Connection: close\r\n"); 1105 response.append("\r\n"); 1106 1107 mNetSession->sendRequest(sessionID, response.c_str()); 1108 1109 if (mStopReplyID != 0) { 1110 finishStop(); 1111 } else { 1112 mClient->onDisplayError(IRemoteDisplayClient::kDisplayErrorUnknown); 1113 } 1114 1115 return OK; 1116} 1117 1118void WifiDisplaySource::finishStop() { 1119 ALOGV("finishStop"); 1120 1121#if REQUIRE_HDCP 1122 if (mHDCP != NULL) { 1123 ALOGI("Initiating HDCP shutdown."); 1124 mHDCP->shutdownAsync(); 1125 return; 1126 } 1127#endif 1128 1129 finishStop2(); 1130} 1131 1132void WifiDisplaySource::finishStop2() { 1133 ALOGV("finishStop2"); 1134 1135#if REQUIRE_HDCP 1136 mHDCP->setObserver(NULL); 1137 mHDCPObserver.clear(); 1138 mHDCP.clear(); 1139#endif 1140 1141 disconnectClient(); 1142 1143 if (mSessionID != 0) { 1144 mNetSession->destroySession(mSessionID); 1145 mSessionID = 0; 1146 } 1147 1148 ALOGV("finishStop2 completed."); 1149 1150 status_t err = OK; 1151 1152 sp<AMessage> response = new AMessage; 1153 response->setInt32("err", err); 1154 response->postReply(mStopReplyID); 1155} 1156 1157status_t WifiDisplaySource::onGetParameterRequest( 1158 int32_t sessionID, 1159 int32_t cseq, 1160 const sp<ParsedMessage> &data) { 1161 int32_t playbackSessionID; 1162 sp<PlaybackSession> playbackSession = 1163 findPlaybackSession(data, &playbackSessionID); 1164 1165 if (playbackSession == NULL) { 1166 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 1167 return ERROR_MALFORMED; 1168 } 1169 1170 playbackSession->updateLiveness(); 1171 1172 AString response = "RTSP/1.0 200 OK\r\n"; 1173 AppendCommonResponse(&response, cseq, playbackSessionID); 1174 response.append("\r\n"); 1175 1176 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 1177 return err; 1178} 1179 1180status_t WifiDisplaySource::onSetParameterRequest( 1181 int32_t sessionID, 1182 int32_t cseq, 1183 const sp<ParsedMessage> &data) { 1184 int32_t playbackSessionID; 1185 sp<PlaybackSession> playbackSession = 1186 findPlaybackSession(data, &playbackSessionID); 1187 1188 if (playbackSession == NULL) { 1189 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 1190 return ERROR_MALFORMED; 1191 } 1192 1193 if (strstr(data->getContent(), "wfd_idr_request\r\n")) { 1194 playbackSession->requestIDRFrame(); 1195 } 1196 1197 playbackSession->updateLiveness(); 1198 1199 AString response = "RTSP/1.0 200 OK\r\n"; 1200 AppendCommonResponse(&response, cseq, playbackSessionID); 1201 response.append("\r\n"); 1202 1203 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 1204 return err; 1205} 1206 1207// static 1208void WifiDisplaySource::AppendCommonResponse( 1209 AString *response, int32_t cseq, int32_t playbackSessionID) { 1210 time_t now = time(NULL); 1211 struct tm *now2 = gmtime(&now); 1212 char buf[128]; 1213 strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2); 1214 1215 response->append("Date: "); 1216 response->append(buf); 1217 response->append("\r\n"); 1218 1219 response->append("Server: Mine/1.0\r\n"); 1220 1221 if (cseq >= 0) { 1222 response->append(StringPrintf("CSeq: %d\r\n", cseq)); 1223 } 1224 1225 if (playbackSessionID >= 0ll) { 1226 response->append( 1227 StringPrintf( 1228 "Session: %d;timeout=%lld\r\n", 1229 playbackSessionID, kPlaybackSessionTimeoutSecs)); 1230 } 1231} 1232 1233void WifiDisplaySource::sendErrorResponse( 1234 int32_t sessionID, 1235 const char *errorDetail, 1236 int32_t cseq) { 1237 AString response; 1238 response.append("RTSP/1.0 "); 1239 response.append(errorDetail); 1240 response.append("\r\n"); 1241 1242 AppendCommonResponse(&response, cseq); 1243 1244 response.append("\r\n"); 1245 1246 mNetSession->sendRequest(sessionID, response.c_str()); 1247} 1248 1249int32_t WifiDisplaySource::makeUniquePlaybackSessionID() const { 1250 return rand(); 1251} 1252 1253sp<WifiDisplaySource::PlaybackSession> WifiDisplaySource::findPlaybackSession( 1254 const sp<ParsedMessage> &data, int32_t *playbackSessionID) const { 1255 if (!data->findInt32("session", playbackSessionID)) { 1256 // XXX the older dongles do not always include a "Session:" header. 1257 *playbackSessionID = mClientInfo.mPlaybackSessionID; 1258 return mClientInfo.mPlaybackSession; 1259 } 1260 1261 if (*playbackSessionID != mClientInfo.mPlaybackSessionID) { 1262 return NULL; 1263 } 1264 1265 return mClientInfo.mPlaybackSession; 1266} 1267 1268void WifiDisplaySource::disconnectClient() { 1269 if (mClientInfo.mPlaybackSession != NULL) { 1270 sp<PlaybackSession> playbackSession = mClientInfo.mPlaybackSession; 1271 mClientInfo.mPlaybackSession.clear(); 1272 1273 ALOGI("Destroying PlaybackSession"); 1274 playbackSession->destroy(); 1275 looper()->unregisterHandler(playbackSession->id()); 1276 } 1277 1278 if (mClientSessionID != 0) { 1279 mNetSession->destroySession(mClientSessionID); 1280 mClientSessionID = 0; 1281 } 1282 1283 mClient->onDisplayDisconnected(); 1284} 1285 1286#if REQUIRE_HDCP 1287struct WifiDisplaySource::HDCPObserver : public BnHDCPObserver { 1288 HDCPObserver(const sp<AMessage> ¬ify); 1289 1290 virtual void notify( 1291 int msg, int ext1, int ext2, const Parcel *obj); 1292 1293private: 1294 sp<AMessage> mNotify; 1295 1296 DISALLOW_EVIL_CONSTRUCTORS(HDCPObserver); 1297}; 1298 1299WifiDisplaySource::HDCPObserver::HDCPObserver( 1300 const sp<AMessage> ¬ify) 1301 : mNotify(notify) { 1302} 1303 1304void WifiDisplaySource::HDCPObserver::notify( 1305 int msg, int ext1, int ext2, const Parcel *obj) { 1306 sp<AMessage> notify = mNotify->dup(); 1307 notify->setInt32("msg", msg); 1308 notify->setInt32("ext1", ext1); 1309 notify->setInt32("ext2", ext2); 1310 notify->post(); 1311} 1312 1313status_t WifiDisplaySource::makeHDCP() { 1314 sp<IServiceManager> sm = defaultServiceManager(); 1315 sp<IBinder> binder = sm->getService(String16("media.player")); 1316 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 1317 CHECK(service != NULL); 1318 1319 mHDCP = service->makeHDCP(); 1320 1321 if (mHDCP == NULL) { 1322 return ERROR_UNSUPPORTED; 1323 } 1324 1325 sp<AMessage> notify = new AMessage(kWhatHDCPNotify, id()); 1326 mHDCPObserver = new HDCPObserver(notify); 1327 1328 status_t err = mHDCP->setObserver(mHDCPObserver); 1329 1330 if (err != OK) { 1331 ALOGE("Failed to set HDCP observer."); 1332 1333 mHDCPObserver.clear(); 1334 mHDCP.clear(); 1335 1336 return err; 1337 } 1338 1339 ALOGI("Initiating HDCP negotiation w/ host %s:%d", 1340 mClientInfo.mRemoteIP.c_str(), mHDCPPort); 1341 1342 err = mHDCP->initAsync(mClientInfo.mRemoteIP.c_str(), mHDCPPort); 1343 1344 if (err != OK) { 1345 return err; 1346 } 1347 1348 return OK; 1349} 1350#endif 1351 1352} // namespace android 1353 1354