Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
4300907
add USB HID touchscreen digitizer backend
May 1, 2026
7823c93
add temporary PicPhone touchscreen UI routing
May 1, 2026
b0cf662
Expose touchscreen HID as Android direct touch digitizer
May 2, 2026
74da49a
PicPhone: default to touchscreen HID routing
May 3, 2026
0b52fca
PicPhone: fix phone controller touchscreen dragging
May 3, 2026
fb0f1a8
PicPhone: preserve no-bars aligned controller LKG
May 3, 2026
0c8cac3
PicPhone LKGS remove stray nav overlay
May 6, 2026
a34815d
Enable Android compact controller layout
May 6, 2026
c6b11b6
Add Android compact controls overlay
May 6, 2026
99f5046
Add Android display wake action
May 6, 2026
76fe8de
Toggle Android display from compact overlay
May 6, 2026
42ab055
Add Android display toggle to desktop viewer
May 6, 2026
e5256cc
Add logout to Android compact controls
May 6, 2026
9c46147
Add authoritative Android native login
May 6, 2026
217007a
Collapse OSK after native login Autofill
May 6, 2026
f57a82c
Add companion app permission cleanup
May 7, 2026
346ef8a
Route Android wheel scroll through relative HID
May 7, 2026
45e478b
Use Android IME from compact controls
May 7, 2026
e23cd8b
Document Android support fork
May 7, 2026
8df4365
Explain Android target companion
May 7, 2026
8d0f80d
Refresh Android APK README release links
May 7, 2026
58c5c8d
Clarify companion keyguard dismissal behavior
May 7, 2026
f6c3a90
Document credential bouncer keyguard flow
May 7, 2026
1d5b800
Add explicit Android input modes
May 10, 2026
205aca9
Add companion target metadata reporting
May 10, 2026
334271e
Allow companion URL setup by intent
May 10, 2026
33affde
Allow companion service URL setup by intent
May 10, 2026
179ee63
Keep Android target metadata active during screen off
May 10, 2026
75011b3
Lock touchscreen HID reports
May 10, 2026
67d96f1
Improve Android companion target support
May 11, 2026
3253abf
Document companion cherry-pick follow-up
May 11, 2026
66b2e4c
Update companion release link to 1.6
May 12, 2026
271e88e
Document Android support work in progress
May 12, 2026
b3af658
Document local JetKVM baseline artifact policy
May 12, 2026
849f897
Add WIP progress notes
May 12, 2026
9a51c19
Guard local JetKVM baseline installs
May 12, 2026
31c24ce
Avoid companion presentation pulse on settings open
May 12, 2026
0c90a40
Add authenticated Android companion pairing
May 14, 2026
18b18db
Document authenticated companion leases
May 14, 2026
3846bf3
Remove local deployment note from README
May 13, 2026
b792b73
Update Android artifact release links
May 14, 2026
f625790
Bump Android APK artifact versions
May 14, 2026
10c945f
Refine companion pairing settings UI
May 14, 2026
442f303
Treat missing remote pairing as unpaired
May 14, 2026
d5055e6
Authenticate companion declarations with signatures
May 14, 2026
cce311a
Refine companion lease confirmation state
May 15, 2026
d17ff02
Handle stale companion endpoints on unpair
May 18, 2026
e5f65e6
Experiment with HID RPC digitizer reports
May 28, 2026
5f44cde
Report companion target only to connected JetKVM
May 29, 2026
91ee22a
Add companion-driven dynamic display mode
May 29, 2026
b0c6ab4
Checkpoint dynamic display HID mapping
May 29, 2026
cca2ffa
Remove local experiment-specific defaults
May 29, 2026
5644797
Restore default EDID when Android target is inactive
May 29, 2026
b5cef33
Expire stale companion display targets
May 29, 2026
79cf235
Reboot after display EDID transitions
May 29, 2026
f4ca83c
Avoid reboot loop before companion target is fresh
May 29, 2026
4c02eb9
Address current Bugbot findings
May 30, 2026
34b3833
Stop rebooting for HDMI EDID changes
Jun 2, 2026
0dd4ec8
Add HDMI reconnect crop fallback
Jun 2, 2026
a3509ff
Improve companion status notifications and pairing UI
Jun 2, 2026
809bf5e
Allow companion status text selection
Jun 2, 2026
7b48192
Add companion status controls to web UI
Jun 2, 2026
771f711
Polish companion status UI
Jun 2, 2026
d3f0fd7
Stabilize companion status controls
Jun 2, 2026
7d5aa74
Collapse companion status lists
Jun 2, 2026
8d35991
Hide non-pairable companion addresses
Jun 2, 2026
2ec4edc
Confirm companion unpair all
Jun 2, 2026
3769692
Polish companion list controls
Jun 2, 2026
987b466
Polish companion disclosure controls
Jun 2, 2026
5dd55d1
Adjust companion list button sizing
Jun 2, 2026
57dd902
Adjust companion IP action buttons
Jun 2, 2026
c1d63db
Keep HDMI EDID stable when unpairing companion
Jun 2, 2026
98ddcca
Synchronize companion unpair state
Jun 2, 2026
496a3ff
Restore default EDID when companion lease is absent
Jun 2, 2026
66ca933
Fix backend-initiated companion pairing
Jun 3, 2026
2360679
Fix WebRTCVideo duplicate import after rebase
Jun 5, 2026
7fd2aa9
Resolve shared HID slot for touchscreen gadget
Jun 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 223 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,226 @@
# JetKVM Android Support Fork

