hwc2: dump
am: 9031c5046d

Change-Id: Iabaeed79162683c013d0b62e237afc2292cebfb3
diff --git a/hwc2/hwc2.cpp b/hwc2/hwc2.cpp
index 838cf78..53b191c 100644
--- a/hwc2/hwc2.cpp
+++ b/hwc2/hwc2.cpp
@@ -56,10 +56,10 @@
     return dev->destroy_virtual_display(display);
 }
 
-void dump(hwc2_device_t* /*device*/, uint32_t* /*out_size*/,
-        char* /*out_buffer*/)
+void dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer)
 {
-    return;
+    hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
+    dev->dump_hwc2(out_size, out_buffer);
 }
 
 uint32_t get_max_virtual_display_count(hwc2_device_t *device)
diff --git a/hwc2/hwc2.h b/hwc2/hwc2.h
index af5902a..2fe383d 100644
--- a/hwc2/hwc2.h
+++ b/hwc2/hwc2.h
@@ -17,13 +17,19 @@
 #ifndef _HWC2_H
 #define _HWC2_H
 
-#include <android-base/unique_fd.h>
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
 #include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include <android-base/unique_fd.h>
 
 #include <unordered_map>
 #include <queue>
 #include <array>
 #include <vector>
+#include <string>
 #include <mutex>
 #include <string>
 
@@ -133,6 +139,8 @@
     hwc2_buffer();
     ~hwc2_buffer();
 
+    std::string dump() const;
+
     hwc2_error_t decompress();
     hwc2_error_t get_adf_post_props(struct tegra_adf_flip_windowattr *win_attr,
                     struct adf_buffer_config *adf_buf, size_t win_idx,
@@ -231,6 +239,8 @@
 public:
     hwc2_config();
 
+    std::string dump() const;
+
     int set_attribute(hwc2_attribute_t attribute, int32_t value);
     int32_t get_attribute(hwc2_attribute_t attribute) const;
 
@@ -280,6 +290,8 @@
 public:
     hwc2_layer(hwc2_layer_t id);
 
+    std::string dump() const;
+
     hwc2_error_t decompress_buffer();
 
     hwc2_error_t get_adf_post_props(struct tegra_adf_flip_windowattr *win_attr,
@@ -396,6 +408,8 @@
                 hwc2_display_type_t type, hwc2_power_mode_t power_mode);
     ~hwc2_display();
 
+    std::string dump() const;
+
     /* Display functions */
     hwc2_display_t      get_id() const { return id; }
     hwc2_display_type_t get_type() const { return type; }
@@ -584,14 +598,17 @@
     hwc2_dev();
     ~hwc2_dev();
 
+    std::string dump() const;
+    void dump_hwc2(uint32_t *out_size, char *out_buffer);
+
     /* Display functions */
     hwc2_error_t get_display_name(hwc2_display_t dpy_id, uint32_t *out_size,
-                    char *out_name) const;
+                    char *out_name);
     hwc2_error_t get_display_type(hwc2_display_t dpy_id,
-                    hwc2_display_type_t *out_type) const;
+                    hwc2_display_type_t *out_type);
 
     /* Virtual display functions */
-    uint32_t     get_max_virtual_display_count() const;
+    uint32_t     get_max_virtual_display_count();
     hwc2_error_t create_virtual_display(uint32_t width, uint32_t height,
                     android_pixel_format_t *format,
                     hwc2_display_t *out_display);
@@ -601,45 +618,44 @@
 
     /* Power modes */
     hwc2_error_t set_power_mode(hwc2_display_t dpy_id, hwc2_power_mode_t mode);
