1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef _CHRE_GNSS_H_
18 #define _CHRE_GNSS_H_
19 
20 /**
21  * @file
22  * Global Navigation Satellite System (GNSS) API.
23  *
24  * These structures and definitions are based on the Android N GPS HAL.
25  * Refer to that header file (located at this path as of the time of this
26  * comment: hardware/libhardware/include/hardware/gps.h) and associated
27  * documentation for further details and explanations for these fields.
28  * References in comments like "(ref: GnssAccumulatedDeltaRangeState)" map to
29  * the relevant element in the GPS HAL where additional information can be
30  * found.
31  *
32  * In general, the parts of this API that are taken from the GPS HAL follow the
33  * naming conventions established in that interface rather than the CHRE API
34  * conventions, in order to avoid confusion and enable code re-use where
35  * applicable.
36  */
37 
38 #include <stdbool.h>
39 #include <stdint.h>
40 
41 #include <chre/common.h>
42 
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46 
47 /**
48  * The set of flags that may be returned by chreGnssGetCapabilities()
49  * @defgroup CHRE_GNSS_CAPABILITIES
50  * @{
51  */
52 
53 //! A lack of flags indicates that GNSS is not supported in this CHRE
54 #define CHRE_GNSS_CAPABILITIES_NONE          UINT32_C(0)
55 
56 //! GNSS position fixes are supported via chreGnssLocationSessionStartAsync()
57 #define CHRE_GNSS_CAPABILITIES_LOCATION      UINT32_C(1 << 0)
58 
59 //! GNSS raw measurements are supported via
60 //! chreGnssMeasurementSessionStartAsync()
61 #define CHRE_GNSS_CAPABILITIES_MEASUREMENTS  UINT32_C(1 << 1)
62 
63 //! Location fixes supplied from chreGnssConfigurePassiveLocationListener()
64 //! are tapped in at the GNSS engine level, so they include additional fixes
65 //! such as those requested by the AP, and not just those requested by other
66 //! nanoapps within CHRE (which is the case when this flag is not set)
67 #define CHRE_GNSS_CAPABILITIES_GNSS_ENGINE_BASED_PASSIVE_LISTENER \
68                                              UINT32_C(1 << 2)
69 
70 /** @} */
71 
72 /**
73  * The current version of struct chreGnssDataEvent associated with this API
74  */
75 #define CHRE_GNSS_DATA_EVENT_VERSION  UINT8_C(0)
76 
77 /**
78  * The maximum time the CHRE implementation is allowed to elapse before sending
79  * an event with the result of an asynchronous request, unless specified
80  * otherwise
81  */
82 #define CHRE_GNSS_ASYNC_RESULT_TIMEOUT_NS  (5 * CHRE_NSEC_PER_SEC)
83 
84 /**
85  * Produce an event ID in the block of IDs reserved for GNSS
86  * @param offset  Index into GNSS event ID block; valid range [0,15]
87  */
88 #define CHRE_GNSS_EVENT_ID(offset)  (CHRE_EVENT_GNSS_FIRST_EVENT + (offset))
89 
90 /**
91  * nanoappHandleEvent argument: struct chreAsyncResult
92  *
93  * Communicates the asynchronous result of a request to the GNSS API, such as
94  * starting a location session via chreGnssLocationSessionStartAsync(). The
95  * requestType field in chreAsyncResult is set to a value from enum
96  * chreGnssRequestType.
97  */
98 #define CHRE_EVENT_GNSS_ASYNC_RESULT  CHRE_GNSS_EVENT_ID(0)
99 
100 /**
101  * nanoappHandleEvent argument: struct chreGnssLocationEvent
102  *
103  * Represents a location fix provided by the GNSS subsystem.
104  */
105 #define CHRE_EVENT_GNSS_LOCATION      CHRE_GNSS_EVENT_ID(1)
106 
107 /**
108  * nanoappHandleEvent argument: struct chreGnssDataEvent
109  *
110  * Represents a set of GNSS measurements with associated clock data.
111  */
112 #define CHRE_EVENT_GNSS_DATA          CHRE_GNSS_EVENT_ID(2)
113 
114 // NOTE: Do not add new events with ID > 15; only values 0-15 are reserved
115 // (see chre/event.h)
116 
117 // Flags indicating the Accumulated Delta Range's states
118 // (ref: GnssAccumulatedDeltaRangeState)
119 #define CHRE_GNSS_ADR_STATE_UNKNOWN     UINT16_C(0)
120 #define CHRE_GNSS_ADR_STATE_VALID       UINT16_C(1 << 0)
121 #define CHRE_GNSS_ADR_STATE_RESET       UINT16_C(1 << 1)
122 #define CHRE_GNSS_ADR_STATE_CYCLE_SLIP  UINT16_C(1 << 2)
123 
124 // Flags to indicate what fields in chreGnssClock are valid (ref: GnssClockFlags)
125 #define CHRE_GNSS_CLOCK_HAS_LEAP_SECOND        UINT16_C(1 << 0)
126 #define CHRE_GNSS_CLOCK_HAS_TIME_UNCERTAINTY   UINT16_C(1 << 1)
127 #define CHRE_GNSS_CLOCK_HAS_FULL_BIAS          UINT16_C(1 << 2)
128 #define CHRE_GNSS_CLOCK_HAS_BIAS               UINT16_C(1 << 3)
129 #define CHRE_GNSS_CLOCK_HAS_BIAS_UNCERTAINTY   UINT16_C(1 << 4)
130 #define CHRE_GNSS_CLOCK_HAS_DRIFT              UINT16_C(1 << 5)
131 #define CHRE_GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY  UINT16_C(1 << 6)
132 
133 // Flags to indicate which values are valid in a GpsLocation
134 // (ref: GpsLocationFlags)
135 #define CHRE_GPS_LOCATION_HAS_LAT_LONG           UINT16_C(1 << 0)
136 #define CHRE_GPS_LOCATION_HAS_ALTITUDE           UINT16_C(1 << 1)
137 #define CHRE_GPS_LOCATION_HAS_SPEED              UINT16_C(1 << 2)
138 #define CHRE_GPS_LOCATION_HAS_BEARING            UINT16_C(1 << 3)
139 #define CHRE_GPS_LOCATION_HAS_ACCURACY           UINT16_C(1 << 4)
140 
141 //! @since v1.3
142 #define CHRE_GPS_LOCATION_HAS_ALTITUDE_ACCURACY  UINT16_C(1 << 5)
143 //! @since v1.3
144 #define CHRE_GPS_LOCATION_HAS_SPEED_ACCURACY     UINT16_C(1 << 6)
145 //! @since v1.3
146 #define CHRE_GPS_LOCATION_HAS_BEARING_ACCURACY   UINT16_C(1 << 7)
147 
148 /**
149  * The maximum number of instances of struct chreGnssMeasurement that may be
150  * included in a single struct chreGnssDataEvent.
151  */
152 #define CHRE_GNSS_MAX_MEASUREMENT  UINT8_C(64)
153 
154 // Flags indicating the GNSS measurement state (ref: GnssMeasurementState)
155 #define CHRE_GNSS_MEASUREMENT_STATE_UNKNOWN                UINT16_C(0)
156 #define CHRE_GNSS_MEASUREMENT_STATE_CODE_LOCK              UINT16_C(1 << 0)
157 #define CHRE_GNSS_MEASUREMENT_STATE_BIT_SYNC               UINT16_C(1 << 1)
158 #define CHRE_GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC          UINT16_C(1 << 2)
159 #define CHRE_GNSS_MEASUREMENT_STATE_TOW_DECODED            UINT16_C(1 << 3)
160 #define CHRE_GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS         UINT16_C(1 << 4)
161 #define CHRE_GNSS_MEASUREMENT_STATE_SYMBOL_SYNC            UINT16_C(1 << 5)
162 #define CHRE_GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC        UINT16_C(1 << 6)
163 #define CHRE_GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED        UINT16_C(1 << 7)
164 #define CHRE_GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC        UINT16_C(1 << 8)
165 #define CHRE_GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC   UINT16_C(1 << 9)
166 #define CHRE_GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK     UINT16_C(1 << 10)
167 #define CHRE_GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK  UINT16_C(1 << 11)
168 #define CHRE_GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC      UINT16_C(1 << 12)
169 #define CHRE_GNSS_MEASUREMENT_STATE_SBAS_SYNC              UINT16_C(1 << 13)
170 
171 
172 /**
173  * Indicates a type of request made in this API. Used to populate the resultType
174  * field of struct chreAsyncResult sent with CHRE_EVENT_GNSS_ASYNC_RESULT.
175  */
176 enum chreGnssRequestType {
177     CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_START    = 1,
178     CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_STOP     = 2,
179     CHRE_GNSS_REQUEST_TYPE_MEASUREMENT_SESSION_START = 3,
180     CHRE_GNSS_REQUEST_TYPE_MEASUREMENT_SESSION_STOP  = 4,
181 };
182 
183 /**
184  * Constellation type associated with an SV
185  */
186 enum chreGnssConstellationType {
187     CHRE_GNSS_CONSTELLATION_UNKNOWN = 0,
188     CHRE_GNSS_CONSTELLATION_GPS     = 1,
189     CHRE_GNSS_CONSTELLATION_SBAS    = 2,
190     CHRE_GNSS_CONSTELLATION_GLONASS = 3,
191     CHRE_GNSS_CONSTELLATION_QZSS    = 4,
192     CHRE_GNSS_CONSTELLATION_BEIDOU  = 5,
193     CHRE_GNSS_CONSTELLATION_GALILEO = 6,
194 };
195 
196 /**
197  * Enumeration of available values for the chreGnssMeasurement multipath indicator
198  */
199 enum chreGnssMultipathIndicator {
200     //! The indicator is not available or unknown
201     CHRE_GNSS_MULTIPATH_INDICATOR_UNKNOWN     = 0,
202     //! The measurement is indicated to be affected by multipath
203     CHRE_GNSS_MULTIPATH_INDICATOR_PRESENT     = 1,
204     //! The measurement is indicated to be not affected by multipath
205     CHRE_GNSS_MULTIPATH_INDICATOR_NOT_PRESENT = 2,
206 };
207 
208 /**
209  * Represents an estimate of the GNSS clock time (see the Android GPS HAL for
210  * more detailed information)
211  */
212 struct chreGnssClock {
213     //! The GNSS receiver hardware clock value in nanoseconds, including
214     //! uncertainty
215     int64_t time_ns;
216 
217     //! The difference between hardware clock inside GNSS receiver and the
218     //! estimated GNSS time in nanoseconds; contains bias uncertainty
219     int64_t full_bias_ns;
220 
221     //! Sub-nanosecond bias, adds to full_bias_ns
222     float bias_ns;
223 
224     //! The clock's drift in nanoseconds per second
225     float drift_nsps;
226 
227     //! 1-sigma uncertainty associated with the clock's bias in nanoseconds
228     float bias_uncertainty_ns;
229 
230     //! 1-sigma uncertainty associated with the clock's drift in nanoseconds
231     //! per second
232     float drift_uncertainty_nsps;
233 
234     //! While this number stays the same, timeNs should flow continuously
235     uint32_t hw_clock_discontinuity_count;
236 
237     //! A set of flags indicating the validity of the fields in this data
238     //! structure (see GNSS_CLOCK_HAS_*)
239     uint16_t flags;
240 
241     //! Reserved for future use; set to 0
242     uint8_t reserved[2];
243 };
244 
245 /**
246  * Represents a GNSS measurement; contains raw and computed information (see the
247  * Android GPS HAL for more detailed information)
248  */
249 struct chreGnssMeasurement {
250     //! Hardware time offset from time_ns for this measurement, in nanoseconds
251     int64_t time_offset_ns;
252 
253     //! Accumulated delta range since the last channel reset in micro-meters
254     int64_t accumulated_delta_range_um;
255 
256     //! Received GNSS satellite time at the time of measurement, in nanoseconds
257     int64_t received_sv_time_in_ns;
258 
259     //! 1-sigma uncertainty of received GNSS satellite time, in nanoseconds
260     int64_t received_sv_time_uncertainty_in_ns;
261 
262     //! Pseudorange rate at the timestamp in meters per second (uncorrected)
263     float pseudorange_rate_mps;
264 
265     //! 1-sigma uncertainty of pseudorange rate in meters per second
266     float pseudorange_rate_uncertainty_mps;
267 
268     //! 1-sigma uncertainty of the accumulated delta range in meters
269     float accumulated_delta_range_uncertainty_m;
270 
271     //! Carrier-to-noise density in dB-Hz, in the range of [0, 63]
272     float c_n0_dbhz;
273 
274     //! Signal to noise ratio (dB), power above observed noise at correlators
275     float snr_db;
276 
277     //! Satellite sync state flags (GNSS_MEASUREMENT_STATE_*) - sets modulus for
278     //! received_sv_time_in_ns
279     uint16_t state;
280 
281     //! Set of ADR state flags (GNSS_ADR_STATE_*)
282     uint16_t accumulated_delta_range_state;
283 
284     //! Satellite vehicle ID number
285     int16_t svid;
286 
287     //! Constellation of the given satellite vehicle
288     //! @see #chreGnssConstellationType
289     uint8_t constellation;
290 
291     //! @see #chreGnssMultipathIndicator
292     uint8_t multipath_indicator;
293 
294     //! Reserved for future use; set to 0
295     uint8_t reserved[4];
296 };
297 
298 /**
299  * Data structure sent with events associated with CHRE_EVENT_GNSS_DATA, enabled
300  * via chreGnssMeasurementSessionStartAsync()
301  */
302 struct chreGnssDataEvent {
303     //! Indicates the version of the structure, for compatibility purposes.
304     //! Clients do not normally need to worry about this field; the CHRE
305     //! implementation guarantees that it only sends the client the structure
306     //! version it expects.
307     uint8_t version;
308 
309     //! Number of chreGnssMeasurement entries included in this event. Must be in
310     //! the range [0, CHRE_GNSS_MAX_MEASUREMENT]
311     uint8_t measurement_count;
312 
313     //! Reserved for future use; set to 0
314     uint8_t reserved[6];
315 
316     struct chreGnssClock clock;
317 
318     //! Pointer to an array containing measurement_count measurements
319     const struct chreGnssMeasurement *measurements;
320 };
321 
322 /**
323  * Data structure sent with events of type CHRE_EVENT_GNSS_LOCATION, enabled via
324  * chreGnssLocationSessionStartAsync(). This is modeled after GpsLocation in the
325  * GPS HAL, but does not use the double data type.
326  */
327 struct chreGnssLocationEvent {
328     //! UTC timestamp for location fix in milliseconds since January 1, 1970
329     uint64_t timestamp;
330 
331     //! Fixed point latitude, degrees times 10^7 (roughly centimeter resolution)
332     int32_t latitude_deg_e7;
333 
334     //! Fixed point longitude, degrees times 10^7 (roughly centimeter
335     //! resolution)
336     int32_t longitude_deg_e7;
337 
338     //! Altitude in meters above the WGS 84 reference ellipsoid
339     float altitude;
340 
341     //! Horizontal speed in meters per second
342     float speed;
343 
344     //! Clockwise angle between north and current heading, in degrees; range
345     //! [0, 360)
346     float bearing;
347 
348     //! Expected horizontal accuracy in meters such that a circle with a radius
349     //! of length 'accuracy' from the latitude and longitude has a 68%
350     //! probability of including the true location.
351     float accuracy;
352 
353     //! A set of flags indicating which fields in this structure are valid.
354     //! If any fields are not available, the flag must not be set and the field
355     //! must be initialized to 0.
356     //! @see #GpsLocationFlags
357     uint16_t flags;
358 
359     //! Reserved for future use; set to 0
360     //! @since v1.3
361     uint8_t reserved[2];
362 
363     //! Expected vertical accuracy in meters such that a range of
364     //! 2 * altitude_accuracy centered around altitude has a 68% probability of
365     //! including the true altitude.
366     //! @since v1.3
367     float altitude_accuracy;
368 
369     //! Expected speed accuracy in meters per second such that a range of
370     //! 2 * speed_accuracy centered around speed has a 68% probability of
371     //! including the true speed.
372     //! @since v1.3
373     float speed_accuracy;
374 
375     //! Expected bearing accuracy in degrees such that a range of
376     //! 2 * bearing_accuracy centered around bearing has a 68% probability of
377     //! including the true bearing.
378     //! @since v1.3
379     float bearing_accuracy;
380 };
381 
382 
383 /**
384  * Retrieves a set of flags indicating the GNSS features supported by the
385  * current CHRE implementation. The value returned by this function must be
386  * consistent for the entire duration of the Nanoapp's execution.
387  *
388  * The client must allow for more flags to be set in this response than it knows
389  * about, for example if the implementation supports a newer version of the API
390  * than the client was compiled against.
391  *
392  * @return A bitmask with zero or more CHRE_GNSS_CAPABILITIES_* flags set
393  *
394  * @since v1.1
395  */
396 uint32_t chreGnssGetCapabilities(void);
397 
398 /**
399  * Initiates a GNSS positioning session, or changes the requested interval of an
400  * existing session. If starting or modifying the session was successful, then
401  * the GNSS engine will work on determining the device's position.
402  *
403  * This result of this request is delivered asynchronously via an event of type
404  * CHRE_EVENT_GNSS_ASYNC_RESULT. Refer to the note in {@link #chreAsyncResult}
405  * for more details.
406  *
407  * If chreGnssGetCapabilities() returns a value that does not have the
408  * CHRE_GNSS_CAPABILITIES_LOCATION flag set, then this method will return false.
409  *
410  * @param minIntervalMs The desired minimum interval between location fixes
411  *        delivered to the client via CHRE_EVENT_GNSS_LOCATION, in milliseconds.
412  *        The requesting client must allow for fixes to be delivered at shorter
413  *        or longer interval than requested. For example, adverse RF conditions
414  *        may result in fixes arriving at a longer interval, etc.
415  * @param minTimeToNextFixMs The desired minimum time to the next location fix.
416  *        If this is 0, the GNSS engine should start working on the next fix
417  *        immediately. If greater than 0, the GNSS engine should not spend
418  *        measurable power to produce a location fix until this amount of time
419  *        has elapsed.
420  * @param cookie An opaque value that will be included in the chreAsyncResult
421  *        sent in relation to this request.
422  *
423  * @return true if the request was accepted for processing, false otherwise
424  *
425  * @since v1.1
426  */
427 bool chreGnssLocationSessionStartAsync(uint32_t minIntervalMs,
428                                        uint32_t minTimeToNextFixMs,
429                                        const void *cookie);
430 
431 /**
432  * Terminates an existing GNSS positioning session. If no positioning session
433  * is active at the time of this request, it is treated as if an active session
434  * was successfully ended.
435  *
436  * This result of this request is delivered asynchronously via an event of type
437  * CHRE_EVENT_GNSS_ASYNC_RESULT. Refer to the note in {@link #chreAsyncResult}
438  * for more details.
439  *
440  * After CHRE_EVENT_GNSS_ASYNC_RESULT is delivered to the client, no more
441  * CHRE_EVENT_GNSS_LOCATION events will be delievered until a new location
442  * session is started.
443  *
444  * If chreGnssGetCapabilities() returns a value that does not have the
445  * CHRE_GNSS_CAPABILITIES_LOCATION flag set, then this method will return false.
446  *
447  * @param cookie An opaque value that will be included in the chreAsyncResult
448  *        sent in relation to this request.
449  *
450  * @return true if the request was accepted for processing, false otherwise
451  *
452  * @since v1.1
453  */
454 bool chreGnssLocationSessionStopAsync(const void *cookie);
455 
456 /**
457  * Initiates a request to receive raw GNSS measurements. A GNSS measurement
458  * session can exist independently of location sessions. In other words, a
459  * Nanoapp is able to receive measurements at its requested interval both with
460  * and without an active location session.
461  *
462  * This result of this request is delivered asynchronously via an event of type
463  * CHRE_EVENT_GNSS_ASYNC_RESULT. Refer to the note in {@link #chreAsyncResult}
464  * for more details.
465  *
466  * If chreGnssGetCapabilities() returns a value that does not have the
467  * CHRE_GNSS_CAPABILITIES_MEASUREMENTS flag set, then this method will return
468  * false.
469  *
470  * @param minIntervalMs The desired minimum interval between measurement reports
471  *        delivered via CHRE_EVENT_GNSS_DATA. When requested at 1000ms or
472  *        faster, and GNSS measurements are tracked, device should report
473  *        measurements as fast as requested, and shall report no slower than
474  *        once every 1000ms, on average.
475  * @param cookie An opaque value that will be included in the chreAsyncResult
476  *        sent in relation to this request.
477  *
478  * @return true if the request was accepted for processing, false otherwise
479  *
480  * @since v1.1
481  */
482 bool chreGnssMeasurementSessionStartAsync(uint32_t minIntervalMs,
483                                           const void *cookie);
484 
485 /**
486  * Terminates an existing raw GNSS measurement session. If no measurement
487  * session is active at the time of this request, it is treated as if an active
488  * session was successfully ended.
489  *
490  * This result of this request is delivered asynchronously via an event of type
491  * CHRE_EVENT_GNSS_ASYNC_RESULT. Refer to the note in {@link #chreAsyncResult}
492  * for more details.
493  *
494  * If chreGnssGetCapabilities() returns a value that does not have the
495  * CHRE_GNSS_CAPABILITIES_MEASUREMENTS flag set, then this method will return
496  * false.
497  *
498  * @param cookie An opaque value that will be included in the chreAsyncResult
499  *        sent in relation to this request.
500  *
501  * @return true if the request was accepted for processing, false otherwise
502  *
503  * @since v1.1
504  */
505 bool chreGnssMeasurementSessionStopAsync(const void *cookie);
506 
507 /**
508  * Controls whether this nanoapp will passively receive GNSS-based location
509  * fixes produced as a result of location sessions initiated by other entities.
510  * This function allows a nanoapp to opportunistically receive location fixes
511  * via CHRE_EVENT_GNSS_LOCATION events without imposing additional power cost,
512  * though with no guarantees as to when or how often those events will arrive.
513  * There will be no duplication of events if a passive location listener and
514  * location session are enabled in parallel.
515  *
516  * Enabling passive location listening is not required to receive events for an
517  * active location session started via chreGnssLocationSessionStartAsync(). This
518  * setting is independent of the active location session, so modifying one does
519  * not have an effect on the other.
520  *
521  * If chreGnssGetCapabilities() returns a value that does not have the
522  * CHRE_GNSS_CAPABILITIES_LOCATION flag set or the value returned by
523  * chreGetApiVersion() is less than CHRE_API_VERSION_1_2, then this method will
524  * return false.
525  *
526  * If chreGnssGetCapabilities() includes
527  * CHRE_GNSS_CAPABILITIES_GNSS_ENGINE_BASED_PASSIVE_LISTENER, the passive
528  * registration is recorded at the GNSS engine level, so events include fixes
529  * requested by the applications processor and potentially other non-CHRE
530  * clients. If this flag is not set, then only fixes requested by other nanoapps
531  * within CHRE are provided.
532  *
533  * @param enable true to receive opportunistic location fixes, false to disable
534  *
535  * @return true if the configuration was processed successfully, false on error
536  *     or if this feature is not supported
537  *
538  * @since v1.2
539  */
540 bool chreGnssConfigurePassiveLocationListener(bool enable);
541 
542 #ifdef __cplusplus
543 }
544 #endif
545 
546 #endif  /* _CHRE_GNSS_H_ */
547