Merge "Fix out-of-order transactions (2/2)" into oc-dr1-dev am: 0436b01d1b am: e89483f1bd
am: 5fd661362c

Change-Id: Ic5f1c2a2d92aad10ed3aa113b17e809037c2b697
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 34aec5b..74430e8 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -681,10 +681,10 @@
 
     const flat_binder_object *fb = reply.readObject(false);
     ASSERT_TRUE(fb != NULL);
-    EXPECT_EQ(fb->hdr.type, BINDER_TYPE_HANDLE);
-    EXPECT_EQ(ProcessState::self()->getStrongProxyForHandle(fb->handle), m_server);
-    EXPECT_EQ(fb->cookie, (binder_uintptr_t)0);
-    EXPECT_EQ(fb->binder >> 32, (binder_uintptr_t)0);
+    EXPECT_EQ(BINDER_TYPE_HANDLE, fb->hdr.type);
+    EXPECT_EQ(m_server, ProcessState::self()->getStrongProxyForHandle(fb->handle));
+    EXPECT_EQ((binder_uintptr_t)0, fb->cookie);
+    EXPECT_EQ((uint64_t)0, (uint64_t)fb->binder >> 32);
 }
 
 TEST_F(BinderLibTest, FreedBinder) {
diff --git a/opengl/tests/lib/include/EGLUtils.h b/opengl/tests/lib/include/EGLUtils.h
index 014c261..29f4fe4 100644
--- a/opengl/tests/lib/include/EGLUtils.h
+++ b/opengl/tests/lib/include/EGLUtils.h
@@ -20,11 +20,16 @@
 
 #include <stdint.h>
 #include <stdlib.h>
+#include <vector>
 
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
 #include <system/window.h>
 #include <utils/Errors.h>
-#include <EGL/egl.h>
+#include <utils/String8.h>
 
+EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 
 // ----------------------------------------------------------------------------
 namespace android {
@@ -47,6 +52,17 @@
             EGLint const* attrs,
             EGLNativeWindowType window,
             EGLConfig* outConfig);
+
+    static inline String8 printGLString(const char* name, GLenum s);
+    static inline String8 printEGLString(EGLDisplay dpy, const char* name, GLenum s);
+    static inline String8 checkEglError(const char* op, EGLBoolean returnVal);
+    static inline String8 checkGlError(const char* op);
+    static inline String8 printEGLConfiguration(EGLDisplay dpy, EGLConfig config);
+    static inline bool printEGLConfigurations(EGLDisplay dpy, String8& msg);
+    static inline bool printEGLConfigurations(FILE* output, EGLDisplay dpy);
+    static inline String8 decodeColorSpace(EGLint colorSpace);
+    static inline bool hasEglExtension(EGLDisplay dpy, const char* name);
+    static inline bool hasExtension(const char* exts, const char* name);
 };
 
 // ----------------------------------------------------------------------------
@@ -91,9 +107,8 @@
     if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE)
         return BAD_VALUE;
 
-    EGLConfig* const configs = (EGLConfig*)malloc(sizeof(EGLConfig)*numConfigs);
-    if (eglChooseConfig(dpy, attrs, configs, numConfigs, &n) == EGL_FALSE) {
-        free(configs);
+    std::vector<EGLConfig> configs(numConfigs);
+    if (eglChooseConfig(dpy, attrs, configs.data(), numConfigs, &n) == EGL_FALSE) {
         return BAD_VALUE;
     }
 
@@ -108,8 +123,6 @@
         }
     }
 
-    free(configs);
-
     if (i<n) {
         *outConfig = config;
         return NO_ERROR;
@@ -137,6 +150,159 @@
     return selectConfigForPixelFormat(dpy, attrs, format, outConfig);
 }
 
