Improve your watch face performance with hardware acceleration

Wear OS apps that use standard views already benefit from hardware-accelerated graphics rendering. In contrast, watch faces are usually implemented using canvases, so they don't automatically get hardware acceleration.

Starting with version 2.7.0 of the Wearable Support Library, you can ask for a hardware-accelerated canvas when using the CanvasWatchFaceService class.

Why use a hardware-accelerated canvas for your watch face?

In most cases, your watch face will render at a higher frame rate when using a hardware-accelerated canvas. At higher frame rates, animations and transitions appear smoother to the eye. For your users, these benefits are self-evident.

When you use a hardware-accelerated canvas, you can also access more UI performance data about your watch face. For example, you can only access the detailed frame information mentioned in Measuring UI performance when you are using a hardware-accelerated canvas.

Request hardware acceleration for your watch face

Use the useHardwareCanvas parameter in the CanvasWatchFaceService.Engine constructor to request hardware acceleration for your watch face:

Kotlin

class MyWatchFaceService : CanvasWatchFaceService() {
    override fun onCreateEngine(): CanvasWatchFaceService.Engine {
        return Engine();
    }
    // Sets useHardwareCanvas to true to request hardware acceleration
    inner class Engine : CanvasWatchFaceService.Engine(true){
    }
}

Java

public class MyWatchFaceService extends CanvasWatchFaceService {
    @Override
    public Engine onCreateEngine() {
        return new Engine();
    }
    private class Engine extends CanvasWatchFaceService.Engine {
       Engine(){
         // Sets useHardwareCanvas to true to request hardware acceleration
         super(true);
       }
   }

Is my watch face using hardware acceleration?

You can check whether your watch face is currently using hardware acceleration using either the developer options or adb.

Check using developer options

To check whether your watch face is using hardware acceleration using the developer options, follow these steps:

  1. On a Wear OS device, navigate to Settings > Developer options.
  2. Enable Debug GPU profiling.

    This option draws an overlay on top of visible surfaces (one per each surface) to show the amount of time spent in each stage of GPU rendering for that surface.

  3. On the device, navigate back to your watch face.

  4. If your watch face is using hardware accelerated canvas, you'll see a new bar (moving from right to left) for each rendered frame of your watch face.

Check using adb

To check whether your watch face is using hardware acceleration using adb, follow these steps:

  1. On a Wear OS device, change the watch face to your watch face that you want to test.
  2. Let the watch face run for a few seconds in interactive mode.
  3. Run the following adb command to check whether your watch face is using hardware acceleration:

    adb shell dumpsys gfxinfo [package-name]

After running the command, the output will be similar to the following example:

Applications Graphics Acceleration Info:
Uptime: 2239933 Realtime: 13568751

** Graphics info for pid 1100 [package-name] **

Stats since: 59875589194ns
Total frames rendered: 1213
Janky frames: 0 (0.00%)
50th percentile: 7ms
90th percentile: 18ms
95th percentile: 25ms
99th percentile: 150ms
Number Missed Vsync: 0
Number High input latency: 0
Number Slow UI thread: 0
Number Slow bitmap uploads: 0
Number Slow issue draw commands: 0
Number Frame deadline missed: 0

...

In this sample output, notice the line that says Total frames rendered. Generally, if you see this frame data in your output, then your watch face is using an accelerated canvas. Otherwise the number for Total frames rendered (and other frame data numbers in the report) will normally be zero.

However, because the gfxinfo is output for your app's full package, you might see some frame time information from something other than a hardware-accelerated canvas, such as an Activity that your app uses for a configuration screen. To tell the difference, make sure that your watch face is the only surface that is visible and then rerun the adb shell dumpsys gfxinfo command to verify if the value for Total frames rendered increases.

Best practices

Follow these best practices to ensure the best possible experience for your users.

Maximize battery life

If your watch face has long-running animations, using hardware acceleration can greatly lower the battery life of a device. This problem can get even worse if your watch face tries to draw in every frame. To avoid negatively impacting your users, you shouldn't have long-running animations in your watch face. This guideline is not specific to using hardware acceleration, but because using hardware acceleration increases the number of frames you're able to draw, it is even more important to follow. For more information, see Best practices for animations.

Use supported drawing operations

Some drawing operations are not supported when using hardware acceleration. If you have a small code path that uses an unsupported operation, you can create a bitmap backed canvas and then draw that bitmap into the watch face's canvas using canvas.drawBitmap():

Kotlin

inner class Engine : CanvasWatchFaceService.Engine(true) {
    private val mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)
    init{
        val bitmapCanvas = Canvas(mBitmap)
        // Any software-only operation on bitmapCanvas
    }
    override fun onDraw(canvas: Canvas, bounds: Rect?) {
        canvas.drawBitmap(mBitmap, 100f, 100f, null)
    }
}

Java

class Engine extends CanvasWatchFaceService.Engine{
    private final Bitmap mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    public Engine(){
        super(true);
        Canvas bitmapCanvas = new Canvas(mBitmap);
        // Any software-only operation on bitmapCanvas
    }
    @Override
    public void onDraw(Canvas canvas, Rect bounds) {
        canvas.drawBitmap(mBitmap, 0, 0, null);
    }
}

Maintain compatibility when using hardware acceleration

Hardware acceleration is available on Wear OS devices that run Android 9 (API level 28) or higher. If you want to avoid a specific draw operation on older devices (where hardware acceleration is not available) or an unsupported draw operation on a hardware accelerated canvas, you can check Canvas.isHardwareAccelerated() and then provide the alternative functionality.

Kotlin

override fun onDraw(canvas: Canvas, bounds: Rect?) {
    if (canvas.isHardwareAccelerated) {
        // Apply a workaround if your app needs to perform an unsupported operation.
    } else {
        // Work directly with the canvas.
    }
}

Java

@Override
public void onDraw(Canvas canvas, Rect bounds) {
  if (canvas.isHardwareAccelerated()){
    // Apply a workaround if your app needs to perform an unsupported operation.
  } else {
    // Work directly with the canvas.
  }
}