androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android
https://developer.android.com/media/media3
Apache License 2.0
1.74k stars 416 forks source link

Session service prevents process from terminating if swiped away from recents while the audio is playing #1269

Open nikushaa991 opened 7 months ago

nikushaa991 commented 7 months ago

Version

Media3 main branch

More version details

a154c98faa3290e9ca45a0e8dabd39c0d74842fc

Devices that reproduce the issue

Galaxy S22 ultra running android 14

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Yes

Reproduction steps

  1. Modify PlaybackService's onTaskRemoved so that it will terminate even if the music is running (Simply calling pauseAllPlayersAndStopSelf() is mentioned in the documentation, so I used just that) image
  2. Optionally add a static integer variable that gets printed and incremented at the start of the app to help with observing the bug image image
  3. Launch the app and start playing music
  4. Swipe the app away from recents while the music is playing
  5. Launch the app again

Expected result

The static integer value gets reset and prints the same value on both launches

Actual result

The static integer retains it's incremented value and prints different values

Media

Not applicable

Bug Report

marcbaechinger commented 7 months ago

Thanks! I believe this is a duplicate of #805

You can verify if this is the same issue by checking whether onTaskRemoved is actually called or not. If it's a duplicate, the onTaskRemoved callback is not called which is the reason why playback continues.

nikushaa991 commented 7 months ago

The music playback ends correctly, or did I misunderstand? I'll check if onTaskRemoved gets called in several hours, although I believe it does get called

marcbaechinger commented 7 months ago

If you try and you see it is called. Can you try to instead of calling pauseAllPlayersAndStopSelf to release all sessions and then call stopSelf directly?

In the demo app with a single session that would be:

  override fun onTaskRemoved(rootIntent: Intent?) {
    mediaLibrarySession.release()
    stopSelf()
  }

The reason is if that would help, then you have a controller that is still bound to the service when onTaskRemoved is called. Releasing the session would release all Media3 controller as well that potentially are bound to the service.

nikushaa991 commented 7 months ago

OnTaskRemoved does get called, pasted your code directly into DemoPlaybackService, but it didn't fix the issue

Dolakrishnan-Dev commented 7 months ago

Hi @marcbaechinger @nikushaa991 Any Update on issue!!! Where Media Session Service still remain Even When the App is Terminated during Playback.

Darkos-den commented 2 weeks ago

@marcbaechinger @nikushaa991 I can confirm that this issue relevant for 1.4.1 and 1.5.0-rc01. Is there any plan to address this issue in the near future or is it not a priority at the moment?

marcbaechinger commented 1 week ago

I can confirm that this issue relevant for 1.4.1 and 1.5.0-rc01

Thanks. I don't think the library can do much if this is a duplicate of #805. The library version shouldn't make a difference. I don't really know what you mean by 'this issue'. We may understand different things. If you are saying that onTaskRemoved is not called by the OS, then what I say applies. ELse you would have to be more precise.

805 is an OS bug that's not yet fixed on a device. You'd need to have this fixed in the OS. So you would need to at least tell us the device and OS that your using. I'm not able to evaluate this for every device due to not having every device, but the build number and the device would be information that is required to look into that.

In any case, I think you would need to provide us with a bit more information to make this actuionable.

Darkos-den commented 1 week ago

If you are saying that onTaskRemoved is not called by the OS, then what I say applies. ELse you would have to be more precise.

All lifecycle methods, including onTaskRemoved are called as expected. The only problem is that the process is not destroyed at the end. This only happens if you close the application during playback. If you pause or stop playback before closing the application, everything works correctly. Something prevents the process from ending correctly during active playback. Calling pause or stop in onTaskRemoved does not help. Adding any delays before calling stopSelf also does not help. I believe #389 also related to this problem.

marcbaechinger commented 1 week ago

Ok, I understand you see this on any version of the OS. Thanks for clarifying.

Darkos-den commented 1 week ago

The profiler does not record memory leaks and the application functions correctly after reopening, so I believe this is not a critical problem. However, the fact that the process continues to work after closing the application is still at least an unnecessary consumption of RAM and in general the situation is alarming.

marcbaechinger commented 1 week ago

I can second your observation. When I test this with the session demo app on a recent Android I see that behaviour. As you say, when not playing, then it works as expected. The app itself calls stopSelf(), the service is gone and as well the process. However, when we leave killing the service to the system, the process sticks:

Case 2) Swiping the app away when playing

When I then check

adb shell dumpsys activity services androidx.media3.demo

I see that the service is still around as expected. I also see the there is no client bound anymore as expected. And I see that the time is ticking for the system to kill the service:

startForegroundCount=1
infoAllowStartForeground=null
createTime=-47s404ms startingBgTimeout=--
lastActivity=-34s7ms restartTime=-47s139ms createdFromFg=true
startRequested=true delayedStop=false stopIfKilled=false callStart=true lastStartId=6

(there is infoAllowStartForeground=null and there is no entry for a bound client).

I also see that there are two processes for the demo app (I run the service in a different process in this example):

# pidof androidx.media3.demo.session:remote , pidof androidx.media3.demo.session                                        <
23506
23474

After a while the system indeed kills the service and the record for the service goeas away. Also the process for the service goes away, but a process sticks like you observed:

# pidof androidx.media3.demo.session:remote , pidof androidx.media3.demo.session                                        <
23506

that the process continues to work after closing the application is still at least an unnecessary consumption of RAM

No need to convince me this is an issue. :) It's definitely worth investigating why this is the case. I'd say from what I observed that the library does behave correct as far as I can tell. That that process sticks there seems wrong to mee too.

Darkos-den commented 1 week ago

I tested primarily the behavior when the service is expected to stop when the application is swiped(https://developer.android.com/media/media3/session/background-playback#service-lifecycle).

override fun onTaskRemoved(rootIntent: Intent?) {
  val player = mediaSession.player
  if (player.playWhenReady) {
    // Make sure the service is not in foreground.
    player.pause()
  }
  stopSelf()
}

onTaskRemoved is called. Playback stops. onDestroy is called. When I then check

adb shell dumpsys activity services androidx.media3.demo

I see that service destroyed. But the process remains alive.

marcbaechinger commented 1 week ago

Yup, thanks. I checked with system health. This is expected behavior. As long as there is no memory pressure the process is kept. My expectation that terminating the last app component would immediately kill the process was not correct.

When I launch the activity again, the process is reused and this is expected behavior.

Darkos-den commented 1 week ago

I've double checked all the logs and can confirm that the process is in the cch+ state after swiping the app, which is, as far as I understand, acceptable behavior on the Android system. This can lead to unexpected results when using static fields, as described in the original request, but this is more related to the specifics of the system than to the player library itself. I believe this covers the issue, but it would be useful to indicate somewhere in the documentation the likelihood of this behavior so that it is not a surprise.