> [!NOTE]
> This Android support fork is work in progress. The current branch is usable
> for local testing, but it is still being refined through real device testing.
> Bug reports, focused review, and help with Android target/controller edge
> cases are welcome.

This fork adds an Android-focused control path to JetKVM. It is built for the
case where the JetKVM target is an Android device and the operator wants the
same practical control surface that a physical touchscreen, keyboard, and mouse
would provide.

The current branch is based on a validated known-good touchscreen and aspect
baseline. The important baseline properties are:

- Android digitizer input is routed through USB HID touchscreen emulation.
- Touch coordinates are aligned with the captured video and feel smooth in use.
- The Android target aspect ratio is preserved for the phone controller view.
- Desktop JetKVM usability remains available for non-Android workflows.

## What This Fork Adds

- **Android USB touchscreen target support** - JetKVM can expose a direct-touch
HID digitizer path for Android targets instead of treating touch as generic
mouse input.
- **Android controller APK** - A native Android wrapper for operating JetKVM
from a phone. It supplies the Android-specific login flow, immersive view,
native OSK integration, and compact controller defaults.
- **Compact controller mode** - The phone controller gets a reduced UI without
the desktop chrome and button strip. Android-only controls are placed in a
draggable floating menu.
- **Floating control overlay** - The overlay includes target actions such as
paste text, virtual media, Wake-on-LAN, virtual keyboard, display toggle,
logout, settings, and connection tools while preserving the video surface for
touch input.
- **Native Android login activity** - The controller APK owns the login
experience instead of relying on the vanilla web auth page. This keeps
password managers and Autofill useful on the controller phone.
- **Android OSK bridge** - In the controller APK, the compact virtual keyboard
action opens Android's own input method and forwards committed text through
JetKVM's existing HID keyboard macro path. Desktop browsers still use the
regular web virtual keyboard.
- **Display toggle for Android targets** - The UI can send a harmless HID key
event to wake the display, or the Android display power shortcut when
available.
- **Relative HID wheel scrolling** - Mouse wheel input is routed through the
relative HID mouse path when Android exposes one, preserving touchscreen
alignment while restoring useful wheel behavior.
- **Android target companion APK** - A small target-side helper runs on the
Android phone being controlled. It handles the Android keyguard edge cases
that USB HID input alone cannot solve, without using root, ADB, Accessibility,
Shizuku, or screen capture.

## How It Works

The backend keeps JetKVM's normal video, WebRTC, keyboard, virtual media, and
device-management paths. Android-specific input is layered on top where it is
needed:

1. The JetKVM device exposes HID endpoints suitable for an Android target.
2. Touchscreen events from the viewer are mapped to the captured Android frame
and sent through the absolute HID digitizer path.
3. Wheel events use the relative mouse HID path when present, because Android
handles wheel scrolling differently from direct touchscreen gestures.
4. The Android controller APK identifies itself to the backend by opening the
controller URL with Android compact-mode parameters.
5. The controller APK replaces the web auth page with a native login activity
so Autofill and Android keyboard behavior work naturally.
6. The compact overlay keeps Android-only actions close to the controller view
without polluting the desktop JetKVM interface.
7. The companion APK pairs with trusted JetKVM devices, watches Android's own
view of the paired JetKVM USB/display identity, and grants the backend a
short Android target lease only while that physical evidence is present.

## Why This Exists

Vanilla JetKVM is designed as a general KVM over IP. Android targets are
different enough that the generic desktop assumptions are not enough:

- Android distinguishes direct touchscreen input from mouse input.
- A phone-shaped captured display needs strict aspect handling or touches drift.
- Android lockscreen behavior has policy boundaries that generic HID input
cannot always cross cleanly.
- A phone controller needs a different UI density from the desktop browser UI.
- Android users expect Autofill, the native OSK, and immersive full-screen app
behavior instead of a desktop-style login form.

This fork keeps those Android-specific decisions explicit. The goal is not to
replace JetKVM's normal UI; it is to add a focused Android target/controller
path while leaving the vanilla experience recognizable.

## Target Companion

