summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorEric Penner <epenner@google.com>2014-07-28 19:51:58 -0700
committerEric Penner <epenner@google.com>2014-07-30 19:05:38 -0700
commit51c59cd1e73be3787eb75bebd87fc41739c65adb (patch)
tree5ba32fda6ae13fa1aa94e3cb2db6f00e1cf9d16c /services
parentd8e5e813433c5c5e4fea29a24d993b5cfe436fe0 (diff)
downloadframeworks_native-51c59cd1e73be3787eb75bebd87fc41739c65adb.zip
frameworks_native-51c59cd1e73be3787eb75bebd87fc41739c65adb.tar.gz
frameworks_native-51c59cd1e73be3787eb75bebd87fc41739c65adb.tar.bz2
SurfaceFlinger: Prevent deadlock by updating an atomic layer set.
Bug: 12934849 Change-Id: I9dede7316f1e967de4140bd731ac810115ea302f
Diffstat (limited to 'services')
-rw-r--r--services/surfaceflinger/Layer.h5
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp19
2 files changed, 22 insertions, 2 deletions
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2d8084d..765f179 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -277,6 +277,11 @@ public:
*/
Rect getContentCrop() const;
+ /*
+ * Returns if a frame is queued.
+ */
+ bool hasQueuedFrame() const { return mQueuedFrames > 0; }
+
// -----------------------------------------------------------------------
void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index aeba720..cfb9d01 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1541,9 +1541,24 @@ void SurfaceFlinger::handlePageFlip()
bool visibleRegions = false;
const LayerVector& layers(mDrawingState.layersSortedByZ);
- const size_t count = layers.size();
- for (size_t i=0 ; i<count ; i++) {
+
+ // Store the set of layers that need updates. This set must not change as
+ // buffers are being latched, as this could result in a deadlock.
+ // Example: Two producers share the same command stream and:
+ // 1.) Layer 0 is latched
+ // 2.) Layer 0 gets a new frame
+ // 2.) Layer 1 gets a new frame
+ // 3.) Layer 1 is latched.
+ // Display is now waiting on Layer 1's frame, which is behind layer 0's
+ // second frame. But layer 0's second frame could be waiting on display.
+ Vector<Layer*> layersWithQueuedFrames;
+ for (size_t i = 0, count = layers.size(); i<count ; i++) {
const sp<Layer>& layer(layers[i]);
+ if (layer->hasQueuedFrame())
+ layersWithQueuedFrames.push_back(layer.get());
+ }
+ for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
+ Layer* layer = layersWithQueuedFrames[i];
const Region dirty(layer->latchBuffer(visibleRegions));
const Layer::State& s(layer->getDrawingState());
invalidateLayerStack(s.layerStack, dirty);