From bc7261130a51dc9f3461d3970eee1b923bcbf193 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 23 Sep 2009 15:44:05 -0700 Subject: [PATCH] fix [2132563] stuck in boot animation (framebuffer_device_open: Failed to create flip chain) --- cmds/bootanimation/BootAnimation.cpp | 22 ++++++++- cmds/bootanimation/BootAnimation.h | 5 +- include/ui/SurfaceComposerClient.h | 4 ++ libs/ui/SurfaceComposerClient.cpp | 69 +++++++++++++++++----------- 4 files changed, 70 insertions(+), 30 deletions(-) diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 99e513cc0710c..80c8ee4dcff69 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#define LOG_TAG "BootAnimation" + #include #include #include @@ -58,13 +60,29 @@ BootAnimation::~BootAnimation() { } void BootAnimation::onFirstRef() { - run("BootAnimation", PRIORITY_DISPLAY); + status_t err = mSession->linkToComposerDeath(this); + LOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err)); + if (err != NO_ERROR) { + run("BootAnimation", PRIORITY_DISPLAY); + } } -const sp& BootAnimation::session() const { +sp BootAnimation::session() const { return mSession; } + +void BootAnimation::binderDied(const wp& who) +{ + // woah, surfaceflinger died! + LOGD("SurfaceFlinger died, exiting..."); + + // calling requestExit() is not enough here because the Surface code + // might be blocked on a condition variable that will never be updated. + kill( getpid(), SIGKILL ); + requestExit(); +} + status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, const char* name) { Asset* asset = assets.open(name, Asset::ACCESS_BUFFER); diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index 796077dc3e1db..afd01faeef067 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -37,18 +37,19 @@ class AssetManager; // --------------------------------------------------------------------------- -class BootAnimation : public Thread +class BootAnimation : public Thread, public IBinder::DeathRecipient { public: BootAnimation(); virtual ~BootAnimation(); - const sp& session() const; + sp session() const; private: virtual bool threadLoop(); virtual status_t readyToRun(); virtual void onFirstRef(); + virtual void binderDied(const wp& who); struct Texture { GLint w; diff --git a/include/ui/SurfaceComposerClient.h b/include/ui/SurfaceComposerClient.h index 269959c9b653d..8701928ebee80 100644 --- a/include/ui/SurfaceComposerClient.h +++ b/include/ui/SurfaceComposerClient.h @@ -20,6 +20,8 @@ #include #include +#include + #include #include #include @@ -106,6 +108,8 @@ public: static ssize_t getDisplayHeight(DisplayID dpy); static ssize_t getDisplayOrientation(DisplayID dpy); + status_t linkToComposerDeath(const sp& recipient, + void* cookie = NULL, uint32_t flags = 0); private: friend class Surface; diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/ui/SurfaceComposerClient.cpp index 8401cb69671e1..3baa2817aac4b 100644 --- a/libs/ui/SurfaceComposerClient.cpp +++ b/libs/ui/SurfaceComposerClient.cpp @@ -62,34 +62,42 @@ static SortedVector > gOpenTransactions; static sp gServerCblkMemory; static volatile surface_flinger_cblk_t* gServerCblk; -const sp& _get_surface_manager() +static sp getComposerService() { - if (gSurfaceManager != 0) { - return gSurfaceManager; - } - - sp binder; - sp sm = defaultServiceManager(); - do { - binder = sm->getService(String16("SurfaceFlinger")); - if (binder == 0) { - LOGW("SurfaceFlinger not published, waiting..."); - usleep(500000); // 0.5 s - } - } while(binder == 0); - sp sc(interface_cast(binder)); - + sp sc; Mutex::Autolock _l(gLock); - if (gSurfaceManager == 0) { - gSurfaceManager = sc; + if (gSurfaceManager != 0) { + sc = gSurfaceManager; + } else { + // release the lock while we're waiting... + gLock.unlock(); + + sp binder; + sp sm = defaultServiceManager(); + do { + binder = sm->getService(String16("SurfaceFlinger")); + if (binder == 0) { + LOGW("SurfaceFlinger not published, waiting..."); + usleep(500000); // 0.5 s + } + } while(binder == 0); + + // grab the lock again for updating gSurfaceManager + gLock.lock(); + if (gSurfaceManager == 0) { + sc = interface_cast(binder); + gSurfaceManager = sc; + } else { + sc = gSurfaceManager; + } } - return gSurfaceManager; + return sc; } static volatile surface_flinger_cblk_t const * get_cblk() { if (gServerCblk == 0) { - const sp& sm(_get_surface_manager()); + sp sm(getComposerService()); Mutex::Autolock _l(gLock); if (gServerCblk == 0) { gServerCblkMemory = sm->getCblk(); @@ -112,7 +120,7 @@ static inline int compare_type( const layer_state_t& lhs, SurfaceComposerClient::SurfaceComposerClient() { - const sp& sm(_get_surface_manager()); + sp sm(getComposerService()); if (sm == 0) { _init(0, 0); return; @@ -133,6 +141,15 @@ SurfaceComposerClient::SurfaceComposerClient( _init(sm, interface_cast(conn)); } + +status_t SurfaceComposerClient::linkToComposerDeath( + const sp& recipient, + void* cookie, uint32_t flags) +{ + sp sm(getComposerService()); + return sm->asBinder()->linkToDeath(recipient, cookie, flags); +} + void SurfaceComposerClient::_init( const sp& sm, const sp& conn) { @@ -183,7 +200,7 @@ SurfaceComposerClient::clientForConnection(const sp& conn) if (client == 0) { // Need to make a new client. - const sp& sm(_get_surface_manager()); + sp sm(getComposerService()); client = new SurfaceComposerClient(sm, conn); if (client != 0 && client->initCheck() == NO_ERROR) { Mutex::Autolock _l(gLock); @@ -377,7 +394,7 @@ void SurfaceComposerClient::closeGlobalTransaction() const size_t N = clients.size(); VERBOSE("closeGlobalTransaction (%ld clients)", N); - const sp& sm(_get_surface_manager()); + sp sm(getComposerService()); sm->openGlobalTransaction(); for (size_t i=0; icloseTransaction(); @@ -389,20 +406,20 @@ void SurfaceComposerClient::closeGlobalTransaction() status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags) { - const sp& sm(_get_surface_manager()); + sp sm(getComposerService()); return sm->freezeDisplay(dpy, flags); } status_t SurfaceComposerClient::unfreezeDisplay(DisplayID dpy, uint32_t flags) { - const sp& sm(_get_surface_manager()); + sp sm(getComposerService()); return sm->unfreezeDisplay(dpy, flags); } int SurfaceComposerClient::setOrientation(DisplayID dpy, int orientation, uint32_t flags) { - const sp& sm(_get_surface_manager()); + sp sm(getComposerService()); return sm->setOrientation(dpy, orientation, flags); }