iPhone Duo simulator baseline: alignment table
Ground truth for vphone-duo, collected 2026-10-29 from Apple's iPhone Duo simulator (iPhone19,4, V68, iOS 27.1 24A94425, Xcode 27.1). The simulator folds through SpringBoard's own display-swap coordinator (README.md, "Posture").
The vphone-duo column was filled on 2026-10-29 from the VM duobase-01
(bundle 2.14.0-local.21dc0c06, upstream main 82afdb9a, two-display Duo path),
iPhone19,4 / iOS 27.1 24A94425, with the simulator probes run in the guest
through tools/vm-probe.zsh (VM versions probes/vm-*.lldb; why they are
needed is in vm-notes.md). Each cell gives the VM value, then match,
differs or n/a. Rows that were marked VM differs before the column
was filled say whether the measurement confirmed or corrected that note.
Method, step list and caveats: vm-notes.md. VM data: vm-*.json, raw
transcripts raw/vm/steps/<step>/.
On 2026-10-30 the rows the duo-sim-align fix can affect were measured again on
duobase-01 with bundle 2.14.0-local.9064efca (branch duo-sim-align:
V68 product-id, /product/display0+display1 panel nodes, CoreMotion's
device-state relay fed through VPhone Host Controls). The pose now reaches
SpringBoard through CoreMotion, not through the test-automation override.
Those cells give the new value; where it changed, "(was: …)" holds the first
pass. Rows not named in "Changes since the first VM pass" were not re-measured
unless their cell says so. Records: the vm-*.json records with
"bundle": "2.14.0-local.9064efca" and step fx-<label>; transcripts
raw/vm/steps/fx-<label>/; method and the two incidents of this pass in
vm-notes.md ("2026-10-30").
Diff summary
Remaining differs rows, most consequential first (state after the 2026-10-30 pass). Struck items are aligned now.
- Auto-lock / AOD. The VM has no always-on display (
DeviceSupportsAlwaysOnDisplayNO,BLSHBacklightHost deviceSupportsAlwaysOnNO). Auto-lock in open turns the inner fully off (backlight 4) instead of AOD (3); folding while auto-locked gives FullyClosed with the cover primary on the lock screen but off (4), inner off. The old note "VM lights the folded inner display" did not reproduce: the inner stayed off and blanked. - Inner display identity (not changed by the fix; another session owns the names). CADisplay
VPhone Duo Inner/VPhone Duo Inner/ displayId 7 (simLCD-1/primary-1/ 3); FBS identityUnknown[7](simUnknown.main[3]), not UIKitMainLike;UIScreen._isEmbeddedScreenNO; UIScreen display corner radius 0, sRGB. Re-read on 2026-10-30: unchanged. - Inner display mode. Now 2007×2853 @3 like the sim (was: native 2853×2007 at pointScale 1), but 120 Hz (sim 60 Hz), sRGB (sim P3), and FBS/UIScreen still list a second mode, 2853×2007 (951×669 @3). The cover runs 120 Hz (sim 60 Hz).
- MobileGestalt identity.
ModelNumberVM0001 (sim A3447),RegulatoryModelNumbernil,HWModelStrV68AP (sim iPhone19,4), AOD keys NO.: aligned (item 5 of "Changes").DisplayExtendedPropertiesnil, logical display count 1 - Display power model (not re-measured beyond the posture rows;
stateControlstill nil). NoCADisplayStateControlon any CADisplay. The coverLCDis the one real panel (the composited output) and is never blanked while the guest is awake, also in book/open; the inner window-server display is enabled when unfolded and blanked when closed. The sim blanks the cover when open. - Digitizer (not re-measured). One
Virtual USB Touch Screen(USB, builtIn) asmainDisplayDigitizerService, re-routed to the inner UUID while unfolded; the sim has one CoreDevice touchscreen per panel. - Resolver transition style at a SpringBoard start. 2
.continuousLiveright after a SpringBoard start in closed (sim 1.fadeuntil the first swap). After a swap it now matches: 2 in every posture, 3 with Safari in front (was: 0 at start, then 1, 2 or 3 by path). - Per-panel pose orientation when closed. Device landscapeRight (4) gives cover 4 and landscapeLeft (3) cover 3, now computed by CoreMotion (
cmMagicPosecover 4 / 3); the sim gives cover 3 / 4. CoreMotion's own table (identical in the sim) maps a closed hinge to the cover unchanged, so the sim's value comes from its synthetic swap-tool pose. Open matches. - Cover corner radii.
extendedPropertiesand MobileGestaltDisplayExtendedPropertiessay [5,5,59,59] (Apple's device tree); the sim's device type says [8,8,59,59]. Everything else in both dictionaries matches. - Pixel density. Both panels 460×460 ppi (was: inner 0 / nil); the sim reads 316×669 (cover) and 324×654 (inner). The physical sizes are the sim's (3.0391×4.4217 and 4.3630×6.2022 in) with width and height swapped; the sim's ppi is the native pixel size divided by those swapped axes.
- Book angle, residual. 99.444° (position 0.552, closed region 0→0.2747, toClosed 0.5525→0.03) against the sim's synthetic 100° (0.556, 0→0.2761, 0.5556→0.03) (was: 90°, 0.500, 0→0.25). The host controls send 100 and the provider's mechanical angle is 100; CoreMotion's angle is 99.444 (= 100 × 179/180). Not investigated further.
- Auto-lock default. The VM runs the real Auto-Lock (60 s; timer warn 40 s, total 60 s); the sim holds the
SBDisableAutoDimassertion. Configuration, not behaviour.
Aligned or reclassified by the 2026-10-30 pass (details in the next section):
CoreMotion is absent; inner ;
extendedProperties carry only DeviceSurfaceTypeMobileGestalt ;
DisplayExtendedProperties nil / display count 1hinge HID: one unnamed 0xFF0C/0x21 service; book at 90°;
inner portrait-shaped ; statusBarFrame 0-recttransition style 1/2/3 by
path after a swap; lock-screen clock height: personalization (the VM's
lock screen uses another poster, v68.colorB, with a taller adaptive time;
see "System chrome").
Corrected notes: the VM does turn the cover landscape for Safari (678×466,
C/C, statusBarFrame 0×0, like the sim); the CoreMotion tabletop and A=7
table rows match (they are CoreMotion's own class methods, not
FoldDisplay); the folded inner does not light after auto-lock.
Changes since the first VM pass
Bundle 2.14.0-local.21dc0c06 → 2.14.0-local.9064efca, same VM, same iOS.
Row 8's refresh rate comes from upstream's "run the inner display at the panel's 120 Hz" (in this branch), not from the alignment change.
Data files
These files were deleted on 2026-10-30, after the values worth keeping were
moved into this table, the domain notes and
Research/Guest/iphone_duo_simulator_reference.md. Rerunning the probes
recreates them (README.md).
Every record has api, kind, process, posture, orientation, call, value, error.
posture includes the path, e.g. open(after-closed), because many values
depend on history. Display UUIDs change on every boot, so join on name or identity.
Posture and policy
Content mode: 1 disabled, 2 primary, 3 auxiliary. The CA display state is
1 / 0 when closed and 0 / 1 when open, and both panels keep power state 1.
Book and open are identical across the display stack. They differ only in
the scene region innerCover (active in book only) and in the hinge state.
VM: the same history paths (after-open, after-closed, after-book, after a
SpringBoard start) give the same rows. There is no CADisplayStateControl on
the VM; the window server shows cover LCD enabled and unblanked in every
awake posture and the inner enabled when unfolded, blanked when closed
(differs, Diff summary 5). Book and open differ only in innerCover and
the hinge state on the VM too.
2026-10-30: one exception seen once, outside the measured steps. After an
unplanned SpringBoard restart had dropped the idle-timer assertion, the guest
auto-locked in closed; an unfold then woke it to the lock screen and the
resolver's prevailing policy read Yoink(inner) instead of FoldingDual in
open and in the following book (raw/vm/steps/discarded/fx-*-sb1064-autolock-on).
With the screen kept lit the same paths give FoldingDual. The sim has no
reference for an unfold from a dark, locked cover.
Display identity
CAWindowServer lists five displays: LCD, TVOut, LCD-1, Wireless, Resizable.
VM: seven, LCD, Wireless, Wireless-1…Wireless-4, VPhone Duo Inner (no TVOut, no Resizable).
Orientation
History-dependent values
Hinge, pose and identity
What an app sees
Migration moves the existing scene: same UIWindowScene, same persistent
identifier, foregroundActive throughout, with no lifecycle callbacks.
- Unfold: hinge 2, then about 110 ms later
UIScreenDidConnect→ onedidUpdateEffectiveGeometry:→ trait C→R. - Fold: hinge 1, then about 70 ms later trait R→C → geometry →
UIScreenDidDisconnect.
VM: the callback sequence was not measured (it needs VPAppKitProbe). In the
app the inner screen's identity is Unknown.main[7] and its _name is
VPhone Duo Inner.
System chrome (points)
Quick action glyph: button 84, icon area 48 (insets 18), glyph view 27×25,
image 19.33×18. Glyph/button is 0.321 × 0.298. The sim hides the quick action
buttons and shows the placeholder symbol questionmark.app, so this does not
measure the flashlight or camera glyph. The VM's 0.68 glyph scale has no
direct sim reference.
Power and auto-lock
Limits
- The sim fold does not go through HID or CoreMotion, so the VM's
HID → CoreMotion → pose provider path has no reference. Only values from
SBFDevicePoseProvideronward compare. - Values with
sim_note(host Mac model, memory, CPU,IsSimulator, theSIMULATOR_*environment) do not exist on the VM. posture.zsh's 3 s readback during a 180° inner rotation once crashed SpringBoard mid-animation (_SBSystemApertureContainerViewRotatingContentView setTransform:). Use a longer settle for rotations.- Known harness defects, worked around but not fixed in
tools/:POSTURE_OUTdefaults to the sharedraw/posture.smoke.zshlabels interface orientations 3 and 4 with device-orientation names.posture.zsh unlockreleases the testing lock, not the device lock screen.sim.zsh pidfails while lldb is attached.
- VM side: see
vm-notes.mdfor the lldb traps (EXC_GUARD from more than one castobjc_msgSendper expression, garbagestrcmp/strncmp, unlowered PAuth_LR code) and the getters skipped on the VM. - 2026-10-30, bundle 2.14.0-local.9064efca: do not run
probes/vm-sensors-backboardd.lldb(anIOHIDServiceCopyPropertywalk from backboardd's main thread). With the CoreMotion relay present it was interrupted and left the relay wedged until locationd was restarted, which restarted backboardd and SpringBoard too. Read the service list with vphoned'sdevice.input_devicesinstead (vm-notes.md, "Incident 1").