This document describes how to set annotations, fidelity parameters, and settings in your project.

## Annotations and fidelity parameters

Annotations give contextual information about what your game is doing when a tick is recorded. Fidelity parameters reflect the performance and graphical settings of your game. You define these using protocol buffers, which are Google's language-neutral, structured, data-interchange format. For more information on using protocol buffers within your game, see[About protocol buffers](https://developer.android.com/games/sdk/performance-tuner/custom-engine/define-parameters#about-protocol-buffers).

The possible annotations and fidelity parameters for your game are defined in a file called`dev_tuningfork.proto`, which is located in the`assets/tuningfork`directory of your project. The following is an example from the demo app:  

    syntax = "proto3";

    package com.google.tuningfork;

    enum InstrumentKey {
      CPU = 0;
      GPU = 1;
      SWAPPY_WAIT = 2;
      SWAPPY_SWAP = 3;
      CHOREOGRAPHER = 4;
    }

    enum Level {
      // 0 is not a valid value
      LEVEL_INVALID = 0;
      LEVEL_1 = 1;
      LEVEL_2 = 2;
      LEVEL_3 = 3;
    };

    message Annotation {
      Level level = 1;
    }

    message FidelityParams {
      int32 num_spheres = 1;
      float tesselation_percent = 2;
    }

Note the following:

- The package must be`com.google.tuningfork`.
- The message names must be exactly`Annotation`and`FidelityParams`.
- You can use only`enums`defined in this file as part of annotations.
- You can only use`enums`,`int32s`or`floats`in`FidelityParams`fields.
- The[validation tool](https://developer.android.com/games/sdk/performance-tuner/custom-engine/validate-and-package)enforces these conventions.

## Settings

The`Settings`message is defined by[`tuningfork.proto`](https://android.googlesource.com/platform/frameworks/opt/gamesdk/+/refs/heads/master/src/tuningfork/proto/tuningfork.proto). See a full example in the following file:

`gamesdk/samples/tuningfork/insightsdemo/app/src/main/assets/tuningfork/tuningfork_settings.txt`

You must define the settings for your game in a file called`tuningfork_settings.txt`located in the`assets/tuningfork`directory of your project. You need to specify only the following fields:

- `aggregation_strategy`: A message containing the following:

  - `method`:`TIME_BASED`to upload every*n* milliseconds or`TICK_BASED`to upload every*n*ticks.
  - `intervalms_or_count`:*n* for the`method`field.
  - `max_instrumentation_keys`: Number of instrumentation keys to use. Set to`4`if using the Android Frame Pacing library.
  - `annotation_enum_size`: An optional field since the size is calculated at start-up from the descriptor.
- `api_key`: Your app's Cloud project API key, used to validate requests to the endpoint. To generate this key, see[Enable the API](https://developer.android.com/games/sdk/performance-tuner/custom-engine/enable-api). If you see connection errors in`logcat`, check that the API key is correct.

- `default_fidelity_parameters_filename`: The fidelity parameter set used at initialization (optional if you set the[`training_fidelity_params`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/struct/t-f-settings#struct_t_f_settings_1a3ab649a2ec035694d4b035b742d56dd9)in your code).

- `level_annotation_index`: (Optional) The index in your annotation fields of the level number.

The following is an example text representation:  

    aggregation_strategy: {method: TIME_BASED, intervalms_or_count: 10000,
      max_instrumentation_keys: 5, annotation_enum_size: [3,4]}
    api_key: <var translate="no">"API-KEY-FROM-GOOGLE-CLOUD-CONSOLE"</var>
    default_fidelity_parameters_filename: "dev_tuningfork_fidelityparams_3.bin"
    level_annotation_index: 1

### Setting annotations

You need to manually set annotations during your game. You can see an example of this in the demo app as it cycles through all of the game levels automatically. For more information, see the`SetAnnotations()`function in[`insightsdemo.cpp`](https://android.googlesource.com/platform/frameworks/opt/gamesdk/+/refs/heads/master/samples/tuningfork/insightsdemo/app/src/main/cpp/insightsdemo.cpp).

In this case, the annotation only specifies the level number.  

    message Annotation {
      Level level = 1;
    }

## Define quality levels

Use quality levels to annotate sessions so that you can determine if devices are running on a quality level that is too high (resulting in lower performance) or too low (resulting in unnecessarily reduced fidelity).

You must define at least one, and preferably several, quality levels for your game. A quality level corresponds to an instance of your`FidelityParams`message. These levels must be given in*increasing*fidelity order with the following filename format:  

```
dev_tuningfork_fidelityparams_i.txt
```

where<var translate="no">i</var>is an index starting at 1 with a maximum value of 15. These files must be located in the`assets/tuningfork`directory of your project. The sample project shows an example of this structure in the`gamesdk/samples/tuningfork/insightsdemo/app/src/main/assets/tuningfork/`directory.

## About protocol buffers

The Tuning Fork library uses Google's protocol buffer format for settings, annotations, and fidelity parameters. This is a well-defined, multi-language protocol for extensible, structured data. For more information, see the[Protocol Buffers documentation](https://developers.google.com/protocol-buffers/).

### Proto2 vs proto3

The version of the protocol buffer format is set in the first line of the file:  

    syntax="proto2";

Proto2 and proto3 are two commonly-used versions of protocol buffers. They both use the same wire format but the definition files are not compatible. Key differences between the two versions include the following:

- The`optional`and`required`keywords are no longer allowed in proto3.
- Everything is effectively`optional`in proto3.
- Extensions are not supported in proto3.

Use proto3 in your proto files since these can be compiled to C#. Proto2 works as well with the limited feature set used in the Tuning Fork library.

### Text versus binary representations

The binary protobuf wire-format is well-defined and stable across different protobuf versions (the generated code is not). There is also a text format that the full version of the protobuf library can generate and read. This format is not as well-defined, but it is stable for the limited set of features in the Tuning Fork library. You can convert between binary and text formats using the`protoc`compiler. The following command converts a text protobuf to binary:  

    protoc --encode com.google.tuningfork.Settings tuningfork.proto < tuningfork_settings.txt > tuningfork_settings.bin

You must include binary files rather than text files in your APK because the full protobuf library is several MB in size; making the Tuning Fork library depend on it would increase the size of your game by a similar amount.

### Full versus Lite versus Nano

As well as the full protobuf library, there is a lite version that reduces code footprint by removing some features such as reflection,`FileDescriptors`, and streaming to and from text formats. This version still requires several MB of extra code footprint and so, the Tuning Fork library internally uses the[nanopb library](https://github.com/nanopb/nanopb). The source code for this library is included in the[Android Open Source Project](https://android.googlesource.com/platform/frameworks/opt/gamesdk/)in`external/nanopb-c`and it is part of the`gamesdk`branch. Use this library in your game if code size is an issue.

There are CMake files in`gamesdk/src/protobuf`that can help you to integrate all three versions of protobuf. The samples use a mix of both nanopb and full protobuf.