Last update: 2026-03-22
- Cross-profile playback control fix for foreign-profile package resolution, with KernelSU Next validation.
- Setup Check / diagnostics ANR validation on device after deferred
SharedPreferenceswrite hardening. - Package rename to
fuck.individualappaudiovolumecontrol.droidvendorssuckwith Magisk/module safety validation. - Privapp allowlist minimization after KernelSU bootloop reports on Android 15.
- Build hardening for module packaging (signed release APK + allowlist validation).
- Overlay UX refinements and feature gating groundwork.
- Volume-button overlay reliability (accessibility-service key events).
- Continuing validation on Android 12-15 devices.
- Rules engine groundwork (storage + playback overrides).
- Added a post-boot best-effort grant probe in
module/service.shthat tries bothpm grantandcmd package grantforINTERACT_ACROSS_USERS(_FULL)across detected users, then logs whether the permission is actually granted so KernelSU/Magisk installs can be diagnosed more concretely. - Fixed foreign-profile package resolution by resolving playback UIDs through the target user context when hidden
getClientPackageName()is unavailable, which should let cross-profileAudioPlaybackConfigurationentries remain controllable instead of being dropped. - Clarified docs that root
dumpsysfallback is detection-only and that actual cross-profile control on KernelSU Next still depends on the app being mounted as a privileged system app withINTERACT_ACROSS_USERS(_FULL). - Added
INTERACT_ACROSS_USERS_FULLto the manifest and privapp allowlist so cross-profile control can be granted on enforcing ROMs. - Ensured playback callbacks reapply volumes using cross-profile configs when across-users permission is granted, and exposed INTERACT_ACROSS_USERS_FULL in diagnostics.
- Added
org.lineageos.settingsto the default overlay ignore list. - Added a diagnostics action to force a cross-profile probe and a report header to group cross-profile rows.
- Added cross-profile diagnostics copy action in modern diagnostics and surfaced probe/apply summaries in legacy diagnostics.
- Added cross-profile diagnostics summaries for playback probing and apply attempts, including per-user config counts and apply results.
- Added a shared deferred
SharedPreferenceswriter and movedVolumeStore,OverlayPrefs,LocationRuleStore,ActiveAppStore,NotificationPrefs, andAudioSettingsPrefsonto backgroundcommit()flushes so hot write paths no longer queue frequent main-processapply()work. - Closed the high-priority ANR audit item for remaining high-frequency preference writes and moved it to the done section in
TODO.md. - Added a per-app notification presentation mode that keeps the foreground controller notification for service survival and posts a separate secondary notification for each active app.
- Fixed slider guide alignment by making the 10% tick overlay use the same left/right insets as the actual
SeekBartrack in both the main UI and the overlay. - Added high-priority playback-notification persistence diagnostics and a forced foreground-notification refresh path so Diagnostics can show whether the controller service is alive, whether notifications/channels are enabled, and when the controller last posted its notification.
- Added configurable notification presentation: the main UI can now switch between multi-app pages and a single-app pager, with
Next/Prevkept as the fallback mode in one shared notification. - Removed the redundant system notification
Overlayaction button so the custom overlay button inside the notification header is the single overlay entry point. - Added profile labels to each notification row so cross-profile entries show whether they belong to Personal, Work, or another user in the notification itself.
- Investigated custom notification sliders: documented the
RemoteViewsdrag limitation, kept notification controls button-based, and added per-app visual level bars so notification rows still read like sliders. - Root fallback now only activates when
INTERACT_ACROSS_USERS(_FULL)is unavailable, and the main UI has a manual cross-profile scan button for forcing a fresh root-based audio probe. - Reduced root fallback churn by extending
suavailability caching and rootdumpsysresult caching so cross-profile detection does fewer expensive refreshes while the UI or overlay is open. - Made manual
Show overlay nowdisplay a test preview card when no app is currently playing audio, without changing volume-button-triggered empty-overlay behavior, and kept the Setup Check disabled message when controls are unavailable. - Added search fields to Setup Check and Diagnostics so long reports can be filtered in-place without affecting copy/share of the full report.
- App-name taps in the overlay now open a package overview dialog with confirmation-backed "Ignore" action scoped to the tapped profile when available.
- Added
com.android.location.fusedto the overlay ignore defaults so fused location playback/noise does not appear in per-app volume controls by default. - Added
INTERACT_ACROSS_USERSto the privapp allowlist and manifest to enable cross-profile playback detection when supported by the ROM. - Added cross-profile playback aggregation when
INTERACT_ACROSS_USERSis granted, with Diagnostics reporting for active userIds. - Captured Diagnostics bundle for overlay watcher on POCO F1 (crDroid, Android 15 / API 35) and logged results in
docs/VALIDATION.md. - Logged overlay watcher validation on POCO F1 (crDroid, Android 15) in
docs/VALIDATION.md. - Added
org.lineageos.lineagesettingsto the overlay ignore defaults so it no longer appears in volume controls by default. - Added
docs/VALIDATION.mdand a helper script (scripts/validate-overlay-watcher.sh) to capture overlay watcher reliability evidence on Android 12-15 devices. - Set a project-wide Gradle heap default (
-Xmx4g) so fullgradle buildruns no longer fail inlintAnalyzeLegacyDebuganddexBuilderModernReleasewith Java heap space on AGP 8.13.2. - Renamed the on-disk source tree for the app code to match the package namespace across
main,modern, andlegacysource sets. - Pinned selected apps to the top of searchable multi-select app dialogs so overlay ignore/block lists and the rules app picker keep chosen entries visible above the remaining results.
- Debounced diagnostics persistence and throttled
ActiveAppStorewrites so UI refresh loops do not keep schedulingSharedPreferencesflushes every couple of seconds. - Moved
SetupCheckActivityrefresh work off the UI thread so the setup screen no longer does audio-session/privilege checks synchronously on launch or manual refresh. - Reworked
DiagnosticsStoreto keep an in-process snapshot and flush via a dedicated backgroundcommit()thread instead of frequentSharedPreferences.apply()calls, to avoidQueuedWork.waitToFinish()ANRs whenSetupCheckActivitystops. - Captured and reviewed the current device ANR dump: main thread blocked in
ActivityThread.handleStopActivity -> QueuedWork.waitToFinish()while the queued-work looper was stuck inSharedPreferencesImpl.writeToFile()/fsync. - Renamed boot log files to
individualappaudiovolumecontrol-boot.logto match the module id. - Added a
priv-appno-protected-permissions probe build path to isolate whetherMODIFY_AUDIO_ROUTINGis the exact Android 15 bootloop trigger. - Added a
system/appprobe packager to isolate KernelSU bootloops between privileged install issues and generic APK/module mount issues. - Trimmed the shipped privapp manifest/XML down to
android.permission.MODIFY_AUDIO_ROUTINGonly, removing non-core privileged requests that could trip package-manager enforcement at boot. - Updated build/module docs to treat the privapp allowlist as a boot-critical surface and keep
WRITE_SECURE_SETTINGS/PACKAGE_USAGE_STATSoptional instead of shipped by default. - Renamed the Android app package/namespace to
fuck.individualappaudiovolumecontrol.droidvendorssuckwithout changing source folders. - Updated privileged permission grant metadata to target the renamed package.
- Added
android.permission.PACKAGE_USAGE_STATSto the module privapp allowlist so enforcing ROMs do not kill package scan at boot for the renamed priv-app. - Switched Magisk module packaging to a signed non-debuggable release APK and added a packaging-time validator for APK package name and reviewed privapp permission coverage.
- Removed unnecessary
FOREGROUND_SERVICEfrom the privapp allowlist, tolerated unsigned release APK outputs in packaging fallback, and removed AndroidX startup/profileinstaller merged components from the base manifest. - Synced the bundled module asset directly from the main packaged ZIP so app-installer and manual-flash paths use the same archive.
- Tightened the privapp validator to fail on stale allowlist entries in addition to missing reviewed grants.
- Switched privapp validation to derive expected allowlisted permissions from the source manifest’s
ProtectedPermissionsmarkers, and trimmed non-derived entries from the XML. - Validator now scans all manifests under
app/srcwith more robust parsing, and rejects allowlist entries not requested by the APK. - Removed Play Services geofencing dependency, stubbed geofence handling, and dropped the geofence receiver from the modern manifest.
- Removed the now-dead geofencing toggle from the Rules UI.
- Removed geofencing preference storage and diagnostics output since Play Services geofencing is gone.
- Removed all remaining geofencing code paths and the GeofenceRuleManager class.
- Keeping Magisk module ID and priv-app mount path stable to avoid unnecessary install-path regressions.
- Fixed Magisk ZIP packaging to recreate the archive instead of updating in place, preventing stale APK paths from surviving rebuilds.
- Exposed dismiss-on-outside-tap toggle in main Overlay settings.
- Added an overlay menu toggle for dismiss-on-outside-tap behavior (defaults on).
- Switched overlay to watch outside taps (no full-screen capture), allowing tap-through while dismissing.
- Hardcoded Face Unlock Service package
co.aospa.senseinto the overlay ignore defaults. - Added tap-outside-to-dismiss overlay behavior (full-screen touch catcher).
- Added next/prev paging for notification controls when more apps are active.
- Collapsed overlay header controls into a dropdown menu and added a pause/resume toggle (menu + watcher notification).
- Suppressed volume-key overlay triggers while paused and resume on manual overlay action.
- Moved overlay row controls (mute/percent) to the left of sliders.
- Styled the notification for OLED, added 100% quick button, and applied overlay ignore list filtering.
- Updated overlay visuals for OLED: transparent root, solid black cards, white borders/text, neon orange sliders, reduced header spacing.
- Overlay background set to transparent with clear white borders for root and rows.
- Overlay app names now open App Info on tap (long-press still copies package).
- Added overlay ignore list (defaults: System UI + Face Unlock label match) and suppress overlay when only ignored apps are active.
- Added overlay quick actions to block/unblock the focused app (usage access required).
- Added Usage Access gate/check + diagnostics line for focused-app overlay suppression reliability.
- Renamed app display label to IndividualAppVolumeControl (including accessibility label).
- Added focused-app blocklist search/filter in the overlay settings dialog.
- Added usage-stats foreground fallback for overlay suppression when accessibility focus is stale.
- Added an explicit foreground service type for the overlay watcher to avoid Android 15 FGS startup crashes.
- Switched playback active checks to reflection-only lookups to avoid hidden API compile errors; added missing
Contextimport for the accessibility volume key service. - Added overlay gating options: only show while audio plays, snooze timer, and focused-app blocklist.
- Added focused app tracking from Accessibility events to support overlay suppression.
- Made the overlay watcher notification more compact.
- Updated the accessibility service label to include the app name.
- Added safe active playback config retrieval with diagnostics logging to avoid crashes when permissions are missing.
- Added overlay/accessibility status to Setup Check + Diagnostics with quick action buttons to open settings.
- Added overlay addView failure logging and an accessibility-triggered overlay start error toast.
- Ensured the overlay watcher restarts on resume when enabled; added a toast when notification controls are used while controls are disabled.
- Added a toast fallback when the Accessibility service deep link is unavailable.
- Added a best-effort deep link to the Accessibility service settings from the overlay controls.
- Added a warning banner when overlay is enabled but the volume key Accessibility listener is disabled.
- Added overlay section status + button to open Accessibility settings for the volume key listener.
- Added an AccessibilityService volume-key listener that triggers the overlay without consuming volume changes.
- Avoided Android 14+ boot-time FGS crash by skipping boot-start for foreground services.
- Added Android 14+ boot notification with user-initiated start action for services.
- Fixed Manage Apps layout so action buttons stay within the visible area.
- Wired
:app:buildto package the Magisk module (modern debug) and print the module output path. - Added Magisk module output path to the build completion printout.
- Added a build-finalizer task to print APK output paths after
:app:build. - Documented debug APK output paths in
docs/BUILD.md. - Added Manage Apps UI for per-app audio attribute overrides (usage/content type filters).
- Added legacy multidex support (manifest + dependency), enabled core library desugaring, and pinned legacy core-ktx; ignored local build artifacts and tracked the bundled Magisk module asset.
- Added per-app audio attribute override storage and applied matching filter in playback control, plus diagnostics counts.
- Added available output device counts to routing-missing diagnostics details.
- Capped routing diagnostics detail length to avoid oversized reports.
- Expanded routing diagnostics details to include per-app output device info and failure reasons.
- Added location listener diagnostics to legacy Diagnostics screen for parity with modern report.
- Added location listener diagnostics (provider/time/accuracy/mock) to help validate live location updates.
- Suppressed deprecated PhoneStateListener usage warnings in PlaybackControllerService and annotated deprecated override; suppressed location permission lint on removeUpdates in LocationRuleManager.
- Fixed PlaybackControllerService pause/resume parsing issue, corrected VolumeStore default mute import parsing, and cleaned SetupStatus flag helper; added explicit deprecation annotation for LocationRuleManager status callback.
- Added per-app auto-resume overrides in Manage Apps and diagnostics reporting.
- Added auto-resume toggle in the main Audio settings section and diagnostics reporting.
- Added best-effort auto-resume for rule/mute-triggered pauses.
- Added diagnostics reporting for default mute behavior and per-app mute override count.
- Added global default mute behavior setting in the main UI.
- Added per-app mute behavior (mute-only vs mute+pause) stored with presets.
- Added audio focus rule actions (pause/duck/mute) with rule editor support.
- Added best-effort player pause support for focus rules.
- Added boot receiver to restart playback service and overlay watcher when enabled.
- Improved privileged detection (privateFlags + source dirs) in Setup Check and Diagnostics.
- Expanded notification controls with larger buttons, mute, 25/50/75% presets, and overlay shortcut.
- Clarified overlay header toggles (auto refresh/auto hide/output only).
- Added optional geofencing support (Play services) with a UI toggle and diagnostics reporting.
- Added optional background location updates via a broadcast receiver and toggle.
- Added legacy flavor with a minimal presets/diagnostics UI and a warning banner for API 16-25 devices.
- Added real location support: stored locations with live GPS/network updates and location permissions.
- Added location list management UI and live location diagnostics.
- Added app picker dialogs for rule/group package selection (search + multi-select).
- Added multi-condition rule editing (any/all active, time window validation, and location ids).
- Added edit-in-place for rule groups/rules and validation for group-id targets in the rules editor.
- Added a basic Rules screen to manage rule groups and simple rules (conditions + set-volume action).
- Added rules engine counts + enabled rule names to Diagnostics output.
- Added rules engine data models (groups, conditions, actions) with JSON import/export support.
- Wired rule evaluation into the playback service (co-active apps + time windows override presets).
- Documented rule format and legacy API 16-25 plan in docs.
- Added binary probes (magisk/ksud) to root manager detection and surfaced probe info in install dialog.
- Added module install dialog actions to try Magisk/KernelSU installs even when detection fails.
- Added KernelSU Next package detection for root manager identification.
- Added Diagnostics line to verify bundled module asset presence.
- Bundled the Magisk module in app assets and added in-app install flow with Magisk/KernelSU detection.
- Moved active volume quick-actions into the Active header row with compact 0/50/100 controls.
- Expanded overlay watcher to observe multiple volume settings keys (System/Secure) and react to mute/ringer broadcasts; force overlay on observer/broadcast signals.
- Added Magisk install helper button with copyable module/package info.
- Added prototype notification with per-app +/- controls (up to 3 active apps).
- Updated notification refresh to track per-app volume changes.
- Allow sliders to stay interactive even when controls are not ready (store presets with warning).
- Added overlay auto-hide preference and toggles in main UI + overlay header.
- Expanded overlay watcher to react to any stream volume changes (multi-stream signature) for better OEM volume-key detection.
- Marked foreground notifications as ongoing and only-alert-once.
- Added a Diagnostics button to request Bluetooth permission (Android 12+).
- Added a main screen Bluetooth permission button with App Info fallback when blocked.
- Added call-state listener to mute active playback during ringing/offhook calls and log state in diagnostics.
- Added Bluetooth codec info toast when selecting BT output devices.
- Shared output type label helper across main list and overlay.
- Added output type prefixes (BT/USB/etc) to output badges in main list and overlay.
- Added output-only filter toggle in main UI and overlay.
- Clarified Magisk install/overlay path in README and module README.
- Show selected output device badge in main list and overlay.
- Added routing stats to Diagnostics and updated compatibility checklist to include output routing validation.
- Added per-app output device selection and storage; apply preferred output device when possible.
- Renamed app/module display name and Magisk packaging paths to IndividualAppAudioVolumeControl.
- Updated compatibility validation workflow to use Diagnostics bundle + hidden API retry.
- Improved compatibility row format (markdown table-ready with Android version).
- Added Diagnostics bundle copy/share (report + presets + compatibility row).
- Added Diagnostics action to copy a prefilled compatibility table row.
- Added hidden API retry + error details to Diagnostics for easier policy validation.
- Added app icons and long-press package copy in the overlay rows.
- Expanded Diagnostics to report requested/granted permission status and missing critical permissions.
- Added overlay watcher diagnostics (signals, show reason, last active count) to aid Android 12-15 validation.
- Added per-app marker/segment configs with Manage Apps editor, export/import support, and slider rendering in main UI + overlay.
- Added control readiness gating with gray-out states in main UI and overlay.
- Added overlay auto-refresh toggle in main UI.
- Added tick markers + snap-to-segment resistance to main UI sliders.
- Added overlay refresh button and auto-refresh toggle to keep active app list current.
- Added mute/unmute icon button in overlay rows with restore behavior.
- Added segmented tick markers and snap-to-segment resistance for overlay sliders.
- Added overlay auto-refresh preference storage.
- Made overlay watcher more reliable (volume broadcast + polling fallback) and kept manual overlay open until closed.
- Updated Android Gradle Plugin to 8.13.2 and removed compileSdk 35 suppression.
- Added volume-button overlay service with active-app sliders and auto-hide.
- Added overlay watcher notification + preference toggle to show overlay on volume changes.
- Added overlay permission screen and main UI controls for permission + enable/disable.
- Added quick settings tile and notification action to open the overlay.
- Extended Manage Apps to select profiles and store presets per profile explicitly.
- Shared profile label utilities across UI + overlay.
- Added profile-aware preset keys (
u<userId>:package) with global fallback. - Applied profile-aware volume lookup in the playback service.
- Added profile filter control to main UI (work/personal separation).
- Reworked app rows to give names more space and move sliders to a second line.
- Replaced text "ACTIVE" badge with a compact indicator dot and instance count.
- Switched mute action to a speaker icon toggle with restore behavior.
- Added per-app info popup (package, install/update time, active timestamps).
- Tracked active timestamps per app for info dialogs.
- Documented profile preset keys and UX ideas in docs.
- Added initial app/service skeleton and Magisk module template.
- Added basic UI with active session list and preset list sliders.
- Added app icons, active indicators, and preset search filter.
- Added hidden API bypass attempts via VMRuntime and Settings.Global.
- Added periodic refresh and last-updated indicator in the UI.
- Added Gradle wrapper jar and updated wrapper scripts/config.
- Build attempt blocked by wrapper download (no network access in this environment).
- Added diagnostics screen and runtime stats tracking.
- Added Magisk module packaging script.
- Added diagnostics self-test action and service dump logging.
- Added diagnostics report copy/share actions.
- Documented offline Gradle distribution seeding.
- Added volume percentage labels next to sliders.
- Marked active apps within the presets list.
- Preset list now refreshes active badges when playback changes.
- Added per-app mute button in the UI.
- Added reset button to clear all stored presets.
- Added device/app flags to diagnostics report.
- Added live active package list to diagnostics report.
- Added hidden API attempt status to diagnostics report.
- Added stored preset count to diagnostics report.
- Added preset export/import via clipboard in diagnostics.
- Added "Max active" quick action.
- Added validation checklist to research notes.
- Added toast feedback for preset import.
- Added compatibility tracking doc.
- Pruned stale playback keys after each apply.
- Documented compatibility matrix in README.
- Persisted "show all apps" toggle in UI prefs.
- Added app version info to diagnostics.
- Added label ellipsize for long app names.
- Added notification channel description.
- Added active session count in UI header.
- Added preset count in UI header.
- Ignored metadata keys during preset import.
- Added version field to preset export.
- Added clear filter button to presets list.
- Added replace/share options for preset import/export.
- Added "Mute active" quick action.
- Added export tracking and metadata for presets.
- Added active config count to diagnostics.
- Switched module packaging script to portable shebang.
- Added "Active 50%" quick action.
- Added fallback setVolume signature handling.
- Documented preset UI in architecture notes.
- Added preset export/import format doc.
- Linked preset format in README.
- Added import error handling to diagnostics.
- Added active app count to service notification.
- Clarified preset export metadata in docs.
- Added FOREGROUND_SERVICE_MEDIA_PLAYBACK permission.
- Cached hidden method lookups in PlaybackUtils.
- Added POST_NOTIFICATIONS status to diagnostics.
- Added target SDK to diagnostics.
- Added package-name copy on long-press of app labels.
- Added audio permission status to diagnostics.
- Added feature summary to README.
- Added QUERY_ALL_PACKAGES status to diagnostics.
- Added INTERACT_ACROSS_USERS status to diagnostics.
- Added debuggable flag to diagnostics.
- Updated compatibility steps with diagnostics details.
- Documented setVolume fallback in architecture notes.
- Sorted preset export keys for readability.
- Added toast confirmation for diagnostics report copy.
- Added toast confirmation for package copy.
- Clarified privileged vs runtime permissions in permissions doc.
- Added active count to last-updated UI and ensured presets load when empty.
- Avoided hidden SDK constants in diagnostics so builds succeed.
- Ran assembleDebug; build succeeds with compileSdk 35 warning on AGP 8.5.2.
- Removed redundant initializers in hidden API helper.
- Suppressed compileSdk 35 AGP warning in gradle.properties.
- Documented compileSdk warning suppression in build notes.
- Noted hidden permission constants in permissions doc.
- Refresh diagnostics after preset export/share to show updated timestamps.
- Use reflection for privileged flag check in diagnostics.
- Sorted active packages in diagnostics report.
- Removed redundant preset refresh calls in main UI actions.
- Clarified POST_NOTIFICATIONS status output for pre-Android 13 devices.
- Added app package to diagnostics report.
- Added preset count metadata to preset exports.
- Added active package count line in diagnostics.
- Cached player setVolume lookup per proxy class for faster apply.
- Documented setVolume method caching in architecture notes.
- Improved empty-state messaging for presets list.
- Added explicit import-failure toast in diagnostics.
- Filtered metadata-like keys from preset export.
- Sorted package list in diagnostics dump logging.
- Documented
_preset_countmetadata in preset format notes. - Start foreground service with media playback type on Android 10+.
- Evict cached setVolume method on invocation failure.
- Skip NaN volumes in preset storage and export.
- Added quick-start instructions and reset confirmation dialog for kid-friendly UI.
- Simplified main screen labels and added a Help dialog.
- Simplified diagnostics labels and added confirmation for replace import.
- Request notification permission on Android 13+ to keep service visible.
- Added a simple readiness flag in diagnostics.
- Added a hint for the "Show all apps" toggle.
- Clarified empty active-audio message for kids.
- Renamed presets section to "Saved volumes".
- Added readiness hint text in diagnostics screen.
- Added setup check screen for kid-friendly validation.
- Added ready indicator and copy button in setup check screen.
- Added "What to fix next" guidance in setup check.
- Added AppCompat theme to prevent startup crash.
- Added toggle to include all installed apps in presets list.
- Added permissions reference doc.
- Preset list now prioritizes active apps.
- Documented module packaging script usage.
- Added POST_NOTIFICATIONS permission for Android 13+ foreground notifications.
- Added simple app icon cache in UI.
- Sorted active apps alphabetically by label.
- Default preset list now stays empty until search or "Show all apps" to reduce lag.
- Added "Search all installed apps" toggle with a minimum search length to avoid heavy loads.
- Added Manage Apps screen for adding packages or searching apps, keeping main list limited to saved apps.
- 2026-03-22