Allow global transactions to nest.

This change fixes a number of small glitches that can occur when
multiple components in the same process are updating surfaces.
One would expect that updates to disjoint sets of surfaces would
not collide but this is not the case.  The first component to
close the global transaction causes all pending updates to
be applied, including those that another component might not
have finished setting up if it also had an open transaction
at the same time.

Change-Id: I99345958581abbe0e1e325a5bcba37e8941a313a
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 80dd6ee..746057b 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -115,13 +115,15 @@
     SortedVector<ComposerState> mComposerStates;
     SortedVector<DisplayState > mDisplayStates;
     uint32_t                    mForceSynchronous;
+    uint32_t                    mTransactionNestCount;
     bool                        mAnimation;
 
     Composer() : Singleton<Composer>(),
-        mForceSynchronous(0),
+        mForceSynchronous(0), mTransactionNestCount(0),
         mAnimation(false)
     { }
 
+    void openGlobalTransactionImpl();
     void closeGlobalTransactionImpl(bool synchronous);
     void setAnimationTransactionImpl();
 
@@ -166,6 +168,10 @@
         Composer::getInstance().setAnimationTransactionImpl();
     }
 
+    static void openGlobalTransaction() {
+        Composer::getInstance().openGlobalTransactionImpl();
+    }
+
     static void closeGlobalTransaction(bool synchronous) {
         Composer::getInstance().closeGlobalTransactionImpl(synchronous);
     }
@@ -184,6 +190,13 @@
     return ComposerService::getComposerService()->getBuiltInDisplay(id);
 }
 
+void Composer::openGlobalTransactionImpl() {
+    { // scope for the lock
+        Mutex::Autolock _l(mLock);
+        mTransactionNestCount += 1;
+    }
+}
+
 void Composer::closeGlobalTransactionImpl(bool synchronous) {
     sp<ISurfaceComposer> sm(ComposerService::getComposerService());
 
@@ -193,13 +206,21 @@
 
     { // scope for the lock
         Mutex::Autolock _l(mLock);
+        mForceSynchronous |= synchronous;
+        if (!mTransactionNestCount) {
+            ALOGW("At least one call to closeGlobalTransaction() was not matched by a prior "
+                    "call to openGlobalTransaction().");
+        } else if (--mTransactionNestCount) {
+            return;
+        }
+
         transaction = mComposerStates;
         mComposerStates.clear();
 
         displayTransaction = mDisplayStates;
         mDisplayStates.clear();
 
-        if (synchronous || mForceSynchronous) {
+        if (mForceSynchronous) {
             flags |= ISurfaceComposer::eSynchronous;
         }
         if (mAnimation) {
@@ -483,7 +504,7 @@
 // ----------------------------------------------------------------------------
 
 void SurfaceComposerClient::openGlobalTransaction() {
-    // Currently a no-op
+    Composer::openGlobalTransaction();
 }
 
 void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) {