SF: protect mDisplayCapabilities with a lock
There is a rare race condition where mDisplayCapabilities can be
read while it is getting updated, which causes a crash.
Bug: 196059993
Test: SF unit tests
Change-Id: Iaca9f1b61cdc1a59639a93f62c1716acddf8186b
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 27146ab..e21b0da 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -283,8 +283,21 @@
return Error::NONE;
}
+bool Display::hasCapability(hal::DisplayCapability capability) const {
+ std::scoped_lock lock(mDisplayCapabilitiesMutex);
+ if (mDisplayCapabilities) {
+ return mDisplayCapabilities->count(capability) > 0;
+ }
+
+ ALOGW("Can't query capability %d."
+ " Display Capabilities were not queried from HWC yet",
+ static_cast<int>(capability));
+
+ return false;
+}
+
Error Display::supportsDoze(bool* outSupport) const {
- *outSupport = mDisplayCapabilities.count(DisplayCapability::DOZE) > 0;
+ *outSupport = hasCapability(DisplayCapability::DOZE);
return Error::NONE;
}
@@ -447,17 +460,21 @@
auto error =
static_cast<Error>(mComposer.getDisplayCapabilities(mId, &tmpCapabilities));
if (error == Error::NONE) {
+ std::scoped_lock lock(mDisplayCapabilitiesMutex);
+ mDisplayCapabilities.emplace();
for (auto capability : tmpCapabilities) {
- mDisplayCapabilities.emplace(static_cast<DisplayCapability>(capability));
+ mDisplayCapabilities->emplace(static_cast<DisplayCapability>(capability));
}
} else if (error == Error::UNSUPPORTED) {
+ std::scoped_lock lock(mDisplayCapabilitiesMutex);
+ mDisplayCapabilities.emplace();
if (mCapabilities.count(Capability::SKIP_CLIENT_COLOR_TRANSFORM)) {
- mDisplayCapabilities.emplace(DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM);
+ mDisplayCapabilities->emplace(DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM);
}
bool dozeSupport = false;
error = static_cast<Error>(mComposer.getDozeSupport(mId, &dozeSupport));
if (error == Error::NONE && dozeSupport) {
- mDisplayCapabilities.emplace(DisplayCapability::DOZE);
+ mDisplayCapabilities->emplace(DisplayCapability::DOZE);
}
}
});