Merge "Updated comments" into jb-mr2-dev
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 18685f7..094dbc2 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -9,7 +9,7 @@
 
 LOCAL_MODULE := dumpstate
 
-LOCAL_SHARED_LIBRARIES := libcutils
+LOCAL_SHARED_LIBRARIES := libcutils liblog
 
 ifdef BOARD_LIB_DUMPSTATE
 LOCAL_STATIC_LIBRARIES := $(BOARD_LIB_DUMPSTATE)
diff --git a/cmds/dumpsys/Android.mk b/cmds/dumpsys/Android.mk
index 42b1b73..9be0901 100644
--- a/cmds/dumpsys/Android.mk
+++ b/cmds/dumpsys/Android.mk
@@ -6,6 +6,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libutils \
+	liblog \
 	libbinder
 	
 
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index 1dd4ee5..e11b4f8 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -30,6 +30,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
+    liblog \
     libselinux
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/cmds/ip-up-vpn/Android.mk b/cmds/ip-up-vpn/Android.mk
index de81889..36bbdf5 100644
--- a/cmds/ip-up-vpn/Android.mk
+++ b/cmds/ip-up-vpn/Android.mk
@@ -18,7 +18,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := ip-up-vpn.c
-LOCAL_SHARED_LIBRARIES := libcutils
+LOCAL_SHARED_LIBRARIES := libcutils liblog
 LOCAL_MODULE := ip-up-vpn
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/ppp
 LOCAL_MODULE_TAGS := optional
diff --git a/cmds/screenshot/Android.mk b/cmds/screenshot/Android.mk
index 73a8e22..0afb2c5 100644
--- a/cmds/screenshot/Android.mk
+++ b/cmds/screenshot/Android.mk
@@ -5,7 +5,7 @@
 
 LOCAL_MODULE := screenshot
 
-LOCAL_SHARED_LIBRARIES := libcutils libz
+LOCAL_SHARED_LIBRARIES := libcutils libz liblog
 LOCAL_STATIC_LIBRARIES := libpng
 LOCAL_C_INCLUDES += external/zlib
 
diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h
index 78a3608..8a7545d 100644
--- a/include/gui/ConsumerBase.h
+++ b/include/gui/ConsumerBase.h
@@ -89,6 +89,18 @@
     // buffers from the given BufferQueue.
     ConsumerBase(const sp<BufferQueue> &bufferQueue);
 
+    // onLastStrongRef gets called by RefBase just before the dtor of the most
+    // derived class.  It is used to clean up the buffers so that ConsumerBase
+    // can coordinate the clean-up by calling into virtual methods implemented
+    // by the derived classes.  This would not be possible from the
+    // ConsuemrBase dtor because by the time that gets called the derived
+    // classes have already been destructed.
+    //
+    // This methods should not need to be overridden by derived classes, but
+    // if they are overridden the ConsumerBase implementation must be called
+    // from the derived class.
+    virtual void onLastStrongRef(const void* id);
+
     // Implementation of the BufferQueue::ConsumerListener interface.  These
     // calls are used to notify the ConsumerBase of asynchronous events in the
     // BufferQueue.  These methods should not need to be overridden by derived
diff --git a/include/media/drm/DrmAPI.h b/include/media/drm/DrmAPI.h
index 81d1ec0..c89f2d6 100644
--- a/include/media/drm/DrmAPI.h
+++ b/include/media/drm/DrmAPI.h
@@ -22,6 +22,7 @@
 #include <utils/Vector.h>
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
+#include <utils/Mutex.h>
 #include <media/stagefright/foundation/ABase.h>
 
 //  Loadable DrmEngine shared libraries should define the entry points
