diff options
author | Andreas Huber <andih@google.com> | 2012-09-27 14:13:05 -0700 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2012-09-27 14:25:18 -0700 |
commit | ef7d3793fa9bbfb25253626ede9a020ee9280a17 (patch) | |
tree | 294e3f0459595612c4b7ae4865e396147ebb0754 | |
parent | e399acc9d9f3b7af72106c4209e4bb40de37aa6a (diff) | |
download | frameworks_av-ef7d3793fa9bbfb25253626ede9a020ee9280a17.zip frameworks_av-ef7d3793fa9bbfb25253626ede9a020ee9280a17.tar.gz frameworks_av-ef7d3793fa9bbfb25253626ede9a020ee9280a17.tar.bz2 |
Cleaner Wifi Display shutdown process, avoid crashing HDCP on exit.
Change-Id: Ie54ee3edd672ec629360b4ecc5df2f85ecbaa45f
related-to-bug: 7247584
7 files changed, 105 insertions, 54 deletions
diff --git a/media/libmediaplayerservice/HDCP.cpp b/media/libmediaplayerservice/HDCP.cpp index e7dea6e..09b9719 100644 --- a/media/libmediaplayerservice/HDCP.cpp +++ b/media/libmediaplayerservice/HDCP.cpp @@ -51,6 +51,8 @@ HDCP::HDCP() } HDCP::~HDCP() { + Mutex::Autolock autoLock(mLock); + if (mHDCPModule != NULL) { delete mHDCPModule; mHDCPModule = NULL; @@ -63,6 +65,8 @@ HDCP::~HDCP() { } status_t HDCP::setObserver(const sp<IHDCPObserver> &observer) { + Mutex::Autolock autoLock(mLock); + if (mHDCPModule == NULL) { return NO_INIT; } @@ -73,6 +77,8 @@ status_t HDCP::setObserver(const sp<IHDCPObserver> &observer) { } status_t HDCP::initAsync(const char *host, unsigned port) { + Mutex::Autolock autoLock(mLock); + if (mHDCPModule == NULL) { return NO_INIT; } @@ -81,6 +87,8 @@ status_t HDCP::initAsync(const char *host, unsigned port) { } status_t HDCP::shutdownAsync() { + Mutex::Autolock autoLock(mLock); + if (mHDCPModule == NULL) { return NO_INIT; } @@ -91,6 +99,8 @@ status_t HDCP::shutdownAsync() { status_t HDCP::encrypt( const void *inData, size_t size, uint32_t streamCTR, uint64_t *outInputCTR, void *outData) { + Mutex::Autolock autoLock(mLock); + if (mHDCPModule == NULL) { *outInputCTR = 0; @@ -106,6 +116,8 @@ void HDCP::ObserveWrapper(void *me, int msg, int ext1, int ext2) { } void HDCP::observe(int msg, int ext1, int ext2) { + Mutex::Autolock autoLock(mLock); + if (mObserver != NULL) { mObserver->notify(msg, ext1, ext2, NULL /* obj */); } diff --git a/media/libmediaplayerservice/HDCP.h b/media/libmediaplayerservice/HDCP.h index 4ee664d..b2fc457 100644 --- a/media/libmediaplayerservice/HDCP.h +++ b/media/libmediaplayerservice/HDCP.h @@ -19,6 +19,7 @@ #define HDCP_H_ #include <media/IHDCP.h> +#include <utils/Mutex.h> namespace android { @@ -35,6 +36,8 @@ struct HDCP : public BnHDCP { uint64_t *outInputCTR, void *outData); private: + Mutex mLock; + void *mLibHandle; HDCPModule *mHDCPModule; sp<IHDCPObserver> mObserver; diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp index e224437..3d3f421 100644 --- a/media/libstagefright/SurfaceMediaSource.cpp +++ b/media/libstagefright/SurfaceMediaSource.cpp @@ -193,6 +193,7 @@ status_t SurfaceMediaSource::stop() mStopped = true; mFrameAvailableCondition.signal(); + mMediaBuffersAvailableCondition.signal(); return mBufferQueue->consumerDisconnect(); } diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp index 28fe0ec..0facafe 100644 --- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp +++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp @@ -153,6 +153,8 @@ void WifiDisplaySource::PlaybackSession::Track::setPacketizerTrackIndex(size_t i } status_t WifiDisplaySource::PlaybackSession::Track::start() { + ALOGV("Track::start isAudio=%d", mIsAudio); + if (mStarted) { return INVALID_OPERATION; } @@ -171,6 +173,8 @@ status_t WifiDisplaySource::PlaybackSession::Track::start() { } status_t WifiDisplaySource::PlaybackSession::Track::stop() { + ALOGV("Track::stop isAudio=%d", mIsAudio); + if (!mStarted) { return INVALID_OPERATION; } @@ -217,6 +221,7 @@ WifiDisplaySource::PlaybackSession::PlaybackSession( mNotify(notify), mInterfaceAddr(interfaceAddr), mHDCP(hdcp), + mWeAreDead(false), mLastLifesignUs(), mVideoTrackIndex(-1), mTSQueue(new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188)), @@ -531,6 +536,10 @@ status_t WifiDisplaySource::PlaybackSession::destroy() { void WifiDisplaySource::PlaybackSession::onMessageReceived( const sp<AMessage> &msg) { + if (mWeAreDead) { + return; + } + switch (msg->what()) { case kWhatRTPNotify: case kWhatRTCPNotify: @@ -590,10 +599,7 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived( } #endif - // Inform WifiDisplaySource of our premature death (wish). - sp<AMessage> notify = mNotify->dup(); - notify->setInt32("what", kWhatSessionDead); - notify->post(); + notifySessionDead(); break; } @@ -714,12 +720,7 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived( status_t err = packetizeQueuedAccessUnits(); if (err != OK) { - // Inform WifiDisplaySource of our premature death - // (wish). - sp<AMessage> notify = mNotify->dup(); - notify->setInt32("what", kWhatSessionDead); - notify->post(); - + notifySessionDead(); break; } } @@ -736,11 +737,7 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived( status_t err = packetizeAccessUnit(trackIndex, accessUnit); if (err != OK) { - // Inform WifiDisplaySource of our premature death - // (wish). - sp<AMessage> notify = mNotify->dup(); - notify->setInt32("what", kWhatSessionDead); - notify->post(); + notifySessionDead(); } break; } else if (what == Converter::kWhatEOS) { @@ -768,10 +765,7 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived( ALOGE("converter signaled error %d", err); - // Inform WifiDisplaySource of our premature death (wish). - sp<AMessage> notify = mNotify->dup(); - notify->setInt32("what", kWhatSessionDead); - notify->post(); + notifySessionDead(); } break; } @@ -1482,5 +1476,14 @@ status_t WifiDisplaySource::PlaybackSession::packetizeQueuedAccessUnits() { return OK; } +void WifiDisplaySource::PlaybackSession::notifySessionDead() { + // Inform WifiDisplaySource of our premature death (wish). + sp<AMessage> notify = mNotify->dup(); + notify->setInt32("what", kWhatSessionDead); + notify->post(); + + mWeAreDead = true; +} + } // namespace android diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.h b/media/libstagefright/wifi-display/source/PlaybackSession.h index b4aaa4d..342fc85 100644 --- a/media/libstagefright/wifi-display/source/PlaybackSession.h +++ b/media/libstagefright/wifi-display/source/PlaybackSession.h @@ -107,6 +107,7 @@ private: sp<AMessage> mNotify; in_addr mInterfaceAddr; sp<IHDCP> mHDCP; + bool mWeAreDead; int64_t mLastLifesignUs; @@ -205,6 +206,8 @@ private: status_t packetizeQueuedAccessUnits(); + void notifySessionDead(); + DISALLOW_EVIL_CONSTRUCTORS(PlaybackSession); }; diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp index b9139c9..286adfa 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp @@ -169,9 +169,10 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { mNetSession->destroySession(sessionID); if (sessionID == mClientSessionID) { - mClientSessionID = -1; + mClientSessionID = 0; - disconnectClient(UNKNOWN_ERROR); + mClient->onDisplayError( + IRemoteDisplayClient::kDisplayErrorUnknown); } break; } @@ -217,7 +218,8 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { status_t err = onReceiveClientData(msg); if (err != OK) { - disconnectClient(err); + mClient->onDisplayError( + IRemoteDisplayClient::kDisplayErrorUnknown); } break; } @@ -232,7 +234,8 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { { CHECK(msg->senderAwaitsResponse(&mStopReplyID)); - if (mSessionID != 0 && mClientSessionID != 0) { + if (mClientSessionID != 0 + && mClientInfo.mPlaybackSessionID != -1) { status_t err = sendM5( mClientSessionID, true /* requestShutdown */); @@ -258,7 +261,11 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { + kPlaybackSessionTimeoutUs < ALooper::GetNowUs()) { ALOGI("playback session timed out, reaping."); - disconnectClient(-ETIMEDOUT); + mNetSession->destroySession(mClientSessionID); + mClientSessionID = 0; + + mClient->onDisplayError( + IRemoteDisplayClient::kDisplayErrorUnknown); } else { scheduleReaper(); } @@ -276,7 +283,8 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { if (what == PlaybackSession::kWhatSessionDead) { ALOGI("playback session wants to quit."); - disconnectClient(UNKNOWN_ERROR); + mClient->onDisplayError( + IRemoteDisplayClient::kDisplayErrorUnknown); } else if (what == PlaybackSession::kWhatSessionEstablished) { if (mClient != NULL) { mClient->onDisplayConnected( @@ -354,8 +362,13 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { } case HDCPModule::HDCP_SHUTDOWN_COMPLETE: + case HDCPModule::HDCP_SHUTDOWN_FAILED: { - finishStop2(); + // Ugly hack to make sure that the call to + // HDCPObserver::notify is completely handled before + // we clear the HDCP instance and unload the shared + // library :( + (new AMessage(kWhatFinishStop2, id()))->post(300000ll); break; } @@ -363,12 +376,19 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { { ALOGE("HDCP failure, shutting down."); - disconnectClient(-EACCES); + mClient->onDisplayError( + IRemoteDisplayClient::kDisplayErrorUnknown); break; } } break; } + + case kWhatFinishStop2: + { + finishStop2(); + break; + } #endif default: @@ -508,6 +528,7 @@ status_t WifiDisplaySource::sendM4(int32_t sessionID) { status_t WifiDisplaySource::sendM5(int32_t sessionID, bool requestShutdown) { AString body = "wfd_trigger_method: "; if (requestShutdown) { + ALOGI("Sending TEARDOWN trigger."); body.append("TEARDOWN"); } else { body.append("SETUP"); @@ -1017,6 +1038,8 @@ status_t WifiDisplaySource::onPlayRequest( return ERROR_MALFORMED; } + ALOGI("Received PLAY request."); + status_t err = playbackSession->play(); CHECK_EQ(err, (status_t)OK); @@ -1065,6 +1088,8 @@ status_t WifiDisplaySource::onTeardownRequest( int32_t sessionID, int32_t cseq, const sp<ParsedMessage> &data) { + ALOGI("Received TEARDOWN request."); + int32_t playbackSessionID; sp<PlaybackSession> playbackSession = findPlaybackSession(data, &playbackSessionID); @@ -1079,26 +1104,23 @@ status_t WifiDisplaySource::onTeardownRequest( response.append("Connection: close\r\n"); response.append("\r\n"); - status_t err = mNetSession->sendRequest(sessionID, response.c_str()); - - if (err != OK) { - return err; - } + mNetSession->sendRequest(sessionID, response.c_str()); if (mStopReplyID != 0) { finishStop(); } else { - disconnectClient(UNKNOWN_ERROR); + mClient->onDisplayError(IRemoteDisplayClient::kDisplayErrorUnknown); } return OK; } void WifiDisplaySource::finishStop() { - disconnectClient(OK); + ALOGV("finishStop"); #if REQUIRE_HDCP if (mHDCP != NULL) { + ALOGI("Initiating HDCP shutdown."); mHDCP->shutdownAsync(); return; } @@ -1108,10 +1130,23 @@ void WifiDisplaySource::finishStop() { } void WifiDisplaySource::finishStop2() { + ALOGV("finishStop2"); + #if REQUIRE_HDCP + mHDCP->setObserver(NULL); + mHDCPObserver.clear(); mHDCP.clear(); #endif + disconnectClient(); + + if (mSessionID != 0) { + mNetSession->destroySession(mSessionID); + mSessionID = 0; + } + + ALOGV("finishStop2 completed."); + status_t err = OK; sp<AMessage> response = new AMessage; @@ -1230,27 +1265,22 @@ sp<WifiDisplaySource::PlaybackSession> WifiDisplaySource::findPlaybackSession( return mClientInfo.mPlaybackSession; } -void WifiDisplaySource::disconnectClient(status_t err) { - if (mClientSessionID != 0) { - if (mClientInfo.mPlaybackSession != NULL) { - sp<PlaybackSession> playbackSession = mClientInfo.mPlaybackSession; - mClientInfo.mPlaybackSession.clear(); +void WifiDisplaySource::disconnectClient() { + if (mClientInfo.mPlaybackSession != NULL) { + sp<PlaybackSession> playbackSession = mClientInfo.mPlaybackSession; + mClientInfo.mPlaybackSession.clear(); - playbackSession->destroy(); - looper()->unregisterHandler(playbackSession->id()); - } + ALOGI("Destroying PlaybackSession"); + playbackSession->destroy(); + looper()->unregisterHandler(playbackSession->id()); + } + if (mClientSessionID != 0) { mNetSession->destroySession(mClientSessionID); mClientSessionID = 0; } - if (mClient != NULL) { - if (err != OK) { - mClient->onDisplayError(IRemoteDisplayClient::kDisplayErrorUnknown); - } else { - mClient->onDisplayDisconnected(); - } - } + mClient->onDisplayDisconnected(); } #if REQUIRE_HDCP @@ -1306,7 +1336,7 @@ status_t WifiDisplaySource::makeHDCP() { return err; } - ALOGI("initiating HDCP negotiation w/ host %s:%d", + ALOGI("Initiating HDCP negotiation w/ host %s:%d", mClientInfo.mRemoteIP.c_str(), mHDCPPort); err = mHDCP->initAsync(mClientInfo.mRemoteIP.c_str(), mHDCPPort); diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h index fb4f53d..77b15f8 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h @@ -63,6 +63,7 @@ private: kWhatPlaybackSessionNotify, kWhatKeepAlive, kWhatHDCPNotify, + kWhatFinishStop2, }; struct ResponseID { @@ -200,10 +201,8 @@ private: const sp<ParsedMessage> &data, int32_t *playbackSessionID) const; // Disconnects the current client and shuts down its playback session - // (if any). The reason for the disconnection is OK for orderly shutdown - // or a nonzero error code. - // A listener is notified accordingly. - void disconnectClient(status_t err); + // (if any). + void disconnectClient(); void finishStop(); void finishStop2(); |