Merge "Newly create idmap only when it is stale" into oc-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 6cfbed9..d3e0cd4 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -31,6 +31,7 @@
 #include <unistd.h>
 #include <zlib.h>
 
+#include <fstream>
 #include <memory>
 
 #include <binder/IBinder.h>
@@ -436,56 +437,31 @@
     return writeStr(k_traceBufferSizePath, str);
 }
 
-// Read the trace_clock sysfs file and return true if it matches the requested
-// value.  The trace_clock file format is:
-// local [global] counter uptime perf
-static bool isTraceClock(const char *mode)
-{
-    int fd = open((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
-    if (fd == -1) {
-        fprintf(stderr, "error opening %s: %s (%d)\n", k_traceClockPath,
-            strerror(errno), errno);
-        return false;
-    }
-
-    char buf[4097];
-    ssize_t n = read(fd, buf, 4096);
-    close(fd);
-    if (n == -1) {
-        fprintf(stderr, "error reading %s: %s (%d)\n", k_traceClockPath,
-            strerror(errno), errno);
-        return false;
-    }
-    buf[n] = '\0';
-
-    char *start = strchr(buf, '[');
-    if (start == NULL) {
-        return false;
-    }
-    start++;
-
-    char *end = strchr(start, ']');
-    if (end == NULL) {
-        return false;
-    }
-    *end = '\0';
-
-    return strcmp(mode, start) == 0;
-}
-
-// Enable or disable the kernel's use of the global clock.  Disabling the global
-// clock will result in the kernel using a per-CPU local clock.
+// Set the clock to the best available option while tracing. Use 'boot' if it's
+// available; otherwise, use 'mono'. If neither are available use 'global'.
 // Any write to the trace_clock sysfs file will reset the buffer, so only
 // update it if the requested value is not the current value.
-static bool setGlobalClockEnable(bool enable)
+static bool setClock()
 {
-    const char *clock = enable ? "global" : "local";
+    std::ifstream clockFile((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
+    std::string clockStr((std::istreambuf_iterator<char>(clockFile)),
+        std::istreambuf_iterator<char>());
 
-    if (isTraceClock(clock)) {
-        return true;
+    std::string newClock;
+    if (clockStr.find("boot") != std::string::npos) {
+        newClock = "boot";
+    } else if (clockStr.find("mono") != std::string::npos) {
+        newClock = "mono";
+    } else {
+        newClock = "global";
     }
 
-    return writeStr(k_traceClockPath, clock);
+    size_t begin = clockStr.find("[") + 1;
+    size_t end = clockStr.find("]");
+    if (newClock.compare(0, std::string::npos, clockStr, begin, end-begin) == 0) {
+        return true;
+    }
+    return writeStr(k_traceClockPath, newClock.c_str());
 }
 
 static bool setPrintTgidEnableIfPresent(bool enable)
@@ -781,7 +757,7 @@
     ok &= setCategoriesEnableFromFile(g_categoriesFile);
     ok &= setTraceOverwriteEnable(g_traceOverwrite);
     ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
-    ok &= setGlobalClockEnable(true);
+    ok &= setClock();
     ok &= setPrintTgidEnableIfPresent(true);
     ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
 
@@ -855,7 +831,6 @@
     // Set the options back to their defaults.
     setTraceOverwriteEnable(true);
     setTraceBufferSizeKB(1);
-    setGlobalClockEnable(false);
     setPrintTgidEnableIfPresent(false);
     setKernelTraceFuncs(NULL);
 }
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 3bbe3a1..b20a807 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1703,10 +1703,20 @@
             result = false;
             continue;
         }
+
+        // Delete oat/vdex/art files.
         result = unlink_if_exists(oat_path) && result;
         result = unlink_if_exists(create_vdex_filename(oat_path)) && result;
         result = unlink_if_exists(create_image_filename(oat_path)) && result;
 
+        // Delete profiles.
+        std::string current_profile = create_current_profile_path(
+                multiuser_get_user_id(uid), dex_path, /*is_secondary*/true);
+        std::string reference_profile = create_reference_profile_path(
+                dex_path, /*is_secondary*/true);
+        result = unlink_if_exists(current_profile) && result;
+        result = unlink_if_exists(reference_profile) && result;
+
         // Try removing the directories as well, they might be empty.
         result = rmdir_if_empty(oat_isa_dir) && result;
         result = rmdir_if_empty(oat_dir) && result;
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 43d0780..68cb0d7 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -64,6 +64,25 @@
 namespace android {
 namespace installd {
 
+// Check expected values for dexopt flags. If you need to change this:
+//
+//   RUN AN A/B OTA TO MAKE SURE THINGS STILL WORK!
+//
+// You most likely need to increase the protocol version and all that entails!
+
+static_assert(DEXOPT_PUBLIC         == 1 << 1, "DEXOPT_PUBLIC unexpected.");
+static_assert(DEXOPT_DEBUGGABLE     == 1 << 2, "DEXOPT_DEBUGGABLE unexpected.");
+static_assert(DEXOPT_BOOTCOMPLETE   == 1 << 3, "DEXOPT_BOOTCOMPLETE unexpected.");
+static_assert(DEXOPT_PROFILE_GUIDED == 1 << 4, "DEXOPT_PROFILE_GUIDED unexpected.");
+static_assert(DEXOPT_SECONDARY_DEX  == 1 << 5, "DEXOPT_SECONDARY_DEX unexpected.");
+static_assert(DEXOPT_FORCE          == 1 << 6, "DEXOPT_FORCE unexpected.");
+static_assert(DEXOPT_STORAGE_CE     == 1 << 7, "DEXOPT_STORAGE_CE unexpected.");
+static_assert(DEXOPT_STORAGE_DE     == 1 << 8, "DEXOPT_STORAGE_DE unexpected.");
+
+static_assert(DEXOPT_MASK           == 0x1fe, "DEXOPT_MASK unexpected.");
+
+
+
 template<typename T>
 static constexpr T RoundDown(T x, typename std::decay<T>::type n) {
     return DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))(x & -n);
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 6fefb38..aec8f10 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2547,16 +2547,8 @@
             objectsSize = 0;
         } else {
             while (objectsSize > 0) {
-                if (mObjects[objectsSize-1] < desired) {
-                    // Check for an object being sliced
-                    if (desired < mObjects[objectsSize-1] + sizeof(flat_binder_object)) {
-                        ALOGE("Attempt to shrink Parcel would slice an objects allocated memory");
-                        return UNKNOWN_ERROR + 0xBADF10;
-                    }
+                if (mObjects[objectsSize-1] < desired)
                     break;
-                }
-                // STOPSHIP: Above code to be replaced with following commented code:
-                // if (mObjects[objectsSize-1] + sizeof(flat_binder_object) <= desired) break;
                 objectsSize--;
             }
         }
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 8159aef..3d57769 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -511,7 +511,7 @@
         { // Autolock scope
             Mutex::Autolock lock(mCore->mMutex);
 
-            if (graphicBuffer != NULL && !mCore->mIsAbandoned) {
+            if (error == NO_ERROR && !mCore->mIsAbandoned) {
                 graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
                 mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
             }
@@ -519,7 +519,7 @@
             mCore->mIsAllocating = false;
             mCore->mIsAllocatingCondition.broadcast();
 
-            if (graphicBuffer == NULL) {
+            if (error != NO_ERROR) {
                 mCore->mFreeSlots.insert(*outSlot);
                 mCore->clearBufferSlotLocked(*outSlot);
                 BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
@@ -732,6 +732,7 @@
     mSlots[*outSlot].mFence = Fence::NO_FENCE;
     mSlots[*outSlot].mRequestBufferCalled = true;
     mSlots[*outSlot].mAcquireCalled = false;
+    mSlots[*outSlot].mNeedsReallocation = false;
     mCore->mActiveBuffers.insert(found);
     VALIDATE_CONSISTENCY();
 
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index ecf27f4..6583a62 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -476,6 +476,9 @@
 
     {
         Mutex::Autolock lock(mMutex);
+        if (mReportRemovedBuffers) {
+            mRemovedBuffers.clear();
+        }
 
         reqWidth = mReqWidth ? mReqWidth : mUserWidth;
         reqHeight = mReqHeight ? mReqHeight : mUserHeight;
@@ -536,7 +539,6 @@
 
     if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) {
         if (mReportRemovedBuffers && (gbuf != nullptr)) {
-            mRemovedBuffers.clear();
             mRemovedBuffers.push_back(gbuf);
         }
         result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
@@ -1208,6 +1210,9 @@
     }
 
     Mutex::Autolock lock(mMutex);
+    if (mReportRemovedBuffers) {
+        mRemovedBuffers.clear();
+    }
 
     sp<GraphicBuffer> buffer(NULL);
     sp<Fence> fence(NULL);
@@ -1224,13 +1229,9 @@
         *outFence = Fence::NO_FENCE;
     }
 
-    if (mReportRemovedBuffers) {
-        mRemovedBuffers.clear();
-    }
-
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         if (mSlots[i].buffer != NULL &&
-                mSlots[i].buffer->handle == buffer->handle) {
+                mSlots[i].buffer->getId() == buffer->getId()) {
             if (mReportRemovedBuffers) {
                 mRemovedBuffers.push_back(mSlots[i].buffer);
             }
@@ -1247,6 +1248,9 @@
     ALOGV("Surface::attachBuffer");
 
     Mutex::Autolock lock(mMutex);
+    if (mReportRemovedBuffers) {
+        mRemovedBuffers.clear();
+    }
 
     sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));
     uint32_t priorGeneration = graphicBuffer->mGenerationNumber;
@@ -1260,7 +1264,6 @@
         return result;
     }
     if (mReportRemovedBuffers && (mSlots[attachedSlot].buffer != nullptr)) {
-        mRemovedBuffers.clear();
         mRemovedBuffers.push_back(mSlots[attachedSlot].buffer);
     }
     mSlots[attachedSlot].buffer = graphicBuffer;
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 192bfc8..7efdb14 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -14,6 +14,7 @@
         "FillBuffer.cpp",
         "GLTest.cpp",
         "IGraphicBufferProducer_test.cpp",
+        "Malicious.cpp",
         "MultiTextureConsumer_test.cpp",
         "StreamSplitter_test.cpp",
         "SurfaceTextureClient_test.cpp",
diff --git a/libs/gui/tests/Malicious.cpp b/libs/gui/tests/Malicious.cpp
new file mode 100644
index 0000000..7ecf08c
--- /dev/null
+++ b/libs/gui/tests/Malicious.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright 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.
+ */
+
+#include <gui/BufferQueue.h>
+#include <gui/IProducerListener.h>
+#include <gui/Surface.h>
+
+#include <android/native_window.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace test {
+
+class ProxyBQP : public BnGraphicBufferProducer {
+public:
+    ProxyBQP(const sp<IGraphicBufferProducer>& producer) : mProducer(producer) {}
+
+    // Pass through calls to mProducer
+    status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override {
+        return mProducer->requestBuffer(slot, buf);
+    }
+    status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override {
+        return mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers);
+    }
+    status_t setAsyncMode(bool async) override { return mProducer->setAsyncMode(async); }
+    status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format,
+                           uint32_t usage, FrameEventHistoryDelta* outTimestamps) override {
+        return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outTimestamps);
+    }
+    status_t detachBuffer(int slot) override { return mProducer->detachBuffer(slot); }
+    status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) override {
+        return mProducer->detachNextBuffer(outBuffer, outFence);
+    }
+    status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer) override {
+        return mProducer->attachBuffer(outSlot, buffer);
+    }
+    status_t queueBuffer(int slot, const QueueBufferInput& input,
+                         QueueBufferOutput* output) override {
+        return mProducer->queueBuffer(slot, input, output);
+    }
+    status_t cancelBuffer(int slot, const sp<Fence>& fence) override {
+        return mProducer->cancelBuffer(slot, fence);
+    }
+    int query(int what, int* value) override { return mProducer->query(what, value); }
+    status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp,
+                     QueueBufferOutput* output) override {
+        return mProducer->connect(listener, api, producerControlledByApp, output);
+    }
+    status_t disconnect(int api, DisconnectMode mode) override {
+        return mProducer->disconnect(api, mode);
+    }
+    status_t setSidebandStream(const sp<NativeHandle>& stream) override {
+        return mProducer->setSidebandStream(stream);
+    }
+    void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format,
+                         uint32_t usage) override {
+        mProducer->allocateBuffers(width, height, format, usage);
+    }
+    status_t allowAllocation(bool allow) override { return mProducer->allowAllocation(allow); }
+    status_t setGenerationNumber(uint32_t generationNumber) override {
+        return mProducer->setGenerationNumber(generationNumber);
+    }
+    String8 getConsumerName() const override { return mProducer->getConsumerName(); }
+    status_t setSharedBufferMode(bool sharedBufferMode) override {
+        return mProducer->setSharedBufferMode(sharedBufferMode);
+    }
+    status_t setAutoRefresh(bool autoRefresh) override {
+        return mProducer->setAutoRefresh(autoRefresh);
+    }
+    status_t setDequeueTimeout(nsecs_t timeout) override {
+        return mProducer->setDequeueTimeout(timeout);
+    }
+    status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence,
+                                 float outTransformMatrix[16]) override {
+        return mProducer->getLastQueuedBuffer(outBuffer, outFence, outTransformMatrix);
+    }
+    void getFrameTimestamps(FrameEventHistoryDelta*) override {}
+    status_t getUniqueId(uint64_t* outId) const override { return mProducer->getUniqueId(outId); }
+
+protected:
+    sp<IGraphicBufferProducer> mProducer;
+};
+
+class MaliciousBQP : public ProxyBQP {
+public:
+    MaliciousBQP(const sp<IGraphicBufferProducer>& producer) : ProxyBQP(producer) {}
+
+    void beMalicious(int32_t value) { mMaliciousValue = value; }
+
+    void setExpectedSlot(int32_t slot) { mExpectedSlot = slot; }
+
+    // Override dequeueBuffer, optionally corrupting the returned slot number
+    status_t dequeueBuffer(int* buf, sp<Fence>* fence, uint32_t width, uint32_t height,
+                           PixelFormat format, uint32_t usage,
+                           FrameEventHistoryDelta* outTimestamps) override {
+        EXPECT_EQ(BUFFER_NEEDS_REALLOCATION,
+                  mProducer->dequeueBuffer(buf, fence, width, height, format, usage,
+                                           outTimestamps));
+        EXPECT_EQ(mExpectedSlot, *buf);
+        if (mMaliciousValue != 0) {
+            *buf = mMaliciousValue;
+            return NO_ERROR;
+        } else {
+            return BUFFER_NEEDS_REALLOCATION;
+        }
+    }
+
+private:
+    int32_t mMaliciousValue = 0;
+    int32_t mExpectedSlot = 0;
+};
+
+class DummyListener : public BnConsumerListener {
+public:
+    void onFrameAvailable(const BufferItem&) override {}
+    void onBuffersReleased() override {}
+    void onSidebandStreamChanged() override {}
+};
+
+sp<MaliciousBQP> getMaliciousBQP() {
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+    sp<IConsumerListener> listener = new DummyListener;
+    consumer->consumerConnect(listener, false);
+
+    sp<MaliciousBQP> malicious = new MaliciousBQP(producer);
+    return malicious;
+}
+
+TEST(Malicious, Bug36991414Max) {
+    sp<MaliciousBQP> malicious = getMaliciousBQP();
+    sp<Surface> surface = new Surface(malicious);
+
+    ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
+    ANativeWindow_Buffer buffer;
+    ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
+    ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
+
+    malicious->setExpectedSlot(1);
+    malicious->beMalicious(std::numeric_limits<int32_t>::max());
+    ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
+}
+
+TEST(Malicious, Bug36991414Min) {
+    sp<MaliciousBQP> malicious = getMaliciousBQP();
+    sp<Surface> surface = new Surface(malicious);
+
+    ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
+    ANativeWindow_Buffer buffer;
+    ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
+    ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
+
+    malicious->setExpectedSlot(1);
+    malicious->beMalicious(std::numeric_limits<int32_t>::min());
+    ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
+}
+
+TEST(Malicious, Bug36991414NegativeOne) {
+    sp<MaliciousBQP> malicious = getMaliciousBQP();
+    sp<Surface> surface = new Surface(malicious);
+
+    ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
+    ANativeWindow_Buffer buffer;
+    ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
+    ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
+
+    malicious->setExpectedSlot(1);
+    malicious->beMalicious(-1);
+    ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
+}
+
+TEST(Malicious, Bug36991414NumSlots) {
+    sp<MaliciousBQP> malicious = getMaliciousBQP();
+    sp<Surface> surface = new Surface(malicious);
+
+    ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
+    ANativeWindow_Buffer buffer;
+    ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
+    ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
+
+    malicious->setExpectedSlot(1);
+    malicious->beMalicious(BufferQueueDefs::NUM_BUFFER_SLOTS);
+    ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
+}
+
+} // namespace test
+} // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 08d6715..fcaa23a 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -24,6 +24,7 @@
 #include <cutils/properties.h>
 #include <gui/BufferItemConsumer.h>
 #include <gui/IDisplayEventConnection.h>
+#include <gui/IProducerListener.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
@@ -320,6 +321,77 @@
     ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, fence));
 }
 
+TEST_F(SurfaceTest, GetAndFlushRemovedBuffers) {
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+
+    sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+    consumer->consumerConnect(dummyConsumer, false);
+    consumer->setConsumerName(String8("TestConsumer"));
+
+    sp<Surface> surface = new Surface(producer);
+    sp<ANativeWindow> window(surface);
+    sp<DummyProducerListener> listener = new DummyProducerListener();
+    ASSERT_EQ(OK, surface->connect(
+            NATIVE_WINDOW_API_CPU,
+            /*listener*/listener,
+            /*reportBufferRemoval*/true));
+    const int BUFFER_COUNT = 4;
+    ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(window.get(), BUFFER_COUNT));
+
+    sp<GraphicBuffer> detachedBuffer;
+    sp<Fence> outFence;
+    int fences[BUFFER_COUNT];
+    ANativeWindowBuffer* buffers[BUFFER_COUNT];
+    // Allocate buffers because detachNextBuffer requires allocated buffers
+    for (int i = 0; i < BUFFER_COUNT; i++) {
+        ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffers[i], &fences[i]));
+    }
+    for (int i = 0; i < BUFFER_COUNT; i++) {
+        ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffers[i], fences[i]));
+    }
+
+    // Test detached buffer is correctly reported
+    ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+    std::vector<sp<GraphicBuffer>> removedBuffers;
+    ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+    ASSERT_EQ(1u, removedBuffers.size());
+    ASSERT_EQ(detachedBuffer->handle, removedBuffers.at(0)->handle);
+    // Test the list is flushed one getAndFlushRemovedBuffers returns
+    ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+    ASSERT_EQ(0u, removedBuffers.size());
+
+
+    // Test removed buffer list is cleanup after next dequeueBuffer call
+    ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffers[0], &fences[0]));
+    ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+    ASSERT_EQ(0u, removedBuffers.size());
+    ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffers[0], fences[0]));
+
+    // Test removed buffer list is cleanup after next detachNextBuffer call
+    ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+    ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+    ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+    ASSERT_EQ(1u, removedBuffers.size());
+    ASSERT_EQ(detachedBuffer->handle, removedBuffers.at(0)->handle);
+
+    // Re-allocate buffers since all buffers are detached up to now
+    for (int i = 0; i < BUFFER_COUNT; i++) {
+        ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffers[i], &fences[i]));
+    }
+    for (int i = 0; i < BUFFER_COUNT; i++) {
+        ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffers[i], fences[i]));
+    }
+
+    ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&detachedBuffer, &outFence));
+    ASSERT_EQ(NO_ERROR, surface->attachBuffer(detachedBuffer.get()));
+    ASSERT_EQ(OK, surface->getAndFlushRemovedBuffers(&removedBuffers));
+    // Depends on which slot GraphicBufferProducer impl pick, the attach call might
+    // get 0 or 1 buffer removed.
+    ASSERT_LE(removedBuffers.size(), 1u);
+}
 
 class FakeConsumer : public BnConsumerListener {
 public:
diff --git a/libs/hwc2on1adapter/Android.bp b/libs/hwc2on1adapter/Android.bp
index 5d7f660..ec9cbf8 100644
--- a/libs/hwc2on1adapter/Android.bp
+++ b/libs/hwc2on1adapter/Android.bp
@@ -14,7 +14,7 @@
 
 cc_library_shared {
     name: "libhwc2on1adapter",
-    vendor_available: true,
+    vendor: true,
 
     clang: true,
     cppflags: [
diff --git a/libs/hwc2on1adapter/CleanSpec.mk b/libs/hwc2on1adapter/CleanSpec.mk
new file mode 100644
index 0000000..7fc2216
--- /dev/null
+++ b/libs/hwc2on1adapter/CleanSpec.mk
@@ -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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libhwc2on1adapter_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libhwc2on1adapter.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/libhwc2on1adapter.so)
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 5ccf178..406968d 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -72,6 +72,7 @@
         "libhardware",
         "libhidlbase",
         "libhidltransport",
+        "libhwbinder",
         "libsync",
         "libutils",
         "liblog",
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index f8d9401..87dbaf4 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "Gralloc2"
 
+#include <hwbinder/IPCThreadState.h>
 #include <ui/Gralloc2.h>
 
 #include <log/log.h>
@@ -241,6 +242,9 @@
                 *outStride = tmpStride;
             });
 
+    // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
+    hardware::IPCThreadState::self()->flushCommands();
+
     return (ret.isOk()) ? error : kTransactionError;
 }
 
diff --git a/services/displayservice/Android.bp b/services/displayservice/Android.bp
new file mode 100644
index 0000000..3442cb2
--- /dev/null
+++ b/services/displayservice/Android.bp
@@ -0,0 +1,46 @@
+//
+// 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.
+//
+
+cc_library_shared {
+    name: "libdisplayservicehidl",
+
+    srcs: [
+        "DisplayService.cpp",
+        "DisplayEventReceiver.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libgui",
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "android.frameworks.displayservice@1.0",
+    ],
+
+    export_include_dirs: ["include"],
+    export_shared_lib_headers: [
+        "android.frameworks.displayservice@1.0",
+        "libgui",
+        "libutils",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ]
+}
diff --git a/services/displayservice/DisplayEventReceiver.cpp b/services/displayservice/DisplayEventReceiver.cpp
new file mode 100644
index 0000000..5993e44
--- /dev/null
+++ b/services/displayservice/DisplayEventReceiver.cpp
@@ -0,0 +1,170 @@
+/*
+ * 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 "libdisplayservicehidl"
+
+#include <displayservice/DisplayEventReceiver.h>
+
+#include <android-base/logging.h>
+#include <android/frameworks/displayservice/1.0/BpHwEventCallback.h>
+
+#include <thread>
+
+namespace android {
+namespace frameworks {
+namespace displayservice {
+namespace V1_0 {
+namespace implementation {
+
+sp<Looper> getLooper() {
+    static sp<Looper> looper = []() {
+        sp<Looper> looper = new Looper(false /* allowNonCallbacks */);
+
+        std::thread{[&](){
+            int pollResult = looper->pollAll(-1 /* timeout */);
+            LOG(ERROR) << "Looper::pollAll returns unexpected " << pollResult;
+        }}.detach();
+
+        return looper;
+    }();
+
+    return looper;
+}
+
+DisplayEventReceiver::AttachedEvent::AttachedEvent(const sp<IEventCallback> &callback)
+    : mCallback(callback)
+{
+    mLooperAttached = getLooper()->addFd(mFwkReceiver.getFd(),
+            Looper::POLL_CALLBACK,
+            Looper::EVENT_INPUT,
+            this,
+            nullptr);
+}
+
+DisplayEventReceiver::AttachedEvent::~AttachedEvent() {
+    if (!detach()) {
+        LOG(ERROR) << "Could not remove fd from looper.";
+    }
+}
+
+bool DisplayEventReceiver::AttachedEvent::detach() {
+    if (!valid()) {
+        return true;
+    }
+
+    return getLooper()->removeFd(mFwkReceiver.getFd());
+}
+
+bool DisplayEventReceiver::AttachedEvent::valid() const {
+    return mFwkReceiver.initCheck() == OK && mLooperAttached;
+}
+
+DisplayEventReceiver::FwkReceiver &DisplayEventReceiver::AttachedEvent::receiver() {
+    return mFwkReceiver;
+}
+
+int DisplayEventReceiver::AttachedEvent::handleEvent(int fd, int events, void* /* data */) {
+    CHECK(fd == mFwkReceiver.getFd());
+
+    if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
+        LOG(ERROR) << "AttachedEvent handleEvent received error or hangup:" << events;
+        return 0; // remove the callback
+    }
+
+    if (!(events & Looper::EVENT_INPUT)) {
+        LOG(ERROR) << "AttachedEvent handleEvent unhandled poll event:" << events;
+        return 1; // keep the callback
+    }
+
+    constexpr size_t SIZE = 1;
+
+    ssize_t n;
+    FwkReceiver::Event buf[SIZE];
+    while ((n = mFwkReceiver.getEvents(buf, SIZE)) > 0) {
+        for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
+            const FwkReceiver::Event &event = buf[i];
+
+            uint32_t type = event.header.type;
+            uint64_t timestamp = event.header.timestamp;
+
+            switch(buf[i].header.type) {
+                case FwkReceiver::DISPLAY_EVENT_VSYNC: {
+                    mCallback->onVsync(timestamp, event.vsync.count);
+                } break;
+                case FwkReceiver::DISPLAY_EVENT_HOTPLUG: {
+                    mCallback->onHotplug(timestamp, event.hotplug.connected);
+                } break;
+                default: {
+                    LOG(ERROR) << "AttachedEvent handleEvent unknown type: " << type;
+                }
+            }
+        }
+    }
+
+    return 1; // keep on going
+}
+
+Return<Status> DisplayEventReceiver::init(const sp<IEventCallback>& callback) {
+    std::unique_lock<std::mutex> lock(mMutex);
+
+    if (mAttached != nullptr || callback == nullptr) {
+        return Status::BAD_VALUE;
+    }
+
+    mAttached = new AttachedEvent(callback);
+
+    return mAttached->valid() ? Status::SUCCESS : Status::UNKNOWN;
+}
+
+Return<Status> DisplayEventReceiver::setVsyncRate(int32_t count) {
+    std::unique_lock<std::mutex> lock(mMutex);
+
+    if (mAttached == nullptr || count < 0) {
+        return Status::BAD_VALUE;
+    }
+
+    bool success = OK == mAttached->receiver().setVsyncRate(count);
+    return success ? Status::SUCCESS : Status::UNKNOWN;
+}
+
+Return<Status> DisplayEventReceiver::requestNextVsync() {
+    std::unique_lock<std::mutex> lock(mMutex);
+
+    if (mAttached == nullptr) {
+        return Status::BAD_VALUE;
+    }
+
+    bool success = OK == mAttached->receiver().requestNextVsync();
+    return success ? Status::SUCCESS : Status::UNKNOWN;
+}
+
+Return<Status> DisplayEventReceiver::close() {
+    std::unique_lock<std::mutex> lock(mMutex);
+    if (mAttached == nullptr) {
+        return Status::BAD_VALUE;
+    }
+
+    bool success = mAttached->detach();
+    mAttached = nullptr;
+
+    return success ? Status::SUCCESS : Status::UNKNOWN;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace displayservice
+}  // namespace frameworks
+}  // namespace android
diff --git a/services/displayservice/DisplayService.cpp b/services/displayservice/DisplayService.cpp
new file mode 100644
index 0000000..18418fd
--- /dev/null
+++ b/services/displayservice/DisplayService.cpp
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#include <displayservice/DisplayService.h>
+#include <displayservice/DisplayEventReceiver.h>
+
+namespace android {
+namespace frameworks {
+namespace displayservice {
+namespace V1_0 {
+namespace implementation {
+
+Return<sp<IDisplayEventReceiver>> DisplayService::getEventReceiver() {
+    return new DisplayEventReceiver();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace displayservice
+}  // namespace frameworks
+}  // namespace android
diff --git a/services/displayservice/include/displayservice/DisplayEventReceiver.h b/services/displayservice/include/displayservice/DisplayEventReceiver.h
new file mode 100644
index 0000000..5d569b6
--- /dev/null
+++ b/services/displayservice/include/displayservice/DisplayEventReceiver.h
@@ -0,0 +1,72 @@
+/*
+ * 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_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYEVENTRECEIVER_H
+#define ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYEVENTRECEIVER_H
+
+#include <android/frameworks/displayservice/1.0/IDisplayEventReceiver.h>
+#include <gui/DisplayEventReceiver.h>
+#include <hidl/Status.h>
+#include <gui/DisplayEventReceiver.h>
+#include <utils/Looper.h>
+
+#include <mutex>
+
+namespace android {
+namespace frameworks {
+namespace displayservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+class DisplayEventReceiver : public IDisplayEventReceiver {
+public:
+    Return<Status> init(const sp<IEventCallback>& callback) override;
+    Return<Status> setVsyncRate(int32_t count) override;
+    Return<Status> requestNextVsync() override;
+    Return<Status> close() override;
+
+private:
+    using FwkReceiver = ::android::DisplayEventReceiver;
+
+    struct AttachedEvent : LooperCallback {
+        AttachedEvent(const sp<IEventCallback> &callback);
+        ~AttachedEvent();
+
+        bool detach();
+        bool valid() const;
+        FwkReceiver &receiver();
+        virtual int handleEvent(int fd, int events, void* /* data */) override;
+
+    private:
+        FwkReceiver mFwkReceiver;
+        sp<IEventCallback> mCallback;
+        bool mLooperAttached;
+    };
+
+    sp<AttachedEvent> mAttached;
+    std::mutex mMutex;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace displayservice
+}  // namespace frameworks
+}  // namespace android
+
+#endif  // ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYEVENTRECEIVER_H
diff --git a/services/displayservice/include/displayservice/DisplayService.h b/services/displayservice/include/displayservice/DisplayService.h
new file mode 100644
index 0000000..9722e71
--- /dev/null
+++ b/services/displayservice/include/displayservice/DisplayService.h
@@ -0,0 +1,42 @@
+/*
+ * 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_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYSERVICE_H
+#define ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYSERVICE_H
+
+#include <android/frameworks/displayservice/1.0/IDisplayService.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace frameworks {
+namespace displayservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct DisplayService : public IDisplayService {
+    Return<sp<IDisplayEventReceiver>> getEventReceiver() override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace displayservice
+}  // namespace frameworks
+}  // namespace android
+
+#endif  // ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYSERVICE_H
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 7bb20ba..95a522d 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -54,11 +54,7 @@
     LOCAL_SRC_FILES += \
         SurfaceFlinger.cpp \
         DisplayHardware/HWComposer.cpp
-    ifeq ($(TARGET_USES_HWC2ON1ADAPTER), true)
-        LOCAL_CFLAGS += -DBYPASS_IHWC
-    endif
 else
-    LOCAL_CFLAGS += -DBYPASS_IHWC
     LOCAL_SRC_FILES += \
         SurfaceFlinger_hwc1.cpp \
         DisplayHardware/HWComposer_hwc1.cpp
@@ -84,7 +80,6 @@
     libdl \
     libfmq \
     libhardware \
-    libhwc2on1adapter \
     libhidlbase \
     libhidltransport \
     libhwbinder \
@@ -133,11 +128,13 @@
     main_surfaceflinger.cpp
 
 LOCAL_SHARED_LIBRARIES := \
+    android.frameworks.displayservice@1.0 \
     android.hardware.configstore@1.0 \
     android.hardware.configstore-utils \
     android.hardware.graphics.allocator@2.0 \
     libsurfaceflinger \
     libcutils \
+    libdisplayservicehidl \
     liblog \
     libbinder \
     libhidlbase \
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 8270c39..0366630 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -88,55 +88,8 @@
 
 // Device methods
 
-#ifdef BYPASS_IHWC
-Device::Device(hwc2_device_t* device)
-  : mHwcDevice(device),
-    mCreateVirtualDisplay(nullptr),
-    mDestroyVirtualDisplay(nullptr),
-    mDump(nullptr),
-    mGetMaxVirtualDisplayCount(nullptr),
-    mRegisterCallback(nullptr),
-    mAcceptDisplayChanges(nullptr),
-    mCreateLayer(nullptr),
-    mDestroyLayer(nullptr),
-    mGetActiveConfig(nullptr),
-    mGetChangedCompositionTypes(nullptr),
-    mGetColorModes(nullptr),
-    mGetDisplayAttribute(nullptr),
-    mGetDisplayConfigs(nullptr),
-    mGetDisplayName(nullptr),
-    mGetDisplayRequests(nullptr),
-    mGetDisplayType(nullptr),
-    mGetDozeSupport(nullptr),
-    mGetHdrCapabilities(nullptr),
-    mGetReleaseFences(nullptr),
-    mPresentDisplay(nullptr),
-    mSetActiveConfig(nullptr),
-    mSetClientTarget(nullptr),
-    mSetColorMode(nullptr),
-    mSetColorTransform(nullptr),
-    mSetOutputBuffer(nullptr),
-    mSetPowerMode(nullptr),
-    mSetVsyncEnabled(nullptr),
-    mValidateDisplay(nullptr),
-    mSetCursorPosition(nullptr),
-    mSetLayerBuffer(nullptr),
-    mSetLayerSurfaceDamage(nullptr),
-    mSetLayerBlendMode(nullptr),
-    mSetLayerColor(nullptr),
-    mSetLayerCompositionType(nullptr),
-    mSetLayerDataspace(nullptr),
-    mSetLayerDisplayFrame(nullptr),
-    mSetLayerPlaneAlpha(nullptr),
-    mSetLayerSidebandStream(nullptr),
-    mSetLayerSourceCrop(nullptr),
-    mSetLayerTransform(nullptr),
-    mSetLayerVisibleRegion(nullptr),
-    mSetLayerZOrder(nullptr),
-#else
 Device::Device(bool useVrComposer)
   : mComposer(std::make_unique<Hwc2::Composer>(useVrComposer)),
-#endif // BYPASS_IHWC
     mCapabilities(),
     mDisplays(),
     mHotplug(),
@@ -147,18 +100,11 @@
     mPendingVsyncs()
 {
     loadCapabilities();
-    loadFunctionPointers();
     registerCallbacks();
 }
 
 Device::~Device()
 {
-#ifdef BYPASS_IHWC
-    if (mHwcDevice == nullptr) {
-        return;
-    }
-#endif
-
     for (auto element : mDisplays) {
         auto display = element.second.lock();
         if (!display) {
@@ -185,36 +131,18 @@
             }
         }
     }
-
-#ifdef BYPASS_IHWC
-    hwc2_close(mHwcDevice);
-#endif
 }
 
 // Required by HWC2 device
 
 std::string Device::dump() const
 {
-#ifdef BYPASS_IHWC
-    uint32_t numBytes = 0;
-    mDump(mHwcDevice, &numBytes, nullptr);
-
-    std::vector<char> buffer(numBytes);
-    mDump(mHwcDevice, &numBytes, buffer.data());
-
-    return std::string(buffer.data(), buffer.size());
-#else
     return mComposer->dumpDebugInfo();
-#endif
 }
 
 uint32_t Device::getMaxVirtualDisplayCount() const
 {
-#ifdef BYPASS_IHWC
-    return mGetMaxVirtualDisplayCount(mHwcDevice);
-#else
     return mComposer->getMaxVirtualDisplayCount();
-#endif
 }
 
 Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
@@ -223,15 +151,9 @@
     ALOGI("Creating virtual display");
 
     hwc2_display_t displayId = 0;
-#ifdef BYPASS_IHWC
-    int32_t intFormat = static_cast<int32_t>(*format);
-    int32_t intError = mCreateVirtualDisplay(mHwcDevice, width, height,
-            &intFormat, &displayId);
-#else
     auto intFormat = static_cast<Hwc2::PixelFormat>(*format);
     auto intError = mComposer->createVirtualDisplay(width, height,
             &intFormat, &displayId);
-#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -285,9 +207,7 @@
 {
     if (connected == Connection::Connected) {
         if (!display->isConnected()) {
-#ifndef BYPASS_IHWC
             mComposer->setClientTargetSlotCount(display->getId());
-#endif
             display->loadConfigs();
             display->setConnected(true);
         }
@@ -345,21 +265,10 @@
 {
     static_assert(sizeof(Capability) == sizeof(int32_t),
             "Capability size has changed");
-#ifdef BYPASS_IHWC
-    uint32_t numCapabilities = 0;
-    mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, nullptr);
-    std::vector<Capability> capabilities(numCapabilities);
-    auto asInt = reinterpret_cast<int32_t*>(capabilities.data());
-    mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, asInt);
-    for (auto capability : capabilities) {
-        mCapabilities.emplace(capability);
-    }
-#else
     auto capabilities = mComposer->getCapabilities();
     for (auto capability : capabilities) {
         mCapabilities.emplace(static_cast<Capability>(capability));
     }
-#endif
 }
 
 bool Device::hasCapability(HWC2::Capability capability) const
@@ -368,105 +277,6 @@
             capability) != mCapabilities.cend();
 }
 
-void Device::loadFunctionPointers()
-{
-#ifdef BYPASS_IHWC
-    // For all of these early returns, we log an error message inside
-    // loadFunctionPointer specifying which function failed to load
-
-    // Display function pointers
-    if (!loadFunctionPointer(FunctionDescriptor::CreateVirtualDisplay,
-            mCreateVirtualDisplay)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::DestroyVirtualDisplay,
-            mDestroyVirtualDisplay)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::Dump, mDump)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetMaxVirtualDisplayCount,
-            mGetMaxVirtualDisplayCount)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::RegisterCallback,
-            mRegisterCallback)) return;
-
-    // Device function pointers
-    if (!loadFunctionPointer(FunctionDescriptor::AcceptDisplayChanges,
-            mAcceptDisplayChanges)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::CreateLayer,
-            mCreateLayer)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::DestroyLayer,
-            mDestroyLayer)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetActiveConfig,
-            mGetActiveConfig)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetChangedCompositionTypes,
-            mGetChangedCompositionTypes)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetColorModes,
-            mGetColorModes)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayAttribute,
-            mGetDisplayAttribute)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayConfigs,
-            mGetDisplayConfigs)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayName,
-            mGetDisplayName)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayRequests,
-            mGetDisplayRequests)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayType,
-            mGetDisplayType)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetDozeSupport,
-            mGetDozeSupport)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetHdrCapabilities,
-            mGetHdrCapabilities)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::GetReleaseFences,
-            mGetReleaseFences)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::PresentDisplay,
-            mPresentDisplay)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetActiveConfig,
-            mSetActiveConfig)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetClientTarget,
-            mSetClientTarget)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetColorMode,
-            mSetColorMode)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetColorTransform,
-            mSetColorTransform)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetOutputBuffer,
-            mSetOutputBuffer)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetPowerMode,
-            mSetPowerMode)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetVsyncEnabled,
-            mSetVsyncEnabled)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::ValidateDisplay,
-            mValidateDisplay)) return;
-
-    // Layer function pointers
-    if (!loadFunctionPointer(FunctionDescriptor::SetCursorPosition,
-            mSetCursorPosition)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerBuffer,
-            mSetLayerBuffer)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerSurfaceDamage,
-            mSetLayerSurfaceDamage)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerBlendMode,
-            mSetLayerBlendMode)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerColor,
-            mSetLayerColor)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerCompositionType,
-            mSetLayerCompositionType)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerDataspace,
-            mSetLayerDataspace)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerDisplayFrame,
-            mSetLayerDisplayFrame)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerPlaneAlpha,
-            mSetLayerPlaneAlpha)) return;
-    if (hasCapability(Capability::SidebandStream)) {
-        if (!loadFunctionPointer(FunctionDescriptor::SetLayerSidebandStream,
-                mSetLayerSidebandStream)) return;
-    }
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerSourceCrop,
-            mSetLayerSourceCrop)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerTransform,
-            mSetLayerTransform)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerVisibleRegion,
-            mSetLayerVisibleRegion)) return;
-    if (!loadFunctionPointer(FunctionDescriptor::SetLayerZOrder,
-            mSetLayerZOrder)) return;
-#endif // BYPASS_IHWC
-}
-
 namespace {
 class ComposerCallback : public Hwc2::IComposerCallback {
 public:
@@ -498,14 +308,8 @@
 
 void Device::registerCallbacks()
 {
-#ifdef BYPASS_IHWC
-    registerCallback<HWC2_PFN_HOTPLUG>(Callback::Hotplug, hotplug_hook);
-    registerCallback<HWC2_PFN_REFRESH>(Callback::Refresh, refresh_hook);
-    registerCallback<HWC2_PFN_VSYNC>(Callback::Vsync, vsync_hook);
-#else
     sp<ComposerCallback> callback = new ComposerCallback(this);
     mComposer->registerCallback(callback);
-#endif
 }
 
 
@@ -514,11 +318,7 @@
 void Device::destroyVirtualDisplay(hwc2_display_t display)
 {
     ALOGI("Destroying virtual display");
-#ifdef BYPASS_IHWC
-    int32_t intError = mDestroyVirtualDisplay(mHwcDevice, display);
-#else
     auto intError = mComposer->destroyVirtualDisplay(display);
-#endif
     auto error = static_cast<Error>(intError);
     ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:"
             " %s (%d)", display, to_string(error).c_str(), intError);
@@ -535,13 +335,8 @@
 {
     ALOGV("Created display %" PRIu64, id);
 
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
-            reinterpret_cast<int32_t *>(&mType));
-#else
     auto intError = mDevice.mComposer->getDisplayType(mId,
             reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType));
-#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)",
@@ -588,22 +383,14 @@
 
 Error Display::acceptChanges()
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mAcceptDisplayChanges(mDevice.mHwcDevice, mId);
-#else
     auto intError = mDevice.mComposer->acceptDisplayChanges(mId);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Display::createLayer(std::shared_ptr<Layer>* outLayer)
 {
     hwc2_layer_t layerId = 0;
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mCreateLayer(mDevice.mHwcDevice, mId, &layerId);
-#else
     auto intError = mDevice.mComposer->createLayer(mId, &layerId);
-#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -620,12 +407,7 @@
 {
     ALOGV("[%" PRIu64 "] getActiveConfig", mId);
     hwc2_config_t configId = 0;
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mGetActiveConfig(mDevice.mHwcDevice, mId,
-            &configId);
-#else
     auto intError = mDevice.mComposer->getActiveConfig(mId, &configId);
-#endif
     auto error = static_cast<Error>(intError);
 
     if (error != Error::None) {
@@ -650,27 +432,12 @@
 Error Display::getChangedCompositionTypes(
         std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes)
 {
-#ifdef BYPASS_IHWC
-    uint32_t numElements = 0;
-    int32_t intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice,
-            mId, &numElements, nullptr, nullptr);
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    std::vector<hwc2_layer_t> layerIds(numElements);
-    std::vector<int32_t> types(numElements);
-    intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice, mId,
-            &numElements, layerIds.data(), types.data());
-#else
     std::vector<Hwc2::Layer> layerIds;
     std::vector<Hwc2::IComposerClient::Composition> types;
     auto intError = mDevice.mComposer->getChangedCompositionTypes(mId,
             &layerIds, &types);
     uint32_t numElements = layerIds.size();
     auto error = static_cast<Error>(intError);
-#endif
     error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -696,25 +463,10 @@
 
 Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const
 {
-#ifdef BYPASS_IHWC
-    uint32_t numModes = 0;
-    int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId,
-            &numModes, nullptr);
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None)  {
-        return error;
-    }
-
-    std::vector<int32_t> modes(numModes);
-    intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId, &numModes,
-            modes.data());
-    error = static_cast<Error>(intError);
-#else
     std::vector<Hwc2::ColorMode> modes;
     auto intError = mDevice.mComposer->getColorModes(mId, &modes);
     uint32_t numModes = modes.size();
     auto error = static_cast<Error>(intError);
-#endif
     if (error != Error::None) {
         return error;
     }
@@ -737,52 +489,14 @@
 
 Error Display::getName(std::string* outName) const
 {
-#ifdef BYPASS_IHWC
-    uint32_t size;
-    int32_t intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
-            nullptr);
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    std::vector<char> rawName(size);
-    intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
-            rawName.data());
-    error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    *outName = std::string(rawName.cbegin(), rawName.cend());
-    return Error::None;
-#else
     auto intError = mDevice.mComposer->getDisplayName(mId, outName);
     return static_cast<Error>(intError);
-#endif
 }
 
 Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
         std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
                 outLayerRequests)
 {
-#ifdef BYPASS_IHWC
-    int32_t intDisplayRequests = 0;
-    uint32_t numElements = 0;
-    int32_t intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
-            &intDisplayRequests, &numElements, nullptr, nullptr);
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    std::vector<hwc2_layer_t> layerIds(numElements);
-    std::vector<int32_t> layerRequests(numElements);
-    intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
-            &intDisplayRequests, &numElements, layerIds.data(),
-            layerRequests.data());
-    error = static_cast<Error>(intError);
-#else
     uint32_t intDisplayRequests;
     std::vector<Hwc2::Layer> layerIds;
     std::vector<uint32_t> layerRequests;
@@ -790,7 +504,6 @@
             &intDisplayRequests, &layerIds, &layerRequests);
     uint32_t numElements = layerIds.size();
     auto error = static_cast<Error>(intError);
-#endif
     if (error != Error::None) {
         return error;
     }
@@ -821,14 +534,8 @@
 
 Error Display::supportsDoze(bool* outSupport) const
 {
-#ifdef BYPASS_IHWC
-    int32_t intSupport = 0;
-    int32_t intError = mDevice.mGetDozeSupport(mDevice.mHwcDevice, mId,
-            &intSupport);
-#else
     bool intSupport = false;
     auto intError = mDevice.mComposer->getDozeSupport(mId, &intSupport);
-#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -844,20 +551,6 @@
     float maxLuminance = -1.0f;
     float maxAverageLuminance = -1.0f;
     float minLuminance = -1.0f;
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId,
-            &numTypes, nullptr, &maxLuminance, &maxAverageLuminance,
-            &minLuminance);
-    auto error = static_cast<HWC2::Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    std::vector<int32_t> types(numTypes);
-    intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId, &numTypes,
-            types.data(), &maxLuminance, &maxAverageLuminance, &minLuminance);
-    error = static_cast<HWC2::Error>(intError);
-#else
     std::vector<Hwc2::Hdr> intTypes;
     auto intError = mDevice.mComposer->getHdrCapabilities(mId, &intTypes,
             &maxLuminance, &maxAverageLuminance, &minLuminance);
@@ -868,7 +561,6 @@
         types.push_back(static_cast<int32_t>(type));
     }
     numTypes = types.size();
-#endif
     if (error != Error::None) {
         return error;
     }
@@ -881,28 +573,12 @@
 Error Display::getReleaseFences(
         std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
 {
-#ifdef BYPASS_IHWC
-    uint32_t numElements = 0;
-    int32_t intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId,
-            &numElements, nullptr, nullptr);
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    std::vector<hwc2_layer_t> layerIds(numElements);
-    std::vector<int32_t> fenceFds(numElements);
-    intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId, &numElements,
-            layerIds.data(), fenceFds.data());
-    error = static_cast<Error>(intError);
-#else
     std::vector<Hwc2::Layer> layerIds;
     std::vector<int> fenceFds;
     auto intError = mDevice.mComposer->getReleaseFences(mId,
             &layerIds, &fenceFds);
     auto error = static_cast<Error>(intError);
     uint32_t numElements = layerIds.size();
-#endif
     if (error != Error::None) {
         return error;
     }
@@ -917,6 +593,9 @@
         } else {
             ALOGE("getReleaseFences: invalid layer %" PRIu64
                     " found on display %" PRIu64, layerIds[element], mId);
+            for (; element < numElements; ++element) {
+                close(fenceFds[element]);
+            }
             return Error::BadLayer;
         }
     }
@@ -928,12 +607,7 @@
 Error Display::present(sp<Fence>* outPresentFence)
 {
     int32_t presentFenceFd = -1;
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mPresentDisplay(mDevice.mHwcDevice, mId,
-            &presentFenceFd);
-#else
     auto intError = mDevice.mComposer->presentDisplay(mId, &presentFenceFd);
-#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -951,12 +625,7 @@
                 config->getDisplayId(), mId);
         return Error::BadConfig;
     }
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetActiveConfig(mDevice.mHwcDevice, mId,
-            config->getId());
-#else
     auto intError = mDevice.mComposer->setActiveConfig(mId, config->getId());
-#endif
     return static_cast<Error>(intError);
 }
 
@@ -965,44 +634,24 @@
 {
     // TODO: Properly encode client target surface damage
     int32_t fenceFd = acquireFence->dup();
-#ifdef BYPASS_IHWC
-    (void) slot;
-    buffer_handle_t handle = nullptr;
-    if (target.get() && target->getNativeBuffer()) {
-        handle = target->getNativeBuffer()->handle;
-    }
-
-    int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, handle,
-            fenceFd, static_cast<int32_t>(dataspace), {0, nullptr});
-#else
     auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
             fenceFd, static_cast<Hwc2::Dataspace>(dataspace),
             std::vector<Hwc2::IComposerClient::Rect>());
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Display::setColorMode(android_color_mode_t mode)
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode);
-#else
     auto intError = mDevice.mComposer->setColorMode(mId,
             static_cast<Hwc2::ColorMode>(mode));
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Display::setColorTransform(const android::mat4& matrix,
         android_color_transform_t hint)
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetColorTransform(mDevice.mHwcDevice, mId,
-            matrix.asArray(), static_cast<int32_t>(hint));
-#else
     auto intError = mDevice.mComposer->setColorTransform(mId,
             matrix.asArray(), static_cast<Hwc2::ColorTransform>(hint));
-#endif
     return static_cast<Error>(intError);
 }
 
@@ -1011,38 +660,22 @@
 {
     int32_t fenceFd = releaseFence->dup();
     auto handle = buffer->getNativeBuffer()->handle;
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetOutputBuffer(mDevice.mHwcDevice, mId, handle,
-            fenceFd);
-#else
     auto intError = mDevice.mComposer->setOutputBuffer(mId, handle, fenceFd);
-#endif
     close(fenceFd);
     return static_cast<Error>(intError);
 }
 
 Error Display::setPowerMode(PowerMode mode)
 {
-#ifdef BYPASS_IHWC
-    auto intMode = static_cast<int32_t>(mode);
-    int32_t intError = mDevice.mSetPowerMode(mDevice.mHwcDevice, mId, intMode);
-#else
     auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode);
     auto intError = mDevice.mComposer->setPowerMode(mId, intMode);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Display::setVsyncEnabled(Vsync enabled)
 {
-#ifdef BYPASS_IHWC
-    auto intEnabled = static_cast<int32_t>(enabled);
-    int32_t intError = mDevice.mSetVsyncEnabled(mDevice.mHwcDevice, mId,
-            intEnabled);
-#else
     auto intEnabled = static_cast<Hwc2::IComposerClient::Vsync>(enabled);
     auto intError = mDevice.mComposer->setVsyncEnabled(mId, intEnabled);
-#endif
     return static_cast<Error>(intError);
 }
 
@@ -1050,13 +683,8 @@
 {
     uint32_t numTypes = 0;
     uint32_t numRequests = 0;
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mValidateDisplay(mDevice.mHwcDevice, mId,
-            &numTypes, &numRequests);
-#else
     auto intError = mDevice.mComposer->validateDisplay(mId,
             &numTypes, &numRequests);
-#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None && error != Error::HasChanges) {
         return error;
@@ -1072,14 +700,9 @@
 int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
 {
     int32_t value = 0;
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mGetDisplayAttribute(mDevice.mHwcDevice, mId,
-            configId, static_cast<int32_t>(attribute), &value);
-#else
     auto intError = mDevice.mComposer->getDisplayAttribute(mId, configId,
             static_cast<Hwc2::IComposerClient::Attribute>(attribute),
             &value);
-#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         ALOGE("getDisplayAttribute(%" PRIu64 ", %u, %s) failed: %s (%d)", mId,
@@ -1108,26 +731,9 @@
 {
     ALOGV("[%" PRIu64 "] loadConfigs", mId);
 
-#ifdef BYPASS_IHWC
-    uint32_t numConfigs = 0;
-    int32_t intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId,
-            &numConfigs, nullptr);
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        ALOGE("[%" PRIu64 "] getDisplayConfigs [1] failed: %s (%d)", mId,
-                to_string(error).c_str(), intError);
-        return;
-    }
-
-    std::vector<hwc2_config_t> configIds(numConfigs);
-    intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId, &numConfigs,
-            configIds.data());
-    error = static_cast<Error>(intError);
-#else
     std::vector<Hwc2::Config> configIds;
     auto intError = mDevice.mComposer->getDisplayConfigs(mId, &configIds);
     auto error = static_cast<Error>(intError);
-#endif
     if (error != Error::None) {
         ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId,
                 to_string(error).c_str(), intError);
@@ -1143,11 +749,7 @@
 
 void Display::destroyLayer(hwc2_layer_t layerId)
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mDestroyLayer(mDevice.mHwcDevice, mId, layerId);
-#else
     auto intError =mDevice.mComposer->destroyLayer(mId, layerId);
-#endif
     auto error = static_cast<Error>(intError);
     ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
             " failed: %s (%d)", mId, layerId, to_string(error).c_str(),
@@ -1189,13 +791,8 @@
 
 Error Layer::setCursorPosition(int32_t x, int32_t y)
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetCursorPosition(mDevice.mHwcDevice,
-            mDisplayId, mId, x, y);
-#else
     auto intError = mDevice.mComposer->setCursorPosition(mDisplayId,
             mId, x, y);
-#endif
     return static_cast<Error>(intError);
 }
 
@@ -1203,19 +800,8 @@
         const sp<Fence>& acquireFence)
 {
     int32_t fenceFd = acquireFence->dup();
-#ifdef BYPASS_IHWC
-    (void) slot;
-    buffer_handle_t handle = nullptr;
-    if (buffer.get() && buffer->getNativeBuffer()) {
-        handle = buffer->getNativeBuffer()->handle;
-    }
-
-    int32_t intError = mDevice.mSetLayerBuffer(mDevice.mHwcDevice, mDisplayId,
-            mId, handle, fenceFd);
-#else
     auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
             mId, slot, buffer, fenceFd);
-#endif
     return static_cast<Error>(intError);
 }
 
@@ -1223,44 +809,22 @@
 {
     // We encode default full-screen damage as INVALID_RECT upstream, but as 0
     // rects for HWC
-#ifdef BYPASS_IHWC
-    int32_t intError = 0;
-#else
     Hwc2::Error intError = Hwc2::Error::NONE;
-#endif
     if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) {
-#ifdef BYPASS_IHWC
-        intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
-                mDisplayId, mId, {0, nullptr});
-#else
         intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
                 mId, std::vector<Hwc2::IComposerClient::Rect>());
-#endif
     } else {
         size_t rectCount = 0;
         auto rectArray = damage.getArray(&rectCount);
 
-#ifdef BYPASS_IHWC
-        std::vector<hwc_rect_t> hwcRects;
-#else
         std::vector<Hwc2::IComposerClient::Rect> hwcRects;
-#endif
         for (size_t rect = 0; rect < rectCount; ++rect) {
             hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
                     rectArray[rect].right, rectArray[rect].bottom});
         }
 
-#ifdef BYPASS_IHWC
-        hwc_region_t hwcRegion = {};
-        hwcRegion.numRects = rectCount;
-        hwcRegion.rects = hwcRects.data();
-
-        intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
-                mDisplayId, mId, hwcRegion);
-#else
         intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
                 mId, hwcRects);
-#endif
     }
 
     return static_cast<Error>(intError);
@@ -1268,83 +832,49 @@
 
 Error Layer::setBlendMode(BlendMode mode)
 {
-#ifdef BYPASS_IHWC
-    auto intMode = static_cast<int32_t>(mode);
-    int32_t intError = mDevice.mSetLayerBlendMode(mDevice.mHwcDevice,
-            mDisplayId, mId, intMode);
-#else
     auto intMode = static_cast<Hwc2::IComposerClient::BlendMode>(mode);
     auto intError = mDevice.mComposer->setLayerBlendMode(mDisplayId,
             mId, intMode);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setColor(hwc_color_t color)
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetLayerColor(mDevice.mHwcDevice, mDisplayId,
-            mId, color);
-#else
     Hwc2::IComposerClient::Color hwcColor{color.r, color.g, color.b, color.a};
     auto intError = mDevice.mComposer->setLayerColor(mDisplayId,
             mId, hwcColor);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setCompositionType(Composition type)
 {
-#ifdef BYPASS_IHWC
-    auto intType = static_cast<int32_t>(type);
-    int32_t intError = mDevice.mSetLayerCompositionType(mDevice.mHwcDevice,
-            mDisplayId, mId, intType);
-#else
     auto intType = static_cast<Hwc2::IComposerClient::Composition>(type);
     auto intError = mDevice.mComposer->setLayerCompositionType(mDisplayId,
             mId, intType);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setDataspace(android_dataspace_t dataspace)
 {
-#ifdef BYPASS_IHWC
-    auto intDataspace = static_cast<int32_t>(dataspace);
-    int32_t intError = mDevice.mSetLayerDataspace(mDevice.mHwcDevice,
-            mDisplayId, mId, intDataspace);
-#else
     auto intDataspace = static_cast<Hwc2::Dataspace>(dataspace);
     auto intError = mDevice.mComposer->setLayerDataspace(mDisplayId,
             mId, intDataspace);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setDisplayFrame(const Rect& frame)
 {
-#ifdef BYPASS_IHWC
-    hwc_rect_t hwcRect{frame.left, frame.top, frame.right, frame.bottom};
-    int32_t intError = mDevice.mSetLayerDisplayFrame(mDevice.mHwcDevice,
-            mDisplayId, mId, hwcRect);
-#else
     Hwc2::IComposerClient::Rect hwcRect{frame.left, frame.top,
         frame.right, frame.bottom};
     auto intError = mDevice.mComposer->setLayerDisplayFrame(mDisplayId,
             mId, hwcRect);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setPlaneAlpha(float alpha)
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetLayerPlaneAlpha(mDevice.mHwcDevice,
-            mDisplayId, mId, alpha);
-#else
     auto intError = mDevice.mComposer->setLayerPlaneAlpha(mDisplayId,
             mId, alpha);
-#endif
     return static_cast<Error>(intError);
 }
 
@@ -1355,42 +885,25 @@
                 "device supports sideband streams");
         return Error::Unsupported;
     }
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetLayerSidebandStream(mDevice.mHwcDevice,
-            mDisplayId, mId, stream);
-#else
     auto intError = mDevice.mComposer->setLayerSidebandStream(mDisplayId,
             mId, stream);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setSourceCrop(const FloatRect& crop)
 {
-#ifdef BYPASS_IHWC
-    hwc_frect_t hwcRect{crop.left, crop.top, crop.right, crop.bottom};
-    int32_t intError = mDevice.mSetLayerSourceCrop(mDevice.mHwcDevice,
-            mDisplayId, mId, hwcRect);
-#else
     Hwc2::IComposerClient::FRect hwcRect{
         crop.left, crop.top, crop.right, crop.bottom};
     auto intError = mDevice.mComposer->setLayerSourceCrop(mDisplayId,
             mId, hwcRect);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setTransform(Transform transform)
 {
-#ifdef BYPASS_IHWC
-    auto intTransform = static_cast<int32_t>(transform);
-    int32_t intError = mDevice.mSetLayerTransform(mDevice.mHwcDevice,
-            mDisplayId, mId, intTransform);
-#else
     auto intTransform = static_cast<Hwc2::Transform>(transform);
     auto intError = mDevice.mComposer->setLayerTransform(mDisplayId,
             mId, intTransform);
-#endif
     return static_cast<Error>(intError);
 }
 
@@ -1399,50 +912,26 @@
     size_t rectCount = 0;
     auto rectArray = region.getArray(&rectCount);
 
-#ifdef BYPASS_IHWC
-    std::vector<hwc_rect_t> hwcRects;
-#else
     std::vector<Hwc2::IComposerClient::Rect> hwcRects;
-#endif
     for (size_t rect = 0; rect < rectCount; ++rect) {
         hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
                 rectArray[rect].right, rectArray[rect].bottom});
     }
 
-#ifdef BYPASS_IHWC
-    hwc_region_t hwcRegion = {};
-    hwcRegion.numRects = rectCount;
-    hwcRegion.rects = hwcRects.data();
-
-    int32_t intError = mDevice.mSetLayerVisibleRegion(mDevice.mHwcDevice,
-            mDisplayId, mId, hwcRegion);
-#else
     auto intError = mDevice.mComposer->setLayerVisibleRegion(mDisplayId,
             mId, hwcRects);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setZOrder(uint32_t z)
 {
-#ifdef BYPASS_IHWC
-    int32_t intError = mDevice.mSetLayerZOrder(mDevice.mHwcDevice, mDisplayId,
-            mId, z);
-#else
     auto intError = mDevice.mComposer->setLayerZOrder(mDisplayId, mId, z);
-#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setInfo(uint32_t type, uint32_t appId)
 {
-#ifdef BYPASS_IHWC
-  (void)type;
-  (void)appId;
-  int32_t intError = 0;
-#else
   auto intError = mDevice.mComposer->setLayerInfo(mDisplayId, mId, type, appId);
-#endif
   return static_cast<Error>(intError);
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 643b1e0..97582a7 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -62,14 +62,10 @@
 class Device
 {
 public:
-#ifdef BYPASS_IHWC
-    explicit Device(hwc2_device_t* device);
-#else
     // useVrComposer is passed to the composer HAL. When true, the composer HAL
     // will use the vr composer service, otherwise it uses the real hardware
     // composer.
     Device(bool useVrComposer);
-#endif
     ~Device();
 
     friend class HWC2::Display;
@@ -107,43 +103,12 @@
 
     bool hasCapability(HWC2::Capability capability) const;
 
-#ifdef BYPASS_IHWC
-    android::Hwc2::Composer* getComposer() { return nullptr; }
-#else
     android::Hwc2::Composer* getComposer() { return mComposer.get(); }
-#endif
 
 private:
     // Initialization methods
 
-#ifdef BYPASS_IHWC
-    template <typename PFN>
-    [[clang::warn_unused_result]] bool loadFunctionPointer(
-            FunctionDescriptor desc, PFN& outPFN) {
-        auto intDesc = static_cast<int32_t>(desc);
-        auto pfn = mHwcDevice->getFunction(mHwcDevice, intDesc);
-        if (pfn != nullptr) {
-            outPFN = reinterpret_cast<PFN>(pfn);
-            return true;
-        } else {
-            ALOGE("Failed to load function %s", to_string(desc).c_str());
-            return false;
-        }
-    }
-
-    template <typename PFN, typename HOOK>
-    void registerCallback(Callback callback, HOOK hook) {
-        static_assert(std::is_same<PFN, HOOK>::value,
-                "Incompatible function pointer");
-        auto intCallback = static_cast<int32_t>(callback);
-        auto callbackData = static_cast<hwc2_callback_data_t>(this);
-        auto pfn = reinterpret_cast<hwc2_function_pointer_t>(hook);
-        mRegisterCallback(mHwcDevice, intCallback, callbackData, pfn);
-    }
-#endif
-
     void loadCapabilities();
-    void loadFunctionPointers();
     void registerCallbacks();
 
     // For use by Display
@@ -151,60 +116,7 @@
     void destroyVirtualDisplay(hwc2_display_t display);
 
     // Member variables
-
-#ifdef BYPASS_IHWC
-    hwc2_device_t* mHwcDevice;
-
-    // Device function pointers
-    HWC2_PFN_CREATE_VIRTUAL_DISPLAY mCreateVirtualDisplay;
-    HWC2_PFN_DESTROY_VIRTUAL_DISPLAY mDestroyVirtualDisplay;
-    HWC2_PFN_DUMP mDump;
-    HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT mGetMaxVirtualDisplayCount;
-    HWC2_PFN_REGISTER_CALLBACK mRegisterCallback;
-
-    // Display function pointers
-    HWC2_PFN_ACCEPT_DISPLAY_CHANGES mAcceptDisplayChanges;
-    HWC2_PFN_CREATE_LAYER mCreateLayer;
-    HWC2_PFN_DESTROY_LAYER mDestroyLayer;
-    HWC2_PFN_GET_ACTIVE_CONFIG mGetActiveConfig;
-    HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES mGetChangedCompositionTypes;
-    HWC2_PFN_GET_COLOR_MODES mGetColorModes;
-    HWC2_PFN_GET_DISPLAY_ATTRIBUTE mGetDisplayAttribute;
-    HWC2_PFN_GET_DISPLAY_CONFIGS mGetDisplayConfigs;
-    HWC2_PFN_GET_DISPLAY_NAME mGetDisplayName;
-    HWC2_PFN_GET_DISPLAY_REQUESTS mGetDisplayRequests;
-    HWC2_PFN_GET_DISPLAY_TYPE mGetDisplayType;
-    HWC2_PFN_GET_DOZE_SUPPORT mGetDozeSupport;
-    HWC2_PFN_GET_HDR_CAPABILITIES mGetHdrCapabilities;
-    HWC2_PFN_GET_RELEASE_FENCES mGetReleaseFences;
-    HWC2_PFN_PRESENT_DISPLAY mPresentDisplay;
-    HWC2_PFN_SET_ACTIVE_CONFIG mSetActiveConfig;
-    HWC2_PFN_SET_CLIENT_TARGET mSetClientTarget;
-    HWC2_PFN_SET_COLOR_MODE mSetColorMode;
-    HWC2_PFN_SET_COLOR_TRANSFORM mSetColorTransform;
-    HWC2_PFN_SET_OUTPUT_BUFFER mSetOutputBuffer;
-    HWC2_PFN_SET_POWER_MODE mSetPowerMode;
-    HWC2_PFN_SET_VSYNC_ENABLED mSetVsyncEnabled;
-    HWC2_PFN_VALIDATE_DISPLAY mValidateDisplay;
-
-    // Layer function pointers
-    HWC2_PFN_SET_CURSOR_POSITION mSetCursorPosition;
-    HWC2_PFN_SET_LAYER_BUFFER mSetLayerBuffer;
-    HWC2_PFN_SET_LAYER_SURFACE_DAMAGE mSetLayerSurfaceDamage;
-    HWC2_PFN_SET_LAYER_BLEND_MODE mSetLayerBlendMode;
-    HWC2_PFN_SET_LAYER_COLOR mSetLayerColor;
-    HWC2_PFN_SET_LAYER_COMPOSITION_TYPE mSetLayerCompositionType;
-    HWC2_PFN_SET_LAYER_DATASPACE mSetLayerDataspace;
-    HWC2_PFN_SET_LAYER_DISPLAY_FRAME mSetLayerDisplayFrame;
-    HWC2_PFN_SET_LAYER_PLANE_ALPHA mSetLayerPlaneAlpha;
-    HWC2_PFN_SET_LAYER_SIDEBAND_STREAM mSetLayerSidebandStream;
-    HWC2_PFN_SET_LAYER_SOURCE_CROP mSetLayerSourceCrop;
-    HWC2_PFN_SET_LAYER_TRANSFORM mSetLayerTransform;
-    HWC2_PFN_SET_LAYER_VISIBLE_REGION mSetLayerVisibleRegion;
-    HWC2_PFN_SET_LAYER_Z_ORDER mSetLayerZOrder;
-#else
     std::unique_ptr<android::Hwc2::Composer> mComposer;
-#endif // BYPASS_IHWC
 
     std::unordered_set<Capability> mCapabilities;
     std::unordered_map<hwc2_display_t, std::weak_ptr<Display>> mDisplays;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 04ab78f..42be935 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -47,7 +47,6 @@
 #include <log/log.h>
 
 #include "HWComposer.h"
-#include "hwc2on1adapter/HWC2On1Adapter.h"
 #include "HWC2.h"
 #include "ComposerHal.h"
 
@@ -61,8 +60,7 @@
 // ---------------------------------------------------------------------------
 
 HWComposer::HWComposer(bool useVrComposer)
-    : mAdapter(),
-      mHwcDevice(),
+    : mHwcDevice(),
       mDisplayData(2),
       mFreeDisplaySlots(),
       mHwcDisplaySlots(),
@@ -108,45 +106,7 @@
 void HWComposer::loadHwcModule(bool useVrComposer)
 {
     ALOGV("loadHwcModule");
-
-#ifdef BYPASS_IHWC
-    (void)useVrComposer; // Silence unused parameter warning.
-
-    hw_module_t const* module;
-
-    if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
-        ALOGE("%s module not found, aborting", HWC_HARDWARE_MODULE_ID);
-        abort();
-    }
-
-    hw_device_t* device = nullptr;
-    int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
-    if (error != 0) {
-        ALOGE("Failed to open HWC device (%s), aborting", strerror(-error));
-        abort();
-    }
-
-    uint32_t majorVersion = (device->version >> 24) & 0xF;
-    if (majorVersion == 2) {
-        mHwcDevice = std::make_unique<HWC2::Device>(
-                reinterpret_cast<hwc2_device_t*>(device));
-    } else {
-        mAdapter = std::make_unique<HWC2On1Adapter>(
-                reinterpret_cast<hwc_composer_device_1_t*>(device));
-        uint8_t minorVersion = mAdapter->getHwc1MinorVersion();
-        if (minorVersion < 1) {
-            ALOGE("Cannot adapt to HWC version %d.%d",
-                    static_cast<int32_t>((minorVersion >> 8) & 0xF),
-                    static_cast<int32_t>(minorVersion & 0xF));
-            abort();
-        }
-        mHwcDevice = std::make_unique<HWC2::Device>(
-                static_cast<hwc2_device_t*>(mAdapter.get()));
-    }
-#else
     mHwcDevice = std::make_unique<HWC2::Device>(useVrComposer);
-#endif
-
     mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
 }
 
@@ -870,11 +830,7 @@
 */
 
 bool HWComposer::isUsingVrComposer() const {
-#ifdef BYPASS_IHWC
-    return false;
-#else
     return getComposer()->isUsingVrComposer();
-#endif
 }
 
 void HWComposer::dump(String8& result) const {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 631af14..3eb968d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -58,7 +58,6 @@
 class Fence;
 class FloatRect;
 class GraphicBuffer;
-class HWC2On1Adapter;
 class NativeHandle;
 class Region;
 class String8;
@@ -205,7 +204,6 @@
         HWC2::Vsync vsyncEnabled;
     };
 
-    std::unique_ptr<HWC2On1Adapter> mAdapter;
     std::unique_ptr<HWC2::Device>   mHwcDevice;
     std::vector<DisplayData>        mDisplayData;
     std::set<size_t>                mFreeDisplaySlots;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
index 6b91224..a234b63 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
@@ -29,10 +29,6 @@
         const sp<GraphicBuffer>& buffer,
         uint32_t* outSlot, sp<GraphicBuffer>* outBuffer)
 {
-#ifdef BYPASS_IHWC
-    *outSlot = slot;
-    *outBuffer = buffer;
-#else
     if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0) {
         // default to slot 0
         slot = 0;
@@ -53,7 +49,6 @@
         // update cache
         mBuffers[slot] = buffer;
     }
-#endif
 }
 
 } // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 06a0765..d5498ed 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -103,7 +103,7 @@
         mLastFrameNumberReceived(0),
         mUpdateTexImageFailed(false),
         mAutoRefresh(false),
-        mFreezePositionUpdates(false)
+        mFreezeGeometryUpdates(false)
 {
 #ifdef USE_HWC2
     ALOGV("Creating Layer %s", name.string());
@@ -131,6 +131,8 @@
     mCurrentState.active.transform.set(0, 0);
     mCurrentState.crop.makeInvalid();
     mCurrentState.finalCrop.makeInvalid();
+    mCurrentState.requestedFinalCrop = mCurrentState.finalCrop;
+    mCurrentState.requestedCrop = mCurrentState.crop;
     mCurrentState.z = 0;
 #ifdef USE_HWC2
     mCurrentState.alpha = 1.0f;
@@ -296,6 +298,11 @@
     }
 
     mSurfaceFlingerConsumer->abandon();
