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