split libandroid.so

- ANativeWindow (native_window.h) and
  AHardwareBuffer (hardware_buffer.h) now live
  in libnativewindow.so, which is a vodka library.

- libandroid.so still provide those symbols
  via a static library version (libnativewindow.a)

- removed libbinder dependency as well

Test: compiled & booted
Bug: 35164655
Change-Id: Ib4bc8e8fc9ec1891bcbee63c28fd0131d82edf29
diff --git a/cmds/surfacereplayer/replayer/Android.mk b/cmds/surfacereplayer/replayer/Android.mk
index 9f06033..1dd926c 100644
--- a/cmds/surfacereplayer/replayer/Android.mk
+++ b/cmds/surfacereplayer/replayer/Android.mk
@@ -42,6 +42,7 @@
     libutils \
     libprotobuf-cpp-lite \
     libbase \
+    libnativewindow \
 
 LOCAL_STATIC_LIBRARIES := \
     libtrace_proto \
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index ddf1072..8f9c38a 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -107,6 +107,7 @@
         "libGLESv2",
         "libui",
         "libutils",
+        "libnativewindow",
         "liblog",
     ],
 
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 092d597..5944110 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -15,7 +15,6 @@
         "IGraphicBufferProducer_test.cpp",
         "MultiTextureConsumer_test.cpp",
         "Sensor_test.cpp",
-        "SRGB_test.cpp",
         "StreamSplitter_test.cpp",
         "SurfaceTextureClient_test.cpp",
         "SurfaceTextureFBO_test.cpp",
@@ -37,5 +36,6 @@
         "libgui",
         "libui",
         "libutils",
+        "libnativewindow"
     ],
 }
