Back to blogs
androidopen-sourceperformance

cleanOS - An Apple TV-Style Home Screen for Slow Android TVs

My 1 GB Android TV spent 187 MB of memory just showing me ads. Here's how I measured it, switched off the bloat and replaced the home screen with a 1 MB Apple TV-style launcher that runs at 60 fps and boots straight into Home, and what each step taught me.

7 min read
cleanOS - An Apple TV-Style Home Screen for Slow Android TVs
The finished home screen, captured on the TV itself. The selected tile lifts out of the frosted-glass dock and its name fades in underneath.

My Android TV has 1 GB of RAM, and it felt like it. Everything was laggy, from opening apps to moving around the home screen. Instead of buying a new TV, I spent two days finding out why it was slow and rebuilding the part that was slowing it down.

No root, no cable, nothing permanently deleted. Here's exactly how I did it, step by step, and what each step taught me.

The Short Version

  • The stock home screen alone used 187 MB of memory. My replacement uses 59 MB.
  • Apps got 100 MB more free memory to work with.
  • Home appears about 7 seconds sooner after the TV is switched on.
  • Moving through the dock went from 34 ms per frame (about 30 fps) to 5 ms, with zero janky frames.
  • The whole launcher is about 1 MB, written in plain Java with no libraries, and it's open source.

Step 1: Measure Before Touching Anything

Android TVs have a developer mode, and on most of them it opens network ADB, the same debug bridge Android developers use with phones. Once it was on, my laptop could talk to the TV over Wi-Fi:

adb connect 192.168.1.50:5555
adb shell dumpsys meminfo        # who is using the memory
adb shell pm list packages -s    # every app the manufacturer installed

Those few commands told me most of what I needed to know:

  • The stock home screen was using about a fifth of the TV's memory, mostly to show promoted rows and posters.
  • A content-recognition service was analysing what was on screen.
  • A vendor app store, two silent installers, two firmware updaters, a FAST channels app and an Alexa integration were all running on a TV where nobody used them.

Takeaway: the hardware wasn't the real problem. Before you replace a slow device, find out what's actually using it.

Step 2: Turn Off the Bloat, Reversibly

Android lets you switch an app off for a user without root (pm disable-user), and switch it back on later. Nothing is deleted. I used that for 22 apps and removed 2 more for my user only, which is also reversible.

Three rules kept it safe:

  1. Back up first. Save the list of enabled apps, the current home app and the screensaver before changing anything.
  2. Work in batches of five, so if something breaks, the culprit is easy to find.
  3. Never touch the TV's core parts. Anything that runs the picture, the HDMI inputs, the tuner, setup or the factory services stays on.

Takeaway: people will only try something on their TV if they can take it back. Build the undo button before the feature.

Step 3: Replace the Home Screen

The stock launcher was the biggest single consumer, so I wrote my own. The project ended up with two halves: a small command-line tool on my laptop that drives the TV over ADB, and a native launcher on the TV.

High-level design. The command-line tool inspects, debloats and sets up the TV; the launcher does one job with as little work per frame as possible.

The launcher, cleanOS Home, is plain Java with plain Android views and no libraries. The design follows Apple TV: a full-screen wallpaper, a greeting where Apple shows a show title, a status capsule for weather, Wi-Fi and the clock, and one frosted-glass dock. Selected tiles lift and shimmer, and apps zoom open out of their tile.

Two things surprised me here:

  • Android ignored my choice of home screen. The stock launcher is a system app with a higher priority, so the system kept picking it. It only gave way once the stock launcher was disabled, and my install script now checks that the new home works before doing that.
  • The TV shipped with app transitions turned off, which is why apps snapped open and shut. A short transition, plus the tile zoom, made it feel far smoother at almost no cost.

Takeaway: a home screen is just an app with the right intent filter. The hard part is earning the right to replace the stock one safely.

Step 4: Make a Weak GPU Feel Fast

