Reconcile with jb-mr1-factory-release jb-mr1-release - do not merge

Change-Id: I219247f1b0f5d87b4144dc1535039e93fc636a94
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index ef5c2e9..f3fcca0 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -85,6 +85,7 @@
     dump_file("ZONEINFO", "/proc/zoneinfo");
     dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
     dump_file("BUDDYINFO", "/proc/buddyinfo");
+    dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
 
 
     dump_file("KERNEL WAKELOCKS", "/proc/wakelocks");
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 002aafc..6500ad5 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -69,7 +69,8 @@
     /* create a display
      * requires ACCESS_SURFACE_FLINGER permission.
      */
-    virtual sp<IBinder> createDisplay(const String8& displayName) = 0;
+    virtual sp<IBinder> createDisplay(const String8& displayName,
+            bool secure) = 0;
 
     /* get the token for the existing default displays. possible values
      * for id are eDisplayIdMain and eDisplayIdHdmi.
@@ -108,9 +109,6 @@
     /* returns information about a display
      * intended to be used to get information about built-in displays */
     virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) = 0;
-
-    /* connects to an external display */
-    virtual void connectDisplay(const sp<ISurfaceTexture>& display) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 21d16a9..ae5d69a 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -86,7 +86,7 @@
     );
 
     //! Create a display
-    static sp<IBinder> createDisplay(const String8& displayName);
+    static sp<IBinder> createDisplay(const String8& displayName, bool secure);
 
     //! Get the token for the existing default displays.
     //! Possible values for id are eDisplayIdMain and eDisplayIdHdmi.
diff --git a/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h
index c7dc354..c3a4d6b 100644
--- a/include/ui/DisplayInfo.h
+++ b/include/ui/DisplayInfo.h
@@ -32,7 +32,8 @@
     float fps;
     float density;
     uint8_t orientation;
-    uint8_t reserved[3];
+    bool secure;
+    uint8_t reserved[2];
     // TODO: this needs to go away (currently needed only by webkit)
     PixelFormatInfo pixelFormatInfo;
 };
diff --git a/include/utils/Trace.h b/include/utils/Trace.h
index e5cc7ec..93e2285 100644
--- a/include/utils/Trace.h
+++ b/include/utils/Trace.h
@@ -67,6 +67,11 @@
 // function body.
 #define ATRACE_CALL() android::ScopedTrace ___tracer(ATRACE_TAG, __FUNCTION__)
 
+// ATRACE_NAME traces the beginning and end of the current function.  To trace
+// the correct start and end times this macro should be the first line of the
+// function body.
+#define ATRACE_NAME(name) android::ScopedTrace ___tracer(ATRACE_TAG, name)
+
 // ATRACE_INT traces a named integer value.  This can be used to track how the
 // value changes over time in a trace.
 #define ATRACE_INT(name, value) android::Tracer::traceCounter(ATRACE_TAG, name, value)
diff --git a/include/utils/VectorImpl.h b/include/utils/VectorImpl.h
index b1224c6..c4ec2ff 100644
--- a/include/utils/VectorImpl.h
+++ b/include/utils/VectorImpl.h
@@ -104,6 +104,16 @@
     virtual void            do_splat(void* dest, const void* item, size_t num) const = 0;
     virtual void            do_move_forward(void* dest, const void* from, size_t num) const = 0;
     virtual void            do_move_backward(void* dest, const void* from, size_t num) const = 0;
+
+    // take care of FBC...
+    virtual void            reservedVectorImpl1();
+    virtual void            reservedVectorImpl2();
+    virtual void            reservedVectorImpl3();
+    virtual void            reservedVectorImpl4();
+    virtual void            reservedVectorImpl5();
+    virtual void            reservedVectorImpl6();
+    virtual void            reservedVectorImpl7();
+    virtual void            reservedVectorImpl8();
     
 private:
         void* _grow(size_t where, size_t amount);
@@ -155,6 +165,16 @@
 protected:
     virtual int             do_compare(const void* lhs, const void* rhs) const = 0;
 
+    // take care of FBC...
+    virtual void            reservedSortedVectorImpl1();
+    virtual void            reservedSortedVectorImpl2();
+    virtual void            reservedSortedVectorImpl3();
+    virtual void            reservedSortedVectorImpl4();
+    virtual void            reservedSortedVectorImpl5();
+    virtual void            reservedSortedVectorImpl6();
+    virtual void            reservedSortedVectorImpl7();
+    virtual void            reservedSortedVectorImpl8();
+
 private:
             ssize_t         _indexOrderOf(const void* item, size_t* order = 0) const;
 
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index d408476..590946a 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -385,18 +385,8 @@
             (uint32_t(buffer->format) != format) ||
             ((uint32_t(buffer->usage) & usage) != usage))
         {
-            status_t error;
-            sp<GraphicBuffer> graphicBuffer(
-                    mGraphicBufferAlloc->createGraphicBuffer(
-                            w, h, format, usage, &error));
-            if (graphicBuffer == 0) {
-                ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
-                        "failed");
-                return error;
-            }
-
             mSlots[buf].mAcquireCalled = false;
-            mSlots[buf].mGraphicBuffer = graphicBuffer;
+            mSlots[buf].mGraphicBuffer = NULL;
             mSlots[buf].mRequestBufferCalled = false;
             mSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
             mSlots[buf].mFence.clear();
@@ -412,6 +402,30 @@
         mSlots[buf].mFence.clear();
     }  // end lock scope
 