-    hwc2_error_t get_doze_support(hwc2_display_t dpy_id, int32_t *out_support)
-                    const;
+    hwc2_error_t get_doze_support(hwc2_display_t dpy_id, int32_t *out_support);
 
     /* Display present functions */
     hwc2_error_t validate_display(hwc2_display_t dpy_id,
                     uint32_t *out_num_types, uint32_t *out_num_requests);
     hwc2_error_t get_changed_composition_types(hwc2_display_t dpy_id,
                     uint32_t *out_num_elements, hwc2_layer_t *out_layers,
-                    hwc2_composition_t *out_types) const;
+                    hwc2_composition_t *out_types);
     hwc2_error_t get_display_requests(hwc2_display_t dpy_id,
                     hwc2_display_request_t *out_display_requests,
                     uint32_t *out_num_elements, hwc2_layer_t *out_layers,
-                    hwc2_layer_request_t *out_layer_requests) const;
+                    hwc2_layer_request_t *out_layer_requests);
     hwc2_error_t accept_display_changes(hwc2_display_t dpy_id);
     hwc2_error_t present_display(hwc2_display_t dpy_id,
                     int32_t *out_present_fence);
     hwc2_error_t get_release_fences(hwc2_display_t dpy_id,
                     uint32_t *out_num_elements, hwc2_layer_t *out_layers,
-                    int32_t *out_fences) const;
+                    int32_t *out_fences);
 
     /* Config functions */
     hwc2_error_t get_display_attribute(hwc2_display_t dpy_id,
                     hwc2_config_t config, hwc2_attribute_t attribute,
-                    int32_t *out_value) const;
+                    int32_t *out_value);
     hwc2_error_t get_display_configs(hwc2_display_t dpy_id,
-                    uint32_t *out_num_configs, hwc2_config_t *out_configs) const;
+                    uint32_t *out_num_configs, hwc2_config_t *out_configs);
     hwc2_error_t get_active_config(hwc2_display_t dpy_id,
-                    hwc2_config_t *out_config) const;
+                    hwc2_config_t *out_config);
     hwc2_error_t set_active_config(hwc2_display_t dpy_id, hwc2_config_t config);
 
     /* Color/hdr functions */
     hwc2_error_t get_color_modes(hwc2_display_t dpy_id, uint32_t *out_num_modes,
-                    android_color_mode_t *out_modes) const;
+                    android_color_mode_t *out_modes);
     hwc2_error_t set_color_mode(hwc2_display_t dpy_id,
                     android_color_mode_t mode);
     hwc2_error_t get_hdr_capabilities(hwc2_display_t dpy_id,
                     uint32_t *out_num_types, android_hdr_t *out_types,
                     float *out_max_luminance, float *out_max_average_luminance,
-                    float *out_min_luminance) const;
+                    float *out_min_luminance);
     hwc2_error_t set_color_transform(hwc2_display_t dpy_id,
                     const float *color_matrix,
                     android_color_transform_t color_hint);
@@ -707,6 +723,9 @@
     /* The physical and virtual displays associated with this device */
     std::unordered_map<hwc2_display_t, hwc2_display> displays;
 
+    /* String containing the dump output between calls */
+    std::string dump_str;
+
     /* The associated adf hardware composer helper */
     struct adf_hwc_helper *adf_helper;
 
diff --git a/hwc2/hwc2_buffer.cpp b/hwc2/hwc2_buffer.cpp
index 1af83ee..8ed16af 100644
--- a/hwc2/hwc2_buffer.cpp
+++ b/hwc2/hwc2_buffer.cpp
@@ -19,6 +19,7 @@
 #include <tegrafb.h>
 #include <tegra_adf.h>
 #include <android-base/macros.h>
+#include <sstream>
 
 #include "hwc2.h"
 
@@ -72,6 +73,29 @@
     close_acquire_fence();
 }
 
