Ensure that expected present time is in the future
onMessageInvalidate() sets mExpectedPresentTime to a value originating from the vsync event that scheduled it. If handling of the invalidate is delayed, this value will be in the past, which is clearly not a plausible present time. Because of this, queued frames may incorrectly be ignored as "too early". This has caused problems in screen-on animations: even though the first frame is drawn and ready, SurfaceFlinger shows an old frame. This looks particularly bad with a fade-from-black animation: the old frame flashes by before the first frame of the animation shows. Here's an example timeline of how this problem could manifest: 1000 ms INVALIDATE queued with expectedVSyncTimestamp = 1010ms 1013 ms SF calls setPowerMode() 1014 ms SystemUI queues new NotificationShade frame 1255 ms setPowerMode() returns; invalidate can now be handled 1256 ms invalidate runs; mExpectedPresentTime set to 1010ms 1257 ms handlePageFlip() skips NotificationShade frame; "too early" 1259 ms refresh runs, composits prehistoric NotificationShade frame It's a bit of a race: if SystemUI manages to queue its new frame before the INVALIDATE message's timestamp, there won't be a problem. To solve this, let's check that the expected present time is in the future, and pick the nearest future vsync point if it's not. In order to not break frame miss detection, mScheduledPresentTime is introduced and used instead of mExpectedPresentTime for jank calculations. Fixes: 178415552 Test: manual on Xperia device; flash of old frame is gone Test: compiles on aosp/redfin Change-Id: I095f1dd08374fd1d14552cd1af90d95e9718b4dd Merged-In: I095f1dd08374fd1d14552cd1af90d95e9718b4dd
Loading
Please register or sign in to comment