+    if (returnFlags & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) {
+        status_t error;
+        sp<GraphicBuffer> graphicBuffer(
+                mGraphicBufferAlloc->createGraphicBuffer(
+                        w, h, format, usage, &error));
+        if (graphicBuffer == 0) {
+            ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
+                    "failed");
+            return error;
+        }
+
+        { // Scope for the lock
+            Mutex::Autolock lock(mMutex);
+
+            if (mAbandoned) {
+                ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
+                return NO_INIT;
+            }
+
+            mSlots[*outBuf].mGraphicBuffer = graphicBuffer;
+        }
+    }
+
+
     if (eglFence != EGL_NO_SYNC_KHR) {
         EGLint result = eglClientWaitSyncKHR(dpy, eglFence, 0, 1000000000);
         // If something goes wrong, log the error, but return the buffer without
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index aff1b45..85a9488 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -179,11 +179,12 @@
         return result;
     }
 
-    virtual sp<IBinder> createDisplay(const String8& displayName)
+    virtual sp<IBinder> createDisplay(const String8& displayName, bool secure)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeString8(displayName);
+        data.writeInt32(secure ? 1 : 0);
         remote()->transact(BnSurfaceComposer::CREATE_DISPLAY, data, &reply);
         return reply.readStrongBinder();
     }
@@ -222,14 +223,6 @@
         memcpy(info, reply.readInplace(sizeof(DisplayInfo)), sizeof(DisplayInfo));
         return reply.readInt32();
     }
-
-
-    virtual void connectDisplay(const sp<ISurfaceTexture>& display) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        data.writeStrongBinder(display->asBinder());
-        remote()->transact(BnSurfaceComposer::CONNECT_DISPLAY, data, &reply);
-    }
 };
 
 IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");
@@ -309,7 +302,8 @@
         case CREATE_DISPLAY: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             String8 displayName = data.readString8();
-            sp<IBinder> display(createDisplay(displayName));
+            bool secure = bool(data.readInt32());
+            sp<IBinder> display(createDisplay(displayName, secure));
             reply->writeStrongBinder(display);
             return NO_ERROR;
         } break;
@@ -338,12 +332,6 @@
             memcpy(reply->writeInplace(sizeof(DisplayInfo)), &info, sizeof(DisplayInfo));
             reply->writeInt32(result);
         } break;
-        case CONNECT_DISPLAY: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<ISurfaceTexture> surfaceTexture =
-                    interface_cast<ISurfaceTexture>(data.readStrongBinder());
-            connectDisplay(surfaceTexture);
-        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 8586ed2..80dd6ee 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -131,7 +131,7 @@
     DisplayState& getDisplayStateLocked(const sp<IBinder>& token);
 
 public:
-    sp<IBinder> createDisplay(const String8& displayName);
+    sp<IBinder> createDisplay(const String8& displayName, bool secure);
     sp<IBinder> getBuiltInDisplay(int32_t id);
 
     status_t setPosition(const sp<SurfaceComposerClient>& client, SurfaceID id,
@@ -175,8 +175,9 @@
 
 // ---------------------------------------------------------------------------
 
-sp<IBinder> Composer::createDisplay(const String8& displayName) {
-    return ComposerService::getComposerService()->createDisplay(displayName);
+sp<IBinder> Composer::createDisplay(const String8& displayName, bool secure) {
+    return ComposerService::getComposerService()->createDisplay(displayName,
+            secure);
 }
 
 sp<IBinder> Composer::getBuiltInDisplay(int32_t id) {
@@ -459,8 +460,9 @@
     return result;
 }
 
-sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName) {
-    return Composer::getInstance().createDisplay(displayName);
+sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName,
+        bool secure) {
+    return Composer::getInstance().createDisplay(displayName, secure);
 }
 
 sp<IBinder> SurfaceComposerClient::getBuiltInDisplay(int32_t id) {
diff --git a/libs/utils/VectorImpl.cpp b/libs/utils/VectorImpl.cpp
index 8083bba..c3257bb 100644
--- a/libs/utils/VectorImpl.cpp
+++ b/libs/utils/VectorImpl.cpp
@@ -494,6 +494,15 @@
     do_move_backward(dest, from, num);
 }
 
+void VectorImpl::reservedVectorImpl1() { }
+void VectorImpl::reservedVectorImpl2() { }
+void VectorImpl::reservedVectorImpl3() { }
+void VectorImpl::reservedVectorImpl4() { }
+void VectorImpl::reservedVectorImpl5() { }
+void VectorImpl::reservedVectorImpl6() { }
+void VectorImpl::reservedVectorImpl7() { }
+void VectorImpl::reservedVectorImpl8() { }
+
 /*****************************************************************************/
 
 SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags)
@@ -609,6 +618,16 @@
     return i;
 }
 
