diff options
author | Eric Penner <epenner@google.com> | 2014-07-28 19:51:58 -0700 |
---|---|---|
committer | Eric Penner <epenner@google.com> | 2014-07-30 19:05:38 -0700 |
commit | 51c59cd1e73be3787eb75bebd87fc41739c65adb (patch) | |
tree | 5ba32fda6ae13fa1aa94e3cb2db6f00e1cf9d16c /services | |
parent | d8e5e813433c5c5e4fea29a24d993b5cfe436fe0 (diff) | |
download | frameworks_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.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 19 |
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); |