Fix a race in SurfaceFlinger that could cause layers to be leaked forever.

The transaction flags were atomically read-and-cleared to determine if
a transaction was needed, in the later case, mStateLock was taken to
keep the current state still during the transaction. This left a small
window open, where a layer could be removed after the transaction flags
were checked but before the transaction was started holding the lock.
In that situation eTraversalNeeded would be set but only seen during the
next transaction cycle; however, because we're handling this transaction
(because of another flag) it will be commited, "loosing" the information
about the layer being removed -- so when the next transaction cycle due
to eTraversalNeeded starts, it won't notice that layers have been removed
and won't populated the ditchedLayers array.

Change-Id: Iedea9e25fee8dd98a0c5bd5ad41a20fcadf75b47
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ad6ab8e..e8f0328 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -395,7 +395,7 @@
     if (LIKELY(mTransactionCount == 0)) {
         // if we're in a global transaction, don't do anything.
         const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
-        uint32_t transactionFlags = getTransactionFlags(mask);
+        uint32_t transactionFlags = peekTransactionFlags(mask);
         if (LIKELY(transactionFlags)) {
             handleTransaction(transactionFlags);
         }
@@ -490,7 +490,17 @@
         Mutex::Autolock _l(mStateLock);
         const nsecs_t now = systemTime();
         mDebugInTransaction = now;
+
+        // Here we're guaranteed that some transaction flags are set
+        // so we can call handleTransactionLocked() unconditionally.
+        // We call getTransactionFlags(), which will also clear the flags,
+        // with mStateLock held to guarantee that mCurrentState won't change
+        // until the transaction is commited.
+
+        const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
+        transactionFlags = getTransactionFlags(mask);
         handleTransactionLocked(transactionFlags, ditchedLayers);
+
         mLastTransactionTime = systemTime() - now;
         mDebugInTransaction = 0;
         invalidateHwcGeometry();
@@ -1153,6 +1163,11 @@
     return NO_ERROR;
 }
 
+uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t flags)
+{
+    return android_atomic_release_load(&mTransactionFlags);
+}
+
 uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
 {
     return android_atomic_and(~flags, &mTransactionFlags) & flags;