Skip to content
← Writing2026-11-02 · android / debugging / lab

Why my projector's remote pressed every button four times

A boot profile over ADB, an accessibility service nobody asked for, and a 400 ms key-repeat timer. No root, every change reversible, and the launcher now appears in 10.3 s instead of 18.3 s.

My projector runs Android TV 11 on a locked bootloader. Two things bugged me. It took ages to become usable after power-on, and the remote “skipped”: one press on the d-pad would sometimes jump four items. Rooting wasn’t an option, so everything below is done over ADB and can be undone.

Profile before touching anything

I put together a boot timeline in seconds from kernel start. Everything up to the end of the boot animation (about 25 s) is vendor firmware I can’t touch. One service blocks for 5 seconds waiting for another that never starts. The part I could fix was the 18 seconds after the animation, when about 40 apps woke up on BOOT_COMPLETED and starved the CPU.

The four-press mystery

Android’s InputDispatcher auto-repeats a key if the key-up hasn’t arrived 400 ms after key-down, and then every 75 ms after that. At boot the system was so saturated, and key events passed through so many accessibility filters, that the key-up arrived about 600 ms late. One press plus three repeats makes four moves.

The surprise suspect was Switch Access. It was enabled as an accessibility service, added an extra key-event filter, and bound Google TTS, which burned 47 seconds of CPU in the first two minutes. Raising long_press_timeout doesn’t help on this firmware because the dispatcher stays at 400 ms (I tested it). The fix was to remove the service.

De-bloat, reversibly

  • Took Switch Access out of enabled_accessibility_services
  • Disabled 15 packages for the user (voice assistant, Chromecast, streaming apps I don’t use, TTS, demo apps)
  • Kept Netflix out of the background. It was using about 22 s of CPU on every boot without ever being opened
  • Saved the original settings to a file, with a revert.sh that undoes all of it

Results

Seconds after boot animation Stock Switch Access off + bloat disabled
Launcher visible 18.3 13.5 10.3
Keystone + focus done ~30 21.5 16.6

One more counter-intuitive finding: fully AOT-compiling the launcher made its cold start slower (0.75 s → 0.9 s), so I put it back. The lesson I keep relearning: measure, change one thing, measure again, and always keep an undo button.