+void SortedVectorImpl::reservedSortedVectorImpl1() { };
+void SortedVectorImpl::reservedSortedVectorImpl2() { };
+void SortedVectorImpl::reservedSortedVectorImpl3() { };
+void SortedVectorImpl::reservedSortedVectorImpl4() { };
+void SortedVectorImpl::reservedSortedVectorImpl5() { };
+void SortedVectorImpl::reservedSortedVectorImpl6() { };
+void SortedVectorImpl::reservedSortedVectorImpl7() { };
+void SortedVectorImpl::reservedSortedVectorImpl8() { };
+
+
 /*****************************************************************************/
 
 }; // namespace android
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 7ca210c..96e1cba 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -62,12 +62,18 @@
 // ----------------------------------------------------------------------------
 
 /**
- * There are two different tracing methods:
- * 1. libs/EGL/trace.cpp: Traces all functions to logcat.
+ * There are three different tracing methods:
+ * 1. libs/EGL/trace.cpp: Traces all functions to systrace.
+ *    To enable:
+ *      - set system property "debug.egl.trace" to "systrace" to trace all apps.
+ * 2. libs/EGL/trace.cpp: Logs a stack trace for GL errors after each function call.
+ *    To enable:
+ *      - set system property "debug.egl.trace" to "error" to trace all apps.
+ * 3. libs/EGL/trace.cpp: Traces all functions to logcat.
  *    To enable:
  *      - set system property "debug.egl.trace" to 1 to trace all apps.
  *      - or call setGLTraceLevel(1) from an app to enable tracing for that app.
- * 2. libs/GLES_trace: Traces all functions via protobuf to host.
+ * 4. libs/GLES_trace: Traces all functions via protobuf to host.
  *    To enable:
  *        - set system property "debug.egl.debug_proc" to the application name.
  *      - or call setGLDebugLevel(1) from the app.
@@ -75,10 +81,15 @@
 static int sEGLTraceLevel;
 static int sEGLApplicationTraceLevel;
 
+static bool sEGLSystraceEnabled;
+static bool sEGLGetErrorEnabled;
+
 int gEGLDebugLevel;
 static int sEGLApplicationDebugLevel;
 
 extern gl_hooks_t gHooksTrace;
+extern gl_hooks_t gHooksSystrace;
+extern gl_hooks_t gHooksErrorTrace;
 
 static inline void setGlTraceThreadSpecific(gl_hooks_t const *value) {
     pthread_setspecific(gGLTraceKey, value);
@@ -91,6 +102,20 @@
 void initEglTraceLevel() {
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.egl.trace", value, "0");
+
+    sEGLGetErrorEnabled = !strcasecmp(value, "error");
+    if (sEGLGetErrorEnabled) {
+        sEGLSystraceEnabled = false;
+        sEGLTraceLevel = 0;
+        return;
+    }
+
+    sEGLSystraceEnabled = !strcasecmp(value, "systrace");
+    if (sEGLSystraceEnabled) {
+        sEGLTraceLevel = 0;
+        return;
+    }
+
     int propertyLevel = atoi(value);
     int applicationLevel = sEGLApplicationTraceLevel;
     sEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
@@ -125,7 +150,13 @@
 }
 
 void setGLHooksThreadSpecific(gl_hooks_t const *value) {
-    if (sEGLTraceLevel > 0) {
+    if (sEGLGetErrorEnabled) {
+        setGlTraceThreadSpecific(value);
+        setGlThreadSpecific(&gHooksErrorTrace);
+    } else if (sEGLSystraceEnabled) {
+        setGlTraceThreadSpecific(value);
+        setGlThreadSpecific(&gHooksSystrace);
+    } else if (sEGLTraceLevel > 0) {
         setGlTraceThreadSpecific(value);
         setGlThreadSpecific(&gHooksTrace);
     } else if (gEGLDebugLevel > 0 && value != &gHooksNoContext) {
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 92023ba..23e89da 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -204,6 +204,59 @@
 
     egl_connection_t* const cnx = &gEGLImpl;
     if (cnx->dso) {
+        if (attrib_list) {
+            char value[PROPERTY_VALUE_MAX];
+            property_get("debug.egl.force_msaa", value, "false");
+
+            if (!strcmp(value, "true")) {
+                size_t attribCount = 0;
+                EGLint attrib = attrib_list[0];
+
+                // Only enable MSAA if the context is OpenGL ES 2.0 and
+                // if no caveat is requested
+                const EGLint *attribRendererable = NULL;
+                const EGLint *attribCaveat = NULL;
+
+                // Count the number of attributes and look for
+                // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
+                while (attrib != EGL_NONE) {
+                    attrib = attrib_list[attribCount];
+                    switch (attrib) {
+                        case EGL_RENDERABLE_TYPE:
+                            attribRendererable = &attrib_list[attribCount];
+                            break;
+                        case EGL_CONFIG_CAVEAT:
+                            attribCaveat = &attrib_list[attribCount];
+                            break;
+                    }
+                    attribCount++;
+                }
+
+                if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
+                        (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
+    
+                    // Insert 2 extra attributes to force-enable MSAA 4x
+                    EGLint aaAttribs[attribCount + 4];
+                    aaAttribs[0] = EGL_SAMPLE_BUFFERS;
+                    aaAttribs[1] = 1;
+                    aaAttribs[2] = EGL_SAMPLES;
+                    aaAttribs[3] = 4;
+
+                    memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
+
+                    EGLint numConfigAA;
+                    EGLBoolean resAA = cnx->egl.eglChooseConfig(
+                            dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
+
+                    if (resAA == EGL_TRUE && numConfigAA > 0) {
+                        ALOGD("Enabling MSAA 4x");
+                        *num_config = numConfigAA;
+                        return resAA;
+                    }
+                }
+            }
+        }
+
         res = cnx->egl.eglChooseConfig(
                 dp->disp.dpy, attrib_list, configs, config_size, num_config);
     }
diff --git a/opengl/libs/EGL/trace.cpp b/opengl/libs/EGL/trace.cpp
index 52907c1..a51b086 100644
--- a/opengl/libs/EGL/trace.cpp
+++ b/opengl/libs/EGL/trace.cpp
@@ -26,6 +26,11 @@
 
 #include <cutils/log.h>
 
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <utils/Trace.h>
+
+#include <utils/CallStack.h>
+
 #include "egl_tls.h"
 #include "hooks.h"
 
@@ -314,6 +319,10 @@
     va_end(argp);
 }
 
+///////////////////////////////////////////////////////////////////////////
+// Log trace
+///////////////////////////////////////////////////////////////////////////
+
 #undef TRACE_GL_VOID
 #undef TRACE_GL
 
@@ -349,7 +358,6 @@
 };
 #undef GL_ENTRY
 
-
 #undef TRACE_GL_VOID
 #undef TRACE_GL
 
@@ -372,6 +380,99 @@
 #include "../debug.in"
 }
 
+///////////////////////////////////////////////////////////////////////////
+// Systrace
+///////////////////////////////////////////////////////////////////////////
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+#define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
+static void Systrace_ ## _api _args {                                     \
+    ATRACE_NAME(#_api);                                                   \
+    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
+    _c->_api _argList;                                                    \
+}
+
+#define TRACE_GL(_type, _api, _args, _argList, ...)                       \
+static _type Systrace_ ## _api _args {                                    \
+    ATRACE_NAME(#_api);                                                   \
+    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
+    return _c->_api _argList;                                             \
+}
+
+extern "C" {
+#include "../trace.in"
+}
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+#define GL_ENTRY(_r, _api, ...) Systrace_ ## _api,
+EGLAPI gl_hooks_t gHooksSystrace = {
+    {
+        #include "entries.in"
+    },
+    {
+        {0}
+    }
+};
+#undef GL_ENTRY
+
+///////////////////////////////////////////////////////////////////////////
+//
+///////////////////////////////////////////////////////////////////////////
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+#define CHECK_ERROR(_c, _api)                                             \
+    GLenum status = GL_NO_ERROR;                                          \
+    bool error = false;                                                   \
+    while ((status = _c->glGetError()) != GL_NO_ERROR) {                  \
+        ALOGD("[" #_api "] 0x%x", status);                                \
+        error = true;                                                     \
+    }                                                                     \
+    if (error) {                                                          \
+        CallStack s;                                                      \
+        s.update();                                                       \
+        s.dump("glGetError:" #_api);                                      \
+    }                                                                     \
+
+#define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
+static void ErrorTrace_ ## _api _args {                                   \
+    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
+    _c->_api _argList;                                                    \
+    CHECK_ERROR(_c, _api);                                                \
+}
+
+#define TRACE_GL(_type, _api, _args, _argList, ...)                       \
+static _type ErrorTrace_ ## _api _args {                                  \
+    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
+    _type _r = _c->_api _argList;                                         \
+    CHECK_ERROR(_c, _api);                                                \
+    return _r;                                                            \
+}
+
+extern "C" {
+#include "../trace.in"
+}
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+#define GL_ENTRY(_r, _api, ...) ErrorTrace_ ## _api,
+EGLAPI gl_hooks_t gHooksErrorTrace = {
+    {
+        #include "entries.in"
+    },
+    {
+        {0}
+    }
+};
+#undef GL_ENTRY
+#undef CHECK_ERROR
+
 #undef TRACE_GL_VOID
 #undef TRACE_GL
 
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index 2d0045e..55ef499 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -26,11 +26,6 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <utils/Trace.h>
-
-#include <utils/CallStack.h>
-
 #include "hooks.h"
 #include "egl_impl.h"
 
@@ -44,10 +39,6 @@
 #undef CALL_GL_API
 #undef CALL_GL_API_RETURN
 
-#define DEBUG_CALL_GL_API 0
-#define DEBUG_PRINT_CALL_STACK_ON_ERROR 0
-#define SYSTRACE_CALL_GL_API 0
-
 #if USE_FAST_TLS_KEY
 
     #ifdef HAVE_ARM_TLS_REGISTER
@@ -83,38 +74,10 @@
 
     #define API_ENTRY(_api) _api
 
-#if DEBUG_CALL_GL_API
-
-    #define CALL_GL_API(_api, ...)                                       \
-        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
-        _c->_api(__VA_ARGS__); \
-        GLenum status = GL_NO_ERROR; \
-        bool error = false; \
-        while ((status = glGetError()) != GL_NO_ERROR) { \
-            ALOGD("[" #_api "] 0x%x", status); \
-            error = true; \
-        } \
-        if (DEBUG_PRINT_CALL_STACK_ON_ERROR && error) { \
-            CallStack s; \
-            s.update(); \
-            s.dump("glGetError:" #_api); \
-        }
-
-#elif SYSTRACE_CALL_GL_API
-
-    #define CALL_GL_API(_api, ...)                                       \
-        ATRACE_CALL();                                                   \
-        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
-        _c->_api(__VA_ARGS__);
-
-#else
-
     #define CALL_GL_API(_api, ...)                                       \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
         _c->_api(__VA_ARGS__);
 
-#endif
-
     #define CALL_GL_API_RETURN(_api, ...)                                \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
         return _c->_api(__VA_ARGS__)
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 40631ee..ce98b67 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -69,7 +69,9 @@
 
 DisplayDevice::DisplayDevice(
         const sp<SurfaceFlinger>& flinger,
-        DisplayType type, const wp<IBinder>& displayToken,
+        DisplayType type,
+        bool isSecure,
+        const wp<IBinder>& displayToken,
         const sp<ANativeWindow>& nativeWindow,
         const sp<FramebufferSurface>& framebufferSurface,
         EGLConfig config)
@@ -83,6 +85,7 @@
       mDisplayWidth(), mDisplayHeight(), mFormat(),
       mFlags(),
       mPageFlipCount(),
+      mIsSecure(isSecure),
       mSecureLayerVisible(false),
       mScreenAcquired(false),
       mLayerStack(0),
@@ -431,13 +434,13 @@
     snprintf(buffer, SIZE,
         "+ DisplayDevice: %s\n"
         "   type=%x, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
-        "flips=%u, secure=%d, acquired=%d, numLayers=%u\n"
+        "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n"
         "   v:[%d,%d,%d,%d], f:[%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,
         mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
         mOrientation, tr.getType(), getPageFlipCount(),
-        mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
+        mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
         mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
         mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
         tr[0][0], tr[1][0], tr[2][0],
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 058680b..d6da422 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -67,7 +67,9 @@
 
     DisplayDevice(
             const sp<SurfaceFlinger>& flinger,
-            DisplayType type, const wp<IBinder>& displayToken,
+            DisplayType type,
+            bool isSecure,
+            const wp<IBinder>& displayToken,
             const sp<ANativeWindow>& nativeWindow,
             const sp<FramebufferSurface>& framebufferSurface,
             EGLConfig config);
@@ -78,6 +80,10 @@
     // when an non existing id is requested
     bool isValid() const;
 
+    // isSecure indicates whether this display can be trusted to display
+    // secure surfaces.
+    bool isSecure() const { return mIsSecure; }
+
     // Flip the front and back buffers if the back buffer is "dirty".  Might
     // be instantaneous, might involve copying the frame buffer around.
     void flip(const Region& dirty) const;
@@ -167,6 +173,7 @@
     uint32_t        mFlags;
     mutable uint32_t mPageFlipCount;
     String8         mDisplayName;
+    bool            mIsSecure;
 
     /*
      * Can only accessed from the main thread, these members
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index d9bda11..31d731e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -128,6 +128,11 @@
         abort();
     }
 
+    // these display IDs are always reserved
+    for (size_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
+        mAllocatedDisplayIDs.markBit(i);
+    }
+
     if (mHwc) {
         ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
               (hwcApiVersion(mHwc) >> 24) & 0xff,
@@ -149,11 +154,6 @@
         // always turn vsync off when we start
         eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
 
-        // these IDs are always reserved
-        for (size_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
-            mAllocatedDisplayIDs.markBit(i);
-        }
-
         // the number of displays we actually have depends on the
         // hw composer version
         if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
@@ -445,6 +445,13 @@
 
 void HWComposer::eventControl(int disp, int event, int enabled) {
     if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) {
+        ALOGD("eventControl ignoring event %d on unallocated disp %d (en=%d)",
+              event, disp, enabled);
+        return;
+    }
+    if (event != EVENT_VSYNC) {
+        ALOGW("eventControl got unexpected event %d (disp=%d en=%d)",
+              event, disp, enabled);
         return;
     }
     status_t err = NO_ERROR;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c2da238..064f689 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -253,6 +253,10 @@
         layer.setSkip(true);
     }
 
+    if (isSecure() && !hw->isSecure()) {
+        layer.setSkip(true);
+    }
+
     /*
      * Transformations are applied in this order:
      * 1) buffer orientation/flip/mirror
@@ -342,7 +346,9 @@
         // is probably going to have something visibly wrong.
     }
 
-    if (!isProtected()) {
+    bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure());
+
+    if (!blackOutLayer) {
         // TODO: we could be more subtle with isFixedSize()
         const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize();
 
diff --git a/services/surfaceflinger/LayerScreenshot.cpp b/services/surfaceflinger/LayerScreenshot.cpp
index 0fd744f..f8009b3 100644
--- a/services/surfaceflinger/LayerScreenshot.cpp
+++ b/services/surfaceflinger/LayerScreenshot.cpp
@@ -37,7 +37,7 @@
 LayerScreenshot::LayerScreenshot(SurfaceFlinger* flinger,
         const sp<Client>& client)
     : LayerBaseClient(flinger, client),
-      mTextureName(0), mFlinger(flinger)
+      mTextureName(0), mFlinger(flinger), mIsSecure(false)
 {
 }
 
@@ -56,6 +56,10 @@
         return result;
     }
     initTexture(u, v);
+
+    // Currently screenshot always comes from the default display
+    mIsSecure = mFlinger->getDefaultDisplayDevice()->getSecureLayerVisible();
+
     return NO_ERROR;
 }
 
@@ -66,6 +70,10 @@
         return result;
     }
     initTexture(u, v);
+
+    // Currently screenshot always comes from the default display
+    mIsSecure = mFlinger->getDefaultDisplayDevice()->getSecureLayerVisible();
+    
     return NO_ERROR;
 }
 
@@ -84,6 +92,10 @@
     if (!(flags & ISurfaceComposerClient::eHidden)) {
         capture();
     }
+    if (flags & ISurfaceComposerClient::eSecure) {
+        ALOGW("ignoring surface flag eSecure - LayerScreenshot is considered "
+                "secure iff it captures the contents of a secure surface.");
+    }
 }
 
 uint32_t LayerScreenshot::doTransaction(uint32_t flags)
@@ -125,6 +137,11 @@
             glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
         }
 
+        GLuint texName = mTextureName;
+        if (isSecure() && !hw->isSecure()) {
+            texName = mFlinger->getProtectedTexName();
+        }
+
         LayerMesh mesh;
         computeGeometry(hw, &mesh);
 
@@ -133,7 +150,7 @@
         glDisable(GL_TEXTURE_EXTERNAL_OES);
         glEnable(GL_TEXTURE_2D);
 
-        glBindTexture(GL_TEXTURE_2D, mTextureName);
+        glBindTexture(GL_TEXTURE_2D, texName);
         glMatrixMode(GL_TEXTURE);
         glLoadIdentity();
         glMatrixMode(GL_MODELVIEW);
diff --git a/services/surfaceflinger/LayerScreenshot.h b/services/surfaceflinger/LayerScreenshot.h
index 7807ffc..38cbd88 100644
--- a/services/surfaceflinger/LayerScreenshot.h
+++ b/services/surfaceflinger/LayerScreenshot.h
@@ -34,6 +34,7 @@
     GLuint mTextureName;
     GLfloat mTexCoords[8];
     sp<SurfaceFlinger> mFlinger;
+    bool mIsSecure;
 public:    
             LayerScreenshot(SurfaceFlinger* flinger, const sp<Client>& client);
         virtual ~LayerScreenshot();
@@ -44,7 +45,7 @@
     virtual uint32_t doTransaction(uint32_t flags);
     virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const;
     virtual bool isOpaque() const         { return false; }
-    virtual bool isSecure() const         { return false; }
+    virtual bool isSecure() const         { return mIsSecure; }
     virtual bool isProtectedByApp() const { return false; }
     virtual bool isProtectedByDRM() const { return false; }
     virtual const char* getTypeId() const { return "LayerScreenshot"; }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e21e2bf..ce10c78 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -163,7 +163,8 @@
     return bclient;
 }
 
-sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName)
+sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName,
+        bool secure)
 {
     class DisplayToken : public BBinder {
         sp<SurfaceFlinger> flinger;
@@ -184,6 +185,7 @@
     Mutex::Autolock _l(mStateLock);
     DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL);
     info.displayName = displayName;
+    info.isSecure = secure;
     mCurrentState.displays.add(token, info);
 
     return token;
@@ -485,12 +487,14 @@
 
         // set-up the displays that are already connected
         if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
+            // All non-virtual displays are currently considered secure.
+            bool isSecure = true;
             mCurrentState.displays.add(token, DisplayDeviceState(type));
             sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i);
             sp<SurfaceTextureClient> stc = new SurfaceTextureClient(
                         static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));
             sp<DisplayDevice> hw = new DisplayDevice(this,
-                    type, token, stc, fbs, mEGLConfig);
+                    type, isSecure, token, stc, fbs, mEGLConfig);
             if (i > DisplayDevice::DISPLAY_PRIMARY) {
                 // FIXME: currently we don't get blank/unblank requests
                 // for displays other than the main display, so we always
@@ -507,7 +511,7 @@
     //  or when a texture is (asynchronously) destroyed, and for that
     //  we need a valid surface, so it's convenient to use the main display
     //  for that.
-    sp<const DisplayDevice> hw = getDefaultDisplayDevice();
+    sp<const DisplayDevice> hw(getDefaultDisplayDevice());
 
     //  initialize OpenGL ES
     DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
@@ -666,6 +670,10 @@
     info->xdpi = xdpi;
     info->ydpi = ydpi;
     info->fps = float(1e9 / hwc.getRefreshPeriod(type));
+
+    // All non-virtual displays are currently considered secure.
+    info->secure = true;
+
     return NO_ERROR;
 }
 
@@ -675,34 +683,6 @@
     return mEventThread->createEventConnection();
 }
 
-void SurfaceFlinger::connectDisplay(const sp<ISurfaceTexture>& surface) {
-
-    sp<IBinder> token;
-    { // scope for the lock
-        Mutex::Autolock _l(mStateLock);
-        token = mExtDisplayToken;
-    }
-
-    if (token == 0) {
-        token = createDisplay(String8("Display from connectDisplay"));
-    }
-
-    { // scope for the lock
-        Mutex::Autolock _l(mStateLock);
-        if (surface == 0) {
-            // release our current display. we're guarantee to have
-            // a reference to it (token), while we hold the lock
-            mExtDisplayToken = 0;
-        } else {
-            mExtDisplayToken = token;
-        }
-
-        DisplayDeviceState& info(mCurrentState.displays.editValueFor(token));
-        info.surface = surface;
-        setTransactionFlags(eDisplayTransactionNeeded);
-    }
-}
-
 // ----------------------------------------------------------------------------
 
 void SurfaceFlinger::waitForEvent() {
@@ -998,10 +978,10 @@
         if (hw->canDraw()) {
             // transform the dirty region into this screen's coordinate space
             const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
-            if (!dirtyRegion.isEmpty()) {
-                // repaint the framebuffer (if needed)
-                doDisplayComposition(hw, dirtyRegion);
-            }
+
+            // repaint the framebuffer (if needed)
+            doDisplayComposition(hw, dirtyRegion);
+
             hw->dirtyRegion.clear();
             hw->flip(hw->swapRegion);
             hw->swapRegion.clear();
@@ -1126,7 +1106,7 @@
                         // 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());
+                        const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
                         DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
                         mDisplays.removeItem(draw.keyAt(i));
                         getHwComposer().disconnectDisplay(draw[i].type);
@@ -1150,7 +1130,7 @@
                         continue;
                     }
 
-                    const sp<DisplayDevice>& disp(getDisplayDevice(display));
+                    const sp<DisplayDevice> disp(getDisplayDevice(display));
                     if (disp != NULL) {
                         if (state.layerStack != draw[i].layerStack) {
                             disp->setLayerStack(state.layerStack);
@@ -1183,6 +1163,7 @@
             for (size_t i=0 ; i<cc ; i++) {
                 if (draw.indexOfKey(curr.keyAt(i)) < 0) {
                     const DisplayDeviceState& state(curr[i]);
+                    bool isSecure = false;
 
                     sp<FramebufferSurface> fbs;
                     sp<SurfaceTextureClient> stc;
@@ -1193,21 +1174,28 @@
                                 "surface is provided (%p), ignoring it",
                                 state.surface.get());
 
+                        // All non-virtual displays are currently considered
+                        // secure.
+                        isSecure = true;
+
                         // for supported (by hwc) displays we provide our
                         // own rendering surface
                         fbs = new FramebufferSurface(*mHwc, state.type);
                         stc = new SurfaceTextureClient(
-                                static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));
+                                static_cast< sp<ISurfaceTexture> >(
+                                        fbs->getBufferQueue()));
                     } else {
                         if (state.surface != NULL) {
                             stc = new SurfaceTextureClient(state.surface);
                         }
+                        isSecure = state.isSecure;
                     }
 
                     const wp<IBinder>& display(curr.keyAt(i));
                     if (stc != NULL) {
                         sp<DisplayDevice> hw = new DisplayDevice(this,
-                                state.type, display, stc, fbs, mEGLConfig);
+                                state.type, isSecure, display, stc, fbs,
+                                mEGLConfig);
                         hw->setLayerStack(state.layerStack);
                         hw->setProjection(state.orientation,
                                 state.viewport, state.frame);
@@ -1512,6 +1500,28 @@
                 drawWormhole(hw, region);
             }
         }
+
+        if (hw->getDisplayType() >= DisplayDevice::DISPLAY_EXTERNAL) {
+            // TODO: just to be on the safe side, we don't set the
+            // scissor on the main display. It should never be needed
+            // anyways (though in theory it could since the API allows it).
+            const Rect& bounds(hw->getBounds());
+            const Transform& tr(hw->getTransform());
+            const Rect scissor(tr.transform(hw->getViewport()));
+            if (scissor != bounds) {
+                // scissor doesn't match the screen's dimensions, so we
+                // need to clear everything outside of it and enable
+                // the GL scissor so we don't draw anything where we shouldn't
+                const GLint height = hw->getHeight();
+                glScissor(scissor.left, height - scissor.bottom,
+                        scissor.getWidth(), scissor.getHeight());
+                // clear everything unscissored
+                glClearColor(0, 0, 0, 0);
+                glClear(GL_COLOR_BUFFER_BIT);
+                // enable scissor for this frame
+                glEnable(GL_SCISSOR_TEST);
+            }
+        }
     }
 
     /*
@@ -1564,6 +1574,9 @@
             }
         }
     }
+
+    // disable scissor at the end of the frame
+    glDisable(GL_SCISSOR_TEST);
 }
 
 void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& hw,
@@ -1664,6 +1677,7 @@
         const Vector<DisplayState>& displays,
         uint32_t flags)
 {
+    ATRACE_CALL();
     Mutex::Autolock _l(mStateLock);
     uint32_t transactionFlags = 0;
 
@@ -1671,11 +1685,12 @@
         // For window updates that are part of an animation we must wait for
         // previous animation "frames" to be handled.
         while (mAnimTransactionPending) {
-            status_t err = mTransactionCV.waitRelative(mStateLock, 500 * 1000);
+            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
             if (CC_UNLIKELY(err != NO_ERROR)) {
                 // just in case something goes wrong in SF, return to the
-                // caller after a few hundred microseconds.
-                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
+                // caller after a few seconds.
+                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out "
+                        "waiting for previous animation frame");
                 mAnimTransactionPending = false;
                 break;
             }
@@ -1691,8 +1706,23 @@
     count = state.size();
     for (size_t i=0 ; i<count ; i++) {
         const ComposerState& s(state[i]);
-        sp<Client> client( static_cast<Client *>(s.client.get()) );
-        transactionFlags |= setClientStateLocked(client, s.state);
+        // Here we need to check that the interface we're given is indeed
+        // one of our own. A malicious client could give us a NULL
+        // IInterface, or one of its own or even one of our own but a
+        // different type. All these situations would cause us to crash.
+        //
+        // NOTE: it would be better to use RTTI as we could directly check
+        // that we have a Client*. however, RTTI is disabled in Android.
+        if (s.client != NULL) {
+            sp<IBinder> binder = s.client->asBinder();
+            if (binder != NULL) {
+                String16 desc(binder->getInterfaceDescriptor());
+                if (desc == ISurfaceComposerClient::descriptor) {
+                    sp<Client> client( static_cast<Client *>(s.client.get()) );
+                    transactionFlags |= setClientStateLocked(client, s.state);
+                }
+            }
+        }
     }
 
     if (transactionFlags) {
@@ -2043,48 +2073,48 @@
 
 void SurfaceFlinger::unblank(const sp<IBinder>& display) {
     class MessageScreenAcquired : public MessageBase {
-        SurfaceFlinger* mFlinger;
-        const sp<DisplayDevice>& mHw;
+        SurfaceFlinger& mFlinger;
+        sp<IBinder> mDisplay;
     public:
-        MessageScreenAcquired(SurfaceFlinger* flinger,
-                const sp<DisplayDevice>& hw) : mFlinger(flinger), mHw(hw) { }
+        MessageScreenAcquired(SurfaceFlinger& flinger,
+                const sp<IBinder>& disp) : mFlinger(flinger), mDisplay(disp) { }
         virtual bool handler() {
-            mFlinger->onScreenAcquired(mHw);
+            const sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
+            if (hw == NULL) {
+                ALOGE("Attempt to unblank null display %p", mDisplay.get());
+            } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) {
+                ALOGW("Attempt to unblank virtual display");
+            } else {
+                mFlinger.onScreenAcquired(hw);
+            }
             return true;
         }
     };
-    const sp<DisplayDevice>& hw = getDisplayDevice(display);
-    if (hw == NULL) {
-        ALOGE("Attempt to unblank null display %p", display.get());
-    } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) {
-        ALOGW("Attempt to unblank virtual display");
-    } else {
-        sp<MessageBase> msg = new MessageScreenAcquired(this, hw);
-        postMessageSync(msg);
-    }
+    sp<MessageBase> msg = new MessageScreenAcquired(*this, display);
+    postMessageSync(msg);
 }
 
 void SurfaceFlinger::blank(const sp<IBinder>& display) {
     class MessageScreenReleased : public MessageBase {
-        SurfaceFlinger* mFlinger;
-        const sp<DisplayDevice>& mHw;
+        SurfaceFlinger& mFlinger;
+        sp<IBinder> mDisplay;
     public:
-        MessageScreenReleased(SurfaceFlinger* flinger,
-                const sp<DisplayDevice>& hw) : mFlinger(flinger), mHw(hw) { }
+        MessageScreenReleased(SurfaceFlinger& flinger,
+                const sp<IBinder>& disp) : mFlinger(flinger), mDisplay(disp) { }
         virtual bool handler() {
-            mFlinger->onScreenReleased(mHw);
+            const sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
+            if (hw == NULL) {
+                ALOGE("Attempt to blank null display %p", mDisplay.get());
+            } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) {
+                ALOGW("Attempt to blank virtual display");
+            } else {
+                mFlinger.onScreenReleased(hw);
+            }
             return true;
         }
     };
-    const sp<DisplayDevice>& hw = getDisplayDevice(display);
-    if (hw == NULL) {
-        ALOGE("Attempt to blank null display %p", display.get());
-    } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) {
-        ALOGW("Attempt to blank virtual display");
-    } else {
-        sp<MessageBase> msg = new MessageScreenReleased(this, hw);
-        postMessageSync(msg);
-    }
+    sp<MessageBase> msg = new MessageScreenReleased(*this, display);
+    postMessageSync(msg);
 }
 
 // ---------------------------------------------------------------------------
@@ -2359,6 +2389,7 @@
 
 const Vector< sp<LayerBase> >&
 SurfaceFlinger::getLayerSortedByZForHwcDisplay(int disp) {
+    // Note: mStateLock is held here
     return getDisplayDevice( getBuiltInDisplay(disp) )->getVisibleLayersSortedByZ();
 }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index efe34af..b0d3bac 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -140,6 +140,7 @@
     friend class LayerBase;
     friend class LayerBaseClient;
     friend class Layer;
+    friend class LayerScreenshot;
 
     // We're reference counted, never destroy SurfaceFlinger directly
     virtual ~SurfaceFlinger();
@@ -168,6 +169,7 @@
         Rect frame;
         uint8_t orientation;
         String8 displayName;
+        bool isSecure;
     };
 
     struct State {
@@ -187,7 +189,7 @@
      */
     virtual sp<ISurfaceComposerClient> createConnection();
     virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
