TVPilot
1.0.0 · GitHub
More about this app
Remote-first system control and app management for Android TV / Google TV, with optional Shizuku-powered advanced actions
TVPilot
A small, remote-first system control utility for Android TV / Google TV.
Designed around Xiaomi TV Box S (2nd Gen / MDZ-28-AA / jaws)
while keeping a conservative generic profile for other Android TV and Google TV devices.
What it does
- Sleep / standby without turning off the connected television.
- Restart the Android TV device.
- Power off using the platform shell shutdown command where the firmware supports it.
- Show launchable, recently active and non-system user applications.
- Show a separate runtime state (Running / Not running / Unknown) when Advanced Access can verify it.
- Show package name, recent use and 7-day foreground time.
- Force-stop one, many, or all eligible apps.
- Built-in critical-package protection.
- User-managed Never Close list.
- Four optional Quick Settings tiles: Sleep, Close Apps, Restart, Power Off.
- Fully usable with a D-pad/TV remote; no touch screen is required.
- English and Turkish TV UI.
- No analytics, ads or tracking. TVPilot itself requests no Internet permission.
- No persistent TVPilot background service.
Screenshots
Important Android limitation
Modern Android does not allow an ordinary third-party application to force-stop other packages, reboot, or fully shut down the device. TVPilot therefore has two layers:
- Standard layer — device detection, app discovery, usage information and Android settings shortcuts.
- Advanced Access — privileged shell operations through Shizuku.
Shizuku is deliberately not bundled. The user chooses whether to install/start it and explicitly grants TVPilot permission.
Commands used by Advanced Access
| Action | Shell operation |
|---|---|
| Sleep | input keyevent 223 with power-key fallback |
| Restart | reboot |
| Power off | reboot -p |
| Force stop | am force-stop --user current <package> |
| Runtime state | cmd activity get-uid-state <uid> |
These fixed-purpose operations run inside a non-daemon AIDL Shizuku UserService. TVPilot does not accept arbitrary shell commands or command text from UI/Intent input.
Power Off is firmware-dependent. On some boxes a full shutdown cannot be resumed by HDMI-CEC or the remote; power may have to be physically re-applied.
Xiaomi TV Box S 2nd Gen setup
TVPilot’s Advanced Access requires Shizuku. Shizuku is not bundled with TVPilot and must be installed and started separately.
- Install TVPilot and Shizuku
Install the TVPilot APK and the official Shizuku APK on the TV box.
Open Shizuku at least once after installation.
If you want TVPilot to display recent activity and usage information, also enable Usage Access when prompted by TVPilot.
- Enable ADB debugging
On the Xiaomi TV Box S 2nd Gen:
Settings → System → About → Android TV OS build
Press OK repeatedly until Developer Options are enabled.
Then open:
Settings → System → Developer options
and enable USB debugging.
- Find the TV box IP address
Open the active network connection on the TV box and note its local IP address.
For example:
192.168.1.100
Your computer and TV box should be connected to the same local network.
- Connect with ADB
Install Android Platform Tools on your computer if adb is not already available.
Then connect to the TV box, replacing <TV_BOX_IP> with its actual IP address:
adb connect <TV_BOX_IP>:5555
For example:
adb connect 192.168.1.100:5555
The TV may display an ADB authorization prompt. Allow the connection, preferably enabling Always allow from this computer.
Verify the connection:
adb devices
The TV box should appear with the state device.
- Start Shizuku
On the Xiaomi TV Box S 2nd Gen, the commonly documented /sdcard/Android/data/moe.shizuku.privileged.api/start.sh file may not be present.
The following command locates Shizuku’s installed native starter dynamically and starts the Shizuku server without relying on a fixed APK installation path:
adb shell 'for p in \((pm path moe.shizuku.privileged.api | cut -d: -f2); do lib=\)(find "${p%/*}/lib" -name "libshizuku.so" 2>/dev/null); if [ -x "$lib" ]; then "$lib"; exit 0; fi; done; echo "Shizuku starter not found"'
A successful start should produce output similar to:
info: starter begin info: killing old process... info: apk path is /data/app/.../moe.shizuku.privileged.api.../base.apk info: starting server... info: shizuku_server pid is ... info: shizuku_starter exit with 0
You can optionally verify that the server is running:
adb shell ps -A | grep shizuku
Then return to the Shizuku application on the TV. It should report that Shizuku is running.
Note: The exact internal Shizuku implementation may change between releases. This command has been verified on the Xiaomi TV Box S 2nd Gen (MDZ-28-AA / jaws) with a Shizuku version that provides the libshizuku.so native starter. If Shizuku starter not found is shown, consult the current official Shizuku documentation instead of attempting to modify system files.
- Grant TVPilot Advanced Access
Open:
TVPilot → Advanced Access
TVPilot will request permission through Shizuku. Approve the Shizuku permission dialog.
TVPilot can now use its privileged operations.
Test Sleep first. Test Restart and especially Power Off only after reading the warning below.
Power Off warning: reboot -p is firmware-dependent. After a full power-off, some TV boxes cannot be powered back on through the normal Bluetooth remote or HDMI-CEC. Physical power may need to be disconnected and re-applied.
After a reboot
Non-root Shizuku does not normally survive a full Android reboot.
You do not need to reinstall Shizuku or TVPilot. Reconnect with ADB:
adb connect <TV_BOX_IP>:5555
and run the Shizuku start command again:
adb shell 'for p in \((pm path moe.shizuku.privileged.api | cut -d: -f2); do lib=\)(find "${p%/*}/lib" -name "libshizuku.so" 2>/dev/null); if [ -x "$lib" ]; then "$lib"; exit 0; fi; done; echo "Shizuku starter not found"'
The TV box IP address may change after a reboot unless your router assigns it a fixed DHCP lease.
Putting the device into normal Sleep / standby does not normally require Shizuku to be started again.
App safety model
Close All does not mean “kill every Android process”. It force-stops eligible apps whose runtime state is verified as Running. If an OEM does not provide a recognizable runtime-state response, TVPilot conservatively falls back to eligible apps with recent UsageStats activity. Installed but inactive apps are not bulk force-stopped.
TVPilot protects core packages such as Android System, System UI, Settings, Google Play Services, Google TV launchers, Shizuku, package/permission controllers and TVPilot itself. It also resolves the active Home launcher and input method dynamically, protects enabled accessibility services and conservatively protects VPN-capable apps. The Xiaomi profile adds Xiaomi-specific core packages. Non-launchable system components are protected by default.
Long-press an application row to force-stop it directly, open Android App Info, or add/remove it from Never Close. Every bulk action shows a preview before it runs.
Quick Settings
TVPilot declares Android TileService implementations for:
- Sleep
- Close Apps
- Restart
- Power Off
Android exposes this API, but TV manufacturers are free to customize their TV Quick Settings UI. A tile may therefore be available on one Android TV / Google TV firmware and hidden on another. The main TVPilot UI remains the supported fallback.
Remote navigation
The UI is intentionally View/XML based rather than Compose-heavy. Interactive cards and list rows are focusable and can be controlled with D-pad directions, OK/Select and Back. A long-press on an app row opens its detail/actions dialog.
Build
Requirements:
- Android Studio with JDK 17+
- Android SDK 35
- Gradle 8.10.x compatible with Android Gradle Plugin 8.7.x
Open the repository in Android Studio and let Gradle sync, or run with a locally installed compatible Gradle:
./gradlew :app:testDebugUnitTest :app:lintDebug :app:assembleDebug
The debug APK will be generated under app/build/outputs/apk/debug/.
Release builds enable R8 and resource shrinking. An unsigned local release can be built with ./gradlew :app:assembleRelease; public APKs must be signed with the project's long-lived release key.
Direct open-source distribution
TVPilot does not require a store. Public releases are designed to be distributed through GitHub Releases as a signed APK plus SHA-256 checksum:
- Download the APK and matching
.sha256file from the release. - Verify the checksum on a computer.
- Install with
adb install TVPilot-vX.Y.Z.apk, or copy the APK to the TV and use a trusted package installer. - Future releases must be signed with the same key so Android can install them as updates.
See Releasing, Device test matrix and TV design system.
Project structure
app/src/main/java/com/alpware/tvpilot/
├── data/ # installed/recent app model and repository
├── device/ # generic + Xiaomi capability/safety profile
├── privilege/ # privileged system controller abstraction
├── tiles/ # Android Quick Settings TileService actions
└── ui/ # remote-first activities and adapters
SystemController deliberately isolates privileged operations from the UI. Its Shizuku backend binds a short-lived, non-daemon AIDL UserService rather than using the deprecated remote-process API. A future root, Sui, OEM or test backend can be added without rewriting screen logic.
Privacy
TVPilot contains no analytics SDK, advertising SDK or telemetry. It does not request Internet access. Usage Access is used locally to display application activity. Package information and selections stay on the device.
See PRIVACY.md.
Status / testing
P1–P4 software work is in place, but hardware-specific behavior must still be verified on a physical Xiaomi TV Box S 2nd Gen. Runtime-state output, Quick Settings exposure, standby fallback, reboot -p, HDMI-CEC and power-on behavior remain P0 device-test items.
License
Apache License 2.0. See LICENSE.
How Shizuku is used
Can put TV to sleep, reboot, power off, force stop apps and check running state via Shizuku with `input`, `reboot`, `am` and `cmd` commands.
This is an AI-assisted analysis of Shizuku-related usages in the app's public source code. It is best effort, so it may not catch every single usage.
How this app uses Shizuku
TVPilot uses Shizuku to perform system power actions and app management on Android TV that are not available to normal apps.
- Put TV to sleep: puts the TV into sleep from the main screen or quick tile using the
input keyeventshell command through Shizuku. - Restart device: restarts the TV after confirmation from the main screen or quick tile using the
rebootshell command through Shizuku. - Power off device: shuts the TV down after confirmation from the main screen or quick tile using the
reboot -pshell command through Shizuku. - Force stop apps: closes selected apps, all eligible apps, or a single app from its details using the
am force-stopshell command through Shizuku. - Show running status: displays whether listed apps are running or not running in the app list and quick close screen using the
cmd activity get-uid-stateshell command through Shizuku.
Android APIs or commands used
input keyevent 223input keyevent 26rebootreboot -pam force-stopcmd activity get-uid-state
Changelog
What's new for version 1.0.0
TVPilot v1.0.0
First public release of TVPilot — a remote-first system control and app management utility for Android TV and Google TV.
TVPilot is designed around the Xiaomi TV Box S (2nd Gen / MDZ-28-AA / jaws), while providing a conservative generic profile for other Android TV and Google TV devices.
Highlights
- Sleep / standby control
- Restart and firmware-dependent power off
- Recent, launchable and non-system app discovery
- Runtime state detection with Advanced Access
- Per-app recent usage and 7-day foreground time
- Force-stop individual or multiple applications
- Bulk Close All with built-in safety protections
- User-managed Never Close list
- Optional Quick Settings actions for Sleep, Close Apps, Restart and Power Off
- Full D-pad and TV remote navigation
- English and Turkish interface
- No ads, analytics or tracking
- No Internet permission required by TVPilot
- No persistent TVPilot background service
Advanced Access
TVPilot uses Shizuku for operations that ordinary Android applications are not permitted to perform, including:
- Force-stopping other applications
- Restarting the device
- Powering off supported devices
- Verifying application runtime state
Shizuku is not bundled with TVPilot and must be installed, started and authorized separately.
See the repository README for Xiaomi TV Box S (2nd Gen) setup instructions.
Device compatibility
The primary target for this release is:
Xiaomi TV Box S (2nd Gen) — MDZ-28-AA / jaws
Other Android TV and Google TV devices can use TVPilot's generic device profile, but firmware-specific behavior may vary.
In particular, Quick Settings availability, standby behavior, runtime-state reporting and full power-off behavior depend on the device firmware.
Important power-off warning
Power Off uses Android's reboot -p operation through Advanced Access.
On some TV boxes, a fully powered-off device cannot be turned back on using the Bluetooth remote or HDMI-CEC. Physical power may need to be disconnected and re-applied.
Test Sleep first and use Power Off only after understanding this limitation.
Installation
- Download the APK attached to this release.
- Install it on your Android TV / Google TV device.
- Grant Usage Access if you want recent activity and usage information.
- Install and start Shizuku if you want to use Advanced Access.
- Open TVPilot → Advanced Access and approve the Shizuku permission request.
Detailed setup instructions are available in the README.
Privacy
TVPilot contains no analytics, advertising or telemetry SDKs.
TVPilot itself requests no Internet permission. Usage and package information remain on the device.
Permissions
4 permissions requested