Merge "Move mSurfaceFlingerConsumer into BufferLayer"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 07a6adb..1b90579 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -152,6 +152,8 @@
     { "freq",       "CPU Frequency",    0, {
         { REQ,      "events/power/cpu_frequency/enable" },
         { OPT,      "events/power/clock_set_rate/enable" },
+        { OPT,      "events/power/clock_disable/enable" },
+        { OPT,      "events/power/clock_enable/enable" },
         { OPT,      "events/power/cpu_frequency_limits/enable" },
     } },
     { "membus",     "Memory Bus Utilization", 0, {
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 380921d..b94d3d5 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -690,6 +690,7 @@
     printf("Kernel: ");
     DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
     printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
+    ds.RunCommand("UPTIME", {"uptime"}, CommandOptions::DEFAULT);
     printf("Bugreport format version: %s\n", version_.c_str());
     printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
            PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
@@ -1092,6 +1093,7 @@
     DurationReporter duration_reporter("DUMPSTATE");
 
     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
+    /* TODO: Remove duplicate uptime call when tools use it from header */
     RunCommand("UPTIME", {"uptime"});
     DumpBlockStatFiles();
     dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
diff --git a/libs/hwc2onfbadapter/Android.bp b/libs/hwc2onfbadapter/Android.bp
new file mode 100644
index 0000000..73a41f7
--- /dev/null
+++ b/libs/hwc2onfbadapter/Android.bp
@@ -0,0 +1,33 @@
+// Copyright 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+    name: "libhwc2onfbadapter",
+    vendor: true,
+
+    clang: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+
+    srcs: [
+        "HWC2OnFbAdapter.cpp",
+    ],
+
+    header_libs: ["libhardware_headers"],
+    shared_libs: ["liblog", "libsync"],
+    export_include_dirs: ["include"],
+}
diff --git a/libs/hwc2onfbadapter/HWC2OnFbAdapter.cpp b/libs/hwc2onfbadapter/HWC2OnFbAdapter.cpp
new file mode 100644
index 0000000..7c9e651
--- /dev/null
+++ b/libs/hwc2onfbadapter/HWC2OnFbAdapter.cpp
@@ -0,0 +1,887 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "HWC2OnFbAdapter"
+
+//#define LOG_NDEBUG 0
+
+#include "hwc2onfbadapter/HWC2OnFbAdapter.h"
+
+#include <algorithm>
+#include <type_traits>
+
+#include <inttypes.h>
+#include <time.h>
+#include <sys/prctl.h>
+#include <unistd.h> // for close
+
+#include <hardware/fb.h>
+#include <log/log.h>
+#include <sync/sync.h>
+
+namespace android {
+
+namespace {
+
+void dumpHook(hwc2_device_t* device, uint32_t* outSize, char* outBuffer) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (outBuffer) {
+        *outSize = adapter.getDebugString().copy(outBuffer, *outSize);
+    } else {
+        adapter.updateDebugString();
+        *outSize = adapter.getDebugString().size();
+    }
+}
+
+int32_t registerCallbackHook(hwc2_device_t* device, int32_t descriptor,
+                             hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    switch (descriptor) {
+        case HWC2_CALLBACK_HOTPLUG:
+            if (pointer) {
+                reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer)(callbackData, adapter.getDisplayId(),
+                                                            HWC2_CONNECTION_CONNECTED);
+            }
+            break;
+        case HWC2_CALLBACK_REFRESH:
+            break;
+        case HWC2_CALLBACK_VSYNC:
+            adapter.setVsyncCallback(reinterpret_cast<HWC2_PFN_VSYNC>(pointer), callbackData);
+            break;
+        default:
+            return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* /*device*/) {
+    return 0;
+}
+
+int32_t createVirtualDisplayHook(hwc2_device_t* /*device*/, uint32_t /*width*/, uint32_t /*height*/,
+                                 int32_t* /*format*/, hwc2_display_t* /*outDisplay*/) {
+    return HWC2_ERROR_NO_RESOURCES;
+}
+
+int32_t destroyVirtualDisplayHook(hwc2_device_t* /*device*/, hwc2_display_t /*display*/) {
+    return HWC2_ERROR_BAD_DISPLAY;
+}
+
+int32_t setOutputBufferHook(hwc2_device_t* /*device*/, hwc2_display_t /*display*/,
+                            buffer_handle_t /*buffer*/, int32_t /*releaseFence*/) {
+    return HWC2_ERROR_BAD_DISPLAY;
+}
+
+int32_t getDisplayNameHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outSize,
+                           char* outName) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    const auto& info = adapter.getInfo();
+    if (outName) {
+        *outSize = info.name.copy(outName, *outSize);
+    } else {
+        *outSize = info.name.size();
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayTypeHook(hwc2_device_t* device, hwc2_display_t display, int32_t* outType) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outType = HWC2_DISPLAY_TYPE_PHYSICAL;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDozeSupportHook(hwc2_device_t* device, hwc2_display_t display, int32_t* outSupport) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outSupport = 0;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getHdrCapabilitiesHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumTypes,
+                               int32_t* /*outTypes*/, float* /*outMaxLuminance*/,
+                               float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outNumTypes = 0;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setPowerModeHook(hwc2_device_t* device, hwc2_display_t display, int32_t /*mode*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    // pretend that it works
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setVsyncEnabledHook(hwc2_device_t* device, hwc2_display_t display, int32_t enabled) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    adapter.enableVsync(enabled == HWC2_VSYNC_ENABLE);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getColorModesHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumModes,
+                          int32_t* outModes) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    if (outModes) {
+        if (*outNumModes > 0) {
+            outModes[0] = HAL_COLOR_MODE_NATIVE;
+            *outNumModes = 1;
+        }
+    } else {
+        *outNumModes = 1;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setColorModeHook(hwc2_device_t* device, hwc2_display_t display, int32_t mode) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (mode != HAL_COLOR_MODE_NATIVE) {
+        return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setColorTransformHook(hwc2_device_t* device, hwc2_display_t display,
+                              const float* /*matrix*/, int32_t /*hint*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    // we always force client composition
+    adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getClientTargetSupportHook(hwc2_device_t* device, hwc2_display_t display, uint32_t width,
+                                   uint32_t height, int32_t format, int32_t dataspace) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (dataspace != HAL_DATASPACE_UNKNOWN) {
+        return HWC2_ERROR_UNSUPPORTED;
+    }
+
+    const auto& info = adapter.getInfo();
+    return (info.width == width && info.height == height && info.format == format)
+            ? HWC2_ERROR_NONE
+            : HWC2_ERROR_UNSUPPORTED;
+}
+
+int32_t setClientTargetHook(hwc2_device_t* device, hwc2_display_t display, buffer_handle_t target,
+                            int32_t acquireFence, int32_t dataspace, hwc_region_t /*damage*/) {
+    if (acquireFence >= 0) {
+        sync_wait(acquireFence, -1);
+        close(acquireFence);
+    }
+
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (dataspace != HAL_DATASPACE_UNKNOWN) {
+        return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    // no state change
+    adapter.setBuffer(target);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayConfigsHook(hwc2_device_t* device, hwc2_display_t display,
+                              uint32_t* outNumConfigs, hwc2_config_t* outConfigs) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    if (outConfigs) {
+        if (*outNumConfigs > 0) {
+            outConfigs[0] = adapter.getConfigId();
+            *outNumConfigs = 1;
+        }
+    } else {
+        *outNumConfigs = 1;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayAttributeHook(hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config,
+                                int32_t attribute, int32_t* outValue) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getConfigId() != config) {
+        return HWC2_ERROR_BAD_CONFIG;
+    }
+
+    const auto& info = adapter.getInfo();
+    switch (attribute) {
+        case HWC2_ATTRIBUTE_WIDTH:
+            *outValue = int32_t(info.width);
+            break;
+        case HWC2_ATTRIBUTE_HEIGHT:
+            *outValue = int32_t(info.height);
+            break;
+        case HWC2_ATTRIBUTE_VSYNC_PERIOD:
+            *outValue = int32_t(info.vsync_period_ns);
+            break;
+        case HWC2_ATTRIBUTE_DPI_X:
+            *outValue = int32_t(info.xdpi_scaled);
+            break;
+        case HWC2_ATTRIBUTE_DPI_Y:
+            *outValue = int32_t(info.ydpi_scaled);
+            break;
+        default:
+            return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getActiveConfigHook(hwc2_device_t* device, hwc2_display_t display,
+                            hwc2_config_t* outConfig) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outConfig = adapter.getConfigId();
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setActiveConfigHook(hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getConfigId() != config) {
+        return HWC2_ERROR_BAD_CONFIG;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t validateDisplayHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumTypes,
+                            uint32_t* outNumRequests) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    const auto& dirtyLayers = adapter.getDirtyLayers();
+    *outNumTypes = dirtyLayers.size();
+    *outNumRequests = 0;
+
+    if (*outNumTypes > 0) {
+        adapter.setState(HWC2OnFbAdapter::State::VALIDATED_WITH_CHANGES);
+        return HWC2_ERROR_HAS_CHANGES;
+    } else {
+        adapter.setState(HWC2OnFbAdapter::State::VALIDATED);
+        return HWC2_ERROR_NONE;
+    }
+}
+
+int32_t getChangedCompositionTypesHook(hwc2_device_t* device, hwc2_display_t display,
+                                       uint32_t* outNumElements, hwc2_layer_t* outLayers,
+                                       int32_t* outTypes) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+        return HWC2_ERROR_NOT_VALIDATED;
+    }
+
+    // request client composition for all layers
+    const auto& dirtyLayers = adapter.getDirtyLayers();
+    if (outLayers && outTypes) {
+        *outNumElements = std::min(*outNumElements, uint32_t(dirtyLayers.size()));
+        auto iter = dirtyLayers.cbegin();
+        for (uint32_t i = 0; i < *outNumElements; i++) {
+            outLayers[i] = *iter++;
+            outTypes[i] = HWC2_COMPOSITION_CLIENT;
+        }
+    } else {
+        *outNumElements = dirtyLayers.size();
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayRequestsHook(hwc2_device_t* device, hwc2_display_t display,
+                               int32_t* outDisplayRequests, uint32_t* outNumElements,
+                               hwc2_layer_t* /*outLayers*/, int32_t* /*outLayerRequests*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+        return HWC2_ERROR_NOT_VALIDATED;
+    }
+
+    *outDisplayRequests = 0;
+    *outNumElements = 0;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t acceptDisplayChangesHook(hwc2_device_t* device, hwc2_display_t display) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+        return HWC2_ERROR_NOT_VALIDATED;
+    }
+
+    adapter.clearDirtyLayers();
+    adapter.setState(HWC2OnFbAdapter::State::VALIDATED);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t presentDisplayHook(hwc2_device_t* device, hwc2_display_t display,
+                           int32_t* outPresentFence) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getState() != HWC2OnFbAdapter::State::VALIDATED) {
+        return HWC2_ERROR_NOT_VALIDATED;
+    }
+
+    adapter.postBuffer();
+    *outPresentFence = -1;
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getReleaseFencesHook(hwc2_device_t* device, hwc2_display_t display,
+                             uint32_t* outNumElements, hwc2_layer_t* /*outLayers*/,
+                             int32_t* /*outFences*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outNumElements = 0;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t createLayerHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t* outLayer) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outLayer = adapter.addLayer();
+    adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t destroyLayerHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    if (adapter.removeLayer(layer)) {
+        adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+        return HWC2_ERROR_NONE;
+    } else {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+}
+
+int32_t setCursorPositionHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t /*layer*/,
+                              int32_t /*x*/, int32_t /*y*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    // always an error
+    return HWC2_ERROR_BAD_LAYER;
+}
+
+int32_t setLayerBufferHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+                           buffer_handle_t /*buffer*/, int32_t acquireFence) {
+    if (acquireFence >= 0) {
+        sync_wait(acquireFence, -1);
+        close(acquireFence);
+    }
+
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (!adapter.hasLayer(layer)) {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+
+    // no state change
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setLayerSurfaceDamageHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+                                  hwc_region_t /*damage*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (!adapter.hasLayer(layer)) {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+
+    // no state change
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setLayerCompositionTypeHook(hwc2_device_t* device, hwc2_display_t display,
+                                    hwc2_layer_t layer, int32_t type) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (!adapter.markLayerDirty(layer, type != HWC2_COMPOSITION_CLIENT)) {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+
+    adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+    return HWC2_ERROR_NONE;
+}
+
+template <typename... Args>
+int32_t setLayerStateHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+                          Args... /*args*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (!adapter.hasLayer(layer)) {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+
+    adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+    return HWC2_ERROR_NONE;
+}
+
+template <typename PFN, typename T>
+static hwc2_function_pointer_t asFP(T function) {
+    static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
+    return reinterpret_cast<hwc2_function_pointer_t>(function);
+}
+
+hwc2_function_pointer_t getFunctionHook(hwc2_device_t* /*device*/, int32_t descriptor) {
+    switch (descriptor) {
+        // global functions
+        case HWC2_FUNCTION_DUMP:
+            return asFP<HWC2_PFN_DUMP>(dumpHook);
+        case HWC2_FUNCTION_REGISTER_CALLBACK:
+            return asFP<HWC2_PFN_REGISTER_CALLBACK>(registerCallbackHook);
+
+        // virtual display functions
+        case HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT:
+            return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(getMaxVirtualDisplayCountHook);
+        case HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY:
+            return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(createVirtualDisplayHook);
+        case HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY:
+            return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(destroyVirtualDisplayHook);
+        case HWC2_FUNCTION_SET_OUTPUT_BUFFER:
+            return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>(setOutputBufferHook);
+
+        // display functions
+        case HWC2_FUNCTION_GET_DISPLAY_NAME:
+            return asFP<HWC2_PFN_GET_DISPLAY_NAME>(getDisplayNameHook);
+        case HWC2_FUNCTION_GET_DISPLAY_TYPE:
+            return asFP<HWC2_PFN_GET_DISPLAY_TYPE>(getDisplayTypeHook);
+        case HWC2_FUNCTION_GET_DOZE_SUPPORT:
+            return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(getDozeSupportHook);
+        case HWC2_FUNCTION_GET_HDR_CAPABILITIES:
+            return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(getHdrCapabilitiesHook);
+        case HWC2_FUNCTION_SET_POWER_MODE:
+            return asFP<HWC2_PFN_SET_POWER_MODE>(setPowerModeHook);
+        case HWC2_FUNCTION_SET_VSYNC_ENABLED:
+            return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(setVsyncEnabledHook);
+        case HWC2_FUNCTION_GET_COLOR_MODES:
+            return asFP<HWC2_PFN_GET_COLOR_MODES>(getColorModesHook);
+        case HWC2_FUNCTION_SET_COLOR_MODE:
+            return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook);
+        case HWC2_FUNCTION_SET_COLOR_TRANSFORM:
+            return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook);
+        case HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT:
+            return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(getClientTargetSupportHook);
+        case HWC2_FUNCTION_SET_CLIENT_TARGET:
+            return asFP<HWC2_PFN_SET_CLIENT_TARGET>(setClientTargetHook);
+
+        // config functions
+        case HWC2_FUNCTION_GET_DISPLAY_CONFIGS:
+            return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(getDisplayConfigsHook);
+        case HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE:
+            return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(getDisplayAttributeHook);
+        case HWC2_FUNCTION_GET_ACTIVE_CONFIG:
+            return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>(getActiveConfigHook);
+        case HWC2_FUNCTION_SET_ACTIVE_CONFIG:
+            return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>(setActiveConfigHook);
+
+        // validate/present functions
+        case HWC2_FUNCTION_VALIDATE_DISPLAY:
+            return asFP<HWC2_PFN_VALIDATE_DISPLAY>(validateDisplayHook);
+        case HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES:
+            return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(getChangedCompositionTypesHook);
+        case HWC2_FUNCTION_GET_DISPLAY_REQUESTS:
+            return asFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(getDisplayRequestsHook);
+        case HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES:
+            return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(acceptDisplayChangesHook);
+        case HWC2_FUNCTION_PRESENT_DISPLAY:
+            return asFP<HWC2_PFN_PRESENT_DISPLAY>(presentDisplayHook);
+        case HWC2_FUNCTION_GET_RELEASE_FENCES:
+            return asFP<HWC2_PFN_GET_RELEASE_FENCES>(getReleaseFencesHook);
+
+        // layer create/destroy
+        case HWC2_FUNCTION_CREATE_LAYER:
+            return asFP<HWC2_PFN_CREATE_LAYER>(createLayerHook);
+        case HWC2_FUNCTION_DESTROY_LAYER:
+            return asFP<HWC2_PFN_DESTROY_LAYER>(destroyLayerHook);
+
+        // layer functions; validateDisplay not required
+        case HWC2_FUNCTION_SET_CURSOR_POSITION:
+            return asFP<HWC2_PFN_SET_CURSOR_POSITION>(setCursorPositionHook);
+        case HWC2_FUNCTION_SET_LAYER_BUFFER:
+            return asFP<HWC2_PFN_SET_LAYER_BUFFER>(setLayerBufferHook);
+        case HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE:
+            return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(setLayerSurfaceDamageHook);
+
+        // layer state functions; validateDisplay required
+        case HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE:
+            return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(setLayerCompositionTypeHook);
+        case HWC2_FUNCTION_SET_LAYER_BLEND_MODE:
+            return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(setLayerStateHook<int32_t>);
+        case HWC2_FUNCTION_SET_LAYER_COLOR:
+            return asFP<HWC2_PFN_SET_LAYER_COLOR>(setLayerStateHook<hwc_color_t>);
+        case HWC2_FUNCTION_SET_LAYER_DATASPACE:
+            return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(setLayerStateHook<int32_t>);
+        case HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME:
+            return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(setLayerStateHook<hwc_rect_t>);
+        case HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA:
+            return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(setLayerStateHook<float>);
+        case HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM:
+            return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(setLayerStateHook<buffer_handle_t>);
+        case HWC2_FUNCTION_SET_LAYER_SOURCE_CROP:
+            return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(setLayerStateHook<hwc_frect_t>);
+        case HWC2_FUNCTION_SET_LAYER_TRANSFORM:
+            return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(setLayerStateHook<int32_t>);
+        case HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION:
+            return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(setLayerStateHook<hwc_region_t>);
+        case HWC2_FUNCTION_SET_LAYER_Z_ORDER:
+            return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(setLayerStateHook<uint32_t>);
+
+        default:
+            ALOGE("unknown function descriptor %d", descriptor);
+            return nullptr;
+    }
+}
+
+void getCapabilitiesHook(hwc2_device_t* /*device*/, uint32_t* outCount,
+                         int32_t* /*outCapabilities*/) {
+    *outCount = 0;
+}
+
+int closeHook(hw_device_t* device) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    adapter.close();
+    return 0;
+}
+
+} // anonymous namespace
+
+HWC2OnFbAdapter::HWC2OnFbAdapter(framebuffer_device_t* fbDevice)
+      : hwc2_device_t(), mFbDevice(fbDevice) {
+    common.close = closeHook;
+    hwc2_device::getCapabilities = getCapabilitiesHook;
+    hwc2_device::getFunction = getFunctionHook;
+
+    mFbInfo.name = "fbdev";
+    mFbInfo.width = mFbDevice->width;
+    mFbInfo.height = mFbDevice->height;
+    mFbInfo.format = mFbDevice->format;
+    mFbInfo.vsync_period_ns = int(1e9 / mFbDevice->fps);
+    mFbInfo.xdpi_scaled = int(mFbDevice->xdpi * 1000.0f);
+    mFbInfo.ydpi_scaled = int(mFbDevice->ydpi * 1000.0f);
+
+    mVsyncThread.start(0, mFbInfo.vsync_period_ns);
+}
+
+HWC2OnFbAdapter& HWC2OnFbAdapter::cast(hw_device_t* device) {
+    return *reinterpret_cast<HWC2OnFbAdapter*>(device);
+}
+
+HWC2OnFbAdapter& HWC2OnFbAdapter::cast(hwc2_device_t* device) {
+    return *reinterpret_cast<HWC2OnFbAdapter*>(device);
+}
+
+hwc2_display_t HWC2OnFbAdapter::getDisplayId() {
+    return 0;
+}
+
+hwc2_config_t HWC2OnFbAdapter::getConfigId() {
+    return 0;
+}
+
+void HWC2OnFbAdapter::close() {
+    mVsyncThread.stop();
+    framebuffer_close(mFbDevice);
+}
+
+const HWC2OnFbAdapter::Info& HWC2OnFbAdapter::getInfo() const {
+    return mFbInfo;
+}
+
+void HWC2OnFbAdapter::updateDebugString() {
+    if (mFbDevice->common.version >= 1 && mFbDevice->dump) {
+        char buffer[4096];
+        mFbDevice->dump(mFbDevice, buffer, sizeof(buffer));
+        buffer[sizeof(buffer) - 1] = '\0';
+
+        mDebugString = buffer;
+    }
+}
+
+const std::string& HWC2OnFbAdapter::getDebugString() const {
+    return mDebugString;
+}
+
+void HWC2OnFbAdapter::setState(State state) {
+    mState = state;
+}
+
+HWC2OnFbAdapter::State HWC2OnFbAdapter::getState() const {
+    return mState;
+}
+
+hwc2_layer_t HWC2OnFbAdapter::addLayer() {
+    hwc2_layer_t id = ++mNextLayerId;
+
+    mLayers.insert(id);
+    mDirtyLayers.insert(id);
+
+    return id;
+}
+
+bool HWC2OnFbAdapter::removeLayer(hwc2_layer_t layer) {
+    mDirtyLayers.erase(layer);
+    return mLayers.erase(layer);
+}
+
+bool HWC2OnFbAdapter::hasLayer(hwc2_layer_t layer) const {
+    return mLayers.count(layer) > 0;
+}
+
+bool HWC2OnFbAdapter::markLayerDirty(hwc2_layer_t layer, bool dirty) {
+    if (mLayers.count(layer) == 0) {
+        return false;
+    }
+
+    if (dirty) {
+        mDirtyLayers.insert(layer);
+    } else {
+        mDirtyLayers.erase(layer);
+    }
+
+    return true;
+}
+
+const std::unordered_set<hwc2_layer_t>& HWC2OnFbAdapter::getDirtyLayers() const {
+    return mDirtyLayers;
+}
+
+void HWC2OnFbAdapter::clearDirtyLayers() {
+    mDirtyLayers.clear();
+}
+
+/*
+ * For each frame, SurfaceFlinger
+ *
+ *  - peforms GLES composition
+ *  - calls eglSwapBuffers
+ *  - calls setClientTarget, which maps to setBuffer below
+ *  - calls presentDisplay, which maps to postBuffer below
+ *
+ * setBuffer should be a good place to call compositionComplete.
+ *
+ * As for post, it
+ *
+ *  - schedules the buffer for presentation on the next vsync
+ *  - locks the buffer and blocks all other users trying to lock it
+ *
+ * It does not give us a way to return a present fence, and we need to live
+ * with that.  The implication is that, when we are double-buffered,
+ * SurfaceFlinger assumes the front buffer is available for rendering again
+ * immediately after the back buffer is posted.  The locking semantics
+ * hopefully are strong enough that the rendering will be blocked.
+ */
+void HWC2OnFbAdapter::setBuffer(buffer_handle_t buffer) {
+    if (mFbDevice->compositionComplete) {
+        mFbDevice->compositionComplete(mFbDevice);
+    }
+    mBuffer = buffer;
+}
+
+bool HWC2OnFbAdapter::postBuffer() {
+    int error = 0;
+    if (mBuffer) {
+        error = mFbDevice->post(mFbDevice, mBuffer);
+    }
+
+    return error == 0;
+}
+
+void HWC2OnFbAdapter::setVsyncCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data) {
+    mVsyncThread.setCallback(callback, data);
+}
+
+void HWC2OnFbAdapter::enableVsync(bool enable) {
+    mVsyncThread.enableCallback(enable);
+}
+
+int64_t HWC2OnFbAdapter::VsyncThread::now() {
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+
+    return int64_t(ts.tv_sec) * 1'000'000'000 + ts.tv_nsec;
+}
+
+bool HWC2OnFbAdapter::VsyncThread::sleepUntil(int64_t t) {
+    struct timespec ts;
+    ts.tv_sec = t / 1'000'000'000;
+    ts.tv_nsec = t % 1'000'000'000;
+
+    while (true) {
+        int error = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, nullptr);
+        if (error) {
+            if (error == EINTR) {
+                continue;
+            }
+            return false;
+        } else {
+            return true;
+        }
+    }
+}
+
+void HWC2OnFbAdapter::VsyncThread::start(int64_t firstVsync, int64_t period) {
+    mNextVsync = firstVsync;
+    mPeriod = period;
+    mStarted = true;
+    mThread = std::thread(&VsyncThread::vsyncLoop, this);
+}
+
+void HWC2OnFbAdapter::VsyncThread::stop() {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mStarted = false;
+    }
+    mCondition.notify_all();
+    mThread.join();
+}
+
+void HWC2OnFbAdapter::VsyncThread::setCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mCallback = callback;
+    mCallbackData = data;
+}
+
+void HWC2OnFbAdapter::VsyncThread::enableCallback(bool enable) {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mCallbackEnabled = enable;
+    }
+    mCondition.notify_all();
+}
+
+void HWC2OnFbAdapter::VsyncThread::vsyncLoop() {
+    prctl(PR_SET_NAME, "VsyncThread", 0, 0, 0);
+
+    std::unique_lock<std::mutex> lock(mMutex);
+    if (!mStarted) {
+        return;
+    }
+
+    while (true) {
+        if (!mCallbackEnabled) {
+            mCondition.wait(lock, [this] { return mCallbackEnabled || !mStarted; });
+            if (!mStarted) {
+                break;
+            }
+        }
+
+        lock.unlock();
+
+        // adjust mNextVsync if necessary
+        int64_t t = now();
+        if (mNextVsync < t) {
+            int64_t n = (t - mNextVsync + mPeriod - 1) / mPeriod;
+            mNextVsync += mPeriod * n;
+        }
+        bool fire = sleepUntil(mNextVsync);
+
+        lock.lock();
+
+        if (fire) {
+            ALOGV("VsyncThread(%" PRId64 ")", mNextVsync);
+            if (mCallback) {
+                mCallback(mCallbackData, getDisplayId(), mNextVsync);
+            }
+            mNextVsync += mPeriod;
+        }
+    }
+}
+
+} // namespace android
diff --git a/libs/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h b/libs/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h
new file mode 100644
index 0000000..d6272fd
--- /dev/null
+++ b/libs/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_SF_HWC2_ON_FB_ADAPTER_H
+#define ANDROID_SF_HWC2_ON_FB_ADAPTER_H
+
+#include <condition_variable>
+#include <mutex>
+#include <string>
+#include <thread>
+#include <unordered_set>
+
+#include <hardware/hwcomposer2.h>
+
+struct framebuffer_device_t;
+
+namespace android {
+
+class HWC2OnFbAdapter : public hwc2_device_t {
+public:
+    HWC2OnFbAdapter(framebuffer_device_t* fbDevice);
+
+    static HWC2OnFbAdapter& cast(hw_device_t* device);
+    static HWC2OnFbAdapter& cast(hwc2_device_t* device);
+
+    static hwc2_display_t getDisplayId();
+    static hwc2_config_t getConfigId();
+
+    void close();
+
+    struct Info {
+        std::string name;
+        uint32_t width;
+        uint32_t height;
+        int format;
+        int vsync_period_ns;
+        int xdpi_scaled;
+        int ydpi_scaled;
+    };
+    const Info& getInfo() const;
+
+    void updateDebugString();
+    const std::string& getDebugString() const;
+
+    enum class State {
+        MODIFIED,
+        VALIDATED_WITH_CHANGES,
+        VALIDATED,
+    };
+    void setState(State state);
+    State getState() const;
+
+    hwc2_layer_t addLayer();
+    bool removeLayer(hwc2_layer_t layer);
+    bool hasLayer(hwc2_layer_t layer) const;
+    bool markLayerDirty(hwc2_layer_t layer, bool dirty);
+    const std::unordered_set<hwc2_layer_t>& getDirtyLayers() const;
+    void clearDirtyLayers();
+
+    void setBuffer(buffer_handle_t buffer);
+    bool postBuffer();
+
+    void setVsyncCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data);
+    void enableVsync(bool enable);
+
+private:
+    framebuffer_device_t* mFbDevice{nullptr};
+    Info mFbInfo{};
+
+    std::string mDebugString;
+
+    State mState{State::MODIFIED};
+
+    uint64_t mNextLayerId{0};
+    std::unordered_set<hwc2_layer_t> mLayers;
+    std::unordered_set<hwc2_layer_t> mDirtyLayers;
+
+    buffer_handle_t mBuffer{nullptr};
+
+    class VsyncThread {
+    public:
+        static int64_t now();
+        static bool sleepUntil(int64_t t);
+
+        void start(int64_t first, int64_t period);
+        void stop();
+        void setCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data);
+        void enableCallback(bool enable);
+
+    private:
+        void vsyncLoop();
+        bool waitUntilNextVsync();
+
+        std::thread mThread;
+        int64_t mNextVsync{0};
+        int64_t mPeriod{0};
+
+        std::mutex mMutex;
+        std::condition_variable mCondition;
+        bool mStarted{false};
+        HWC2_PFN_VSYNC mCallback{nullptr};
+        hwc2_callback_data_t mCallbackData{nullptr};
+        bool mCallbackEnabled{false};
+    };
+    VsyncThread mVsyncThread;
+};
+
+} // namespace android
+
+#endif // ANDROID_SF_HWC2_ON_FB_ADAPTER_H
diff --git a/libs/vr/libdvr/include/dvr/dvr_display_types.h b/libs/vr/libdvr/include/dvr/dvr_display_types.h
index 25364d8..fd69843 100644
--- a/libs/vr/libdvr/include/dvr/dvr_display_types.h
+++ b/libs/vr/libdvr/include/dvr/dvr_display_types.h
@@ -13,7 +13,7 @@
 #ifndef __FLOAT32X4T_86
 #define __FLOAT32X4T_86
 typedef float float32x4_t __attribute__((__vector_size__(16)));
