Use the functions in this topic to integrate the Tuning Fork library
into your game code.

The header file at `include/tuningfork/tuningfork.h` contains the core interface
for the Tuning Fork library. The file at
`include/tuningfork/tuningfork_extra.h` contains utility functions.

Several functions take serializations of protocol buffers. For more 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).

Function parameters and return values are explained in the headers and
[reference API documentation](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine).

## Android Performance Tuner lifecycle functions

Use the following functions to control the lifecycle of a Tuning Fork
instance.

### Initialize

[`TFErrorCode TuningFork_init(const TFSettings* settings, JNIEnv* env, jobject
context);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_init)

You must call this function once at start-up, typically from within native code
executed by the app's `onCreate()` method. It allocates the data needed by the
Tuning Fork library.

You must have a `tuningfork_settings.bin` file present in `assets/tuningfork`
within your app, which contains the histogram and annotation settings. To
convert the text file to binary, see
[Text versus binary representations](https://developer.android.com/games/sdk/performance-tuner/custom-engine/define-parameters#binary-protobuf-representation).

The fields you fill in `settings` determine how the library initializes itself.  

    /**
     * @brief Initialization settings
     *   Zero any values that are not being used.
     */
    struct TFSettings {
      /**
       * Cache object to be used for upload data persistence.
       * If unset, data is persisted to /data/local/tmp/tuningfork
       */
      const TFCache* persistent_cache;
      /**
       * The address of the Swappy_injectTracers function.
       * If this is unset, you need to call TuningFork_tick explicitly.
       * If it is set, telemetry for 4 instrument keys is automatically recorded.
       */
      SwappyTracerFn swappy_tracer_fn;
      /**
       * Callback
       * If set, this is called with the fidelity parameters that are downloaded.
       * If unset, you need to call TuningFork_getFidelityParameters explicitly.
       */
      ProtoCallback fidelity_params_callback;
      /**
       * A serialized protobuf containing the fidelity parameters to be uploaded
       *  for training.
       * Set this to nullptr if you are not using training mode. Note that these
       *  are used instead of the default parameters loaded from the APK, if they
       *  are present and there are neither a successful download nor saved parameters.
       */
      const CProtobufSerialization* training_fidelity_params;
      /**
       * A null-terminated UTF-8 string containing the endpoint that Tuning Fork
       * will connect to for parameter, upload, and debug requests. This overrides
       * the value in base_uri in the settings proto and is intended for debugging
       * purposes only.
       */
      const char* endpoint_uri_override;
      /**
       * The version of Swappy that swappy_tracer_fn comes from.
       */
      uint32_t swappy_version;
      /**
       * The number of each metric that is allowed to be allocated at any given
       * time. If any element is zero, the default for that metric type is used.
       * Memory for all metrics is allocated up-front at initialization. When all
       * metrics of a given type are allocated, further requested metrics are not
       * added and data is lost.
       */
      TuningFork_MetricLimits max_num_metrics;
    };

If you pass in the `Swappy_injectTracer()` function
([OpenGL](https://developer.android.com/games/sdk/reference/frame-pacing/group/swappy-g-l-extra#swappygl_injecttracer),
[Vulkan](https://developer.android.com/games/sdk/reference/frame-pacing/group/swappy-vk#swappyvk_injecttracer))
from the Frame Pacing API at initialization, the Tuning Fork library
automatically records frame time without you explicitly calling the tick
functions yourself. This is done in the demo app:  

    void InitTf(JNIEnv* env, jobject activity) {
       SwappyGL_init(env, activity);
       swappy_enabled = SwappyGL_isEnabled();
       TFSettings settings {};
       if (swappy_enabled) {
           settings.swappy_tracer_fn = &SwappyGL_injectTracer;
           settings.swappy_version = Swappy_version();
       }
    ...
    }

| **Note:** it is critical to set the version of Swappy that you are using in the `swappy_version` field of `TFSettings`. This ensures that TuningFork can interpret the data coming back from the Swappy callbacks.

### Destroy

[`TFErrorCode TuningFork_destroy();`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_destroy)

You can call this function at shut-down. This function attempts to submit all
currently stored-histogram data for later upload before deallocating any memory
used by the Tuning Fork library.

### Flush

[`TFErrorCode TuningFork_flush();`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_flush)

This function flushes the recorded histograms (for example, when the game is
sent to the background or foreground). It doesn't flush data if the minimum
upload period, which has a default of one minute, has not elapsed since the
previous upload.

### Set fidelity parameters

[`TFErrorCode TuningFork_setFidelityParameters(const CProtobufSerialization*
params);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_setfidelityparameters)

This function overrides the current fidelity parameters with which frame data is
associated. You should call this function when a player manually changes the
quality settings of the game.

## Annotations

[`TFErrorCode TuningFork_setCurrentAnnotation(const CProtobufSerialization*
annotation);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_setcurrentannotation)

This function sets the annotation to associate with subsequent ticks. It returns
`TFERROR_INVALID_ANNOTATION` if there was an error decoding the annotation and
`TFERROR_OK` if there was no error.

## Per-frame functions

[`TFErrorCode TuningFork_frameTick(TFInstrumentKey key);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_frametick)

This function records the time between the previous tick with the given `key`
and the current time in the histogram associated with `key` and the current
annotation.

[`TFErrorCode TuningFork_frameDeltaTimeNanos(TFInstrumentKey key, TFDuration
dt);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_framedeltatimenanos)

This function records duration in the histogram associated with `key` and the
current annotation.

[`TFErrorCode TuningFork_startTrace(TFInstrumentKey key, TraceHandle* handle);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_starttrace)

This function sets a handle to a trace handle associated with the given `key`.

[`TFErrorCode TuningFork_endTrace(TraceHandle handle);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_endtrace)

This function records the time interval since the associated
[`TuningFork_startTrace()`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_starttrace)
call in the histogram associated with the `key` that was used and the current
annotation.

## App lifecycle functions

    typedef enum TuningFork_LifecycleState {
        TUNINGFORK_STATE_UNINITIALIZED = 0,
        TUNINGFORK_STATE_ONCREATE = 1,
        TUNINGFORK_STATE_ONSTART = 2,
        TUNINGFORK_STATE_ONSTOP = 3,
        TUNINGFORK_STATE_ONDESTROY = 4,
    } TuningFork_LifecycleState;

[`TFErrorCode TuningFork_reportLifecycleEvent(TuningForkLifecycleState state);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_reportlifecycleevent)

Call this function from the appropriate lifecycle methods in your
game's main [Activity](https://developer.android.com/guide/components/activities/activity-lifecycle), passing
the appropriate enum. By recording the game's lifecycle events, APT is better
able to understand when your game may be crashing or when users may be quitting
(for example, during long loading events).

## Advanced functions

The following functions are available in `tuningfork_extra.h`.

### Find and load files in an APK

[`TFErrorCode TuningFork_findFidelityParamsInApk(JNIEnv* env, jobject context,
const char* filename, CProtobufSerialization*
fidelityParams);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork-extra#tuningfork_findfidelityparamsinapk)

This function loads `fidelityParams` from the `assets/tuningfork` directory in
the APK with the given filename. `fidelityParams` must be a serialization of a
`FidelityParams` message. For more information, see
[Define quality levels](https://developer.android.com/games/sdk/performance-tuner/custom-engine/define-parameters#define-quality-levels).

Ownership of the serialization is passed to the caller, which must call
`CProtobufSerialization_Free` to deallocate any memory held.

### Download fidelity parameters on a separate thread

[`void TuningFork_startFidelityParamDownloadThread(const CProtobufSerialization*
defaultParams, ProtoCallback
fidelity_params_callback);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork-extra#tuningfork_startfidelityparamdownloadthread)

Activates a download thread to retrieve fidelity params. The thread retries the
request until the params download or a timeout occurs. Downloaded params are
stored locally. When the app is restarted, it uses these downloaded params
rather than the default params.

### Save and delete fidelity parameters stored on device

[`TFErrorCode TuningFork_saveOrDeleteFidelityParamsFile(JNIEnv* env, jobject
context, const CProtobufSerialization*
fidelity_params);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork-extra#tuningfork_saveordeletefidelityparamsfile)

This function is only needed in expert mode where fidelity parameters are
downloaded from a server. It either saves over or deletes (if `fidelity_params`
is null) the locally stored files that are used when the server is unreachable.

## Web requests

The library makes the following kinds of requests to the server endpoint:

- A `generateTuningParameters` request is made at initialization.
- During gameplay, an `uploadTelemetry` request is periodically made to send data to the server.
- Debug APKs can also send `debugInfo` requests, which inform a debug server of the settings, default fidelity parameters, and `dev_tuningfork.proto` structure.

### Offline players

If there is no available connection at initialization, the request is retried
several times with an increasing back-off time.

If there is no connection at upload, the upload is cached. You can provide your
own caching mechanism by passing a
[`TFCache`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/struct/t-f-cache)
object at initialization. If you do not provide your own cache, uploads are
stored as files in temporary storage.