android: turned over, for real — the walk rotates the phone, and puts it back
Round twenty-seven wrote the landscape layout and proved it at 915×411 in
headless Chrome; no real device had ever been turned, and the phone walk
refuses a `{ view: [...] }` step because a device's orientation is not the
step list's to set. That refusal stays. The turn goes in the phone tail
instead, right after `background` has proved playback is live with the app
off screen, and it asserts the four things the mock physically cannot show:
`screen.orientation.angle` is 90 or 270 — an override without
`screenOrientation` leaves the angle at 0, so this one is only ever a real
phone — the WebView RESIZED as well (a separate clause, because a WebView
that never got the configuration change looks exactly like a display that
never rotated), `--nav-h` computed to 48px so the phone-sized landscape query
really fired, and the activity was not recreated: the same window token, the
same `performance.timeOrigin`, the same pid, no `AndroidRuntime` fatal — and
those last two are read tolerantly, because `pidof` exits 1 when the process
is GONE and `adb()` throws on a non-zero exit, so the plain read threw the
whole report away at exactly the moment it mattered. Then the stack, the
track still playing and past where it was (a track that rolled over during
the turn is still playing, which is all the clause claims), nothing clipped,
and the player sheet sideways in two columns with every control on screen.
The safe-area insets are printed, not asserted. Nobody had ever measured
them here — `MainActivity` calls androidx's `enableEdgeToEdge()` and nothing
in the generated Kotlin touches insets, so `env()` comes straight out of
Chromium's window-inset mapping — and asserting a number nobody has measured
is how a round fails on a correct build. What is asserted is the plumbing, on
both edges, because a hole-punch is only on one of them: whatever `env()`
says, the glass bar, the mini bar, the screen and the sheet spend it.
The phone is Kyle's, so the two rotation settings are read before either is
written and put back from four places — the block's own finally, main's
finally, `process.on("exit")` and SIGINT/SIGTERM/SIGBREAK — because a failed
clause only walks on but a WebView that stops answering throws clean out of
the loop, and Ctrl-C runs no exit handler at all. The latch clears itself
before it writes, a failed restore hands it back for the next caller, and the
skip paths disarm rather than restore, so a phone that could not be read, one
already sideways and `--no-rotate` all leave it untouched. Nothing else on the
device is written.
One thing beyond the turn: the `{ adb }` step kept its stdout. `am start`
prints "Error: Activity not started, unable to resolve Intent" on stdout and
exits 0, so `share-import` — the step that exists to prove the share intent
resolves — could not fail for its own reason. It can now.
This commit is contained in:
1 parent
33f32cb4c9
commit
867fd42972
2 files changed
+500
-6
No files matched your search
+63
-4
@@ -80,10 +80,14 @@ turns it off.
|
||||
The activity declares no `screenOrientation` and handles `orientation` and
|
||||
`screenSize` itself, so turning the phone over is a resize and nothing else —
|
||||
the audio thread, the stack and the screen's scroll all survive it, and the
|
||||
layout is the only thing that has to answer. Two media queries do that. The
|
||||
player sheet is the one surface whose portrait shape cannot survive a wide
|
||||
viewport: its artwork is a square sized by WIDTH, so at 915×411 the cover came
|
||||
out 879px tall and the title, the lane, the transport and the face buttons sat
|
||||
layout is the only thing that has to answer. Two media queries do that.
|
||||
Every claim in that sentence was read off the CSS and proved at 915×411
|
||||
behind a viewport override; the phone walk now turns a real device over and
|
||||
reads each of them there — the angle, the insets around the cutout and the
|
||||
gesture pill, the activity, the audio. See **Verifying**. The player sheet
|
||||
is the one surface whose portrait shape cannot survive a wide viewport: its
|
||||
artwork is a square sized by WIDTH, so at 915×411 the cover came out 879px
|
||||
tall and the title, the lane, the transport and the face buttons sat
|
||||
below the bottom of a sheet that does not scroll — a corner of the cover and no
|
||||
way to pause. Sideways it is two columns: the head across the top, the cover
|
||||
down the left sized by HEIGHT, and the track, the scrubber, the transport and
|
||||
@@ -1426,6 +1430,61 @@ through the same client, which is how the walk turns the phone over and back;
|
||||
the phone walk refuses one, because a real device's orientation is not the
|
||||
harness's to set.
|
||||
|
||||
The device turns itself over instead, in a block of the phone walk's own,
|
||||
after `background` and before the network — because a step list cannot do
|
||||
either of the two things this needs. It reads
|
||||
`settings get system accelerometer_rotation` and `user_rotation` FIRST and
|
||||
latches the pair; only then does it put auto-rotate off and `user_rotation`
|
||||
to 1 (a retry at 3 for a device whose natural orientation is landscape), and
|
||||
it polls for the turn rather than waiting a fixed time. Then it asserts what
|
||||
only a device can answer: `screen.orientation.angle` is 90 or 270 — an
|
||||
`Emulation.setDeviceMetricsOverride` without `screenOrientation` leaves the
|
||||
angle at 0, so the mock physically cannot fake this, and it is the one clean
|
||||
"a real phone did this" clause — that the WebView RESIZED as well (a separate
|
||||
clause, because a WebView that never got the configuration change looks
|
||||
identical to a display that never rotated), that `--nav-h` computed to 48px
|
||||
so the phone-sized landscape query really fired, that the activity was NOT
|
||||
recreated (the same window token and the same `performance.timeOrigin`, the
|
||||
same pid, no `AndroidRuntime` fatal — the manifest declares `orientation` and
|
||||
`screenSize` handled, so a recreation here would be the bug), that the tab
|
||||
and every stack are where they were, that the track is still playing and past
|
||||
where it was, that nothing is clipped, and that the glass bar, the mini bar
|
||||
and the screen spend whatever `env()` says. Then the player sheet sideways:
|
||||
two columns, every control on screen, its own side padding. Then back.
|
||||
|
||||
The four safe-area insets are printed, not asserted. Nobody had ever measured
|
||||
them on this phone: `MainActivity` calls androidx's `enableEdgeToEdge()`,
|
||||
`themes.xml` sets no cutout attribute and nothing in the generated Kotlin
|
||||
touches insets, so `env()` comes straight out of Chromium's own window-inset
|
||||
mapping and whether the hole-punch shows up as a non-zero side inset depends
|
||||
on the cutout mode that picks. The run records the numbers — `insets` as
|
||||
top/right/bottom/left, `insetsReal`, the app's own `--inset-left/right` beside
|
||||
them, and `chromePct` — and a later round can assert them once they are known.
|
||||
Asserting a number nobody has measured is how a round fails on a correct
|
||||
build.
|
||||
|
||||
Putting the phone back is the part that is written carefully, because the
|
||||
phone is Kyle's. The saved pair is a module-level latch, and the restore is
|
||||
reached from four places: the rotation block's own `finally`, main's
|
||||
`finally`, `process.on("exit")` and SIGINT/SIGTERM/SIGBREAK. It has to be all
|
||||
four — a failed clause only pushes a problem and walks on, but `still()` and
|
||||
the probe call are wrapped in nothing, so a WebView that stops answering
|
||||
rejects after 45 s and throws clean out of the loop, and Ctrl-C runs no `exit`
|
||||
handler at all. The latch clears itself before it writes, so only the first
|
||||
caller acts and a restore that fails hands the latch back for the next one.
|
||||
The rotation goes back before auto-rotate does, so a phone that had the sensor
|
||||
in charge gets it back last. A device whose two settings will not read is
|
||||
skipped with a line rather than forced — `rotation skipped: the phone's
|
||||
rotation settings would not read` — as is one that is already sideways, and
|
||||
`--no-rotate` skips the block outright for a run where he is holding the
|
||||
phone. Nothing else on the device is touched: no download, no room, no
|
||||
message, no sign-in, nothing written to the config or the library. The one
|
||||
case no handler covers is a hard kill of the machine, after which auto-rotate
|
||||
is a Quick Settings tile away.
|
||||
|
||||
The stills are `phone-turned.png`, `phone-turned-sheet.png` and
|
||||
`phone-turned-back.png`.
|
||||
|
||||
The phone walk is the same driver on the real thing (plus a step kind of
|
||||
its own: `{ adb: [...] }` runs an adb command — the share-sheet intent, a
|
||||
key — and a step may carry a `probe` as well, a function whose reading of
|
||||
|
||||
Reference in new issue
Block a user