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