-typedef struct float32x4x4_t { float32x4_t val[4]; };
+typedef struct float32x4x4_t { float32x4_t val[4]; } float32x4x4_t;
 #endif
 #endif
 
diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp
index 452c8c6..330861d 100644
--- a/services/sensorservice/BatteryService.cpp
+++ b/services/sensorservice/BatteryService.cpp
@@ -78,12 +78,13 @@
     if (checkService()) {
         Mutex::Autolock _l(mActivationsLock);
         int64_t identity = IPCThreadState::self()->clearCallingIdentity();
-        for (size_t i=0 ; i<mActivations.size() ; i++) {
+        for (size_t i=0 ; i<mActivations.size() ; ) {
             const Info& info(mActivations[i]);
             if (info.uid == uid) {
                 mBatteryStatService->noteStopSensor(info.uid, info.handle);
                 mActivations.removeAt(i);
-                i--;
+            } else {
+              i++;
             }
         }
         IPCThreadState::self()->restoreCallingIdentity(identity);
@@ -105,4 +106,3 @@
 
 // ---------------------------------------------------------------------------
 }; // namespace android
-
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 9201520..e92b8d8 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -44,6 +44,13 @@
 
   cflags: [
     "-DLOG_TAG=\"vr_hwc\"",
+    "-Wall",
+    "-Werror",
+    // mVrClient unused in vr_composer_client.cpp
+    "-Wno-error=unused-private-field",
+    // Warnings in vr_hwc.cpp to be fixed after sync of goog/master.
+    "-Wno-sign-compare",
+    "-Wno-unused-parameter",
   ],
 
 }
