/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _CHRE_SENSOR_H_
#define _CHRE_SENSOR_H_

/**
 * API dealing with sensor interaction in the Context Hub Runtime
 * Environment.
 *
 * This includes the definition of our sensor types and the ability to
 * configure them for receiving events.
 */

#include <stdbool.h>
#include <stdint.h>

// For CHRE_EVENT_SENSOR_FIRST_EVENT and CHRE_EVENT_SENSOR_LAST_EVENT
#include <chre/event.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * The CHRE_SENSOR_TYPE_* defines are the sensor types supported.
 *
 * Unless otherwise noted, each of these sensor types is based off of a
 * corresponding sensor type in the Android API's sensors.h interface.
 * For a given CHRE_SENSOR_TYPE_FOO, it corresponds to the SENSOR_TYPE_FOO in
 * hardware/libhardware/include/hardware/sensors.h of the Android code base.
 *
 * Unless otherwise noted below, a CHRE_SENSOR_TYPE_FOO should be assumed
 * to work the same as the Android SENSOR_TYPE_FOO, as documented in the
 * sensors.h documentation and as detailed within the Android Compatibility
 * Definition Document.
 *
 * Note that every sensor will generate CHRE_EVENT_SENSOR_SAMPLING_CHANGE
 * events, so it is not listed with each individual sensor.
 */

/**
 * Accelerometer.
 *
 * Generates: CHRE_EVENT_SENSOR_ACCELEROMETER_DATA
 *
 * @see CHRE_EVENT_SENSOR_ACCELEROMETER_DATA
 */
#define CHRE_SENSOR_TYPE_ACCELEROMETER  UINT8_C(1)

/**
 * Instantaneous motion detection.
 *
 * Generates: CHRE_EVENT_SENSOR_INSTANT_MOTION_DETECT_DATA
 *
 * This is a one-shot sensor.
 *
 * This does not have a direct analogy within sensors.h.  This is similar
 * to SENSOR_TYPE_MOTION_DETECT, but this triggers instantly upon any
 * motion, instead of waiting for a period of continuous motion.
 */
#define CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT  UINT8_C(2)

/**
 * Stationary detection.
 *
 * Generates: CHRE_EVENT_SENSOR_STATIONARY_DETECT_DATA
 *
 * This is a one-shot sensor.
 */
#define CHRE_SENSOR_TYPE_STATIONARY_DETECT  UINT8_C(3)

/**
 * Gyroscope.
 *
 * Generates: CHRE_EVENT_SENSOR_GYROSCOPE_DATA and
 *     CHRE_EVENT_SENSOR_GYROSCOPE_BIAS_INFO
 *
 * Note that the GYROSCOPE_DATA is always the calibrated data, and not
 * raw data.
 */
#define CHRE_SENSOR_TYPE_GYROSCOPE  UINT8_C(6)

/**
 * Magnetometer.
 *
 * Generates: CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_DATA and
 *     CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_BIAS_INFO
 *
 * Note that the GEOMAGNETIC_FIELD_DATA is always the calibrated data, and not
 * raw data.
 */
#define CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD  UINT8_C(8)

/**
 * Barometric pressure sensor.
 *
 * Generates: CHRE_EVENT_SENSOR_PRESSURE_DATA
 */
#define CHRE_SENSOR_TYPE_PRESSURE  UINT8_C(10)

/**
 * Ambient light sensor.
 *
 * Generates: CHRE_EVENT_SENSOR_LIGHT_DATA
 */
#define CHRE_SENSOR_TYPE_LIGHT  UINT8_C(12)

/**
 * Proximity detection.
 *
 * Generates: CHRE_EVENT_SENSOR_PROXIMITY_DATA
 *
 * This is an on-change sensor.
 */
#define CHRE_SENSOR_TYPE_PROXIMITY  UINT8_C(13)

/**
 * Base value for all of the data events for sensors.
 *
 * The value for a data event FOO is
 * CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_FOO
 *
 * This allows for easy mapping, and also explains why there are gaps
 * in our values since we don't have all possible sensor types assigned.
 */
