How yume-chan/volumemanager works
1. What this repo is
- An Android app called Volume Manager that lets the user control per-app audio volume on Android 13+.
- It is not a general media app; its core architecture is about monitoring active audio players and writing volume changes into Android’s internal audio APIs.
2. High-level runtime shape
- The app is a single Android application module (app) with a small benchmark/profile module (baselineProfile) for startup/performance optimization.
- The main UI is built with Jetpack Compose.
- Privileged access is obtained through Shizuku, which is explicitly called out in the README as the mechanism used to reach hidden/system APIs.
3. Primary user-facing entry points
- MainActivity is the main control screen.
- PopupActivity is the volume popup UI that can replace the system volume panel behavior.
- The Compose UI lives under app/src/main/java/moe/chensi/volume/compose, with separate components for:
- app volume lists/sliders,
- system stream sliders,
- toggle buttons,
- dialogs such as about and crash reporting.
4. Core orchestration layer
- Manager appears to be the central application coordinator: it likely holds current state, bridges UI actions to audio/system operations, and coordinates enabled/disabled behavior.
- Service is the runtime service boundary, likely responsible for always-on monitoring and integrating with accessibility/overlay-like behavior.
- MyApplication and CrashHandler provide process-level initialization and crash capture/reporting behavior.
5. How the volume control mechanism works
- The architecture follows the flow described in the README:
1. query active playback sessions from AudioManager#getActivePlaybackConfigurations(),
2. map each playback session back to an app using process/package information,
3. call internal player APIs to set the volume multiplier,
4. register callbacks so new playback sessions receive the current per-app volume automatically.
- This means the app’s domain model is built around audio playback configurations, not around files, tracks, or media libraries.
6. System integration boundary
- The system package contains proxy wrappers around privileged Android services:
- ActivityTaskManagerProxy
- AudioPlaybackConfigurationProxy
- NotificationManagerProxy
- PackageManagerProxy
- UserManagerProxy
- These are the main boundary layer between app code and hidden/system APIs, which is where the app’s privileged capabilities are concentrated.
7. Hidden binder/API hooking layer
- android/media/IPlaybackConfigDispatcher.aidl and ToggleableBinderProxy.kt indicate the app also interacts with binder-level callbacks/proxies, not just public SDK calls.
- This suggests a design where the app can intercept or emulate system dispatch behavior for playback configuration updates, then enable/disable that behavior dynamically.
8. Accessibility-driven behavior
- The presence of res/xml/accessibility_service_config.xml and the README instructions imply an accessibility service is part of the product’s control surface.
- The accessibility button and auto-enabled service are likely used to provide quick access to the popup/control experience and to keep the app responsive to system UI interactions.
9. State and persistence
- The data package contains:
- App — app-level domain model,
- AppPreferences — user settings/state,
- AppPreferencesStore — persistence layer.
- This is the boundary for long-lived configuration such as user preferences, enabling/disabling behavior, and possibly per-app saved volume values.
10. UI composition structure
- The Compose layer is separated by responsibility rather than by screen only:
- app list + per-app slider,
- system volume panel,
- stream volume slider,
- generic track slider,
- toggle controls.
- This indicates a shared component architecture where the same slider/toggle primitives are reused across the main screen and popup surfaces.
11. Error handling and support UX
- CrashHandler plus CrashReportDialog show that crashes are handled as a first-class UX concern.
- AboutDialog suggests an in-app informational/support boundary rather than relying only on external docs.
12. Assets, branding, and release concerns
- The app includes a standard Android resource set for icons, themes, localization, and accessibility service XML.
- There is Chinese localization (values-zh-rCN) alongside default strings, indicating the UI is localized but still centered around the same single core workflow.
13. Build, test, and release pipeline
- The repo uses Gradle Kotlin DSL and ships via GitHub Actions (.github/workflows/build.yml).
- It also has baseline profile generation to improve app startup on Android.
- fastlane metadata is present for store/release distribution assets and descriptions.
14. Architecture summary for a diagram
- The clearest diagram is:
- User touches Compose UI / popup / accessibility entry points
- → Manager / Service coordinate state
- → Preferences store provides saved settings
- → System proxy layer + Shizuku-backed privileged access
- → Android audio/process/package services
- → active playback configs are mapped to apps
- → volume is applied via internal player APIs
- → callbacks keep new sessions in sync
- The central boundary is between ordinary app UI/state and privileged hidden Android audio/system APIs.
Main entry points: Manager.kt Manager · compose Compose UI · system System proxies · MyApplication.kt MyApplication
Components 21
App runtime
Main Android application entry points, orchestration, and UI.
- MainActivity · Primary control screen for managing per-app audio volume.
app/src/main/java/moe/chensi/volume/MainActivity.kt - PopupActivity · Overlay-style volume popup surface.
app/src/main/java/moe/chensi/volume/PopupActivity.kt - Manager · Central coordinator for app state, UI actions, and volume operations.
app/src/main/java/moe/chensi/volume/Manager.kt - Service · Always-on service boundary for monitoring and system interaction.
app/src/main/java/moe/chensi/volume/Service.kt - MyApplication · Process-level initialization entry point.
app/src/main/java/moe/chensi/volume/MyApplication.kt - CrashHandler · Global crash capture and reporting setup.
app/src/main/java/moe/chensi/volume/CrashHandler.kt - Compose UI · Shared Jetpack Compose component layer for screens, sliders, toggles, and dialogs.
app/src/main/java/moe/chensi/volume/compose - App list · Per-app volume list presentation.
app/src/main/java/moe/chensi/volume/compose/AppVolumeList.kt - App slider · Per-app volume slider component.
app/src/main/java/moe/chensi/volume/compose/AppVolumeSlider.kt - System panel · System volume panel UI surface.
app/src/main/java/moe/chensi/volume/compose/SystemVolumePanel.kt - Toggle · Shared enable/disable control component.
app/src/main/java/moe/chensi/volume/compose/ToggleButton.kt
Privileged system
Hidden API wrappers, binder hooks, and Android service integration.
- System proxies · Wrapper layer around privileged Android services and hidden system interfaces.
app/src/main/java/moe/chensi/volume/system - Audio config · Access to playback configuration and audio session mapping.
app/src/main/java/moe/chensi/volume/system/AudioPlaybackConfigurationProxy.kt - Binder proxy · Toggleable binder-level interception for playback config dispatch.
app/src/main/java/moe/chensi/volume/ToggleableBinderProxy.kt - Playback AIDL · AIDL definition for playback configuration dispatch callbacks.
app/src/main/aidl/android/media/IPlaybackConfigDispatcher.aidl - Shizuku · Mechanism used to reach hidden and system APIs.
State & persistence
Domain models and stored preferences.
- App model · App-level domain object used for playback-to-app mapping and saved settings.
app/src/main/java/moe/chensi/volume/data/App.kt - Preferences · User settings and persisted app state.
app/src/main/java/moe/chensi/volume/data/AppPreferences.kt - Prefs store · Storage boundary for application preferences.
app/src/main/java/moe/chensi/volume/data/AppPreferencesStore.kt
Build & release
Performance profiling and distribution support.
- Baseline profile · Startup and performance profiling module.
baselineProfile - Store assets · Fastlane metadata and localized release materials.
fastlane
Connections 25
- MyApplication → MainActivity: starts · Launches the primary UI entry point.
- MyApplication → Service: initializes · Sets up long-lived runtime behavior.
- MyApplication → CrashHandler: installs · Registers process-wide crash capture.
- MainActivity → Manager: controls · Sends user actions to the coordinator.
- PopupActivity → Manager: controls · Routes popup interactions to the coordinator.
- Service → Manager: hosts · Keeps orchestration active in the background.
- Manager → Compose UI: renders · Binds state into shared Compose surfaces.
- Compose UI → App list: contains · List of managed apps.
- Compose UI → App slider: contains · Per-app slider control.
- Compose UI → System panel: contains · System volume panel surface.
- Compose UI → Toggle: contains · Shared toggle controls.
- Manager → Prefs store: loads/saves · Reads and persists configuration.
- Prefs store → Preferences: stores · Persists app settings and user choices.
- Manager → App model: uses · Represents apps and their volume state.
- Manager → System proxies: invokes · Calls privileged Android service wrappers.
- System proxies → Audio config: includes · Audio/session configuration access.
- System proxies → Binder proxy: includes · Dynamic binder interception layer.
- Binder proxy → Playback AIDL: implements · Hooks playback config callbacks.
- System proxies → Shizuku: backed by · Uses Shizuku to reach hidden/system APIs.
- Audio config → App model: maps to · Maps playback sessions back to apps.
- Audio config → Manager: feeds · Provides active playback configuration updates.
- Manager → Service: registers callbacks · Keeps new playback sessions in sync.
- Manager → CrashHandler: reports · Routes crash context to support UX.
- Baseline profile → MainActivity: optimizes · Profiles startup and launch paths.
- Store assets → Compose UI: documents · Contains store-facing screenshots and descriptions.