hwc2: add locks for callback functions

In case surfaceflinger is killed, the function pointer of
RegisterCallback will be null. If the system is still handling
callback function tasks, it could have the chance to access null
pointer and result in a crash. This change adds locks for
callback functions to ensure the tasks are finished then we can
assign null pointer via RegisterCallback.

Bug: 150223963
Test: no crash while surfaceflinger is killed
Merged-In: I3b29c2e17f3a8968348d0d0a29feaca287d4c72c
Change-Id: I3b29c2e17f3a8968348d0d0a29feaca287d4c72c
diff --git a/msm8998/sdm/libs/hwc2/hwc_callbacks.cpp b/msm8998/sdm/libs/hwc2/hwc_callbacks.cpp
index c52632a..e12e057 100644
--- a/msm8998/sdm/libs/hwc2/hwc_callbacks.cpp
+++ b/msm8998/sdm/libs/hwc2/hwc_callbacks.cpp
@@ -35,18 +35,21 @@
 namespace sdm {
 
 void HWCCallbacks::Hotplug(hwc2_display_t display, HWC2::Connection state) {
+  std::lock_guard<std::mutex> hotplug_lock(hotplug_mutex_);
   if (hotplug_) {
     hotplug_(hotplug_data_, display, INT32(state));
   }
 }
 
 void HWCCallbacks::Refresh(hwc2_display_t display) {
+  std::lock_guard<std::mutex> refresh_lock(refresh_mutex_);
   if (refresh_) {
     refresh_(refresh_data_, display);
   }
 }
 
 void HWCCallbacks::Vsync(hwc2_display_t display, int64_t timestamp) {
+  std::lock_guard<std::mutex> vsync_lock(vsync_mutex_);
   if (vsync_) {
     DTRACE_SCOPED();
     vsync_(vsync_data_, display, timestamp);
@@ -56,18 +59,21 @@
 HWC2::Error HWCCallbacks::Register(HWC2::Callback descriptor, hwc2_callback_data_t callback_data,
                                    hwc2_function_pointer_t pointer) {
   switch (descriptor) {
-    case HWC2::Callback::Hotplug:
+    case HWC2::Callback::Hotplug: {
+      std::lock_guard<std::mutex> hotplug_lock(hotplug_mutex_);
       hotplug_data_ = callback_data;
       hotplug_ = reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer);
-      break;
-    case HWC2::Callback::Refresh:
+    } break;
+    case HWC2::Callback::Refresh: {
+      std::lock_guard<std::mutex> refresh_lock(refresh_mutex_);
       refresh_data_ = callback_data;
       refresh_ = reinterpret_cast<HWC2_PFN_REFRESH>(pointer);
-      break;
-    case HWC2::Callback::Vsync:
+    } break;
+    case HWC2::Callback::Vsync: {
+      std::lock_guard<std::mutex> vsync_lock(vsync_mutex_);
       vsync_data_ = callback_data;
       vsync_ = reinterpret_cast<HWC2_PFN_VSYNC>(pointer);
-      break;
+    } break;
     default:
       return HWC2::Error::BadParameter;
   }
diff --git a/msm8998/sdm/libs/hwc2/hwc_callbacks.h b/msm8998/sdm/libs/hwc2/hwc_callbacks.h
index 015bf5d..6c1e696 100644
--- a/msm8998/sdm/libs/hwc2/hwc_callbacks.h
+++ b/msm8998/sdm/libs/hwc2/hwc_callbacks.h
@@ -36,6 +36,8 @@
 #undef HWC2_INCLUDE_STRINGIFICATION
 #undef HWC2_USE_CPP11
 
+#include <mutex>
+
 namespace sdm {
 
 class HWCCallbacks {
@@ -56,6 +58,10 @@
   HWC2_PFN_HOTPLUG hotplug_ = nullptr;
   HWC2_PFN_REFRESH refresh_ = nullptr;
   HWC2_PFN_VSYNC vsync_ = nullptr;
+
+  std::mutex hotplug_mutex_;
+  std::mutex refresh_mutex_;
+  std::mutex vsync_mutex_;
 };
 
 }  // namespace sdm
diff --git a/msm8998/sdm/libs/hwc2/hwc_session.cpp b/msm8998/sdm/libs/hwc2/hwc_session.cpp
index f077667..1331686 100644
--- a/msm8998/sdm/libs/hwc2/hwc_session.cpp
+++ b/msm8998/sdm/libs/hwc2/hwc_session.cpp
@@ -437,7 +437,7 @@
   }
   auto desc = static_cast<HWC2::Callback>(descriptor);
   auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer);
-  DLOGD("Registering callback: %s", to_string(desc).c_str());
+  DLOGD("%s callback: %s", pointer ? "Registering" : "Deregistering", to_string(desc).c_str());
   if (descriptor == HWC2_CALLBACK_HOTPLUG)
     hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
   return INT32(error);