#define CHRE_EVENT_SENSOR_DATA_EVENT_BASE  CHRE_EVENT_SENSOR_FIRST_EVENT

/**
 * nanoappHandleEvent argument: struct chreSensorThreeAxisData
 *
 * The data can be interpreted using the 'x', 'y', and 'z' fields within
 * 'readings', or by the 3D array 'v' (v[0] == x; v[1] == y; v[2] == z).
 *
 * All values are in SI units (m/s^2) and measure the acceleration of the
 * device minus the force of gravity.
 */
#define CHRE_EVENT_SENSOR_ACCELEROMETER_DATA \
    (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_ACCELEROMETER)

/**
 * nanoappHandleEvent argument: struct chreSensorOccurrenceData
 *
 * Since this is a one-shot sensor, after this event is delivered to the
 * nanoapp, the sensor automatically goes into DONE mode.  Sensors of this
 * type must be configured with a ONE_SHOT mode.
 */
#define CHRE_EVENT_SENSOR_INSTANT_MOTION_DETECT_DATA \
    (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT)

/**
 * nanoappHandleEvent argument: struct chreSensorOccurrenceData
 *
 * Since this is a one-shot sensor, after this event is delivered to the
 * nanoapp, the sensor automatically goes into DONE mode.  Sensors of this
 * type must be configured with a ONE_SHOT mode.
 */
#define CHRE_EVENT_SENSOR_STATIONARY_DETECT_DATA \
    (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_STATIONARY_DETECT)

/**
 * nanoappHandleEvent argument: struct chreSensorThreeAxisData
 *
 * The data can be interpreted using the 'x', 'y', and 'z' fields within
 * 'readings', or by the 3D array 'v' (v[0] == x; v[1] == y; v[2] == z).
 *
 * All values are in radians/second and measure the rate of rotation
 * around the X, Y and Z axis.
 */
#define CHRE_EVENT_SENSOR_GYROSCOPE_DATA \
    (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_GYROSCOPE)

/**
 * nanoappHandleEvent argument: struct chreSensorThreeAxisData
 *
 * The data can be interpreted using the 'x', 'y', and 'z' fields within
 * 'readings', or by the 3D array 'v' (v[0] == x; v[1] == y; v[2] == z).
 *
 * All values are in micro-Tesla (uT) and measure the geomagnetic
 * field in the X, Y and Z axis.
 */
#define CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_DATA \
    (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD)

/**
 * nanoappHandleEvent argument: struct chreSensorFloatData
 *
 * The data can be interpreted using the 'pressure' field within 'readings'.
 * This value is in hectopascals (hPa).
 */
#define CHRE_EVENT_SENSOR_PRESSURE_DATA \
    (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_PRESSURE)

/**
 * nanoappHandleEvent argument: struct chreSensorFloatData
 *
 * The data can be interpreted using the 'light' field within 'readings'.
 * This value is in SI lux units.
 */
#define CHRE_EVENT_SENSOR_LIGHT_DATA \
    (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_LIGHT)

/**
 * nanoappHandleEvent argument: struct chreSensorByteData
 *
 * The data is interpreted from the following fields in 'readings':
 * o 'isNear': If set to 1, we are nearby (on the order of centimeters);
 *       if set to 0, we are far.
 * o 'invalid': If set to 1, this is not a valid reading of this data.
 *
 * As an on-change sensor, there is an event generated upon configuring
 * this sensor.  This is when we might get an 'invalid' reading.  Thus,
 * this field must be checked on the first event before interpreting 'isNear'.
 */
#define CHRE_EVENT_SENSOR_PROXIMITY_DATA \
    (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_PROXIMITY)


/**
 * First value for sensor events which are not data from the sensor.
 *
 * Unlike the data event values, these other event values don't have any
 * mapping to sensor types.
 */
#define CHRE_EVENT_SENSOR_OTHER_EVENTS_BASE \
    (CHRE_EVENT_SENSOR_FIRST_EVENT + 0x0100)

/**
 * nanoappHandleEvent argument: struct chreSensorSamplingStatusEvent
 *
 * Indicates that the interval and/or the latency which this sensor is
 * sampling at has changed.
 */