+std::string hwc2_buffer::dump() const
+{
+    std::stringstream dmp;
+
+    dmp << "    Buffer: " << std::hex << handle << "/" << std::dec
+            << acquire_fence << "    Z: " << z_order << "\n";
+    dmp << "    Display Frame: [" << display_frame.left << ", "
+            << display_frame.top << ", " << display_frame.right << ", "
+            << display_frame.bottom << "]\n";
+    dmp << "    Source Crop: [" << source_crop.left << ", "
+            << source_crop.top << ", " << source_crop.right << ", "
+            << source_crop.bottom << "]\n";
+    dmp << "    Transform: " << getTransformName(transform)
+            << "    Blend Mode: " << getBlendModeName(blend_mode);
+
+    if (plane_alpha != 1.0f)
+        dmp << "    Alpha: " << plane_alpha;
+
+    dmp << "\n";
+
+    return dmp.str();
+}
+
 hwc2_error_t hwc2_buffer::decompress()
 {
     int ret = hwc2_gralloc::get_instance().decompress(handle, acquire_fence,
diff --git a/hwc2/hwc2_config.cpp b/hwc2/hwc2_config.cpp
index 3801a62..cf84477 100644
--- a/hwc2/hwc2_config.cpp
+++ b/hwc2/hwc2_config.cpp
@@ -16,6 +16,9 @@
 
 #include <cutils/log.h>
 
+#include <iomanip>
+#include <sstream>
+
 #include "hwc2.h"
 
 hwc2_config::hwc2_config()
@@ -25,6 +28,22 @@
       dpi_x(-1),
       dpi_y(-1) { }
 
+std::string hwc2_config::dump() const
+{
+    std::stringstream dmp;
+
+    dmp << std::fixed << std::setprecision(1);
+
+    dmp << "    Resolution: " << width << " x " << height;
+
+    if (vsync_period != 0)
+        dmp << " @ " << 1e9 / vsync_period << " Hz";
+
+    dmp << "\n    DPI: " << dpi_x / 1000.0f << " x " << dpi_y / 1000.0f << "\n";
+
+    return dmp.str();
+}
+
 int hwc2_config::set_attribute(hwc2_attribute_t attribute, int32_t value)
 {
     switch (attribute) {
diff --git a/hwc2/hwc2_dev.cpp b/hwc2/hwc2_dev.cpp
index 60af4cf..adffecf 100644
--- a/hwc2/hwc2_dev.cpp
+++ b/hwc2/hwc2_dev.cpp
@@ -17,6 +17,8 @@
 #include <fcntl.h>
 #include <cutils/log.h>
 #include <inttypes.h>
+
+#include <sstream>
 #include <cstdlib>
 #include <vector>
 
@@ -52,6 +54,7 @@
     : state_mutex(),
       callback_handler(),
       displays(),
+      dump_str(),
       adf_helper(nullptr) { }
 
 hwc2_dev::~hwc2_dev()
@@ -61,9 +64,38 @@
     hwc2_display::reset_ids();
 }
 
-hwc2_error_t hwc2_dev::get_display_name(hwc2_display_t dpy_id, uint32_t *out_size,
-        char *out_name) const
+std::string hwc2_dev::dump() const
 {
+    std::stringstream dmp;
+
+    dmp << "NVIDIA HWC2:\n";
+    for (auto &dpy: displays)
+        dmp << dpy.second.dump() << "\n";
+
+    return dmp.str();
+}
+
+void hwc2_dev::dump_hwc2(uint32_t *out_size, char *out_buffer)
+{
+    std::lock_guard<std::mutex> guard(state_mutex);
+
+    if (!out_buffer) {
+        dump_str.clear();
+        dump_str.append(dump());
+        *out_size = dump_str.length();
+        return;
+    }
+
+    *out_size = (*out_size > dump_str.length())? dump_str.length(): *out_size;
+    dump_str.copy(out_buffer, *out_size);
+    dump_str.clear();
+}
+
+hwc2_error_t hwc2_dev::get_display_name(hwc2_display_t dpy_id, uint32_t *out_size,
+        char *out_name)
+{
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -74,8 +106,10 @@
 }
 
 hwc2_error_t hwc2_dev::get_display_type(hwc2_display_t dpy_id,
-        hwc2_display_type_t *out_type) const
+        hwc2_display_type_t *out_type)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -86,7 +120,7 @@
     return HWC2_ERROR_NONE;
 }
 
-uint32_t hwc2_dev::get_max_virtual_display_count() const
+uint32_t hwc2_dev::get_max_virtual_display_count()
 {
     return 0;
 }
@@ -130,8 +164,10 @@
 }
 
 hwc2_error_t hwc2_dev::get_doze_support(hwc2_display_t dpy_id,
-        int32_t *out_support) const
+        int32_t *out_support)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -144,6 +180,8 @@
 hwc2_error_t hwc2_dev::validate_display(hwc2_display_t dpy_id,
         uint32_t *out_num_types, uint32_t *out_num_requests)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -155,8 +193,10 @@
 
 hwc2_error_t hwc2_dev::get_changed_composition_types(hwc2_display_t dpy_id,
         uint32_t *out_num_elements, hwc2_layer_t *out_layers,
-        hwc2_composition_t *out_types) const
+        hwc2_composition_t *out_types)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -170,8 +210,10 @@
 hwc2_error_t hwc2_dev::get_display_requests(hwc2_display_t dpy_id,
         hwc2_display_request_t *out_display_requests,
         uint32_t *out_num_elements, hwc2_layer_t *out_layers,
-        hwc2_layer_request_t *out_layer_requests) const
+        hwc2_layer_request_t *out_layer_requests)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -184,6 +226,8 @@
 
 hwc2_error_t hwc2_dev::accept_display_changes(hwc2_display_t dpy_id)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -209,8 +253,10 @@
 
 hwc2_error_t hwc2_dev::get_release_fences(hwc2_display_t dpy_id,
         uint32_t *out_num_elements, hwc2_layer_t *out_layers,
-        int32_t *out_fences) const
+        int32_t *out_fences)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -223,8 +269,9 @@
 
 hwc2_error_t hwc2_dev::get_display_attribute(hwc2_display_t dpy_id,
         hwc2_config_t config, hwc2_attribute_t attribute, int32_t *out_value)