@@ -63,6 +70,11 @@
   },
   export_include_dirs: ["aidl"],
 
+  cflags: [
+    "-Wall",
+    "-Werror",
+  ],
+
   shared_libs: [
     "libbinder",
     "libui",
@@ -92,6 +104,8 @@
   ],
   cflags: [
     "-DLOG_TAG=\"vr_hwc\"",
+    "-Wall",
+    "-Werror",
   ],
 }
 
@@ -120,6 +134,8 @@
   ],
   cflags: [
     "-DLOG_TAG=\"vr_hwc\"",
+    "-Wall",
+    "-Werror",
   ],
   init_rc: [
     "vr_hwc.rc",
@@ -137,6 +153,13 @@
     // symbols in the *-binder library get optimized out.
     "libvr_hwc-binder",
   ],
+  cflags: [
+    "-Wall",
+    "-Werror",
+    // warnings in vr_composer_test.cpp to be fixed after merge of goog/master
+    "-Wno-sign-compare",
+    "-Wno-unused-parameter",
+  ],
   shared_libs: [
     "libbase",
     "libbinder",
diff --git a/services/vr/performanced/Android.mk b/services/vr/performanced/Android.mk
index dbc66f1..1470234 100644
--- a/services/vr/performanced/Android.mk
+++ b/services/vr/performanced/Android.mk
@@ -36,6 +36,7 @@
 LOCAL_SRC_FILES := $(sourceFiles)
 LOCAL_CFLAGS := -DLOG_TAG=\"performanced\"
 LOCAL_CFLAGS += -DTRACE=0
+LOCAL_CFLAGS += -Wall -Werror
 LOCAL_STATIC_LIBRARIES := $(staticLibraries)
 LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
 LOCAL_MODULE := performanced
diff --git a/services/vr/performanced/directory_reader.h b/services/vr/performanced/directory_reader.h
index 7d7ecc5..b9d27c3 100644
--- a/services/vr/performanced/directory_reader.h
+++ b/services/vr/performanced/directory_reader.h
@@ -19,7 +19,7 @@
     directory_ = fdopendir(directory_fd.get());
     error_ = errno;
     if (directory_ != nullptr)
-      directory_fd.release();
+      (void) directory_fd.release(); // ignore return result?
   }
 
   ~DirectoryReader() {
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
index 6b11ce3..7196b2b 100644
--- a/services/vr/virtual_touchpad/Android.bp
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -23,7 +23,11 @@
     shared_libs: shared_libs,
     header_libs: header_libraries,
     cppflags: ["-std=c++11"],
-    cflags: ["-DLOG_TAG=\"VrVirtualTouchpad\""],
+    cflags: [
+        "-DLOG_TAG=\"VrVirtualTouchpad\"",
+        "-Wall",
+        "-Werror",
+    ],
     name: "libvirtualtouchpad",
     tags: ["optional"],
 }