@@ -34,7 +35,8 @@
 
 namespace android {
 
-    struct DrmPlugin;
+    class DrmPlugin;
+    class DrmPluginListener;
 
     // DRMs are implemented in DrmEngine plugins, which are dynamically
     // loadable shared libraries that implement the entry points
@@ -70,7 +72,7 @@
     class DrmPlugin {
     public:
         enum EventType {
-            kDrmPluginEventProvisionRequired,
+            kDrmPluginEventProvisionRequired = 1,
             kDrmPluginEventKeyNeeded,
             kDrmPluginEventKeyExpired,
             kDrmPluginEventVendorDefined
@@ -261,12 +263,46 @@
                                 bool &match) = 0;
 
 
+        status_t setListener(const sp<DrmPluginListener>& listener) {
+            Mutex::Autolock lock(mEventLock);
+            mListener = listener;
+            return OK;
+        }
 
-        // TODO: provide way to send an event
+    protected:
+        // Plugins call sendEvent to deliver events to the java app
+        void sendEvent(EventType eventType, int extra,
+                       Vector<uint8_t> const *sessionId,
+                       Vector<uint8_t> const *data);
+
     private:
+        Mutex mEventLock;
+        sp<DrmPluginListener> mListener;
+
         DISALLOW_EVIL_CONSTRUCTORS(DrmPlugin);
     };
 
+    class DrmPluginListener: virtual public RefBase
+    {
+    public:
+        virtual void sendEvent(DrmPlugin::EventType eventType, int extra,
+                               Vector<uint8_t> const *sesionId,
+                               Vector<uint8_t> const *data) = 0;
+    };
+
+    inline void DrmPlugin::sendEvent(EventType eventType, int extra,
+                                     Vector<uint8_t> const *sessionId,
+                                     Vector<uint8_t> const *data) {
+
+        mEventLock.lock();
+        sp<DrmPluginListener> listener = mListener;
+        mEventLock.unlock();
+
+        if (listener != NULL) {
+            listener->sendEvent(eventType, extra, sessionId, data);
+        }
+    }
+
 }  // namespace android
 
 #endif // DRM_API_H_
diff --git a/include/ui/Region.h b/include/ui/Region.h
index ffcd429..ce91f3b 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -108,6 +108,10 @@
     inline  Region&     operator += (const Point& pt);
 
     
+    // returns true if the regions share the same underlying storage
+    bool isTriviallyEqual(const Region& region) const;
+
+
     /* various ways to access the rectangle list */
 
     
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 8fcfa7d..c080f47 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -36,6 +36,7 @@
 	libsync \
 	libui \
 	libutils \
+	liblog
 
 
 LOCAL_MODULE:= libgui
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 8694d21..4937b17 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -76,7 +76,18 @@
 }
 
 ConsumerBase::~ConsumerBase() {
-	CB_LOGV("~ConsumerBase");
+    CB_LOGV("~ConsumerBase");
+    Mutex::Autolock lock(mMutex);
+
+    // Verify that abandon() has been called before we get here.  This should
+    // be done by ConsumerBase::onLastStrongRef(), but it's possible for a
+    // derived class to override that method and not call
+    // ConsumerBase::onLastStrongRef().
+    LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~ConsumerBase was called, but the "
+        "consumer is not abandoned!", mName.string());
+}
+
+void ConsumerBase::onLastStrongRef(const void* id) {
     abandon();
 }
 
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index ce96036..7376b4c 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -178,21 +178,21 @@
     EXPECT_EQ(EGL_SUCCESS, eglGetError());
 
     EGLBoolean success = eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, mEglContext);
-    EXPECT_EQ(EGL_TRUE, success);
+    EXPECT_TRUE(success);
 
     glClear(GL_COLOR_BUFFER_BIT);
     success = eglSwapBuffers(mEglDisplay, eglSurface);
-    EXPECT_EQ(EGL_TRUE, success);
+    EXPECT_TRUE(success);
 
     mST->abandon();
 
     glClear(GL_COLOR_BUFFER_BIT);
     success = eglSwapBuffers(mEglDisplay, eglSurface);
-    EXPECT_EQ(EGL_FALSE, success);
+    EXPECT_FALSE(success);
     EXPECT_EQ(EGL_BAD_SURFACE, eglGetError());
 
     success = eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
