Watchface on Forerunner 235 slow to start

I have a watchface that works as expected on the Fenix 7 simulator and actual watch. it also works in the Forerunner 235 simulator as expected, but on the actual watch it takes minutes to display. It does eventually start and it looks right and updates like I think it should after the initial wait. This is a sideloaded watch face, not from the store. I have a log file that has a basic startup message but no error messages or other files. It's not crashing the way my Fenix did when I was using application storage. Memory usage is about 55k. All the built-in stuff seems to work OK. Any CIQ tricks I could try before I go in and add a lot of profiling code to maybe see what is happening?

  • Add some logs with timestamp to the startup code to see what takes time

  • Are you trying to do something where you don't draw the entire screen every time onUpdate is called? I can see where it might take .7 seconds to show vs .6 seconds on more powerful devices, but not take minutes.  I have a number of WFs I wrote when the fr32x was new and never seen anything like this.  I need to charge my 230, but I'll see if those WFs still work.

  • There is some math that takes a few runs through onUpdate to complete, but the ticks and hands I should see right away, and I do on the sims and Fenix. I'll add some profiling. I think onUpdate might be running only once per minute, any way to get it to run more often for the first few seconds after the WF starts?

  • Could be that on the 23x/630/735 the WF starts in low power mode or drops to low power (onEnterSleep) right away.  I'd have to run some tests.  And remember, there is no onPartialUpdate on these devices.  

    There's no way to change this behavior.

  • I added logs and it got a lot better, but it's still a little strange. Times are in sec.msec from the initial getTimer. For the curious jparts 0 is the J2000.0 date, the last two are the raw unix time and raw getTimer.

    Beginning of init @ 0.008000
    API 10405 jparts time: [8460.026476, 2023, 3, 1, 6, 36, 54, 3, 45414, 1677674214, 67733527]
    init complete @ 1.760000
    Drawing layout ticks @ 1.800000
    Drawing layout date @ 4.208000
    onLayout complete @ 4.240000
    in onShow @ 5.504000
    in onExitSleep @ 5.592000
    Begin onUpdate @ 7.040000
    Begin reOrb calc @ 7.088000
    Begin reOrb chunk 0 @ 8.496000
    Begin redraw @ 13.920001
    Begin redraw hands @ 15.384001
    Begin onUpdate @ 15.568001
    Begin reOrb calc @ 16.984001
    Begin reOrb chunk 1 @ 17.016001
    in onEnterSleep @ 23.392000
    Begin onUpdate @ 23.416000
    Begin reOrb calc @ 24.816002
    Begin reOrb chunk 2 @ 24.848001
    Begin redraw @ 29.736002
    Begin redraw hands @ 29.760002
    Begin onUpdate @ 31.256002
    Begin reOrb calc @ 31.296001
    Begin reOrb chunk 3 @ 32.688000
    Begin redraw @ 34.728001
    Begin redraw hands @ 36.120003
    Begin onUpdate @ 36.240002
    Begin reOrb calc @ 37.648003
    Begin reOrb chunk 4 @ 37.680000
    Begin redraw @ 41.080002
    Begin redraw hands @ 41.104000
    Begin onUpdate @ 42.592003
    Begin reOrb calc @ 42.632004
    Begin reOrb chunk 5 @ 44.040001
    Begin redraw @ 46.752003
    Begin redraw hands @ 47.456001
    Begin onUpdate @ 48.272003
    Begin reOrb calc @ 48.992001
    Begin reOrb chunk 6 @ 49.704002
    Begin redraw @ 52.400002
    Begin redraw hands @ 53.120003
    Begin onUpdate @ 53.904003
    Begin reOrb calc @ 54.632004
    Begin reOrb chunk 7 @ 55.344002
    Begin redraw @ 58.048004
    Begin redraw hands @ 58.752003
    Begin onUpdate @ 60.120003
    Begin reOrb calc @ 60.848003
    Begin reOrb chunk 8 @ 61.560001
    Begin redraw @ 63.568005
    Begin redraw hands @ 64.280006
    Begin onUpdate @ 66.128006
    Begin reOrb calc @ 66.864006
    Complete reOrb calc @ 67.568001
    Begin redraw @ 68.320000
    Begin redraw Orb @ 69.048004
    Begin redraw ticks @ 71.928001
    Begin redraw date @ 73.616005
    Begin redraw hands @ 74.336006
    Begin onUpdate @ 126.128006
    in onExitSleep @ 128.264008
    Begin onUpdate @ 128.840012
    Begin redraw @ 129.424011
    Begin redraw Orb @ 132.352005
    Begin redraw ticks @ 136.192001
    Begin redraw date @ 137.768005
    Begin redraw hands @ 138.328003
    in onEnterSleep @ 138.944000
    Begin onUpdate @ 139.488007
    Begin redraw @ 140.040009
    Begin redraw Orb @ 140.608002
    Begin redraw ticks @ 143.304001
    Begin redraw date @ 144.832001
    Begin redraw hands @ 145.376007

    onShow calls WatchUi.requestUpdate, so it seems like it should have then gone to onUpdate instead of onExitSleep? It calls onEnterSleep but onUpdate keeps getting called? The order and timing of calls for sleep and update seem wonky.

  • Same log from the Fenix 7. Obviously faster hardware, but the order seems more like what I would expect from the FR 235 as well.

    Beginning of init @ 0.000000
    API 40200 jparts time: [8460.045736, 2023, 3, 1, 7, 4, 38, 3, 47078, 1677675878, 788313630]
    init complete @ 0.128000
    Drawing layout ticks @ 0.192000
    Drawing layout date @ 0.704000
    onLayout complete @ 0.768000
    in onShow @ 0.768000
    Begin onUpdate @ 0.768000
    Begin reOrb calc @ 0.768000
    Begin reOrb chunk 0 @ 0.768000
    Begin redraw @ 1.984000
    Begin redraw hands @ 1.984000
    Begin onUpdate @ 2.240000
    Begin reOrb calc @ 2.304000
    Begin reOrb chunk 1 @ 2.304000
    Begin onUpdate @ 3.008000
    Begin reOrb calc @ 3.008000
    Begin reOrb chunk 2 @ 3.008000
    Begin onUpdate @ 3.520000
    Begin reOrb calc @ 3.520000
    Begin reOrb chunk 3 @ 3.520000
    Begin onUpdate @ 4.032000
    Begin reOrb calc @ 4.096000
    Begin reOrb chunk 4 @ 4.096000
    Begin onUpdate @ 4.864000
    Begin reOrb calc @ 4.864000
    Complete reOrb calc @ 4.864000
    Begin redraw @ 4.864000
    Begin redraw Orb @ 4.864000
    Begin redraw ticks @ 5.248000
    Begin redraw date @ 5.760000
    Begin redraw hands @ 5.824000
    Begin onUpdate @ 5.888000
    Begin onUpdate @ 6.848001
    Begin onUpdate @ 7.872000
    Begin onUpdate @ 8.064000
    in onEnterSleep @ 8.640000
    Begin onUpdate @ 8.640000
    Begin redraw @ 8.640000
    Begin redraw Orb @ 8.640000
    Begin redraw ticks @ 9.024000
    Begin redraw date @ 9.536000
    Begin redraw hands @ 9.600000
    Begin onUpdate @ 9.600000
    Begin onUpdate @ 9.664001
    Begin onUpdate @ 9.856001
    Begin onUpdate @ 10.816001
    

  • You don't need to call Ui.requestUpdate() from onShow.

    Try this WF on the 23x.  You'll see seconds when you first start the WF, then it drops to low power after 10 seconds, and the seconds are no longer shown.They show again after a gesture.

    https://apps.garmin.com/en-US/apps/2c632834-3bb2-4dfa-b008-4f6d48dda0cb

    I do nothing in onShow() and always update the whole screen in onUpdate, but suppress the seconds when in low power.

  • That's what happens on the Fenix except that onPartialUpdate draws the second hand always. I didn't add any logging to onPartialUpdate initially in fear of breaking the power budget. onPartialUpdate is listed as an API 2.3.0 feature in the docs so I would not expect it to be called on the FR. I added logging to onPartialUpdate, my power budget fears do not seem to have materialized.

    Beginning of init @ 0.000000
    API 40200 jparts time: [8460.067220, 2023, 3, 1, 7, 35, 34, 3, 48934, 1677677734, 790168816]
    init complete @ 0.192000
    Drawing layout ticks @ 0.192000
    Drawing layout date @ 0.704000
    onLayout complete @ 0.768000
    in onShow @ 0.768000
    Begin onUpdate @ 0.768000
    Begin reOrb calc @ 0.768000
    Begin reOrb chunk 0 @ 0.768000
    Begin redraw @ 1.984000
    Begin redraw hands @ 2.048000
    in onPartialUpdate @ 2.048000
    redraw bitmap from previous clip region @ 2.048000
    redefine clip region @ 2.048000
    draw second hand @ 2.048000
    onPartialUpdate complete @ 2.112000
    Begin onUpdate @ 2.368000
    Begin reOrb calc @ 2.368000
    Begin reOrb chunk 1 @ 2.368000
    in onPartialUpdate @ 2.944000
    redraw bitmap from previous clip region @ 2.944000
    redefine clip region @ 2.944000
    draw second hand @ 3.008000
    onPartialUpdate complete @ 3.008000
    Begin onUpdate @ 3.008000
    Begin reOrb calc @ 3.072000
    Begin reOrb chunk 2 @ 3.072000
    in onPartialUpdate @ 3.520000
    redraw bitmap from previous clip region @ 3.520000
    redefine clip region @ 3.520000
    draw second hand @ 3.584000
    onPartialUpdate complete @ 3.584000
    Begin onUpdate @ 3.840000
    Begin reOrb calc @ 3.840000
    Begin reOrb chunk 3 @ 3.840000
    in onPartialUpdate @ 4.288000
    redraw bitmap from previous clip region @ 4.288000
    redefine clip region @ 4.288000
    draw second hand @ 4.288000
    onPartialUpdate complete @ 4.352000
    Begin onUpdate @ 4.800000
    Begin reOrb calc @ 4.800000
    Begin reOrb chunk 4 @ 4.864000
    in onPartialUpdate @ 5.120000
    redraw bitmap from previous clip region @ 5.120000
    redefine clip region @ 5.120000
    draw second hand @ 5.120000
    onPartialUpdate complete @ 5.184000
    Begin onUpdate @ 5.824000
    Begin reOrb calc @ 5.824000
    Complete reOrb calc @ 5.824000
    Begin redraw @ 5.824000
    Begin redraw Orb @ 5.888000
    Begin redraw ticks @ 6.208000
    Begin redraw date @ 6.784000
    Begin redraw hands @ 6.784000
    in onPartialUpdate @ 6.784000
    redraw bitmap from previous clip region @ 6.848001
    redefine clip region @ 6.848001
    draw second hand @ 6.848001
    onPartialUpdate complete @ 6.848001
    Begin onUpdate @ 6.912000
    in onPartialUpdate @ 6.912000
    redraw bitmap from previous clip region @ 6.912000
    redefine clip region @ 6.912000
    draw second hand @ 6.976000
    onPartialUpdate complete @ 6.976000
    Begin onUpdate @ 7.808001
    in onPartialUpdate @ 7.808001
    redraw bitmap from previous clip region @ 7.808001
    redefine clip region @ 7.872000
    draw second hand @ 7.872000
    onPartialUpdate complete @ 7.872000
    Begin onUpdate @ 8.832001
    in onPartialUpdate @ 8.832001
    redraw bitmap from previous clip region @ 8.832001
    redefine clip region @ 8.832001
    draw second hand @ 8.832001
    onPartialUpdate complete @ 8.896001
    Begin onUpdate @ 8.960000
    in onPartialUpdate @ 8.960000
    redraw bitmap from previous clip region @ 8.960000
    redefine clip region @ 8.960000
    draw second hand @ 8.960000
    onPartialUpdate complete @ 8.960000
    Begin onUpdate @ 9.792001
    in onPartialUpdate @ 9.856001
    redraw bitmap from previous clip region @ 9.856001
    redefine clip region @ 9.856001
    draw second hand @ 9.856001
    onPartialUpdate complete @ 9.856001
    Begin onUpdate @ 10.816001
    in onPartialUpdate @ 10.816001
    redraw bitmap from previous clip region @ 10.816001
    redefine clip region @ 10.880000
    draw second hand @ 10.880000
    onPartialUpdate complete @ 10.880000
    Begin onUpdate @ 11.840000
    in onPartialUpdate @ 11.840000
    redraw bitmap from previous clip region @ 11.840000
    redefine clip region @ 11.840000
    draw second hand @ 11.840000
    onPartialUpdate complete @ 11.904000
    in onEnterSleep @ 11.904000
    Begin onUpdate @ 11.968000
    Begin redraw @ 11.968000
    Begin redraw Orb @ 11.968000
    Begin redraw ticks @ 12.288000
    Begin redraw date @ 12.864000
    Begin redraw hands @ 12.864000
    in onPartialUpdate @ 12.928000
    redraw bitmap from previous clip region @ 12.928000
    redefine clip region @ 12.928000
    draw second hand @ 12.928000
    onPartialUpdate complete @ 12.928000
    Begin onUpdate @ 12.928000
    in onPartialUpdate @ 12.992001
    redraw bitmap from previous clip region @ 12.992001
    redefine clip region @ 12.992001
    draw second hand @ 12.992001
    onPartialUpdate complete @ 12.992001
    Begin onUpdate @ 26.816002
    Begin redraw @ 26.816002
    Begin redraw hands @ 26.816002
    in onPartialUpdate @ 26.880001
    redraw bitmap from previous clip region @ 26.880001
    redefine clip region @ 26.880001
    draw second hand @ 26.880001
    onPartialUpdate complete @ 26.880001
    Begin onUpdate @ 86.784004
    Begin redraw @ 86.976006
    Begin redraw hands @ 86.976006
    in onPartialUpdate @ 86.976006
    redraw bitmap from previous clip region @ 86.976006
    redefine clip region @ 86.976006
    draw second hand @ 87.040001
    onPartialUpdate complete @ 87.040001
    in onExitSleep @ 119.296005
    Begin onUpdate @ 119.296005
    Begin redraw @ 119.296005
    Begin redraw hands @ 119.296005
    in onPartialUpdate @ 119.296005
    redraw bitmap from previous clip region @ 119.360008
    redefine clip region @ 119.360008
    draw second hand @ 119.360008
    onPartialUpdate complete @ 119.360008
    Begin onUpdate @ 119.424004
    in onPartialUpdate @ 119.424004
    redraw bitmap from previous clip region @ 119.424004
    redefine clip region @ 119.424004
    draw second hand @ 119.424004
    onPartialUpdate complete @ 119.488007
    in onEnterSleep @ 119.552002
    

  • The fr 23x devices don't have onPartialUpdate.  No CIQ 1 devices have it.  It also doesn't have dc.setClip

  • Which is why I have this:

    in initalize:
    var thisDev = System.getDeviceSettings();
    var devAPI = thisDev.monkeyVersion;
    _api = devAPI[0] * 10000 + devAPI[1] * 100 + devAPI[2];
    _partialUpdatesAllowed = WatchUi.WatchFace has :onPartialUpdate;
    
    in onUpdate:
    if (_api >= 20300) {
    	dc.clearClip();
    }
    
    ...later in onUpdate...
    if (_partialUpdatesAllowed) {
    	onPartialUpdate(dc);
    }
    

    onPartialUpdate is where the second hand gets drawn, so if it doesn't get called, no second hand. It would be nice if the FR had a second hand but onUpdate doesn't get called every second so that wouldn't work.

    _api version checks get used in several places, like buffers, bitmaps, json data, storage, and other things that have been added or changed between versions.