fix [2132563] stuck in boot animation (framebuffer_device_open: Failed to create flip chain)
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 99e513c..80c8ee4 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "BootAnimation"
+
 #include <stdint.h>
 #include <sys/types.h>
 #include <math.h>
@@ -58,13 +60,29 @@
 }
 
 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<SurfaceComposerClient>& BootAnimation::session() const {
+sp<SurfaceComposerClient> BootAnimation::session() const {
     return mSession;
 }
 
+
+void BootAnimation::binderDied(const wp<IBinder>& 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 796077d..afd01fa 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -37,18 +37,19 @@
 
 // ---------------------------------------------------------------------------
 
-class BootAnimation : public Thread
+class BootAnimation : public Thread, public IBinder::DeathRecipient
 {
 public:
                 BootAnimation();
     virtual     ~BootAnimation();
 
-    const sp<SurfaceComposerClient>& session() const;
+    sp<SurfaceComposerClient> session() const;
 
 private:
     virtual bool        threadLoop();
     virtual status_t    readyToRun();
     virtual void        onFirstRef();
+    virtual void        binderDied(const wp<IBinder>& who);
 
     struct Texture {
         GLint   w;
diff --git a/include/ui/SurfaceComposerClient.h b/include/ui/SurfaceComposerClient.h
index 269959c..8701928 100644
--- a/include/ui/SurfaceComposerClient.h
+++ b/include/ui/SurfaceComposerClient.h
@@ -20,6 +20,8 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <binder/IBinder.h>
+
 #include <utils/SortedVector.h>
 #include <utils/RefBase.h>
 #include <utils/threads.h>
@@ -106,6 +108,8 @@
     static ssize_t getDisplayHeight(DisplayID dpy);
     static ssize_t getDisplayOrientation(DisplayID dpy);
 
+    status_t linkToComposerDeath(const sp<IBinder::DeathRecipient>& 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 8401cb6..3baa281 100644
--- a/libs/ui/SurfaceComposerClient.cpp
+++ b/libs/ui/SurfaceComposerClient.cpp
@@ -62,34 +62,42 @@
 static sp<IMemoryHeap>                                      gServerCblkMemory;
 static volatile surface_flinger_cblk_t*                     gServerCblk;
 
-const sp<ISurfaceComposer>& _get_surface_manager()
+static sp<ISurfaceComposer> getComposerService()
 {
-    if (gSurfaceManager != 0) {
-        return gSurfaceManager;
-    }
-
-    sp<IBinder> binder;
-    sp<IServiceManager> 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<ISurfaceComposer> sc(interface_cast<ISurfaceComposer>(binder));
-
+    sp<ISurfaceComposer> 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<IBinder> binder;
+        sp<IServiceManager> 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<ISurfaceComposer>(binder);
+            gSurfaceManager = sc;
+        } else {
+            sc = gSurfaceManager;
+        }
     }
-    return gSurfaceManager;
+    return sc;
 }
 
 static volatile surface_flinger_cblk_t const * get_cblk()
 {
     if (gServerCblk == 0) {
-        const sp<ISurfaceComposer>& sm(_get_surface_manager());
+        sp<ISurfaceComposer> sm(getComposerService());
         Mutex::Autolock _l(gLock);
         if (gServerCblk == 0) {
             gServerCblkMemory = sm->getCblk();
@@ -112,7 +120,7 @@
 
 SurfaceComposerClient::SurfaceComposerClient()
 {
-    const sp<ISurfaceComposer>& sm(_get_surface_manager());
+    sp<ISurfaceComposer> sm(getComposerService());
     if (sm == 0) {
         _init(0, 0);
         return;
@@ -133,6 +141,15 @@
     _init(sm, interface_cast<ISurfaceFlingerClient>(conn));
 }
 
+
+status_t SurfaceComposerClient::linkToComposerDeath(
+        const sp<IBinder::DeathRecipient>& recipient,
+        void* cookie, uint32_t flags)
+{
+    sp<ISurfaceComposer> sm(getComposerService());
+    return sm->asBinder()->linkToDeath(recipient, cookie, flags);    
+}
+
 void SurfaceComposerClient::_init(
         const sp<ISurfaceComposer>& sm, const sp<ISurfaceFlingerClient>& conn)
 {
@@ -183,7 +200,7 @@
 
     if (client == 0) {
         // Need to make a new client.
-        const sp<ISurfaceComposer>& sm(_get_surface_manager());
+        sp<ISurfaceComposer> sm(getComposerService());
         client = new SurfaceComposerClient(sm, conn);
         if (client != 0 && client->initCheck() == NO_ERROR) {
             Mutex::Autolock _l(gLock);
@@ -377,7 +394,7 @@
     const size_t N = clients.size();
     VERBOSE("closeGlobalTransaction (%ld clients)", N);
 
-    const sp<ISurfaceComposer>& sm(_get_surface_manager());
+    sp<ISurfaceComposer> sm(getComposerService());
     sm->openGlobalTransaction();
     for (size_t i=0; i<N; i++) {
         clients[i]->closeTransaction();
@@ -389,20 +406,20 @@
 
 status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags)
 {
-    const sp<ISurfaceComposer>& sm(_get_surface_manager());
+    sp<ISurfaceComposer> sm(getComposerService());
     return sm->freezeDisplay(dpy, flags);
 }
 
 status_t SurfaceComposerClient::unfreezeDisplay(DisplayID dpy, uint32_t flags)
 {
-    const sp<ISurfaceComposer>& sm(_get_surface_manager());
+    sp<ISurfaceComposer> sm(getComposerService());
     return sm->unfreezeDisplay(dpy, flags);
 }
 
 int SurfaceComposerClient::setOrientation(DisplayID dpy, 
         int orientation, uint32_t flags)
 {
-    const sp<ISurfaceComposer>& sm(_get_surface_manager());
+    sp<ISurfaceComposer> sm(getComposerService());
     return sm->setOrientation(dpy, orientation, flags);
 }