My first Apple TV-style dock looked right and felt wrong. Android's frame stats (dumpsys gfxinfo) showed a median frame of 34 ms and 14.5% janky frames. Every frame redrew a full-screen photo, two gradients, a clipped glass panel and six clipped, shadowed tiles, which was too much for a TV graphics chip.

The fix was one rule: if it doesn't change, render it once.

Low-level design of the render pipeline. The left side runs once, off the main thread; the right side is all the GPU does per frame.
  • The wallpaper became the window background, cropped to the TV's exact resolution with its shading baked in. Android draws it as one 1:1 bitmap copy.
  • The frosted glass is fake. A blurred copy of the wallpaper is made once and cut to the dock's shape. There's no live blur.
  • Rounded corners are baked into each tile. This GPU clips rounded shapes without anti-aliasing, so live clipping gave jagged corners.
  • Focus only changes scale, elevation and transparency, which the GPU animates without redrawing anything.

The result on the same screen: a 5 ms median frame, 2 ms of GPU time and zero janky frames out of 189.

Takeaway: on weak hardware, the fastest frame is the one with nothing left to compute. Move every expensive effect out of the frame loop.

Step 5: Boot Straight Into Home

This TV fully restarts every time it's switched on. The boot log showed that after Android finished starting, the screen sat on a blank placeholder for 6.4 seconds. That's Android waiting to unlock the user's encrypted storage, and normal apps can't start until it's done.

Android does allow a home screen to keep its data in device-protected storage, which is available from the very start. Moving the settings, wallpaper cache and tile art there let Android open my launcher the moment the screen turned on.

Boot sequence, measured on one clock. The first 44 seconds belong to the hardware and firmware; the blank 6.4 seconds were removable.

Other apps still can't open in those first seconds, so instead of showing an error, the launcher remembers the tile you pressed and opens it as soon as Android is ready.

Takeaway: read the boot log. The slow part is often a wait, not work, and waits can sometimes be skipped.

Step 6: Verify on the Real Screen

I checked every change with a screenshot taken on the TV, and that's where most bugs showed up: a clock cut in half, a cropped Play Store logo, tiles hidden under the glass, jagged corners, and flat bands on gradient banners. None of them were obvious in the code. The screensaver, a slow pan across the wallpaper with a clock that shifts every minute to avoid burn-in, went through the same loop.

The cleanOS Clock screensaver, captured on the TV.

Takeaway: test on the real device. A TV GPU, a TV-sized interface and a remote control behave nothing like an emulator.

The Results

Everything below was measured on the TV with Android's own tools.

MetricBeforeAfter
Home screen memory187 MB59 MB
Memory free at Home237 MB337 MB
Home on screen after power-onabout 50.8 sabout 44 s
Median frame time34 ms (first draft)5 ms
Janky frames14.5% (first draft)0%
Factory apps switched off024 (22 disabled, 2 removed)

Not everything worked. I wanted every app except one to close when you return Home, but Android 14 doesn't let an ordinary app close other apps. Android already freezes background apps and reclaims their memory when it needs it, so I left that to the system.

Try It on Your TV

I rebuilt the project as cleanOS, a general version for any Android TV. Nothing personal is built in: you set your own name, city, apps and wallpaper, and a scan command finds the bloat your brand ships with.

python3 tools/cleanos.py --tv 192.168.1.50 probe
python3 tools/cleanos.py scan --write lists/my-tv.txt
python3 tools/cleanos.py debloat lists/my-tv.txt --yes
python3 tools/cleanos.py install
python3 tools/cleanos.py config --name "Sam" --city "Lisbon"

Every step takes a backup first, and restore puts the TV back exactly as it was.

Key Takeaways

  1. Measure first. Five minutes with dumpsys meminfo changed the whole plan.
  2. Make it reversible. Undo is what makes people willing to try.
  3. Precompute on weak hardware. Blur, shading, corners and shadows don't belong in the frame loop.
  4. Read the boot log. The 7 seconds I saved were spent waiting, not working.
  5. Trust the screen, not the code. The real device finds the bugs.

If your TV feels slow, it probably isn't the hardware.

Keep reading