diff --git a/libs/gui/tests/SRGB_test.cpp b/libs/gui/tests/SRGB_test.cpp
deleted file mode 100644
index c2640cd..0000000
--- a/libs/gui/tests/SRGB_test.cpp
+++ /dev/null
@@ -1,486 +0,0 @@
-/*
- * Copyright 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "SRGB_test"
-//#define LOG_NDEBUG 0
-
-// Ignore for this file because it flags every instance of
-// ASSERT_EQ(GL_NO_ERROR, glGetError());
-#pragma clang diagnostic ignored "-Wsign-compare"
-
-#include "GLTest.h"
-
-#include <math.h>
-
-#include <gui/CpuConsumer.h>
-#include <gui/Surface.h>
-#include <gui/SurfaceComposerClient.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES3/gl3.h>
-
-#include <android/native_window.h>
-
-#include <gtest/gtest.h>
-
-namespace android {
-
-class SRGBTest : public ::testing::Test {
-protected:
-    // Class constants
-    enum {
-        DISPLAY_WIDTH = 512,
-        DISPLAY_HEIGHT = 512,
-        PIXEL_SIZE = 4, // bytes or components
-        DISPLAY_SIZE = DISPLAY_WIDTH * DISPLAY_HEIGHT * PIXEL_SIZE,
-        ALPHA_VALUE = 223, // should be in [0, 255]
-        TOLERANCE = 1,
-    };
-    static const char SHOW_DEBUG_STRING[];
-
-    SRGBTest() :
-            mInputSurface(), mCpuConsumer(), mLockedBuffer(),
-            mEglDisplay(EGL_NO_DISPLAY), mEglConfig(),
-            mEglContext(EGL_NO_CONTEXT), mEglSurface(EGL_NO_SURFACE),
-            mComposerClient(), mSurfaceControl(), mOutputSurface() {
-    }
-
-    virtual ~SRGBTest() {
-        if (mEglDisplay != EGL_NO_DISPLAY) {
-            if (mEglSurface != EGL_NO_SURFACE) {
-                eglDestroySurface(mEglDisplay, mEglSurface);
-            }
-            if (mEglContext != EGL_NO_CONTEXT) {
-                eglDestroyContext(mEglDisplay, mEglContext);
-            }
-            eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
-                    EGL_NO_CONTEXT);
-            eglTerminate(mEglDisplay);
-        }
-    }
-
-    virtual void SetUp() {
-        sp<IGraphicBufferProducer> producer;
-        sp<IGraphicBufferConsumer> consumer;
-        BufferQueue::createBufferQueue(&producer, &consumer);
-        ASSERT_EQ(NO_ERROR, consumer->setDefaultBufferSize(
-                DISPLAY_WIDTH, DISPLAY_HEIGHT));
-        mCpuConsumer = new CpuConsumer(consumer, 1);
-        String8 name("CpuConsumer_for_SRGBTest");
-        mCpuConsumer->setName(name);
-        mInputSurface = new Surface(producer);
-
-        ASSERT_NO_FATAL_FAILURE(createEGLSurface(mInputSurface.get()));
-        ASSERT_NO_FATAL_FAILURE(createDebugSurface());
-    }
-
-    virtual void TearDown() {
-        ASSERT_NO_FATAL_FAILURE(copyToDebugSurface());
-        ASSERT_TRUE(mLockedBuffer.data != NULL);
-        ASSERT_EQ(NO_ERROR, mCpuConsumer->unlockBuffer(mLockedBuffer));
-    }
-
-    static float linearToSRGB(float l) {
-        if (l <= 0.0031308f) {
-            return l * 12.92f;
-        } else {
-            return 1.055f * pow(l, (1 / 2.4f)) - 0.055f;
-        }
-    }
-
-    static float srgbToLinear(float s) {
-        if (s <= 0.04045) {
-            return s / 12.92f;
-        } else {
-            return pow(((s + 0.055f) / 1.055f), 2.4f);
-        }
-    }
-
-    static uint8_t srgbToLinear(uint8_t u) {
-        float f = u / 255.0f;
-        return static_cast<uint8_t>(srgbToLinear(f) * 255.0f + 0.5f);
-    }
-
-    void fillTexture(bool writeAsSRGB) {
-        uint8_t* textureData = new uint8_t[DISPLAY_SIZE];
-
-        for (int y = 0; y < DISPLAY_HEIGHT; ++y) {
-            for (int x = 0; x < DISPLAY_WIDTH; ++x) {
-                float realValue = static_cast<float>(x) / (DISPLAY_WIDTH - 1);
-                realValue *= ALPHA_VALUE / 255.0f; // Premultiply by alpha
-                if (writeAsSRGB) {
-                    realValue = linearToSRGB(realValue);
-                }
-
-                int offset = (y * DISPLAY_WIDTH + x) * PIXEL_SIZE;
-                for (int c = 0; c < 3; ++c) {
-                    uint8_t intValue = static_cast<uint8_t>(
-                            realValue * 255.0f + 0.5f);
-                    textureData[offset + c] = intValue;
-                }
-                textureData[offset + 3] = ALPHA_VALUE;
-            }
-        }
-
-        glTexImage2D(GL_TEXTURE_2D, 0, writeAsSRGB ? GL_SRGB8_ALPHA8 : GL_RGBA8,
-                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE,
-                textureData);
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-
-        delete[] textureData;
-    }
-
-    void initShaders() {
-        static const char vertexSource[] =
-            "attribute vec4 vPosition;\n"
-            "varying vec2 texCoords;\n"
-            "void main() {\n"
-            "  texCoords = 0.5 * (vPosition.xy + vec2(1.0, 1.0));\n"
-            "  gl_Position = vPosition;\n"
-            "}\n";
-
-        static const char fragmentSource[] =
-            "precision mediump float;\n"
-            "uniform sampler2D texSampler;\n"
-            "varying vec2 texCoords;\n"
-            "void main() {\n"
-            "  gl_FragColor = texture2D(texSampler, texCoords);\n"
-            "}\n";
-
-        GLuint program;
-        {
-            SCOPED_TRACE("Creating shader program");
-            ASSERT_NO_FATAL_FAILURE(GLTest::createProgram(
-                    vertexSource, fragmentSource, &program));
-        }
-
-        GLint positionHandle = glGetAttribLocation(program, "vPosition");
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-        ASSERT_NE(-1, positionHandle);
-
-        GLint samplerHandle = glGetUniformLocation(program, "texSampler");
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-        ASSERT_NE(-1, samplerHandle);
-
-        static const GLfloat vertices[] = {
-            -1.0f, 1.0f,
-            -1.0f, -1.0f,
-            1.0f, -1.0f,
-            1.0f, 1.0f,
-        };
-
-        glVertexAttribPointer(positionHandle, 2, GL_FLOAT, GL_FALSE, 0, vertices);
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-        glEnableVertexAttribArray(positionHandle);
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-
-        glUseProgram(program);
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-        glUniform1i(samplerHandle, 0);
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-
-        GLuint textureHandle;
-        glGenTextures(1, &textureHandle);
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-        glBindTexture(GL_TEXTURE_2D, textureHandle);
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-    }
-
-    void drawTexture(bool asSRGB, GLint x, GLint y, GLsizei width,
-            GLsizei height) {
-        ASSERT_NO_FATAL_FAILURE(fillTexture(asSRGB));
-        glViewport(x, y, width, height);
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-        ASSERT_EQ(GL_NO_ERROR, glGetError());
-    }
-
-    void checkLockedBuffer(PixelFormat format, android_dataspace dataSpace) {
-        ASSERT_EQ(mLockedBuffer.format, format);
-        ASSERT_EQ(mLockedBuffer.width, DISPLAY_WIDTH);
-        ASSERT_EQ(mLockedBuffer.height, DISPLAY_HEIGHT);
-        ASSERT_EQ(mLockedBuffer.dataSpace, dataSpace);
-    }
-
-    static bool withinTolerance(int a, int b) {
-        int diff = a - b;
-        return diff >= 0 ? diff <= TOLERANCE : -diff <= TOLERANCE;
-    }
-
-    // Primary producer and consumer
-    sp<Surface> mInputSurface;
-    sp<CpuConsumer> mCpuConsumer;
-    CpuConsumer::LockedBuffer mLockedBuffer;
-
-    EGLDisplay mEglDisplay;
-    EGLConfig mEglConfig;
-    EGLContext mEglContext;
-    EGLSurface mEglSurface;
-
-    // Auxiliary display output
-    sp<SurfaceComposerClient> mComposerClient;
-    sp<SurfaceControl> mSurfaceControl;
-    sp<Surface> mOutputSurface;
-
-private:
-    void createEGLSurface(Surface* inputSurface) {
-        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-        ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
-
-        EXPECT_TRUE(eglInitialize(mEglDisplay, NULL, NULL));
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
-        static const EGLint configAttribs[] = {
-            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
-            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
-            EGL_RED_SIZE, 8,
-            EGL_GREEN_SIZE, 8,
-            EGL_BLUE_SIZE, 8,
-            EGL_ALPHA_SIZE, 8,
-            EGL_NONE };
-
-        EGLint numConfigs = 0;
-        EXPECT_TRUE(eglChooseConfig(mEglDisplay, configAttribs, &mEglConfig, 1,
-                &numConfigs));
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-        ASSERT_GT(numConfigs, 0);
-
-        static const EGLint contextAttribs[] = {
-            EGL_CONTEXT_CLIENT_VERSION, 3,
-            EGL_NONE } ;
-
-        mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT,
-                contextAttribs);
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-        ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
-
-        mEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig,
-                inputSurface, NULL);
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-        ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
-
-        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
-                mEglContext));
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-    }
-
-    void createDebugSurface() {
-        if (getenv(SHOW_DEBUG_STRING) == NULL) return;
-
-        mComposerClient = new SurfaceComposerClient;
-        ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
-
-        mSurfaceControl = mComposerClient->createSurface(
-                String8("SRGBTest Surface"), DISPLAY_WIDTH, DISPLAY_HEIGHT,
-                PIXEL_FORMAT_RGBA_8888);
-
-        ASSERT_TRUE(mSurfaceControl != NULL);
-        ASSERT_TRUE(mSurfaceControl->isValid());
-
-        SurfaceComposerClient::openGlobalTransaction();
-        ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
-        ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
-        SurfaceComposerClient::closeGlobalTransaction();
-
-        ANativeWindow_Buffer outBuffer;
-        ARect inOutDirtyBounds;
-        mOutputSurface = mSurfaceControl->getSurface();
-        mOutputSurface->lock(&outBuffer, &inOutDirtyBounds);
-        uint8_t* bytePointer = reinterpret_cast<uint8_t*>(outBuffer.bits);
-        for (int y = 0; y < outBuffer.height; ++y) {
-            int rowOffset = y * outBuffer.stride; // pixels
-            for (int x = 0; x < outBuffer.width; ++x) {
-                int colOffset = (rowOffset + x) * PIXEL_SIZE; // bytes
-                for (int c = 0; c < PIXEL_SIZE; ++c) {
-                    int offset = colOffset + c;
-                    bytePointer[offset] = ((c + 1) * 56) - 1;
-                }
-            }
-        }
-        mOutputSurface->unlockAndPost();
-    }
-
-    void copyToDebugSurface() {
-        if (!mOutputSurface.get()) return;
-
-        size_t bufferSize = mLockedBuffer.height * mLockedBuffer.stride *
-                PIXEL_SIZE;
-
-        ANativeWindow_Buffer outBuffer;
-        ARect outBufferBounds;
-        mOutputSurface->lock(&outBuffer, &outBufferBounds);
-        ASSERT_EQ(mLockedBuffer.width, static_cast<uint32_t>(outBuffer.width));
-        ASSERT_EQ(mLockedBuffer.height, static_cast<uint32_t>(outBuffer.height));
-        ASSERT_EQ(mLockedBuffer.stride, static_cast<uint32_t>(outBuffer.stride));
-
-        if (mLockedBuffer.format == outBuffer.format) {
-            memcpy(outBuffer.bits, mLockedBuffer.data, bufferSize);
-        } else {
-            ASSERT_EQ(mLockedBuffer.format, PIXEL_FORMAT_RGBA_8888);
-            ASSERT_EQ(mLockedBuffer.dataSpace, HAL_DATASPACE_SRGB);
-            ASSERT_EQ(outBuffer.format, PIXEL_FORMAT_RGBA_8888);
-            uint8_t* outPointer = reinterpret_cast<uint8_t*>(outBuffer.bits);
-            for (int y = 0; y < outBuffer.height; ++y) {
-                int rowOffset = y * outBuffer.stride; // pixels
-                for (int x = 0; x < outBuffer.width; ++x) {
-                    int colOffset = (rowOffset + x) * PIXEL_SIZE; // bytes
-
-                    // RGB are converted
-                    for (int c = 0; c < (PIXEL_SIZE - 1); ++c) {
-                        outPointer[colOffset + c] = srgbToLinear(
-                                mLockedBuffer.data[colOffset + c]);
-                    }
-
-                    // Alpha isn't converted
-                    outPointer[colOffset + 3] =
-                            mLockedBuffer.data[colOffset + 3];
-                }
-            }
-        }
-        mOutputSurface->unlockAndPost();
-
-        int sleepSeconds = atoi(getenv(SHOW_DEBUG_STRING));
-        sleep(sleepSeconds);
-    }
-};
-
-const char SRGBTest::SHOW_DEBUG_STRING[] = "DEBUG_OUTPUT_SECONDS";
-
-TEST_F(SRGBTest, GLRenderFromSRGBTexture) {
-    ASSERT_NO_FATAL_FAILURE(initShaders());
-
-    // The RGB texture is displayed in the top half
-    ASSERT_NO_FATAL_FAILURE(drawTexture(false, 0, DISPLAY_HEIGHT / 2,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT / 2));
-
-    // The SRGB texture is displayed in the bottom half
-    ASSERT_NO_FATAL_FAILURE(drawTexture(true, 0, 0,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT / 2));
-
-    eglSwapBuffers(mEglDisplay, mEglSurface);
-    ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
-    // Lock
-    ASSERT_EQ(NO_ERROR, mCpuConsumer->lockNextBuffer(&mLockedBuffer));
-    ASSERT_NO_FATAL_FAILURE(
-        checkLockedBuffer(PIXEL_FORMAT_RGBA_8888, HAL_DATASPACE_UNKNOWN));
-
-    // Compare a pixel in the middle of each texture
-    int midSRGBOffset = (DISPLAY_HEIGHT / 4) * mLockedBuffer.stride *
-            PIXEL_SIZE;
-    int midRGBOffset = midSRGBOffset * 3;
-    midRGBOffset += (DISPLAY_WIDTH / 2) * PIXEL_SIZE;
-    midSRGBOffset += (DISPLAY_WIDTH / 2) * PIXEL_SIZE;
-    for (int c = 0; c < PIXEL_SIZE; ++c) {
-        int expectedValue = mLockedBuffer.data[midRGBOffset + c];
-        int actualValue = mLockedBuffer.data[midSRGBOffset + c];
-        ASSERT_PRED2(withinTolerance, expectedValue, actualValue);
-    }
-
-    // mLockedBuffer is unlocked in TearDown so we can copy data from it to
-    // the debug surface if necessary
-}
-
-// XXX: Disabled since we don't currently expect this to work
-TEST_F(SRGBTest, DISABLED_RenderToSRGBSurface) {
-    ASSERT_NO_FATAL_FAILURE(initShaders());
-
-    // By default, the first buffer we write into will be RGB
-
-    // Render an RGB texture across the whole surface
-    ASSERT_NO_FATAL_FAILURE(drawTexture(false, 0, 0,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT));
-    eglSwapBuffers(mEglDisplay, mEglSurface);
-    ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
-    // Lock
-    ASSERT_EQ(NO_ERROR, mCpuConsumer->lockNextBuffer(&mLockedBuffer));
-    ASSERT_NO_FATAL_FAILURE(
-        checkLockedBuffer(PIXEL_FORMAT_RGBA_8888, HAL_DATASPACE_UNKNOWN));
-
-    // Save the values of the middle pixel for later comparison against SRGB
-    uint8_t values[PIXEL_SIZE] = {};
-    int middleOffset = (DISPLAY_HEIGHT / 2) * mLockedBuffer.stride *
-            PIXEL_SIZE;
-    middleOffset += (DISPLAY_WIDTH / 2) * PIXEL_SIZE;
-    for (int c = 0; c < PIXEL_SIZE; ++c) {
-        values[c] = mLockedBuffer.data[middleOffset + c];
-    }
-
-    // Unlock
-    ASSERT_EQ(NO_ERROR, mCpuConsumer->unlockBuffer(mLockedBuffer));
-
-    // Switch to SRGB window surface
-    static const int srgbAttribs[] = {
-        EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR,
-        EGL_NONE,
-    };
-
-    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
-            mEglContext));
-    ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
-    EXPECT_TRUE(eglDestroySurface(mEglDisplay, mEglSurface));
-    ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
-    mEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig,
-            mInputSurface.get(), srgbAttribs);
-    ASSERT_EQ(EGL_SUCCESS, eglGetError());
-    ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
-
-    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
-            mEglContext));
-    ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
-    // Render the texture again
-    ASSERT_NO_FATAL_FAILURE(drawTexture(false, 0, 0,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT));
-    eglSwapBuffers(mEglDisplay, mEglSurface);
-    ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
-    // Lock
-    ASSERT_EQ(NO_ERROR, mCpuConsumer->lockNextBuffer(&mLockedBuffer));
-
-    // Make sure we actually got the SRGB buffer on the consumer side
-    ASSERT_NO_FATAL_FAILURE(
-        checkLockedBuffer(PIXEL_FORMAT_RGBA_8888, HAL_DATASPACE_SRGB));
-
-    // Verify that the stored value is the same, accounting for RGB/SRGB
-    for (int c = 0; c < PIXEL_SIZE; ++c) {
-        // The alpha value should be equivalent before linear->SRGB
-        float rgbAsSRGB = (c == 3) ? values[c] / 255.0f :
-                linearToSRGB(values[c] / 255.0f);
-        int expectedValue = rgbAsSRGB * 255.0f + 0.5f;
-        int actualValue = mLockedBuffer.data[middleOffset + c];
-        ASSERT_PRED2(withinTolerance, expectedValue, actualValue);
-    }
-
-    // mLockedBuffer is unlocked in TearDown so we can copy data from it to
-    // the debug surface if necessary
-}
-
-} // namespace android
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
new file mode 100644
index 0000000..b4b5303
--- /dev/null
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHardwareBuffer"
+
+#include <android/hardware_buffer.h>
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <memory>
+
+#include <cutils/native_handle.h>
+#include <log/log.h>
+#include <utils/StrongPointer.h>
+#include <ui/GraphicBuffer.h>
+#include <system/graphics.h>
+#include <hardware/gralloc1.h>
+
+#include <private/android/AHardwareBufferHelpers.h>
+
+
+static constexpr int kDataBufferSize = 64 * sizeof(int);  // 64 ints
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+// Public functions
+// ----------------------------------------------------------------------------
+
+int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer) {
+    if (!outBuffer || !desc)
+        return BAD_VALUE;
+
+    int format = AHardwareBuffer_convertToPixelFormat(desc->format);
+    if (format == 0) {
+        ALOGE("Invalid pixel format %u", desc->format);
+        return BAD_VALUE;
+    }
+
+    if (desc->format == AHARDWAREBUFFER_FORMAT_BLOB && desc->height != 1) {
+        ALOGE("Height must be 1 when using the AHARDWAREBUFFER_FORMAT_BLOB format");
+        return BAD_VALUE;
+    }
+
+    uint64_t producerUsage = 0;
+    uint64_t consumerUsage = 0;
+    AHardwareBuffer_convertToGrallocUsageBits(desc->usage0, &producerUsage, &consumerUsage);
+
+    sp<GraphicBuffer> gbuffer(new GraphicBuffer(
+            desc->width, desc->height, format, desc->layers, producerUsage, consumerUsage,
+            std::string("AHardwareBuffer pid [") + std::to_string(getpid()) + "]"));
+
+    status_t err = gbuffer->initCheck();
+    if (err != 0 || gbuffer->handle == 0) {
+        if (err == NO_MEMORY) {
+            GraphicBuffer::dumpAllocationsToSystemLog();
+        }
+        ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%u, h=%u, lc=%u) failed (%s), handle=%p",
+                desc->width, desc->height, desc->layers, strerror(-err), gbuffer->handle);
+        return err;
+    }
+
+    *outBuffer = AHardwareBuffer_from_GraphicBuffer(gbuffer.get());
+
+    // Ensure the buffer doesn't get destroyed when the sp<> goes away.
+    AHardwareBuffer_acquire(*outBuffer);
+    return NO_ERROR;
+}
+
+void AHardwareBuffer_acquire(AHardwareBuffer* buffer) {
+    AHardwareBuffer_to_GraphicBuffer(buffer)->incStrong((void*)AHardwareBuffer_acquire);
+}
+
+void AHardwareBuffer_release(AHardwareBuffer* buffer) {
+    AHardwareBuffer_to_GraphicBuffer(buffer)->decStrong((void*)AHardwareBuffer_release);
+}
+
+void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
+        AHardwareBuffer_Desc* outDesc) {
+    if (!buffer || !outDesc) return;
+
+    const GraphicBuffer* gbuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
+
+    outDesc->width = gbuffer->getWidth();
+    outDesc->height = gbuffer->getHeight();
+    outDesc->layers = gbuffer->getLayerCount();
+    outDesc->usage0 = AHardwareBuffer_convertFromGrallocUsageBits(
+            gbuffer->getUsage(), gbuffer->getUsage());
+    outDesc->usage1 = 0;
+    outDesc->format = AHardwareBuffer_convertFromPixelFormat(
+            static_cast<uint32_t>(gbuffer->getPixelFormat()));
+}
+
+int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage0,
+        int32_t fence, const ARect* rect, void** outVirtualAddress) {
+    if (!buffer) return BAD_VALUE;
+
+    if (usage0 & ~(AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN |
+                   AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN)) {
+        ALOGE("Invalid usage flags passed to AHardwareBuffer_lock; only "
+                " AHARDWAREBUFFER_USAGE0_CPU_* flags are allowed");
+        return BAD_VALUE;
+    }
+
+    uint64_t producerUsage = 0;
+    uint64_t consumerUsage = 0;
+    AHardwareBuffer_convertToGrallocUsageBits(usage0, &producerUsage, &consumerUsage);
+    GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
+    Rect bounds;
+    if (!rect) {
+        bounds.set(Rect(gBuffer->getWidth(), gBuffer->getHeight()));
+    } else {
+        bounds.set(Rect(rect->left, rect->top, rect->right, rect->bottom));
+    }
+    return gBuffer->lockAsync(producerUsage, consumerUsage, bounds,
+            outVirtualAddress, fence);
+}
+
+int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) {
+    if (!buffer) return BAD_VALUE;
+
+    GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
+    return gBuffer->unlockAsync(fence);
+}
+
+int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer,
+        int socketFd) {
+    if (!buffer) return BAD_VALUE;
+    const GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
+
+    size_t flattenedSize = gBuffer->getFlattenedSize();
+    size_t fdCount = gBuffer->getFdCount();
+
+    std::unique_ptr<uint8_t[]> data(new uint8_t[flattenedSize]);
+    std::unique_ptr<int[]> fds(new int[fdCount]);
+
+    // Make copies of needed items since flatten modifies them, and we don't
+    // want to send anything if there's an error during flatten.
+    size_t flattenedSizeCopy = flattenedSize;
+    size_t fdCountCopy = fdCount;
+    void* dataStart = data.get();
+    int* fdsStart = fds.get();
+    status_t err = gBuffer->flatten(dataStart, flattenedSizeCopy, fdsStart,
+            fdCountCopy);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    struct iovec iov[1];
+    iov[0].iov_base = data.get();
+    iov[0].iov_len = flattenedSize;
+
+    char buf[CMSG_SPACE(kDataBufferSize)];
+    struct msghdr msg = {
+            .msg_control = buf,
+            .msg_controllen = sizeof(buf),
+            .msg_iov = &iov[0],
+            .msg_iovlen = 1,
+    };
+
+    struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
+    cmsg->cmsg_level = SOL_SOCKET;
+    cmsg->cmsg_type = SCM_RIGHTS;
+    cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fdCount);
+    int* fdData = reinterpret_cast<int*>(CMSG_DATA(cmsg));
+    memcpy(fdData, fds.get(), sizeof(int) * fdCount);
+    msg.msg_controllen = cmsg->cmsg_len;
+
+    int result = sendmsg(socketFd, &msg, 0);
+    if (result <= 0) {
+        ALOGE("Error writing AHardwareBuffer to socket: error %#x (%s)",
+                result, strerror(errno));
+        return result;
+    }
+    return NO_ERROR;
+}
+
+int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd,
+        AHardwareBuffer** outBuffer) {
+    if (!outBuffer) return BAD_VALUE;
+
+    char dataBuf[CMSG_SPACE(kDataBufferSize)];
+    char fdBuf[CMSG_SPACE(kDataBufferSize)];
+    struct iovec iov[1];
+    iov[0].iov_base = dataBuf;
+    iov[0].iov_len = sizeof(dataBuf);
+
+    struct msghdr msg = {
+            .msg_control = fdBuf,
+            .msg_controllen = sizeof(fdBuf),
+            .msg_iov = &iov[0],
+            .msg_iovlen = 1,
+    };
+
+    int result = recvmsg(socketFd, &msg, 0);
+    if (result <= 0) {
+        ALOGE("Error reading AHardwareBuffer from socket: error %#x (%s)",
+                result, strerror(errno));
+        return result;
+    }
+
+    if (msg.msg_iovlen != 1) {
+        ALOGE("Error reading AHardwareBuffer from socket: bad data length");
+        return INVALID_OPERATION;
+    }
+
+    if (msg.msg_controllen % sizeof(int) != 0) {
+        ALOGE("Error reading AHardwareBuffer from socket: bad fd length");
+        return INVALID_OPERATION;
+    }
+
+    size_t dataLen = msg.msg_iov[0].iov_len;
+    const void* data = static_cast<const void*>(msg.msg_iov[0].iov_base);
+    if (!data) {
+        ALOGE("Error reading AHardwareBuffer from socket: no buffer data");
+        return INVALID_OPERATION;
+    }
+
+    struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
+    if (!cmsg) {
+        ALOGE("Error reading AHardwareBuffer from socket: no fd header");
+        return INVALID_OPERATION;
+    }
+
+    size_t fdCount = msg.msg_controllen >> 2;
+    const int* fdData = reinterpret_cast<const int*>(CMSG_DATA(cmsg));
+    if (!fdData) {
+        ALOGE("Error reading AHardwareBuffer from socket: no fd data");
+        return INVALID_OPERATION;
+    }
+
+    GraphicBuffer* gBuffer = new GraphicBuffer();
+    status_t err = gBuffer->unflatten(data, dataLen, fdData, fdCount);
+    if (err != NO_ERROR) {
+        return err;
+    }
+    *outBuffer = AHardwareBuffer_from_GraphicBuffer(gBuffer);
+    // Ensure the buffer has a positive ref-count.
+    AHardwareBuffer_acquire(*outBuffer);
+
+    return NO_ERROR;
+}
+
+const struct native_handle* AHardwareBuffer_getNativeHandle(
+        const AHardwareBuffer* buffer) {
+    if (!buffer) return nullptr;
+    const GraphicBuffer* gbuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
+    return gbuffer->handle;
+}
+
+
+// ----------------------------------------------------------------------------
+// Helpers implementation
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+static inline bool containsBits(uint64_t mask, uint64_t bitsToCheck) {
+    return (mask & bitsToCheck) == bitsToCheck;
+}
+
+uint32_t AHardwareBuffer_convertFromPixelFormat(uint32_t format) {
+    switch (format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:    return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
+        case HAL_PIXEL_FORMAT_RGBX_8888:    return AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
+        case HAL_PIXEL_FORMAT_RGB_565:      return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
+        case HAL_PIXEL_FORMAT_RGB_888:      return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
+        case HAL_PIXEL_FORMAT_RGBA_FP16:    return AHARDWAREBUFFER_FORMAT_R16G16B16A16_SFLOAT;
+        case HAL_PIXEL_FORMAT_RGBA_1010102: return AHARDWAREBUFFER_FORMAT_A2R10G10B10_UNORM_PACK32;
+        case HAL_PIXEL_FORMAT_BLOB:         return AHARDWAREBUFFER_FORMAT_BLOB;
+        default:ALOGE("Unknown pixel format %u", format);
+            return 0;
+    }
+}
+
+uint32_t AHardwareBuffer_convertToPixelFormat(uint32_t format) {
+    switch (format) {
+        case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:         return HAL_PIXEL_FORMAT_RGBA_8888;
+        case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:         return HAL_PIXEL_FORMAT_RGBX_8888;
+        case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:           return HAL_PIXEL_FORMAT_RGB_565;
+        case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:           return HAL_PIXEL_FORMAT_RGB_888;
+        case AHARDWAREBUFFER_FORMAT_R16G16B16A16_SFLOAT:    return HAL_PIXEL_FORMAT_RGBA_FP16;
+        case AHARDWAREBUFFER_FORMAT_A2R10G10B10_UNORM_PACK32: return HAL_PIXEL_FORMAT_RGBA_1010102;
+        case AHARDWAREBUFFER_FORMAT_BLOB:                   return HAL_PIXEL_FORMAT_BLOB;
+        default:ALOGE("Unknown AHardwareBuffer format %u", format);
+            return 0;
+    }
+}
+
+void AHardwareBuffer_convertToGrallocUsageBits(uint64_t usage, uint64_t* outProducerUsage,
+        uint64_t* outConsumerUsage) {
+    *outProducerUsage = 0;
+    *outConsumerUsage = 0;
+    if (containsBits(usage, AHARDWAREBUFFER_USAGE0_CPU_READ))
+        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
+    if (containsBits(usage, AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN))
+        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
+    if (containsBits(usage, AHARDWAREBUFFER_USAGE0_CPU_WRITE))
+        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
+    if (containsBits(usage, AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN))
+        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
+    if (containsBits(usage, AHARDWAREBUFFER_USAGE0_GPU_SAMPLED_IMAGE))
+        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
+    if (containsBits(usage, AHARDWAREBUFFER_USAGE0_GPU_COLOR_OUTPUT))
+        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
+    // Not sure what this should be.
+    //if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_CUBEMAP)) bits |= 0;
+    if (containsBits(usage, AHARDWAREBUFFER_USAGE0_GPU_DATA_BUFFER))
+        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
+    if (containsBits(usage, AHARDWAREBUFFER_USAGE0_VIDEO_ENCODE))
+        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER;
+    if (containsBits(usage, AHARDWAREBUFFER_USAGE0_PROTECTED_CONTENT))
+        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_PROTECTED;
+    if (containsBits(usage, AHARDWAREBUFFER_USAGE0_SENSOR_DIRECT_DATA))
+        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_SENSOR_DIRECT_DATA;
+}
+
+uint64_t AHardwareBuffer_convertFromGrallocUsageBits(uint64_t producerUsage, uint64_t consumerUsage) {
+    uint64_t bits = 0;
+    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_CPU_READ))
+        bits |= AHARDWAREBUFFER_USAGE0_CPU_READ;
+    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN))
+        bits |= AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN;
+    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_CPU_WRITE))
+        bits |= AHARDWAREBUFFER_USAGE0_CPU_WRITE;
+    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN))
+        bits |= AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN;
+    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE))
+        bits |= AHARDWAREBUFFER_USAGE0_GPU_SAMPLED_IMAGE;
+    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET))
+        bits |= AHARDWAREBUFFER_USAGE0_GPU_COLOR_OUTPUT;
+    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER))
+        bits |= AHARDWAREBUFFER_USAGE0_GPU_DATA_BUFFER;
+    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER))
+        bits |= AHARDWAREBUFFER_USAGE0_VIDEO_ENCODE;
+    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_PROTECTED))
+        bits |= AHARDWAREBUFFER_USAGE0_PROTECTED_CONTENT;
+    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_SENSOR_DIRECT_DATA))
+        bits |= AHARDWAREBUFFER_USAGE0_SENSOR_DIRECT_DATA;
+
+    return bits;
+}
+
+const GraphicBuffer* AHardwareBuffer_to_GraphicBuffer(const AHardwareBuffer* buffer) {
+    return reinterpret_cast<const GraphicBuffer*>(buffer);
+}
+
+GraphicBuffer* AHardwareBuffer_to_GraphicBuffer(AHardwareBuffer* buffer) {
+    return reinterpret_cast<GraphicBuffer*>(buffer);
+}
+
+AHardwareBuffer* AHardwareBuffer_from_GraphicBuffer(GraphicBuffer* buffer) {
+    return reinterpret_cast<AHardwareBuffer*>(buffer);
+}
+
+} // namespace android
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
new file mode 100644
index 0000000..34c136a
--- /dev/null
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ANativeWindow"
+
+#include <android/native_window.h>
+#include <system/window.h>
+
+void ANativeWindow_acquire(ANativeWindow* window) {
+    window->incStrong((void*)ANativeWindow_acquire);
+}
+
+void ANativeWindow_release(ANativeWindow* window) {
+    window->decStrong((void*)ANativeWindow_release);
+}
+
+static int32_t getWindowProp(ANativeWindow* window, int what) {
+    int value;
+    int res = window->query(window, what, &value);
+    return res < 0 ? res : value;
+}
+
+int32_t ANativeWindow_getWidth(ANativeWindow* window) {
+    return getWindowProp(window, NATIVE_WINDOW_WIDTH);
+}
+
+int32_t ANativeWindow_getHeight(ANativeWindow* window) {
+    return getWindowProp(window, NATIVE_WINDOW_HEIGHT);
+}
+
+int32_t ANativeWindow_getFormat(ANativeWindow* window) {
+    return getWindowProp(window, NATIVE_WINDOW_FORMAT);
+}
+
+int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, int32_t width,
+        int32_t height, int32_t format) {
+    int32_t err = native_window_set_buffers_format(window, format);
+    if (!err) {
+        err = native_window_set_buffers_user_dimensions(window, width, height);
+        if (!err) {
+            int mode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
+            if (width && height) {
+                mode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
+            }
+            err = native_window_set_scaling_mode(window, mode);
+        }
+    }
+    return err;
+}
+
+int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer,
+        ARect* inOutDirtyBounds) {
+    return window->perform(window, NATIVE_WINDOW_LOCK, outBuffer, inOutDirtyBounds);
+}
+
+int32_t ANativeWindow_unlockAndPost(ANativeWindow* window) {
+    return window->perform(window, NATIVE_WINDOW_UNLOCK_AND_POST);
+}
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
new file mode 100644
index 0000000..4d1d8ac
--- /dev/null
+++ b/libs/nativewindow/Android.bp
@@ -0,0 +1,50 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+ndk_headers {
+    name: "libnativewdinwow_headers",
+    from: "include/android",
+    to: "android",
+    srcs: ["include/android/*.h"],
+    license: "NOTICE",
+}
+
+cc_library {
+    name: "libnativewindow",
+    export_include_dirs: ["include"],
+
+    clang: true,
+
+    srcs: [
+        "AHardwareBuffer.cpp",
+        "ANativeWindow.cpp",
+    ],
+
+    shared_libs: [
+        "libhardware",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libui",
+    ],
+
+    static_libs: [
+        "libarect",
+    ],
+
+    // headers we include in our public headers
+    export_static_lib_headers: [
+        "libarect",
+    ],
+}
diff --git a/libs/nativewindow/MODULE_LICENSE_APACHE2 b/libs/nativewindow/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/nativewindow/MODULE_LICENSE_APACHE2
diff --git a/libs/nativewindow/NOTICE b/libs/nativewindow/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/libs/nativewindow/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2008, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
similarity index 100%
rename from include/android/hardware_buffer.h
rename to libs/nativewindow/include/android/hardware_buffer.h
diff --git a/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
similarity index 100%
rename from include/android/native_window.h
rename to libs/nativewindow/include/android/native_window.h
diff --git a/libs/nativewindow/include/private/android/AHardwareBufferHelpers.h b/libs/nativewindow/include/private/android/AHardwareBufferHelpers.h
new file mode 100644
index 0000000..f138fa7
--- /dev/null
+++ b/libs/nativewindow/include/private/android/AHardwareBufferHelpers.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_PRIVATE_NATIVE_AHARDWARE_BUFFER_HELPERS_H
+#define ANDROID_PRIVATE_NATIVE_AHARDWARE_BUFFER_HELPERS_H
+
+/*
+ * This file contains utility functions related to AHardwareBuffer, mostly to convert
+ * to/from HAL formats.
+ *
+ * These are PRIVATE methods, so this file can NEVER appear in a public NDK header.
+ * They are used by higher level libraries such as core/jni.
+ */
+
+#include <stdint.h>
+
+struct AHardwareBuffer;
+
+namespace android {
+
+uint32_t AHardwareBuffer_convertFromPixelFormat(uint32_t format);
+
+uint32_t AHardwareBuffer_convertToPixelFormat(uint32_t format);
+
+void AHardwareBuffer_convertToGrallocUsageBits(uint64_t usage,
+        uint64_t* outProducerUsage, uint64_t* outConsumerUsage);
+
+uint64_t AHardwareBuffer_convertFromGrallocUsageBits(
+        uint64_t producerUsage, uint64_t consumerUsage);
+
+
+class GraphicBuffer;
+const GraphicBuffer* AHardwareBuffer_to_GraphicBuffer(const AHardwareBuffer* buffer);
+GraphicBuffer* AHardwareBuffer_to_GraphicBuffer(AHardwareBuffer* buffer);
+AHardwareBuffer* AHardwareBuffer_from_GraphicBuffer(GraphicBuffer* buffer);
+
+} // namespace android
+
+#endif // ANDROID_PRIVATE_NATIVE_AHARDWARE_BUFFER_HELPERS_H
diff --git a/libs/vr/libbufferhub/bufferhub_tests.cpp b/libs/vr/libbufferhub/bufferhub_tests.cpp
index 0b9e0cc..fa61c4a 100644
--- a/libs/vr/libbufferhub/bufferhub_tests.cpp
+++ b/libs/vr/libbufferhub/bufferhub_tests.cpp
@@ -1,4 +1,3 @@
-#include <android/native_window.h>
 #include <gtest/gtest.h>
 #include <private/dvr/buffer_hub_client.h>
 
