Avoid promoting weak reference of Layer on Binder thread.
BufferQueueLayer registers itself to ConsumerBase so it can receive
callbacks about incoming frames. When doing this, ConsumerBase holds a
weak reference to BufferQueueLayer. This would normally be fine except
ConsumerBase promotes the weak pointer on a Binder thread.
This leads to a race where the layer is ready to get destroyed in
SurfaceFlinger, but ConsumerBase promotes the layer. The layer will get
destroyed after the function finishes, but now it gets destroyed off the
main thread. When this happens, a lot of unexpected behavior occurs
since the layer destructor expects the call to only happen on the main
thread and therefore, doesn't hold any locks.
Instead of giving ConsumerBase a weak reference to the layer, we can
give it a reference to a listener. This listener can be managed by
BufferQueueLayer and will only hold a raw reference to the Layer.
ConsumerBase can promote the listener, but it will not be holding a
strong reference to the Layer, allowing the layer to get destroyed on
the main thread.
We hold a lock when accessing the raw reference to ensure it's not being
destroyed. The raw reference is nulled when the layer is getting
destroyed to ensure no more calls are made to the layer after it's
destroyed.
Fixes: 143735125
Fixes: 143200062
Test: go/wm-smoke
Change-Id: I47122b0e4c6d73f23a64027fd3622b2d7fd28871
2 files changed