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