Acknowledged
CIQQA-3506

[BUG] Watchface onPartialUpdate() reports GraphicsTime = 1,700,000 - with no screen updates!

With no screen writes, and 3x reads of properties defined as settings; on-device and in-simulator the VM reports :

onPowerBudgetExceeded() gets triggered on all Devices and in-simulator (so at least it is consistent :) )

As these Settings Properties are stored in-memory it is unlikely Properties.getValue() can take 1,700,000uSec (1.7 seconds).
Even if that were possible, it should be reflected in Execution Time -- not Graphics Time.

Link to the Watchface working source code demonstrating this bug: https://github.com/blueacorn/Infocal/tree/2025.8.20 [note issue is fixed in mainline - reproducible on tag 2025.8.20]

Notes:

1. Properties are all defined in <setting propertyKey="@Properties...  , Settings are stored in-memory at runtime, so getValue() should not cost 1,700,000 uSecs.
2. If Properties.getValue() cannot be called in partial updates, at least make it a compiler warning,
3. The side-effect on Graphics Time is very misleading - at least move the time cost to Execution Time -- not Graphics Time.

For context, the original root-cause discussion thread: https://forums.garmin.com/developer/connect-iq/f/discussion/420832/watchface-onpartialupdate-powerbudgetexceeded---with-no-screen-updates/

  • > Properties.setValue() does update the in-memory copy.

    That's good to know, thanks!

    I stand by my guess that the in-memory copy is probably just there for the old API.

    Although it is somewhat ironic that the new API is obligated to update the in-memory copy on setValue, but also (apparently) obligated *not* to read from the in-memory copy on getValue. I totally get it though - Garmin has wanted to remove the old API for years, and the only reason they haven't done is because devs won't stop using it.

  • I was curious about this too, so I tried  it in the simulator:

    Properties.setValue() does update the in-memory copy.

  • > I think the newer API - Application.Properties - always reads and writes to storage regardless.

    It might *also* write to memory (RAM) (to support the use case of mixing AppBase.get/setProperty and Application.Properties [**]), but I think it always uses storage [*] as the primary medium for reading and writing.

    [**] but I have no idea if that would actually work and it would be interesting to see what would happen. Let's say AppBase.getProperty was unable to see changes made by Application.Properties.setValue without an app restart - that would definitively prove that setValue only ever updates storage [*] and not the in-memory copy of properties.

    [*] I just mean non-volatile storage, not the Storage class.

    idk, maybe I should be saying "the file system" or even the Object Store.

  • 1. As explained in the linked thread, even though properties/settings may be in memory at runtime, this is *probably* just to support the old, deprecated AppBase.getProperty/setProperty functions, which reads and writes from memory (storage [*] is only read/written at application startup/termination). I think the newer API - Application.Properties - always reads and writes to storage regardless. This is probably to avoid issues like losing changes to properties if the app crashes.

    Sorry, it's my fault that I brought up "application settings" being in the memory viewer and added to the confusion. Kind of a red herring.

    [*] I just mean non-volatile storage as opposed to RAM, not the literal Storage class

    2. This is a good idea

    3. Agreed