You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
204 lines
5.9 KiB
204 lines
5.9 KiB
/* |
|
* Copyright (C) 2017 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. |
|
*/ |
|
|
|
#include <chre.h> |
|
#include <cinttypes> |
|
|
|
#include "chre/util/macros.h" |
|
#include "chre/util/nanoapp/log.h" |
|
#include "chre/util/time.h" |
|
|
|
#define LOG_TAG "[GnssWorld]" |
|
|
|
#ifdef CHRE_NANOAPP_INTERNAL |
|
namespace chre { |
|
namespace { |
|
#endif // CHRE_NANOAPP_INTERNAL |
|
|
|
//! A dummy cookie to pass into the location session async request. |
|
const uint32_t kLocationSessionCookie = 0x1337; |
|
|
|
//! The minimum time to the next fix for a location. |
|
constexpr Milliseconds kLocationMinTimeToNextFix(0); |
|
|
|
//! The interval in seconds between location updates. |
|
const uint32_t kLocationIntervals[] = { |
|
30, |
|
15, |
|
30, |
|
15, |
|
0, |
|
10, |
|
}; |
|
|
|
//! Whether Gnss Location capability is supported by the platform |
|
bool gLocationSupported = false; |
|
|
|
uint32_t gTimerHandle; |
|
uint32_t gTimerCount = 0; |
|
|
|
//! Whether an async result has been received. |
|
bool gAsyncResultReceived = false; |
|
|
|
void makeLocationRequest() { |
|
uint32_t interval = kLocationIntervals[gTimerCount++]; |
|
LOGI("Modifying location update interval to %" PRIu32 " sec", interval); |
|
|
|
if (interval > 0) { |
|
if (chreGnssLocationSessionStartAsync( |
|
interval * 1000, |
|
kLocationMinTimeToNextFix.getMilliseconds(), |
|
&kLocationSessionCookie)) { |
|
LOGI("Location session start request sent"); |
|
} else { |
|
LOGE("Error sending location session start request"); |
|
} |
|
} else { |
|
if (chreGnssLocationSessionStopAsync( |
|
&kLocationSessionCookie)) { |
|
LOGI("Location session stop request sent"); |
|
} else { |
|
LOGE("Error sending location session stop request"); |
|
} |
|
} |
|
|
|
// set a timer to verify reception of async result. |
|
gTimerHandle = chreTimerSet( |
|
CHRE_GNSS_ASYNC_RESULT_TIMEOUT_NS, /* 5 sec in CHRE 1.1 */ |
|
nullptr /* data */, true /* oneShot */); |
|
} |
|
|
|
void handleTimerEvent(const void *eventData) { |
|
LOGI("Timer event received, count %d", gTimerCount); |
|
if (!gAsyncResultReceived) { |
|
LOGE("Async result not received!"); |
|
} |
|
gAsyncResultReceived = false; |
|
|
|
if (gLocationSupported && gTimerCount < ARRAY_SIZE(kLocationIntervals)) { |
|
makeLocationRequest(); |
|
} |
|
} |
|
|
|
void handleGnssAsyncResult(const chreAsyncResult *result) { |
|
if (result->requestType == CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_START) { |
|
if (result->success) { |
|
LOGI("Successfully requested a GNSS location session"); |
|
gAsyncResultReceived = true; |
|
} else { |
|
LOGE("Error requesting GNSS scan monitoring with %" PRIu8, |
|
result->errorCode); |
|
} |
|
|
|
if (result->cookie != &kLocationSessionCookie) { |
|
LOGE("Location session start request cookie mismatch"); |
|
} |
|
} else if (result->requestType |
|
== CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_STOP) { |
|
if (result->success) { |
|
LOGI("Successfully stopped a GNSS location session"); |
|
gAsyncResultReceived = true; |
|
} else { |
|
LOGE("Error stoppinging GNSS scan monitoring with %" PRIu8, |
|
result->errorCode); |
|
} |
|
|
|
if (result->cookie != &kLocationSessionCookie) { |
|
LOGE("Location session stop request cookie mismatch"); |
|
} |
|
} else { |
|
LOGE("Received invalid async result %" PRIu8, result->requestType); |
|
} |
|
} |
|
|
|
void handleGnssLocationEvent(const chreGnssLocationEvent *event) { |
|
LOGI("Received location: %" PRId32 ", %" PRId32, event->latitude_deg_e7, |
|
event->longitude_deg_e7); |
|
LOGI(" timestamp (ms): %" PRIu64, event->timestamp); |
|
LOGI(" altitude (m): %f", event->altitude); |
|
LOGI(" speed (m/s): %f", event->speed); |
|
LOGI(" bearing (deg): %f", event->bearing); |
|
LOGI(" accuracy: %f", event->accuracy); |
|
LOGI(" flags: %" PRIx16, event->flags); |
|
} |
|
|
|
bool nanoappStart() { |
|
LOGI("App started as instance %" PRIu32, chreGetInstanceId()); |
|
|
|
const char *gnssCapabilitiesStr; |
|
uint32_t gnssCapabilities = chreGnssGetCapabilities(); |
|
switch (gnssCapabilities) { |
|
case CHRE_GNSS_CAPABILITIES_LOCATION |
|
| CHRE_GNSS_CAPABILITIES_MEASUREMENTS: |
|
gnssCapabilitiesStr = "LOCATION | MEASUREMENTS"; |
|
gLocationSupported = true; |
|
break; |
|
case CHRE_GNSS_CAPABILITIES_LOCATION: |
|
gnssCapabilitiesStr = "LOCATION"; |
|
gLocationSupported = true; |
|
break; |
|
case CHRE_GNSS_CAPABILITIES_MEASUREMENTS: |
|
gnssCapabilitiesStr = "MEASUREMENTS"; |
|
break; |
|
case CHRE_GNSS_CAPABILITIES_NONE: |
|
gnssCapabilitiesStr = "NONE"; |
|
break; |
|
default: |
|
gnssCapabilitiesStr = "INVALID"; |
|
} |
|
|
|
LOGI("Detected GNSS support as: %s (%" PRIu32 ")", |
|
gnssCapabilitiesStr, gnssCapabilities); |
|
|
|
if (gLocationSupported) { |
|
makeLocationRequest(); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
void nanoappHandleEvent(uint32_t senderInstanceId, |
|
uint16_t eventType, |
|
const void *eventData) { |
|
switch (eventType) { |
|
case CHRE_EVENT_GNSS_ASYNC_RESULT: |
|
handleGnssAsyncResult(static_cast<const chreAsyncResult *>(eventData)); |
|
break; |
|
case CHRE_EVENT_GNSS_LOCATION: |
|
handleGnssLocationEvent( |
|
static_cast<const chreGnssLocationEvent *>(eventData)); |
|
break; |
|
case CHRE_EVENT_TIMER: |
|
handleTimerEvent(eventData); |
|
break; |
|
default: |
|
LOGW("Unhandled event type %" PRIu16, eventType); |
|
} |
|
} |
|
|
|
void nanoappEnd() { |
|
LOGI("Stopped"); |
|
} |
|
|
|
#ifdef CHRE_NANOAPP_INTERNAL |
|
} // anonymous namespace |
|
} // namespace chre |
|
|
|
#include "chre/util/nanoapp/app_id.h" |
|
#include "chre/platform/static_nanoapp_init.h" |
|
|
|
CHRE_STATIC_NANOAPP_INIT(GnssWorld, chre::kGnssWorldAppId, 0); |
|
#endif // CHRE_NANOAPP_INTERNAL
|
|
|