Optimize memory usage for Watch Face Format

To provide the best possible battery life of Wear OS devices, the system performs a memory capacity check. As part of the Wear OS app quality guidelines, watch faces that use the Watch Face Format have limits on the amount of memory that they can consume, depending on the watch's current state:

  • In ambient mode, the watch face can't consume more than 10 MB of memory.
  • In interactive mode, the watch face can't consume more than 100 MB of memory.

System calculates a watch face's memory usage

To compute the size taken up by an image or bitmap font within a watch face that uses the Watch Face Format, the system completes the following steps:

  1. Decompresses the image or bitmap font.
  2. Examines the image or bitmap font to see if it can be optimized in one of the following ways:
    • Resized to better match its display size.
    • Cropped to remove fully transparent pixels.
    • Downsampled to RGB565, if this can be done without loss of fidelity.

Based on the resulting bounding box, the system computes the size of the image or bitmap font, in bytes, as one of the following:

  • For images and fonts that use RGBA8888: \( 4 \times width \times height \)
  • For images and fonts that use RGB565: \( 2 \times width \times height \)
  • For images and fonts that use the ALPHA_8 bitmap configuration: \( width \times height \)

Interactive mode

When calculating memory usage for interactive mode, the system calculates the sum of the following:

  1. The unprocessed size of any vector fonts.
  2. The estimated usage of the system's default font.
  3. The total size of the images and bitmap fonts after any cropping, resizing, or reformatting has been applied.

Configurations

For watch faces that contain configurations, the system attempts to compute the total size of the resources used in the different configurations. Occasionally, when there's a very large number of combinations, the system slightly overestimates how many resources are used simultaneously across the different configurations.

Ambient mode and layers

For ambient mode, the system assumes that the watch is rendered using up to three full screen layers, two of which are completely static:

  1. Everything underneath the watch elements. Most of the watch face's "body" is composited into this layer. It doesn't matter how many images are used to draw this layer; the system counts it as one full-screen image.
  2. Any watch hands, digital display, or complications with platform bindings that are rendered dynamically.
  3. All elements that are listed after the watch hands and complications in the source XML file.

Typically, most memory usage in ambient mode comes from bitmap fonts, especially large ones.

Methods of reducing memory usage

By following the suggestions in this sections, you're more likely to create a watch face whose memory consumption stays within these limits.

Crop and resize bitmap fonts

Crop your images and BitmapFont objects, and resize them to match their display size.

When Wear OS draws a watch face, all images are decompressed. A full-screen image that's mostly blank might consume 3 KB on disk, but if it's displayed on a 450-pixel x 450-pixel screen, the system decompresses the image, increasing the image's size in memory to 750 KB or larger.

Use consistent bitmap font heights

When using a BitmapFont, all images for a character should each have the same height. Likewise, all images for words should each have the same height.

Use consistent frame sizes in animations

Instead of moving an image across a watch face, update the elements within the image and keep its bounding box in the same location relative to the watch face. For example, if you want to animate a circle on your watch face, consider changing the color of a circle instead of rolling the circle across the watch face.

This technique reduces the size of the bounding box that the system calculates for the animation.

Deduplicate images

If your watch face displays multiple copies of the same image, load only one copy of that image into memory and make several references to that one image.

Show progress using arcs

To emulate a progress bar that completes after 1 minute or after 1 hour, don't use 60 separate images. Instead, create an Arc object that contains an expression controlling its length, as shown in the following code snippet:

<PartDraw angle="0" width="400" height="400" name="ProgressBar"
          pivotX="0.5" pivotY="0.5 x="40" y="40">
    <Arc centerX="200" centerY="200" width="400" height="400"
         startAngle="0" endAngle="360">
        <!-- Completes a "progress loop" every minute. -->
        <Transform target="endAngle"
                   value="0 + (clamp([SECOND], 0, 60) - 0) * 6" />
        <Stroke cap="ROUND" color="#123456" thickness="10" />
    </Arc>
</PartDraw>

To display a non-continuous line, for example to achieve a retro digital watch style look, use either a dash property for a Stroke object or a semi-transparent mask image overlay.

Place watch hands and complications at the end of the source file

XML nodes are drawn in the order that they're listed in the source XML file. By putting the watch hands and complications at the end of the file, the system eliminates an entire layer from the ambient mode memory calculation.

Evaluate the performance of your watch face

To measure the memory performance of your watch face, use the memory footprint evaluator tool, available in the watchface repository on GitHub.