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.56k stars 373 forks source link

The Huawei device failed crashed when displaying media notification #903

Closed MrWhhh closed 8 months ago

MrWhhh commented 9 months ago

Version

Media3 1.2.0

More version details

android.app.RemoteServiceException: Bad notification(tag=null, id=1001) posted from package com.xxx.xxx, crashing app(uid=10289, pid=26950): long overflow
    at android.app.ActivityThread.throwRemoteServiceException(ActivityThread.java:2591)
    at android.app.ActivityThread.access$4000(ActivityThread.java:311)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:3001)
    at android.os.Handler.dispatchMessage(Handler.java:117)
    at android.os.Looper.loopOnce(Looper.java:205)
    at android.os.Looper.loop(Looper.java:293)
    at android.app.ActivityThread.loopProcess(ActivityThread.java:9961)
    at android.app.ActivityThread.main(ActivityThread.java:9950)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:586)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1240)

Devices that reproduce the issue

Huawei

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Yes

Reproduction steps

lay

Expected result

Media playback success

Actual result

android.app.RemoteServiceException: Bad notification(tag=null, id=1001) posted from package com.xxx.xxx, crashing app(uid=10289, pid=26950): long overflow
    at android.app.ActivityThread.throwRemoteServiceException(ActivityThread.java:2591)
    at android.app.ActivityThread.access$4000(ActivityThread.java:311)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:3001)
    at android.os.Handler.dispatchMessage(Handler.java:117)
    at android.os.Looper.loopOnce(Looper.java:205)
    at android.os.Looper.loop(Looper.java:293)
    at android.app.ActivityThread.loopProcess(ActivityThread.java:9961)
    at android.app.ActivityThread.main(ActivityThread.java:9950)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:586)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1240)
Back traces ends.

Media

all meida

Bug Report

oceanjules commented 9 months ago

Hello @MrWhhh,

The information you provided is not enough to make it actionable for us. It would be useful to see what device you used and clear steps to reproduce the issue.

It would also be useful to see the bug report. If you're unable to share bug reports or test content publicly, please send them to android-media-github@google.com using a subject "Issue #903". Please also update this issue to indicate you’ve done this.

MrWhhh commented 9 months ago

@oceanjules The device I use is Huawei mate60pro, the system is Hongmeng4, and the music playing service is inherited from MediaLibraryService(). When I call exoplayer to play, other devices can normally send notifications and play, but there is a crash on Huawei mate60pro. Error log as above

WXFY commented 9 months ago

I have also encountered this error. It appears on the Huawei P40, and HarmonyOS 4 must appear.

wuhenge commented 8 months ago

When I turn off all notification permissions of the APP, there will be no crash, so this error should be a crash caused by the notification.

marcbaechinger commented 8 months ago

@MrWhhh Please provide repro steps with the demo app if you want us look into this. If we don't know how to repro we probably work on other issues first that are more actionable. I'm not sure when and whether we get such a Huawei device in our hands, but if we do and we don't have the repro steps with the demo app, it would be unfortunate.

Regarding this happening on Huawei only: while being not a politician nor a prophet - I'd also try to talk to Huawei directly. Personally, I have taken notice of Hongmeng4 in this issue for the first time. You know that story behind it probably better then I do.

MrWhhh commented 8 months ago

@marcbaechinger

browserFuture = MediaBrowser.Builder(
                this,
                SessionToken(
                    this,
                    ComponentName(this, MusicService::class.java)
                )
            )
                .buildAsync()

serivce inherits from MediaLibraryService() in the same way as Demo

class MusicService : MediaLibraryService() {

    lateinit var player: ExoPlayer
    lateinit var mediaLibrarySession: MediaLibrarySession

