Skip to content

ForegroundServiceDidNotStartInTimeException due to dropped KeyCode. KEYCODE_HEADSETHOOK #2768

@johngray1965

Description

@johngray1965

Version

Media3 main branch

More version details

No response

Devices that reproduce the issue

Samsung devices are the vast majority of the crashes.

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

No

Reproduction steps

I can reproduce the issue via unit tests

Expected result

The app doesn't crash.

Actual result

      Fatal Exception: android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{f5d3566 u0 xxxx/xxxxService}
   at android.app.ActivityThread.generateForegroundServiceDidNotStartInTimeException(ActivityThread.java:2118)
   at android.app.ActivityThread.throwRemoteServiceException(ActivityThread.java:2089)
   at android.app.ActivityThread.-$$Nest$mthrowRemoteServiceException()
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2354)
   at android.os.Handler.dispatchMessage(Handler.java:106)
   at android.os.Looper.loopOnce(Looper.java:211)
   at android.os.Looper.loop(Looper.java:300)
   at android.app.ActivityThread.main(ActivityThread.java:8227)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1028)

Media

I've had an ongoing issue with ForegroundServiceDidNotStartInTimeExceptions. I implement onPlaybackResumption, and I have a MediaButtonReceiver that implements shouldStartForegroundService to verify I have something to play. My service implements MediaLibraryService and I have a custom player. Over the past few months, I've been adding Google Analytics events at various points. When the crashes occur, onPlaybackResumption isn't called. I just overrode onMediaButtonEvent, it just logs an event and returns super. onMediaButtonEvent is called. It's called from onMediaButtonEvent in MediaSessionImpl. I'm also logging the intent. The intent is always something like this:
Intent { act=android.intent.action.MEDIA_BUTTON flg=0x10000010 cmp=xxxx/xxxxrService (has extras) } Bundle[android.intent.extra.PACKAGE_NAME=android, android.intent.extra.KEY_EVENT=KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_HEADSETHOOK, scanCode=0, metaState=0, flags=0x8, repeatCount=0, eventTime=617362637000000, downTime=617362634000000, deviceId=-1, source=0x101, displayId=-1 }]
Its always KEYCODE_HEADSETHOOK, always repeatCount=0. I've traced through the code in MediaSessionImpl, I see right after callback.onMediaButtonEvent, it does a swicth with a case for KEYCODE_HEADSETHOOK. With the info I have, it's hard to know which branch its hits there. One branch tries to play/pause without calling onPlaybackResumption (so I haven't loaded anything to play). I see doubleTapCompleted is true, then the KEYCODE_HEADSETHOOK will be changed to KEYCODE_MEDIA_NEXT in applyMediaButtonKeyEvent (called at the bottom MediaSessionImpl.onMediaButtonEvent). Otherwise KEYCODE_HEADSETHOOK doesn't appear to get handled. I may well have missed something in my walk through on the code, but regardless, the bottom line is onPlaybackResumption is never called, so we don't even attempt to play anything. Thus the timeout.

Bug Report

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions