Merge "connect/disconnect is now called from our EGL wrapper"
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 16755ad..4f51f03 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -168,18 +168,18 @@
         }
     }
 
+    const int minBufferSlots = mSynchronousMode ?
+            MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
     if (bufferCount == 0) {
-        const int minBufferSlots = mSynchronousMode ?
-                MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
         mClientBufferCount = 0;
         bufferCount = (mServerBufferCount >= minBufferSlots) ?
                 mServerBufferCount : minBufferSlots;
         return setBufferCountServerLocked(bufferCount);
     }
 
-    // We don't allow the client to set a buffer-count less than
-    // MIN_ASYNC_BUFFER_SLOTS (3), there is no reason for it.
-    if (bufferCount < MIN_ASYNC_BUFFER_SLOTS) {
+    if (bufferCount < minBufferSlots) {
+        LOGE("setBufferCount: requested buffer count (%d) is less than "
+                "minimum (%d)", bufferCount, minBufferSlots);
         return BAD_VALUE;
     }
 
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 33ef1fc..e75415b 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -61,13 +61,19 @@
     const size_t c = list.size();
     for (size_t i=0 ; i<c ; i++) {
         const alloc_rec_t& rec(list.valueAt(i));
-        snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %8X | 0x%08x\n",
-            list.keyAt(i), rec.size/1024.0f, 
-            rec.w, rec.s, rec.h, rec.format, rec.usage);
+        if (rec.size) {
+            snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %8X | 0x%08x\n",
+                    list.keyAt(i), rec.size/1024.0f,
+                    rec.w, rec.s, rec.h, rec.format, rec.usage);
+        } else {
+            snprintf(buffer, SIZE, "%10p: unknown     | %4u (%4u) x %4u | %8X | 0x%08x\n",
+                    list.keyAt(i),
+                    rec.w, rec.s, rec.h, rec.format, rec.usage);
+        }
         result.append(buffer);
         total += rec.size;
     }
-    snprintf(buffer, SIZE, "Total allocated: %.2f KB\n", total/1024.0f);
+    snprintf(buffer, SIZE, "Total allocated (estimate): %.2f KB\n", total/1024.0f);
     result.append(buffer);
     if (mAllocDev->common.version >= 1 && mAllocDev->dump) {
         mAllocDev->dump(mAllocDev, buffer, SIZE);
@@ -101,13 +107,19 @@
     if (err == NO_ERROR) {
         Mutex::Autolock _l(sLock);
         KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
+        int bpp = bytesPerPixel(format);
+        if (bpp < 0) {
+            // probably a HAL custom format. in any case, we don't know
+            // what its pixel size is.
+            bpp = 0;
+        }
         alloc_rec_t rec;
         rec.w = w;
         rec.h = h;
         rec.s = *stride;
         rec.format = format;
         rec.usage = usage;
-        rec.size = h * stride[0] * bytesPerPixel(format);
+        rec.size = h * stride[0] * bpp;
         list.add(*handle, rec);
     }
 
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index f67c82e..b178e49 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -22,7 +22,7 @@
 	LOCAL_CFLAGS += -DNO_RGBX_8888
 endif
 ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
-	LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
+	LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
 endif
 
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 7d6a14d..886bb2a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -105,6 +105,7 @@
 // in the purgatory list
 void Layer::onRemoved()
 {
+    mSurfaceTexture->abandon();
 }
 
 sp<ISurface> Layer::createSurface()
@@ -326,8 +327,9 @@
 {
     // if we don't have a buffer yet, we're translucent regardless of the
     // layer's opaque flag.
-    if (mActiveBuffer == 0)
+    if (mActiveBuffer == 0) {
         return false;
+    }
 
     // if the layer has the opaque flag, then we're always opaque,
     // otherwise we use the current buffer's format.
@@ -411,6 +413,8 @@
 void Layer::lockPageFlip(bool& recomputeVisibleRegions)
 {
     if (mQueuedFrames > 0) {
+        const bool oldOpacity = isOpaque();
+
         // signal another event if we have more frames pending
         if (android_atomic_dec(&mQueuedFrames) > 1) {
             mFlinger->signalEvent();
@@ -438,9 +442,8 @@
             mFlinger->invalidateHwcGeometry();
         }
 
-        const bool opacity(getOpacityForFormat(mActiveBuffer->format));
-        if (opacity != mCurrentOpacity) {
-            mCurrentOpacity = opacity;
+        mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
+        if (oldOpacity != isOpaque()) {
             recomputeVisibleRegions = true;
         }
 
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index 91e010f..5973e76 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -86,6 +86,32 @@
     return res;
 }
 
+status_t SurfaceTextureLayer::connect(int api) {
+    status_t err = SurfaceTexture::connect(api);
+    if (err == NO_ERROR) {
+        switch(api) {
+            case NATIVE_WINDOW_API_MEDIA:
+            case NATIVE_WINDOW_API_CAMERA:
+                // Camera preview and videos are rate-limited on the producer
+                // side.  If enabled for this build, we use async mode to always
+                // show the most recent frame at the cost of requiring an
+                // additional buffer.
+#ifndef NEVER_DEFAULT_TO_ASYNC_MODE
+                err = setSynchronousMode(false);
+                break;
+#endif
+                // fall through to set synchronous mode when not defaulting to
+                // async mode.
+            deafult:
+                err = setSynchronousMode(true);
+                break;
+        }
+        if (err != NO_ERROR) {
+            disconnect(api);
+        }
+    }
+    return err;
+}
 
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h
index 29a9cbe..5d328b7 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.h
+++ b/services/surfaceflinger/SurfaceTextureLayer.h
@@ -50,6 +50,8 @@
 
     virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
             uint32_t format, uint32_t usage);
+
+    virtual status_t connect(int api);
 };
 
 // ---------------------------------------------------------------------------