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