Hacked and debloated an Echo Dot 2 (local LLM + local Speech recognition)
Code and instructions available here: https://github.com/albertoZurini/echo-dot-2-playground
Hello there!
After a few days of playing around, with a lot of help from Gemini and GPT, I was able to successfully debloat an Echo Dot 2 from most of Amazon's services and let it run speech to text locally with Sherpa-ONNX and a small LLM through llama.cpp.
The first step was rooting it by following the procedure on XDA. There is a link to the XDA thread in the GitHub repo along with a step-by-step guide for the rest of the setup. Once I had root access I pulled the APKs of some of the system applications, especially SpeechInteractionManager which contains the wake word and speech interaction code, plus the native audio and wake word libraries it loads.
At first I wanted to do something similar to what the Wyoming team did, which was intercepting the wake word from FireOS services through logcat. That worked as a quick proof of concept but it gave me a lot of limitations. The Amazon speech service would still be running in the background and would still own parts of the audio pipeline. Volume handling was also not just a normal Android volume-key event. The FireOS services receive the hardware button events, change the audio stream volume and control the LED ring feedback. This meant that even if I reacted to the wake word from logcat, I was still relying on a large part of Amazon's stack underneath.
That is why I decided to do a more complete reverse engineering pass. The APK included native `.so` libraries such as `libwakewordmanager.so`, `libwakewordmanageraudiostream.so` and the newer `libwakewordserver_jni.so`. Some of the older libraries turned out to be compatibility stubs on this firmware. The useful path was the newer native wake word server, which loads Pryon and creates the native audio recorder. I also decompiled the Java code around `AudioStreamProviderService`, `AudioRecordStrategy` and `NativeWakeWordServiceCore` to understand how the pieces connect.
The main reason for doing the full reverse was to understand how these apps connect to the hardware and communicate with each other. It turns out there are two separate pieces that matter: one service for the native wake word detector and another service for speech processing and the rest of the assistant. I ended up running my own wake word service alongside my custom assistant. They communicate through an explicit Android service intent. Logcat is only used for diagnostics now.
I had done some prior research and saw that with 512 MB of RAM and a theoretical maximum memory bandwidth of about 5 GB/s this device might be able to run small LLMs locally. It turns out it can. The original TinyStories 28M model was not directly usable with llama.cpp because of its architecture, so I used an architecturally equivalent 25M LLaMA2 TinyStories model in GGUF format. Through llama.cpp it reaches around 7 tokens per second during prefill and around 4 tokens per second during decoding. This is roughly the kind of model that has also been used in ESP32 experiments.
I also tried the larger `MobileLLM-125M-Q4_K_M.gguf` model but prefill plus generation took around 20 seconds which is too slow for this device. Even with the smaller model I was able to trigger some simple tools by voice, for example turning on the light or playing a sound.
When the wake word is detected I can stop the detector process while the assistant is processing the request to save CPU. The detector uses around 20% CPU when it is active. This would have been much harder to control cleanly if I had kept the original FireOS speech services running.
I am also able to intercept all the hardware buttons. I assigned playing a sample WAV file to the action button. The volume keys change the music stream volume, play a tone and show visual feedback using the LEDs. The mute button works through the hardware microphone mute integration as well.
There is still a lot to improve, especially around making the assistant more useful and reducing the startup and response time, but it is pretty interesting to see this little device running an entirely local voice pipeline after removing most of the original services. I also want to try running openWakeWord/Porcupine to see if they'd be using less CPU than the stock Amazon's library.
The code and the reverse engineering notes are here: https://github.com/albertoZurini/echo-dot-2-playground
I would be interested to hear if anyone has tried something similar with other Echo devices or with the older FireOS speech components.