diff --git a/libs/vr/libdisplay/Android.mk b/libs/vr/libdisplay/Android.mk
index f0e62df..6a9458c 100644
--- a/libs/vr/libdisplay/Android.mk
+++ b/libs/vr/libdisplay/Android.mk
@@ -46,7 +46,8 @@
 	libui \
 	libgui \
 	libhardware \
-	libsync
+	libsync \
+	libnativewindow \
 
 staticLibraries := \
 	libbufferhub \
diff --git a/libs/vr/libsensor/tests/sensor_app_tests.cpp b/libs/vr/libsensor/tests/sensor_app_tests.cpp
index 0f5bf00..64c9864 100644
--- a/libs/vr/libsensor/tests/sensor_app_tests.cpp
+++ b/libs/vr/libsensor/tests/sensor_app_tests.cpp
@@ -1,6 +1,7 @@
 #include <EGL/egl.h>
 #include <GLES2/gl2.h>
 #include <math.h>
+#include <inttypes.h>
 
 #include <dvr/graphics.h>
 #include <dvr/pose_client.h>
diff --git a/libs/vr/libvrflinger/Android.mk b/libs/vr/libvrflinger/Android.mk
index 1706f30..3450788 100644
--- a/libs/vr/libvrflinger/Android.mk
+++ b/libs/vr/libvrflinger/Android.mk
@@ -56,6 +56,7 @@
 	libcutils \
 	liblog \
 	libhardware \