+String8 EGLUtils::printGLString(const char* name, GLenum s) {
+    String8 msg;
+    const char* v = reinterpret_cast<const char*>(glGetString(s));
+    msg.appendFormat("GL %s = %s\n", name, v);
+    return msg;
+}
+
+String8 EGLUtils::printEGLString(EGLDisplay dpy, const char* name, GLenum s) {
+    String8 msg;
+    const char* v = static_cast<const char*>(eglQueryString(dpy, s));
+    msg.appendFormat("GL %s = %s\n", name, v);
+    const char* va = (const char*)eglQueryStringImplementationANDROID(dpy, s);
+    msg.appendFormat("ImplementationANDROID: %s = %s\n", name, va);
+    return msg;
+}
+
+String8 EGLUtils::checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
+    String8 msg;
+    if (returnVal != EGL_TRUE) {
+        msg.appendFormat("%s() returned %d\n", op, returnVal);
+    }
+
+    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error = eglGetError()) {
+        msg.appendFormat("after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error), error);
+    }
+    return msg;
+}
+
+String8 EGLUtils::checkGlError(const char* op) {
+    String8 msg;
+    for (GLint error = glGetError(); error != GL_NO_ERROR; error = glGetError()) {
+        msg.appendFormat("after %s() glError (0x%x)\n", op, error);
+    }
+    return msg;
+}
+
+String8 EGLUtils::printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
+#define X(VAL) \
+    { VAL, #VAL }
+    struct {
+        EGLint attribute;
+        const char* name;
+    } names[] = {
+            X(EGL_BUFFER_SIZE),
+            X(EGL_ALPHA_SIZE),
+            X(EGL_BLUE_SIZE),
+            X(EGL_GREEN_SIZE),
+            X(EGL_RED_SIZE),
+            X(EGL_DEPTH_SIZE),
+            X(EGL_STENCIL_SIZE),
+            X(EGL_CONFIG_CAVEAT),
+            X(EGL_CONFIG_ID),
+            X(EGL_LEVEL),
+            X(EGL_MAX_PBUFFER_HEIGHT),
+            X(EGL_MAX_PBUFFER_PIXELS),
+            X(EGL_MAX_PBUFFER_WIDTH),
+            X(EGL_NATIVE_RENDERABLE),
+            X(EGL_NATIVE_VISUAL_ID),
+            X(EGL_NATIVE_VISUAL_TYPE),
+            X(EGL_SAMPLES),
+            X(EGL_SAMPLE_BUFFERS),
+            X(EGL_SURFACE_TYPE),
+            X(EGL_TRANSPARENT_TYPE),
+            X(EGL_TRANSPARENT_RED_VALUE),
+            X(EGL_TRANSPARENT_GREEN_VALUE),
+            X(EGL_TRANSPARENT_BLUE_VALUE),
+            X(EGL_BIND_TO_TEXTURE_RGB),
+            X(EGL_BIND_TO_TEXTURE_RGBA),
+            X(EGL_MIN_SWAP_INTERVAL),
+            X(EGL_MAX_SWAP_INTERVAL),
+            X(EGL_LUMINANCE_SIZE),
+            X(EGL_ALPHA_MASK_SIZE),
+            X(EGL_COLOR_BUFFER_TYPE),
+            X(EGL_RENDERABLE_TYPE),
+            X(EGL_CONFORMANT),
+    };
+#undef X
+
+    String8 msg;
+    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
+        EGLint value = -1;
+        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
+        EGLint error = eglGetError();
+        if (returnVal && error == EGL_SUCCESS) {
+            msg.appendFormat(" %s: %d (0x%x)", names[j].name, value, value);
+        }
+    }
+    msg.append("\n");
+    return msg;
+}
+
+bool EGLUtils::printEGLConfigurations(EGLDisplay dpy, String8& msg) {
+    EGLint numConfig = 0;
+    EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig);
+    msg.append(checkEglError("eglGetConfigs", returnVal));
+    if (!returnVal) {
+        return false;
+    }
+
+    msg.appendFormat("Number of EGL configuration: %d\n", numConfig);
+
+    std::vector<EGLConfig> configs(numConfig);
+
+    returnVal = eglGetConfigs(dpy, configs.data(), numConfig, &numConfig);
+    msg.append(checkEglError("eglGetConfigs", returnVal));
+    if (!returnVal) {
+        return false;
+    }
+
+    for (int i = 0; i < numConfig; i++) {
+        msg.appendFormat("Configuration %d\n", i);
+        msg.append(printEGLConfiguration(dpy, configs[i]));
+    }
+
+    return true;
+}
+
+bool EGLUtils::printEGLConfigurations(FILE* output, EGLDisplay dpy) {
+    String8 msg;
+    bool status = printEGLConfigurations(dpy, msg);
+    fprintf(output, "%s", msg.c_str());
+    return status;
+}
+
+String8 EGLUtils::decodeColorSpace(EGLint colorSpace) {
+    switch (colorSpace) {
+        case EGL_GL_COLORSPACE_SRGB_KHR:
+            return String8("EGL_GL_COLORSPACE_SRGB_KHR");
+        case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
+            return String8("EGL_GL_COLORSPACE_DISPLAY_P3_EXT");
+        case  EGL_GL_COLORSPACE_LINEAR_KHR:
+            return String8("EGL_GL_COLORSPACE_LINEAR_KHR");
+        default:
+            return String8::format("UNKNOWN ColorSpace %d", colorSpace);
+    }
+}
+
+bool EGLUtils::hasExtension(const char* exts, const char* name) {
+    size_t nameLen = strlen(name);
+    if (exts) {
+        for (const char* match = strstr(exts, name); match; match = strstr(match + nameLen, name)) {
+            if (match[nameLen] == '\0' || match[nameLen] == ' ') {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool EGLUtils::hasEglExtension(EGLDisplay dpy, const char* name) {
+    return hasExtension(eglQueryString(dpy, EGL_EXTENSIONS), name);
+}
+
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
index 60916f3..d97ffa3 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
@@ -36,7 +36,6 @@
 #include <thread>
 
 constexpr Config NULL_DISPLAY_CONFIG = static_cast<Config>(0);
-constexpr Display DEFAULT_DISPLAY = static_cast<Display>(1);
 
 using namespace sftest;
 
@@ -168,7 +167,7 @@
     ALOGV("enableCallback");
     mCallbacksOn = enable;
     if (mCallbacksOn) {
-        mClient->onHotplug(DEFAULT_DISPLAY, IComposerCallback::Connection::CONNECTED);
+        mClient->onHotplug(PRIMARY_DISPLAY, IComposerCallback::Connection::CONNECTED);
     }
 }
 
@@ -507,7 +506,7 @@
         if (mSurfaceComposer != nullptr) {
             mSurfaceComposer->injectVSync(timestamp);
         } else {
-            mClient->onVsync(DEFAULT_DISPLAY, timestamp);
+            mClient->onVsync(PRIMARY_DISPLAY, timestamp);
         }
     }
 }
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h
index 294abb2..2a5a8ad 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h
@@ -19,6 +19,9 @@
 #include "ComposerClient.h"
 #include "RenderState.h"
 
+// Needed for display type/ID enums
+#include <hardware/hwcomposer_defs.h>
+
 #include <utils/Condition.h>
 
 #include <chrono>
@@ -40,6 +43,13 @@
 
 namespace sftest {
 
+// NOTE: The ID's need to be exactly these. VR composer and parts of
+// the SurfaceFlinger assume the display IDs to have these values
+// despite the enum being documented as a display type.
+// TODO: Reference to actual documentation
+constexpr Display PRIMARY_DISPLAY = static_cast<Display>(HWC_DISPLAY_PRIMARY);
+constexpr Display EXTERNAL_DISPLAY = static_cast<Display>(HWC_DISPLAY_EXTERNAL);
+
 class FakeComposerClient : public ComposerBase {
 public:
     FakeComposerClient();
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index 8902ede..9ac3331 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -168,17 +168,15 @@
     android::hardware::ProcessState::self()->startThreadPool();
     android::ProcessState::self()->startThreadPool();
 
-    EXPECT_CALL(*mMockComposer, getDisplayType(1, _))
+    EXPECT_CALL(*mMockComposer, getDisplayType(PRIMARY_DISPLAY, _))
             .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL),
                             Return(Error::NONE)));
