0ad4e6eff7
Roll the pf-client-core slot pattern to the Android client (Kotlin + JNI): - New kit/GamepadRouter.kt: the Android analogue of the client-core Slot model — a deviceId→Slot map assigning each InputDevice a stable lowest-free wire pad index held for its lifetime, GamepadArrival(pref) before a pad's first input, GamepadRemove on onInputDeviceRemoved, per-slot AxisMapper + held-bitmask so two pads never clobber each other. The isForwardable gate (excludes DualSense/DS4 all-zero sensor sibling nodes) is centralized in slotFor so no entry point can open a phantom slot. - native/src/session/input.rs: JNI shims take a pad arg -> flags=pad (nativeSendGamepadButton/Axis, plus nativeSendGamepadArrival/Remove). - native/src/feedback.rs: pad carried in rumble bits 49..52 + a leading hidout pad byte; GamepadFeedback.kt routes rumble/lightbar/LED back to the originating device by pad via deviceForPad. - MainActivity.kt routes key/motion events by device; ControllersScreen.kt badges every forwarded pad (was hardcoded i==0), reading getControllerNumber. A lone controller lands on wire index 0, so its per-transition datagrams stay byte-identical to the old single-pad path. gradle :app:assembleDebug green (Rust cross-compiled via cargo-ndk); JNI signatures hand-verified 1:1. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>