From 2765f9d406aae93adceaec67e8053f2ac1129312 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 14 Dec 2017 17:59:48 -0800 Subject: [PATCH] Fix crash on hotplug disconnect ComposerClient destroys its internal model of the display while handling the onHotPlug event from the Hwc. Subsequently SurfaceFlinger destroys its model of the display, and destroys all Hwc layers associated with the display. This fixes the code for destroying layers to not dereference an invalid iterator if the display does not exist, allowing destruction to continue. It also fixes a similar issue which could occur if a HWC layer is being created for a display at around the same time as the disconnect event. Test: hotplug disconnect no longer crashes Bug: 38464421 Change-Id: I0f2d28fe89fccf997b4bbb9fa6b5c0e6a6e49b93 --- .../composer/2.1/default/ComposerClient.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/graphics/composer/2.1/default/ComposerClient.cpp b/graphics/composer/2.1/default/ComposerClient.cpp index 4e6dd4f7e1..8aa9af0e97 100644 --- a/graphics/composer/2.1/default/ComposerClient.cpp +++ b/graphics/composer/2.1/default/ComposerClient.cpp @@ -299,10 +299,17 @@ Return ComposerClient::createLayer(Display display, Error err = mHal.createLayer(display, &layer); if (err == Error::NONE) { std::lock_guard lock(mDisplayDataMutex); - auto dpy = mDisplayData.find(display); - auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first; - ly->second.Buffers.resize(bufferSlotCount); + // The display entry may have already been removed by onHotplug. + if (dpy != mDisplayData.end()) { + auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first; + ly->second.Buffers.resize(bufferSlotCount); + } else { + err = Error::BAD_DISPLAY; + // Note: We do not destroy the layer on this error as the hotplug + // disconnect invalidates the display id. The implementation should + // ensure all layers for the display are destroyed. + } } hidl_cb(err, layer); @@ -316,7 +323,10 @@ Return ComposerClient::destroyLayer(Display display, Layer layer) std::lock_guard lock(mDisplayDataMutex); auto dpy = mDisplayData.find(display); - dpy->second.Layers.erase(layer); + // The display entry may have already been removed by onHotplug. + if (dpy != mDisplayData.end()) { + dpy->second.Layers.erase(layer); + } } return err;