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