-    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_TRUE(success);
 
     if (eglSurface != EGL_NO_SURFACE) {
         eglDestroySurface(mEglDisplay, eglSurface);
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 2d30305..84ec7f2 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -716,18 +716,18 @@
     glViewport(0, 0, texWidth, texHeight);
     drawTexture();
 
-    EXPECT_TRUE(checkPixel( 0,  0, 255, 127, 255, 255));
-    EXPECT_TRUE(checkPixel(63,  0,   0, 133,   0, 255));
-    EXPECT_TRUE(checkPixel(63, 65,   0, 133,   0, 255));
-    EXPECT_TRUE(checkPixel( 0, 65, 255, 127, 255, 255));
+    EXPECT_TRUE(checkPixel( 0,  0, 255, 127, 255, 255, 3));
+    EXPECT_TRUE(checkPixel(63,  0,   0, 133,   0, 255, 3));
+    EXPECT_TRUE(checkPixel(63, 65,   0, 133,   0, 255, 3));
+    EXPECT_TRUE(checkPixel( 0, 65, 255, 127, 255, 255, 3));
 
-    EXPECT_TRUE(checkPixel(22, 44, 255, 127, 255, 255));
-    EXPECT_TRUE(checkPixel(45, 52, 255, 127, 255, 255));
-    EXPECT_TRUE(checkPixel(52, 51,  98, 255,  73, 255));
-    EXPECT_TRUE(checkPixel( 7, 31, 155,   0, 118, 255));
-    EXPECT_TRUE(checkPixel(31,  9, 107,  24,  87, 255));
-    EXPECT_TRUE(checkPixel(29, 35, 255, 127, 255, 255));
-    EXPECT_TRUE(checkPixel(36, 22, 155,  29,   0, 255));
+    EXPECT_TRUE(checkPixel(22, 44, 255, 127, 255, 255, 3));
+    EXPECT_TRUE(checkPixel(45, 52, 255, 127, 255, 255, 3));
+    EXPECT_TRUE(checkPixel(52, 51,  98, 255,  73, 255, 3));
+    EXPECT_TRUE(checkPixel( 7, 31, 155,   0, 118, 255, 3));
+    EXPECT_TRUE(checkPixel(31,  9, 107,  24,  87, 255, 3));
+    EXPECT_TRUE(checkPixel(29, 35, 255, 127, 255, 255, 3));
+    EXPECT_TRUE(checkPixel(36, 22, 155,  29,   0, 255, 3));
 }
 
 TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferPow2) {
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 0d2e44c..008446b 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -30,7 +30,8 @@
 	libcutils \
 	libhardware \
 	libsync \
-	libutils
+	libutils \
+	liblog
 
 ifneq ($(BOARD_FRAMEBUFFER_FORCE_FORMAT),)
 LOCAL_CFLAGS += -DFRAMEBUFFER_FORCE_FORMAT=$(BOARD_FRAMEBUFFER_FORCE_FORMAT)
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 488fba3..bf01488 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -239,6 +239,10 @@
     mStorage.add(Rect(w,h));
 }
 
+bool Region::isTriviallyEqual(const Region& region) const {
+    return begin() == region.begin();
+}
+
 // ----------------------------------------------------------------------------
 
 void Region::addRectUnchecked(int l, int t, int r, int b)
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index 9b8d3fe..9886bf0 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -26,7 +26,7 @@
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 LOCAL_CFLAGS += -fvisibility=hidden
 
-LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger libETC1 libui
+LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils liblog libpixelflinger libETC1 libui
 LOCAL_LDLIBS := -lpthread -ldl
 
 ifeq ($(TARGET_ARCH),arm)
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 581c4d4..b4756dd 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -32,7 +32,7 @@
 	EGL/Loader.cpp 	       \
 #
 
-LOCAL_SHARED_LIBRARIES += libcutils libutils libGLES_trace
+LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libGLES_trace
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libEGL
 LOCAL_LDFLAGS += -Wl,--exclude-libs=ALL
@@ -85,7 +85,7 @@
 	GLES_CM/gl.cpp.arm 	\
 #
 
-LOCAL_SHARED_LIBRARIES += libcutils libEGL
+LOCAL_SHARED_LIBRARIES += libcutils liblog libEGL
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libGLESv1_CM
 
@@ -110,7 +110,7 @@
 	GLES2/gl2.cpp.arm 	\
 #
 
-LOCAL_SHARED_LIBRARIES += libcutils libutils libEGL
+LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libEGL
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libGLESv2
 
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 9ee3686..00bfa5a 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -27,9 +27,9 @@
 
 #include <EGL/egl.h>
 
+#include "../glestrace.h"
+
 #include "egldefs.h"
-#include "glestrace.h"
-#include "hooks.h"
 #include "Loader.h"
 
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index a6e91e0..6ac8724 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -32,11 +32,11 @@
 #include <utils/CallStack.h>
 #include <utils/String8.h>
 
-#include "egldefs.h"
-#include "egl_impl.h"
+#include "../egl_impl.h"
+#include "../glestrace.h"
+
 #include "egl_tls.h"
-#include "glestrace.h"
-#include "hooks.h"
+#include "egldefs.h"
 #include "Loader.h"
 
 #include "egl_display.h"
@@ -387,7 +387,7 @@
 #define EGL_ENTRY(_r, _api, ...) #_api,
 
 char const * const gl_names[] = {
-    #include "entries.in"
+    #include "../entries.in"
     NULL
 };
 
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 1be4961..f6bc069 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -37,13 +37,11 @@
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
-#include "egl_impl.h"
-#include "egl_tls.h"
-#include "glestrace.h"
-#include "hooks.h"
+#include "../egl_impl.h"
+#include "../glestrace.h"
+#include "../hooks.h"
 
 #include "egl_display.h"
