# Chromecast with Google TV 4K (2020, device sabrina, product sabrina_prod_stable), 2 GB RAM # Google TV 14 (SDK 34), build UTTC.250917.004 (14193937) # Second unit: Canada, same build, one day of use (2026-10-22). Notes under "Second unit" below. # # Apply: TV_HOST= tools/disable.sh examples/google-chromecast-gtv-4k/debloat.txt # Undo: TV_HOST= tools/restore.sh examples/google-chromecast-gtv-4k/debloat.txt com.google.android.apps.tv.launcherx # Everything is DISABLED, not uninstalled. Comment out any line you want to keep. # To keep phone casting and the stock home (no new launcher), use debloat-keep-cast.txt in this folder instead. # # Stock launcher: com.google.android.apps.tv.launcherx. No Live TV app and no HDMI inputs (it's a dongle): # leave live_tv_package empty in config.xml. # # Known quirks on this firmware: # - ADB on port 5555 is closed (connection refused) until you pair once through Wireless debugging with # the stock adb: Developer options > Wireless debugging > Pair device with pairing code, `adb pair # `, `adb connect ` (`adb mdns services` lists both ports), then # `adb tcpip 5555`. After that tools/tv.py works on 5555 # (docs/TROUBLESHOOTING.md, "USB debugging never opens port 5555"). # - `cmd package set-home-activity com.gathin.tvhome` returns Success but launcherx stays the default. # Disable BOTH com.google.android.apps.tv.launcherx and com.google.android.tungsten.setupwraith # (setupwraith re-enables launcherx), only after the new launcher is installed. # - WARNING: setupwraith can own a saved Wi-Fi network on this model too, as on the HD. On the second # unit `dumpsys wifi | grep -o 'cname=[^ ]*'` named com.google.android.tungsten.setupwraith as the # creator of one of its two saved networks; the network it was on when checked was created by # android.uid.system:1000. Android deletes an app's saved networks when the app is disabled, so # disabling setupwraith deletes that network, and if the stick is on it, Wi-Fi and ADB go with it. # Before disabling setupwraith, forget that network and join it again in Settings > Network & # Internet until every cname reads android.uid.system:1000 (the HD list, same build, also removes it # under Wi-Fi > App preferences). tools/disable.sh skips setupwraith while it owns a network, and # FORCE_SETUPWRAITH=1 overrides that (docs/TROUBLESHOOTING.md, "The TV drops off Wi-Fi for good"). # - Disabling setupwraith also breaks casting from phones, reported on the Chromecast HD on the same # build (#361). The Cast receiver (com.google.android.apps.mediashell) reads its factory device # credentials from a provider inside setupwraith # (com.google.android.libraries.tv.setupwraith.libs.castinfo.CastInfoProvider), so once the wizard # is gone and the device has rebooted, YouTube on the phone answers "Untrusted device ... couldn't # be verified" and the receiver logs "No private key, hence empty signature" every minute. Keeping # the provider while taking Home away does not work: pm disable-user on # setupwraith/.RecoveryActivity is refused with a SecurityException. Either debloat only (keep # launcherx and setupwraith enabled), or re-enable setupwraith after each boot, wait a minute for # "Created singleton instance of ClientAuthSigner" in logcat, then disable it again - the receiver # holds the credentials in memory, so casting works until the next reboot # (docs/TROUBLESHOOTING.md, "Casting fails with Untrusted device"). # Seen again after a reboot: re-enabling setupwraith brought no ClientAuthSigner line within 3 minutes # and phones did not list the device at all. Restart the receiver while setupwraith is enabled: # pm enable com.google.android.tungsten.setupwraith # logcat -c # am crash com.google.android.apps.mediashell # The system starts it again with a new pid, and "Created singleton instance of ClientAuthSigner" # follows within seconds. Check that pid (pidof com.google.android.apps.mediashell) is still the same # 30 s later, then: pm disable-user --user 0 com.google.android.tungsten.setupwraith # Not am force-stop plus am start-foreground-service: started that way the receiver never calls # startForeground(), Android kills it after 30 s, and the copy that comes back with setupwraith # already off has no credentials (the signer line came from the killed process) (#2615). # - Turning USB debugging off leaves Wireless debugging listening on its own port. Switch both off when # you are done. tools/adb-closed.py checks 5555 unless it is given that port: note the port from # `adb mdns services` first, and check it with tools/adb-closed.py before the reboot. # - With launcherx disabled the YouTube button on the remote does nothing. It sends BUTTON_3 # (keycode 190). Button Mapper only remaps added buttons in its paid Pro version; Key Mapper # (open source, keymapperorg/KeyMapper) does it for free. Play Store lists Key Mapper as incompatible # with this device, so install the -foss APK from its GitHub releases, then over ADB: # pm grant io.github.sds100.keymapper android.permission.WRITE_SECURE_SETTINGS # settings put secure enabled_accessibility_services io.github.sds100.keymapper/io.github.sds100.keymapper.system.accessibility.MyAccessibilityService # Map trigger "Button 3" (short press) to action "Launch app > YouTube". Record the trigger with the # physical remote: keys injected with `input keyevent 190` don't reach Key Mapper, and D-pad presses # made while recording get added to the trigger. # - com.google.android.tvrecommendations and com.google.android.apps.education.cast2class ship # disabled at the factory; `pm disable-user` on them fails with "Shell cannot change component # state". Don't add them to a restore list either. # - Disabling dreamx leaves screensaver_components pointing at it. Point it at the launcher's clock: # settings put secure screensaver_components com.gathin.tvhome/.ClockDream # - Animation scales already ship at 0.5x on this build. # - Disable in small batches, and wait before walking away. A run that disabled 21 packages in one # batch had every one report "new state", then the device rebooted: 19 of the 21 were back # afterwards. PackageManager writes package-restrictions.xml asynchronously, so a package disabled # seconds before a reboot is lost while ones disabled minutes earlier (launcherx, setupwraith) # survive. Four batches of 4/4/4/7 with a 20-second pause after each, checking the device is still # up between them, went through with no reboot. # - If the device does reboot, check the uptime before assuming a crash loop: # GET http://:8008/setup/eureka_info reports it, and one reboot with a steadily climbing # uptime afterwards is not a loop. # # Second unit. The list's telemetry and preloaded-app groups were applied (the screensaver pair and # setupwraith were kept), plus a few apps by choice; # after a reboot the disabled list was unchanged. Private DNS validated, and YouTube and Plex loaded # their profiles. Power and Ethernet came through one USB-C hub. # - On Ethernet the Wireless debugging toggle flipped straight back off: unplug the cable, join Wi-Fi # and pair as above. Wireless debugging also went off at every reboot (Wi-Fi drops during boot) and # had to be switched on again by hand; the pairing was kept and the stock adb reconnected on its own. # Port 5555 from `adb tcpip` lasted until the next reboot. # - The hub stayed powered with USB debugging on: `ip link` still listed eth0 (NO-CARRIER only because # the cable was out), while `dumpsys usb` printed host_connected=false and sys.usb.config was "none", # so host_connected=false was no proof the hub was gone. With USB debugging still on, plugging the # Ethernet cable back in brought the Chromecast up on Ethernet, and tools/adb-closed.py then reported # 5555 refused (not checked whether that came from a restart or from Wireless debugging going off). # - The remote ("Chromecast Remote", 18d1:9450; /odm/usr/keylayout/Vendor_18d1_Product_9450.kl is not # readable from the shell) shows YouTube and Netflix as KEY_UNKNOWN in `getevent -lt`, with MSC_SCAN # 000c0077 and 000c0078: the usages the Google TV Streamer list maps to BUTTON_3 (190) and # BUTTON_4 (191). # - Home by redirect: launcherx and setupwraith left enabled for casting, stock_home_redirect set to # com.google.android.apps.tv.launcherx, HomeKeyService enabled by hand. launcher/build-and-install.sh # with STOCK_LAUNCHER=none installs, then stops at its Home check, as expected while launcherx is # Home. Home pressed in an app landed on the new launcher. After a reboot the TV stayed on the Google # TV home: it is drawn before Android binds HomeKeyService, so no window change reaches the redirect # (#698 and #1024 work on this). With launcherx kept as Home, tools/check.py needs it as the second # argument, or every run reports Home as drift: the Check line in debloat-keep-cast.txt, which is the # list this setup matches. # - With the redirect on, the YouTube button did nothing although launcherx was enabled. The redirect # opens the launcher with ACTION_MAIN + CATEGORY_HOME, so this is consistent with #698's explanation # (this launcher becomes the Home process and launcherx loses its Android 14 exemption for background # activity starts, BAL_BLOCK), but no BAL_BLOCK line was captured in logcat. app_keys # "190:com.google.android.youtube.tv" and "191:" in a theme, handled by HomeKeyService, # worked with both buttons on the real remote. (Seen on a build with a local boot check added to # HomeKeyService; the redirect's intent was main's.) # - Holding Volume Up on the real remote still ramped with HomeKeyService filtering keys (key_filter at # its default) and Button Mapper's accessibility service enabled as well. Not checked with # HomeKeyService alone. # # Kept on purpose: Google Assistant (com.google.android.katniss), Cast receiver # (com.google.android.apps.mediashell), phone remote (com.google.android.tv.remote.service), Play Store / # Play Services, Gboard, Bluetooth, com.google.android.tv.dfuservice (remote firmware updates). # The receiver itself stays enabled, but casting still needs setupwraith for its credentials # (see the setupwraith quirks above). # Telemetry, feedback and ads com.google.android.feedback com.android.tv.feedbackconsent com.google.android.tv.remotecontrol.logging # remote usage logging com.google.android.apps.tv.netoscope # network diagnostics reporting # The next four are Privacy Sandbox / federated-learning Mainline modules: worked here, re-enable if # the Play Store or Assistant misbehave. com.google.android.federatedcompute com.google.android.ondevicepersonalization.services com.google.android.adservices.api # Privacy Sandbox ad services com.google.android.ext.adservices.api # Preloaded apps com.google.android.play.games com.google.android.videos # Google TV / Play Movies com.android.printspooler com.google.android.marvin.talkback # re-enable if you need the screen reader # Google ambient mode screensaver (replaced by the launcher's Clock screensaver) com.google.android.apps.tv.dreamx com.google.android.backdrop # Stock home. launcher/build-and-install.sh disables launcherx itself once the new launcher is installed # and verified, and restore.sh re-enables it; setupwraith has to go too on this firmware (see quirks), # so it stays in the list for restore.sh to bring back. # com.google.android.apps.tv.launcherx com.google.android.tungsten.setupwraith # setup wizard; its RecoveryActivity otherwise takes over Home