Use the following functions to add game controller support to your game using the Game Controller library.

## Initialize and destroy the Game Controller library

Use the[`Paddleboat_init`](https://developer.android.com/reference/games/game-controller/group/paddleboat#group__paddleboat_1ga930a7540c1efa580e40f1b8020f388e2)function to initialize the Game Controller library.  

    Paddleboat_ErrorCode Paddleboat_init(JNIEnv *env, jobject jcontext)

`Paddleboat_init`takes two parameters:

- A pointer to a[`JNIEnv`](https://developer.android.com/training/articles/perf-jni#javavm-and-jnienv)attached to the current thread
- A`jobject`JNI object reference to a[`Context`](https://developer.android.com/reference/android/content/Context)derived class. Any`Context`derived class object is valid, including but not limited to[`Activity`](https://developer.android.com/reference/android/app/Activity),[`NativeActivity`](https://developer.android.com/reference/android/app/NativeActivity), or[`GameActivity`](https://developer.android.com/reference/games/game-activity).

`Paddleboat_init`returns[`PADDLEBOAT_NO_ERROR`](https://developer.android.com/reference/games/game-controller/group/paddleboat#group__paddleboat_1ggac5a324359f2819f584ef26762ecc923cac84ade8bc1d9322a3f3b2b0c48bb625b)if initialization was successful, otherwise an appropriate error code is returned.

You can use[`Paddleboat_isInitialized`](https://developer.android.com/reference/games/game-%0Acontroller/group/paddleboat#paddleboat_isinitialized)to check if the Game Controller library has been successfully initialized. It returns a boolean value. If true, the API is available for use.  

    bool Paddleboat_isInitialized()

Prior to terminating the application, use the[`Paddleboat_destroy`](https://developer.android.com/reference/games/game-controller/group/paddleboat#paddleboat_destroy)function to shut down the Game Controller library. The function takes a single parameter, a pointer to a`JNIEnv`attached to the current thread.`Paddleboat_init`may be called again after`Paddleboat_destroy`.  

    void Paddleboat_destroy(JNIEnv *env)

## Inform the library of lifecycle events

The Game Controller library must be informed of[activity lifecycle](https://developer.android.com/guide/components/activities/activity-lifecycle)[`onStop`](https://developer.android.com/reference/android/app/Activity#onStop())and[`onStart`](https://developer.android.com/reference/android/app/Activity#onStart())events. Call the[`Paddleboat_onStop`](https://developer.android.com/reference/games/game-controller/group/paddleboat#paddleboat_onstop)and[`Paddleboat_onStart`](https://developer.android.com/reference/games/game-controller/group/paddleboat#paddleboat_onstart)functions from your stop and start event handling code. Both functions take a single parameter: a pointer to a`JNIEnv`attached to the current thread.  

    void Paddleboat_onStop(JNIEnv *env)
    void Paddleboat_onStart(JNIEnv *env)

## Register or remove a controller status callback

The Game Controller library uses a controller status callback to notify a game when a controller is connected or disconnected. It supports only one controller status callback at a time.

- To register a controller status callback or replace any previously registered callback with a new callback function, call the[`Paddleboat_setControllerStatusCallback`](https://developer.android.com/reference/games/game-controller/group/paddleboat#paddleboat_setcontrollerstatuscallback)function.
- To remove any currently registered callback, pass`NULL`or`nullptr`.
- The`userData`parameter is an optional pointer to user defined data. The`userData`parameter will be passed to the callback function. This pointer is retained internally until changed by a subsequent call to`Paddleboat_setControllerStatusCallback`.

    void Paddleboat_setControllerStatusCallback(Paddleboat_ControllerStatusCallback
      statusCallback, void *userData)

The function signature of the callback function is:  

    typedef void (*Paddleboat_ControllerStatusCallback)(
      const int32_t controllerIndex,
      const Paddleboat_ControllerStatus controllerStatus,
      void *userData)

|     Parameter      |                                                          Description                                                          |
|--------------------|-------------------------------------------------------------------------------------------------------------------------------|
| `controllerIndex`  | Index of the controller that initiated the callback. Will be a value between`0`and `PADDLEBOAT_MAX_CONTROLLERS - 1`           |
| `controllerStatus` | Enum value of`PADDLEBOAT_CONTROLLER_JUST_CONNECTED`or `PADDLEBOAT_CONTROLLER_JUST_DISCONNECTED`.                              |
| `userData`         | An optional pointer (may be NULL) to user defined data specified by the last call to`Paddleboat_setControllerStatusCallback`. |

## Call the Game Controller library update function

The Game Controller library update function,[`Paddleboat_update`](https://developer.android.com/reference/games/game-controller/group/paddleboat#paddleboat_update), should be called once per game frame, preferably near the start of the frame. The function takes a single parameter, a pointer to a`JNIEnv`attached to the current thread.  

    void Paddleboat_update(JNIEnv *env)

## Process events

When receiving input events, your game needs to forward them to the Game Controller library for inspection. The Game Controller library evaluates if an input event is associated with one of its managed devices. Events from managed devices are processed and consumed.

The Game Controller library supports two types of input events:[`AInputEvents`](https://developer.android.com/ndk/reference/group/input#ainputevent)and[`GameActivity`](https://developer.android.com/reference/games/game-activity)input events.

### AInputEvent processing

Your game should forward`AInputEvents`by calling[`Paddleboat_processInputEvent`](https://developer.android.com/reference/games/game-controller/group/paddleboat#paddleboat_processinputevent)from your event handling code.  

    int32_t Paddleboat_processInputEvent(const AInputEvent *event)

`Paddleboat_processInputEvent`will return`0`if the event was ignored and`1`if the event was processed and consumed by the Game Controller library.

### GameActivity event processing

If your game uses`GameActivity`, forward[`GameActivityKeyEvent`](https://developer.android.com/reference/games/game-activity/struct/game-activity-key-event)and[`GameActivityMotionEvent`](https://developer.android.com/reference/games/game-activity/struct/game-activity-motion-event)events by calling[`Paddleboat_processGameActivityKeyInputEvent`](https://developer.android.com/reference/games/game-controller/group/paddleboat#paddleboat_processgameactivitykeyinputevent)or[`Paddleboat_processGameActivityMotionInputEvent`](https://developer.android.com/reference/games/game-controller/group/paddleboat#paddleboat_processgameactivitymotioninputevent)from your event handling code.  

    int32_t Paddleboat_processGameActivityKeyInputEvent(const void *event,
                                                        const size_t eventSize)
    int32_t Paddleboat_processGameActivityMotionInputEvent(const void *event,
                                                           const size_t eventSize)

|  Parameter  |                                                      Description                                                       |
|-------------|------------------------------------------------------------------------------------------------------------------------|
| `event`     | A pointer to a`GameActivityKeyEvent`or`GameActivityMotionEvent`structure, depending on which function is being called. |
| `eventSize` | The size in bytes of the event structure passed in the`event`parameter.                                                |

Both functions will return`0`if the event was ignored and`1`if the event was processed and consumed by the Game Controller library.

`GameActivity`requires the active motion axis to be specified using the[`GameActivityPointerAxes_enableAxis`](https://developer.android.com/reference/games/game-activity/group/game-activity#group___game_activity_1gab1cc236d83c32a82e431b58f43cfd1af)function. The[`Paddleboat_getActiveAxisMask`](https://developer.android.com/reference/games/game-controller/group/paddleboat#paddleboat_getactiveaxismask)call returns a bitmask of currently active motion axis used by connected controllers.  

    uint64_t Paddleboat_getActiveAxisMask()

For an example of how to handle this, see the Game Controller library sample that uses`GameActivity`. The sample polls the active axis mask and informs`GameActivity`when new axis are used. This is implemented in the`NativeEngine::CheckForNewAxis()`function.  

    void NativeEngine::CheckForNewAxis() {
        // Tell GameActivity about any new axis ids so it reports
        // their events
        const uint64_t activeAxisIds = Paddleboat_getActiveAxisMask();
        uint64_t newAxisIds = activeAxisIds ^ mActiveAxisIds;
        if (newAxisIds != 0) {
            mActiveAxisIds = activeAxisIds;
            int32_t currentAxisId = 0;
            while(newAxisIds != 0) {
                if ((newAxisIds & 1) != 0) {
                    LOGD("Enable Axis: %d", currentAxisId);
                    GameActivityPointerAxes_enableAxis(currentAxisId);
                }
                ++currentAxisId;
                newAxisIds >>= 1;
            }
        }
    }

## Read controllers

The Game Controller library uses an index value to refer to a specific controller. Valid index values range from`0`to`PADDLEBOAT_MAX_CONTROLLERS - 1`. The[`Paddleboat_getControllerStatus`](https://developer.android.com/reference/games/game-controller/group/paddleboat#paddleboat_getcontrollerstatus)function determines the status of a specified controller index.  

    Paddleboat_ControllerStatus Paddleboat_getControllerStatus(
      const int32_t controllerIndex)

There are three functions for reading information from a connected controller.

- The[`Paddleboat_getControllerName`](https://developer.android.com/reference/games/game-controller/group/paddleboat#paddleboat_getcontrollername)function retrieves the name of the controller device.
- The[`Paddleboat_getControllerInfo`](https://developer.android.com/reference/games/game-controller/group/paddleboat#paddleboat_getcontrollerinfo)function retrieves data about the controller device itself.
- The[`Paddleboat_getControllerData`](https://developer.android.com/reference/games/game-controller/group/paddleboat#paddleboat_getcontrollerdata)function retrieves the current state of the controller inputs.

## Controller name

The`Paddleboat_getControllerName function`takes two input parameters: a controller index, a buffer size, and a pointer to a buffer to store the controller name string. The name string is formatted as a C string using UTF-8 encoding. The name of the device is obtained internally using`InputDevice.getName()`.

If`Paddleboat_getControllerName`successfully retrieves the name, it returns`PADDLEBOAT_NO_ERROR`, otherwise an appropriate error code is returned.  

    Paddleboat_ErrorCode Paddleboat_getControllerName(const int32_t controllerIndex,
                                                      const size_t bufferSize,
                                                      char *controllerName);

|     Parameter     |                                                              Description                                                               |
|-------------------|----------------------------------------------------------------------------------------------------------------------------------------|
| `controllerIndex` | Index of the controller that initiated the callback. Will be a value between`0`and `PADDLEBOAT_MAX_CONTROLLERS - 1`                    |
| `bufferSize`      | Size in bytes of the buffer passed by`controllerName`, the name string will be. truncated if necessary to fit in the buffer.           |
| `controllerName`  | A pointer to a buffer of`bufferSize`bytes to store the controller name in. The name will be stored as a C string using UTF-8 encoding. |

## Controller device information

The`Paddleboat_getControllerInfo function`takes two input parameters: a controller index and a pointer to a`Paddleboat_Controller_Info`structure.

If`Paddleboat_Controller_Info`was successfully populated with data,`Paddleboat_getControllerInfo`returns`PADDLEBOAT_NO_ERROR`, otherwise an appropriate error code is returned.  

    Paddleboat_ErrorCode Paddleboat_getControllerInfo(const int32_t controllerIndex,
      Paddleboat_Controller_Info *controllerInfo)

The`Paddleboat_Controller_Info`structure contains device-specific information about the controller.  

    typedef struct Paddleboat_Controller_Info {
        uint32_t controllerFlags;
        int32_t controllerNumber;
        int32_t vendorId;
        int32_t productId;
        int32_t deviceId;
        Paddleboat_Controller_Thumbstick_Precision leftStickPrecision;
        Paddleboat_Controller_Thumbstick_Precision rightStickPrecision;
    } Paddleboat_Controller_Info;

    typedef struct Paddleboat_Controller_Thumbstick_Precision {
        float stickFlatX;
        float stickFlatY;
        float stickFuzzX;
        float stickFuzzY;
    } Paddleboat_Controller_Thumbstick_Precision;

Several struct members are populated by values taken from the[`InputDevice`](https://developer.android.com/reference/android/view/InputDevice)associated with the controller:  

    controllerNumber    -   InputDevice.getControllerNumber()
    vendorId              - InputDevice.getVendorId()
    productId             - InputDevice.getProductId()
    deviceId              - InputDevice.getId()

- A`stickFlat`value represents the extent of a center flat position. This value is mainly useful for calculating a default center 'dead-zone' on self-centering devices.
- A`stickFuzz`value represents the error tolerance, or how far the current value may deviate from the actual value due to noise and device sensitivity limitations.

Both values are normalized to a maximum axis value of`1.0`in either dimension.

The`controllerFlags`member contains a combination of individual bitmasked flags and multiple-bit combination values.

Performing a logical`AND`of`controllerFlags`with`PADDLEBOAT_CONTROLLER_LAYOUT_MASK`results in a value that may be cast to the`Paddleboat_ControllerButtonLayout`enum. This enum specifies the button iconography and layout used by the controller.  

    enum Paddleboat_ControllerButtonLayout {
        //  Y
        // X B
        //  A
        PADDLEBOAT_CONTROLLER_LAYOUT_STANDARD = 0,
        //  △
        // □ ○
        //  x
        PADDLEBOAT_CONTROLLER_LAYOUT_SHAPES = 1,
        //  X
        // Y A
        //  B
        PADDLEBOAT_CONTROLLER_LAYOUT_REVERSE = 2,
        // X Y R1 L1
        // A B R2 L2
        PADDLEBOAT_CONTROLLER_LAYOUT_ARCADE_STICK = 3,
        PADDLEBOAT_CONTROLLER_LAYOUT_MASK = 3
    };

The following constants define capability bits. To determine if a controller supports a particular capability, perform a logical`AND`of the corresponding constant against`controllerFlags`. A non-zero result means the capability is supported by the controller.

`PADDLEBOAT_CONTROLLER_FLAG_TOUCHPAD`

If this flag bit is set, the controller has an integrated touchpad. If the touchpad is pressed, the controller sets the`PADDLEBOAT_BUTTON_TOUCHPAD`bit in the`Paddleboat_Controller_Data.buttonsDown`field.

`PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE`

If this flag bit is set, the controller emulates a pointer device. The`virtualPointer`member of the`Paddleboat_Controller_Data`structure is populated with the current coordinates of the virtual pointer.

## Controller data

The`Paddleboat_getControllerData`function takes two input parameters: a controller index and a pointer to a`Paddleboat_Controller_Data`structure. If`Paddleboat_Controller_Data`is successfully populated with data,`Paddleboat_getControllerInfo`returns`PADDLEBOAT_NO_ERROR`, otherwise an appropriate error code is returned.  

    Paddleboat_ErrorCode Paddleboat_getControllerData(const int32_t controllerIndex,
      Paddleboat_Controller_Data *controllerData)

The`Paddleboat_Controller_Data`structure contains the current control input values of the controller.  

    typedef struct Paddleboat_Controller_Data {
        uint64_t timestamp;
        uint32_t buttonsDown;
        Paddleboat_Controller_Thumbstick leftStick;
        Paddleboat_Controller_Thumbstick rightStick;
        float triggerL1;
        float triggerL2;
        float triggerR1;
        float triggerR2;
        Paddleboat_Controller_Pointer virtualPointer;
    } Paddleboat_Controller_Data;

    typedef struct Paddleboat_Controller_Pointer {
        float pointerX;
        float pointerY;
    } Paddleboat_Controller_Pointer;

    typedef struct Paddleboat_Controller_Thumbstick {
        float stickX;
        float stickY;
    } Paddleboat_Controller_Thumbstick;

### Value ranges

|    Input type    |               Value range               |
|------------------|-----------------------------------------|
| Thumbstick axis  | `-1.0`to`1.0`                           |
| Triggers         | `0.0`to`1.0`                            |
| Virtual pointers | `0.0`to window width/height (in pixels) |

| **Note:** Most, but not all controllers support L2/R2 button analog ranges. Some controllers have digital L2/R2 buttons and report either`0.0`or`1.0`. The L1/R1 triggers are generally digital and report either`0.0`or`1.0`, although analog ranges are reported if supported by the controller. Triggers will also set button bitmasks when pressed (in other words,`PADDLEBOAT_BUTTON_L1`).

### Structure details

| Structure member |                                                                    Description                                                                     |
|------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
| `buttonsDown`    | Bit-per-button bitfield array. Button bitmask constants are defined in the**paddleboat.h** . header file and begin with`PADDLEBOAT_BUTTON_`.       |
| `timestamp.`     | Timestamp of the most recent controller input event. The timestamp is microseconds since the clock epoch.                                          |
| `virtualPointer` | Virtual pointer location. Only valid if the`PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE`flag is set in`controllerFlags`, otherwise will be`0.0, 0.0`. |