-        const
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -235,8 +282,10 @@
 }
 
 hwc2_error_t hwc2_dev::get_display_configs(hwc2_display_t dpy_id,
-        uint32_t *out_num_configs, hwc2_config_t *out_configs) const
+        uint32_t *out_num_configs, hwc2_config_t *out_configs)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -247,8 +296,10 @@
 }
 
 hwc2_error_t hwc2_dev::get_active_config(hwc2_display_t dpy_id,
-        hwc2_config_t *out_config) const
+        hwc2_config_t *out_config)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -261,6 +312,8 @@
 hwc2_error_t hwc2_dev::set_active_config(hwc2_display_t dpy_id,
         hwc2_config_t config)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -271,8 +324,10 @@
 }
 
 hwc2_error_t hwc2_dev::get_color_modes(hwc2_display_t dpy_id,
-        uint32_t *out_num_modes, android_color_mode_t *out_modes) const
+        uint32_t *out_num_modes, android_color_mode_t *out_modes)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -285,6 +340,8 @@
 hwc2_error_t hwc2_dev::set_color_mode(hwc2_display_t dpy_id,
         android_color_mode_t mode)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -297,8 +354,10 @@
 hwc2_error_t hwc2_dev::get_hdr_capabilities(hwc2_display_t dpy_id,
         uint32_t *out_num_types, android_hdr_t *out_types,
         float *out_max_luminance, float *out_max_average_luminance,
-        float *out_min_luminance) const
+        float *out_min_luminance)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -313,6 +372,8 @@
 hwc2_error_t hwc2_dev::set_color_transform(hwc2_display_t dpy_id,
         const float *color_matrix, android_color_transform_t color_hint)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -326,6 +387,8 @@
         uint32_t width, uint32_t height, android_pixel_format_t format,
         android_dataspace_t dataspace)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -340,6 +403,8 @@
         buffer_handle_t target, int32_t acquire_fence,
         android_dataspace_t dataspace, const hwc_region_t &surface_damage)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -352,6 +417,8 @@
 
 hwc2_error_t hwc2_dev::create_layer(hwc2_display_t dpy_id, hwc2_layer_t *out_layer)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -363,6 +430,8 @@
 
 hwc2_error_t hwc2_dev::destroy_layer(hwc2_display_t dpy_id, hwc2_layer_t lyr_id)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -375,6 +444,7 @@
 hwc2_error_t hwc2_dev::set_layer_composition_type(hwc2_display_t dpy_id,
         hwc2_layer_t lyr_id, hwc2_composition_t comp_type)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
     return displays.find(dpy_id)->second.set_layer_composition_type(lyr_id,
             comp_type);
 }