#define CHRE_EVENT_SENSOR_SAMPLING_CHANGE \
    (CHRE_EVENT_SENSOR_OTHER_EVENTS_BASE + 0)

/**
 * nanoappHandleEvent argument: struct chreSensorThreeAxisData
 *
 * The data can be interpreted using the 'x_bias', 'y_bias', and 'z_bias'
 * field within 'readings', or by the 3D array 'bias' (bias[0] == x_bias;
 * bias[1] == y_bias; bias[2] == z_bias).
 *
 * All values are in radians/second and measure the rate of rotation
 * around the X, Y and Z axis.
 */
#define CHRE_EVENT_SENSOR_GYROSCOPE_BIAS_INFO \
    (CHRE_EVENT_SENSOR_OTHER_EVENTS_BASE + 1)

/**
 * nanoappHandleEvent argument: struct chreSensorThreeAxisData
 *
 * The data can be interpreted using the 'x_bias', 'y_bias', and 'z_bias'
 * field within 'readings', or by the 3D array 'bias' (bias[0] == x_bias;
 * bias[1] == y_bias; bias[2] == z_bias).
 *
 * All values are in micro-Tesla (uT) and measure the geomagnetic
 * field in the X, Y and Z axis.
 */
#define CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_BIAS_INFO \
    (CHRE_EVENT_SENSOR_OTHER_EVENTS_BASE + 2)


#if CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_BIAS_INFO > CHRE_EVENT_SENSOR_LAST_EVENT
#error Too many sensor events.
#endif


/**
 * Value indicating we want the smallest possible latency for a sensor.
 *
 * This literally translates to 0 nanoseconds for the chreSensorConfigure()
 * argument.  While we won't get exactly 0 nanoseconds, the CHRE will
 * queue up this event As Soon As Possible.
 */
#define CHRE_SENSOR_LATENCY_ASAP  UINT64_C(0)

/**
 * Special value indicating non-importance of the interval.
 *
 * @see chreSensorConfigure
 * @see chreSensorSamplingStatus
 */
#define CHRE_SENSOR_INTERVAL_DEFAULT  UINT64_C(-1)

/**
 * Special value indicating non-importance of the latency.
 *
 * @see chreSensorConfigure
 * @see chreSensorSamplingStatus
 */
#define CHRE_SENSOR_LATENCY_DEFAULT  UINT64_C(-1)


// This is used to define elements of enum chreSensorConfigureMode.
#define CHRE_SENSOR_CONFIGURE_RAW_POWER_ON           (1 << 0)

// This is used to define elements of enum chreSensorConfigureMode.
#define CHRE_SENSOR_CONFIGURE_RAW_REPORT_CONTINUOUS  (1 << 1)

// This is used to define elements of enum chreSensorConfigureMode.
#define CHRE_SENSOR_CONFIGURE_RAW_REPORT_ONE_SHOT    (2 << 1)



/**
 * Modes we can configure a sensor to use.
 *
 * Our mode will affect not only how/if we receive events, but
 * also whether or not the sensor will be powered on our behalf.
 *
 * @see chreSensorConfigure
 */
enum chreSensorConfigureMode {
    /**
     * Get events from the sensor.
     *
     * Power: Turn on if not already on.
     * Reporting: Continuous.  Send each new event as it comes (subject to
     *     batching and latency).
     */
    CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS =
        (CHRE_SENSOR_CONFIGURE_RAW_POWER_ON |
         CHRE_SENSOR_CONFIGURE_RAW_REPORT_CONTINUOUS),

    /**
     * Get a single event from the sensor and then become DONE.
     *
     * Once the event is sent, the sensor automatically
     * changes to CHRE_SENSOR_CONFIGURE_MODE_DONE mode.
     *
     * Power: Turn on if not already on.
     * Reporting: One shot.  Send the next event and then be DONE.
     */
    CHRE_SENSOR_CONFIGURE_MODE_ONE_SHOT =
        (CHRE_SENSOR_CONFIGURE_RAW_POWER_ON |
         CHRE_SENSOR_CONFIGURE_RAW_REPORT_ONE_SHOT),

