SF: Handle deferred removal of disconnected pacesetter display in commit
There are many display abstractions throughout SF, and they are not destroyed at the same time. On Hotplug disconnect, SF::processHotplugDisconnect() removes the PhysicalDisplay from its map, and from mCurrentState; but stops there. Other display abstractions, like Scheduler::Display, are removed when SF detects a difference in the number of displays in the current and drawing state during processDisplayChangesLocked(), part of commit(). This deferral leads to use-after-free if a pacesetter display is hotplug disconnected. SF::commit() is called by Scheduler using the pacesetter display, which hasn't been cleaned up yet, and when commit() tells SF to unregister the pacesetter, it also deletes the FrameTargeter and RefreshRateSelector, which are used heavily throughout commit/composite and subsequent uses will lead to UB. This CL adds a check in SF::commit() that sees if SF still has a display corresponding to the pacesetter ID passed in by the scheduler. If not, it assumes that a hotplug disconnect has taken place, and runs processDisplayChangesLocked() to propagate the disconnect to Scheduler. It will then schedule another commit to happen immediately and then cancel out of the commit prematurely. This prevents use of the deleted pacesetter display, and also allows the commit/composite to run for the targeted vsync. Flag: com.android.graphics.surfaceflinger.flags.pacesetter_selection Bug: 389983418, 241286431 Test: Manually tested on a foldable by unplugging external pacestter Change-Id: Ifaea005f73a9b238685d148c6774fe0cec93dbea
Loading
Please register or sign in to comment