@@ -382,6 +452,7 @@
 hwc2_error_t hwc2_dev::set_layer_buffer(hwc2_display_t dpy_id,
         hwc2_layer_t lyr_id, buffer_handle_t handle, int32_t acquire_fence)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
     return displays.find(dpy_id)->second.set_layer_buffer(lyr_id, handle,
             acquire_fence);
 }
@@ -389,12 +460,14 @@
 hwc2_error_t hwc2_dev::set_layer_dataspace(hwc2_display_t dpy_id,
         hwc2_layer_t lyr_id, android_dataspace_t dataspace)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
     return displays.find(dpy_id)->second.set_layer_dataspace(lyr_id, dataspace);
 }
 
 hwc2_error_t hwc2_dev::set_layer_display_frame(hwc2_display_t dpy_id,
         hwc2_layer_t lyr_id, const hwc_rect_t &display_frame)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
     return displays.find(dpy_id)->second.set_layer_display_frame(lyr_id,
             display_frame);
 }
@@ -402,6 +475,7 @@
 hwc2_error_t hwc2_dev::set_layer_source_crop(hwc2_display_t dpy_id,
         hwc2_layer_t lyr_id, const hwc_frect_t &source_crop)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
     return displays.find(dpy_id)->second.set_layer_source_crop(lyr_id,
             source_crop);
 }
@@ -409,12 +483,14 @@
 hwc2_error_t hwc2_dev::set_layer_z_order(hwc2_display_t dpy_id,
         hwc2_layer_t lyr_id, uint32_t z_order)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
     return displays.find(dpy_id)->second.set_layer_z_order(lyr_id, z_order);
 }
 
 hwc2_error_t hwc2_dev::set_layer_surface_damage(hwc2_display_t dpy_id,
         hwc2_layer_t lyr_id, const hwc_region_t &surface_damage)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
     return displays.find(dpy_id)->second.set_layer_surface_damage(lyr_id,
             surface_damage);
 }
@@ -422,6 +498,7 @@
 hwc2_error_t hwc2_dev::set_layer_blend_mode(hwc2_display_t dpy_id,
         hwc2_layer_t lyr_id, hwc2_blend_mode_t blend_mode)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
     return displays.find(dpy_id)->second.set_layer_blend_mode(lyr_id,
             blend_mode);
 }
@@ -429,6 +506,7 @@
 hwc2_error_t hwc2_dev::set_layer_plane_alpha(hwc2_display_t dpy_id,
         hwc2_layer_t lyr_id, float plane_alpha)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
     return displays.find(dpy_id)->second.set_layer_plane_alpha(lyr_id,
             plane_alpha);
 }
@@ -436,12 +514,14 @@
 hwc2_error_t hwc2_dev::set_layer_transform(hwc2_display_t dpy_id,
         hwc2_layer_t lyr_id, const hwc_transform_t transform)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
     return displays.find(dpy_id)->second.set_layer_transform(lyr_id, transform);
 }
 
 hwc2_error_t hwc2_dev::set_layer_visible_region(hwc2_display_t dpy_id,
         hwc2_layer_t lyr_id, const hwc_region_t &visible_region)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
     return displays.find(dpy_id)->second.set_layer_visible_region(lyr_id,
             visible_region);
 }