    /**
     * Get events from a sensor that are generated for other apps.
     *
     * This is considered passive because the sensor will not be powered
     * on for the sake of our nanoapp.  If and only if another app in
     * the system has requested this sensor power on will we get events.
     *
     * This can be useful for something which is interested in seeing data,
     * but not interested enough to be responsible for powering on the sensor.
     *
     * Power: Do not power the sensor on our behalf.
     * Reporting: Continuous.  Send each event as it comes.
     */
    CHRE_SENSOR_CONFIGURE_MODE_PASSIVE_CONTINUOUS =
        CHRE_SENSOR_CONFIGURE_RAW_REPORT_CONTINUOUS,

    /**
     * Get a single event from a sensor that is generated for other apps.
     *
     * See CHRE_SENSOR_CONFIGURE_MODE_PASSIVE_CONTINUOUS for more details
     * on what be "passive" means.
     *
     * Power: Do not power the sensor on our behalf.
     * Reporting: One shot.  Send only the next event and then be DONE.
     */
    CHRE_SENSOR_CONFIGURE_MODE_PASSIVE_ONE_SHOT =
        CHRE_SENSOR_CONFIGURE_RAW_REPORT_ONE_SHOT,

    /**
     * Indicate we are done using this sensor and no longer interested in it.
     *
     * See chreSensorConfigure for more details on expressing interest or
     * lack of interest in a sensor.
     *
     * Power: Do not power the sensor on our behalf.
     * Reporting: None.
     */
    CHRE_SENSOR_CONFIGURE_MODE_DONE = 0,
};

/**
 * A structure containing information about a Sensor.
 *
 * See documentation of individual fields below.
 */
struct chreSensorInfo {
    /**
     * The name of the sensor.
     *
     * A text name, useful for logging/debugging, describing the Sensor.  This
     * is not assured to be unique (i.e. there could be multiple sensors with
     * the name "Temperature").
     *
     * CHRE implementations may not set this as NULL.  An empty
     * string, while discouraged, is legal.
     */
    const char *sensorName;

    /**
     * One of the CHRE_SENSOR_TYPE_* defines above.
     */
    uint8_t sensorType;

    /**
     * Flag indicating if this sensor is on-change.
     *
     * An on-change sensor only generates events when underlying state
     * changes.  This has the same meaning as on-change does in the Android
     * Sensors HAL.  See sensors.h for much more details.
     *
     * A value of 1 indicates this is on-change.  0 indicates this is not
     * on-change.
     */
    uint8_t isOnChange  : 1;

    /**
     * Flag indicating if this sensor is one-shot.
     *
     * A one-shot sensor only triggers a single event, and then automatically
     * disables itself.
     *
     * A value of 1 indicates this is on-change.  0 indicates this is not
     * on-change.
     */
    uint8_t isOneShot   : 1;
    uint8_t unusedFlags : 6;
};

/**
 * Header used in every structure containing batchable data from a sensor.
 *
 * The typical structure for sensor data looks like:
 *
 *   struct chreSensorTypeData {
 *       struct chreSensorDataHeader header;
 *       struct chreSensorTypeSampleData {
 *           uint32_t timestampDelta;
 *           union {
 *               <type> value;
 *               <type> interpretation0;
 *               <type> interpretation1;
 *           };
 *       } readings[1];
 *   };
 *
 * Despite 'readings' being declared as an array of 1 element,
 * an instance of the struct will actually have 'readings' as
 * an array of header.readingCount elements (which may be 1).
 * The 'timestampDelta' is in relation to the previous 'readings' (or
 * the baseTimestamp for readings[0].  So,
 * Timestamp for readings[0] == header.baseTimestamp +
 *     readings[0].timestampDelta.
 * Timestamp for readings[1] == timestamp for readings[0] +
 *     readings[1].timestampDelta.
 * And thus, in order to determine the timestamp for readings[N], it's
 * necessary to process through all of the N-1 readings.  The advantage,
 * though, is that our entire readings can span an arbitrary length of time,
 * just as long as any two consecutive readings differ by no more than
 * 4.295 seconds (timestampDelta, like all time in the CHRE, is in
 * nanoseconds).
 *
 * If a sensor has batched readings where two consecutive readings differ by
 * more than 4.295 seconds, the CHRE will split them across multiple
 * instances of the struct, and send multiple events.
 *
 * The value from the sensor is typically expressed in a union,
 * allowing a generic access to the data ('value'), along with
 * differently named access giving a more natural interpretation
 * of the data for the specific sensor types which use this
 * structure.  This allows, for example, barometer code to
 * reference readings[N].pressure, and an ambient light sensor
 * to reference readings[N].light, while both use the same
 * structure.
 */
