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