-#include "egl_impl.h"
 #include "egl_object.h"
 #include "egl_tls.h"
 #include "egldefs.h"
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index 72655df..03397a9 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -14,9 +14,10 @@
  ** limitations under the License.
  */
 
+#include "../egl_impl.h"
+
 #include "egl_cache.h"
 #include "egl_display.h"
-#include "egl_impl.h"
 #include "egldefs.h"
 
 #include <fcntl.h>
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 59dd2d9..1955904 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -18,11 +18,12 @@
 
 #include <string.h>
 
+#include "../egl_impl.h"
+
 #include "egl_cache.h"
 #include "egl_display.h"
 #include "egl_object.h"
 #include "egl_tls.h"
-#include "egl_impl.h"
 #include "Loader.h"
 #include <cutils/properties.h>
 
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 8bb32f4..754085c 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -31,7 +31,7 @@
 #include <utils/String8.h>
 
 #include "egldefs.h"
-#include "hooks.h"
+#include "../hooks.h"
 
 // ----------------------------------------------------------------------------
 namespace android {
diff --git a/opengl/libs/EGL/egl_tls.h b/opengl/libs/EGL/egl_tls.h
index 2442ca0..56c5dba 100644
--- a/opengl/libs/EGL/egl_tls.h
+++ b/opengl/libs/EGL/egl_tls.h
@@ -22,7 +22,6 @@
 #include <EGL/egl.h>
 
 #include "egldefs.h"
-#include "hooks.h"
 
 // ----------------------------------------------------------------------------
 namespace android {
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index c900c1c..1cfe561 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_EGLDEFS_H
 #define ANDROID_EGLDEFS_H
 
-#include "hooks.h"
+#include "../hooks.h"
 
 #define VERSION_MAJOR 1
 #define VERSION_MINOR 4
diff --git a/opengl/libs/EGL/getProcAddress.cpp b/opengl/libs/EGL/getProcAddress.cpp
index 1909232..c160aa0 100644
--- a/opengl/libs/EGL/getProcAddress.cpp
+++ b/opengl/libs/EGL/getProcAddress.cpp
@@ -21,7 +21,6 @@
 #include <cutils/log.h>
 
 #include "egldefs.h"
-#include "hooks.h"
 
 // ----------------------------------------------------------------------------
 namespace android {
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index dd454bd..fad2176 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -27,8 +27,8 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
-#include "hooks.h"
-#include "egl_impl.h"
+#include "../hooks.h"
+#include "../egl_impl.h"
 
 using namespace android;
 
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index 8ac8ff9..a5bbdc6 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -26,8 +26,8 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
-#include "hooks.h"
-#include "egl_impl.h"
+#include "../hooks.h"
+#include "../egl_impl.h"
 
 using namespace android;
 
diff --git a/opengl/libs/GLES_trace/Android.mk b/opengl/libs/GLES_trace/Android.mk
index 9dec020..846932d 100644
--- a/opengl/libs/GLES_trace/Android.mk
+++ b/opengl/libs/GLES_trace/Android.mk
@@ -22,7 +22,7 @@
 
 LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI
 LOCAL_STATIC_LIBRARIES := libprotobuf-cpp-2.3.0-lite liblzf
-LOCAL_SHARED_LIBRARIES := libcutils libutils libstlport
+LOCAL_SHARED_LIBRARIES := libcutils libutils liblog libstlport
 
 LOCAL_CFLAGS += -DLOG_TAG=\"libGLES_trace\"
 
diff --git a/opengl/tests/gl2_jni/Android.mk b/opengl/tests/gl2_jni/Android.mk
index 25187c9..409bd73 100644
--- a/opengl/tests/gl2_jni/Android.mk
+++ b/opengl/tests/gl2_jni/Android.mk
@@ -37,6 +37,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libutils \
+	liblog \
 	libEGL \
 	libGLESv2
 
diff --git a/opengl/tests/gl_jni/Android.mk b/opengl/tests/gl_jni/Android.mk
index 80b4bac..11b4c8b 100644
--- a/opengl/tests/gl_jni/Android.mk
+++ b/opengl/tests/gl_jni/Android.mk
@@ -37,6 +37,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libutils \
+	liblog \
 	libEGL \
 	libGLESv1_CM
 
diff --git a/opengl/tests/gl_perf/Android.mk b/opengl/tests/gl_perf/Android.mk
index cfca089..b0f825c 100644
--- a/opengl/tests/gl_perf/Android.mk
+++ b/opengl/tests/gl_perf/Android.mk
@@ -6,7 +6,8 @@
 	filltest.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libcutils \
+    libcutils \
+    liblog \
     libEGL \
     libGLESv2 \
     libui
diff --git a/opengl/tests/gl_perfapp/Android.mk b/opengl/tests/gl_perfapp/Android.mk
index 45a5516..854b54f 100644
--- a/opengl/tests/gl_perfapp/Android.mk
+++ b/opengl/tests/gl_perfapp/Android.mk
@@ -40,6 +40,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libutils \
+	liblog \
 	libEGL \
 	libGLESv2
 
diff --git a/opengl/tests/gldual/Android.mk b/opengl/tests/gldual/Android.mk
index 42094c8..1991ed9 100644
--- a/opengl/tests/gldual/Android.mk
+++ b/opengl/tests/gldual/Android.mk
@@ -37,6 +37,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libutils \
+	liblog \
 	libEGL \
 	libGLESv2
 
diff --git a/opengl/tests/hwc/Android.mk b/opengl/tests/hwc/Android.mk
index 177eb63..2fdfcf8 100644
--- a/opengl/tests/hwc/Android.mk
+++ b/opengl/tests/hwc/Android.mk
@@ -40,6 +40,7 @@
     libEGL \
     libGLESv2 \
     libutils \
+    liblog \
     libui \
     libhardware \
 
@@ -72,6 +73,7 @@
     libEGL \
     libGLESv2 \
     libutils \
+    liblog \
     libui \
     libhardware \
 
@@ -102,6 +104,7 @@
     libEGL \
     libGLESv2 \
     libutils \
+    liblog \
     libui \
     libhardware \
 
@@ -132,6 +135,7 @@
     libEGL \
     libGLESv2 \
     libutils \
+    liblog \
     libui \
     libhardware \
 
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index e0cfaa6..a1de3c5 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -21,6 +21,7 @@
 	libcutils \
 	libhardware \
 	libutils \
+	liblog \
 	libbinder \
 	libui \
 	libgui
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 30a01be..f36e1bf 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -44,6 +44,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
+	liblog \
 	libdl \
 	libhardware \
 	libutils \
@@ -68,6 +69,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
+	liblog \
 	libdl
 
 LOCAL_MODULE:= libsurfaceflinger_ddmconnection
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 6936a7f..68b0b7f 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -143,6 +143,15 @@
     }
 }
 
+void DisplayDevice::disconnect(HWComposer& hwc) {
+    if (mHwcDisplayId >= 0) {
+        hwc.disconnectDisplay(mHwcDisplayId);
+        if (mHwcDisplayId >= DISPLAY_VIRTUAL)
+            hwc.freeDisplayId(mHwcDisplayId);
+        mHwcDisplayId = -1;
+    }
+}
+
 bool DisplayDevice::isValid() const {
     return mFlinger != NULL;
 }
@@ -419,11 +428,11 @@
     const Transform& tr(mGlobalTransform);
     snprintf(buffer, SIZE,
         "+ DisplayDevice: %s\n"
-        "   type=%x, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
+        "   type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
         "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n"
         "   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
         "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
-        mDisplayName.string(), mType,
+        mDisplayName.string(), mType, mHwcDisplayId,
         mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
         mOrientation, tr.getType(), getPageFlipCount(),
         mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index d4a6daa..377d924 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -146,6 +146,9 @@
     bool isScreenAcquired() const;
     bool canDraw() const;
 
+    // release HWC resources (if any) for removable displays
+    void disconnect(HWComposer& hwc);
+
     /* ------------------------------------------------------------------------
      * Debugging
      */
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index a68ddd8..3f00f07 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -38,6 +38,8 @@
 #include <hardware/hardware.h>
 #include <hardware/hwcomposer.h>
 
+#include <android/configuration.h>
+
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
@@ -297,6 +299,11 @@
     mEventHandler.onHotplugReceived(disp, bool(connected));
 }
 
+static float getDefaultDensity(uint32_t height) {
+    if (height >= 1080) return ACONFIGURATION_DENSITY_XHIGH;
+    else                return ACONFIGURATION_DENSITY_TV;
+}
+
 static const uint32_t DISPLAY_ATTRIBUTES[] = {
     HWC_DISPLAY_VSYNC_PERIOD,
     HWC_DISPLAY_WIDTH,
@@ -307,10 +314,6 @@
 };
 #define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0])
 
-// http://developer.android.com/reference/android/util/DisplayMetrics.html
-#define ANDROID_DENSITY_TV    213
-#define ANDROID_DENSITY_XHIGH 320
-
 status_t HWComposer::queryDisplayProperties(int disp) {
 
     LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
@@ -364,18 +367,26 @@
     mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;
     mDisplayData[disp].connected = true;
     if (mDisplayData[disp].xdpi == 0.0f || mDisplayData[disp].ydpi == 0.0f) {
-        // is there anything smarter we can do?
-        if (h >= 1080) {
-            mDisplayData[disp].xdpi = ANDROID_DENSITY_XHIGH;
-            mDisplayData[disp].ydpi = ANDROID_DENSITY_XHIGH;
-        } else {
-            mDisplayData[disp].xdpi = ANDROID_DENSITY_TV;
-            mDisplayData[disp].ydpi = ANDROID_DENSITY_TV;
-        }
+        float dpi = getDefaultDensity(h);
+        mDisplayData[disp].xdpi = dpi;
+        mDisplayData[disp].ydpi = dpi;
     }
     return NO_ERROR;
 }
 
+status_t HWComposer::setVirtualDisplayProperties(int32_t id,
+        uint32_t w, uint32_t h, uint32_t format) {
+    if (id < VIRTUAL_DISPLAY_ID_BASE || id >= int32_t(mNumDisplays) ||
+            !mAllocatedDisplayIDs.hasBit(id)) {
+        return BAD_INDEX;
+    }
+    mDisplayData[id].width = w;
+    mDisplayData[id].height = h;
+    mDisplayData[id].format = format;
+    mDisplayData[id].xdpi = mDisplayData[id].ydpi = getDefaultDensity(h);
+    return NO_ERROR;
+}
+
 int32_t HWComposer::allocateDisplayId() {
     if (mAllocatedDisplayIDs.count() >= mNumDisplays) {
         return NO_MEMORY;
@@ -416,7 +427,6 @@
     return mDisplayData[disp].lastDisplayFence;
 }
 
-
 uint32_t HWComposer::getWidth(int disp) const {
     return mDisplayData[disp].width;
 }
@@ -954,17 +964,17 @@
         result.appendFormat("  mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
         for (size_t i=0 ; i<mNumDisplays ; i++) {
             const DisplayData& disp(mDisplayData[i]);
+            if (!disp.connected)
+                continue;
 
             const Vector< sp<Layer> >& visibleLayersSortedByZ =
                     mFlinger->getLayerSortedByZForHwcDisplay(i);
 
-            if (disp.connected) {
-                result.appendFormat(
-                        "  Display[%d] : %ux%u, xdpi=%f, ydpi=%f, refresh=%lld\n",
-                        i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh);
-            }
+            result.appendFormat(
+                    "  Display[%d] : %ux%u, xdpi=%f, ydpi=%f, refresh=%lld\n",
+                    i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh);
 
-            if (disp.list && disp.connected) {
+            if (disp.list) {
                 result.appendFormat(
                         "  numHwLayers=%u, flags=%08x\n",
                         disp.list->numHwLayers, disp.list->flags);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 58f7e8f..604de38 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -253,6 +253,9 @@
     float getDpiY(int disp) const;
     bool isConnected(int disp) const;
 
+    status_t setVirtualDisplayProperties(int32_t id, uint32_t w, uint32_t h,
+            uint32_t format);
+
     // this class is only used to fake the VSync event on systems that don't
     // have it.
     class VSyncThread : public Thread {
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index d2b3edb..7e14d95 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -76,7 +76,11 @@
     if (result != NO_ERROR)
         return result;
 
-    return mHwc.fbPost(mDisplayId, fence, mAcquiredBuffer);
+    result = mHwc.fbPost(mDisplayId, fence, mAcquiredBuffer);
+    if (result == NO_ERROR) {
+        result = mHwc.setOutputBuffer(mDisplayId, fence, mAcquiredBuffer);
+    }
+    return result;
 }
 
 void VirtualDisplaySurface::onFrameCommitted() {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a4c613c..2302367 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -881,8 +881,7 @@
     return true;
 }
 bool Layer::setTransparentRegionHint(const Region& transparent) {
-    mCurrentState.sequence++;
-    mCurrentState.transparentRegion = transparent;
+    mCurrentState.requestedTransparentRegion = transparent;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1008,7 +1007,6 @@
                     swap(bufWidth, bufHeight);
                 }
 
-
                 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
                 if (front.active != front.requested) {
 
@@ -1061,6 +1059,17 @@
                         return true;
                     }
                 }
+
+                // if the transparent region has changed (this test is
+                // conservative, but that's fine, worst case we're doing
+                // a bit of extra work), we latch the new one and we
+                // trigger a visible-region recompute.
+                if (!front.activeTransparentRegion.isTriviallyEqual(
+                        front.requestedTransparentRegion)) {
+                    front.activeTransparentRegion = front.requestedTransparentRegion;
+                    recomputeVisibleRegions = true;
+                }
+
                 return false;
             }
         };
@@ -1168,7 +1177,7 @@
             getTypeId(), this, getName().string());
     result.append(buffer);
 
-    s.transparentRegion.dump(result, "transparentRegion");
+    s.activeTransparentRegion.dump(result, "transparentRegion");
     visibleRegion.dump(result, "visibleRegion");
     sp<Client> client(mClientRef.promote());
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 6bca941..2765db1 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -103,7 +103,11 @@
         uint8_t reserved[2];
         int32_t sequence; // changes when visible regions can change
         Transform transform;
-        Region transparentRegion;
+        // the transparentRegion hint is a bit special, it's latched only
+        // when we receive a buffer -- this is because it's "content"
+        // dependent.
+        Region activeTransparentRegion;
+        Region requestedTransparentRegion;
     };
 
     class LayerMesh {
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index 3f77f74..c9c7b96 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -61,6 +61,12 @@
     }
 }
 
