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