From ad0d97c7cf620e96a0b088dd9461645a3f8900b7 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Mon, 1 Oct 2012 11:26:30 -0700 Subject: Perform an orderly shutdown if possible, force disconnect if necessary wait for up to 2 secs for the dongle to send us a "TEARDOWN", after that forcibly shutdown the connection. Change-Id: Ie049857cd468b7af6986d6305f725c54571b2276 related-to-bug: 7258622 --- .../wifi-display/source/PlaybackSession.cpp | 4 +- .../wifi-display/source/WifiDisplaySource.cpp | 54 ++++++++++++++++++++-- .../wifi-display/source/WifiDisplaySource.h | 20 ++++++++ 3 files changed, 71 insertions(+), 7 deletions(-) (limited to 'media/libstagefright/wifi-display') diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp index c8b9afd8..9c065b28 100644 --- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp +++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp @@ -173,13 +173,11 @@ status_t WifiDisplaySource::PlaybackSession::Track::start() { void WifiDisplaySource::PlaybackSession::Track::stopAsync() { ALOGV("Track::stopAsync isAudio=%d", mIsAudio); - CHECK(mStarted); - mConverter->shutdownAsync(); sp msg = new AMessage(kWhatMediaPullerStopped, id()); - if (mMediaPuller != NULL) { + if (mStarted && mMediaPuller != NULL) { mMediaPuller->stopAsync(msg); } else { msg->post(); diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp index d5ffc650..adb15499 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp @@ -41,7 +41,8 @@ namespace android { WifiDisplaySource::WifiDisplaySource( const sp &netSession, const sp &client) - : mNetSession(netSession), + : mState(INITIALIZED), + mNetSession(netSession), mClient(client), mSessionID(0), mStopReplyID(0), @@ -61,6 +62,8 @@ WifiDisplaySource::~WifiDisplaySource() { } status_t WifiDisplaySource::start(const char *iface) { + CHECK_EQ(mState, INITIALIZED); + sp msg = new AMessage(kWhatStart, id()); msg->setString("iface", iface); @@ -137,6 +140,10 @@ void WifiDisplaySource::onMessageReceived(const sp &msg) { } } + if (err == OK) { + mState = AWAITING_CLIENT_CONNECTION; + } + sp response = new AMessage; response->setInt32("err", err); response->postReply(replyID); @@ -190,6 +197,8 @@ void WifiDisplaySource::onMessageReceived(const sp &msg) { break; } + CHECK_EQ(mState, AWAITING_CLIENT_CONNECTION); + CHECK(msg->findString("client-ip", &mClientInfo.mRemoteIP)); CHECK(msg->findString("server-ip", &mClientInfo.mLocalIP)); @@ -208,6 +217,8 @@ void WifiDisplaySource::onMessageReceived(const sp &msg) { ALOGI("We now have a client (%d) connected.", sessionID); + mState = AWAITING_CLIENT_SETUP; + status_t err = sendM1(sessionID); CHECK_EQ(err, (status_t)OK); break; @@ -234,14 +245,24 @@ void WifiDisplaySource::onMessageReceived(const sp &msg) { { CHECK(msg->senderAwaitsResponse(&mStopReplyID)); - if (mClientSessionID != 0 - && mClientInfo.mPlaybackSessionID != -1) { + CHECK_LT(mState, AWAITING_CLIENT_TEARDOWN); + + if (mState >= AWAITING_CLIENT_PLAY) { + // We have a session, i.e. a previous SETUP succeeded. + status_t err = sendM5( mClientSessionID, true /* requestShutdown */); if (err == OK) { + mState = AWAITING_CLIENT_TEARDOWN; + + (new AMessage(kWhatTeardownTriggerTimedOut, id()))->post( + kTeardownTriggerTimeouSecs * 1000000ll); + break; } + + // fall through. } finishStop(); @@ -293,6 +314,10 @@ void WifiDisplaySource::onMessageReceived(const sp &msg) { mClientInfo.mPlaybackSession->height(), 0 /* flags */); } + + if (mState == ABOUT_TO_PLAY) { + mState = PLAYING; + } } else if (what == PlaybackSession::kWhatSessionDestroyed) { disconnectClient2(); } else { @@ -339,6 +364,18 @@ void WifiDisplaySource::onMessageReceived(const sp &msg) { break; } + case kWhatTeardownTriggerTimedOut: + { + if (mState == AWAITING_CLIENT_TEARDOWN) { + ALOGI("TEARDOWN trigger timed out, forcing disconnection."); + + CHECK_NE(mStopReplyID, 0); + finishStop(); + break; + } + break; + } + #if REQUIRE_HDCP case kWhatHDCPNotify: { @@ -1020,6 +1057,8 @@ status_t WifiDisplaySource::onSetupRequest( return err; } + mState = AWAITING_CLIENT_PLAY; + scheduleReaper(); scheduleKeepAlive(sessionID); @@ -1057,6 +1096,9 @@ status_t WifiDisplaySource::onPlayRequest( playbackSession->finishPlay(); + CHECK_EQ(mState, AWAITING_CLIENT_PLAY); + mState = ABOUT_TO_PLAY; + return OK; } @@ -1107,7 +1149,8 @@ status_t WifiDisplaySource::onTeardownRequest( mNetSession->sendRequest(sessionID, response.c_str()); - if (mStopReplyID != 0) { + if (mState == AWAITING_CLIENT_TEARDOWN) { + CHECK_NE(mStopReplyID, 0); finishStop(); } else { mClient->onDisplayError(IRemoteDisplayClient::kDisplayErrorUnknown); @@ -1119,6 +1162,8 @@ status_t WifiDisplaySource::onTeardownRequest( void WifiDisplaySource::finishStop() { ALOGV("finishStop"); + mState = STOPPING; + disconnectClientAsync(); } @@ -1153,6 +1198,7 @@ void WifiDisplaySource::finishStop2() { } ALOGI("We're stopped."); + mState = STOPPED; status_t err = OK; diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h index ade623aa..8c043cd0 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h @@ -55,6 +55,18 @@ private: struct HDCPObserver; #endif + enum State { + INITIALIZED, + AWAITING_CLIENT_CONNECTION, + AWAITING_CLIENT_SETUP, + AWAITING_CLIENT_PLAY, + ABOUT_TO_PLAY, + PLAYING, + AWAITING_CLIENT_TEARDOWN, + STOPPING, + STOPPED, + }; + enum { kWhatStart, kWhatRTSPNotify, @@ -64,6 +76,7 @@ private: kWhatKeepAlive, kWhatHDCPNotify, kWhatFinishStop2, + kWhatTeardownTriggerTimedOut, }; struct ResponseID { @@ -82,11 +95,18 @@ private: static const int64_t kReaperIntervalUs = 1000000ll; + // We request that the dongle send us a "TEARDOWN" in order to + // perform an orderly shutdown. We're willing to wait up to 2 secs + // for this message to arrive, after that we'll force a disconnect + // instead. + static const int64_t kTeardownTriggerTimeouSecs = 2; + static const int64_t kPlaybackSessionTimeoutSecs = 30; static const int64_t kPlaybackSessionTimeoutUs = kPlaybackSessionTimeoutSecs * 1000000ll; + State mState; sp mNetSession; sp mClient; struct in_addr mInterfaceAddr; -- cgit v1.2.3