@@ -486,11 +566,15 @@
 
 void hwc2_dev::vsync(hwc2_display_t dpy_id, uint64_t timestamp)
 {
-    auto it = displays.find(dpy_id);
-    if (it == displays.end()) {
-        ALOGW("dpy %" PRIu64 ": invalid display handle preventing vsync"
-                " callback", dpy_id);
-        return;
+    {
+        std::lock_guard<std::mutex> guard(state_mutex);
+
+        auto it = displays.find(dpy_id);
+        if (it == displays.end()) {
+            ALOGW("dpy %" PRIu64 ": invalid display handle preventing vsync"
+                    " callback", dpy_id);
+            return;
+        }
     }
 
     callback_handler.call_vsync(dpy_id, timestamp);
@@ -499,6 +583,8 @@
 hwc2_error_t hwc2_dev::set_vsync_enabled(hwc2_display_t dpy_id,
         hwc2_vsync_t enabled)
 {
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     auto it = displays.find(dpy_id);
     if (it == displays.end()) {
         ALOGE("dpy %" PRIu64 ": invalid display handle", dpy_id);
@@ -552,6 +638,8 @@
     adf_id_t *dev_ids = nullptr;
     int ret;
 
+    std::lock_guard<std::mutex> guard(state_mutex);
+
     ssize_t n_devs = adf_devices(&dev_ids);
     if (n_devs < 0) {
         ALOGE("failed to enumerate adf devices: %s", strerror(n_devs));
diff --git a/hwc2/hwc2_display.cpp b/hwc2/hwc2_display.cpp
index 0bed1e9..707dca9 100644
--- a/hwc2/hwc2_display.cpp
+++ b/hwc2/hwc2_display.cpp
@@ -18,6 +18,7 @@
 #include <tegra_adf.h>
 #include <inttypes.h>
 
+#include <sstream>
 #include <cstdlib>
 #include <map>
 #include <vector>
@@ -60,6 +61,46 @@
     adf_device_close(&adf_dev);
 }
 
+std::string hwc2_display::dump() const
+{
+    std::stringstream dmp;
+
+    dmp << "Display [" << id << "] " << getDisplayTypeName(type) << ":\n";
+
+    dmp << "  Power Mode: " << getPowerModeName(power_mode) << "\n";
+
+    dmp << "  Active Config:";
+
+    auto it = configs.begin();
+    if (configs.size() > 0 || it != configs.end())
+        dmp << "\n" << configs.at(active_config).dump();
+    else
+        dmp << " None\n";
+
+    if (power_mode == HWC2_POWER_MODE_OFF)
+        return dmp.str();
+
+    size_t idx = 0;
+    for (auto &win: windows) {
+        dmp << "  Window [" << idx << "]:";
+
+        if (win.contains_layer()) {
+            dmp << " Layer\n";
+            dmp << layers.at(win.get_layer()).dump();
+
+        } else if (win.contains_client_target()) {
+            dmp << " Client Target\n";
+            dmp << client_target.dump();
+
+        } else
+            dmp << " Unused\n";
+
+        idx++;
+    }
+
+    return dmp.str();
+}
+
 hwc2_error_t hwc2_display::set_connection(hwc2_connection_t connection)
 {
     if (connection == HWC2_CONNECTION_INVALID) {
diff --git a/hwc2/hwc2_layer.cpp b/hwc2/hwc2_layer.cpp
index 2c24d95..e97aab5 100644
--- a/hwc2/hwc2_layer.cpp
+++ b/hwc2/hwc2_layer.cpp
@@ -17,6 +17,8 @@
 #include <inttypes.h>
 #include <cutils/log.h>
 
+#include <sstream>
+
 #include "hwc2.h"
 
 uint64_t hwc2_layer::layer_cnt = 0;
@@ -27,6 +29,16 @@
       comp_type(HWC2_COMPOSITION_INVALID),
       modified(true) { }
 
+std::string hwc2_layer::dump() const
+{
+    std::stringstream dmp;
+
+    dmp << "    Composition Type: " << getCompositionName(comp_type) << "\n";
+    dmp << buffer.dump();
+
+    return dmp.str();
+}
+
 hwc2_error_t hwc2_layer::decompress_buffer()
 {
     return buffer.decompress();