Acknowledged
CIQQA-3116

Simulator: If onAppinstall() or onAppUpdate() are overridden, and (BG) makeWebRequest()'s response callback calls Background.exit(), onBackgroundData() is not called

This problem exists on both Windows and Mac, on SDK 8.1.1 (fr955). I also tested on 7.4.1 and 6.4.2 (fr935), and the same problem exists on those SDKs.

On a real fr955 (built with SDK 8.1.1), this problem does not exist.

Related discussion at: https://forums.garmin.com/developer/connect-iq/f/discussion/408604/onbackgrounddata-not-called-from-when-background-exit-is-called-from-makewebrequest-callback

Code which reproduces this problem: https://litdev.uk/stuff/bgwfApp.mc

(I am not the OP for that thread or code. Sorry for the plain text urls, but the forum is broken)

All credit goes to StevenX for rediscovering the bug and jim_m_58 for finding the workaround.

--

In the code that reproduces the problem:

- the app type is watchface

- onAppInstall and onAppUpdate are overridden

- registerForTemporalEvents is called in the foreground

- the background implements onTemporalEvent(), which calls makeWebRequest

- makeWebRequest's response callback calls Background.exit(). The bug is that onBackgroundData() is never called in this case.

(Note that we are sure the response callback itself is called, because it logs messages to the console)

However, if Background.exit() is called directly from onTemporalEvent(), then onBackgroundData() is called as expected.

This behaviour is not specific to temporal events. The exact same behaviour can be seen with registerForStepsEvent() / onSteps(), for example.

I think the two main elements that trigger the bug are:

1) onAppInstall and onAppUpdate are overridden

2) makeWebRequest is called in the background [during the handling of *some* event, like a temporal event or steps event] and the response callback of makeWebRequest calls Background.exit(). I think it has something to do with the background process "scheduling" a callback via makeWebRequest, returning control to the non-app code without calling Background.exit(), and the "scheduled" callback calling Background.exit(). In other words, if Background.exit() is called before control is initially returned to the non-app code, there's no problem.

I assume that makeImageRequest() would also trigger the bug, but I haven't tried it. I also assume that any other function which can "schedule" a callback would trigger the bug (are there any others besides make*Request(), which can be used in the background?)

  • > Are you sure that all that is in the title really needed? I mean does it only happen in case it's a makeWebRequest? My guess is it would also happen in temporal events.

    To answer these questions more simply.

    "Are you sure that all that is in the title really needed? I mean does it only happen in case it's a makeWebRequest?"

    I only reproduced this with makeWebRequest in the BG although you're welcome to try to reproduce it other ways. My guess would be that if Timer.Timer() could be used in the bg, then it would also trigger this bug, but it can't. I'd guess that any other function which can "schedule" a callback for "later" (outside of the current execution context) would also trigger the bug. Surely makeImageRequest() would be a good candidate.

    It seems to me that Garmin has everything they need to reproduce and fix the bug, and that other devs can see this title and make sense of the circumstances which would cause this bug, but again, you are welcome to suggest a better a title.

    "My guess is it would also happen in temporal events."

    This statement makes zero sense, no matter how it's interpreted.

    OP of the other thread already established that this bug does not happen when Background.exit() is called directly from onTemporalEvent(). So if that's what you meant, your guess was already disconfirmed before it was made.

    Furthermore, the code that reproduces this problem involves calling makeWebRequest from onTemporalEvent() and calling Background.exit() from makeWebRequest()'s response callback. So if you meant the bug "also" happens when temporal events are involved in any way, well "also" makes zero sense, since that's literally in the code that reproduces the problem.

  • So in my never-ending quest to write the most accurate and useful bug report titles possible (thanks for the motivation flocsy), I also did the following test:

    - leave onAppInstall() and onAppUpdate() in the code

    - Remove registerForTemporalEvent() from code

    - Add registerForStepsEvent()

    - in the service delegate:

    -- rename onTemporalEvent() to onSteps()

    Test A:

    - onSteps() calls Background.exit() directly: bug does not occur

    Test B:

    - onSteps() calls makeWebRequest, whose response callback calls Background.exit(): bug occurs

    - If I remove onAppInstall() and onAppUpdate(), the bug goes away

    So actually, I think my bug report title is pretty ok. afaict, it neither says too much or too little. But if anyone else wants to suggest an improved version, go for it.

  • I think it's interesting that Background seems to have an undocumented function called registerForAppInstallStateEvent, according to VS Code's autocomplete:

    It looks like it's only existed since 7.0.0 beta, according to a search of the SDK directories. It appears in api.debug.xml for SDKs starting 7.0.0, but not any of the device *.api.debug.xml files.

    I guess it doesn't have anything to do with the bug, which seems to have existed as far back as 6.4.2

  • > My guess is it would also happen in temporal events.

    I'm not sure exactly what you mean by "also", given that:

    - in the code which reproduces the problem, makeWebRequest() is called during a temporal event (onTemporalEvent calls the function which calls makeWebRequest). (The bug does happen here)

    - if Background.exit() is called directly in onTemporalEvent(), onBackgroundData() is called (meaning the bug doesn't happen here)

    > My guess is it would also happen in temporal events.

    Why would you guess this when the OP of the thread already said it doesn't happen when Background.exit() is directly called from onTemporalEvent()?

    And just to confirm, I tried it myself and saw that it doesn't happen.

    Honestly, I kind of regret reporting this bug now, and I kind of regret trying to word it as precisely as I could.

    Some ppl (not you) might just post as vaguely as possible, and shrug their shoulders when asked for clarification. I try to post as precisely as possible and it always backfires on me.

    All credit goes to StevenX for finding the bug (again) and jim_m_58 for finding the workaround. I'm just a worthless human LLM, like you said.

    > Are you sure that all that is in the title really needed? 

    Funnily enough,

    1a) I never said what's in the title is a necessary condition for the bug. You implied that some of the things could be removed from the title, and the bug would still happen - but see above.

    1b) to extend 1a), I never said the bug doesn't also happen in other cases, like non-temporal events (although I don't think that's what you meant)

    What I am saying that what's in the title is a sufficient condition for the bug.

    My intuition is that the response callback for makeWebRequest has something to do with the problem. Specifically, I think it has something to do with the new "execution context" that's created by the use of a callback that the VM is going to call "later" (same as what would happen with a timer)

    We know that the response callback is being called (due to System.println()), but for whatever reason, when you call Background.exit() from the callback, onBackgroundData() is not triggered (when onAppInstall() or onAppUpdate() are overridden.)

    But just for you, I will try to recreate this in two other ways, even though this isn't my job and it's the weekend:

    - having the background process run when some other event is triggered, like onSteps(), and calling Background.exit() directly from onSteps(). My intuition is this will not trigger the bug

    - calling Background.Exit() from makeWebRequest's response callback, when makeWebRequest is called from onSteps(). My intuition is this will trigger the bug

    But who knows, we'll see!

  • Are you sure that all that is in the title really needed? I mean does it only happen in case it's a makeWebRequest? My guess is it would also happen in temporal events.