ShizuStore

Volt

lebiggg

0.5.0 · GitHub

Download APK
Power management Android 14+ 3 months ago GPL-3.0
110 ShizuStore
701 GitHub
11 Stars
4 MB Size

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.

License FOSS No Trackers GrapheneOS Status Build


πŸ“Έ Screenshots

Dashboard Hibernate Settings Push
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_PACKAGES delivers 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 batterystats via 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_FAILED when 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 with FLAG_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

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/UNREGISTER handshake
  • UnifiedPush β€” broad connector-app interop testing

πŸ“œ License

GPL-3.0 β€” see LICENSE.


Made with anger at battery drain and respect for your privacy.

Close

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-stop shell 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-bucket shell 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 batterystats through Shizuku to count wakeups per app and rank which apps woke or used the phone overnight.

Android APIs or commands used

  • am force-stop
  • am set-standby-bucket
  • dumpsys 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.

Close

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_FAILED when 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 with FLAG_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 β†’ endpoint https://push.example.org/UP?token=tok_cold persisted + NEW_ENDPOINT sent.
  • UNREGISTER β†’ registration removed.
  • No server URL β†’ REGISTRATION_FAILED, no DB pollution.

πŸ” Verify

SHA-256: `a17c1dc55f2dc0a0f86beb164efeda2937130288c77541de38986a568591f7ef`

πŸ€– Generated with Claude Code

Close

Permissions

13 permissions requested

  • android.permission.INTERNET
  • android.permission.ACCESS_NETWORK_STATE
  • android.permission.FOREGROUND_SERVICE
  • android.permission.FOREGROUND_SERVICE_DATA_SYNC
  • android.permission.POST_NOTIFICATIONS
  • android.permission.PACKAGE_USAGE_STATS
  • android.permission.CHANGE_APP_IDLE_STATE
  • android.permission.QUERY_ALL_PACKAGES
  • android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
  • android.permission.RECEIVE_BOOT_COMPLETED
  • android.permission.WAKE_LOCK
  • com.tonnomdeved.volt.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION
  • moe.shizuku.manager.permission.API_V23
Close