-    // Seems to be doubled right now, once for display ID 1 and once for 0. This sounds fishy
-    // but encoding that here exactly.
-    EXPECT_CALL(*mMockComposer, getDisplayAttribute(1, 1, _, _))
-            .Times(5)
-            .WillRepeatedly(Invoke(mMockComposer, &MockComposerClient::getDisplayAttributeFake));
-    // TODO: Find out what code is generating the ID 0.
-    EXPECT_CALL(*mMockComposer, getDisplayAttribute(0, 1, _, _))
-            .Times(5)
+    // Primary display will be queried twice for all 5 attributes. One
+    // set of queries comes from the SurfaceFlinger proper an the
+    // other set from the VR composer.
+    // TODO: Is VR composer always present? Change to atLeast(5)?
+    EXPECT_CALL(*mMockComposer, getDisplayAttribute(PRIMARY_DISPLAY, 1, _, _))
+            .Times(2 * 5)
             .WillRepeatedly(Invoke(mMockComposer, &MockComposerClient::getDisplayAttributeFake));
 
     startSurfaceFlinger();
@@ -207,31 +205,32 @@
 TEST_F(DisplayTest, Hotplug) {
     ALOGD("DisplayTest::Hotplug");
 
-    EXPECT_CALL(*mMockComposer, getDisplayType(2, _))
+    EXPECT_CALL(*mMockComposer, getDisplayType(EXTERNAL_DISPLAY, _))
             .Times(2)
             .WillRepeatedly(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL),
                                   Return(Error::NONE)));
     // The attribute queries will get done twice. This is for defaults
-    EXPECT_CALL(*mMockComposer, getDisplayAttribute(2, 1, _, _))
+    EXPECT_CALL(*mMockComposer, getDisplayAttribute(EXTERNAL_DISPLAY, 1, _, _))
             .Times(2 * 3)
             .WillRepeatedly(Invoke(mMockComposer, &MockComposerClient::getDisplayAttributeFake));
     // ... and then special handling for dimensions. Specifying this
     // rules later means that gmock will try them first, i.e.,
     // ordering of width/height vs. the default implementation for
     // other queries is significant.
-    EXPECT_CALL(*mMockComposer, getDisplayAttribute(2, 1, IComposerClient::Attribute::WIDTH, _))
+    EXPECT_CALL(*mMockComposer,
+                getDisplayAttribute(EXTERNAL_DISPLAY, 1, IComposerClient::Attribute::WIDTH, _))
             .Times(2)
             .WillRepeatedly(DoAll(SetArgPointee<3>(400), Return(Error::NONE)));
 
-    EXPECT_CALL(*mMockComposer, getDisplayAttribute(2, 1, IComposerClient::Attribute::HEIGHT, _))
+    EXPECT_CALL(*mMockComposer,
+                getDisplayAttribute(EXTERNAL_DISPLAY, 1, IComposerClient::Attribute::HEIGHT, _))
             .Times(2)
             .WillRepeatedly(DoAll(SetArgPointee<3>(200), Return(Error::NONE)));
 
     // TODO: Width and height queries are not actually called. Display
     // info returns dimensions 0x0 in display info. Why?
 
-    mMockComposer->hotplugDisplay(static_cast<Display>(2),
-                                  IComposerCallback::Connection::CONNECTED);
+    mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::CONNECTED);
 
     {
         sp<android::IBinder> display(
@@ -257,13 +256,11 @@
         }
     }
 
-    mMockComposer->hotplugDisplay(static_cast<Display>(2),
-                                  IComposerCallback::Connection::DISCONNECTED);
+    mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::DISCONNECTED);
 
     mMockComposer->clearFrames();
 
-    mMockComposer->hotplugDisplay(static_cast<Display>(2),
-                                  IComposerCallback::Connection::CONNECTED);
+    mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::CONNECTED);
 
     {
         sp<android::IBinder> display(
@@ -288,8 +285,7 @@
             ASSERT_EQ(NO_ERROR, surfaceControl->show());
         }
     }
-    mMockComposer->hotplugDisplay(static_cast<Display>(2),
-                                  IComposerCallback::Connection::DISCONNECTED);
+    mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::DISCONNECTED);
 }
 
 ////////////////////////////////////////////////
@@ -664,7 +660,7 @@
              {{0.f, 1.f, 1.f, 0.f},     HWC_TRANSFORM_FLIP_H_ROT_90,    {64, 64, 128, 128}},
              {{0.f, 1.f, 1.f, 0.f},     HWC_TRANSFORM_FLIP_V_ROT_90,    {64, 64, 128, 128}}};
     // clang-format on
-    constexpr int TEST_COUNT = sizeof(MATRIX_TESTS)/sizeof(matrixTestData);
+    constexpr int TEST_COUNT = sizeof(MATRIX_TESTS) / sizeof(matrixTestData);
 
     for (int i = 0; i < TEST_COUNT; i++) {
         // TODO: How to leverage the HWC2 stringifiers?