From a5896f08839a55887784dcd805f272fd7c5f3d9d Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Fri, 31 Jul 2026 10:12:56 +0200 Subject: [PATCH] =?UTF-8?q?feat(android):=20the=20phase-lock=20ACK=20is=20?= =?UTF-8?q?logged=20=E2=80=94=20the=20closed=20loop=20reads=20out=20in=20l?= =?UTF-8?q?ogcat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The host's applied hold rides the 0xCF tail but nothing client-side showed it; 'adb logcat -s pf.phase' now logs transitions. This line is what exposed the dead-median controller orbit on the first on-glass run. Co-Authored-By: Claude Fable 5 --- clients/android/native/src/decode/async_loop.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/clients/android/native/src/decode/async_loop.rs b/clients/android/native/src/decode/async_loop.rs index 917bf3ff..796e4570 100644 --- a/clients/android/native/src/decode/async_loop.rs +++ b/clients/android/native/src/decode/async_loop.rs @@ -542,6 +542,9 @@ fn feeder_loop( ) { // Received AUs awaiting their 0xCF host timing (Phase-2 split), as (pts_ns, capture→received µs). let mut pending_split: VecDeque<(u64, u64)> = VecDeque::new(); + // Last logged phase-lock ACK (the host's applied capture hold, from the 0xCF tail) — logged + // on change so `adb logcat -s pf.phase` shows the closed loop working (or not) at a glance. + let mut last_phase_ack: Option = None; while !shutdown.load(Ordering::Relaxed) { match client.next_frame(Duration::from_millis(5)) { Ok(frame) => { @@ -584,6 +587,17 @@ fn feeder_loop( } } while let Ok(t) = client.next_host_timing(Duration::ZERO) { + // Phase-lock closed-loop readout: the host's applied hold rides the + // 0xCF tail; log transitions (~1 Hz worst case — the host updates it + // once a second). None = a host without the tail (pre-phase-lock). + if t.applied_phase_ns != last_phase_ack { + log::info!( + target: "pf.phase", + "host applied_phase={:?}us", + t.applied_phase_ns.map(|n| n / 1000) + ); + last_phase_ack = t.applied_phase_ns; + } if let Some(i) = pending_split.iter().position(|&(p, _)| p == t.pts_ns) { let (_, hostnet_us) = pending_split.remove(i).unwrap();