The companion APK is installed on the Android target, not on the controller
phone. Its job is narrow: make JetKVM-controlled Android targets recover
cleanly from display wake and soft keyguard states while keeping the trust and
presence boundary on the target device.

JetKVM can send touchscreen, keyboard, mouse, wheel, and display-toggle input
over USB HID. That is enough once Android is interactive. The lockscreen is the
exception. On stock Android, secondary-display keyguard behavior is governed by
Android multi-display policy, and the external display shown through JetKVM may
not be allowed to dismiss a trusted keyguard purely from the external USB
digitizer. That is an Android policy boundary, not a broken touch coordinate
path.

The companion uses public Android APIs and an authenticated pairing flow to
bridge that boundary:

- Pairing establishes trust between the Android companion and one or more
JetKVM endpoints. The backend rejects companion target declarations unless
they authenticate with a paired companion token.
- Each JetKVM exposes a stable per-device identity through the USB gadget
serial/product strings and through the default EDID monitor name/serial. On
Android this appears in input devices such as `JetKVM USB Emulation Device
<short id>` and in the external display name as `JKVM <short id>`.
- The companion stores the paired JetKVM endpoint, paired token, and expected
JetKVM identity.
- Its foreground service reflects state: before pairing it waits for a device
to be paired, after pairing it waits for matching peripherals, and once
physical evidence is present it monitors display-on events.
- Presence is OR-based. Matching keyboard, digitizer/touchscreen, mouse/pointer,
or monitor evidence is enough to activate the companion path.
- While matching evidence remains visible to Android, the companion refreshes an
authenticated Android target lease to the paired JetKVM. The lease reports the
JetKVM identity, Android target type, preferred digitizer mode, display
dimensions/aspect, and the evidence list. Disconnection is reported
immediately when evidence disappears; lease expiry is the backend fallback for
companion crashes or network loss.
- When the target wakes, it launches a transparent `showWhenLocked` activity and
calls `KeyguardManager.requestDismissKeyguard()`. Android decides whether the
keyguard can be dismissed.
- Around display-on events, the companion briefly creates a transparent 1x1
`Presentation` on the JetKVM external display to keep that display path awake
without dimming or presenting UI.
- It can optionally use Android's overlay permission as a non-touchable launch
assist so background wake-unlock remains reliable after the display turns on.

What it deliberately does not do:

- It does not inject input.
- It does not capture or read the screen.
- It does not use ADB.
- It does not require root, Shizuku, Accessibility, device-owner privileges, or
OEM-only APIs.
- It does not accept generic USB or generic display metadata as proof. Evidence
must match the paired JetKVM identity before Android mode is granted.

The recommended mode is normal Android keyguard with the companion foreground
service installed, notification permission granted where Android requires it,
unrestricted battery enabled for reliability, at least one JetKVM paired, and
launch-on-boot enabled if the target should recover after reboots. A trusted
state such as Extend Unlock can make wake recovery automatic. Without a trusted
state, the companion can still bring up Android's credential bouncer after wake;
the user can then enter the PIN or password through JetKVM keyboard input or the
Android controller's OSK bridge.

## Current Validation State

The current support branch has been locally validated with:

- Android digitizer touch input.
- Correct phone-controller aspect and crop behavior.
- Desktop viewer behavior preserved.
- Compact overlay actions.
- Display wake/toggle actions.
- Native Android login and logout flow.
- Autofill password entry with OSK collapse handling.
- Companion app permission UI cleanup.
- Relative HID mouse wheel scrolling.
- Controller APK Android OSK text forwarding.
- Authenticated companion pairing and Android lease renewal.
- JetKVM identity binding through USB gadget strings and EDID display identity.
- Companion activation from matching keyboard, digitizer, mouse, or monitor
evidence.

Non-trivial changes to this fork should be built, deployed, and tested on the
JetKVM device plus the controller/target phones before being committed or
published.

## Components

- `jetkvm-android/` - Android controller APK.
- `jetkvm-companion/` - Android target companion APK.
- `ui/src/components/AndroidCompactControls.tsx` - compact Android controller
overlay.
- Backend HID/RPC changes live in the normal JetKVM backend tree.

## Build Notes

Build the JetKVM backend and device UI:

```bash
make build_dev
```

Build the Android controller APK:

```bash
./jetkvm-android/build.sh release
```

Build the Android companion APK:

```bash
./jetkvm-companion/build.sh release
```

Install APKs with ADB as usual:

```bash
adb install -r jetkvm-android/build/JetKVM-release.apk
adb install -r jetkvm-companion/build/JetKVM-Companion-release.apk
```

## Upstream README

The section below is the vanilla upstream JetKVM README, kept intact for
project context.

---

<div align="center">
<img alt="JetKVM logo" src="https://jetkvm.com/logo-blue.png" height="28">

Expand Down
Loading
Loading