+
+#ifdef USE_HWC2
+    clearHwcLayers();
+#endif
+
     for (const auto& child : mCurrentChildren) {
         child->onRemoved();
     }
@@ -1636,12 +1643,25 @@
         }
     }
 
-    // always set active to requested, unless we're asked not to
-    // this is used by Layer, which special cases resizes.
-    if (flags & eDontUpdateGeometryState)  {
-    } else {
+    // Here we apply various requested geometry states, depending on our
+    // latching configuration. See Layer.h for a detailed discussion of
+    // how geometry latching is controlled.
+    if (!(flags & eDontUpdateGeometryState)) {
         Layer::State& editCurrentState(getCurrentState());
-        if (mFreezePositionUpdates) {
+
+        // If mFreezeGeometryUpdates is true we are in the setGeometryAppliesWithResize
+        // mode, which causes attributes which normally latch regardless of scaling mode,
+        // to be delayed. We copy the requested state to the active state making sure
+        // to respect these rules (again see Layer.h for a detailed discussion).
+        //
+        // There is an awkward asymmetry in the handling of the crop states in the position
+        // states, as can be seen below. Largely this arises from position and transform
+        // being stored in the same data structure while having different latching rules.
+        // b/38182305
+        //
+        // Careful that "c" and editCurrentState may not begin as equivalent due to
+        // applyPendingStates in the presence of deferred transactions.
+        if (mFreezeGeometryUpdates) {
             float tx = c.active.transform.tx();
             float ty = c.active.transform.ty();
             c.active = c.requested;
@@ -1702,10 +1722,14 @@
     // we want to apply the position portion of the transform matrix immediately,
     // but still delay scaling when resizing a SCALING_MODE_FREEZE layer.
     mCurrentState.requested.transform.set(x, y);
-    if (immediate && !mFreezePositionUpdates) {
+    if (immediate && !mFreezeGeometryUpdates) {
+        // Here we directly update the active state
+        // unlike other setters, because we store it within
+        // the transform, but use different latching rules.
+        // b/38182305
         mCurrentState.active.transform.set(x, y);
     }
-    mFreezePositionUpdates = mFreezePositionUpdates || !immediate;
+    mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
 
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
@@ -1828,26 +1852,30 @@
 }
 
 bool Layer::setCrop(const Rect& crop, bool immediate) {
-    if (mCurrentState.crop == crop)
+    if (mCurrentState.requestedCrop == crop)
         return false;
     mCurrentState.sequence++;
     mCurrentState.requestedCrop = crop;
-    if (immediate) {
+    if (immediate && !mFreezeGeometryUpdates) {
         mCurrentState.crop = crop;
     }
+    mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
+
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setFinalCrop(const Rect& crop, bool immediate) {
-    if (mCurrentState.finalCrop == crop)
+    if (mCurrentState.requestedFinalCrop == crop)
         return false;
     mCurrentState.sequence++;
     mCurrentState.requestedFinalCrop = crop;
-    if (immediate) {
+    if (immediate && !mFreezeGeometryUpdates) {
         mCurrentState.finalCrop = crop;
     }
+    mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
+
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
@@ -2137,7 +2165,7 @@
     bool queuedBuffer = false;
     LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
                     getProducerStickyTransform() != 0, mName.string(),
-                    mOverrideScalingMode, mFreezePositionUpdates);
+                    mOverrideScalingMode, mFreezeGeometryUpdates);
     status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
             mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
             mLastFrameNumberReceived);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 9f45435..05c367d 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -169,25 +169,64 @@
     // the this layer's size and format
     status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
 
-    // modify current state
+    // ------------------------------------------------------------------------
+    // Geometry setting functions.
+    //
+    // The following group of functions are used to specify the layers
+    // bounds, and the mapping of the texture on to those bounds. According
+    // to various settings changes to them may apply immediately, or be delayed until
+    // a pending resize is completed by the producer submitting a buffer. For example
+    // if we were to change the buffer size, and update the matrix ahead of the
+    // new buffer arriving, then we would be stretching the buffer to a different
+    // aspect before and after the buffer arriving, which probably isn't what we wanted.
+    //
+    // The first set of geometry functions are controlled by the scaling mode, described
+    // in window.h. The scaling mode may be set by the client, as it submits buffers.
+    // This value may be overriden through SurfaceControl, with setOverrideScalingMode.
+    //
+    // Put simply, if our scaling mode is SCALING_MODE_FREEZE, then
+    // matrix updates will not be applied while a resize is pending
+    // and the size and transform will remain in their previous state
+    // until a new buffer is submitted. If the scaling mode is another value
+    // then the old-buffer will immediately be scaled to the pending size
+    // and the new matrix will be immediately applied following this scaling
+    // transformation.
 
-    // These members of state (position, crop, and finalCrop)
-    // may be updated immediately or have the update delayed
-    // until a pending surface resize completes (if applicable).
+    // Set the default buffer size for the assosciated Producer, in pixels. This is
+    // also the rendered size of the layer prior to any transformations. Parent
+    // or local matrix transformations will not affect the size of the buffer,
+    // but may affect it's on-screen size or clipping.
+    bool setSize(uint32_t w, uint32_t h);
+    // Set a 2x2 transformation matrix on the layer. This transform
+    // will be applied after parent transforms, but before any final
+    // producer specified transform.
+    bool setMatrix(const layer_state_t::matrix22_t& matrix);
+
+    // This second set of geometry attributes are controlled by
+    // setGeometryAppliesWithResize, and their default mode is to be
+    // immediate. If setGeometryAppliesWithResize is specified
+    // while a resize is pending, then update of these attributes will
+    // be delayed until the resize completes.
+
+    // setPosition operates in parent buffer space (pre parent-transform) or display
+    // space for top-level layers.
     bool setPosition(float x, float y, bool immediate);
+    // Buffer space
     bool setCrop(const Rect& crop, bool immediate);
+    // Parent buffer space/display space
     bool setFinalCrop(const Rect& crop, bool immediate);
 
+    // TODO(b/38182121): Could we eliminate the various latching modes by
+    // using the layer hierarchy?
+    // -----------------------------------------------------------------------
     bool setLayer(int32_t z);
     bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
 
-    bool setSize(uint32_t w, uint32_t h);
 #ifdef USE_HWC2
     bool setAlpha(float alpha);
 #else
     bool setAlpha(uint8_t alpha);
 #endif
-    bool setMatrix(const layer_state_t::matrix22_t& matrix);
     bool setTransparentRegionHint(const Region& transparent);
     bool setFlags(uint8_t flags, uint8_t mask);
     bool setLayerStack(uint32_t layerStack);
@@ -754,7 +793,7 @@
     bool mUpdateTexImageFailed; // This is only accessed on the main thread.
 
     bool mAutoRefresh;
-    bool mFreezePositionUpdates;
+    bool mFreezeGeometryUpdates;
 
     // Child list about to be committed/used for editing.
     LayerVector mCurrentChildren;
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index 0b302eb..6e37b45 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -37,7 +37,7 @@
     mStickyTransformSet(stickySet),
     mName(name),
     mOverrideScalingMode(overrideScalingMode),
-    mFreezePositionUpdates(freezePositionUpdates) {}
+    mFreezeGeometryUpdates(freezePositionUpdates) {}
 
 bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) {
     if (buf == NULL) {
@@ -73,6 +73,19 @@
 
             // recompute visible region
             mRecomputeVisibleRegions = true;
+
+            mFreezeGeometryUpdates = false;
+
+            if (mFront.crop != mFront.requestedCrop) {
+                mFront.crop = mFront.requestedCrop;
+                mCurrent.crop = mFront.requestedCrop;
+                mRecomputeVisibleRegions = true;
+            }
+            if (mFront.finalCrop != mFront.requestedFinalCrop) {
+                mFront.finalCrop = mFront.requestedFinalCrop;
+                mCurrent.finalCrop = mFront.requestedFinalCrop;
+                mRecomputeVisibleRegions = true;
+            }
         }
 
         ALOGD_IF(DEBUG_RESIZE,
@@ -100,6 +113,10 @@
     // conservative, but that's fine, worst case we're doing
     // a bit of extra work), we latch the new one and we
     // trigger a visible-region recompute.
+    //
+    // We latch the transparent region here, instead of above where we latch
+    // the rest of the geometry because it is only content but not necessarily
+    // resize dependent.
     if (!mFront.activeTransparentRegion.isTriviallyEqual(mFront.requestedTransparentRegion)) {
         mFront.activeTransparentRegion = mFront.requestedTransparentRegion;
 
@@ -115,18 +132,6 @@
         mRecomputeVisibleRegions = true;
     }
 
-    if (mFront.crop != mFront.requestedCrop) {
-        mFront.crop = mFront.requestedCrop;
-        mCurrent.crop = mFront.requestedCrop;
-        mRecomputeVisibleRegions = true;
-    }
-    if (mFront.finalCrop != mFront.requestedFinalCrop) {
-        mFront.finalCrop = mFront.requestedFinalCrop;
-        mCurrent.finalCrop = mFront.requestedFinalCrop;
-        mRecomputeVisibleRegions = true;
-    }
-    mFreezePositionUpdates = false;
-
     return false;
 }
 
diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h
index c2a9483..828cd8b 100644
--- a/services/surfaceflinger/LayerRejecter.h
+++ b/services/surfaceflinger/LayerRejecter.h
@@ -40,8 +40,8 @@
         bool mStickyTransformSet;
         const char *mName;
         int32_t mOverrideScalingMode;
-        bool &mFreezePositionUpdates;
+        bool &mFreezeGeometryUpdates;
     };
 }  // namespace android
 
-#endif  // ANDROID_LAYER_REJECTER_H
\ No newline at end of file
+#endif  // ANDROID_LAYER_REJECTER_H
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index d15376e..e50f3ce 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -18,6 +18,7 @@
 
 #include <sched.h>
 
+#include <android/frameworks/displayservice/1.0/IDisplayService.h>
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
 #include <cutils/sched_policy.h>
@@ -25,6 +26,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
+#include <displayservice/DisplayService.h>
 #include <hidl/LegacySupport.h>
 #include <configstore/Utils.h>
 #include "GpuService.h"
@@ -32,14 +34,9 @@
 
 using namespace android;
 
-using android::hardware::graphics::allocator::V2_0::IAllocator;
-using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
-using android::hardware::configstore::getBool;
-using android::hardware::configstore::getBool;
-
 static status_t startGraphicsAllocatorService() {
-    hardware::configureRpcThreadpool( 1 /* maxThreads */,
-            false /* callerWillJoin */);
+    using android::hardware::graphics::allocator::V2_0::IAllocator;
+
     status_t result =
         hardware::registerPassthroughServiceImplementation<IAllocator>();
     if (result != OK) {
@@ -50,12 +47,38 @@
     return OK;
 }
 
-int main(int, char**) {
+static status_t startHidlServices() {
+    using android::frameworks::displayservice::V1_0::implementation::DisplayService;
+    using android::frameworks::displayservice::V1_0::IDisplayService;
+    using android::hardware::configstore::getBool;
+    using android::hardware::configstore::getBool;
+    using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
+    hardware::configureRpcThreadpool(1 /* maxThreads */,
+            false /* callerWillJoin */);
+
+    status_t err;
+
     if (getBool<ISurfaceFlingerConfigs,
             &ISurfaceFlingerConfigs::startGraphicsAllocatorService>(false)) {
-        startGraphicsAllocatorService();
+        err = startGraphicsAllocatorService();
+        if (err != OK) {
+           return err;
+        }
     }
 
+    sp<IDisplayService> displayservice = new DisplayService();
+    err = displayservice->registerAsService();
+
+    if (err != OK) {
+        ALOGE("Could not register IDisplayService service.");
+    }
+
+    return err;
+}
+
+int main(int, char**) {
+    startHidlServices();
+
     signal(SIGPIPE, SIG_IGN);
     // When SF is launched in its own process, limit the number of
     // binder threads to 4.
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 1b17e55..68519a1 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -33,7 +33,7 @@
 
 // Fill an RGBA_8888 formatted surface with a single color.
 static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc,
-        uint8_t r, uint8_t g, uint8_t b) {
+        uint8_t r, uint8_t g, uint8_t b, bool unlock=true) {
     ANativeWindow_Buffer outBuffer;
     sp<Surface> s = sc->getSurface();
     ASSERT_TRUE(s != NULL);
@@ -48,7 +48,9 @@
             pixel[3] = 255;
         }
     }
-    ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+    if (unlock) {
+        ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+    }
 }
 
 // A ScreenCapture is a screenshot from SurfaceFlinger that can be used to check
@@ -479,6 +481,17 @@
         sc->expectFGColor(127, 127);
         sc->expectBGColor(128, 128);
     }
+
+    void lockAndFillFGBuffer() {
+        fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false);
+    }
+
+    void unlockFGBuffer() {
+        sp<Surface> s = mFGSurfaceControl->getSurface();
+        ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+        waitForPostedBuffers();
+    }
+
     void completeFGResize() {
         fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
         waitForPostedBuffers();
@@ -605,6 +618,65 @@
     EXPECT_CROPPED_STATE("after the resize finishes");
 }
 
+// In this test we ensure that setGeometryAppliesWithResize actually demands
+// a buffer of the new size, and not just any size.
+TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) {
+    EXPECT_INITIAL_STATE("before anything");
+    // Normally the crop applies immediately even while a resize is pending.
+    SurfaceComposerClient::openGlobalTransaction();
+    mFGSurfaceControl->setSize(128, 128);
+    mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)");
+
+    restoreInitialState();
+
+    // In order to prepare to submit a buffer at the wrong size, we acquire it prior to
+    // initiating the resize.
+    lockAndFillFGBuffer();
+
+    SurfaceComposerClient::openGlobalTransaction();
+    mFGSurfaceControl->setSize(128, 128);
+    mFGSurfaceControl->setGeometryAppliesWithResize();
+    mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)");
+
+    // We now submit our old buffer, at the old size, and ensure it doesn't
+    // trigger geometry latching.
+    unlockFGBuffer();
+
+    EXPECT_INITIAL_STATE("after unlocking FG buffer (with geometryAppliesWithResize)");
+
+    completeFGResize();
+
+    EXPECT_CROPPED_STATE("after the resize finishes");
+}
+
+TEST_F(CropLatchingTest, FinalCropLatchingRegressionForb37531386) {
+    EXPECT_INITIAL_STATE("before anything");
+    // In this scenario, we attempt to set the final crop a second time while the resize
+    // is still pending, and ensure we are successful. Success meaning the second crop
+    // is the one which eventually latches and not the first.
+    SurfaceComposerClient::openGlobalTransaction();
+    mFGSurfaceControl->setSize(128, 128);
+    mFGSurfaceControl->setGeometryAppliesWithResize();
+    mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    SurfaceComposerClient::openGlobalTransaction();
+    mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    EXPECT_INITIAL_STATE("after setting crops with geometryAppliesWithResize");
+
+    completeFGResize();
+
+    EXPECT_INITIAL_STATE("after the resize finishes");
+}
+
 TEST_F(LayerUpdateTest, DeferredTransactionTest) {
     sp<ScreenCapture> sc;
     {
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 0005a90..6f425f5 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -39,9 +39,6 @@
 android_namespace_t* android_get_exported_namespace(const char*);
 }
 
-// Set to true to enable exposing unratified extensions for development
-static const bool kEnableUnratifiedExtensions = false;
-
 // #define ENABLE_ALLOC_CALLSTACKS 1
 #if ENABLE_ALLOC_CALLSTACKS
 #include <utils/CallStack.h>
@@ -717,12 +714,9 @@
     loader_extensions.push_back({
         VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
         VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION});
-
-    if (kEnableUnratifiedExtensions) {
-        loader_extensions.push_back({
-            VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
-            VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
-    }
+    loader_extensions.push_back({
+        VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
+        VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
 
     static const VkExtensionProperties loader_debug_report_extension = {
         VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
@@ -818,15 +812,12 @@
         VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
         VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
 
-    if (kEnableUnratifiedExtensions) {
-        // conditionally add shared_presentable_image if supportable
-        VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
-        if (QueryPresentationProperties(physicalDevice, &presentation_properties) &&
-            presentation_properties.sharedImage) {
-            loader_extensions.push_back({
-                VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
-                        VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION});
-        }
+    VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
+    if (QueryPresentationProperties(physicalDevice, &presentation_properties) &&
+        presentation_properties.sharedImage) {
+        loader_extensions.push_back({
+            VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
+            VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION});
     }
 
     // conditionally add VK_GOOGLE_display_timing if present timestamps are
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index caa2674..e2c8c06 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1092,12 +1092,9 @@
         image_native_buffer.stride = img.buffer->stride;
         image_native_buffer.format = img.buffer->format;
         image_native_buffer.usage = img.buffer->usage;
-        // TODO: Adjust once ANativeWindowBuffer supports gralloc1-style usage.
-        // For now, this is the same translation Gralloc1On0Adapter does.
-        image_native_buffer.usage2.consumer =
-            static_cast<uint64_t>(img.buffer->usage);
-        image_native_buffer.usage2.producer =
-            static_cast<uint64_t>(img.buffer->usage);
+        android_convertGralloc0To1Usage(img.buffer->usage,
+            &image_native_buffer.usage2.producer,
+            &image_native_buffer.usage2.consumer);
 
         result =
             dispatch.CreateImage(device, &image_create, nullptr, &img.image);