@@ -44,6 +48,10 @@
     srcs: test_src_files,
     static_libs: test_static_libs,
     header_libs: header_libraries,
+    cflags = [
+        "-Wall",
+        "-Werror",
+    ],
     cppflags = [
         "-std=c++11",
     ],
@@ -83,6 +91,8 @@
     cppflags: ["-std=c++11"],
     cflags: [
         "-DLOG_TAG=\"VrVirtualTouchpad\"",
+        "-Wall",
+        "-Werror",
     ],
     host_ldlibs: ["-llog"],
     name: "virtual_touchpad",
@@ -112,7 +122,11 @@
     shared_libs: client_shared_libs,
     header_libs: header_libraries,
     cppflags: ["-std=c++11"],
-    cflags: ["-DLOG_TAG=\"VirtualTouchpadClient\""],
+    cflags: [
+        "-DLOG_TAG=\"VirtualTouchpadClient\"",
+        "-Wall",
+        "-Werror",
+    ],
     host_ldlibs: ["-llog"],
     name: "libvirtualtouchpadclient",
     tags: ["optional"],
diff --git a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
index b19b018..198ed06 100644
--- a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
+++ b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
@@ -110,17 +110,6 @@
   EvdevInjectorForTesting injector[kTouchpads];
 };
 
-void DumpDifference(const char* expect, const char* actual) {
-  printf("  common: ");
-  while (*expect && *expect == *actual) {
-    putchar(*expect);
-    ++expect;
-    ++actual;
-  }
-  printf("\n  expect: %s\n", expect);
-  printf("  actual: %s\n", actual);
-}
-
 }  // anonymous namespace
 
 class VirtualTouchpadTest : public testing::Test {};
@@ -153,7 +142,6 @@
   }
   const int32_t width = 1 + uidev->absmax[ABS_MT_POSITION_X];
   const int32_t height = 1 + uidev->absmax[ABS_MT_POSITION_Y];
-  const int32_t slots = uidev->absmax[ABS_MT_SLOT];
 
   for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
     SCOPED_TRACE(t);