Skip to content

Fix part of #6446: Fix lock contention ANR in AudioFragment and AudioPlayerController - #6464

Open
Kishan8548 wants to merge 9 commits into
oppia:developfrom
Kishan8548:fix-6446-audio-fragment-lock-contention
Open

Kishan8548 wants to merge 9 commits into
oppia:developfrom
Kishan8548:fix-6446-audio-fragment-lock-contention

Conversation

@Kishan8548

@Kishan8548 Kishan8548 commented Sep 16, 2026 •

Copy link
Copy Markdown
Collaborator

Explanation

Fixes part of #6446

Fixes input lock contention and ANR issues in AudioFragment and AudioPlayerController.

Root Cause

  1. Synchronous calls to MediaPlayer.reset() and MediaPlayer.release() were executed on the main UI thread. During network I/O, Android's internal MediaHTTPConnection binder thread holds internal locks, causing the main thread to block and trigger ANRs.
  2. AudioViewModel.loadAudio() was re-triggered on every ephemeral state compute even if the requested voiceover audio URI was already loaded, causing redundant resets and re-loads.

Solution

  1. AudioViewModel:
    • Tracked currentLoadedAudioUri to short-circuit redundant loadAudio() invocations when the target URI is already active.
    • Cleared the tracked URI on reset, release, and abort.
  2. AudioPlayerController:
    • Injected @BackgroundDispatcher to offload blocking MediaPlayer operations (reset(), prepareDataSource(), and release()) via Kotlin coroutines.
    • Used a suspending Mutex to serialize MediaPlayer lifecycle operations in background jobs without blocking the main UI thread.
    • Confined audioLock (ReentrantLock) strictly to fast in-memory state mutations so UI thread calls (pause(), play(), seekTo()) are never blocked waiting on I/O.
    • Tracked activeLoadJob to cancel stale in-flight loads upon subsequent operations.
  3. Tests:
    • Synchronized Robolectric ShadowMediaPlayer events with coroutines using testCoroutineDispatchers.runCurrent().
    • Added concurrency tests in AudioPlayerControllerTest for rapid sequential loads and mid-load teardowns.
    • Added test in AudioFragmentTest to verify that repeated state updates with the same audio source keep the audio playing without reloading.

Essential Checklist

  • The PR title starts with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".)
  • The explanation section above starts with "Fixes #bugnum: " (If this PR fixes part of an issue, use instead: "Fixes part of #bugnum: ...".)
  • Any changes to scripts/assets files have their rationale included in the PR explanation.
  • The PR follows the style guide.
  • The PR does not contain any unnecessary code changes from Android Studio (reference).
  • The PR is made from a branch that's not called "develop" and is up-to-date with "develop".
  • The PR is assigned to the appropriate reviewers (reference).

Disclosure of LLM Usage

  • Did you use AI/LLMs when working on this PR? Yes
  • If yes, describe the extent AI was used: Brainstorming the background coroutine and mutex approach, understanding thread lock contention, and discussing test edge cases.

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report

Results

Number of files assessed: 25
Overall Coverage: 0.00%
Coverage Analysis: PASS ✅

Exempted coverage

Files exempted from coverage
File Exemption Reason
QuestionAssessmentProgressController.ktdomain/src/main/java/org/oppia/android/domain/question/QuestionAssessmentProgressController.kt
This file is incompatible with code coverage tooling; skipping coverage check.
ExplorationProgressController.ktdomain/src/main/java/org/oppia/android/domain/exploration/ExplorationProgressController.kt
This file is incompatible with code coverage tooling; skipping coverage check.
HintsAndSolutionProdModule.ktdomain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionProdModule.kt
This file is incompatible with code coverage tooling; skipping coverage check.
HintHandlerDebugImpl.ktdomain/src/main/java/org/oppia/android/domain/hintsandsolution/HintHandlerDebugImpl.kt
This file is incompatible with code coverage tooling; skipping coverage check.
HintsAndSolutionDebugModule.ktdomain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionDebugModule.kt
This file is incompatible with code coverage tooling; skipping coverage check.
HintHandlerProdImpl.ktdomain/src/main/java/org/oppia/android/domain/hintsandsolution/HintHandlerProdImpl.kt
This file is incompatible with code coverage tooling; skipping coverage check.
HintHandler.ktdomain/src/main/java/org/oppia/android/domain/hintsandsolution/HintHandler.kt
This file is exempted from having a test file; skipping coverage check.
AudioPlayerController.ktdomain/src/main/java/org/oppia/android/domain/audio/AudioPlayerController.kt
This file is incompatible with code coverage tooling; skipping coverage check.
QuestionPlayerFragmentPresenter.ktapp/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerFragmentPresenter.kt
This file is exempted from having a test file; skipping coverage check.
QuestionPlayerActivityPresenter.ktapp/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityPresenter.kt
This file is exempted from having a test file; skipping coverage check.
QuestionPlayerFragment.ktapp/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerFragment.kt
This file is exempted from having a test file; skipping coverage check.
QuestionPlayerActivity.ktapp/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivity.kt
This file is incompatible with code coverage tooling; skipping coverage check.
ExplorationFragment.ktapp/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragment.kt
This file is exempted from having a test file; skipping coverage check.
ExplorationActivity.ktapp/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivity.kt
This file is incompatible with code coverage tooling; skipping coverage check.
ExplorationFragmentPresenter.ktapp/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragmentPresenter.kt
This file is exempted from having a test file; skipping coverage check.
ExplorationActivityPresenter.ktapp/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivityPresenter.kt
This file is exempted from having a test file; skipping coverage check.
StateFragment.ktapp/src/main/java/org/oppia/android/app/player/state/StateFragment.kt
This file is incompatible with code coverage tooling; skipping coverage check.
StateFragmentPresenter.ktapp/src/main/java/org/oppia/android/app/player/state/StateFragmentPresenter.kt
This file is exempted from having a test file; skipping coverage check.
StateFragmentTestActivityPresenter.ktapp/src/main/java/org/oppia/android/app/player/state/testing/StateFragmentTestActivityPresenter.kt
This file is exempted from having a test file; skipping coverage check.
StateFragmentTestActivity.ktapp/src/main/java/org/oppia/android/app/player/state/testing/StateFragmentTestActivity.kt
This file is exempted from having a test file; skipping coverage check.
AudioViewModel.ktapp/src/main/java/org/oppia/android/app/player/audio/AudioViewModel.kt
This file is exempted from having a test file; skipping coverage check.
AudioFragment.ktapp/src/main/java/org/oppia/android/app/player/audio/AudioFragment.kt
This file is incompatible with code coverage tooling; skipping coverage check.
HintsAndSolutionDialogFragment.ktapp/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragment.kt
This file is exempted from having a test file; skipping coverage check.
HintsAndSolutionListener.ktapp/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionListener.kt
This file is exempted from having a test file; skipping coverage check.
HintsAndSolutionDialogFragmentPresenter.ktapp/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragmentPresenter.kt
This file is exempted from having a test file; skipping coverage check.

Refer test_file_exemptions.textproto for the comprehensive list of file exemptions and their required coverage percentages.

To learn more, visit the Oppia Android Code Coverage wiki page

@Kishan8548
Kishan8548 marked this pull request as ready for review September 17, 2026 16:42
@Kishan8548
Kishan8548 requested review from a team as code owners September 17, 2026 16:42
@Kishan8548
Kishan8548 requested review from adhiamboperes and a lite review from Copilot September 17, 2026 16:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are correctness issues around cancellation/retry behavior (stale cancelled jobs can still start prepares, and URI caching can block retries after failures).

Get a fresh assessment by requesting another Copilot review.

Pull request overview

This PR addresses ANRs caused by MediaPlayer.reset()/release() blocking the UI thread during network-backed audio operations, and reduces redundant audio reloads triggered by repeated ephemeral state recomputation in the player UI.

Changes:

  • Offloads blocking MediaPlayer lifecycle operations to a background dispatcher and serializes them via a coroutine Mutex.
  • Adds URI-level short-circuiting in AudioViewModel to avoid reloading the same voiceover repeatedly.
  • Updates/extends Robolectric tests to synchronize coroutine execution and cover rapid load/teardown scenarios.
File summaries
File Description
domain/src/main/java/org/oppia/android/domain/audio/AudioPlayerController.kt Moves reset/release/prepare sequencing off the main thread and adds coroutine-based serialization/cancellation.
app/src/main/java/org/oppia/android/app/player/audio/AudioViewModel.kt Tracks the currently loaded voiceover URI to prevent redundant changeDataSource() calls.
domain/src/test/java/org/oppia/android/domain/audio/AudioPlayerControllerTest.kt Adjusts tests for coroutine scheduling and adds concurrency-focused controller tests.
app/src/sharedTest/java/org/oppia/android/app/player/audio/AudioFragmentTest.kt Adds a regression test to ensure repeated same-audio state updates don’t restart playback.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread domain/src/main/java/org/oppia/android/domain/audio/AudioPlayerController.kt Outdated
@adhiamboperes

Copy link
Copy Markdown
Contributor

@Kishan8548, please be sure to assign a reviewer if the PR is ready.

@Kishan8548

Kishan8548 commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator Author

PTAL @Neer-rn

@oppiabot

oppiabot Bot commented Sep 18, 2026

Copy link
Copy Markdown

Unassigning @Kishan8548 since a re-review was requested. @Kishan8548, please make sure you have addressed all review comments. Thanks!

@Neer-rn Neer-rn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work @Kishan8548. The PR mostly looks good, I have left few comments PTAL.

Comment thread domain/src/main/java/org/oppia/android/domain/audio/AudioPlayerController.kt Outdated
@oppiabot

oppiabot Bot commented Sep 19, 2026

Copy link
Copy Markdown

Hi @Kishan8548, it looks like some changes were requested on this pull request by @Neer-rn. PTAL. Thanks!

@Kishan8548

Copy link
Copy Markdown
Collaborator Author

@Neer-rn PTAL, addressed all requested changes and added corresponding tests.

@oppiabot

oppiabot Bot commented Sep 20, 2026

Copy link
Copy Markdown

Unassigning @Kishan8548 since a re-review was requested. @Kishan8548, please make sure you have addressed all review comments. Thanks!

@Neer-rn Neer-rn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Kishan8548 I again reviewed your PR but with the help of LLM this time and found a few more issues that need to be addressed. Left few comments PTAL.

Comment thread domain/src/main/java/org/oppia/android/domain/audio/AudioPlayerController.kt Outdated
Comment thread domain/src/main/java/org/oppia/android/domain/audio/AudioPlayerController.kt Outdated
@oppiabot oppiabot Bot unassigned Neer-rn Sep 21, 2026
@oppiabot

oppiabot Bot commented Sep 21, 2026

Copy link
Copy Markdown

Unassigning @Neer-rn since the review is done.

@oppiabot

oppiabot Bot commented Sep 21, 2026

Copy link
Copy Markdown

Hi @Kishan8548, it looks like some changes were requested on this pull request by @Neer-rn. PTAL. Thanks!

@oppiabot

oppiabot Bot commented Sep 24, 2026

Copy link
Copy Markdown

Hi @Kishan8548, it looks like some changes were requested on this pull request by @Neer-rn. PTAL. Thanks!

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report

Results

Number of files assessed: 43
Overall Coverage: 92.72%
Coverage Analysis: PASS ✅

Passing coverage

Files with passing code coverage
File Coverage Lines Hit Status Min Required
LiTagHandler.ktutility/src/main/java/org/oppia/android/util/parser/html/LiTagHandler.kt
90.80% 148 / 163 ✅ 70%
TestFileCheck.ktscripts/src/java/org/oppia/android/scripts/testfile/TestFileCheck.kt
99.03% 204 / 206 ✅ 70%
UpdateRolloutPermille.ktscripts/src/java/org/oppia/android/scripts/release/UpdateRolloutPermille.kt
86.84% 66 / 76 ✅ 70%
UploadChangelogToPlayConsole.ktscripts/src/java/org/oppia/android/scripts/release/UploadChangelogToPlayConsole.kt
86.92% 93 / 107 ✅ 70%
SurveyProgressController.ktdomain/src/main/java/org/oppia/android/domain/survey/SurveyProgressController.kt
92.76% 269 / 290 ✅ 70%
SurveyGatingController.ktdomain/src/main/java/org/oppia/android/domain/survey/SurveyGatingController.kt
97.14% 34 / 35 ✅ 70%
AppStartupStateController.ktdomain/src/main/java/org/oppia/android/domain/onboarding/AppStartupStateController.kt
91.67% 77 / 84 ✅ 70%

Exempted coverage

Files exempted from coverage
File Exemption Reason
AccessibilityServiceImpl.ktutility/src/main/java/org/oppia/android/util/accessibility/AccessibilityServiceImpl.kt
This file is exempted from having a test file; skipping coverage check.
HtmlParser.ktutility/src/main/java/org/oppia/android/util/parser/html/HtmlParser.kt
This file is incompatible with code coverage tooling; skipping coverage check.
SplashActivityPresenter.ktapp/src/main/java/org/oppia/android/app/splash/SplashActivityPresenter.kt
This file is exempted from having a test file; skipping coverage check.
SplashActivity.ktapp/src/main/java/org/oppia/android/app/splash/SplashActivity.kt
This file is incompatible with code coverage tooling; skipping coverage check.
AudioFragment.ktapp/src/main/java/org/oppia/android/app/player/audio/AudioFragment.kt
This file is incompatible with code coverage tooling; skipping coverage check.
AudioViewModel.ktapp/src/main/java/org/oppia/android/app/player/audio/AudioViewModel.kt
This file is exempted from having a test file; skipping coverage check.
StateFragmentPresenter.ktapp/src/main/java/org/oppia/android/app/player/state/StateFragmentPresenter.kt
This file is exempted from having a test file; skipping coverage check.
StateFragment.ktapp/src/main/java/org/oppia/android/app/player/state/StateFragment.kt
This file is incompatible with code coverage tooling; skipping coverage check.
StateFragmentTestActivity.ktapp/src/main/java/org/oppia/android/app/player/state/testing/StateFragmentTestActivity.kt
This file is exempted from having a test file; skipping coverage check.
StateFragmentTestActivityPresenter.ktapp/src/main/java/org/oppia/android/app/player/state/testing/StateFragmentTestActivityPresenter.kt
This file is exempted from having a test file; skipping coverage check.
ExplorationActivityPresenter.ktapp/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivityPresenter.kt
This file is exempted from having a test file; skipping coverage check.
ExplorationFragment.ktapp/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragment.kt
This file is exempted from having a test file; skipping coverage check.
ExplorationFragmentPresenter.ktapp/src/main/java/org/oppia/android/app/player/exploration/ExplorationFragmentPresenter.kt
This file is exempted from having a test file; skipping coverage check.
ExplorationActivity.ktapp/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivity.kt
This file is incompatible with code coverage tooling; skipping coverage check.
HintsAndSolutionListener.ktapp/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionListener.kt
This file is exempted from having a test file; skipping coverage check.
HintsAndSolutionDialogFragment.ktapp/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragment.kt
This file is exempted from having a test file; skipping coverage check.
HintsAndSolutionDialogFragmentPresenter.ktapp/src/main/java/org/oppia/android/app/hintsandsolution/HintsAndSolutionDialogFragmentPresenter.kt
This file is exempted from having a test file; skipping coverage check.
ContinueButtonView.ktapp/src/main/java/org/oppia/android/app/customview/ContinueButtonView.kt
This file is exempted from having a test file; skipping coverage check.
QuestionPlayerFragmentPresenter.ktapp/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerFragmentPresenter.kt
This file is exempted from having a test file; skipping coverage check.
QuestionPlayerFragment.ktapp/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerFragment.kt
This file is exempted from having a test file; skipping coverage check.
QuestionPlayerActivityPresenter.ktapp/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityPresenter.kt
This file is exempted from having a test file; skipping coverage check.
QuestionPlayerActivity.ktapp/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivity.kt
This file is incompatible with code coverage tooling; skipping coverage check.
ChapterSummaryViewModel.ktapp/src/main/java/org/oppia/android/app/topic/lessons/ChapterSummaryViewModel.kt
This file is exempted from having a test file; skipping coverage check.
StorySummaryViewModel.ktapp/src/main/java/org/oppia/android/app/topic/lessons/StorySummaryViewModel.kt
This file is exempted from having a test file; skipping coverage check.
TopicLessonsFragment.ktapp/src/main/java/org/oppia/android/app/topic/lessons/TopicLessonsFragment.kt
This file is incompatible with code coverage tooling; skipping coverage check.
TopicLessonsFragmentPresenter.ktapp/src/main/java/org/oppia/android/app/topic/lessons/TopicLessonsFragmentPresenter.kt
This file is exempted from having a test file; skipping coverage check.
FrozenReleaseConfig.ktscripts/src/java/org/oppia/android/scripts/release/FrozenReleaseConfig.kt
This file is exempted from having a test file; skipping coverage check.
HintHandler.ktdomain/src/main/java/org/oppia/android/domain/hintsandsolution/HintHandler.kt
This file is exempted from having a test file; skipping coverage check.
HintHandlerDebugImpl.ktdomain/src/main/java/org/oppia/android/domain/hintsandsolution/HintHandlerDebugImpl.kt
This file is incompatible with code coverage tooling; skipping coverage check.
HintsAndSolutionProdModule.ktdomain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionProdModule.kt
This file is incompatible with code coverage tooling; skipping coverage check.
HintsAndSolutionDebugModule.ktdomain/src/main/java/org/oppia/android/domain/hintsandsolution/HintsAndSolutionDebugModule.kt
This file is incompatible with code coverage tooling; skipping coverage check.
HintHandlerProdImpl.ktdomain/src/main/java/org/oppia/android/domain/hintsandsolution/HintHandlerProdImpl.kt
This file is incompatible with code coverage tooling; skipping coverage check.
AudioPlayerController.ktdomain/src/main/java/org/oppia/android/domain/audio/AudioPlayerController.kt
This file is incompatible with code coverage tooling; skipping coverage check.
ExplorationProgressController.ktdomain/src/main/java/org/oppia/android/domain/exploration/ExplorationProgressController.kt
This file is incompatible with code coverage tooling; skipping coverage check.
ExplorationActiveTimeController.ktdomain/src/main/java/org/oppia/android/domain/exploration/ExplorationActiveTimeController.kt
This file is incompatible with code coverage tooling; skipping coverage check.
QuestionAssessmentProgressController.ktdomain/src/main/java/org/oppia/android/domain/question/QuestionAssessmentProgressController.kt
This file is incompatible with code coverage tooling; skipping coverage check.

