xref: /aosp_15_r20/system/chre/platform/linux/pal_gnss.cc (revision 84e339476a462649f82315436d70fd732297a399)
1 /*
2  * Copyright (C) 2020 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/platform/linux/pal_gnss.h"
18 #include "chre/pal/gnss.h"
19 #include "chre/platform/linux/task_util/task_manager.h"
20 #include "chre/platform/log.h"
21 
22 #include "chre/util/memory.h"
23 #include "chre/util/unique_ptr.h"
24 
25 #include <chrono>
26 #include <cinttypes>
27 #include <mutex>
28 #include <optional>
29 
30 /**
31  * A simulated implementation of the GNSS PAL for the linux platform.
32  */
33 namespace {
34 
35 using ::chre::TaskManagerSingleton;
36 
37 const struct chrePalSystemApi *gSystemApi = nullptr;
38 const struct chrePalGnssCallbacks *gCallbacks = nullptr;
39 
40 // Task to deliver asynchronous location data after a CHRE request.
41 std::mutex gLocationEventsMutex;
42 std::optional<uint32_t> gLocationEventsTaskId;
43 uint32_t gLocationEventsMinIntervalMs = 0;
44 bool gDelaySendingLocationEvents = false;
45 bool gIsLocationEnabled = false;
46 
47 // Task to use when delivering a location status update.
48 std::optional<uint32_t> gLocationStatusTaskId;
49 
50 // Task to deliver asynchronous measurement data after a CHRE request.
51 std::optional<uint32_t> gMeasurementEventsTaskId;
52 bool gIsMeasurementEnabled = false;
53 
54 // Task to use when delivering a measurement status update.
55 std::optional<uint32_t> gMeasurementStatusTaskId;
56 
57 // Passive listener flag.
58 bool gIsPassiveListenerEnabled = false;
59 
sendLocationEvents()60 void sendLocationEvents() {
61   if (!gIsLocationEnabled) {
62     return;
63   }
64 
65   auto event = chre::MakeUniqueZeroFill<struct chreGnssLocationEvent>();
66   event->timestamp = gSystemApi->getCurrentTime();
67   gCallbacks->locationEventCallback(event.release());
68 }
69 
startSendingLocationEvents(uint32_t minIntervalMs)70 void startSendingLocationEvents(uint32_t minIntervalMs) {
71   std::lock_guard<std::mutex> lock(gLocationEventsMutex);
72   if (gLocationEventsTaskId.has_value()) {
73     TaskManagerSingleton::get()->cancelTask(gLocationEventsTaskId.value());
74     gLocationEventsTaskId.reset();
75   }
76 
77   TaskManagerSingleton::get()->addTask(
78       []() { gCallbacks->locationStatusChangeCallback(true, CHRE_ERROR_NONE); },
79       std::chrono::nanoseconds(0), true /* isOneShot */);
80 
81   gLocationEventsTaskId = TaskManagerSingleton::get()->addTask(
82       sendLocationEvents, std::chrono::milliseconds(minIntervalMs));
83 }
84 
sendMeasurementEvents()85 void sendMeasurementEvents() {
86   if (!gIsMeasurementEnabled) {
87     return;
88   }
89 
90   auto event = chre::MakeUniqueZeroFill<struct chreGnssDataEvent>();
91   auto measurement = chre::MakeUniqueZeroFill<struct chreGnssMeasurement>();
92   measurement->c_n0_dbhz = 63.0f;
93   event->measurement_count = 1;
94   event->clock.time_ns = static_cast<int64_t>(gSystemApi->getCurrentTime());
95   event->measurements = measurement.release();
96   gCallbacks->measurementEventCallback(event.release());
97 }
98 
stopLocation()99 void stopLocation() {
100   gCallbacks->locationStatusChangeCallback(false, CHRE_ERROR_NONE);
101 }
102 
stopMeasurement()103 void stopMeasurement() {
104   gCallbacks->measurementStatusChangeCallback(false, CHRE_ERROR_NONE);
105 }
106 
stopLocationTasks()107 void stopLocationTasks() {
108   {
109     std::lock_guard<std::mutex> lock(gLocationEventsMutex);
110 
111     if (gLocationEventsTaskId.has_value()) {
112       TaskManagerSingleton::get()->cancelTask(gLocationEventsTaskId.value());
113       gLocationEventsTaskId.reset();
114     }
115   }
116 
117   if (gLocationStatusTaskId.has_value()) {
118     TaskManagerSingleton::get()->cancelTask(gLocationStatusTaskId.value());
119     gLocationStatusTaskId.reset();
120   }
121 }
122 
stopMeasurementTasks()123 void stopMeasurementTasks() {
124   if (gMeasurementEventsTaskId.has_value()) {
125     TaskManagerSingleton::get()->cancelTask(gMeasurementEventsTaskId.value());
126     gMeasurementEventsTaskId.reset();
127   }
128 
129   if (gMeasurementStatusTaskId.has_value()) {
130     TaskManagerSingleton::get()->cancelTask(gMeasurementStatusTaskId.value());
131     gMeasurementStatusTaskId.reset();
132   }
133 }
134 
chrePalGnssGetCapabilities()135 uint32_t chrePalGnssGetCapabilities() {
136   return CHRE_GNSS_CAPABILITIES_LOCATION | CHRE_GNSS_CAPABILITIES_MEASUREMENTS |
137          CHRE_GNSS_CAPABILITIES_GNSS_ENGINE_BASED_PASSIVE_LISTENER;
138 }
139 
chrePalControlLocationSession(bool enable,uint32_t minIntervalMs,uint32_t)140 bool chrePalControlLocationSession(bool enable, uint32_t minIntervalMs,
141                                    uint32_t /* minTimeToNextFixMs */) {
142   stopLocationTasks();
143 
144   gLocationEventsMinIntervalMs = minIntervalMs;
145   if (enable && !gDelaySendingLocationEvents) {
146     startSendingLocationEvents(minIntervalMs);
147     if (!gLocationEventsTaskId.has_value()) {
148       return false;
149     }
150   } else if (!enable) {
151     gLocationStatusTaskId = TaskManagerSingleton::get()->addTask(stopLocation);
152     if (!gLocationStatusTaskId.has_value()) {
153       return false;
154     }
155   }
156 
157   gIsLocationEnabled = enable;
158   return true;
159 }
160 
chrePalGnssReleaseLocationEvent(struct chreGnssLocationEvent * event)161 void chrePalGnssReleaseLocationEvent(struct chreGnssLocationEvent *event) {
162   chre::memoryFree(event);
163 }
164 
chrePalControlMeasurementSession(bool enable,uint32_t minIntervalMs)165 bool chrePalControlMeasurementSession(bool enable, uint32_t minIntervalMs) {
166   stopMeasurementTasks();
167 
168   if (enable) {
169     std::optional<uint32_t> measurementEventsChangeCallbackTaskId =
170         TaskManagerSingleton::get()->addTask(
171             []() {
172               gCallbacks->measurementStatusChangeCallback(true,
173                                                           CHRE_ERROR_NONE);
174             },
175             std::chrono::nanoseconds(0), true /* isOneShot */);
176     if (!measurementEventsChangeCallbackTaskId.has_value()) {
177       return false;
178     }
179 
180     gMeasurementEventsTaskId = TaskManagerSingleton::get()->addTask(
181         sendMeasurementEvents, std::chrono::milliseconds(minIntervalMs));
182     if (!gMeasurementEventsTaskId.has_value()) {
183       return false;
184     }
185   } else {
186     gMeasurementStatusTaskId =
187         TaskManagerSingleton::get()->addTask(stopMeasurement);
188     if (!gMeasurementStatusTaskId.has_value()) {
189       return false;
190     }
191   }
192 
193   gIsMeasurementEnabled = enable;
194   return true;
195 }
196 
chrePalGnssReleaseMeasurementDataEvent(struct chreGnssDataEvent * event)197 void chrePalGnssReleaseMeasurementDataEvent(struct chreGnssDataEvent *event) {
198   chre::memoryFree(
199       const_cast<struct chreGnssMeasurement *>(event->measurements));
200   chre::memoryFree(event);
201 }
202 
chrePalGnssApiClose()203 void chrePalGnssApiClose() {
204   stopLocationTasks();
205   stopMeasurementTasks();
206 }
207 
chrePalGnssApiOpen(const struct chrePalSystemApi * systemApi,const struct chrePalGnssCallbacks * callbacks)208 bool chrePalGnssApiOpen(const struct chrePalSystemApi *systemApi,
209                         const struct chrePalGnssCallbacks *callbacks) {
210   chrePalGnssApiClose();
211 
212   bool success = false;
213   if (systemApi != nullptr && callbacks != nullptr) {
214     gSystemApi = systemApi;
215     gCallbacks = callbacks;
216     success = true;
217   }
218 
219   return success;
220 }
221 
chrePalGnssconfigurePassiveLocationListener(bool enable)222 bool chrePalGnssconfigurePassiveLocationListener(bool enable) {
223   gIsPassiveListenerEnabled = enable;
224   return true;
225 }
226 
227 }  // anonymous namespace
228 
chrePalGnssIsLocationEnabled()229 bool chrePalGnssIsLocationEnabled() {
230   return gIsLocationEnabled;
231 }
232 
chrePalGnssIsMeasurementEnabled()233 bool chrePalGnssIsMeasurementEnabled() {
234   return gIsMeasurementEnabled;
235 }
236 
chrePalGnssIsPassiveLocationListenerEnabled()237 bool chrePalGnssIsPassiveLocationListenerEnabled() {
238   return gIsPassiveListenerEnabled;
239 }
240 
chrePalGnssDelaySendingLocationEvents(bool enabled)241 void chrePalGnssDelaySendingLocationEvents(bool enabled) {
242   gDelaySendingLocationEvents = enabled;
243 }
244 
chrePalGnssStartSendingLocationEvents()245 void chrePalGnssStartSendingLocationEvents() {
246   CHRE_ASSERT(gDelaySendingLocationEvents);
247   startSendingLocationEvents(gLocationEventsMinIntervalMs);
248 }
249 
chrePalGnssGetApi(uint32_t requestedApiVersion)250 const struct chrePalGnssApi *chrePalGnssGetApi(uint32_t requestedApiVersion) {
251   static const struct chrePalGnssApi kApi = {
252       .moduleVersion = CHRE_PAL_GNSS_API_CURRENT_VERSION,
253       .open = chrePalGnssApiOpen,
254       .close = chrePalGnssApiClose,
255       .getCapabilities = chrePalGnssGetCapabilities,
256       .controlLocationSession = chrePalControlLocationSession,
257       .releaseLocationEvent = chrePalGnssReleaseLocationEvent,
258       .controlMeasurementSession = chrePalControlMeasurementSession,
259       .releaseMeasurementDataEvent = chrePalGnssReleaseMeasurementDataEvent,
260       .configurePassiveLocationListener =
261           chrePalGnssconfigurePassiveLocationListener,
262   };
263 
264   if (!CHRE_PAL_VERSIONS_ARE_COMPATIBLE(kApi.moduleVersion,
265                                         requestedApiVersion)) {
266     return nullptr;
267   } else {
268     return &kApi;
269   }
270 }
271