struct chreSensorDataHeader {
    /**
     * The base timestamp, in nanoseconds.
     */
    uint64_t baseTimestamp;

    /**
     * The handle of the sensor producing this event.
     */
    uint32_t sensorHandle;

    /**
     * The number elements in the 'readings' array.
     *
     * This must be at least 1.
     */
    uint16_t readingCount;

    /**
     * Reserved bytes.
     *
     * These must be 0.
     */
    uint8_t reserved[2];
};

/**
 * Data for a sensor which reports on three axes.
 *
 * This is used by CHRE_EVENT_SENSOR_ACCELEROMETER_DATA,
 * CHRE_EVENT_SENSOR_GYROSCOPE_DATA,
 * CHRE_EVENT_SENSOR_GYROSCOPE_BIAS_INFO,
 * CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_DATA, and
 * CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_BIAS_INFO.
 */
struct chreSensorThreeAxisData {
    /**
     * @see chreSensorDataHeader
     */
    struct chreSensorDataHeader header;
    struct chreSensorThreeAxisSampleData {
        /**
         * @see chreSensorDataHeader
         */
        uint32_t timestampDelta;
        union {
            float values[3];
            float v[3];
            struct {
                float x;
                float y;
                float z;
            };
            float bias[3];
            struct {
                float x_bias;
                float y_bias;
                float z_bias;
            };
        };
    } readings[1];
};

/**
 * Data from a sensor where we only care about a event occurring.
 *
 * This is a bit unusual in that our readings have no data in addition
 * to the timestamp.  But since we only care about the occurrence, we
 * don't need to know anything else.
 *
 * Used by: CHRE_EVENT_SENSOR_INSTANT_MOTION_DETECT_DATA and
 *     CHRE_EVENT_SENSOR_STATIONARY_DETECT_DATA.
 */
struct chreSensorOccurrenceData {
    struct chreSensorDataHeader header;
    struct chreSensorOccurenceSampleData {
        uint32_t timestampDelta;
        // This space intentionally left blank.
        // Only the timestamp is meaningful here, there
        // is no additional data.
    } readings[1];
};

/**
 * CHRE_EVENT_SENSOR_LIGHT_DATA and CHRE_EVENT_SENSOR_PRESSURE_DATA.
 */
struct chreSensorFloatData {
    struct chreSensorDataHeader header;
    struct chreSensorFloatSampleData {
        uint32_t timestampDelta;
        union {
            float value;
            float light;  // lux
            float pressure;  // hectopascals (hPa)
        };
    } readings[1];
};

/**
 * CHRE_EVENT_SENSOR_PROXIMITY_DATA.
 */
struct chreSensorByteData {
    struct chreSensorDataHeader header;
    struct chreSensorByteSampleData {
        uint32_t timestampDelta;
        union {
            uint8_t value;
            struct {
                uint8_t isNear : 1;
                uint8_t invalid : 1;
                uint8_t padding0 : 6;
            };
        };
    } readings[1];
};

/**
 * The status of a sensor's sampling configuration.
 */
struct chreSensorSamplingStatus {
    /**
     * The interval, in nanoseconds, at which the sensor is now sampling.
     *
     * If this is CHRE_SENSOR_INTERVAL_DEFAULT, then a sampling interval
     * isn't meaningful for this sensor.
     *
     * Note that if 'enabled' is false, this value is not meaningful.
     */
    uint64_t interval;

    /**
     * The latency, in nanoseconds, at which the senor is now reporting.
     *
     * If this is CHRE_SENSOR_LATENCY_DEFAULT, then a latency
     * isn't meaningful for this sensor.
     *
     * Note that if 'enabled' is false, this value is not meaningful.
     */
    uint64_t latency;

    /**
     * True if the sensor is actively powered and sampling; false otherwise.
     */
    bool enabled;
};

/**
 * The nanoappHandleEvent argument for CHRE_EVENT_SENSOR_SAMPLING_CHANGE.
 *
 * Note that only at least one of 'interval' or 'latency' must be
 * different than it was prior to this event.  Thus, one of these
 * fields may be (but doesn't need to be) the same as before.
 */
struct chreSensorSamplingStatusEvent {
    /**
     * The handle of the sensor which has experienced a change in sampling.
     */
    uint32_t sensorHandle;

    /**
     * The new sampling status.
     *
     * At least one of the field in this struct will be different from
     * the previous sampling status event.
     */
    struct chreSensorSamplingStatus status;
};



/**
 * Find the default sensor for a given sensor type.
 *
 * @param sensorType One of the CHRE_SENSOR_TYPE_* constants.
 * @param handle  If a sensor is found, then the memory will be filled with
 *     the value for the sensor's handle.  This argument must be non-NULL.
 * @returns true if a sensor was found, false otherwise.
 */
bool chreSensorFindDefault(uint8_t sensorType, uint32_t *handle);

/**
 * Get the chreSensorInfo struct for a given sensor.
 *
 * @param sensorHandle  The sensor handle, as obtained from
 *     chreSensorFindDefault() or passed to nanoappHandleEvent().
 * @param info  If the sensor is valid, then this memory will be filled with
 *     the SensorInfo contents for this sensor.  This argument must be
 *     non-NULL.
 * @returns true if the senor handle is valid and 'info' was filled in;
 *     false otherwise.
 */
bool chreGetSensorInfo(uint32_t sensorHandle, struct chreSensorInfo *info);

/**
 * Get the chreSensorSamplingStatus struct for a given sensor.
 *
 * Note that this may be different from what was requested in
 * chreSensorConfigure(), for multiple reasons.  It's possible that the sensor
 * does not exactly support the interval requested in chreSensorConfigure(), so
 * a faster one was chosen.
 *
 * It's also possible that there is another user of this sensor who has
 * requested a faster interval and/or lower latency.  This latter scenario
 * should be noted, because it means the sensor rate can change due to no
 * interaction from this nanoapp.  Note that the
 * CHRE_EVENT_SENSOR_SAMPLING_CHANGE event will trigger in this case, so it's
 * not necessary to poll for such a change.
 *
 * @param sensorHandle  The sensor handle, as obtained from
 *     chreSensorFindDefault() or passed to nanoappHandleEvent().
 * @param status  If the sensor is valid, then this memory will be filled with
 *     the sampling status contents for this sensor.  This argument must be
 *     non-NULL.
 * @returns true if the senor handle is valid and 'status' was filled in;
 *     false otherwise.
 */
bool chreGetSensorSamplingStatus(uint32_t sensorHandle,
                                 struct chreSensorSamplingStatus *status);

/**
 * Configures a given sensor at a specific interval and latency and mode.
 *
 * If this sensor's chreSensorInfo has isOneShot set to 1,
 * then the mode must be one of the ONE_SHOT modes, or this method will fail.
 *
 * The CHRE wants to power as few sensors as possible, in keeping with its
 * low power design.  As such, it only turns on sensors when there are clients
 * actively interested in that sensor data, and turns off sensors as soon as
 * there are no clients interested in them.  Calling this method generally
 * indicates an interest, and using CHRE_SENSOR_CONFIGURE_MODE_DONE shows
 * when we are no longer interested.
 *
 * Thus, each initial Configure of a sensor (per nanoapp) needs to eventually
 * have a DONE call made, either directly or on its behalf.  Subsequent calls
 * to a Configure method within the same nanoapp, when there has been no DONE
 * in between, still only require a single DONE call.
 *
 * For example, the following is valid usage:
 * <code>
 *   chreSensorConfigure(myHandle, mode, interval0, latency0);
 *   [...]
 *   chreSensorConfigure(myHandle, mode, interval1, latency0);
 *   [...]
 *   chreSensorConfigure(myHandle, mode, interval1, latency1);
 *   [...]
 *   chreSensorConfigureModeOnly(myHandle, CHRE_SENSOR_CONFIGURE_MODE_DONE);
 * </code>
 *
 * The first call to Configure is the one which creates the requirement
 * to eventually call with DONE.  The subsequent calls are just changing the
 * interval/latency.  They have not changed the fact that this nanoapp is
 * still interested in output from the sensor 'myHandle'.  Thus, only one
 * single call for DONE is needed.
 *
 * There is a special case.  One-shot sensors, sensors which
 * just trigger a single event and never trigger again, implicitly go into
 * DONE mode after that single event triggers.  Thus, the
 * following are legitimate usages:
 * <code>
 *   chreSensorConfigure(myHandle, MODE_ONE_SHOT, rate, latency);
 *   [...]
 *   [myHandle triggers an event]
 *   [no need to configure to DONE].
 * </code>
 *
 * And:
 * <code>
 *   chreSensorConfigure(myHandle, MODE_ONE_SHOT, rate, latency);
 *   [...]
 *   chreSensorConfigureModeOnly(myHandle, MODE_DONE);
 *   [we cancelled myHandle before it ever triggered an event]
 * </code>
 *
 * Note that while PASSIVE modes, by definition, don't express
 * an interest in powering the sensor, DONE is still necessary
 * to silence the event reporting.
 *
 * @param sensorHandle  The handle to the sensor, as obtained from
 *     chreSensorFindDefault().
 * @param mode  The mode to use.  See descriptions within the
 *     chreSensorConfigureMode enum.
 * @param interval  The interval, in nanoseconds, at which we want events from
 *     the sensor.  On success, the sensor will be set to 'interval', or a value
 *     less than 'interval'.  There is a special value
 *     CHRE_SENSOR_INTERVAL_DEFAULT, in which we don't express a preference for
 *     the interval, and allow the sensor to chose what it wants.  Note that
 *     due to batching, we may receive events less frequently than
 *     'interval'.
 * @param latency  The maximum latency, in nanoseconds, allowed before the
 *     CHRE begins delivery of an event.  This will control how many events
 *     can be queued by the sensor before requiring a delivery event.
 *     Latency is defined as the "timestamp when event is queued by the CHRE"
 *     minus "timestamp of oldest unsent data reading".
 *     There is a special value CHRE_SENSOR_LATENCY_DEFAULT, in which we don't
 *     express a preference for the latency, and allow the sensor to chose what
 *     it wants.
 *     Note that there is no assurance of how long it will take an event to
 *     get through a CHRE's queueing system, and thus there is no ability to
 *     request a minimum time from the occurrence of a phenomenon to when the
 *     nanoapp receives the information.  The current CHRE API has no
 *     real-time elements, although future versions may introduce some to
 *     help with this issue.
 * @returns true if the configuration succeeded, false otherwise.
 *
 * @see chreSensorConfigureMode
 * @see chreSensorFindDefault
 * @see chreSensorInfo
 */
bool chreSensorConfigure(uint32_t sensorHandle,
                         enum chreSensorConfigureMode mode,
                         uint64_t interval, uint64_t latency);

/**
 * Short cut for chreSensorConfigure where we only want to change the mode.
 *
 * @see chreSensorConfigure
 */
static inline bool chreSensorConfigureModeOnly(
        uint32_t sensorHandle, enum chreSensorConfigureMode mode) {
    return chreSensorConfigure(sensorHandle,
                               mode,
                               CHRE_SENSOR_INTERVAL_DEFAULT,
                               CHRE_SENSOR_LATENCY_DEFAULT);
}


#ifdef __cplusplus
}
#endif

#endif  /* _CHRE_SENSOR_H_ */