WifiDisplaySource.cpp revision 94a483bf2bd699275673d9cd57cb125d48572f30
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#include "Sender.h" 26 27#include <binder/IServiceManager.h> 28#include <gui/IGraphicBufferProducer.h> 29#include <media/IHDCP.h> 30#include <media/IMediaPlayerService.h> 31#include <media/IRemoteDisplayClient.h> 32#include <media/stagefright/foundation/ABuffer.h> 33#include <media/stagefright/foundation/ADebug.h> 34#include <media/stagefright/foundation/AMessage.h> 35#include <media/stagefright/MediaErrors.h> 36 37#include <arpa/inet.h> 38#include <cutils/properties.h> 39 40#include <ctype.h> 41 42namespace android { 43 44WifiDisplaySource::WifiDisplaySource( 45 const sp<ANetworkSession> &netSession, 46 const sp<IRemoteDisplayClient> &client) 47 : mState(INITIALIZED), 48 mNetSession(netSession), 49 mClient(client), 50 mSessionID(0), 51 mStopReplyID(0), 52 mChosenRTPPort(-1), 53 mUsingPCMAudio(false), 54 mClientSessionID(0), 55 mReaperPending(false), 56 mNextCSeq(1), 57 mUsingHDCP(false), 58 mIsHDCP2_0(false), 59 mHDCPPort(0), 60 mHDCPInitializationComplete(false), 61 mSetupTriggerDeferred(false) { 62 mSupportedSourceVideoFormats.enableAll(); 63 64 mSupportedSourceVideoFormats.setNativeResolution( 65 VideoFormats::RESOLUTION_CEA, 5); // 1280x720 p30 66 67 // Disable resolutions above 1080p since the encoder won't be able to 68 // handle them. 69 mSupportedSourceVideoFormats.setResolutionEnabled( 70 VideoFormats::RESOLUTION_VESA, 28, false); // 1920x1200 p30 71 72 mSupportedSourceVideoFormats.setResolutionEnabled( 73 VideoFormats::RESOLUTION_VESA, 29, false); // 1920x1200 p60 74} 75 76WifiDisplaySource::~WifiDisplaySource() { 77} 78 79static status_t PostAndAwaitResponse( 80 const sp<AMessage> &msg, sp<AMessage> *response) { 81 status_t err = msg->postAndAwaitResponse(response); 82 83 if (err != OK) { 84 return err; 85 } 86 87 if (response == NULL || !(*response)->findInt32("err", &err)) { 88 err = OK; 89 } 90 91 return err; 92} 93 94status_t WifiDisplaySource::start(const char *iface) { 95 CHECK_EQ(mState, INITIALIZED); 96 97 sp<AMessage> msg = new AMessage(kWhatStart, id()); 98 msg->setString("iface", iface); 99 100 sp<AMessage> response; 101 return PostAndAwaitResponse(msg, &response); 102} 103 104status_t WifiDisplaySource::stop() { 105 sp<AMessage> msg = new AMessage(kWhatStop, id()); 106 107 sp<AMessage> response; 108 return PostAndAwaitResponse(msg, &response); 109} 110 111status_t WifiDisplaySource::pause() { 112 sp<AMessage> msg = new AMessage(kWhatPause, id()); 113 114 sp<AMessage> response; 115 return PostAndAwaitResponse(msg, &response); 116} 117 118status_t WifiDisplaySource::resume() { 119 sp<AMessage> msg = new AMessage(kWhatResume, id()); 120 121 sp<AMessage> response; 122 return PostAndAwaitResponse(msg, &response); 123} 124 125void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { 126 switch (msg->what()) { 127 case kWhatStart: 128 { 129 uint32_t replyID; 130 CHECK(msg->senderAwaitsResponse(&replyID)); 131 132 AString iface; 133 CHECK(msg->findString("iface", &iface)); 134 135 status_t err = OK; 136 137 ssize_t colonPos = iface.find(":"); 138 139 unsigned long port; 140 141 if (colonPos >= 0) { 142 const char *s = iface.c_str() + colonPos + 1; 143 144 char *end; 145 port = strtoul(s, &end, 10); 146 147 if (end == s || *end != '\0' || port > 65535) { 148 err = -EINVAL; 149 } else { 150 iface.erase(colonPos, iface.size() - colonPos); 151 } 152 } else { 153 port = kWifiDisplayDefaultPort; 154 } 155 156 if (err == OK) { 157 if (inet_aton(iface.c_str(), &mInterfaceAddr) != 0) { 158 sp<AMessage> notify = new AMessage(kWhatRTSPNotify, id()); 159 160 err = mNetSession->createRTSPServer( 161 mInterfaceAddr, port, notify, &mSessionID); 162 } else { 163 err = -EINVAL; 164 } 165 } 166 167 if (err == OK) { 168 mState = AWAITING_CLIENT_CONNECTION; 169 } 170 171 sp<AMessage> response = new AMessage; 172 response->setInt32("err", err); 173 response->postReply(replyID); 174 break; 175 } 176 177 case kWhatRTSPNotify: 178 { 179 int32_t reason; 180 CHECK(msg->findInt32("reason", &reason)); 181 182 switch (reason) { 183 case ANetworkSession::kWhatError: 184 { 185 int32_t sessionID; 186 CHECK(msg->findInt32("sessionID", &sessionID)); 187 188 int32_t err; 189 CHECK(msg->findInt32("err", &err)); 190 191 AString detail; 192 CHECK(msg->findString("detail", &detail)); 193 194 ALOGE("An error occurred in session %d (%d, '%s/%s').", 195 sessionID, 196 err, 197 detail.c_str(), 198 strerror(-err)); 199 200 mNetSession->destroySession(sessionID); 201 202 if (sessionID == mClientSessionID) { 203 mClientSessionID = 0; 204 205 mClient->onDisplayError( 206 IRemoteDisplayClient::kDisplayErrorUnknown); 207 } 208 break; 209 } 210 211 case ANetworkSession::kWhatClientConnected: 212 { 213 int32_t sessionID; 214 CHECK(msg->findInt32("sessionID", &sessionID)); 215 216 if (mClientSessionID > 0) { 217 ALOGW("A client tried to connect, but we already " 218 "have one."); 219 220 mNetSession->destroySession(sessionID); 221 break; 222 } 223 224 CHECK_EQ(mState, AWAITING_CLIENT_CONNECTION); 225 226 CHECK(msg->findString("client-ip", &mClientInfo.mRemoteIP)); 227 CHECK(msg->findString("server-ip", &mClientInfo.mLocalIP)); 228 229 if (mClientInfo.mRemoteIP == mClientInfo.mLocalIP) { 230 // Disallow connections from the local interface 231 // for security reasons. 232 mNetSession->destroySession(sessionID); 233 break; 234 } 235 236 CHECK(msg->findInt32( 237 "server-port", &mClientInfo.mLocalPort)); 238 mClientInfo.mPlaybackSessionID = -1; 239 240 mClientSessionID = sessionID; 241 242 ALOGI("We now have a client (%d) connected.", sessionID); 243 244 mState = AWAITING_CLIENT_SETUP; 245 246 status_t err = sendM1(sessionID); 247 CHECK_EQ(err, (status_t)OK); 248 break; 249 } 250 251 case ANetworkSession::kWhatData: 252 { 253 status_t err = onReceiveClientData(msg); 254 255 if (err != OK) { 256 mClient->onDisplayError( 257 IRemoteDisplayClient::kDisplayErrorUnknown); 258 } 259 260#if 0 261 // testing only. 262 char val[PROPERTY_VALUE_MAX]; 263 if (property_get("media.wfd.trigger", val, NULL)) { 264 if (!strcasecmp(val, "pause") && mState == PLAYING) { 265 mState = PLAYING_TO_PAUSED; 266 sendTrigger(mClientSessionID, TRIGGER_PAUSE); 267 } else if (!strcasecmp(val, "play") && mState == PAUSED) { 268 mState = PAUSED_TO_PLAYING; 269 sendTrigger(mClientSessionID, TRIGGER_PLAY); 270 } 271 } 272#endif 273 break; 274 } 275 276 default: 277 TRESPASS(); 278 } 279 break; 280 } 281 282 case kWhatStop: 283 { 284 CHECK(msg->senderAwaitsResponse(&mStopReplyID)); 285 286 CHECK_LT(mState, AWAITING_CLIENT_TEARDOWN); 287 288 if (mState >= AWAITING_CLIENT_PLAY) { 289 // We have a session, i.e. a previous SETUP succeeded. 290 291 status_t err = sendTrigger( 292 mClientSessionID, TRIGGER_TEARDOWN); 293 294 if (err == OK) { 295 mState = AWAITING_CLIENT_TEARDOWN; 296 297 (new AMessage(kWhatTeardownTriggerTimedOut, id()))->post( 298 kTeardownTriggerTimeouSecs * 1000000ll); 299 300 break; 301 } 302 303 // fall through. 304 } 305 306 finishStop(); 307 break; 308 } 309 310 case kWhatPause: 311 { 312 uint32_t replyID; 313 CHECK(msg->senderAwaitsResponse(&replyID)); 314 315 status_t err = OK; 316 317 if (mState != PLAYING) { 318 err = INVALID_OPERATION; 319 } else { 320 mState = PLAYING_TO_PAUSED; 321 sendTrigger(mClientSessionID, TRIGGER_PAUSE); 322 } 323 324 sp<AMessage> response = new AMessage; 325 response->setInt32("err", err); 326 response->postReply(replyID); 327 break; 328 } 329 330 case kWhatResume: 331 { 332 uint32_t replyID; 333 CHECK(msg->senderAwaitsResponse(&replyID)); 334 335 status_t err = OK; 336 337 if (mState != PAUSED) { 338 err = INVALID_OPERATION; 339 } else { 340 mState = PAUSED_TO_PLAYING; 341 sendTrigger(mClientSessionID, TRIGGER_PLAY); 342 } 343 344 sp<AMessage> response = new AMessage; 345 response->setInt32("err", err); 346 response->postReply(replyID); 347 break; 348 } 349 350 case kWhatReapDeadClients: 351 { 352 mReaperPending = false; 353 354 if (mClientSessionID == 0 355 || mClientInfo.mPlaybackSession == NULL) { 356 break; 357 } 358 359 if (mClientInfo.mPlaybackSession->getLastLifesignUs() 360 + kPlaybackSessionTimeoutUs < ALooper::GetNowUs()) { 361 ALOGI("playback session timed out, reaping."); 362 363 mNetSession->destroySession(mClientSessionID); 364 mClientSessionID = 0; 365 366 mClient->onDisplayError( 367 IRemoteDisplayClient::kDisplayErrorUnknown); 368 } else { 369 scheduleReaper(); 370 } 371 break; 372 } 373 374 case kWhatPlaybackSessionNotify: 375 { 376 int32_t playbackSessionID; 377 CHECK(msg->findInt32("playbackSessionID", &playbackSessionID)); 378 379 int32_t what; 380 CHECK(msg->findInt32("what", &what)); 381 382 if (what == PlaybackSession::kWhatSessionDead) { 383 ALOGI("playback session wants to quit."); 384 385 mClient->onDisplayError( 386 IRemoteDisplayClient::kDisplayErrorUnknown); 387 } else if (what == PlaybackSession::kWhatSessionEstablished) { 388 if (mClient != NULL) { 389 if (!mSinkSupportsVideo) { 390 mClient->onDisplayConnected( 391 NULL, // SurfaceTexture 392 0, // width, 393 0, // height, 394 mUsingHDCP 395 ? IRemoteDisplayClient::kDisplayFlagSecure 396 : 0); 397 } else { 398 size_t width, height; 399 400 CHECK(VideoFormats::GetConfiguration( 401 mChosenVideoResolutionType, 402 mChosenVideoResolutionIndex, 403 &width, 404 &height, 405 NULL /* framesPerSecond */, 406 NULL /* interlaced */)); 407 408 mClient->onDisplayConnected( 409 mClientInfo.mPlaybackSession->getSurfaceTexture(), 410 width, 411 height, 412 mUsingHDCP 413 ? IRemoteDisplayClient::kDisplayFlagSecure 414 : 0); 415 } 416 } 417 418 if (mState == ABOUT_TO_PLAY) { 419 mState = PLAYING; 420 } 421 } else if (what == PlaybackSession::kWhatSessionDestroyed) { 422 disconnectClient2(); 423 } else { 424 CHECK_EQ(what, PlaybackSession::kWhatBinaryData); 425 426 int32_t channel; 427 CHECK(msg->findInt32("channel", &channel)); 428 429 sp<ABuffer> data; 430 CHECK(msg->findBuffer("data", &data)); 431 432 CHECK_LE(channel, 0xffu); 433 CHECK_LE(data->size(), 0xffffu); 434 435 int32_t sessionID; 436 CHECK(msg->findInt32("sessionID", &sessionID)); 437 438 char header[4]; 439 header[0] = '$'; 440 header[1] = channel; 441 header[2] = data->size() >> 8; 442 header[3] = data->size() & 0xff; 443 444 mNetSession->sendRequest( 445 sessionID, header, sizeof(header)); 446 447 mNetSession->sendRequest( 448 sessionID, data->data(), data->size()); 449 } 450 break; 451 } 452 453 case kWhatKeepAlive: 454 { 455 int32_t sessionID; 456 CHECK(msg->findInt32("sessionID", &sessionID)); 457 458 if (mClientSessionID != sessionID) { 459 // Obsolete event, client is already gone. 460 break; 461 } 462 463 sendM16(sessionID); 464 break; 465 } 466 467 case kWhatTeardownTriggerTimedOut: 468 { 469 if (mState == AWAITING_CLIENT_TEARDOWN) { 470 ALOGI("TEARDOWN trigger timed out, forcing disconnection."); 471 472 CHECK_NE(mStopReplyID, 0); 473 finishStop(); 474 break; 475 } 476 break; 477 } 478 479 case kWhatHDCPNotify: 480 { 481 int32_t msgCode, ext1, ext2; 482 CHECK(msg->findInt32("msg", &msgCode)); 483 CHECK(msg->findInt32("ext1", &ext1)); 484 CHECK(msg->findInt32("ext2", &ext2)); 485 486 ALOGI("Saw HDCP notification code %d, ext1 %d, ext2 %d", 487 msgCode, ext1, ext2); 488 489 switch (msgCode) { 490 case HDCPModule::HDCP_INITIALIZATION_COMPLETE: 491 { 492 mHDCPInitializationComplete = true; 493 494 if (mSetupTriggerDeferred) { 495 mSetupTriggerDeferred = false; 496 497 sendTrigger(mClientSessionID, TRIGGER_SETUP); 498 } 499 break; 500 } 501 502 case HDCPModule::HDCP_SHUTDOWN_COMPLETE: 503 case HDCPModule::HDCP_SHUTDOWN_FAILED: 504 { 505 // Ugly hack to make sure that the call to 506 // HDCPObserver::notify is completely handled before 507 // we clear the HDCP instance and unload the shared 508 // library :( 509 (new AMessage(kWhatFinishStop2, id()))->post(300000ll); 510 break; 511 } 512 513 default: 514 { 515 ALOGE("HDCP failure, shutting down."); 516 517 mClient->onDisplayError( 518 IRemoteDisplayClient::kDisplayErrorUnknown); 519 break; 520 } 521 } 522 break; 523 } 524 525 case kWhatFinishStop2: 526 { 527 finishStop2(); 528 break; 529 } 530 531 default: 532 TRESPASS(); 533 } 534} 535 536void WifiDisplaySource::registerResponseHandler( 537 int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func) { 538 ResponseID id; 539 id.mSessionID = sessionID; 540 id.mCSeq = cseq; 541 mResponseHandlers.add(id, func); 542} 543 544status_t WifiDisplaySource::sendM1(int32_t sessionID) { 545 AString request = "OPTIONS * RTSP/1.0\r\n"; 546 AppendCommonResponse(&request, mNextCSeq); 547 548 request.append( 549 "Require: org.wfa.wfd1.0\r\n" 550 "\r\n"); 551 552 status_t err = 553 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 554 555 if (err != OK) { 556 return err; 557 } 558 559 registerResponseHandler( 560 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM1Response); 561 562 ++mNextCSeq; 563 564 return OK; 565} 566 567status_t WifiDisplaySource::sendM3(int32_t sessionID) { 568 AString body = 569 "wfd_content_protection\r\n" 570 "wfd_video_formats\r\n" 571 "wfd_audio_codecs\r\n" 572 "wfd_client_rtp_ports\r\n"; 573 574 AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 575 AppendCommonResponse(&request, mNextCSeq); 576 577 request.append("Content-Type: text/parameters\r\n"); 578 request.append(StringPrintf("Content-Length: %d\r\n", body.size())); 579 request.append("\r\n"); 580 request.append(body); 581 582 status_t err = 583 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 584 585 if (err != OK) { 586 return err; 587 } 588 589 registerResponseHandler( 590 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM3Response); 591 592 ++mNextCSeq; 593 594 return OK; 595} 596 597status_t WifiDisplaySource::sendM4(int32_t sessionID) { 598 CHECK_EQ(sessionID, mClientSessionID); 599 600 AString transportString = "UDP"; 601 602 char val[PROPERTY_VALUE_MAX]; 603 if (property_get("media.wfd.enable-tcp", val, NULL) 604 && (!strcasecmp("true", val) || !strcmp("1", val))) { 605 ALOGI("Using TCP transport."); 606 transportString = "TCP"; 607 } 608 609 AString body; 610 611 if (mSinkSupportsVideo) { 612 body.append("wfd_video_formats: "); 613 614 VideoFormats chosenVideoFormat; 615 chosenVideoFormat.disableAll(); 616 chosenVideoFormat.setNativeResolution( 617 mChosenVideoResolutionType, mChosenVideoResolutionIndex); 618 619 body.append(chosenVideoFormat.getFormatSpec()); 620 body.append("\r\n"); 621 } 622 623 if (mSinkSupportsAudio) { 624 body.append( 625 StringPrintf("wfd_audio_codecs: %s\r\n", 626 (mUsingPCMAudio 627 ? "LPCM 00000002 00" // 2 ch PCM 48kHz 628 : "AAC 00000001 00"))); // 2 ch AAC 48kHz 629 } 630 631 body.append( 632 StringPrintf( 633 "wfd_presentation_URL: rtsp://%s/wfd1.0/streamid=0 none\r\n" 634 "wfd_client_rtp_ports: RTP/AVP/%s;unicast %d 0 mode=play\r\n", 635 mClientInfo.mLocalIP.c_str(), 636 transportString.c_str(), 637 mChosenRTPPort)); 638 639 AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 640 AppendCommonResponse(&request, mNextCSeq); 641 642 request.append("Content-Type: text/parameters\r\n"); 643 request.append(StringPrintf("Content-Length: %d\r\n", body.size())); 644 request.append("\r\n"); 645 request.append(body); 646 647 status_t err = 648 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 649 650 if (err != OK) { 651 return err; 652 } 653 654 registerResponseHandler( 655 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM4Response); 656 657 ++mNextCSeq; 658 659 return OK; 660} 661 662status_t WifiDisplaySource::sendTrigger( 663 int32_t sessionID, TriggerType triggerType) { 664 AString body = "wfd_trigger_method: "; 665 switch (triggerType) { 666 case TRIGGER_SETUP: 667 body.append("SETUP"); 668 break; 669 case TRIGGER_TEARDOWN: 670 ALOGI("Sending TEARDOWN trigger."); 671 body.append("TEARDOWN"); 672 break; 673 case TRIGGER_PAUSE: 674 body.append("PAUSE"); 675 break; 676 case TRIGGER_PLAY: 677 body.append("PLAY"); 678 break; 679 default: 680 TRESPASS(); 681 } 682 683 body.append("\r\n"); 684 685 AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 686 AppendCommonResponse(&request, mNextCSeq); 687 688 request.append("Content-Type: text/parameters\r\n"); 689 request.append(StringPrintf("Content-Length: %d\r\n", body.size())); 690 request.append("\r\n"); 691 request.append(body); 692 693 status_t err = 694 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 695 696 if (err != OK) { 697 return err; 698 } 699 700 registerResponseHandler( 701 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM5Response); 702 703 ++mNextCSeq; 704 705 return OK; 706} 707 708status_t WifiDisplaySource::sendM16(int32_t sessionID) { 709 AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 710 AppendCommonResponse(&request, mNextCSeq); 711 712 CHECK_EQ(sessionID, mClientSessionID); 713 request.append( 714 StringPrintf("Session: %d\r\n", mClientInfo.mPlaybackSessionID)); 715 request.append("\r\n"); // Empty body 716 717 status_t err = 718 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 719 720 if (err != OK) { 721 return err; 722 } 723 724 registerResponseHandler( 725 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM16Response); 726 727 ++mNextCSeq; 728 729 return OK; 730} 731 732status_t WifiDisplaySource::onReceiveM1Response( 733 int32_t sessionID, const sp<ParsedMessage> &msg) { 734 int32_t statusCode; 735 if (!msg->getStatusCode(&statusCode)) { 736 return ERROR_MALFORMED; 737 } 738 739 if (statusCode != 200) { 740 return ERROR_UNSUPPORTED; 741 } 742 743 return OK; 744} 745 746// sink_audio_list := ("LPCM"|"AAC"|"AC3" HEXDIGIT*8 HEXDIGIT*2) 747// (", " sink_audio_list)* 748static void GetAudioModes(const char *s, const char *prefix, uint32_t *modes) { 749 *modes = 0; 750 751 size_t prefixLen = strlen(prefix); 752 753 while (*s != '0') { 754 if (!strncmp(s, prefix, prefixLen) && s[prefixLen] == ' ') { 755 unsigned latency; 756 if (sscanf(&s[prefixLen + 1], "%08x %02x", modes, &latency) != 2) { 757 *modes = 0; 758 } 759 760 return; 761 } 762 763 char *commaPos = strchr(s, ','); 764 if (commaPos != NULL) { 765 s = commaPos + 1; 766 767 while (isspace(*s)) { 768 ++s; 769 } 770 } else { 771 break; 772 } 773 } 774} 775 776status_t WifiDisplaySource::onReceiveM3Response( 777 int32_t sessionID, const sp<ParsedMessage> &msg) { 778 int32_t statusCode; 779 if (!msg->getStatusCode(&statusCode)) { 780 return ERROR_MALFORMED; 781 } 782 783 if (statusCode != 200) { 784 return ERROR_UNSUPPORTED; 785 } 786 787 sp<Parameters> params = 788 Parameters::Parse(msg->getContent(), strlen(msg->getContent())); 789 790 if (params == NULL) { 791 return ERROR_MALFORMED; 792 } 793 794 AString value; 795 if (!params->findParameter("wfd_client_rtp_ports", &value)) { 796 ALOGE("Sink doesn't report its choice of wfd_client_rtp_ports."); 797 return ERROR_MALFORMED; 798 } 799 800 unsigned port0, port1; 801 if (sscanf(value.c_str(), 802 "RTP/AVP/UDP;unicast %u %u mode=play", 803 &port0, 804 &port1) != 2 805 || port0 == 0 || port0 > 65535 || port1 != 0) { 806 ALOGE("Sink chose its wfd_client_rtp_ports poorly (%s)", 807 value.c_str()); 808 809 return ERROR_MALFORMED; 810 } 811 812 mChosenRTPPort = port0; 813 814 if (!params->findParameter("wfd_video_formats", &value)) { 815 ALOGE("Sink doesn't report its choice of wfd_video_formats."); 816 return ERROR_MALFORMED; 817 } 818 819 mSinkSupportsVideo = false; 820 821 if (!(value == "none")) { 822 mSinkSupportsVideo = true; 823 if (!mSupportedSinkVideoFormats.parseFormatSpec(value.c_str())) { 824 ALOGE("Failed to parse sink provided wfd_video_formats (%s)", 825 value.c_str()); 826 827 return ERROR_MALFORMED; 828 } 829 830 if (!VideoFormats::PickBestFormat( 831 mSupportedSinkVideoFormats, 832 mSupportedSourceVideoFormats, 833 &mChosenVideoResolutionType, 834 &mChosenVideoResolutionIndex)) { 835 ALOGE("Sink and source share no commonly supported video " 836 "formats."); 837 838 return ERROR_UNSUPPORTED; 839 } 840 841 size_t width, height, framesPerSecond; 842 bool interlaced; 843 CHECK(VideoFormats::GetConfiguration( 844 mChosenVideoResolutionType, 845 mChosenVideoResolutionIndex, 846 &width, 847 &height, 848 &framesPerSecond, 849 &interlaced)); 850 851 ALOGI("Picked video resolution %u x %u %c%u", 852 width, height, interlaced ? 'i' : 'p', framesPerSecond); 853 } else { 854 ALOGI("Sink doesn't support video at all."); 855 } 856 857 if (!params->findParameter("wfd_audio_codecs", &value)) { 858 ALOGE("Sink doesn't report its choice of wfd_audio_codecs."); 859 return ERROR_MALFORMED; 860 } 861 862 mSinkSupportsAudio = false; 863 864 if (!(value == "none")) { 865 mSinkSupportsAudio = true; 866 867 uint32_t modes; 868 GetAudioModes(value.c_str(), "AAC", &modes); 869 870 bool supportsAAC = (modes & 1) != 0; // AAC 2ch 48kHz 871 872 GetAudioModes(value.c_str(), "LPCM", &modes); 873 874 bool supportsPCM = (modes & 2) != 0; // LPCM 2ch 48kHz 875 876 char val[PROPERTY_VALUE_MAX]; 877 if (supportsPCM 878 && property_get("media.wfd.use-pcm-audio", val, NULL) 879 && (!strcasecmp("true", val) || !strcmp("1", val))) { 880 ALOGI("Using PCM audio."); 881 mUsingPCMAudio = true; 882 } else if (supportsAAC) { 883 ALOGI("Using AAC audio."); 884 mUsingPCMAudio = false; 885 } else if (supportsPCM) { 886 ALOGI("Using PCM audio."); 887 mUsingPCMAudio = true; 888 } else { 889 ALOGI("Sink doesn't support an audio format we do."); 890 return ERROR_UNSUPPORTED; 891 } 892 } else { 893 ALOGI("Sink doesn't support audio at all."); 894 } 895 896 if (!mSinkSupportsVideo && !mSinkSupportsAudio) { 897 ALOGE("Sink supports neither video nor audio..."); 898 return ERROR_UNSUPPORTED; 899 } 900 901 mUsingHDCP = false; 902 if (!params->findParameter("wfd_content_protection", &value)) { 903 ALOGI("Sink doesn't appear to support content protection."); 904 } else if (value == "none") { 905 ALOGI("Sink does not support content protection."); 906 } else { 907 mUsingHDCP = true; 908 909 bool isHDCP2_0 = false; 910 if (value.startsWith("HDCP2.0 ")) { 911 isHDCP2_0 = true; 912 } else if (!value.startsWith("HDCP2.1 ")) { 913 ALOGE("malformed wfd_content_protection: '%s'", value.c_str()); 914 915 return ERROR_MALFORMED; 916 } 917 918 int32_t hdcpPort; 919 if (!ParsedMessage::GetInt32Attribute( 920 value.c_str() + 8, "port", &hdcpPort) 921 || hdcpPort < 1 || hdcpPort > 65535) { 922 return ERROR_MALFORMED; 923 } 924 925 mIsHDCP2_0 = isHDCP2_0; 926 mHDCPPort = hdcpPort; 927 928 status_t err = makeHDCP(); 929 if (err != OK) { 930 ALOGE("Unable to instantiate HDCP component. " 931 "Not using HDCP after all."); 932 933 mUsingHDCP = false; 934 } 935 } 936 937 return sendM4(sessionID); 938} 939 940status_t WifiDisplaySource::onReceiveM4Response( 941 int32_t sessionID, const sp<ParsedMessage> &msg) { 942 int32_t statusCode; 943 if (!msg->getStatusCode(&statusCode)) { 944 return ERROR_MALFORMED; 945 } 946 947 if (statusCode != 200) { 948 return ERROR_UNSUPPORTED; 949 } 950 951 if (mUsingHDCP && !mHDCPInitializationComplete) { 952 ALOGI("Deferring SETUP trigger until HDCP initialization completes."); 953 954 mSetupTriggerDeferred = true; 955 return OK; 956 } 957 958 return sendTrigger(sessionID, TRIGGER_SETUP); 959} 960 961status_t WifiDisplaySource::onReceiveM5Response( 962 int32_t sessionID, const sp<ParsedMessage> &msg) { 963 int32_t statusCode; 964 if (!msg->getStatusCode(&statusCode)) { 965 return ERROR_MALFORMED; 966 } 967 968 if (statusCode != 200) { 969 return ERROR_UNSUPPORTED; 970 } 971 972 return OK; 973} 974 975status_t WifiDisplaySource::onReceiveM16Response( 976 int32_t sessionID, const sp<ParsedMessage> &msg) { 977 // If only the response was required to include a "Session:" header... 978 979 CHECK_EQ(sessionID, mClientSessionID); 980 981 if (mClientInfo.mPlaybackSession != NULL) { 982 mClientInfo.mPlaybackSession->updateLiveness(); 983 984 scheduleKeepAlive(sessionID); 985 } 986 987 return OK; 988} 989 990void WifiDisplaySource::scheduleReaper() { 991 if (mReaperPending) { 992 return; 993 } 994 995 mReaperPending = true; 996 (new AMessage(kWhatReapDeadClients, id()))->post(kReaperIntervalUs); 997} 998 999void WifiDisplaySource::scheduleKeepAlive(int32_t sessionID) { 1000 // We need to send updates at least 5 secs before the timeout is set to 1001 // expire, make sure the timeout is greater than 5 secs to begin with. 1002 CHECK_GT(kPlaybackSessionTimeoutUs, 5000000ll); 1003 1004 sp<AMessage> msg = new AMessage(kWhatKeepAlive, id()); 1005 msg->setInt32("sessionID", sessionID); 1006 msg->post(kPlaybackSessionTimeoutUs - 5000000ll); 1007} 1008 1009status_t WifiDisplaySource::onReceiveClientData(const sp<AMessage> &msg) { 1010 int32_t sessionID; 1011 CHECK(msg->findInt32("sessionID", &sessionID)); 1012 1013 sp<RefBase> obj; 1014 CHECK(msg->findObject("data", &obj)); 1015 1016 sp<ParsedMessage> data = 1017 static_cast<ParsedMessage *>(obj.get()); 1018 1019 ALOGV("session %d received '%s'", 1020 sessionID, data->debugString().c_str()); 1021 1022 AString method; 1023 AString uri; 1024 data->getRequestField(0, &method); 1025 1026 int32_t cseq; 1027 if (!data->findInt32("cseq", &cseq)) { 1028 sendErrorResponse(sessionID, "400 Bad Request", -1 /* cseq */); 1029 return ERROR_MALFORMED; 1030 } 1031 1032 if (method.startsWith("RTSP/")) { 1033 // This is a response. 1034 1035 ResponseID id; 1036 id.mSessionID = sessionID; 1037 id.mCSeq = cseq; 1038 1039 ssize_t index = mResponseHandlers.indexOfKey(id); 1040 1041 if (index < 0) { 1042 ALOGW("Received unsolicited server response, cseq %d", cseq); 1043 return ERROR_MALFORMED; 1044 } 1045 1046 HandleRTSPResponseFunc func = mResponseHandlers.valueAt(index); 1047 mResponseHandlers.removeItemsAt(index); 1048 1049 status_t err = (this->*func)(sessionID, data); 1050 1051 if (err != OK) { 1052 ALOGW("Response handler for session %d, cseq %d returned " 1053 "err %d (%s)", 1054 sessionID, cseq, err, strerror(-err)); 1055 1056 return err; 1057 } 1058 1059 return OK; 1060 } 1061 1062 AString version; 1063 data->getRequestField(2, &version); 1064 if (!(version == AString("RTSP/1.0"))) { 1065 sendErrorResponse(sessionID, "505 RTSP Version not supported", cseq); 1066 return ERROR_UNSUPPORTED; 1067 } 1068 1069 status_t err; 1070 if (method == "OPTIONS") { 1071 err = onOptionsRequest(sessionID, cseq, data); 1072 } else if (method == "SETUP") { 1073 err = onSetupRequest(sessionID, cseq, data); 1074 } else if (method == "PLAY") { 1075 err = onPlayRequest(sessionID, cseq, data); 1076 } else if (method == "PAUSE") { 1077 err = onPauseRequest(sessionID, cseq, data); 1078 } else if (method == "TEARDOWN") { 1079 err = onTeardownRequest(sessionID, cseq, data); 1080 } else if (method == "GET_PARAMETER") { 1081 err = onGetParameterRequest(sessionID, cseq, data); 1082 } else if (method == "SET_PARAMETER") { 1083 err = onSetParameterRequest(sessionID, cseq, data); 1084 } else { 1085 sendErrorResponse(sessionID, "405 Method Not Allowed", cseq); 1086 1087 err = ERROR_UNSUPPORTED; 1088 } 1089 1090 return err; 1091} 1092 1093status_t WifiDisplaySource::onOptionsRequest( 1094 int32_t sessionID, 1095 int32_t cseq, 1096 const sp<ParsedMessage> &data) { 1097 int32_t playbackSessionID; 1098 sp<PlaybackSession> playbackSession = 1099 findPlaybackSession(data, &playbackSessionID); 1100 1101 if (playbackSession != NULL) { 1102 playbackSession->updateLiveness(); 1103 } 1104 1105 AString response = "RTSP/1.0 200 OK\r\n"; 1106 AppendCommonResponse(&response, cseq); 1107 1108 response.append( 1109 "Public: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, " 1110 "GET_PARAMETER, SET_PARAMETER\r\n"); 1111 1112 response.append("\r\n"); 1113 1114 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 1115 1116 if (err == OK) { 1117 err = sendM3(sessionID); 1118 } 1119 1120 return err; 1121} 1122 1123status_t WifiDisplaySource::onSetupRequest( 1124 int32_t sessionID, 1125 int32_t cseq, 1126 const sp<ParsedMessage> &data) { 1127 CHECK_EQ(sessionID, mClientSessionID); 1128 if (mClientInfo.mPlaybackSessionID != -1) { 1129 // We only support a single playback session per client. 1130 // This is due to the reversed keep-alive design in the wfd specs... 1131 sendErrorResponse(sessionID, "400 Bad Request", cseq); 1132 return ERROR_MALFORMED; 1133 } 1134 1135 AString transport; 1136 if (!data->findString("transport", &transport)) { 1137 sendErrorResponse(sessionID, "400 Bad Request", cseq); 1138 return ERROR_MALFORMED; 1139 } 1140 1141 Sender::TransportMode transportMode = Sender::TRANSPORT_UDP; 1142 1143 int clientRtp, clientRtcp; 1144 if (transport.startsWith("RTP/AVP/TCP;")) { 1145 AString interleaved; 1146 if (ParsedMessage::GetAttribute( 1147 transport.c_str(), "interleaved", &interleaved) 1148 && sscanf(interleaved.c_str(), "%d-%d", 1149 &clientRtp, &clientRtcp) == 2) { 1150 transportMode = Sender::TRANSPORT_TCP_INTERLEAVED; 1151 } else { 1152 bool badRequest = false; 1153 1154 AString clientPort; 1155 if (!ParsedMessage::GetAttribute( 1156 transport.c_str(), "client_port", &clientPort)) { 1157 badRequest = true; 1158 } else if (sscanf(clientPort.c_str(), "%d-%d", 1159 &clientRtp, &clientRtcp) == 2) { 1160 } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) { 1161 // No RTCP. 1162 clientRtcp = -1; 1163 } else { 1164 badRequest = true; 1165 } 1166 1167 if (badRequest) { 1168 sendErrorResponse(sessionID, "400 Bad Request", cseq); 1169 return ERROR_MALFORMED; 1170 } 1171 1172 transportMode = Sender::TRANSPORT_TCP; 1173 } 1174 } else if (transport.startsWith("RTP/AVP;unicast;") 1175 || transport.startsWith("RTP/AVP/UDP;unicast;")) { 1176 bool badRequest = false; 1177 1178 AString clientPort; 1179 if (!ParsedMessage::GetAttribute( 1180 transport.c_str(), "client_port", &clientPort)) { 1181 badRequest = true; 1182 } else if (sscanf(clientPort.c_str(), "%d-%d", 1183 &clientRtp, &clientRtcp) == 2) { 1184 } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) { 1185 // No RTCP. 1186 clientRtcp = -1; 1187 } else { 1188 badRequest = true; 1189 } 1190 1191 if (badRequest) { 1192 sendErrorResponse(sessionID, "400 Bad Request", cseq); 1193 return ERROR_MALFORMED; 1194 } 1195#if 1 1196 // The older LG dongles doesn't specify client_port=xxx apparently. 1197 } else if (transport == "RTP/AVP/UDP;unicast") { 1198 clientRtp = 19000; 1199 clientRtcp = -1; 1200#endif 1201 } else { 1202 sendErrorResponse(sessionID, "461 Unsupported Transport", cseq); 1203 return ERROR_UNSUPPORTED; 1204 } 1205 1206 int32_t playbackSessionID = makeUniquePlaybackSessionID(); 1207 1208 sp<AMessage> notify = new AMessage(kWhatPlaybackSessionNotify, id()); 1209 notify->setInt32("playbackSessionID", playbackSessionID); 1210 notify->setInt32("sessionID", sessionID); 1211 1212 sp<PlaybackSession> playbackSession = 1213 new PlaybackSession( 1214 mNetSession, notify, mInterfaceAddr, mHDCP); 1215 1216 looper()->registerHandler(playbackSession); 1217 1218 AString uri; 1219 data->getRequestField(1, &uri); 1220 1221 if (strncasecmp("rtsp://", uri.c_str(), 7)) { 1222 sendErrorResponse(sessionID, "400 Bad Request", cseq); 1223 return ERROR_MALFORMED; 1224 } 1225 1226 if (!(uri.startsWith("rtsp://") && uri.endsWith("/wfd1.0/streamid=0"))) { 1227 sendErrorResponse(sessionID, "404 Not found", cseq); 1228 return ERROR_MALFORMED; 1229 } 1230 1231 status_t err = playbackSession->init( 1232 mClientInfo.mRemoteIP.c_str(), 1233 clientRtp, 1234 clientRtcp, 1235 transportMode, 1236 mSinkSupportsAudio, 1237 mUsingPCMAudio, 1238 mSinkSupportsVideo, 1239 mChosenVideoResolutionType, 1240 mChosenVideoResolutionIndex); 1241 1242 if (err != OK) { 1243 looper()->unregisterHandler(playbackSession->id()); 1244 playbackSession.clear(); 1245 } 1246 1247 switch (err) { 1248 case OK: 1249 break; 1250 case -ENOENT: 1251 sendErrorResponse(sessionID, "404 Not Found", cseq); 1252 return err; 1253 default: 1254 sendErrorResponse(sessionID, "403 Forbidden", cseq); 1255 return err; 1256 } 1257 1258 mClientInfo.mPlaybackSessionID = playbackSessionID; 1259 mClientInfo.mPlaybackSession = playbackSession; 1260 1261 AString response = "RTSP/1.0 200 OK\r\n"; 1262 AppendCommonResponse(&response, cseq, playbackSessionID); 1263 1264 if (transportMode == Sender::TRANSPORT_TCP_INTERLEAVED) { 1265 response.append( 1266 StringPrintf( 1267 "Transport: RTP/AVP/TCP;interleaved=%d-%d;", 1268 clientRtp, clientRtcp)); 1269 } else { 1270 int32_t serverRtp = playbackSession->getRTPPort(); 1271 1272 AString transportString = "UDP"; 1273 if (transportMode == Sender::TRANSPORT_TCP) { 1274 transportString = "TCP"; 1275 } 1276 1277 if (clientRtcp >= 0) { 1278 response.append( 1279 StringPrintf( 1280 "Transport: RTP/AVP/%s;unicast;client_port=%d-%d;" 1281 "server_port=%d-%d\r\n", 1282 transportString.c_str(), 1283 clientRtp, clientRtcp, serverRtp, serverRtp + 1)); 1284 } else { 1285 response.append( 1286 StringPrintf( 1287 "Transport: RTP/AVP/%s;unicast;client_port=%d;" 1288 "server_port=%d\r\n", 1289 transportString.c_str(), 1290 clientRtp, serverRtp)); 1291 } 1292 } 1293 1294 response.append("\r\n"); 1295 1296 err = mNetSession->sendRequest(sessionID, response.c_str()); 1297 1298 if (err != OK) { 1299 return err; 1300 } 1301 1302 mState = AWAITING_CLIENT_PLAY; 1303 1304 scheduleReaper(); 1305 scheduleKeepAlive(sessionID); 1306 1307 return OK; 1308} 1309 1310status_t WifiDisplaySource::onPlayRequest( 1311 int32_t sessionID, 1312 int32_t cseq, 1313 const sp<ParsedMessage> &data) { 1314 int32_t playbackSessionID; 1315 sp<PlaybackSession> playbackSession = 1316 findPlaybackSession(data, &playbackSessionID); 1317 1318 if (playbackSession == NULL) { 1319 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 1320 return ERROR_MALFORMED; 1321 } 1322 1323 ALOGI("Received PLAY request."); 1324 1325 status_t err = playbackSession->play(); 1326 CHECK_EQ(err, (status_t)OK); 1327 1328 AString response = "RTSP/1.0 200 OK\r\n"; 1329 AppendCommonResponse(&response, cseq, playbackSessionID); 1330 response.append("Range: npt=now-\r\n"); 1331 response.append("\r\n"); 1332 1333 err = mNetSession->sendRequest(sessionID, response.c_str()); 1334 1335 if (err != OK) { 1336 return err; 1337 } 1338 1339 if (mState == PAUSED_TO_PLAYING) { 1340 mState = PLAYING; 1341 return OK; 1342 } 1343 1344 playbackSession->finishPlay(); 1345 1346 CHECK_EQ(mState, AWAITING_CLIENT_PLAY); 1347 mState = ABOUT_TO_PLAY; 1348 1349 return OK; 1350} 1351 1352status_t WifiDisplaySource::onPauseRequest( 1353 int32_t sessionID, 1354 int32_t cseq, 1355 const sp<ParsedMessage> &data) { 1356 int32_t playbackSessionID; 1357 sp<PlaybackSession> playbackSession = 1358 findPlaybackSession(data, &playbackSessionID); 1359 1360 if (playbackSession == NULL) { 1361 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 1362 return ERROR_MALFORMED; 1363 } 1364 1365 ALOGI("Received PAUSE request."); 1366 1367 if (mState != PLAYING_TO_PAUSED) { 1368 return INVALID_OPERATION; 1369 } 1370 1371 status_t err = playbackSession->pause(); 1372 CHECK_EQ(err, (status_t)OK); 1373 1374 AString response = "RTSP/1.0 200 OK\r\n"; 1375 AppendCommonResponse(&response, cseq, playbackSessionID); 1376 response.append("\r\n"); 1377 1378 err = mNetSession->sendRequest(sessionID, response.c_str()); 1379 1380 if (err != OK) { 1381 return err; 1382 } 1383 1384 mState = PAUSED; 1385 1386 return err; 1387} 1388 1389status_t WifiDisplaySource::onTeardownRequest( 1390 int32_t sessionID, 1391 int32_t cseq, 1392 const sp<ParsedMessage> &data) { 1393 ALOGI("Received TEARDOWN request."); 1394 1395 int32_t playbackSessionID; 1396 sp<PlaybackSession> playbackSession = 1397 findPlaybackSession(data, &playbackSessionID); 1398 1399 if (playbackSession == NULL) { 1400 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 1401 return ERROR_MALFORMED; 1402 } 1403 1404 AString response = "RTSP/1.0 200 OK\r\n"; 1405 AppendCommonResponse(&response, cseq, playbackSessionID); 1406 response.append("Connection: close\r\n"); 1407 response.append("\r\n"); 1408 1409 mNetSession->sendRequest(sessionID, response.c_str()); 1410 1411 if (mState == AWAITING_CLIENT_TEARDOWN) { 1412 CHECK_NE(mStopReplyID, 0); 1413 finishStop(); 1414 } else { 1415 mClient->onDisplayError(IRemoteDisplayClient::kDisplayErrorUnknown); 1416 } 1417 1418 return OK; 1419} 1420 1421void WifiDisplaySource::finishStop() { 1422 ALOGV("finishStop"); 1423 1424 mState = STOPPING; 1425 1426 disconnectClientAsync(); 1427} 1428 1429void WifiDisplaySource::finishStopAfterDisconnectingClient() { 1430 ALOGV("finishStopAfterDisconnectingClient"); 1431 1432 if (mHDCP != NULL) { 1433 ALOGI("Initiating HDCP shutdown."); 1434 mHDCP->shutdownAsync(); 1435 return; 1436 } 1437 1438 finishStop2(); 1439} 1440 1441void WifiDisplaySource::finishStop2() { 1442 ALOGV("finishStop2"); 1443 1444 if (mHDCP != NULL) { 1445 mHDCP->setObserver(NULL); 1446 mHDCPObserver.clear(); 1447 mHDCP.clear(); 1448 } 1449 1450 if (mSessionID != 0) { 1451 mNetSession->destroySession(mSessionID); 1452 mSessionID = 0; 1453 } 1454 1455 ALOGI("We're stopped."); 1456 mState = STOPPED; 1457 1458 status_t err = OK; 1459 1460 sp<AMessage> response = new AMessage; 1461 response->setInt32("err", err); 1462 response->postReply(mStopReplyID); 1463} 1464 1465status_t WifiDisplaySource::onGetParameterRequest( 1466 int32_t sessionID, 1467 int32_t cseq, 1468 const sp<ParsedMessage> &data) { 1469 int32_t playbackSessionID; 1470 sp<PlaybackSession> playbackSession = 1471 findPlaybackSession(data, &playbackSessionID); 1472 1473 if (playbackSession == NULL) { 1474 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 1475 return ERROR_MALFORMED; 1476 } 1477 1478 playbackSession->updateLiveness(); 1479 1480 AString response = "RTSP/1.0 200 OK\r\n"; 1481 AppendCommonResponse(&response, cseq, playbackSessionID); 1482 response.append("\r\n"); 1483 1484 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 1485 return err; 1486} 1487 1488status_t WifiDisplaySource::onSetParameterRequest( 1489 int32_t sessionID, 1490 int32_t cseq, 1491 const sp<ParsedMessage> &data) { 1492 int32_t playbackSessionID; 1493 sp<PlaybackSession> playbackSession = 1494 findPlaybackSession(data, &playbackSessionID); 1495 1496 if (playbackSession == NULL) { 1497 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 1498 return ERROR_MALFORMED; 1499 } 1500 1501 if (strstr(data->getContent(), "wfd_idr_request\r\n")) { 1502 playbackSession->requestIDRFrame(); 1503 } 1504 1505 playbackSession->updateLiveness(); 1506 1507 AString response = "RTSP/1.0 200 OK\r\n"; 1508 AppendCommonResponse(&response, cseq, playbackSessionID); 1509 response.append("\r\n"); 1510 1511 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 1512 return err; 1513} 1514 1515// static 1516void WifiDisplaySource::AppendCommonResponse( 1517 AString *response, int32_t cseq, int32_t playbackSessionID) { 1518 time_t now = time(NULL); 1519 struct tm *now2 = gmtime(&now); 1520 char buf[128]; 1521 strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2); 1522 1523 response->append("Date: "); 1524 response->append(buf); 1525 response->append("\r\n"); 1526 1527 response->append("Server: Mine/1.0\r\n"); 1528 1529 if (cseq >= 0) { 1530 response->append(StringPrintf("CSeq: %d\r\n", cseq)); 1531 } 1532 1533 if (playbackSessionID >= 0ll) { 1534 response->append( 1535 StringPrintf( 1536 "Session: %d;timeout=%lld\r\n", 1537 playbackSessionID, kPlaybackSessionTimeoutSecs)); 1538 } 1539} 1540 1541void WifiDisplaySource::sendErrorResponse( 1542 int32_t sessionID, 1543 const char *errorDetail, 1544 int32_t cseq) { 1545 AString response; 1546 response.append("RTSP/1.0 "); 1547 response.append(errorDetail); 1548 response.append("\r\n"); 1549 1550 AppendCommonResponse(&response, cseq); 1551 1552 response.append("\r\n"); 1553 1554 mNetSession->sendRequest(sessionID, response.c_str()); 1555} 1556 1557int32_t WifiDisplaySource::makeUniquePlaybackSessionID() const { 1558 return rand(); 1559} 1560 1561sp<WifiDisplaySource::PlaybackSession> WifiDisplaySource::findPlaybackSession( 1562 const sp<ParsedMessage> &data, int32_t *playbackSessionID) const { 1563 if (!data->findInt32("session", playbackSessionID)) { 1564 // XXX the older dongles do not always include a "Session:" header. 1565 *playbackSessionID = mClientInfo.mPlaybackSessionID; 1566 return mClientInfo.mPlaybackSession; 1567 } 1568 1569 if (*playbackSessionID != mClientInfo.mPlaybackSessionID) { 1570 return NULL; 1571 } 1572 1573 return mClientInfo.mPlaybackSession; 1574} 1575 1576void WifiDisplaySource::disconnectClientAsync() { 1577 ALOGV("disconnectClient"); 1578 1579 if (mClientInfo.mPlaybackSession == NULL) { 1580 disconnectClient2(); 1581 return; 1582 } 1583 1584 if (mClientInfo.mPlaybackSession != NULL) { 1585 ALOGV("Destroying PlaybackSession"); 1586 mClientInfo.mPlaybackSession->destroyAsync(); 1587 } 1588} 1589 1590void WifiDisplaySource::disconnectClient2() { 1591 ALOGV("disconnectClient2"); 1592 1593 if (mClientInfo.mPlaybackSession != NULL) { 1594 looper()->unregisterHandler(mClientInfo.mPlaybackSession->id()); 1595 mClientInfo.mPlaybackSession.clear(); 1596 } 1597 1598 if (mClientSessionID != 0) { 1599 mNetSession->destroySession(mClientSessionID); 1600 mClientSessionID = 0; 1601 } 1602 1603 mClient->onDisplayDisconnected(); 1604 1605 finishStopAfterDisconnectingClient(); 1606} 1607 1608struct WifiDisplaySource::HDCPObserver : public BnHDCPObserver { 1609 HDCPObserver(const sp<AMessage> ¬ify); 1610 1611 virtual void notify( 1612 int msg, int ext1, int ext2, const Parcel *obj); 1613 1614private: 1615 sp<AMessage> mNotify; 1616 1617 DISALLOW_EVIL_CONSTRUCTORS(HDCPObserver); 1618}; 1619 1620WifiDisplaySource::HDCPObserver::HDCPObserver( 1621 const sp<AMessage> ¬ify) 1622 : mNotify(notify) { 1623} 1624 1625void WifiDisplaySource::HDCPObserver::notify( 1626 int msg, int ext1, int ext2, const Parcel *obj) { 1627 sp<AMessage> notify = mNotify->dup(); 1628 notify->setInt32("msg", msg); 1629 notify->setInt32("ext1", ext1); 1630 notify->setInt32("ext2", ext2); 1631 notify->post(); 1632} 1633 1634status_t WifiDisplaySource::makeHDCP() { 1635 sp<IServiceManager> sm = defaultServiceManager(); 1636 sp<IBinder> binder = sm->getService(String16("media.player")); 1637 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 1638 CHECK(service != NULL); 1639 1640 mHDCP = service->makeHDCP(); 1641 1642 if (mHDCP == NULL) { 1643 return ERROR_UNSUPPORTED; 1644 } 1645 1646 sp<AMessage> notify = new AMessage(kWhatHDCPNotify, id()); 1647 mHDCPObserver = new HDCPObserver(notify); 1648 1649 status_t err = mHDCP->setObserver(mHDCPObserver); 1650 1651 if (err != OK) { 1652 ALOGE("Failed to set HDCP observer."); 1653 1654 mHDCPObserver.clear(); 1655 mHDCP.clear(); 1656 1657 return err; 1658 } 1659 1660 ALOGI("Initiating HDCP negotiation w/ host %s:%d", 1661 mClientInfo.mRemoteIP.c_str(), mHDCPPort); 1662 1663 err = mHDCP->initAsync(mClientInfo.mRemoteIP.c_str(), mHDCPPort); 1664 1665 if (err != OK) { 1666 return err; 1667 } 1668 1669 return OK; 1670} 1671 1672} // namespace android 1673 1674