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