    private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)

    override fun onCreate() {
        super.onCreate()

        player = ExoPlayer.Builder(this)
            .setAudioAttributes(AudioAttributes.DEFAULT, !DataStoreEnum.RESTS_APP_PLAY.read(false))
            .setHandleAudioBecomingNoisy(true)
            .build()
        player.addListener(MyPlayer())

        val forwardingPlayer = @OptIn(UnstableApi::class) object : ForwardingPlayer(player){}
        mediaLibrarySession =
            MediaLibrarySession
                .Builder(this, forwardingPlayer, MySessionCallback())
                .build()
 }

    override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaLibrarySession? =
        mediaLibrarySession

    override fun onDestroy() {
        serviceScope.cancel()
        player.release()
        mediaLibrarySession.release()
        super.onDestroy()
    }

}
marcbaechinger commented 8 months ago

@MrWhhh Please provide repro steps with the demo app if you want us look into this.

WXFY commented 8 months ago

I myself pull the source code in the HarmonyOS 4 phone debugging found that the following code may cause long overflow exception.

long playbackStartTimeMs = getPlaybackStartTimeEpochMs(player);
boolean displayElapsedTimeWithChronometer = playbackStartTimeMs != C.TIME_UNSET;
builder
.setWhen(playbackStartTimeMs)
.setShowWhen(displayElapsedTimeWithChronometer)
.setUsesChronometer(displayElapsedTimeWithChronometer);

getPlaybackStartTimeEpochMs method returns the value Long.MIN_VALUE + 1 and then sets the setWhen method to have a long overflow exception. I tried to divide the value by 2 and it was normal.

marcbaechinger commented 8 months ago

@WXFY Thanks for investigation and reporting.

setWhen is documented to be the time at which the event occured. So setting C.TIME_UNSET as we do isn't correct and we can avoid this with a trivial change I think:

builder
    .setWhen(displayElapsedTimeWithChronometer ? playbackStartTimeMs : 0L)
    .setShowWhen(displayElapsedTimeWithChronometer)
    .setUsesChronometer(displayElapsedTimeWithChronometer);

I think a time at which the event occurred shouldn't be a negative value. I sent the change above in DefaultMediaNotificationProvider for review as it seems we violate what is documented. There will be an entry in this issue when the change lands here on GitHub.

It looks like this isn't a problem on other devices, I have tested the code below with API 28 and API 34 on Pixels and I can not repro the crash:

long playbackStartTimeMs = getPlaybackStartTimeEpochMs(player);
boolean displayElapsedTimeWithChronometer = playbackStartTimeMs != C.TIME_UNSET;
builder
    .setWhen(C.TIME_UNSET)
    .setShowWhen(displayElapsedTimeWithChronometer)
    .setUsesChronometer(displayElapsedTimeWithChronometer);

If you wanna do me a favor and you have the source already available, you can test the proposed fix above and test with the HarmonyOS 4 device to verify this actually helps.

WXFY commented 8 months ago

@WXFY Thanks for investigation and reporting.

setWhen is documented to be the time at which the event occured. So setting C.TIME_UNSET as we do isn't correct and we can avoid this with a trivial change I think:

builder
    .setWhen(displayElapsedTimeWithChronometer ? playbackStartTimeMs : 0L)
    .setShowWhen(displayElapsedTimeWithChronometer)
    .setUsesChronometer(displayElapsedTimeWithChronometer);

I think a time at which the event occurred shouldn't be a negative value. I sent the change above in DefaultMediaNotificationProvider for review as it seems we violate what is documented. There will be an entry in this issue when the change lands here on GitHub.

It looks like this isn't a problem on other devices, I have tested the code below with API 28 and API 34 on Pixels and I can not repro the crash:

long playbackStartTimeMs = getPlaybackStartTimeEpochMs(player);
boolean displayElapsedTimeWithChronometer = playbackStartTimeMs != C.TIME_UNSET;
builder
    .setWhen(C.TIME_UNSET)
    .setShowWhen(displayElapsedTimeWithChronometer)
    .setUsesChronometer(displayElapsedTimeWithChronometer);

If you wanna do me a favor and you have the source already available, you can test the proposed fix above and test with the HarmonyOS 4 device to verify this actually helps.

I tested the Huawei P40 HarmonyOS 4 with your modified code and it works normally.

marcbaechinger commented 8 months ago

Thanks for confirming. I'm closing this issue as the fix seems to work.