New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
We don't pump frames on Android when the screen is split #11906
Comments
This is a new-user-experience issue that affects everyone. The problem is probably that we use the wrong app lifecycle state for the split-screen mode on Android. We should be using "inactive". |
cc @amirh who said he might be interested in this bug. |
/cc @jason-simmons |
@jason-simmons If you're not looking at this right now I could take a look, since I'm blocked on my other work for a while... |
This also requires us to add |
Looked at this today - It seems the only change we would need to make is to also consider the lifecycle |
Hi @jonahwilliams :) While multi-window is the most obvious case for being not in focus but visible, they also mention dialogs that can pause your activity while keeping it visible. I believe we shouldn't stop pumping frames when the activity loses focus. e.g think of a stopwatch application, you probably still want to see the stopwatch running when losing focus due to e.g multi-window or a dialog. While the documentation say that onPause is a good place to stop animations, I don't believe it should always stop all animations, and apps should probably still be able to update the screen while not in focus but visible. For these reasons (and probably for future compatibility as onPause now doesn't mean invisible) I would suggest we consider to not restrict the solution to multi window detection, and allow apps to keep updating the screen even when not in focus. |
Thanks for the background @amirh. I believe @Hixie and @cbracken could give more background on why the decision was made original to stop pumping frames entirely in onPause. Ideally we would stop pumping frames only when the app was "invisible." That concept is poorly defined in the Android world, but onPause and onResume are a good proxy. Except of course for all the times that they aren't, like you mentioned:
I don't think we should necessarily give up just because there are edge cases though, we can fix them. As the ultimate work around, you can always override |
Would it be reasonable to stop pumping frames onStop ("Called when you are no longer visible to the user")? |
Keep in mind that due to significant differences in the Android and iOS lifecycle platform callbacks these map to somewhat different concepts on the two platforms. On iOS it's particularly important not to pump frames once backgrounded, since the result is an |
Probably because we didn't know what we were doing. |
I agree with @amirh's interpretation, that we shouldn't stop painting on Android when we're still visible. We continue painting on iOS. We are probably just mapping the Android lifecycle events to the wrong values of the lifecycle enum. |
This is pretty likely; I certainly didn't have split-screen in mind when I originally added this code. |
Okay - I will do some more investigation into onStop and onPause in the android world. If I can simplify that code then I can probably avoid using the more specific split screen APIs |
I'd definitely look at instrumenting the two calls and gathering some empirical evidence for what they do. IIRC the documentation at the time was quite vague on when each was called. It's entirely possible they've added more detail to the docs now with split-screen in mind. |
Some more investigation - If you use picture in picture mode with another app, the flutter app will also pause if you tap into that |
The original addition of the onPause and onResume hooks is here flutter/engine@6f0c2d0983. It seems like the intention was to ensure we weren't needlessly pumping frames. |
|
@chinmaygarde can speak to this more, but I believe the plan is to get the engine out of this business and have the Dart code entirely in charge of when we push frames. |
We might need to look at the iOS side too, though |
It is entirely possible (and likely) that the choreographer on Android is making decisions about when to give the engine vsync pulses. You can try switching to a timer based fallback vsync waiter to check to see if this indeed the issue. Patch in this method on Android and return If it turns out that the we depend on the vsync waiter to give us frames even when the application is inactive, we might need to introduce a switching mechanism to use the fallback when the platform vsync waiter refuses to give us events. |
@chinmaygarde if the choreographer doesn't call the callback because we're invisible, why should we pump frames? |
After initially skimming this thread, I thought that the choreographer was not giving us frames even when it was on screen but the user had focused another application in split screen mode. If this is not the case and the choreographer works as expected when the application is not focused but still present on screen, then lets not stop the animator based on lifecycle. |
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of |
If you run a Flutter app in split-screen mode, we don't pump frames once you tap the other app.
The text was updated successfully, but these errors were encountered: