Volt
0.5.0 · GitHub
More about this app
Greenify successor: scored app hibernation with UnifiedPush wake-on-push via Shizuku
β‘ Volt β Privacy-first power suite for GrapheneOS
The FOSS successor to Greenify β intelligent app hibernation, no root, with UnifiedPush wake-on-push. Built for Android 14/15/16, tested on GrapheneOS / Pixel 8.
πΈ Screenshots
| Dashboard | Hibernate | Settings | Push |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
(Shown in French β the app defaults to English and follows your system language.)
β¨ What Volt does
1. π Hibernate β the core module
Automatically detects unused, battery-draining apps, hibernates them in graduated levels, and guarantees notifications keep arriving thanks to UnifiedPush wake-on-push.
- 0β100 nocivity score per app, broken into 5 transparent components (inactivity, background ratio, CPU wakeups, background network, battery impact). No opaque score β tap it to see the breakdown.
- 5-layer automatic whitelist: system apps, critical roles (dialer, SMS, launcher), active keyboard, accessibility services, password managers, known 2FA apps, VPNs. Signal, Aegis, Bitwarden & co. are protected by default.
- 3 levels: SOFT (RESTRICTED bucket), MEDIUM (+ force-stop on screen off), HARD (+ periodic 6h sweep).
- Auto-hibernation: configurable score thresholds drive automatic hibernation on a periodic sweep β or run a pass on demand.
- Wake-on-push:
FLAG_INCLUDE_STOPPED_PACKAGESdelivers the push even to a force-stopped app β something Greenify never did cleanly. - Battery savings estimate, "wake all" panic button, Quick Settings tile.
2. π Forensics β "why did my battery drain overnight?"
A scanner that ranks the apps that woke your phone and used the network while you slept, over a configurable window (4 / 8 / 12 / 24h).
- Per-app wakeup attribution parsed from
dumpsys batterystatsvia Shizuku (wakeupap=history) β validated against real Android 16 output. - Foreground transitions (UsageStatsManager) and background network (NetworkStatsManager) folded into one 0β100 impact score.
- One-tap hibernate straight from a culprit row.
- Honest degradation: without Shizuku, wakeup data is shown as "?" and only foreground + network signals are used.
3. π‘ UnifiedPush distributor
Volt is a real UnifiedPush distributor: other apps can pick it as their push provider.
- Implements the distributor handshake β
REGISTERβNEW_ENDPOINT,UNREGISTERβUNREGISTERED,REGISTRATION_FAILEDwhen no server is configured. - Persistent WebSocket (TLS 1.3, full-jitter backoff, zero payload logging) to the push server of your choice (NextPush, Gotify, ntfyβ¦).
- Incoming messages (
<token>:<message>over the WebSocket) are routed to the right app and delivered withFLAG_INCLUDE_STOPPED_PACKAGESβ the wake-on-push synergy with Hibernate. - Endpoint convention:
wss://host/wsβhttps://host/UP?token=<token>. Your push server POSTs to that endpoint and forwards<token>:<message>over the WebSocket.
The full distributor protocol is validated on-device (REGISTER/UNREGISTER round-trip, endpoint generation, tokenβapp delivery). Interop with the full range of connector apps is still being tested β treat as alpha.
β οΈ Requirement: Shizuku (read before installing)
On Android 16, Volt requires Shizuku to work. This is not a design choice β it's an OS constraint: Google locked the CHANGE_APP_IDLE_STATE permission (not a changeable permission type), and it's no longer grantable via adb pm grant. The only remaining app-level path to manipulate App Standby Buckets is Shizuku, which runs under the shell UID.
Shizuku requires no root, but needs a one-time setup (via wireless debugging or a PC). Volt guides you step by step in the Dashboard tab.
| Android | Shizuku |
|---|---|
| β€ 15 | optional (reflection path to setAppStandbyBucket still works) |
| 16+ | required for any hibernation |
π Install (β 10 min, no compiling)
1. Install Volt
Download the latest APK from Releases β install it (1 tap). No Android Studio needed.
2. Install + start Shizuku
- Install Shizuku from F-Droid
- Start it via wireless debugging (no PC) β official guide
3. Configure Volt
- Open Volt β Dashboard tab β grant the requested access (the onboarding adapts and disappears once everything is green)
- Hibernate tab β authorize Volt in Shizuku β pick your apps
Build from source (developers)
git clone https://github.com/lebiggg/volt
cd volt
./gradlew :app:assembleDebug
adb install app/build/outputs/apk/debug/app-debug.apk
π Permissions β full transparency
Zero telemetry. No network connection beyond the outgoing UnifiedPush WebSocket you configure.
| Permission | Type | Why |
|---|---|---|
INTERNET |
normal | Outgoing UnifiedPush WebSocket |
FOREGROUND_SERVICE_DATA_SYNC |
normal | Persistent network service |
POST_NOTIFICATIONS |
runtime | Minimal service notification |
PACKAGE_USAGE_STATS |
special access | Nocivity score (UsageStatsManager) |
QUERY_ALL_PACKAGES |
normal | List installed apps |
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS |
normal | Service longevity |
RECEIVE_BOOT_COMPLETED |
normal | Opt-in start on boot (off by default) |
The privileged action (am set-standby-bucket) goes through Shizuku, not a direct Volt permission.
ποΈ Architecture
ui/screens/ Dashboard | Push | Hibernate (3 tabs) + Settings
ui/theme/ Dynamic Material You (GrapheneOS-friendly)
BatteryCommandService dataSync foreground service, FLAG_INCLUDE_STOPPED_PACKAGES
PushConnectionManager OkHttp WebSocket, full-jitter backoff, zero payload logging
ScreenStateReceiver ACTION_SCREEN_ON/OFF β triggers the sweep
BootReceiver opt-in service start on boot
VoltTileService "Hibernate now" Quick Settings tile
data/hibernation/
βββ HibernationController Single facade (idempotent, thread-safe, Shizuku-first)
βββ HibernationDecisionEngine Score β level
βββ AutoHibernationRunner Wires the engine to the periodic sweep
βββ HibernationRepository Entity β Policy bridge (Room)
βββ HibernationWorker Periodic 6h sweep (WorkManager)
βββ SavingsEstimator Indicative battery savings model
βββ nocivity/NocivityScorer 0-100 score in 5 components
βββ whitelist/WhitelistResolver 5-layer protection
βββ shizuku/ShizukuGateway am set-standby-bucket / force-stop via Shizuku
βββ persistence/ Room database
VoltContainer Minimal service locator (no Hilt)
Every bucket operation goes through one point: HibernationController. That's the central invariant β a single file to touch if the system API changes.
π§ͺ Tests
./gradlew :app:testDebugUnitTest # pure-JVM models (30 assertions)
./gradlew :app:connectedAndroidTest # integration (device required)
CI runs build + unit tests on every push via GitHub Actions.
Manual verification (Pixel 8 / GrapheneOS / Android 16)
# Prereq: Shizuku started and Volt authorized.
# Verify an app moves to the restricted bucket after hibernation:
adb shell am get-standby-bucket org.fdroid.fdroid # β 45 (RESTRICTED) after a SOFT in Volt
π€ Contributing
See CONTRIBUTING.md.
Adding an app to the curated whitelist
Missing a 2FA / password manager / encrypted messenger in CuratedWhitelist.kt? Open a PR with the packageName, the source-repo link, and a justification.
π‘οΈ Threat model
Volt assumes: an up-to-date GrapheneOS device, a user willing to set up Shizuku once, a trusted UnifiedPush server.
Volt does not protect against: a physical attacker with ADB access, a network MITM without certificate pinning (enable it manually in PushConnectionManager), an app that roots itself (out of scope β see GrapheneOS Auditor).
πΊοΈ Roadmap
- Hibernate β engine, whitelist, scoring, UI, Shizuku
- Quick Settings tile
- Battery savings estimate
- Auto-hibernation wired to the periodic sweep
- Internationalization (English + French)
- Opt-in start on boot
- Forensics β nightly wakeup analyzer
- UnifiedPush distributor β
REGISTER/UNREGISTERhandshake - UnifiedPush β broad connector-app interop testing
π License
GPL-3.0 β see LICENSE.
Made with anger at battery drain and respect for your privacy.
How Shizuku is used
Can hibernate apps, wake them for push and analyze battery wakeups via `am`, `dumpsys` through Shizuku.
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
Volt uses Shizuku to hibernate apps and to explain overnight battery use, by running privileged shell commands as the shell user.
- Force stop hibernated apps: apps the user puts to sleep at medium or hard level are stopped with the
am force-stopshell command through Shizuku, including automatic passes, screen off sweeps and quick tile actions. - Restrict background activity: the standby level chosen for each app is applied with the
am set-standby-bucketshell command through Shizuku, which limits background jobs and network on recent Android versions. - Wake apps for push: hibernated apps are temporarily promoted to active so an incoming UnifiedPush message can be delivered, then returned to their previous restricted level after delivery.
- Analyze overnight wakeups: the battery report reads
dumpsys batterystatsthrough Shizuku to count wakeups per app and rank which apps woke or used the phone overnight.
Android APIs or commands used
am force-stopam set-standby-bucketdumpsys batterystats
Notable details
Without Shizuku, stronger levels fall back to a basic restricted bucket without force stop, and the battery report still shows foreground and network activity but without wakeup counts.
Changelog
What's new for version 0.5.0
β‘ Volt v0.5.0-alpha β Real UnifiedPush distributor
The last "experimental" module is now real. Apps can register Volt as their UnifiedPush distributor.
π‘ What's new
- Full distributor handshake:
REGISTERβNEW_ENDPOINT,UNREGISTERβUNREGISTERED,REGISTRATION_FAILEDwhen no server is set. - Secure caller identification (PendingIntent
creatorPackage). - Room-backed tokenβapp registry; endpoint generation (
wss://host/wsβhttps://host/UP?token=β¦). - Incoming
<token>:<message>over the WebSocket β resolved to the right app β delivered withFLAG_INCLUDE_STOPPED_PACKAGES(the wake-on-push synergy with Hibernate). - Registered-apps counter on the Push screen.
β Validated on-device (Pixel 8 / Android 16)
REGISTER tok_cold / org.fdroid.fdroidβ endpointhttps://push.example.org/UP?token=tok_coldpersisted +NEW_ENDPOINTsent.UNREGISTERβ registration removed.- No server URL β
REGISTRATION_FAILED, no DB pollution.
π Verify
SHA-256: `a17c1dc55f2dc0a0f86beb164efeda2937130288c77541de38986a568591f7ef`
π€ Generated with Claude Code
Permissions
13 permissions requested



