From 6686b80ededb8b9876d70c0493ea9e46a0070c8a Mon Sep 17 00:00:00 2001 From: rope Date: Mon, 19 Oct 2026 13:26:28 +0100 Subject: [PATCH] tv-detox: keep Philips TV bloat off over adb Co-Authored-By: Claude Opus 5.5 --- common.nix | 1 + devices.toml | 6 ++ services/tv-detox.nix | 152 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 services/tv-detox.nix diff --git a/common.nix b/common.nix index ed68913..6a931a4 100644 --- a/common.nix +++ b/common.nix @@ -130,6 +130,7 @@ in ./services/guildhall-join.nix ./services/hardware-health.nix ./services/wan-watchdog.nix + ./services/tv-detox.nix ./services/deployment.nix ./services/valheim-autoupdate.nix ./services/owncast.nix diff --git a/devices.toml b/devices.toml index cb11f8a..b55385d 100644 --- a/devices.toml +++ b/devices.toml @@ -27,3 +27,9 @@ mac = "74:56:3c:42:9d:a3" name = "FredOS-Gaming" ip = "10.0.0.20" note = "Fixed so the server can `ssh gaming` (hosts/FredOS-Gaming.nix)." + +[[device]] +mac = "d8:13:99:dd:bf:09" +name = "philips-tv" +ip = "10.0.0.40" +note = "Fixed so services/tv-detox.nix can reach it over adb." diff --git a/services/tv-detox.nix b/services/tv-detox.nix new file mode 100644 index 0000000..3c275df --- /dev/null +++ b/services/tv-detox.nix @@ -0,0 +1,152 @@ +# services/tv-detox.nix — keep the Philips TV's bloat turned off. +# +# Oct 2026: the living-room Philips 58PUS7304 (Android TV 12) was cleaned up +# over adb: bloat turned off with `pm disable-user` (never uninstalled), and +# the tv-detox home screen (github.com/Ansub/tv-detox) replaced Google's +# launcher. Philips firmware switches some of those apps back on at every +# cold boot (the UK Freeview Play apps and DTS Play-Fi), and nothing on an +# unrooted TV can switch them off again by itself. +# +# This timer connects over adb every 2 minutes and turns off anything on +# `keepOff` that has come back. TV off / in standby / unreachable -> no-op. +# +# One-time setup: on the first run the TV shows "Allow USB debugging?" for this +# server's own key (kept in /var/lib/tv-detox). Tick "Always allow". +# +# To deliberately turn an app back on, remove it from `keepOff` first, +# otherwise this switches it off again within 2 minutes. + +{ config, lib, pkgs, ... }: +let + # Reserved for the TV in ../devices.toml. + tv = "10.0.0.40:5555"; + + keepOff = [ + # Pre-installed Philips / partner apps + "org.droidtv.nettvapp1814" # ARTE + "org.droidtv.nettvapp20004410" # Couchplay Games + "org.droidtv.nettvapp4546" # MEGOGO + "org.droidtv.nettvapp4655" # Deezer + "org.droidtv.nettvapp4771" # Divan.TV + "org.droidtv.nettvapp4932" # Free Games by PlayWorks + "org.droidtv.nettvapp5326" # Toon Goggles + "org.droidtv.nettvapp5512" # Fishing TV + "org.droidtv.nettvapp5527" # Flix Premiere + "com.zeasn.whalelive" # WhaleLive + "com.mgmedia.androidApp" # CHILI + "tv.wuaki.apptv" # Rakuten TV + "com.singa.client" # Singa + "com.ted.android.tv" # TED + "com.blacknut.client" # Blacknut + "com.boosteroidtv.streaming" # Boosteroid + "org.droidtv.android.fitness" # Fitness Buddy + "tv.pluto.android" # Pluto TV + + # Philips / Google background extras + "org.droidtv.demome" # Demo me + "org.droidtv.sticker" # Sticker (store demo) + "org.droidtv.eum" # How to… (manual) + "org.droidtv.nettvrecommender" # Top Picks + "org.droidtv.recommendation" # Recommendation + "org.droidtv.usagelogger" # Usage logger + "org.droidtv.tv.frameworklogger" # Framework logger + "org.droidtv.nettv.market" # Philips App Gallery + "com.google.android.tvrecommendations" # Google TV recommendations + "com.google.android.play.games" # Google Play Games + "com.google.android.feedback" # Google Feedback + "com.android.printspooler" # Print spooler + "com.google.android.marvin.talkback" # TalkBack + "com.google.android.backdrop" # Ambient mode / Backdrop + + # Not used + "com.google.android.youtube.tvmusic" # YouTube Music + "tv.twitch.android.app" # Twitch (official) + "com.google.android.videos" # Google TV / Play Movies + "com.google.android.apps.mediashell" # Chromecast built-in + "com.google.android.katniss" # Google Assistant / voice search + "org.droidtv.amazonalexa" # Amazon Alexa + "org.droidtv.alhuewizard" # Hue setup wizard + "org.droidtv.ambihuecommon" # Ambilight + Hue + "org.droidtv.ambiair" # Ambilight + air + "org.droidtv.contentexplorer" # Media (USB player) + "org.droidtv.dlna" # DLNA + "com.phorus.playfi.tv" # DTS Play-Fi + "com.phorus.playfi.softap" # DTS Play-Fi hotspot + + # Freeview Play (re-enabled by Philips at every boot) + "org.droidtv.freeviewplayers" # Freeview Play hub + "uk.co.freeview.bbc" # BBC iPlayer + "uk.co.freeview.bbc_sounds" # BBC Sounds + "uk.co.freeview.itv" # ITVX + "uk.co.freeview.ch4_vod" # Channel 4 + "uk.co.freeview.ch5" # Channel 5 + "uk.co.freeview.stv" # STV + "uk.co.freeview.uktv" # UKTV Play + "uk.co.freeview.amc_catchup" # AMC + "uk.co.freeview.amc_horror" # AMC Horror + "uk.co.freeview.sony_kids_vod" # Sony Kids + "uk.co.freeview.explore" # Freeview Explore + "uk.co.freeview.onnow" # Freeview On Now + "uk.co.freeview.mdsclient" # Freeview Play bridge + "uk.co.freeview.tifbridge" # Freeview Play TV-input bridge + "uk.co.freeview.fvpconfigauth" # Freeview Play config/auth + + # Replaced by the tv-detox home screen (com.ansub.tvhome) + "com.google.android.tvlauncher" # Google Android TV home screen + ]; + + enforce = pkgs.writeShellScript "tv-detox" '' + set -uo pipefail + tv=${tv} + + adb connect "$tv" >/dev/null 2>&1 || true + state=$(adb -s "$tv" get-state 2>&1 || true) + case "$state" in + device) ;; + *unauthorized*) + echo "tv-detox: TV is asking \"Allow USB debugging?\" for this server; tick Always allow" + exit 0 ;; + *) exit 0 ;; # off, in standby or unreachable + esac + + enabled=$(adb -s "$tv" shell pm list packages -e /dev/null 2>&1 || true + ''; +in +{ + config = lib.mkIf (config.networking.hostName == "FredOS-Mediaserver") { + + systemd.services.tv-detox = { + description = "Keep the Philips TV's bloat apps turned off"; + path = with pkgs; [ android-tools coreutils gnugrep gnused ]; + environment = { + # adb keeps its key in $HOME/.android. Own server port so it never + # shares an adb server (and key) with an interactive session. + HOME = "/var/lib/tv-detox"; + ANDROID_ADB_SERVER_PORT = "5038"; + }; + serviceConfig = { + Type = "oneshot"; + ExecStart = enforce; + DynamicUser = true; + StateDirectory = "tv-detox"; + TimeoutStartSec = "90s"; + }; + }; + systemd.timers.tv-detox = { + wantedBy = [ "timers.target" ]; + timerConfig = { + OnBootSec = "2min"; + OnUnitActiveSec = "2min"; + }; + }; + }; +}