+	libnativewindow \
 	libutils \
 	libEGL \
 	libGLESv1_CM \
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 865313c..4fa6a33 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -80,6 +80,7 @@
         "libbinder",
         "libutils",
         "libui",
+        "libnativewindow",
     ],
 }
 
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index f15c29d..d0943a9 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -28,6 +28,8 @@
 #include <EGL/eglext.h>
 
 #include <android/hardware_buffer.h>
+#include <private/android/AHardwareBufferHelpers.h>
+
 #include <cutils/atomic.h>
 #include <cutils/compiler.h>
 #include <cutils/memory.h>
@@ -38,6 +40,7 @@
 
 #include <ui/GraphicBuffer.h>
 
+
 #include <utils/KeyedVector.h>
 #include <utils/SortedVector.h>
 #include <utils/String8.h>
@@ -1991,9 +1994,7 @@
 
     if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
 
-    // FIXME: remove this dangerous reinterpret_cast.
-    const GraphicBuffer* graphicBuffer =
-            reinterpret_cast<const GraphicBuffer*>(buffer);
+    const GraphicBuffer* graphicBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
     return static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
 }
 
diff --git a/services/vr/vr_window_manager/application.cpp b/services/vr/vr_window_manager/application.cpp
index 33cd499..467e95e 100644
--- a/services/vr/vr_window_manager/application.cpp
+++ b/services/vr/vr_window_manager/application.cpp
@@ -1,5 +1,6 @@
 #include "application.h"
 
+#include <inttypes.h>
 #include <EGL/egl.h>
 #include <GLES3/gl3.h>
 #include <binder/IServiceManager.h>
diff --git a/vulkan/include/vulkan/vk_platform.h b/vulkan/include/vulkan/vk_platform.h
index 610c723..644be36 100644
--- a/vulkan/include/vulkan/vk_platform.h
+++ b/vulkan/include/vulkan/vk_platform.h
@@ -94,9 +94,6 @@
 // controls inclusion of the extension interfaces in vulkan.h.
 
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
-// FIXME: this forces a dependency on libandroid.so, we can't have that right now
-// because of circular dependencies. this will be resolved at a later time.
-//#include <android/native_window.h>
 struct ANativeWindow;
 #endif
 
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index 16f43e5..0980f24 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -3702,7 +3702,7 @@
 
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
 #define VK_KHR_android_surface 1
-#include <android/native_window.h>
+struct ANativeWindow;
 
 #define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6
 #define VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "VK_KHR_android_surface"