WifiDisplaySource.cpp revision efd9c63dc846dd3dea2c979fe2a9d6770e73f9ac
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 clientRtcp = clientRtp + 1; // XXX 873 } else { 874 badRequest = true; 875 } 876 877 if (badRequest) { 878 sendErrorResponse(sessionID, "400 Bad Request", cseq); 879 return ERROR_MALFORMED; 880 } 881#if 1 882 // The older LG dongles doesn't specify client_port=xxx apparently. 883 } else if (transport == "RTP/AVP/UDP;unicast") { 884 clientRtp = 19000; 885 clientRtcp = clientRtp + 1; 886#endif 887 } else { 888 sendErrorResponse(sessionID, "461 Unsupported Transport", cseq); 889 return ERROR_UNSUPPORTED; 890 } 891 892 int32_t playbackSessionID = makeUniquePlaybackSessionID(); 893 894 sp<AMessage> notify = new AMessage(kWhatPlaybackSessionNotify, id()); 895 notify->setInt32("playbackSessionID", playbackSessionID); 896 notify->setInt32("sessionID", sessionID); 897 898 sp<PlaybackSession> playbackSession = 899 new PlaybackSession( 900 mNetSession, notify, mInterfaceAddr, 901 mClient == NULL, /* legacyMode */ 902#if REQUIRE_HDCP 903 mHDCP 904#else 905 NULL 906#endif 907 ); 908 909 looper()->registerHandler(playbackSession); 910 911 AString uri; 912 data->getRequestField(1, &uri); 913 914 if (strncasecmp("rtsp://", uri.c_str(), 7)) { 915 sendErrorResponse(sessionID, "400 Bad Request", cseq); 916 return ERROR_MALFORMED; 917 } 918 919 if (!(uri.startsWith("rtsp://") && uri.endsWith("/wfd1.0/streamid=0"))) { 920 sendErrorResponse(sessionID, "404 Not found", cseq); 921 return ERROR_MALFORMED; 922 } 923 924 status_t err = playbackSession->init( 925 mClientInfo.mRemoteIP.c_str(), 926 clientRtp, 927 clientRtcp, 928 transportMode); 929 930 if (err != OK) { 931 looper()->unregisterHandler(playbackSession->id()); 932 playbackSession.clear(); 933 } 934 935 switch (err) { 936 case OK: 937 break; 938 case -ENOENT: 939 sendErrorResponse(sessionID, "404 Not Found", cseq); 940 return err; 941 default: 942 sendErrorResponse(sessionID, "403 Forbidden", cseq); 943 return err; 944 } 945 946 mClientInfo.mPlaybackSessionID = playbackSessionID; 947 mClientInfo.mPlaybackSession = playbackSession; 948 949 AString response = "RTSP/1.0 200 OK\r\n"; 950 AppendCommonResponse(&response, cseq, playbackSessionID); 951 952 if (transportMode == PlaybackSession::TRANSPORT_TCP_INTERLEAVED) { 953 response.append( 954 StringPrintf( 955 "Transport: RTP/AVP/TCP;interleaved=%d-%d;", 956 clientRtp, clientRtcp)); 957 } else { 958 int32_t serverRtp = playbackSession->getRTPPort(); 959 960 AString transportString = "UDP"; 961 if (transportMode == PlaybackSession::TRANSPORT_TCP) { 962 transportString = "TCP"; 963 } 964 965 if (clientRtcp >= 0) { 966 response.append( 967 StringPrintf( 968 "Transport: RTP/AVP/%s;unicast;client_port=%d-%d;" 969 "server_port=%d-%d\r\n", 970 transportString.c_str(), 971 clientRtp, clientRtcp, serverRtp, serverRtp + 1)); 972 } else { 973 response.append( 974 StringPrintf( 975 "Transport: RTP/AVP/%s;unicast;client_port=%d;" 976 "server_port=%d\r\n", 977 transportString.c_str(), 978 clientRtp, serverRtp)); 979 } 980 } 981 982 response.append("\r\n"); 983 984 err = mNetSession->sendRequest(sessionID, response.c_str()); 985 986 if (err != OK) { 987 return err; 988 } 989 990 scheduleReaper(); 991 scheduleKeepAlive(sessionID); 992 993 return OK; 994} 995 996status_t WifiDisplaySource::onPlayRequest( 997 int32_t sessionID, 998 int32_t cseq, 999 const sp<ParsedMessage> &data) { 1000 int32_t playbackSessionID; 1001 sp<PlaybackSession> playbackSession = 1002 findPlaybackSession(data, &playbackSessionID); 1003 1004 if (playbackSession == NULL) { 1005 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 1006 return ERROR_MALFORMED; 1007 } 1008 1009 status_t err = playbackSession->play(); 1010 CHECK_EQ(err, (status_t)OK); 1011 1012 AString response = "RTSP/1.0 200 OK\r\n"; 1013 AppendCommonResponse(&response, cseq, playbackSessionID); 1014 response.append("Range: npt=now-\r\n"); 1015 response.append("\r\n"); 1016 1017 err = mNetSession->sendRequest(sessionID, response.c_str()); 1018 1019 if (err != OK) { 1020 return err; 1021 } 1022 1023 playbackSession->finishPlay(); 1024 1025 return OK; 1026} 1027 1028status_t WifiDisplaySource::onPauseRequest( 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 status_t err = playbackSession->pause(); 1042 CHECK_EQ(err, (status_t)OK); 1043 1044 AString response = "RTSP/1.0 200 OK\r\n"; 1045 AppendCommonResponse(&response, cseq, playbackSessionID); 1046 response.append("\r\n"); 1047 1048 err = mNetSession->sendRequest(sessionID, response.c_str()); 1049 1050 return err; 1051} 1052 1053status_t WifiDisplaySource::onTeardownRequest( 1054 int32_t sessionID, 1055 int32_t cseq, 1056 const sp<ParsedMessage> &data) { 1057 int32_t playbackSessionID; 1058 sp<PlaybackSession> playbackSession = 1059 findPlaybackSession(data, &playbackSessionID); 1060 1061 if (playbackSession == NULL) { 1062 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 1063 return ERROR_MALFORMED; 1064 } 1065 1066 AString response = "RTSP/1.0 200 OK\r\n"; 1067 AppendCommonResponse(&response, cseq, playbackSessionID); 1068 response.append("Connection: close\r\n"); 1069 response.append("\r\n"); 1070 1071 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 1072 1073 if (err != OK) { 1074 return err; 1075 } 1076 1077 disconnectClient(UNKNOWN_ERROR); 1078 1079 return OK; 1080} 1081 1082status_t WifiDisplaySource::onGetParameterRequest( 1083 int32_t sessionID, 1084 int32_t cseq, 1085 const sp<ParsedMessage> &data) { 1086 int32_t playbackSessionID; 1087 sp<PlaybackSession> playbackSession = 1088 findPlaybackSession(data, &playbackSessionID); 1089 1090 if (playbackSession == NULL) { 1091 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 1092 return ERROR_MALFORMED; 1093 } 1094 1095 playbackSession->updateLiveness(); 1096 1097 AString response = "RTSP/1.0 200 OK\r\n"; 1098 AppendCommonResponse(&response, cseq, playbackSessionID); 1099 response.append("\r\n"); 1100 1101 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 1102 return err; 1103} 1104 1105status_t WifiDisplaySource::onSetParameterRequest( 1106 int32_t sessionID, 1107 int32_t cseq, 1108 const sp<ParsedMessage> &data) { 1109 int32_t playbackSessionID; 1110 sp<PlaybackSession> playbackSession = 1111 findPlaybackSession(data, &playbackSessionID); 1112 1113 if (playbackSession == NULL) { 1114 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 1115 return ERROR_MALFORMED; 1116 } 1117 1118 if (strstr(data->getContent(), "wfd_idr_request\r\n")) { 1119 playbackSession->requestIDRFrame(); 1120 } 1121 1122 playbackSession->updateLiveness(); 1123 1124 AString response = "RTSP/1.0 200 OK\r\n"; 1125 AppendCommonResponse(&response, cseq, playbackSessionID); 1126 response.append("\r\n"); 1127 1128 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 1129 return err; 1130} 1131 1132// static 1133void WifiDisplaySource::AppendCommonResponse( 1134 AString *response, int32_t cseq, int32_t playbackSessionID) { 1135 time_t now = time(NULL); 1136 struct tm *now2 = gmtime(&now); 1137 char buf[128]; 1138 strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2); 1139 1140 response->append("Date: "); 1141 response->append(buf); 1142 response->append("\r\n"); 1143 1144 response->append("Server: Mine/1.0\r\n"); 1145 1146 if (cseq >= 0) { 1147 response->append(StringPrintf("CSeq: %d\r\n", cseq)); 1148 } 1149 1150 if (playbackSessionID >= 0ll) { 1151 response->append( 1152 StringPrintf( 1153 "Session: %d;timeout=%lld\r\n", 1154 playbackSessionID, kPlaybackSessionTimeoutSecs)); 1155 } 1156} 1157 1158void WifiDisplaySource::sendErrorResponse( 1159 int32_t sessionID, 1160 const char *errorDetail, 1161 int32_t cseq) { 1162 AString response; 1163 response.append("RTSP/1.0 "); 1164 response.append(errorDetail); 1165 response.append("\r\n"); 1166 1167 AppendCommonResponse(&response, cseq); 1168 1169 response.append("\r\n"); 1170 1171 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 1172 CHECK_EQ(err, (status_t)OK); 1173} 1174 1175int32_t WifiDisplaySource::makeUniquePlaybackSessionID() const { 1176 return rand(); 1177} 1178 1179sp<WifiDisplaySource::PlaybackSession> WifiDisplaySource::findPlaybackSession( 1180 const sp<ParsedMessage> &data, int32_t *playbackSessionID) const { 1181 if (!data->findInt32("session", playbackSessionID)) { 1182 // XXX the older dongles do not always include a "Session:" header. 1183 *playbackSessionID = mClientInfo.mPlaybackSessionID; 1184 return mClientInfo.mPlaybackSession; 1185 } 1186 1187 if (*playbackSessionID != mClientInfo.mPlaybackSessionID) { 1188 return NULL; 1189 } 1190 1191 return mClientInfo.mPlaybackSession; 1192} 1193 1194void WifiDisplaySource::disconnectClient(status_t err) { 1195 if (mClientSessionID != 0) { 1196 if (mClientInfo.mPlaybackSession != NULL) { 1197 looper()->unregisterHandler(mClientInfo.mPlaybackSession->id()); 1198 mClientInfo.mPlaybackSession.clear(); 1199 } 1200 1201 mNetSession->destroySession(mClientSessionID); 1202 mClientSessionID = 0; 1203 } 1204 1205 if (mClient != NULL) { 1206 if (err != OK) { 1207 mClient->onDisplayError(IRemoteDisplayClient::kDisplayErrorUnknown); 1208 } else { 1209 mClient->onDisplayDisconnected(); 1210 } 1211 } 1212} 1213 1214#if REQUIRE_HDCP 1215struct WifiDisplaySource::HDCPObserver : public BnHDCPObserver { 1216 HDCPObserver(const sp<AMessage> ¬ify); 1217 1218 virtual void notify( 1219 int msg, int ext1, int ext2, const Parcel *obj); 1220 1221private: 1222 sp<AMessage> mNotify; 1223 1224 DISALLOW_EVIL_CONSTRUCTORS(HDCPObserver); 1225}; 1226 1227WifiDisplaySource::HDCPObserver::HDCPObserver( 1228 const sp<AMessage> ¬ify) 1229 : mNotify(notify) { 1230} 1231 1232void WifiDisplaySource::HDCPObserver::notify( 1233 int msg, int ext1, int ext2, const Parcel *obj) { 1234 sp<AMessage> notify = mNotify->dup(); 1235 notify->setInt32("msg", msg); 1236 notify->setInt32("ext1", ext1); 1237 notify->setInt32("ext2", ext2); 1238 notify->post(); 1239} 1240 1241status_t WifiDisplaySource::makeHDCP() { 1242 sp<IServiceManager> sm = defaultServiceManager(); 1243 sp<IBinder> binder = sm->getService(String16("media.player")); 1244 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 1245 CHECK(service != NULL); 1246 1247 mHDCP = service->makeHDCP(); 1248 1249 if (mHDCP == NULL) { 1250 return ERROR_UNSUPPORTED; 1251 } 1252 1253 sp<AMessage> notify = new AMessage(kWhatHDCPNotify, id()); 1254 mHDCPObserver = new HDCPObserver(notify); 1255 1256 status_t err = mHDCP->setObserver(mHDCPObserver); 1257 1258 if (err != OK) { 1259 ALOGE("Failed to set HDCP observer."); 1260 1261 mHDCPObserver.clear(); 1262 mHDCP.clear(); 1263 1264 return err; 1265 } 1266 1267 ALOGI("initiating HDCP negotiation w/ host %s:%d", 1268 mClientInfo.mRemoteIP.c_str(), mHDCPPort); 1269 1270 err = mHDCP->initAsync(mClientInfo.mRemoteIP.c_str(), mHDCPPort); 1271 1272 if (err != OK) { 1273 return err; 1274 } 1275 1276 return OK; 1277} 1278#endif 1279 1280} // namespace android 1281 1282