[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