+void MessageQueue::Handler::dispatchTransaction() {
+    if ((android_atomic_or(eventMaskTransaction, &mEventMask) & eventMaskTransaction) == 0) {
+        mQueue.mLooper->sendMessage(this, Message(MessageQueue::TRANSACTION));
+    }
+}
+
 void MessageQueue::Handler::handleMessage(const Message& message) {
     switch (message.what) {
         case INVALIDATE:
@@ -71,6 +77,10 @@
             android_atomic_and(~eventMaskRefresh, &mEventMask);
             mQueue.mFlinger->onMessageReceived(message.what);
             break;
+        case TRANSACTION:
+            android_atomic_and(~eventMaskTransaction, &mEventMask);
+            mQueue.mFlinger->onMessageReceived(message.what);
+            break;
     }
 }
 
@@ -132,6 +142,7 @@
     return NO_ERROR;
 }
 
+
 /* when INVALIDATE_ON_VSYNC is set SF only processes
  * buffer updates on VSYNC and performs a refresh immediately
  * after.
@@ -143,6 +154,10 @@
  */
 #define INVALIDATE_ON_VSYNC 1
 
+void MessageQueue::invalidateTransactionNow() {
+    mHandler->dispatchTransaction();
+}
+
 void MessageQueue::invalidate() {
 #if INVALIDATE_ON_VSYNC
     mEvents->requestNextVsync();
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index 710b2c2..b77e08e 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -62,8 +62,9 @@
 class MessageQueue {
     class Handler : public MessageHandler {
         enum {
-            eventMaskInvalidate = 0x1,
-            eventMaskRefresh    = 0x2
+            eventMaskInvalidate     = 0x1,
+            eventMaskRefresh        = 0x2,
+            eventMaskTransaction    = 0x4
         };
         MessageQueue& mQueue;
         int32_t mEventMask;
@@ -72,6 +73,7 @@
         virtual void handleMessage(const Message& message);
         void dispatchRefresh();
         void dispatchInvalidate();
+        void dispatchTransaction();
     };
 
     friend class Handler;
@@ -89,8 +91,9 @@
 
 public:
     enum {
-        INVALIDATE = 0,
-        REFRESH    = 1,
+        INVALIDATE  = 0,
+        REFRESH     = 1,
+        TRANSACTION = 2
     };
 
     MessageQueue();
@@ -100,8 +103,13 @@
 
     void waitMessage();
     status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
+
+    // sends INVALIDATE message at next VSYNC
     void invalidate();
+    // sends REFRESH message at next VSYNC
     void refresh();
+    // sends TRANSACTION message immediately
+    void invalidateTransactionNow();
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3ed8b1b..32b97eb 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -744,6 +744,9 @@
 void SurfaceFlinger::onMessageReceived(int32_t what) {
     ATRACE_CALL();
     switch (what) {
+    case MessageQueue::TRANSACTION:
+        handleMessageTransaction();
+        break;
     case MessageQueue::INVALIDATE:
         handleMessageTransaction();
         handleMessageInvalidate();
@@ -1102,12 +1105,14 @@
                         // Call makeCurrent() on the primary display so we can
                         // be sure that nothing associated with this display
                         // is current.
-                        const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-                        DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
-                        mDisplays.removeItem(draw.keyAt(i));
-                        getHwComposer().disconnectDisplay(draw[i].type);
+                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
+                        DisplayDevice::makeCurrent(mEGLDisplay, defaultDisplay, mEGLContext);
+                        sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
+                        if (hw != NULL)
+                            hw->disconnect(getHwComposer());
                         if (draw[i].type < DisplayDevice::NUM_DISPLAY_TYPES)
                             mEventThread->onHotplugReceived(draw[i].type, false);
+                        mDisplays.removeItem(draw.keyAt(i));
                     } else {
                         ALOGW("trying to remove the main display");
                     }
@@ -1120,6 +1125,9 @@
                         // recreating the DisplayDevice, so we just remove it
                         // from the drawing state, so that it get re-added
                         // below.
+                        sp<DisplayDevice> hw(getDisplayDevice(display));
+                        if (hw != NULL)
+                            hw->disconnect(getHwComposer());
                         mDisplays.removeItem(display);
                         mDrawingState.displays.removeItemsAt(i);
                         dc--; i--;
@@ -1150,9 +1158,13 @@
                     const DisplayDeviceState& state(curr[i]);
 
                     sp<DisplaySurface> dispSurface;
-                    int32_t hwcDisplayId = allocateHwcDisplayId(state.type);
+                    int32_t hwcDisplayId = -1;
                     if (state.isVirtualDisplay()) {
+                        // Virtual displays without a surface are dormant:
+                        // they have external state (layer stack, projection,
+                        // etc.) but no internal state (i.e. a DisplayDevice).
                         if (state.surface != NULL) {
+                            hwcDisplayId = allocateHwcDisplayId(state.type);
                             dispSurface = new VirtualDisplaySurface(
                                     *mHwc, hwcDisplayId, state.surface,
                                     state.displayName);
@@ -1162,7 +1174,7 @@
                                 "adding a supported display, but rendering "
                                 "surface is provided (%p), ignoring it",
                                 state.surface.get());
-
+                        hwcDisplayId = allocateHwcDisplayId(state.type);
                         // for supported (by hwc) displays we provide our
                         // own rendering surface
                         dispSurface = new FramebufferSurface(*mHwc, state.type);
@@ -1178,8 +1190,15 @@
                                 state.viewport, state.frame);
                         hw->setDisplayName(state.displayName);
                         mDisplays.add(display, hw);
-                        if (state.type < DisplayDevice::NUM_DISPLAY_TYPES)
+                        if (state.isVirtualDisplay()) {
+                            if (hwcDisplayId >= 0) {
+                                mHwc->setVirtualDisplayProperties(hwcDisplayId,
+                                        hw->getWidth(), hw->getHeight(),
+                                        hw->getFormat());
+                            }
+                        } else {
                             mEventThread->onHotplugReceived(state.type, true);
+                        }
                     }
                 }
             }
@@ -1360,14 +1379,14 @@
                     if (tr.transformed()) {
                         if (tr.preserveRects()) {
                             // transform the transparent region
-                            transparentRegion = tr.transform(s.transparentRegion);
+                            transparentRegion = tr.transform(s.activeTransparentRegion);
                         } else {
                             // transformation too complex, can't do the
                             // transparent region optimization.
                             transparentRegion.clear();
                         }
                     } else {
-                        transparentRegion = s.transparentRegion;
+                        transparentRegion = s.activeTransparentRegion;
                     }
                 }
 
@@ -2610,6 +2629,13 @@
         }
     };
 
+    // make sure to process transactions before screenshots -- a transaction
+    // might already be pending but scheduled for VSYNC; this guarantees we
+    // will handle it before the screenshot. When VSYNC finally arrives
+    // the scheduled transaction will be a no-op. If no transactions are
+    // scheduled at this time, this will end-up being a no-op as well.
+    mEventQueue.invalidateTransactionNow();
+
     sp<MessageBase> msg = new MessageCaptureScreen(this,
             display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ,
             isCpuConsumer);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f0e6deb..57ee8b9 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -108,9 +108,6 @@
     // utility function to delete a texture on the main thread
     void deleteTextureAsync(GLuint texture);
 
-    // allocate a h/w composer display id
-    int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type);
-
     // enable/disable h/w composer event
     // TODO: this should be made accessible only to EventThread
     void eventControl(int disp, int event, int enabled);
@@ -338,6 +335,9 @@
     // region of all screens presenting this layer stack.
     void invalidateLayerStack(uint32_t layerStack, const Region& dirty);
 
+    // allocate a h/w composer display id
+    int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type);
+
     /* ------------------------------------------------------------------------
      * H/W composer
      */