Merge changes Ibe02e76d,Ibb542595,Ic63aba39 into rvc-dev am: db283837dc am: dc67deb3ea am: 34f0dbe2b4

Change-Id: Ieedc2ee10cdac795a986f0f92b08844edbb8100f
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 2307fbf..605c2e8 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -430,6 +430,19 @@
 }
 
 status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const {
+    // If we write the Transaction to a parcel, we want to ensure the Buffers are cached
+    // before crossing the IPC boundary. Otherwise the receiving party will cache the buffers
+    // but is unlikely to use them again as they are owned by the other process.
+    // You may be asking yourself, is this const cast safe? Const cast is safe up
+    // until the point where you try and write to an object that was originally const at which
+    // point we enter undefined behavior. In this case we are safe though, because there are
+    // two possibilities:
+    //    1. The SurfaceComposerClient::Transaction was originally non-const. Safe.
+    //    2. It was originall const! In this case not only was it useless, but it by definition
+    //       contains no composer states and so cacheBuffers will not perform any writes.
+
+    const_cast<SurfaceComposerClient::Transaction*>(this)->cacheBuffers();
+
     parcel->writeUint32(mForceSynchronous);
     parcel->writeUint32(mTransactionNestCount);
     parcel->writeBool(mAnimation);
@@ -507,7 +520,7 @@
 
     mInputWindowCommands.merge(other.mInputWindowCommands);
 
-    mContainsBuffer = other.mContainsBuffer;
+    mContainsBuffer |= other.mContainsBuffer;
     mEarlyWakeup = mEarlyWakeup || other.mEarlyWakeup;
     other.clear();
     return *this;
@@ -547,6 +560,11 @@
         layer_state_t* s = getLayerState(handle);
         if (!(s->what & layer_state_t::eBufferChanged)) {
             continue;
+        } else if (s->what & layer_state_t::eCachedBufferChanged) {
+            // If eBufferChanged and eCachedBufferChanged are both trued then that means
+            // we already cached the buffer in a previous call to cacheBuffers, perhaps
+            // from writeToParcel on a Transaction that was merged in to this one.
+            continue;
         }
 
         // Don't try to cache a null buffer. Sending null buffers is cheap so we shouldn't waste