Some additional notes on this reland:
In local testing across SPA and MPA navigations, scroll sequences, and route changes, the pre-draw listener approach reduces toolbar bitmap captures by ~60–75% compared to my previous fix. The reduction comes from coalescing multiple invalidations per frame into a single capture, and the listener self-deregistering once the toolbar starts revealing.
Memory: the bisect flagged ~1 MB regression (crbug.com/504007917) in the previous fix. Fewer unnecessary captures could bring it down. Or it could stay the same if the remaining captures are all necessary, which would mean the bitmap cache is working as intended (I believe). Either way it shouldn't be worse.
Also tested manually on a Samsung S21 (ARM64, Android 15). No UI/UX regressions. Done some additional Android x64 tests that would fail in previous CL/patches. All good.
The NullPointerException was a pre-existing latent bug. Our increased capture rate was the first time it was reliably triggered in CI.
Ready for review/CQ Dry Run whenever you want!
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Some additional notes on this reland:
In local testing across SPA and MPA navigations, scroll sequences, and route changes, the pre-draw listener approach reduces toolbar bitmap captures by ~60–75% compared to my previous fix. The reduction comes from coalescing multiple invalidations per frame into a single capture, and the listener self-deregistering once the toolbar starts revealing.
Memory: the bisect flagged ~1 MB regression (crbug.com/504007917) in the previous fix. Fewer unnecessary captures could bring it down. Or it could stay the same if the remaining captures are all necessary, which would mean the bitmap cache is working as intended (I believe). Either way it shouldn't be worse.
Also tested manually on a Samsung S21 (ARM64, Android 15). No UI/UX regressions. Done some additional Android x64 tests that would fail in previous CL/patches. All good.
The NullPointerException was a pre-existing latent bug. Our increased capture rate was the first time it was reliably triggered in CI.
Ready for review/CQ Dry Run whenever you want!
Oh and please, if I'm speaking non-sense about the memory regression and it's important to address (if this keeps being a problem), please let me know. I don't have the sufficient knowledge to debug it properly and verify the nature of it, but I'm willing to learn of course
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
if (dirtyRect != null) {sorry you're gonna get a merge conflict here, I landed another patch to fix this first cause it was causing crashes in canary/dev
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Alejandro RomanoSome additional notes on this reland:
In local testing across SPA and MPA navigations, scroll sequences, and route changes, the pre-draw listener approach reduces toolbar bitmap captures by ~60–75% compared to my previous fix. The reduction comes from coalescing multiple invalidations per frame into a single capture, and the listener self-deregistering once the toolbar starts revealing.
Memory: the bisect flagged ~1 MB regression (crbug.com/504007917) in the previous fix. Fewer unnecessary captures could bring it down. Or it could stay the same if the remaining captures are all necessary, which would mean the bitmap cache is working as intended (I believe). Either way it shouldn't be worse.
Also tested manually on a Samsung S21 (ARM64, Android 15). No UI/UX regressions. Done some additional Android x64 tests that would fail in previous CL/patches. All good.
The NullPointerException was a pre-existing latent bug. Our increased capture rate was the first time it was reliably triggered in CI.
Ready for review/CQ Dry Run whenever you want!
Oh and please, if I'm speaking non-sense about the memory regression and it's important to address (if this keeps being a problem), please let me know. I don't have the sufficient knowledge to debug it properly and verify the nature of it, but I'm willing to learn of course
The memory regression can be real. In the past we reduced memory by capturing less often. If we run an A/B test we can see how big/real the regression is in the real world. You can land this patch first and I can run an A/B test after.
Alejandro RomanoSome additional notes on this reland:
In local testing across SPA and MPA navigations, scroll sequences, and route changes, the pre-draw listener approach reduces toolbar bitmap captures by ~60–75% compared to my previous fix. The reduction comes from coalescing multiple invalidations per frame into a single capture, and the listener self-deregistering once the toolbar starts revealing.
Memory: the bisect flagged ~1 MB regression (crbug.com/504007917) in the previous fix. Fewer unnecessary captures could bring it down. Or it could stay the same if the remaining captures are all necessary, which would mean the bitmap cache is working as intended (I believe). Either way it shouldn't be worse.
Also tested manually on a Samsung S21 (ARM64, Android 15). No UI/UX regressions. Done some additional Android x64 tests that would fail in previous CL/patches. All good.
The NullPointerException was a pre-existing latent bug. Our increased capture rate was the first time it was reliably triggered in CI.
Ready for review/CQ Dry Run whenever you want!
Peilin WangOh and please, if I'm speaking non-sense about the memory regression and it's important to address (if this keeps being a problem), please let me know. I don't have the sufficient knowledge to debug it properly and verify the nature of it, but I'm willing to learn of course
The memory regression can be real. In the past we reduced memory by capturing less often. If we run an A/B test we can see how big/real the regression is in the real world. You can land this patch first and I can run an A/B test after.
Got it. Thanks!
if (dirtyRect != null) {sorry you're gonna get a merge conflict here, I landed another patch to fix this first cause it was causing crashes in canary/dev
Got it. Awesome that it's already been taken care of. Thanks!
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
New patchset. Ready for review and a CQ Dry Run.
Rebased, removed dirtyRect workaround and test in favor of upstream fix.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
New patchset. Ready for review and a CQ Dry Run.
Rebased, removed dirtyRect workaround and test in favor of upstream fix.
Done
Patchset 7. Rebased. Please trigger a CQ Run when ready!
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Patchset 7. Rebased. Please trigger a CQ Run when ready!
All tests passing! Resolving this comment
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
private boolean onHiddenCapturePreDraw() {does this get called from anywhere?
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
private boolean onHiddenCapturePreDraw() {does this get called from anywhere?
not really, only from the line above it, mHiddenCaptureOnPreDraw. I can turn it into a simpler = () -> {} inline
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
private boolean onHiddenCapturePreDraw() {Alejandro Romanodoes this get called from anywhere?
not really, only from the line above it, mHiddenCaptureOnPreDraw. I can turn it into a simpler = () -> {} inline
Declaring+initializing OnPreDrawListener will call this function?
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
private boolean onHiddenCapturePreDraw() {Alejandro Romanodoes this get called from anywhere?
Peilin Wangnot really, only from the line above it, mHiddenCaptureOnPreDraw. I can turn it into a simpler = () -> {} inline
Declaring+initializing OnPreDrawListener will call this function?
No, it just stores a reference to `onHiddenCapturePreDraw()`. It won't initialize it right away.
We do that to pass the same `mHiddenCaptureOnPreDraw` object to both `addOnPreDrawListener()` and `removeOnPreDrawListener()`. If we passed `this::onHiddenCapturePreDraw` directly each time, each call would create a new object with no way to unregister it, if that makes sense.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
private boolean onHiddenCapturePreDraw() {Alejandro Romanodoes this get called from anywhere?
Peilin Wangnot really, only from the line above it, mHiddenCaptureOnPreDraw. I can turn it into a simpler = () -> {} inline
Alejandro RomanoDeclaring+initializing OnPreDrawListener will call this function?
No, it just stores a reference to `onHiddenCapturePreDraw()`. It won't initialize it right away.
We do that to pass the same `mHiddenCaptureOnPreDraw` object to both `addOnPreDrawListener()` and `removeOnPreDrawListener()`. If we passed `this::onHiddenCapturePreDraw` directly each time, each call would create a new object with no way to unregister it, if that makes sense.
Ah sorry I didn't see you're adding the listener on line 802...
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Code-Review | +1 |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Code-Review | +1 |
private boolean shouldCaptureWhileHidden() {Since this is only used once, you could fold the `!mHiddenCaptureRegistered` check into the method and rename to `shouldRegisterHiddenCapturePreDrawListener` . up to you
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
private boolean shouldCaptureWhileHidden() {Since this is only used once, you could fold the `!mHiddenCaptureRegistered` check into the method and rename to `shouldRegisterHiddenCapturePreDrawListener` . up to you
You mean `shouldCaptureWhileHidden` being used once? It is used in three places
That's why it exists as its own function
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
private boolean shouldCaptureWhileHidden() {Alejandro RomanoSince this is only used once, you could fold the `!mHiddenCaptureRegistered` check into the method and rename to `shouldRegisterHiddenCapturePreDrawListener` . up to you
You mean `shouldCaptureWhileHidden` being used once? It is used in three places
- Line 706: inside onHiddenCapturePreDraw() to decide whether to deregister
- Line 715: inside the posted runnable to re-check before capturing
- Line 798: at registration time, combined with !mHiddenCaptureRegistered
That's why it exists as its own function
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Sorry, previous rebase was missing some changes. PTAL!
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |