[Android] player: prevent audio player trigger and tips leak on SAF video playback
Riteshwar Poddar
git at videolan.org
Thu Sep 3 11:25:28 UTC 2026
vlc-android | branch: master | Riteshwar Poddar <riteshwar at zohomail.in> | Sun Aug 23 03:11:41 2026 +0530| [4e773d5546c331a57aa67d3cb8103f701f944228] | committer: Nicolas Pomepuy
player: prevent audio player trigger and tips leak on SAF video playback
When opening a video file via the Android Storage Access Framework
(SAF), FileUtils.getUri() resolves the content:// URI into an fd://<fd>
file descriptor URI. Because the path lacks a dot extension,
MediaWrapper.defineType() fails to identify the format and leaves
MediaWrapper.mType as -1 (TYPE_ALL / Unknown).
During playback initialization, PlaylistManager.playIndex() initiates
background playback to probe the unknown stream. Upon receiving
MediaPlayer.Event.Playing (with newMedia = true):
1. No SurfaceView is attached yet, causing player.isVideoPlaying() to
return false.
2. PlaylistManager evaluated:
`if (player.hasRenderer || !player.isVideoPlaying()) showAudioPlayer.value = true`
3. AudioPlayerContainerActivity observed this LiveData event, invoked
showAudioPlayer(), and set `showAudioPlayerWhenResumed = true`.
4. Shortly after (~20ms), LibVLC's demuxer detected video tracks
(MediaPlayer.Event.ESAdded), triggering switchToVideo().
5. While switchToVideo() launched VideoPlayerActivity and called
hideAudioPlayer(), `showAudioPlayerWhenResumed` was never reset to false.
Consequently, when the user finishes watching the video and returns to
MainActivity, onResume() evaluates `showAudioPlayerWhenResumed == true`
and calls showAudioPlayerImpl() -> initAudioPlayer(). On a fresh install
where PREF_AUDIOPLAYER_TIPS_SHOWN is false, this inflates
audio_player_tips.xml, erroneously displaying the Audio Tutorial overlay
on top of the Home screen.
Fix this by ensuring PlaylistManager only sets showAudioPlayer to true
if the media is explicitly forced to audio (MEDIA_FORCE_AUDIO) or has
no detectable video tracks (!player.canSwitchToVideo()). This preserves
standard audio files, context-menu "Play as audio", and in-player audio
mode transitions while preventing false triggers during video stream probing.
> https://code.videolan.org/videolan/vlc-android/commit/4e773d5546c331a57aa67d3cb8103f701f944228
---
application/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/application/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt b/application/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt
index f424cfa9fb..31f85062f4 100644
--- a/application/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt
+++ b/application/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt
@@ -1211,7 +1211,9 @@ class PlaylistManager(val service: PlaybackService) : MediaWrapperList.EventList
savePosition()
saveCurrentMedia()
newMedia = false
- if (player.hasRenderer || !player.isVideoPlaying()) showAudioPlayer.value = true
+ if (player.hasRenderer || (!player.isVideoPlaying() && (mw.hasFlag(MediaWrapper.MEDIA_FORCE_AUDIO) || !player.canSwitchToVideo()))) {
+ showAudioPlayer.value = true
+ }
savePlaycount(mw)
if (mw.title == mw.fileName || (mw.type == MediaWrapper.TYPE_STREAM && (mw.title != player.mediaplayer.media?.getMeta(IMedia.Meta.Title, true) || mw.artistName != player.mediaplayer.media?.getMeta(IMedia.Meta.Artist, true)))) {
// used for initial metadata update. We avoid the metadata load when the initial MediaPlayer.Event.ESSelected is sent to avoid race conditions
More information about the Android
mailing list