• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 #include <chre.h>
18 #include <cinttypes>
19 
20 #include "chre/util/macros.h"
21 #include "chre/util/nanoapp/log.h"
22 #include "chre/util/time.h"
23 
24 #define LOG_TAG "[GnssWorld]"
25 
26 #ifdef CHRE_NANOAPP_INTERNAL
27 namespace chre {
28 namespace {
29 #endif  // CHRE_NANOAPP_INTERNAL
30 
31 //! A dummy cookie to pass into the location session async request.
32 const uint32_t kLocationSessionCookie = 0x1337;
33 
34 //! The minimum time to the next fix for a location.
35 constexpr Milliseconds kLocationMinTimeToNextFix(0);
36 
37 //! The interval in seconds between location updates.
38 const uint32_t kLocationIntervals[] = {
39   30,
40   15,
41   30,
42   15,
43   0,
44   10,
45 };
46 
47 //! Whether Gnss Location capability is supported by the platform
48 bool gLocationSupported = false;
49 
50 uint32_t gTimerHandle;
51 uint32_t gTimerCount = 0;
52 
53 //! Whether an async result has been received.
54 bool gAsyncResultReceived = false;
55 
makeLocationRequest()56 void makeLocationRequest() {
57   uint32_t interval = kLocationIntervals[gTimerCount++];
58   LOGI("Modifying location update interval to %" PRIu32 " sec", interval);
59 
60   if (interval > 0) {
61     if (chreGnssLocationSessionStartAsync(
62           interval * 1000,
63           kLocationMinTimeToNextFix.getMilliseconds(),
64           &kLocationSessionCookie)) {
65       LOGI("Location session start request sent");
66     } else {
67       LOGE("Error sending location session start request");
68     }
69   } else {
70     if (chreGnssLocationSessionStopAsync(
71           &kLocationSessionCookie)) {
72       LOGI("Location session stop request sent");
73     } else {
74       LOGE("Error sending location session stop request");
75     }
76   }
77 
78   // set a timer to verify reception of async result.
79   gTimerHandle = chreTimerSet(
80       CHRE_GNSS_ASYNC_RESULT_TIMEOUT_NS, /* 5 sec in CHRE 1.1 */
81       nullptr /* data */, true /* oneShot */);
82 }
83 
handleTimerEvent(const void * eventData)84 void handleTimerEvent(const void *eventData) {
85   LOGI("Timer event received, count %d", gTimerCount);
86   if (!gAsyncResultReceived) {
87     LOGE("Async result not received!");
88   }
89   gAsyncResultReceived = false;
90 
91   if (gLocationSupported && gTimerCount < ARRAY_SIZE(kLocationIntervals)) {
92     makeLocationRequest();
93   }
94 }
95 
handleGnssAsyncResult(const chreAsyncResult * result)96 void handleGnssAsyncResult(const chreAsyncResult *result) {
97   if (result->requestType == CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_START) {
98     if (result->success) {
99       LOGI("Successfully requested a GNSS location session");
100       gAsyncResultReceived = true;
101     } else {
102       LOGE("Error requesting GNSS scan monitoring with %" PRIu8,
103            result->errorCode);
104     }
105 
106     if (result->cookie != &kLocationSessionCookie) {
107       LOGE("Location session start request cookie mismatch");
108     }
109   } else if (result->requestType
110              == CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_STOP) {
111     if (result->success) {
112       LOGI("Successfully stopped a GNSS location session");
113       gAsyncResultReceived = true;
114     } else {
115       LOGE("Error stoppinging GNSS scan monitoring with %" PRIu8,
116            result->errorCode);
117     }
118 
119     if (result->cookie != &kLocationSessionCookie) {
120       LOGE("Location session stop request cookie mismatch");
121     }
122   } else {
123     LOGE("Received invalid async result %" PRIu8, result->requestType);
124   }
125 }
126 
handleGnssLocationEvent(const chreGnssLocationEvent * event)127 void handleGnssLocationEvent(const chreGnssLocationEvent *event) {
128   LOGI("Received location: %" PRId32 ", %" PRId32, event->latitude_deg_e7,
129        event->longitude_deg_e7);
130   LOGI("  timestamp (ms): %" PRIu64, event->timestamp);
131   LOGI("  altitude (m): %f", event->altitude);
132   LOGI("  speed (m/s): %f", event->speed);
133   LOGI("  bearing (deg): %f", event->bearing);
134   LOGI("  accuracy: %f", event->accuracy);
135   LOGI("  flags: %" PRIx16, event->flags);
136 }
137 
nanoappStart()138 bool nanoappStart() {
139   LOGI("App started as instance %" PRIu32, chreGetInstanceId());
140 
141   const char *gnssCapabilitiesStr;
142   uint32_t gnssCapabilities = chreGnssGetCapabilities();
143   switch (gnssCapabilities) {
144     case CHRE_GNSS_CAPABILITIES_LOCATION
145         | CHRE_GNSS_CAPABILITIES_MEASUREMENTS:
146       gnssCapabilitiesStr = "LOCATION | MEASUREMENTS";
147       gLocationSupported = true;
148       break;
149     case CHRE_GNSS_CAPABILITIES_LOCATION:
150       gnssCapabilitiesStr = "LOCATION";
151       gLocationSupported = true;
152       break;
153     case CHRE_GNSS_CAPABILITIES_MEASUREMENTS:
154       gnssCapabilitiesStr = "MEASUREMENTS";
155       break;
156     case CHRE_GNSS_CAPABILITIES_NONE:
157       gnssCapabilitiesStr = "NONE";
158       break;
159     default:
160       gnssCapabilitiesStr = "INVALID";
161   }
162 
163   LOGI("Detected GNSS support as: %s (%" PRIu32 ")",
164        gnssCapabilitiesStr, gnssCapabilities);
165 
166   if (gLocationSupported) {
167     makeLocationRequest();
168   }
169 
170   return true;
171 }
172 
nanoappHandleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)173 void nanoappHandleEvent(uint32_t senderInstanceId,
174                         uint16_t eventType,
175                         const void *eventData) {
176   switch (eventType) {
177     case CHRE_EVENT_GNSS_ASYNC_RESULT:
178       handleGnssAsyncResult(static_cast<const chreAsyncResult *>(eventData));
179       break;
180     case CHRE_EVENT_GNSS_LOCATION:
181       handleGnssLocationEvent(
182           static_cast<const chreGnssLocationEvent *>(eventData));
183       break;
184     case CHRE_EVENT_TIMER:
185       handleTimerEvent(eventData);
186       break;
187     default:
188       LOGW("Unhandled event type %" PRIu16, eventType);
189   }
190 }
191 
nanoappEnd()192 void nanoappEnd() {
193   LOGI("Stopped");
194 }
195 
196 #ifdef CHRE_NANOAPP_INTERNAL
197 }  // anonymous namespace
198 }  // namespace chre
199 
200 #include "chre/util/nanoapp/app_id.h"
201 #include "chre/platform/static_nanoapp_init.h"
202 
203 CHRE_STATIC_NANOAPP_INIT(GnssWorld, chre::kGnssWorldAppId, 0);
204 #endif  // CHRE_NANOAPP_INTERNAL
205