Refer test_file_exemptions.textproto for the comprehensive list of file exemptions and their required coverage percentages.

To learn more, visit the Oppia Android Code Coverage wiki page

@Kishan8548

Copy link
Copy Markdown
Collaborator Author

@Neer-rn PTAL

@Kishan8548 Kishan8548 assigned Neer-rn and unassigned Kishan8548 Sep 26, 2026

@Neer-rn Neer-rn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work @Kishan8548. Great work!!!

@oppiabot oppiabot Bot unassigned Neer-rn Sep 27, 2026
@oppiabot

oppiabot Bot commented Sep 27, 2026

Copy link
Copy Markdown

Unassigning @Neer-rn since they have already approved the PR.

@oppiabot

oppiabot Bot commented Sep 27, 2026

Copy link
Copy Markdown

Assigning @adhiamboperes for code owner reviews. Thanks!

@adhiamboperes adhiamboperes left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Kishan8548!

This PR fixes a part of the ANR, but not all of it, so I would propose the title and headline to reflect that.

  • Duplicate loading is partially fixed. AudioViewModel skipped reloading the same URI once audio was prepared, playing, paused, or completed. It still restarted the same source while loading, which is the particularly risky case.
  • Some protection added against stale callbacks. Load IDs and player identity checks helped reject obsolete preparation callbacks.
  • Main-thread blocking is not yet fixed. reset(), release(), and other media operations still run synchronously under audioLock. Both paths in the ANR reports remained.
  • Progress polling moved in the wrong direction. The changes explicitly moved media position reads onto the main thread.

Do you think that you may be able to fix the outstanding issues in this PR? Alternatively, we can merge this PR as is, as "Fixes part of #".

What is left:

  • give MediaPlayer a dedicated background thread with a Looper and serialize the player's lifecycle on that thread.
  • avoid making the main thread wait on a lock held while MediaPlayer operations are running.

nextUpdateJob = CoroutineScope(backgroundDispatcher).launch {
updateSeekBar()
nextUpdateJob = CoroutineScope(blockingDispatcher).launch {
withContext(Dispatchers.Main) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This switches to Dispatchers.Main before reading isPlaying, currentPosition, and duration under audioLock. Previously these reads ran in the background. Keep media reads on the player’s owning thread and dispatch only the resulting UI state.

The ANR is likely caused by making synchronous calls on the main thread while an audio network operation is still in progress.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Removed withContext(Dispatchers.Main) from scheduleNextSeekBarUpdate so that isPlaying, currentPosition, and duration reads stay on the background blockingDispatcher thread under audioLock, and dispatched the resulting progress via postValue().


if (languageCodeForDataSource != null) {
val targetUri = voiceOverToUri(voiceoverMap[languageCodeForDataSource])
val currentStatus = (playProgressResultLiveData.value as? AsyncResult.Success)?.value?.type

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate requests still restart audio while it is loading.
This only skips loading for successful prepared/playback states. While the source is AsyncResult.Pending, another request for the same URI calls changeDataSource() again. The setter followed by loadMainContentAudio() can therefore still reset an in-flight network request. Track and deduplicate the requested source during preparation too, while preserving explicit retry behavior.

@Kishan8548 Kishan8548 Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Updated AudioViewModel to track the requested audio source identity (currentLoadedAudioUri, currentLoadedContentId, currentLoadedHasFeedback) and deduplicate in-flight requests while the source is in Pending/PREPARING. This prevents rapid duplicate calls (such as setting the language code followed by loadMainContentAudio()) from restarting an in-flight fetch, while preserving explicit retry behavior when reloadingMainContent == true or when recovering from AsyncResult.Failure.

@adhiamboperes

Copy link
Copy Markdown
Contributor

On further thought, #6446 (comment) describes a much larger refactor, so I think it is best to keep the current PR scope as fixing part of the issue.

Do you think that you may be able to fix the outstanding issues in this PR? Alternatively, we can merge this PR as is, as "Fixes part of #".

What is left:

  • give MediaPlayer a dedicated background thread with a Looper and serialize the player's lifecycle on that thread.
  • avoid making the main thread wait on a lock held while MediaPlayer operations are running.

@oppiabot

oppiabot Bot commented Oct 6, 2026

Copy link
Copy Markdown

Hi @Kishan8548, I'm going to mark this PR as stale because it hasn't had any updates for 7 days. If no further activity occurs within 7 days, it will be automatically closed so that others can take up the issue.
If you are still working on this PR, please make a follow-up commit within 3 days (and submit it for review, if applicable). Please also let us know if you are stuck so we can help you! If you're unsure how to reassign this PR to a reviewer, please make sure to review the wiki page that details the Guidance on submitting PRs.

@oppiabot oppiabot Bot added the stale Corresponds to items that haven't seen a recent update and may be automatically closed. label Oct 6, 2026
@Neer-rn

Neer-rn commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator

@Kishan8548 PTAL at adhiambo's comments.

@oppiabot oppiabot Bot removed the stale Corresponds to items that haven't seen a recent update and may be automatically closed. label Oct 6, 2026
@Kishan8548

Kishan8548 commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator Author

@Neer-rn I am a little busy with my college exams, i'll work on the requested comments in some days.

@Kishan8548 Kishan8548 changed the title Fix #6446: Fix lock contention ANR in AudioFragment and AudioPlayerController Fixes part of #6446: Fix lock contention ANR in AudioFragment and AudioPlayerController Oct 6, 2026
@Kishan8548 Kishan8548 changed the title Fixes part of #6446: Fix lock contention ANR in AudioFragment and AudioPlayerController Fix part of #6446: Fix lock contention ANR in AudioFragment and AudioPlayerController Oct 6, 2026
@Kishan8548

Copy link
Copy Markdown
Collaborator Author

@Neer-rn PTAL, addressed all requested changes, one unit test timed out due to runner cancellation.

@oppiabot

oppiabot Bot commented Oct 11, 2026

Copy link
Copy Markdown

Unassigning @Kishan8548 since a re-review was requested. @Kishan8548, please make sure you have addressed all review comments. Thanks!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants