Hardware regression check

2026-08-08Google Pixel 6aAndroid 16 / API 36 1080x2400 @ 420 dpithree-button navigation patched Chromium ToT + WebAppShortEdgesCutoutModestock Chrome 141 control CL 8117612 + CL 8117613 (landed) + local cutout-paint fix
Full hardware matrix green: PASS, 9 passed, 0 failed, 0 skipped, no known issues.

The complete automated matrix ran end-to-end on a Pixel 6a, including the new landscape viewport-fit transition cases (cover → auto → contain → cover → auto) and the on-device keyboard accessory instrumentation test. Both artifacts found during this work are now root-caused and fixed: the cold-launch toolbar hairline remnant and the system bar icons staying white over a white page. All fixes are uploaded under Gerrit topic hja-pwa-fixups.

CasePatchedStock control
Fullscreen PWA cold launchPASS 832/832, safe top 29803/832, safe top 0
Standalone PWA cold launchPASS top edge-to-edge, opaque 48px nav fallback755/832, safe top 0
Pull-to-refreshPASS metrics stablecontrol remains fitted
Off-origin CCT toolbarPASS toolbar begins below status barsame
Standalone parent recoveryPASS 784/832 remains stable755/832 remains fitted
Fullscreen parent recoveryPASS remains 832/832, safe top 29803 before and after
Fullscreen backswipePASS viewport remains 832starts fitted at 803
requestFullscreen baselinePASS 832/832832/832
Three-button navigation renderingPASS page content renders behind the buttonscontent renders behind buttons
Dynamic status icon contrastFIXED status icons and navigation buttons follow the page themestock 141 toggles
Landscape viewport-fit transitionsPASS cover/auto/contain geometry and repeat-cycle equalityn/a (feature off)
Cold-launch toolbar hairline remnantFIXED capture parked fully offscreenhidden by fitted status bar
IME CSS safe-area transitionPASS 15px closed, 0px opennot edge-to-edge, 0px throughout
Keyboard accessory integrationPASS physical IME geometry + injected Chrome accessoryproduction accessory captured

All patched-side screenshots below are from the latest all-fixes Pixel 6a run. Metric numbers quoted in the case texts (832/832, safe top 29) are from the original SM-A546B run and correspond to that device's dimensions; the Pixel 6a equivalents are 914/915 with safe top 51. Stock-control screenshots remain from the Samsung control run. The only intentionally old capture is the fullscreen-recovery "before" failure evidence.

Original sampler cases

Case 1: fullscreen PWA cold launch

Patched Chromium occupies the complete 832 CSS px screen and exposes the 29px top safe area. Stock Chrome reproduces the original fitted top and reports no safe area.

PASS
PatchedinnerHeight 832
safe top 29px
StockinnerHeight 803
safe top 0px
Patched Chromium
Stock Chrome control

Case 2: standalone PWA

The patched page draws behind the status bar and receives a 29px safe area. Its 48px height difference is solely the opaque three-button navigation fallback. Stock excludes both status and navigation bars.

PASS
Patched784/832
top 29px, bottom 0px
Stock755/832
top 0px, bottom 0px
Patched Chromium
Stock Chrome control

The sampler initially called the patched result a failure because its heuristic assumed a navigation bar no taller than the status safe area. The live sampler now allows a 64 CSS px opaque three-button navigation fallback while still requiring a non-zero top safe area.

Case 3: fullscreen backswipe

Gesture navigation was enabled temporarily and restored afterward. Patched Chromium retained innerHeight=832, visualViewport=832, and safe-area-inset-top=29px. No resize event was added by the swipe.

PASS
Patched after transient-bar swipe
Stock control starts fitted

Case 4: document.requestFullscreen()

The regular document API remains unchanged and fills the complete screen in both builds.

PASS
Patchedfullscreen yes
832/832
Stockfullscreen yes
832/832
Patched Chromium
Stock Chrome control

Navigation and child-tab transitions

Fullscreen PWA recovers full top layout after child CCT closes

The failure came from mutating the window's copied layout attributes without applying them. The child transition reset the registered cutout mode to default. Calling Window.setAttributes() makes shortEdges reach WindowManager again when immersive mode returns.

PASS
Before childinnerHeight 832
After childinnerHeight 832
Safe top29px throughout
Before: cutout mode was lost
After: shortEdges restored

Standalone off-origin CCT and recovery

The toolbar starts at physical y=80, below the status bar, and closing it returns to the same 784/832 standalone viewport with top safe area 29px.

PASS
Off-origin child
Recovered standalone parent

Follow-up reports

Landscape viewport-fit transitions

The Fit Switch PWA cycles cover → auto → contain → cover → auto under a landscape rotation lock. cover must span the full landscape width with a non-zero CSS side safe-area inset; auto and contain must use a narrower fitted viewport with zero CSS side inset. The second cover and auto captures must exactly match the first, which catches stale padding or inset ownership after dynamic transitions. Every state also records JSON metrics and the WindowManager state.

PASS
cover: full width, safe-area insets exposed
contain: fitted viewport beside the cutout

Cold-launch toolbar hairline remnant: fixed

Every cold launch of an edge-to-edge web app showed a 1 dp strip of the dynamic theme surface color at the very top of the screen. Root cause: the toolbar capture is toolbar + hairline tall (150 px here), but fully hidden browser controls rest exactly at the zero min-height boundary with browser-applied offsets, so the scroll-time boundary guard from the earlier hairline series skipped the adjustment and parked the layer at -147 px instead of -150 px, leaving the capture's hairline row visible. The fix also applies the adjustment when the controls are entirely off screen. Verified red/green in TopToolbarCoordinatorUnitTest (wanted setYOffset(-150), previously -147) and on hardware; 106 related stacker/control-container tests pass unchanged.

FIXED
Before: 1 dp theme-surface strip over the page (top 40 px, magnified)
After: page content starts at the first pixel row
Before: full cold-launch capture
After: full cold-launch capture

Commit: Hide toolbar hairline capture for fully hidden browser controls (Bug: 512898018). The artifact reproduced with the WebAppShortEdgesCutoutMode feature disabled, on a clean origin/main build, and persisted across scrolling; one off-origin CCT round-trip cleared it, which is why it needed a cold launch to reproduce.

System bar icons over white pages: fixed

Two stacked causes. First, homescreen webapp shortcuts run as ActivityType.WEBAPP and were excluded from bright and night-mode page theming, so a page switching theme-color to white never reached the status bar computation and APPEARANCE_LIGHT_STATUS_BARS never toggled. Second, edge-to-edge navigation buttons render over page content with a transparent bar but ignored the page theme entirely, leaving white Back/Home/Recents buttons invisible over a white page. The fix allows webapp theming like WebAPKs and derives the navigation button appearance from the theme color, updating on theme and edge-to-edge changes. Verified red/green in BaseCustomTabRootUiCoordinatorUnitTest and CustomTabNavigationBarControllerTest; on hardware the white page now reports LIGHT_STATUS_BARS LIGHT_NAVIGATION_BARS and the black page clears both. Uploaded as CL 8227486.

FIXED
Before: white navigation buttons invisible over the white page (bottom 140 px, magnified)
After: dark buttons over the white page
After: white page, dark status icons and buttons
After: black page, light icons and buttons

Keyboard safe-area and scroll behavior

Under temporary gesture navigation, the standalone page reports bottom safe area 15px with the keyboard closed and 0px after the IME opens. The visual viewport changes from 832px to 488.5px while innerHeight remains 832px on this Samsung keyboard implementation.

PASS
Closedbottom 15px
VV 832px
Openbottom 0px
VV 488.5px
Patched, gesture navigation + IME
Stock fullscreen control

Public Chromium cannot create a production saved-password entry on this device. The complete automated check combines the physical fullscreen PWA run, which verifies resizing-IME geometry and no empty gap, with AutofillKeyboardAccessoryIntegrationTest#testTapInputFieldShowsKeyboardAccessory, which injects a suggestion and exercises the real Chrome accessory UI. Both parts passed on the same device.

interactive-widget=resizes-content WebKit repro

The installed WebKit Repro PWA exposes the stale safe-area-inset-bottom bug directly. With the all-fixes APK plus CL 8207801, focusing its bottom input resizes innerHeight from 914px to 572px and updates bottom padding from 56px to 8px; the input ends at 563.8px inside the 571.8px visual viewport, so there is no stale 56px gap above the IME. Raw metrics: before / after.

Pixel 6a, WebKit Repro PWA focused with fixed safe-area bottom

Downloadable automation

The complete hardware workflow is published with direct links so another Chromium checkout and Android device can reproduce the run.

The bundle also contains the separately scoped sampler pages needed to install independent stock Chrome WebAPKs.

Method and reproducibility