1e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol/*
2e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol * Copyright (C) 2017 The Android Open Source Project
3e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol *
4e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol * Licensed under the Apache License, Version 2.0 (the "License");
5e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol * you may not use this file except in compliance with the License.
6e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol * You may obtain a copy of the License at
7e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol *
8e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol *      http://www.apache.org/licenses/LICENSE-2.0
9e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol *
10e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol * Unless required by applicable law or agreed to in writing, software
11e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol * distributed under the License is distributed on an "AS IS" BASIS,
12e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol * See the License for the specific language governing permissions and
14e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol * limitations under the License.
15e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol */
16e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol
17a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol#include <chre.h>
18e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol#include <cinttypes>
19e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol
203884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung#include "chre/util/macros.h"
21a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol#include "chre/util/nanoapp/log.h"
2227d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol#include "chre/util/time.h"
23a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol
24a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol#define LOG_TAG "[GnssWorld]"
25a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol
26e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol#ifdef CHRE_NANOAPP_INTERNAL
27e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignolnamespace chre {
28e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignolnamespace {
29e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol#endif  // CHRE_NANOAPP_INTERNAL
30e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol
313e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung//! Control which test(s) to run
323e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chungconstexpr bool kEnableLocationTest = true;
333e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chungconstexpr bool kEnableMeasurementTest = true;
343e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
353e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung//! A dummy cookie to pass into the session async and timer request.
363884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chungconst uint32_t kLocationSessionCookie = 0x1337;
373e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chungconst uint32_t kMeasurementSessionCookie = 0xdaad;
3827d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol
3927d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol//! The minimum time to the next fix for a location.
4027d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignolconstexpr Milliseconds kLocationMinTimeToNextFix(0);
4127d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol
423e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung//! The interval in seconds between updates.
433e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chungconst uint32_t kReportIntervals[] = {
443884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung  30,
453884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung  15,
463884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung  30,
473884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung  15,
483884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung  0,
493884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung  10,
503884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung};
513884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung
523e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung//! Whether a specific Gnss capability is supported by the platform
533884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chungbool gLocationSupported = false;
543e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chungbool gMeasurementSupported = false;
553e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
563e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chunguint32_t gLocationTimerHandle;
573e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chunguint32_t gLocationTimerCount = 0;
583884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung
593e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chunguint32_t gMeasurementTimerHandle;
603e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chunguint32_t gMeasurementTimerCount = 0;
613884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung
623884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung//! Whether an async result has been received.
633e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chungbool gLocationAsyncResultReceived = false;
643e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chungbool gMeasurementAsyncResultReceived = false;
653884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung
663884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chungvoid makeLocationRequest() {
673e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  uint32_t interval = kReportIntervals[gLocationTimerCount++];
683884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung  LOGI("Modifying location update interval to %" PRIu32 " sec", interval);
693884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung
703884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung  if (interval > 0) {
713884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung    if (chreGnssLocationSessionStartAsync(
723884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung          interval * 1000,
733884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung          kLocationMinTimeToNextFix.getMilliseconds(),
743884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung          &kLocationSessionCookie)) {
753884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung      LOGI("Location session start request sent");
763884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung    } else {
773884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung      LOGE("Error sending location session start request");
783884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung    }
793884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung  } else {
803884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung    if (chreGnssLocationSessionStopAsync(
813884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung          &kLocationSessionCookie)) {
823884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung      LOGI("Location session stop request sent");
833884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung    } else {
843884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung      LOGE("Error sending location session stop request");
853884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung    }
863884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung  }
873884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung
883884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung  // set a timer to verify reception of async result.
893e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  gLocationTimerHandle = chreTimerSet(
903e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      CHRE_GNSS_ASYNC_RESULT_TIMEOUT_NS, /* 5 sec in CHRE 1.1 */
913e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      &kLocationSessionCookie, true /* oneShot */);
923e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung}
933e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
943e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chungvoid makeMeasurementRequest() {
953e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  uint32_t interval = kReportIntervals[gMeasurementTimerCount++];
963e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  LOGI("Modifying measurement update interval to %" PRIu32 " sec", interval);
973e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
983e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  if (interval > 0) {
993e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    if (chreGnssMeasurementSessionStartAsync(
1003e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung          interval * 1000, &kMeasurementSessionCookie)) {
1013e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      LOGI("Measurement session start request sent");
1023e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    } else {
1033e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      LOGE("Error sending measurement session start request");
1043e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    }
1053e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  } else {
1063e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    if (chreGnssMeasurementSessionStopAsync(
1073e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung          &kMeasurementSessionCookie)) {
1083e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      LOGI("Measurement session stop request sent");
1093e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    } else {
1103e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      LOGE("Error sending measurement session stop request");
1113e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    }
1123e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  }
1133e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
1143e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  // set a timer to verify reception of async result.
1153e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  gMeasurementTimerHandle = chreTimerSet(
1163884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung      CHRE_GNSS_ASYNC_RESULT_TIMEOUT_NS, /* 5 sec in CHRE 1.1 */
1173e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      &kMeasurementSessionCookie, true /* oneShot */);
1183884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung}
1193884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung
1203884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chungvoid handleTimerEvent(const void *eventData) {
1213e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  bool validData = true;
1223e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
1233e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  bool supported;
1243e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  const char *name;
1253e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  uint32_t timerCount;
1263e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  bool *asyncResultReceived;
1273e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  void (*makeRequest)();
1283e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
1293e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  if (eventData == &kLocationSessionCookie) {
1303e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    supported = gLocationSupported;
1313e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    name = "location";
1323e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    timerCount = gLocationTimerCount;
1333e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    asyncResultReceived = &gLocationAsyncResultReceived;
1343e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    makeRequest = makeLocationRequest;
1353e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  } else if (eventData == &kMeasurementSessionCookie) {
1363e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    supported = gMeasurementSupported;
1373e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    name = "measurement";
1383e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    timerCount = gMeasurementTimerCount;
1393e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    asyncResultReceived = &gMeasurementAsyncResultReceived;
1403e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    makeRequest = makeMeasurementRequest;
1413e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  } else {
1423e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    validData = false;
1433e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    LOGE("Invalid timer cookie");
1443884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung  }
1453884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung
1463e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  if (validData) {
1473e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    LOGI("%s timer event received, count %" PRIu32, name, timerCount);
1483e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    if (!*asyncResultReceived) {
1493e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      LOGE("%s async result not received!", name);
1503e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    }
1513e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    *asyncResultReceived = false;
1523e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
1533e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    if (supported && timerCount < ARRAY_SIZE(kReportIntervals)) {
1543e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      makeRequest();
1553e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    }
1563884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung  }
1573884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung}
1583884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung
15927d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignolvoid handleGnssAsyncResult(const chreAsyncResult *result) {
1603e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  bool validResult = true;
1613e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  const char *action = nullptr;
1623e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  const char *name;
1633e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  bool *received;
1643e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  const uint32_t *cookie;
16527d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol
1663e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  switch (result->requestType) {
1673e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    case CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_START:
1683e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      action = "start";
1693e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      // fall through to CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_STOP
1703e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
1713e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    case CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_STOP:
1723e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      if (action == nullptr) {
1733e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung        action = "stop";
1743e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      }
1753e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      name = "location";
1763e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      received = &gLocationAsyncResultReceived;
1773e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      cookie = &kLocationSessionCookie;
1783e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      break;
1793e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
1803e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    case CHRE_GNSS_REQUEST_TYPE_MEASUREMENT_SESSION_START:
1813e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      action = "start";
1823e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      // fall through to CHRE_GNSS_REQUEST_TYPE_MEASUREMENT_SESSION_STOP
1833e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
1843e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    case CHRE_GNSS_REQUEST_TYPE_MEASUREMENT_SESSION_STOP:
1853e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      if (action == nullptr) {
1863e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung        action = "stop";
1873e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      }
1883e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      name = "measurement";
1893e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      received = &gMeasurementAsyncResultReceived;
1903e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      cookie = &kMeasurementSessionCookie;
1913e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      break;
1923e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
1933e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    default:
1943e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      LOGE("Received invalid async result %" PRIu8, result->requestType);
1953e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      validResult = false;
1963e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      break;
1973e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  }
1983e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
1993e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  if (validResult) {
200b89961dcb9e0cf11df436ad01ed98d89a166738eMeng-hsuan Chung    *received = true;
2013884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung    if (result->success) {
2023e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      LOGI("GNSS %s %s success", name, action);
2033884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung    } else {
2043e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      LOGE("GNSS %s %s failure: %" PRIu8, name, action, result->errorCode);
2053884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung    }
2063884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung
2073e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    if (result->cookie != cookie) {
2083e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      LOGE("GNSS %s session %s request cookie mismatch", name, action);
2093884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung    }
21027d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol  }
21127d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol}
21227d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol
213f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignolvoid handleGnssLocationEvent(const chreGnssLocationEvent *event) {
214f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignol  LOGI("Received location: %" PRId32 ", %" PRId32, event->latitude_deg_e7,
215f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignol       event->longitude_deg_e7);
216f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignol  LOGI("  timestamp (ms): %" PRIu64, event->timestamp);
217f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignol  LOGI("  altitude (m): %f", event->altitude);
218f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignol  LOGI("  speed (m/s): %f", event->speed);
219f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignol  LOGI("  bearing (deg): %f", event->bearing);
220f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignol  LOGI("  accuracy: %f", event->accuracy);
221f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignol  LOGI("  flags: %" PRIx16, event->flags);
222f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignol}
223f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignol
2243e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chungvoid handleGnssDataEvent(const chreGnssDataEvent *event) {
2253e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  LOGI("Received data: %" PRIu8 " measurements", event->measurement_count);
2263e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
2273e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  const struct chreGnssMeasurement *measurement = event->measurements;
2283e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  for (uint8_t i = 0; i < event->measurement_count; i++) {
2293e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    LOGI("%" PRIu8 ": const %" PRIu8 ", cn0 %f",
2303e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung         i, measurement->constellation, measurement->c_n0_dbhz);
2313e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    measurement++;
2323e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  }
2333e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung}
2343e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
235e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignolbool nanoappStart() {
236a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol  LOGI("App started as instance %" PRIu32, chreGetInstanceId());
237e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol
238e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol  const char *gnssCapabilitiesStr;
239e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol  uint32_t gnssCapabilities = chreGnssGetCapabilities();
240e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol  switch (gnssCapabilities) {
241e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol    case CHRE_GNSS_CAPABILITIES_LOCATION
242e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol        | CHRE_GNSS_CAPABILITIES_MEASUREMENTS:
243e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol      gnssCapabilitiesStr = "LOCATION | MEASUREMENTS";
2443884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung      gLocationSupported = true;
2453e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      gMeasurementSupported = true;
246e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol      break;
247e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol    case CHRE_GNSS_CAPABILITIES_LOCATION:
248e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol      gnssCapabilitiesStr = "LOCATION";
2493884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung      gLocationSupported = true;
250e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol      break;
251e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol    case CHRE_GNSS_CAPABILITIES_MEASUREMENTS:
252e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol      gnssCapabilitiesStr = "MEASUREMENTS";
2533e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      gMeasurementSupported = true;
254e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol      break;
255e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol    case CHRE_GNSS_CAPABILITIES_NONE:
256e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol      gnssCapabilitiesStr = "NONE";
257e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol      break;
258e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol    default:
259e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol      gnssCapabilitiesStr = "INVALID";
260e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol  }
261e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol
262a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol  LOGI("Detected GNSS support as: %s (%" PRIu32 ")",
263a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol       gnssCapabilitiesStr, gnssCapabilities);
26427d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol
2653e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  if (gLocationSupported && kEnableLocationTest) {
2663884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung    makeLocationRequest();
26727d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol  }
26827d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol
2693e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  if (gMeasurementSupported && kEnableMeasurementTest) {
2703e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    makeMeasurementRequest();
2713e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung  }
2723e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung
273e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol  return true;
274e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol}
275e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol
276e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignolvoid nanoappHandleEvent(uint32_t senderInstanceId,
277e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol                        uint16_t eventType,
278e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol                        const void *eventData) {
27927d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol  switch (eventType) {
28027d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol    case CHRE_EVENT_GNSS_ASYNC_RESULT:
28127d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol      handleGnssAsyncResult(static_cast<const chreAsyncResult *>(eventData));
28227d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol      break;
283f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignol    case CHRE_EVENT_GNSS_LOCATION:
284f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignol      handleGnssLocationEvent(
285f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignol          static_cast<const chreGnssLocationEvent *>(eventData));
286f6dd8800732ba8c24448e4cd4fa3a135a218b509Andrew Rossignol      break;
2873e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung    case CHRE_EVENT_GNSS_DATA:
2883e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      handleGnssDataEvent(static_cast<const chreGnssDataEvent *>(eventData));
2893e1c98d9c4d08a47c439d4a60923edd2a23891b3Meng-hsuan Chung      break;
2903884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung    case CHRE_EVENT_TIMER:
2913884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung      handleTimerEvent(eventData);
2923884ae8a863be35992abc3c172a29f84ba8a4b83Meng-hsuan Chung      break;
29327d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol    default:
29427d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol      LOGW("Unhandled event type %" PRIu16, eventType);
29527d4adedb8c7d1f4b41388efb04a30a9038f33e1Andrew Rossignol  }
296e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol}
297e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol
2982b9d71a9f6a9e8cc0e787957d022154231f29962Brian Duddievoid nanoappEnd() {
299a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol  LOGI("Stopped");
300e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol}
301e47c28ffe449ca6b91ad0604be2bf164cdd490a3Andrew Rossignol
302e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol#ifdef CHRE_NANOAPP_INTERNAL
3039d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie}  // anonymous namespace
3049d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie}  // namespace chre
305e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol
3069d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie#include "chre/util/nanoapp/app_id.h"
3079d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie#include "chre/platform/static_nanoapp_init.h"
308e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol
3099d5b500a223ef73560f0dce38f50b809bde5dd0dBrian DuddieCHRE_STATIC_NANOAPP_INIT(GnssWorld, chre::kGnssWorldAppId, 0);
310e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol#endif  // CHRE_NANOAPP_INTERNAL
311