[Android] Add integration test for SystemUiMode transitions#187269
Conversation
2125b5d to
77f82b1
Compare
Local verification — the test catches the regressionRebased onto current Pre-fix engine (master at
|
Before-fix (#183072 only — regressed) |
After-fix (#183072 + #187207) |
|---|---|
![]() |
![]() |
Both screens show mode label edgeToEdge. On the left (regressed), strips fill the entire screen — status bar and nav bar are still hidden, exactly as #186723 reported. On the right (fixed), the status bar (5:19, wifi/signal/battery) sits on the green TOP STRIP and the gesture-nav pill sits on the yellow BOTTOM STRIP — bars correctly restored.
immersive → edgeToEdge
| Before-fix | After-fix |
|---|---|
![]() |
![]() |
leanBack → edgeToEdge
| Before-fix | After-fix |
|---|---|
![]() |
![]() |
Confirming the pre-state (bars hidden before the switch)
For reference, here's immersiveSticky before the switch — same in both states, bars hidden, strips fully visible:
Note on the visual entrypoint
The colored strips + mode label app above is for capture only. The committed entrypoint stays minimal (ColoredBox body) — the visual instrumentation was a temporary local edit and is not in the diff.
Marking ready for review.
There was a problem hiding this comment.
Code Review
This pull request adds integration tests to verify SystemUiMode transitions on Android, including a new test app, a companion test driver, and native driver support to retrieve system UI visibility flags. Feedback on the changes includes addressing a potential compilation error in Kotlin due to unsafe access of the nullable activity object, removing an unnecessary endOfFrame wait and its unused import in the Dart test harness, and avoiding the use of Timeout.none in the integration tests to prevent CI hangs.
77f82b1 to
e0e9866
Compare
dbebawy
left a comment
There was a problem hiding this comment.
All three review threads addressed and resolved:
- Comment 1 (compile error claim): replied — it's a Kotlin smart-cast, not a compile error; same pattern used by every other branch in this method.
- Comment 2 (
SchedulerBinding.instance.endOfFrame): fix applied in commit e0e9866 — dropped the await and the unusedscheduler.dartimport. All 6 tests still pass. - Comment 3 (
Timeout.none): replied — it's the established convention for every test intest_driver/.
End-to-end verification on a real Impeller-Vulkan emulator (Pixel API 36):
- Pass against current master (with #187207).
- Fail against pre-#187207 engine in a worktree, with the exact expected diagnostic
Expected: <0>, Actual: <6>on all three newX → edgeToEdgecells — confirming the test catches the regression.
Ready for code-owner review.
|
Friendly ping @reidbaker @gmackall @camsim99 @mboetger — this is the integration-test follow-up to #186723 / #187207 (per discussion on the original regression). All review threads resolved, and end-to-end verification posted above confirms the test catches the regression on a pre-#187207 engine ( |
camsim99
left a comment
There was a problem hiding this comment.
LGTM, thanks for jumping on integration testing so quickly! I'm super excited to have these tests in place to help avoid regressions as we continue to improve our support for edge-to-edge.
d871c3f to
f0ec673
Compare
f0ec673 to
6664b54
Compare
Adds a Flutter Driver test under android_engine_test that drives `SystemChrome.setEnabledSystemUIMode` through transition pairs and asserts the resulting decor-view `systemUiVisibility` flags via a new `get_system_ui_visibility` method on `native_driver`. The regression-named test reproduces the `immersiveSticky -> edgeToEdge` cell from flutter#186723 / fixed in flutter#187207: without the fix, FLAG_FULLSCREEN and FLAG_HIDE_NAVIGATION from the prior immersiveSticky call persist on the decor view, leaving the system bars hidden under edgeToEdge. Tests skip on API < 29 since edgeToEdge requires API 29+. Closes flutter#187265
6664b54 to
38d853c
Compare
…187269) ## Summary Adds a Flutter Driver integration test under `dev/integration_tests/android_engine_test/` covering `SystemUiMode` transitions on Android. The test exposes a `requestData` handler that applies modes via `SystemChrome.setEnabledSystemUIMode` and reads the resulting decor-view `systemUiVisibility` flags via a new `get_system_ui_visibility` method on the existing `native_driver` method channel. Closes flutter#187265. ## Why flutter#186723 was a P1 regression introduced by flutter#183072 and fixed by flutter#187207. The Mockito-based `PlatformPluginTest` unit tests verify which APIs are called on a mocked `Window`/`View` but cannot observe residual `decorView` state that bleeds across mode switches — which is the exact bug class the regression was. A device-level integration test closes that gap. ## What the tests cover | Transition | Assertion | |------------|-----------| | `immersiveSticky → edgeToEdge` (regression case for flutter#186723) | `FLAG_FULLSCREEN` and `FLAG_HIDE_NAVIGATION` are cleared | | `immersive → edgeToEdge` | Same | | `leanBack → edgeToEdge` | Same | | `edgeToEdge → immersive` | `IMMERSIVE \| FULLSCREEN \| HIDE_NAVIGATION` set | | `edgeToEdge → immersiveSticky` | `IMMERSIVE_STICKY \| FULLSCREEN \| HIDE_NAVIGATION` set | | `edgeToEdge → leanBack` | `FULLSCREEN \| HIDE_NAVIGATION` set, no immersive flags | All tests skip on API < 29 since `edgeToEdge` requires Android 10+. ## Files - New: `lib/system_ui_mode_transitions_main.dart` — Flutter Driver entrypoint with mode-applying handler. - New: `test_driver/system_ui_mode_transitions_main_test.dart` — assertion suite. - Modified: `NativeDriverSupportPlugin.kt` — adds `get_system_ui_visibility` method that returns the decor view's `systemUiVisibility` int. Reading the deprecated field is the most direct signal of the regression class (flutter#186723 was specifically about flag bleed-through on this field). - Modified: `README.md` — adds the new entrypoint to the test list. CI auto-discovery is via `Glob('dev/integration_tests/android_engine_test/lib/**_main.dart')` in `dev/bots/suite_runners/run_android_engine_tests.dart` — no separate registration needed. ## Pre-launch Checklist - [x] I read the [Contributor Guide](https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview). - [x] I read the [Tree Hygiene](https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md) wiki page. - [x] I read and followed the [Flutter Style Guide](https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md). - [x] I signed the [CLA](https://cla.developers.google.com/). - [x] I listed at least one issue that this PR fixes in the description above. - [x] I added new tests to check the change I am making. - [x] All existing and new tests are passing. ## Notes for reviewers - Marked as draft because I do not have a local Android emulator set up — `flutter analyze` is clean but I have not run the test end-to-end. CI is the source of truth. - The reason for reading the deprecated `systemUiVisibility` field on the native side (rather than `WindowInsetsCompat.isVisible(...)`) is that the regression was specifically about bit flags persisting on the decor view; the deprecated read gives a deterministic, version-independent signal. The production code still migrates to non-deprecated APIs for *setting* state per flutter#183072. - `SystemUiMode.manual` is out of scope here (different API surface — takes a `List<SystemUiOverlay>`) and can follow up.







Summary
Adds a Flutter Driver integration test under
dev/integration_tests/android_engine_test/coveringSystemUiModetransitions on Android. The test exposes arequestDatahandler that applies modes viaSystemChrome.setEnabledSystemUIModeand reads the resulting decor-viewsystemUiVisibilityflags via a newget_system_ui_visibilitymethod on the existingnative_drivermethod channel.Closes #187265.
Why
#186723 was a P1 regression introduced by #183072 and fixed by #187207. The Mockito-based
PlatformPluginTestunit tests verify which APIs are called on a mockedWindow/Viewbut cannot observe residualdecorViewstate that bleeds across mode switches — which is the exact bug class the regression was. A device-level integration test closes that gap.What the tests cover
immersiveSticky → edgeToEdge(regression case for #186723)FLAG_FULLSCREENandFLAG_HIDE_NAVIGATIONare clearedimmersive → edgeToEdgeleanBack → edgeToEdgeedgeToEdge → immersiveIMMERSIVE | FULLSCREEN | HIDE_NAVIGATIONsetedgeToEdge → immersiveStickyIMMERSIVE_STICKY | FULLSCREEN | HIDE_NAVIGATIONsetedgeToEdge → leanBackFULLSCREEN | HIDE_NAVIGATIONset, no immersive flagsAll tests skip on API < 29 since
edgeToEdgerequires Android 10+.Files
lib/system_ui_mode_transitions_main.dart— Flutter Driver entrypoint with mode-applying handler.test_driver/system_ui_mode_transitions_main_test.dart— assertion suite.NativeDriverSupportPlugin.kt— addsget_system_ui_visibilitymethod that returns the decor view'ssystemUiVisibilityint. Reading the deprecated field is the most direct signal of the regression class ([Regression] [Android] Failed to swtich SystemUIMode fromimmersiveStickytoedgeToEdgein Flutter 3.44.0 #186723 was specifically about flag bleed-through on this field).README.md— adds the new entrypoint to the test list.CI auto-discovery is via
Glob('dev/integration_tests/android_engine_test/lib/**_main.dart')indev/bots/suite_runners/run_android_engine_tests.dart— no separate registration needed.Pre-launch Checklist
Notes for reviewers
flutter analyzeis clean but I have not run the test end-to-end. CI is the source of truth.systemUiVisibilityfield on the native side (rather thanWindowInsetsCompat.isVisible(...)) is that the regression was specifically about bit flags persisting on the decor view; the deprecated read gives a deterministic, version-independent signal. The production code still migrates to non-deprecated APIs for setting state per [Android] Use EdgeToEdge.enable/WindowCompat for edge-to-edge mode instead of deprecated View flags #183072.SystemUiMode.manualis out of scope here (different API surface — takes aList<SystemUiOverlay>) and can follow up.