SurfaceFlinger: Prevent deadlock by updating an atomic layer set.

Bug: 12934849

Change-Id: I9dede7316f1e967de4140bd731ac810115ea302f
This commit is contained in:
Eric Penner 2014-07-28 19:51:58 -07:00
parent d8e5e81343
commit 51c59cd1e7
2 changed files with 22 additions and 2 deletions

View File

@ -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;

View File

@ -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);