-    virtual sp<IBinder> createDisplay(const String8& displayName);
+    virtual sp<IBinder> createDisplay(const String8& displayName, bool secure);
     virtual sp<IBinder> getBuiltInDisplay(int32_t id);
     virtual void setTransactionState(const Vector<ComposerState>& state,
             const Vector<DisplayState>& displays, uint32_t flags);
@@ -204,7 +206,6 @@
     // called when screen is turning back on
     virtual void unblank(const sp<IBinder>& display);
     virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info);
-    virtual void connectDisplay(const sp<ISurfaceTexture>& display);
 
     /* ------------------------------------------------------------------------
      * DeathRecipient interface
@@ -327,10 +328,13 @@
     // called when starting, or restarting after system_server death
     void initializeDisplays();
 
+    // NOTE: can only be called from the main thread or with mStateLock held
     sp<const DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) const {
         return mDisplays.valueFor(dpy);
     }
-    const sp<DisplayDevice>& getDisplayDevice(const wp<IBinder>& dpy) {
+
+    // NOTE: can only be called from the main thread or with mStateLock held
+    sp<DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) {
         return mDisplays.valueFor(dpy);
     }
 
@@ -425,6 +429,9 @@
     State mDrawingState;
     bool mVisibleRegionsDirty;
     bool mHwWorkListDirty;
+
+    // this may only be written from the main thread with mStateLock held
+    // it may be read from other threads with mStateLock held
     DefaultKeyedVector< wp<IBinder>, sp<DisplayDevice> > mDisplays;
 
     // don't use a lock for these, we don't care