Merge PR #1476: docs: G09 note: app buttons and held-volume repeat at once, with a getevent listener you start by hand

This commit is contained in:
Gathin23 committed 2026-10-26 22:35:59 +05:30
commit c8c1ae8350
1 file changed
+68
+68
View File
@@ -214,9 +214,77 @@ for, and with 800 set that action still fired 400 ms after the down, before and
survives. This is the only configuration that has both, and the price is the stock home screen the
cleanup was replacing.
- **Keep both with a listener you start by hand.** A script run by the `shell` user can answer the app
buttons without any service bound, so the ramp stays; see "Both at once" below. It does not come back
after a reboot, so it is started again each time.
It is a toggle, not a fix: two one-line `settings` writes switch between the two behaviours whenever
you want, but never both at once.
## Both at once: a listener you start by hand
A unit with the same product, `G09_4K_GB`, and the same build, `STT2.230203.001.AS23` (Android 12, security
patch 2025-09-05), and a Bluetooth remote that names itself `BT_RC813A_B4`, had the three app buttons and the
volume ramp together, with no accessibility service bound. That does not contradict the bisect above: it is
about services that filter keys, and this uses none. One owner, one unit, and the only checks were pressing
the real Netflix, Prime Video and YouTube buttons, holding volume up and down, and a day of ordinary use.
**What reads the buttons.** With `enabled_accessibility_services` empty and `accessibility_enabled 0` (the
control in the bisect), a script run by the `shell` user reads the remote's consumer-control input node with
`getevent` and starts an app when one of three keys goes down. The keys are the scancodes in the table above,
472, 473 and 569, which `getevent` prints as `0001 01d8`, `0001 01d9` and `0001 0239`. The node is found by
name, not by `/dev/input/event<N>`, as the [TROUBLESHOOTING](../TROUBLESHOOTING.md) section on remapping the
buttons without a key helper explains, along with the limit that a reader cannot consume a press. Here that
costs nothing visible only because these vendor keycodes reach nothing else once launcherx is disabled
(`KeyDownBehaviorReceiver` above); that is read from this note, not re-measured with the script.
**Keep it reading the right node.** The remote sleeps and reconnects, and each time the system recreates its
input node. A `getevent` still open on the old one (`ls -l /proc/<pid>/fd` shows `event9 (deleted)`) never
gets another event and never exits, so the buttons silently stop working until the script is restarted. This
showed up after about a day. The script below checks for it every three seconds and reopens the new node. It
is the script that ran, with its log lines dropped and its paths shortened:
```sh
#!/system/bin/sh
NAME='BT_RC813A_B4 Consumer Control' # the node's name in `getevent -p`
echo $$ > /data/local/tmp/keys.pid
find_dev() { getevent -p 2>/dev/null | grep -B1 "name: .*\"$NAME\"" | head -1 | sed 's/.*: //'; }
open_app() { am start -a android.intent.action.MAIN -c android.intent.category.LEANBACK_LAUNCHER -n "$1" >/dev/null 2>&1; }
while true; do
DEV=$(find_dev)
if [ -z "$DEV" ]; then sleep 5; continue; fi
(
getevent "$DEV" 2>/dev/null | while read -r line; do
case "$line" in
*"0001 01d8 00000001"*) open_app com.netflix.ninja/.MainActivity ;;
*"0001 01d9 00000001"*) open_app com.amazon.amazonvideo.livingroom/com.amazon.ignition.IgnitionActivity ;;
*"0001 0239 00000001"*) open_app com.google.android.youtube.tv/com.google.android.apps.youtube.tv.activity.ShellActivity ;;
esac
done
) &
sleep 1
while true; do
GP=$(pgrep -f "getevent $DEV" | head -1)
[ -z "$GP" ] && break
if ls -l /proc/$GP/fd 2>/dev/null | grep -q '(deleted)'; then kill $GP 2>/dev/null; break; fi
NOW=$(find_dev)
if [ -n "$NOW" ] && [ "$NOW" != "$DEV" ]; then kill $GP 2>/dev/null; break; fi
sleep 3
done
wait
sleep 2
done
```
**Start it by hand**, detached from the debugging session, or it dies with it, as the Streamer section does:
`setsid nohup sh /data/local/tmp/keys.sh > /dev/null 2>&1 < /dev/null &`. It does not come back after a
reboot; start it again the same way. The loop waits for the remote when it is not connected and reads again
when it comes back.
Not covered: the Gear button (that stays with a helper, and so with the lost repeat), the buttons the system
answers itself, starting it again after a reboot or power loss, standby, a second remote, and whether any
firmware other than this build lets the `shell` user read the remote's node.
## Limits
One unit, one firmware build (`STT2.230203.001.AS23`), one session. Only volume up/down was held: