Fixes high CPU usage after connecting to Android Auto during playback.
Removes busy‑wait loops in PlayerNotificationService and in library personalization code, replacing them with callback‑based async handling.
Previously the code used tight while loops to wait for async work:
while (libraryPersonalizationsDone > 0) { }
while (!this::browseTree.isInitialized) { }
If one callback failed or init was delayed (common when Android Auto connects/rebinds services), these loops never exited, pegging the CPU at ~100%.
This PR removes the spin‑loops:
Personalization loading now uses a counter (AtomicInteger/callback) to invoke completion when all libraries finish.
BrowseTree initialization inside onLoadChildren uses result.detach() + a small helper (waitForBrowseTree/onBrowseTreeInitialized) to defer sending results until browseTree is ready.
This avoids ANRs and runaway CPU usage, and aligns with MediaBrowserService’s async contract.
How have you tested this?
Built and ran Audiobookshelf Android app locally in debug.
Reproduced bug on master: while playback is active, connect Android Auto via Desktop Head Unit → CPU spikes >100% and app freezes.
Applied fix:
Reconnected Android Auto during playback.
CPU remains stable, UI responsive.
Verified browse menus display correctly after browseTree initializes.
Verified personalization logs show all libraries finishing.
Screenshots
N/A – changes are to background service / logs only.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.
## 📋 Pull Request Information
**Original PR:** https://github.com/advplyr/audiobookshelf-app/pull/1675
**Author:** [@laurisvr](https://github.com/laurisvr)
**Created:** 8/29/2025
**Status:** ✅ Merged
**Merged:** 8/31/2025
**Merged by:** [@advplyr](https://github.com/advplyr)
**Base:** `master` ← **Head:** `remove-busy-loops`
---
### 📝 Commits (2)
- [`361c55c`](https://github.com/advplyr/audiobookshelf-app/commit/361c55c5acb9fa357801bc447611aa2c418804c4) fix(media): remove busy‑wait loop in library personalization loading
- [`719e517`](https://github.com/advplyr/audiobookshelf-app/commit/719e517dda851f8feaf3470f21406648f745eae3) fix(androidauto): async handling of browseTree init instead of busy‑loop
### 📊 Changes
**2 files changed** (+65 additions, -25 deletions)
<details>
<summary>View changed files</summary>
📝 `android/app/src/main/java/com/audiobookshelf/app/media/MediaManager.kt` (+13 -13)
📝 `android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt` (+52 -12)
</details>
### 📄 Description
## Brief summary
Fixes high CPU usage after connecting to Android Auto during playback.
Removes busy‑wait loops in `PlayerNotificationService` and in library personalization code, replacing them with callback‑based async handling.
## Which issue is fixed?
Fixes #1446
## Pull Request Type
- Platform: **Android**
- Area: **native service / Android Auto media browser**
## In-depth Description
Previously the code used tight `while` loops to wait for async work:
- `while (libraryPersonalizationsDone > 0) { }`
- `while (!this::browseTree.isInitialized) { }`
If one callback failed or init was delayed (common when Android Auto connects/rebinds services), these loops never exited, pegging the CPU at ~100%.
This PR removes the spin‑loops:
- Personalization loading now uses a counter (`AtomicInteger`/callback) to invoke completion when all libraries finish.
- BrowseTree initialization inside `onLoadChildren` uses `result.detach()` + a small helper (`waitForBrowseTree/onBrowseTreeInitialized`) to defer sending results until `browseTree` is ready.
This avoids ANRs and runaway CPU usage, and aligns with MediaBrowserService’s async contract.
## How have you tested this?
- Built and ran Audiobookshelf Android app locally in debug.
- Reproduced bug on master: while playback is active, connect Android Auto via Desktop Head Unit → CPU spikes >100% and app freezes.
- Applied fix:
- Reconnected Android Auto during playback.
- CPU remains stable, UI responsive.
- Verified browse menus display correctly after `browseTree` initializes.
- Verified personalization logs show all libraries finishing.
## Screenshots
N/A – changes are to background service / logs only.
---
<sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
📋 Pull Request Information
Original PR: https://github.com/advplyr/audiobookshelf-app/pull/1675
Author: @laurisvr
Created: 8/29/2025
Status: ✅ Merged
Merged: 8/31/2025
Merged by: @advplyr
Base:
master← Head:remove-busy-loops📝 Commits (2)
361c55cfix(media): remove busy‑wait loop in library personalization loading719e517fix(androidauto): async handling of browseTree init instead of busy‑loop📊 Changes
2 files changed (+65 additions, -25 deletions)
View changed files
📝
android/app/src/main/java/com/audiobookshelf/app/media/MediaManager.kt(+13 -13)📝
android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt(+52 -12)📄 Description
Brief summary
Fixes high CPU usage after connecting to Android Auto during playback.
Removes busy‑wait loops in
PlayerNotificationServiceand in library personalization code, replacing them with callback‑based async handling.Which issue is fixed?
Fixes #1446
Pull Request Type
In-depth Description
Previously the code used tight
whileloops to wait for async work:while (libraryPersonalizationsDone > 0) { }while (!this::browseTree.isInitialized) { }If one callback failed or init was delayed (common when Android Auto connects/rebinds services), these loops never exited, pegging the CPU at ~100%.
This PR removes the spin‑loops:
AtomicInteger/callback) to invoke completion when all libraries finish.onLoadChildrenusesresult.detach()+ a small helper (waitForBrowseTree/onBrowseTreeInitialized) to defer sending results untilbrowseTreeis ready.This avoids ANRs and runaway CPU usage, and aligns with MediaBrowserService’s async contract.
How have you tested this?
browseTreeinitializes.Screenshots
N/A – changes are to background service / logs only.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.