1 /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
2  *
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are
5  * met:
6  *     * Redistributions of source code must retain the above copyright
7  *       notice, this list of conditions and the following disclaimer.
8  *     * Redistributions in binary form must reproduce the above
9  *       copyright notice, this list of conditions and the following
10  *       disclaimer in the documentation and/or other materials provided
11  *       with the distribution.
12  *     * Neither the name of The Linux Foundation, nor the names of its
13  *       contributors may be used to endorse or promote products derived
14  *       from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 #define LOG_NDEBUG 0
30 #define LOG_TAG "LocSvc_GnssAdapter"
31 
32 #include <inttypes.h>
33 #include <sys/stat.h>
34 #include <errno.h>
35 #include <ctype.h>
36 #include <cutils/properties.h>
37 #include <math.h>
38 #include <arpa/inet.h>
39 #include <netinet/in.h>
40 #include <netdb.h>
41 #include <GnssAdapter.h>
42 #include <string>
43 #include <sstream>
44 #include <loc_log.h>
45 #include <loc_nmea.h>
46 #include <Agps.h>
47 #include <SystemStatus.h>
48 
49 #include <vector>
50 
51 #define RAD2DEG    (180.0 / M_PI)
52 #define PROCESS_NAME_ENGINE_SERVICE "engine-service"
53 #define MIN_TRACKING_INTERVAL (100) // 100 msec
54 
55 using namespace loc_core;
56 
57 /* Method to fetch status cb from loc_net_iface library */
58 typedef AgpsCbInfo& (*LocAgpsGetAgpsCbInfo)(LocAgpsOpenResultCb openResultCb,
59         LocAgpsCloseResultCb closeResultCb, void* userDataPtr);
60 
61 static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
62         AGpsBearerType bearerType, void* userDataPtr);
63 static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr);
64 
GnssAdapter()65 GnssAdapter::GnssAdapter() :
66     LocAdapterBase(0,
67                    LocContext::getLocContext(NULL,
68                                                    NULL,
69                                                    LocContext::mLocationHalName,
70                                                    false), true, nullptr),
71     mEngHubProxy(new EngineHubProxyBase()),
72     mLocPositionMode(),
73     mGnssSvIdUsedInPosition(),
74     mGnssSvIdUsedInPosAvail(false),
75     mControlCallbacks(),
76     mAfwControlId(0),
77     mNmeaMask(0),
78     mGnssSvIdConfig(),
79     mGnssSvTypeConfig(),
80     mGnssSvTypeConfigCb(nullptr),
81     mNiData(),
82     mAgpsManager(),
83     mOdcpiRequestCb(nullptr),
84     mOdcpiRequestActive(false),
85     mOdcpiTimer(this),
86     mOdcpiRequest(),
87     mSystemStatus(SystemStatus::getInstance(mMsgTask)),
88     mServerUrl(":"),
89     mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask),
90     mLocSystemInfo{},
91     mBlockCPIInfo{},
92     mNfwCb(NULL),
93     mPowerOn(false),
94     mAllowFlpNetworkFixes(0),
95     mGnssEnergyConsumedCb(nullptr),
96     mPowerStateCb(nullptr),
97     mIsE911Session(NULL),
98     mGnssMbSvIdUsedInPosition{},
99     mGnssMbSvIdUsedInPosAvail(false),
100     mSupportNfwControl(true)
101 {
102     LOC_LOGD("%s]: Constructor %p", __func__, this);
103     mLocPositionMode.mode = LOC_POSITION_MODE_INVALID;
104 
105     pthread_condattr_t condAttr;
106     pthread_condattr_init(&condAttr);
107     pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
108     pthread_cond_init(&mNiData.session.tCond, &condAttr);
109     pthread_cond_init(&mNiData.sessionEs.tCond, &condAttr);
110     pthread_condattr_destroy(&condAttr);
111 
112     /* Set ATL open/close callbacks */
113     AgpsAtlOpenStatusCb atlOpenStatusCb =
114             [this](int handle, int isSuccess, char* apn, uint32_t apnLen,
__anon04917ab80102(int handle, int isSuccess, char* apn, uint32_t apnLen, AGpsBearerType bearerType, AGpsExtType agpsType, LocApnTypeMask mask) 115                     AGpsBearerType bearerType, AGpsExtType agpsType, LocApnTypeMask mask) {
116 
117                 mLocApi->atlOpenStatus(
118                         handle, isSuccess, apn, apnLen, bearerType, agpsType, mask);
119             };
120     AgpsAtlCloseStatusCb atlCloseStatusCb =
__anon04917ab80202(int handle, int isSuccess) 121             [this](int handle, int isSuccess) {
122 
123                 mLocApi->atlCloseStatus(handle, isSuccess);
124             };
125     mAgpsManager.registerATLCallbacks(atlOpenStatusCb, atlCloseStatusCb);
126 
127     readConfigCommand();
128     initDefaultAgpsCommand();
129     initEngHubProxyCommand();
130 }
131 
132 void
setControlCallbacksCommand(LocationControlCallbacks & controlCallbacks)133 GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks)
134 {
135     struct MsgSetControlCallbacks : public LocMsg {
136         GnssAdapter& mAdapter;
137         const LocationControlCallbacks mControlCallbacks;
138         inline MsgSetControlCallbacks(GnssAdapter& adapter,
139                                       LocationControlCallbacks& controlCallbacks) :
140             LocMsg(),
141             mAdapter(adapter),
142             mControlCallbacks(controlCallbacks) {}
143         inline virtual void proc() const {
144             mAdapter.setControlCallbacks(mControlCallbacks);
145         }
146     };
147 
148     sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks));
149 }
150 
151 void
convertOptions(LocPosMode & out,const TrackingOptions & trackingOptions)152 GnssAdapter::convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions)
153 {
154     switch (trackingOptions.mode) {
155     case GNSS_SUPL_MODE_MSB:
156         out.mode = LOC_POSITION_MODE_MS_BASED;
157         break;
158     case GNSS_SUPL_MODE_MSA:
159         out.mode = LOC_POSITION_MODE_MS_ASSISTED;
160         break;
161     default:
162         out.mode = LOC_POSITION_MODE_STANDALONE;
163         break;
164     }
165     out.share_position = true;
166     out.min_interval = trackingOptions.minInterval;
167     out.powerMode = trackingOptions.powerMode;
168     out.timeBetweenMeasurements = trackingOptions.tbm;
169 }
170 
171 void
convertLocation(Location & out,const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,const LocPosTechMask techMask)172 GnssAdapter::convertLocation(Location& out, const UlpLocation& ulpLocation,
173                              const GpsLocationExtended& locationExtended,
174                              const LocPosTechMask techMask)
175 {
176     memset(&out, 0, sizeof(Location));
177     out.size = sizeof(Location);
178     if (LOC_GPS_LOCATION_HAS_LAT_LONG & ulpLocation.gpsLocation.flags) {
179         out.flags |= LOCATION_HAS_LAT_LONG_BIT;
180         out.latitude = ulpLocation.gpsLocation.latitude;
181         out.longitude = ulpLocation.gpsLocation.longitude;
182     }
183     if (LOC_GPS_LOCATION_HAS_ALTITUDE & ulpLocation.gpsLocation.flags) {
184         out.flags |= LOCATION_HAS_ALTITUDE_BIT;
185         out.altitude = ulpLocation.gpsLocation.altitude;
186     }
187     if (LOC_GPS_LOCATION_HAS_SPEED & ulpLocation.gpsLocation.flags) {
188         out.flags |= LOCATION_HAS_SPEED_BIT;
189         out.speed = ulpLocation.gpsLocation.speed;
190     }
191     if (LOC_GPS_LOCATION_HAS_BEARING & ulpLocation.gpsLocation.flags) {
192         out.flags |= LOCATION_HAS_BEARING_BIT;
193         out.bearing = ulpLocation.gpsLocation.bearing;
194     }
195     if (LOC_GPS_LOCATION_HAS_ACCURACY & ulpLocation.gpsLocation.flags) {
196         out.flags |= LOCATION_HAS_ACCURACY_BIT;
197         out.accuracy = ulpLocation.gpsLocation.accuracy;
198     }
199     if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) {
200         out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
201         out.verticalAccuracy = locationExtended.vert_unc;
202     }
203     if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) {
204         out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
205         out.speedAccuracy = locationExtended.speed_unc;
206     }
207     if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) {
208         out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
209         out.bearingAccuracy = locationExtended.bearing_unc;
210     }
211     out.timestamp = ulpLocation.gpsLocation.timestamp;
212     if (LOC_POS_TECH_MASK_SATELLITE & techMask) {
213         out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
214     }
215     if (LOC_POS_TECH_MASK_CELLID & techMask) {
216         out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
217     }
218     if (LOC_POS_TECH_MASK_WIFI & techMask) {
219         out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
220     }
221     if (LOC_POS_TECH_MASK_SENSORS & techMask) {
222         out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
223     }
224 
225     if (LOC_GPS_LOCATION_HAS_SPOOF_MASK & ulpLocation.gpsLocation.flags) {
226         out.flags |= LOCATION_HAS_SPOOF_MASK;
227         out.spoofMask = ulpLocation.gpsLocation.spoof_mask;
228     }
229 }
230 
231 /* This is utility routine that computes number of SV used
232    in the fix from the svUsedIdsMask.
233  */
234 #define MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION 64
getNumSvUsed(uint64_t svUsedIdsMask,int totalSvCntInThisConstellation)235 uint16_t GnssAdapter::getNumSvUsed(uint64_t svUsedIdsMask,
236                                    int totalSvCntInThisConstellation)
237 {
238     if (totalSvCntInThisConstellation > MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION) {
239         LOC_LOGe ("error: total SV count in this constellation %d exceeded limit of %d",
240                   totalSvCntInThisConstellation, MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION);
241         return 0;
242     }
243 
244     uint16_t numSvUsed = 0;
245     uint64_t mask = 0x1;
246     for (int i = 0; i < totalSvCntInThisConstellation; i++) {
247         if (svUsedIdsMask & mask) {
248             numSvUsed++;
249         }
250         mask <<= 1;
251     }
252 
253     return numSvUsed;
254 }
255 
256 void
convertLocationInfo(GnssLocationInfoNotification & out,const GpsLocationExtended & locationExtended)257 GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out,
258                                  const GpsLocationExtended& locationExtended)
259 {
260     out.size = sizeof(GnssLocationInfoNotification);
261     if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) {
262         out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT;
263         out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel;
264     }
265     if (GPS_LOCATION_EXTENDED_HAS_EXT_DOP & locationExtended.flags) {
266         out.flags |= (GNSS_LOCATION_INFO_DOP_BIT|GNSS_LOCATION_INFO_EXT_DOP_BIT);
267         out.pdop = locationExtended.extDOP.PDOP;
268         out.hdop = locationExtended.extDOP.HDOP;
269         out.vdop = locationExtended.extDOP.VDOP;
270         out.gdop = locationExtended.extDOP.GDOP;
271         out.tdop = locationExtended.extDOP.TDOP;
272     } else if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) {
273         out.flags |= GNSS_LOCATION_INFO_DOP_BIT;
274         out.pdop = locationExtended.pdop;
275         out.hdop = locationExtended.hdop;
276         out.vdop = locationExtended.vdop;
277     }
278     if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) {
279         out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT;
280         out.magneticDeviation = locationExtended.magneticDeviation;
281     }
282     if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) {
283         out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT;
284         switch (locationExtended.horizontal_reliability) {
285             case LOC_RELIABILITY_VERY_LOW:
286                 out.horReliability = LOCATION_RELIABILITY_VERY_LOW;
287                 break;
288             case LOC_RELIABILITY_LOW:
289                 out.horReliability = LOCATION_RELIABILITY_LOW;
290                 break;
291             case LOC_RELIABILITY_MEDIUM:
292                 out.horReliability = LOCATION_RELIABILITY_MEDIUM;
293                 break;
294             case LOC_RELIABILITY_HIGH:
295                 out.horReliability = LOCATION_RELIABILITY_HIGH;
296                 break;
297             default:
298                 out.horReliability = LOCATION_RELIABILITY_NOT_SET;
299                 break;
300         }
301     }
302     if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) {
303         out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT;
304         switch (locationExtended.vertical_reliability) {
305             case LOC_RELIABILITY_VERY_LOW:
306                 out.verReliability = LOCATION_RELIABILITY_VERY_LOW;
307                 break;
308             case LOC_RELIABILITY_LOW:
309                 out.verReliability = LOCATION_RELIABILITY_LOW;
310                 break;
311             case LOC_RELIABILITY_MEDIUM:
312                 out.verReliability = LOCATION_RELIABILITY_MEDIUM;
313                 break;
314             case LOC_RELIABILITY_HIGH:
315                 out.verReliability = LOCATION_RELIABILITY_HIGH;
316                 break;
317             default:
318                 out.verReliability = LOCATION_RELIABILITY_NOT_SET;
319                 break;
320         }
321     }
322     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) {
323         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT;
324         out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor;
325     }
326     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) {
327         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT;
328         out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor;
329     }
330     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) {
331         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT;
332         out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth;
333     }
334     if (GPS_LOCATION_EXTENDED_HAS_NORTH_STD_DEV & locationExtended.flags) {
335         out.flags |= GNSS_LOCATION_INFO_NORTH_STD_DEV_BIT;
336         out.northStdDeviation = locationExtended.northStdDeviation;
337     }
338     if (GPS_LOCATION_EXTENDED_HAS_EAST_STD_DEV & locationExtended.flags) {
339         out.flags |= GNSS_LOCATION_INFO_EAST_STD_DEV_BIT;
340         out.eastStdDeviation = locationExtended.eastStdDeviation;
341     }
342     if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL & locationExtended.flags) {
343         out.flags |= GNSS_LOCATION_INFO_NORTH_VEL_BIT;
344         out.northVelocity = locationExtended.northVelocity;
345     }
346     if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC & locationExtended.flags) {
347         out.flags |= GNSS_LOCATION_INFO_NORTH_VEL_UNC_BIT;
348         out.northVelocityStdDeviation = locationExtended.northVelocityStdDeviation;
349     }
350     if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL & locationExtended.flags) {
351         out.flags |= GNSS_LOCATION_INFO_EAST_VEL_BIT;
352         out.eastVelocity = locationExtended.eastVelocity;
353     }
354     if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC & locationExtended.flags) {
355         out.flags |= GNSS_LOCATION_INFO_EAST_VEL_UNC_BIT;
356         out.eastVelocityStdDeviation = locationExtended.eastVelocityStdDeviation;
357     }
358     if (GPS_LOCATION_EXTENDED_HAS_UP_VEL & locationExtended.flags) {
359         out.flags |= GNSS_LOCATION_INFO_UP_VEL_BIT;
360         out.upVelocity = locationExtended.upVelocity;
361     }
362     if (GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC & locationExtended.flags) {
363         out.flags |= GNSS_LOCATION_INFO_UP_VEL_UNC_BIT;
364         out.upVelocityStdDeviation = locationExtended.upVelocityStdDeviation;
365     }
366     if (GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA & locationExtended.flags) {
367         out.flags |= GNSS_LOCATION_INFO_GNSS_SV_USED_DATA_BIT;
368         out.svUsedInPosition.gpsSvUsedIdsMask =
369                 locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask;
370         out.svUsedInPosition.gloSvUsedIdsMask =
371                 locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask;
372         out.svUsedInPosition.galSvUsedIdsMask =
373                 locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask;
374         out.svUsedInPosition.bdsSvUsedIdsMask =
375                 locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask;
376         out.svUsedInPosition.qzssSvUsedIdsMask =
377                 locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask;
378 
379         out.flags |= GNSS_LOCATION_INFO_NUM_SV_USED_IN_POSITION_BIT;
380         out.numSvUsedInPosition = getNumSvUsed(out.svUsedInPosition.gpsSvUsedIdsMask,
381                                                GPS_SV_PRN_MAX - GPS_SV_PRN_MIN + 1);
382         out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.gloSvUsedIdsMask,
383                                                 GLO_SV_PRN_MAX - GLO_SV_PRN_MIN + 1);
384         out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.qzssSvUsedIdsMask,
385                                                 QZSS_SV_PRN_MAX - QZSS_SV_PRN_MIN + 1);
386         out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.bdsSvUsedIdsMask,
387                                                 BDS_SV_PRN_MAX - BDS_SV_PRN_MIN + 1);
388         out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.galSvUsedIdsMask,
389                                                 GAL_SV_PRN_MAX - GAL_SV_PRN_MIN + 1);
390 
391         out.numOfMeasReceived = locationExtended.numOfMeasReceived;
392         for (int idx =0; idx < locationExtended.numOfMeasReceived; idx++) {
393             out.measUsageInfo[idx].gnssSignalType =
394                     locationExtended.measUsageInfo[idx].gnssSignalType;
395             out.measUsageInfo[idx].gnssSvId =
396                     locationExtended.measUsageInfo[idx].gnssSvId;
397             out.measUsageInfo[idx].gnssConstellation =
398                     locationExtended.measUsageInfo[idx].gnssConstellation;
399         }
400     }
401     if (GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK & locationExtended.flags) {
402         out.flags |= GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT;
403         out.navSolutionMask = locationExtended.navSolutionMask;
404     }
405     if (GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK & locationExtended.flags) {
406         out.flags |= GNSS_LOCATION_INFO_POS_TECH_MASK_BIT;
407         out.posTechMask = locationExtended.tech_mask;
408     }
409     if (GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA & locationExtended.flags) {
410         out.flags |= GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA;
411         if (locationExtended.bodyFrameData.bodyFrameDataMask &
412                 LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT) {
413             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT;
414         }
415         if (locationExtended.bodyFrameData.bodyFrameDataMask &
416                 LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT) {
417             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT;
418         }
419         if (locationExtended.bodyFrameData.bodyFrameDataMask &
420                 LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT) {
421             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT;
422         }
423         if (locationExtended.bodyFrameData.bodyFrameDataMask & LOCATION_NAV_DATA_HAS_YAW_RATE_BIT) {
424             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_RATE_BIT;
425         }
426         if (locationExtended.bodyFrameData.bodyFrameDataMask & LOCATION_NAV_DATA_HAS_PITCH_BIT) {
427             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_BIT;
428         }
429         out.bodyFrameData.longAccel = locationExtended.bodyFrameData.longAccel;
430         out.bodyFrameData.latAccel = locationExtended.bodyFrameData.latAccel;
431         out.bodyFrameData.vertAccel = locationExtended.bodyFrameData.vertAccel;
432         out.bodyFrameData.yawRate = locationExtended.bodyFrameData.yawRate;
433         out.bodyFrameData.pitch = locationExtended.bodyFrameData.pitch;
434     }
435     if (GPS_LOCATION_EXTENDED_HAS_GPS_TIME & locationExtended.flags) {
436         out.flags |= GPS_LOCATION_EXTENDED_HAS_GPS_TIME;
437         out.gnssSystemTime.gnssSystemTimeSrc = locationExtended.gnssSystemTime.gnssSystemTimeSrc;
438         out.gnssSystemTime.u = locationExtended.gnssSystemTime.u;
439     }
440     if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL & locationExtended.flags) {
441         out.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_VEL;
442         out.northVelocity = locationExtended.northVelocity;
443     }
444     if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL & locationExtended.flags) {
445         out.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_VEL;
446         out.eastVelocity = locationExtended.eastVelocity;
447     }
448     if (GPS_LOCATION_EXTENDED_HAS_UP_VEL & locationExtended.flags) {
449         out.flags |= GPS_LOCATION_EXTENDED_HAS_UP_VEL;
450         out.upVelocity = locationExtended.upVelocity;
451     }
452     if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC & locationExtended.flags) {
453         out.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC;
454         out.northVelocityStdDeviation = locationExtended.northVelocityStdDeviation;
455     }
456     if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC & locationExtended.flags) {
457         out.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC;
458         out.eastVelocityStdDeviation = locationExtended.eastVelocityStdDeviation;
459     }
460     if (GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC & locationExtended.flags) {
461         out.flags |= GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC;
462         out.upVelocityStdDeviation = locationExtended.upVelocityStdDeviation;
463     }
464 
465     // Validity of this structure is established from the timeSrc of the GnssSystemTime structure.
466     out.gnssSystemTime = locationExtended.gnssSystemTime;
467 
468     if (GPS_LOCATION_EXTENDED_HAS_LEAP_SECONDS & locationExtended.flags) {
469         out.flags |= GNSS_LOCATION_INFO_LEAP_SECONDS_BIT;
470         out.leapSeconds = locationExtended.leapSeconds;
471     }
472 
473     if (GPS_LOCATION_EXTENDED_HAS_TIME_UNC & locationExtended.flags) {
474         out.flags |= GNSS_LOCATION_INFO_TIME_UNC_BIT;
475         out.timeUncMs = locationExtended.timeUncMs;
476     }
477 
478     if (GPS_LOCATION_EXTENDED_HAS_CALIBRATION_CONFIDENCE & locationExtended.flags) {
479         out.flags |= GNSS_LOCATION_INFO_CALIBRATION_CONFIDENCE_BIT;
480         out.calibrationConfidence = locationExtended.calibrationConfidence;
481     }
482 
483     if (GPS_LOCATION_EXTENDED_HAS_CALIBRATION_STATUS & locationExtended.flags) {
484         out.flags |= GNSS_LOCATION_INFO_CALIBRATION_STATUS_BIT;
485         out.calibrationStatus = locationExtended.calibrationStatus;
486     }
487 
488     if (GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & locationExtended.flags) {
489         out.flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT;
490         out.locOutputEngType = locationExtended.locOutputEngType;
491     }
492 
493     if (GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_MASK & locationExtended.flags) {
494         out.flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT;
495         out.locOutputEngMask = locationExtended.locOutputEngMask;
496     }
497 }
498 
499 
500 
501 inline uint32_t
convertSuplVersion(const GnssConfigSuplVersion suplVersion)502 GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion)
503 {
504     switch (suplVersion) {
505         case GNSS_CONFIG_SUPL_VERSION_2_0_0:
506             return 0x00020000;
507         case GNSS_CONFIG_SUPL_VERSION_2_0_2:
508             return 0x00020002;
509         case GNSS_CONFIG_SUPL_VERSION_1_0_0:
510         default:
511             return 0x00010000;
512     }
513 }
514 
515 inline uint32_t
convertLppProfile(const GnssConfigLppProfile lppProfile)516 GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile)
517 {
518     switch (lppProfile) {
519         case GNSS_CONFIG_LPP_PROFILE_USER_PLANE:
520             return 1;
521         case GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE:
522             return 2;
523         case GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE:
524             return 3;
525         case GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE:
526         default:
527             return 0;
528     }
529 }
530 
531 uint32_t
convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)532 GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)
533 {
534     uint32_t mask = 0;
535     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) {
536         mask |= (1<<0);
537     }
538     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
539         mask |= (1<<1);
540     }
541     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
542         mask |= (1<<2);
543     }
544     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeControlPlaneMask) {
545         mask |= (1<<3);
546     }
547     return mask;
548 }
549 
550 uint32_t
convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)551 GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)
552 {
553     uint32_t mask = 0;
554     if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) {
555         mask |= (1<<0);
556     }
557     if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
558         mask |= (1<<1);
559     }
560     if (GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
561         mask |= (1<<2);
562     }
563     if (GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeUserPlaneMask) {
564         mask |= (1<<3);
565     }
566     return mask;
567 }
568 
569 uint32_t
convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)570 GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)
571 {
572     uint32_t mask = 0;
573     if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
574         mask |= (1<<0);
575     }
576     if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
577         mask |= (1<<1);
578     }
579     if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
580         mask |= (1<<2);
581     }
582     if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
583         mask |= (1<<3);
584     }
585     return mask;
586 }
587 
588 uint32_t
convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)589 GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)
590 {
591     switch (emergencyPdnForEmergencySupl) {
592        case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES:
593            return 1;
594        case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO:
595        default:
596            return 0;
597     }
598 }
599 
600 uint32_t
convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)601 GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)
602 {
603     switch (suplEmergencyServices) {
604        case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES:
605            return 1;
606        case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO:
607        default:
608            return 0;
609     }
610 }
611 
612 uint32_t
convertSuplMode(const GnssConfigSuplModeMask suplModeMask)613 GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask)
614 {
615     uint32_t mask = 0;
616     if (GNSS_CONFIG_SUPL_MODE_MSB_BIT & suplModeMask) {
617         mask |= (1<<0);
618     }
619     if (GNSS_CONFIG_SUPL_MODE_MSA_BIT & suplModeMask) {
620         mask |= (1<<1);
621     }
622     return mask;
623 }
624 
625 void
readConfigCommand()626 GnssAdapter::readConfigCommand()
627 {
628     LOC_LOGD("%s]: ", __func__);
629 
630     struct MsgReadConfig : public LocMsg {
631         GnssAdapter* mAdapter;
632         ContextBase& mContext;
633         inline MsgReadConfig(GnssAdapter* adapter,
634                              ContextBase& context) :
635             LocMsg(),
636             mAdapter(adapter),
637             mContext(context) {}
638         inline virtual void proc() const {
639             static bool confReadDone = false;
640             if (!confReadDone) {
641                 confReadDone = true;
642                 // reads config into mContext->mGps_conf
643                 mContext.readConfig();
644 
645                 uint32_t allowFlpNetworkFixes = 0;
646                 static const loc_param_s_type flp_conf_param_table[] =
647                 {
648                     {"ALLOW_NETWORK_FIXES", &allowFlpNetworkFixes, NULL, 'n'},
649                 };
650                 UTIL_READ_CONF(LOC_PATH_FLP_CONF, flp_conf_param_table);
651                 LOC_LOGd("allowFlpNetworkFixes %u", allowFlpNetworkFixes);
652                 mAdapter->setAllowFlpNetworkFixes(allowFlpNetworkFixes);
653             }
654         }
655     };
656 
657     if (mContext != NULL) {
658         sendMsg(new MsgReadConfig(this, *mContext));
659     }
660 }
661 
662 void
setSuplHostServer(const char * server,int port,LocServerType type)663 GnssAdapter::setSuplHostServer(const char* server, int port, LocServerType type)
664 {
665     if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
666         char serverUrl[MAX_URL_LEN] = {};
667         int32_t length = -1;
668         const char noHost[] = "NONE";
669 
670         if ((NULL == server) || (server[0] == 0) ||
671                 (strncasecmp(noHost, server, sizeof(noHost)) == 0)) {
672             serverUrl[0] = '\0';
673             length = 0;
674         } else if (port > 0) {
675             length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u", server, port);
676         }
677         if (LOC_AGPS_SUPL_SERVER != type && LOC_AGPS_MO_SUPL_SERVER != type) {
678             LOC_LOGe("Invalid type=%d", type);
679         } else if (length >= 0) {
680             if (LOC_AGPS_SUPL_SERVER == type) {
681                 getServerUrl().assign(serverUrl);
682                 strlcpy(ContextBase::mGps_conf.SUPL_HOST, server, LOC_MAX_PARAM_STRING);
683                 ContextBase::mGps_conf.SUPL_PORT = port;
684             } else {
685                 if (strncasecmp(getMoServerUrl().c_str(), serverUrl, sizeof(serverUrl)) != 0) {
686                     getMoServerUrl().assign(serverUrl);
687                 }
688             }
689         }
690     }
691 }
692 
693 void
setConfig()694 GnssAdapter::setConfig()
695 {
696     LOC_LOGD("%s]: ", __func__);
697 
698     // set nmea mask type
699     uint32_t mask = 0;
700     if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
701         mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
702     }
703     if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
704         mask |= LOC_NMEA_MASK_DEBUG_V02;
705     }
706     if (mNmeaMask != mask) {
707         mNmeaMask = mask;
708         if (mNmeaMask) {
709             for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
710                 if ((it->second.gnssNmeaCb != nullptr)) {
711                     updateEvtMask(LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT,
712                                   LOC_REGISTRATION_MASK_ENABLED);
713                     break;
714                 }
715             }
716         }
717     }
718 
719     std::string oldMoServerUrl = getMoServerUrl();
720     setSuplHostServer(ContextBase::mGps_conf.SUPL_HOST,
721                       ContextBase::mGps_conf.SUPL_PORT,
722                       LOC_AGPS_SUPL_SERVER);
723     setSuplHostServer(ContextBase::mGps_conf.MO_SUPL_HOST,
724                       ContextBase::mGps_conf.MO_SUPL_PORT,
725                       LOC_AGPS_MO_SUPL_SERVER);
726 
727     // inject the configurations into modem
728     loc_gps_cfg_s gpsConf = ContextBase::mGps_conf;
729     loc_sap_cfg_s_type sapConf = ContextBase::mSap_conf;
730 
731     //cache the injected configuration with GnssConfigRequested struct
732     GnssConfig gnssConfigRequested = {};
733     gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT |
734             GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
735     /* Here we process an SSR. We need to set the GPS_LOCK to the proper values, as follows:
736     1. Q behavior. This is identified by mSupportNfwControl being 1. In this case
737     ContextBase::mGps_conf.GPS_LOCK is a "state", meaning it should reflect the
738     NV value. Therefore we will set the NV to ContextBase::mGps_conf.GPS_LOCK
739     2. P behavior. This is identified by mSupportNfwControl being 0. In this case
740     ContextBase::mGps_conf.GPS_LOCK is a "configuration", meaning it should hold
741     the "mask" for NI. There are two subcases:
742     a. Location enabled in GUI (1 == getAfwControlId()). We need to set
743     the NV to GNSS_CONFIG_GPS_LOCK_NONE (both MO and NI enabled)
744     b. Location disabled in GUI (0 == getAfwControlId()). We need to set
745     the NV to ContextBase::mGps_conf.GPS_LOCK (the "mask", which is SIM-card
746     specific)
747     */
748     if (mSupportNfwControl || (0 == getAfwControlId())) {
749         gnssConfigRequested.gpsLock = gpsConf.GPS_LOCK;
750     } else {
751         gnssConfigRequested.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
752     }
753 
754     if (gpsConf.AGPS_CONFIG_INJECT) {
755         gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT |
756                 GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT |
757                 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT |
758                 GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
759         gnssConfigRequested.suplVersion =
760                 mLocApi->convertSuplVersion(gpsConf.SUPL_VER);
761         gnssConfigRequested.lppProfile =
762                 mLocApi->convertLppProfile(gpsConf.LPP_PROFILE);
763         gnssConfigRequested.aGlonassPositionProtocolMask =
764                 gpsConf.A_GLONASS_POS_PROTOCOL_SELECT;
765     }
766     if (gpsConf.LPPE_CP_TECHNOLOGY) {
767         gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
768         gnssConfigRequested.lppeControlPlaneMask =
769                 mLocApi->convertLppeCp(gpsConf.LPPE_CP_TECHNOLOGY);
770     }
771 
772     if (gpsConf.LPPE_UP_TECHNOLOGY) {
773         gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
774         gnssConfigRequested.lppeUserPlaneMask =
775                 mLocApi->convertLppeUp(gpsConf.LPPE_UP_TECHNOLOGY);
776     }
777     gnssConfigRequested.blacklistedSvIds.assign(mBlacklistedSvIds.begin(),
778                                                 mBlacklistedSvIds.end());
779     mLocApi->sendMsg(new LocApiMsg(
780             [this, gpsConf, sapConf, oldMoServerUrl, gnssConfigRequested] () {
781         gnssUpdateConfig(oldMoServerUrl, gnssConfigRequested, gnssConfigRequested);
782 
783         // set nmea mask type
784         uint32_t mask = 0;
785         if (NMEA_PROVIDER_MP == gpsConf.NMEA_PROVIDER) {
786             mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
787         }
788         if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
789             mask |= LOC_NMEA_MASK_DEBUG_V02;
790         }
791 
792         if (mask != 0) {
793             mLocApi->setNMEATypesSync(mask);
794         }
795 
796         mLocApi->setXtraVersionCheckSync(gpsConf.XTRA_VERSION_CHECK);
797 
798         mLocApi->setConstrainedTuncMode(
799                 gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED == 1,
800                 (float)gpsConf.CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD,
801                 gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET);
802         mLocApi->setPositionAssistedClockEstimatorMode(
803                 gpsConf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED == 1);
804 
805         if (sapConf.GYRO_BIAS_RANDOM_WALK_VALID ||
806             sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
807             sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
808             sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
809             sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) {
810             mLocApi->setSensorPropertiesSync(
811                 sapConf.GYRO_BIAS_RANDOM_WALK_VALID,
812                 sapConf.GYRO_BIAS_RANDOM_WALK,
813                 sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
814                 sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY,
815                 sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
816                 sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY,
817                 sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
818                 sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY,
819                 sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
820                 sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY);
821         }
822         mLocApi->setSensorPerfControlConfigSync(
823                 sapConf.SENSOR_CONTROL_MODE,
824                 sapConf.SENSOR_ACCEL_SAMPLES_PER_BATCH,
825                 sapConf.SENSOR_ACCEL_BATCHES_PER_SEC,
826                 sapConf.SENSOR_GYRO_SAMPLES_PER_BATCH,
827                 sapConf.SENSOR_GYRO_BATCHES_PER_SEC,
828                 sapConf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH,
829                 sapConf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH,
830                 sapConf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH,
831                 sapConf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
832                 sapConf.SENSOR_ALGORITHM_CONFIG_MASK);
833     } ));
834 
835 }
836 
gnssUpdateConfig(const std::string & oldMoServerUrl,const GnssConfig & gnssConfigRequested,const GnssConfig & gnssConfigNeedEngineUpdate,size_t count)837 std::vector<LocationError> GnssAdapter::gnssUpdateConfig(const std::string& oldMoServerUrl,
838         const GnssConfig& gnssConfigRequested,
839         const GnssConfig& gnssConfigNeedEngineUpdate, size_t count) {
840     loc_gps_cfg_s gpsConf = ContextBase::mGps_conf;
841     size_t index = 0;
842     LocationError err = LOCATION_ERROR_SUCCESS;
843     std::vector<LocationError> errsList = {err};
844     if (count > 0) {
845         errsList.insert(errsList.begin(), count, LOCATION_ERROR_SUCCESS);
846     }
847 
848 
849     std::string serverUrl = getServerUrl();
850     std::string moServerUrl = getMoServerUrl();
851 
852     int serverUrlLen = serverUrl.length();
853     int moServerUrlLen = moServerUrl.length();
854 
855     if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
856         if (gnssConfigNeedEngineUpdate.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
857             err = mLocApi->setGpsLockSync(gnssConfigRequested.gpsLock);
858             if (index < count) {
859                 errsList[index] = err;
860             }
861         }
862         index++;
863     }
864 
865     if (gnssConfigRequested.flags &
866             GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
867         if (gnssConfigNeedEngineUpdate.flags &
868                 GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
869             if (gnssConfigNeedEngineUpdate.assistanceServer.type ==
870                     GNSS_ASSISTANCE_TYPE_SUPL) {
871                 err = mLocApi->setServerSync(
872                         serverUrl.c_str(), serverUrlLen, LOC_AGPS_SUPL_SERVER);
873                 if (index < count) {
874                     errsList[index] = err;
875                 }
876                 if (0 != oldMoServerUrl.compare(moServerUrl)) {
877                     LocationError locErr =
878                         mLocApi->setServerSync(moServerUrl.c_str(),
879                                 moServerUrlLen,
880                                 LOC_AGPS_MO_SUPL_SERVER);
881                     if (locErr != LOCATION_ERROR_SUCCESS) {
882                         LOC_LOGe("Error while setting MO SUPL_HOST server:%s",
883                                 moServerUrl.c_str());
884                     }
885                 }
886             } else if (gnssConfigNeedEngineUpdate.assistanceServer.type ==
887                     GNSS_ASSISTANCE_TYPE_C2K) {
888                 struct in_addr addr;
889                 struct hostent* hp;
890                 bool resolveAddrSuccess = true;
891 
892                 hp = gethostbyname(
893                         gnssConfigNeedEngineUpdate.assistanceServer.hostName);
894                 if (hp != NULL) { /* DNS OK */
895                     memcpy(&addr, hp->h_addr_list[0], hp->h_length);
896                 } else {
897                     /* Try IP representation */
898                     if (inet_aton(
899                                 gnssConfigNeedEngineUpdate.assistanceServer.hostName,
900                                 &addr) == 0) {
901                         /* IP not valid */
902                         LOC_LOGE("%s]: hostname '%s' cannot be resolved ",
903                                 __func__,
904                                 gnssConfigNeedEngineUpdate.assistanceServer.hostName);
905                         if (index < count) {
906                             errsList[index] = LOCATION_ERROR_INVALID_PARAMETER;
907                         }
908                     } else {
909                         resolveAddrSuccess = false;
910                     }
911                 }
912 
913                 if (resolveAddrSuccess) {
914                     unsigned int ip = htonl(addr.s_addr);
915                     err = mLocApi->setServerSync(ip,
916                             gnssConfigNeedEngineUpdate.assistanceServer.port,
917                             LOC_AGPS_CDMA_PDE_SERVER);
918                     if (index < count) {
919                         errsList[index] = err;
920                     }
921                 }
922             }
923         }
924         index++;
925     }
926 
927     if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
928         if (gnssConfigNeedEngineUpdate.flags &
929                 GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
930             err = mLocApi->setSUPLVersionSync(gnssConfigRequested.suplVersion);
931             if (index < count) {
932                 errsList[index] = err;
933             }
934         }
935         index++;
936     }
937 
938     if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
939         if (gnssConfigNeedEngineUpdate.flags &
940                 GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
941             err = mLocApi->setLPPConfigSync(gnssConfigRequested.lppProfile);
942             if (index < count) {
943                 errsList[index] = err;
944             }
945         }
946         index++;
947     }
948 
949     /* Comment out LPPe injection as it's configured by MBN.
950     if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
951         if (gnssConfigNeedEngineUpdate.flags &
952                 GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
953             err = mLocApi->setLPPeProtocolCpSync(
954                     gnssConfigRequested.lppeControlPlaneMask);
955             if (index < count) {
956                 errsList[index] = err;
957             }
958         }
959         index++;
960     }
961 
962     if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
963         if (gnssConfigNeedEngineUpdate.flags &
964                 GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
965             err = mLocApi->setLPPeProtocolUpSync(
966                     gnssConfigRequested.lppeUserPlaneMask);
967             if (index < count) {
968                 errsList[index] = err;
969             }
970         }
971         index++;
972     }
973     */
974     if (gnssConfigRequested.flags &
975             GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
976         if (gnssConfigNeedEngineUpdate.flags &
977                 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
978             err = mLocApi->setAGLONASSProtocolSync(
979                     gnssConfigRequested.aGlonassPositionProtocolMask);
980             if (index < count) {
981                 errsList[index] = err;
982             }
983         }
984         index++;
985     }
986     if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
987         // Check if feature is supported
988         if (!ContextBase::isFeatureSupported(
989                     LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
990             LOC_LOGe("Feature constellation enablement not supported.");
991             err = LOCATION_ERROR_NOT_SUPPORTED;
992         } else {
993             // Send the SV ID Config to Modem
994             mBlacklistedSvIds.assign(gnssConfigRequested.blacklistedSvIds.begin(),
995                     gnssConfigRequested.blacklistedSvIds.end());
996             err = gnssSvIdConfigUpdateSync(gnssConfigRequested.blacklistedSvIds);
997             if (LOCATION_ERROR_SUCCESS != err) {
998                 LOC_LOGe("Failed to send config to modem, err %d", err);
999             }
1000         }
1001         if (index < count) {
1002             errsList[index] = err;
1003         }
1004         index++;
1005     }
1006     if (gnssConfigRequested.flags &
1007             GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1008         if (gnssConfigNeedEngineUpdate.flags &
1009                 GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1010             err = mLocApi->setEmergencyExtensionWindowSync(
1011                     gnssConfigRequested.emergencyExtensionSeconds);
1012             if (index < count) {
1013                 errsList[index] = err;
1014             }
1015         }
1016         index++;
1017     }
1018     return errsList;
1019 }
1020 
1021 uint32_t*
gnssUpdateConfigCommand(GnssConfig config)1022 GnssAdapter::gnssUpdateConfigCommand(GnssConfig config)
1023 {
1024     // count the number of bits set
1025     GnssConfigFlagsMask flagsCopy = config.flags;
1026     size_t count = 0;
1027     while (flagsCopy > 0) {
1028         if (flagsCopy & 1) {
1029             count++;
1030         }
1031         flagsCopy >>= 1;
1032     }
1033     std::string idsString = "[";
1034     uint32_t* ids = NULL;
1035     if (count > 0) {
1036         ids = new uint32_t[count];
1037         if (ids == nullptr) {
1038             LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
1039             return nullptr;
1040         }
1041         for (size_t i=0; i < count; ++i) {
1042             ids[i] = generateSessionId();
1043             IF_LOC_LOGD {
1044                 idsString += std::to_string(ids[i]) + " ";
1045             }
1046         }
1047     }
1048     idsString += "]";
1049 
1050     LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags);
1051 
1052     struct MsgGnssUpdateConfig : public LocMsg {
1053         GnssAdapter& mAdapter;
1054         LocApiBase& mApi;
1055         GnssConfig mConfig;
1056         size_t mCount;
1057         uint32_t* mIds;
1058         inline MsgGnssUpdateConfig(GnssAdapter& adapter,
1059                                    LocApiBase& api,
1060                                    GnssConfig config,
1061                                    uint32_t* ids,
1062                                    size_t count) :
1063             LocMsg(),
1064             mAdapter(adapter),
1065             mApi(api),
1066             mConfig(config),
1067             mCount(count),
1068             mIds(ids) {}
1069         inline MsgGnssUpdateConfig(const MsgGnssUpdateConfig& obj) :
1070                 MsgGnssUpdateConfig(obj.mAdapter, obj.mApi, obj.mConfig,
1071                         new uint32_t[obj.mCount], obj.mCount) {
1072             if (mIds != nullptr) {
1073                 for (int i = 0; i < mCount; ++i) {
1074                     mIds[i] = obj.mIds[i];
1075                 }
1076             }
1077         }
1078         inline virtual ~MsgGnssUpdateConfig()
1079         {
1080             delete[] mIds;
1081         }
1082 
1083         inline virtual void proc() const {
1084             if (!mAdapter.isEngineCapabilitiesKnown()) {
1085                 mAdapter.mPendingMsgs.push_back(new MsgGnssUpdateConfig(*this));
1086                 return;
1087             }
1088             GnssAdapter& adapter = mAdapter;
1089             size_t countOfConfigs = mCount;
1090             GnssConfig gnssConfigRequested = mConfig;
1091             GnssConfig gnssConfigNeedEngineUpdate = mConfig;
1092 
1093             std::vector<uint32_t> sessionIds;
1094             sessionIds.assign(mIds, mIds + mCount);
1095             std::vector<LocationError> errs(mCount, LOCATION_ERROR_SUCCESS);
1096             int index = 0;
1097 
1098             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1099                 GnssConfigGpsLock newGpsLock = gnssConfigRequested.gpsLock;
1100 
1101                 newGpsLock |= GNSS_CONFIG_GPS_LOCK_MO;
1102                 ContextBase::mGps_conf.GPS_LOCK = newGpsLock;
1103                 /* If we get here it means that the changes in the framework to request for
1104                    'P' behavior were made, and therefore we need to "behave" as in 'P'
1105                 However, we need to determine if enableCommand function has already been
1106                 called, since it could get called before this function.*/
1107                 if (0 != mAdapter.getAfwControlId()) {
1108                     /* enableCommand function has already been called since getAfwControlId
1109                     returns non zero. Now there are two possible cases:
1110                     1. This is the first time this function is called
1111                        (mSupportNfwControl is true). We need to behave as in 'P', but
1112                        for the first time, meaning MO was enabled, but NI was not, so
1113                        we need to unlock NI
1114                     2. This is not the first time this function is called, meaning we
1115                        are already behaving as in 'P'. No need to update the configuration
1116                        in this case (return to 'P' code) */
1117                     if (mAdapter.mSupportNfwControl) {
1118                         // case 1 above
1119                         newGpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
1120                     } else {
1121                         // case 2 above
1122                         gnssConfigNeedEngineUpdate.flags &= ~(GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT);
1123                     }
1124                 }
1125                 gnssConfigRequested.gpsLock = newGpsLock;
1126                 mAdapter.mSupportNfwControl = false;
1127                 index++;
1128             }
1129             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1130                 uint32_t newSuplVersion =
1131                         mAdapter.convertSuplVersion(gnssConfigRequested.suplVersion);
1132                 ContextBase::mGps_conf.SUPL_VER = newSuplVersion;
1133                 index++;
1134             }
1135             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1136                 if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) {
1137                     mAdapter.setSuplHostServer(mConfig.assistanceServer.hostName,
1138                                                      mConfig.assistanceServer.port,
1139                                                      LOC_AGPS_SUPL_SERVER);
1140                 } else {
1141                     LOC_LOGE("%s]: Not a valid gnss assistance type %u",
1142                             __func__, mConfig.assistanceServer.type);
1143                     errs.at(index) = LOCATION_ERROR_INVALID_PARAMETER;
1144                     gnssConfigNeedEngineUpdate.flags &=
1145                             ~(GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT);
1146                 }
1147                 index++;
1148             }
1149             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1150                 uint32_t newLppProfile = mAdapter.convertLppProfile(gnssConfigRequested.lppProfile);
1151                 ContextBase::mGps_conf.LPP_PROFILE = newLppProfile;
1152                 index++;
1153             }
1154             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1155                 uint32_t newLppeControlPlaneMask =
1156                         mAdapter.convertLppeCp(gnssConfigRequested.lppeControlPlaneMask);
1157                 ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask;
1158                 index++;
1159             }
1160             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1161                 uint32_t newLppeUserPlaneMask =
1162                         mAdapter.convertLppeUp(gnssConfigRequested.lppeUserPlaneMask);
1163                 ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask;
1164                 index++;
1165             }
1166             if (gnssConfigRequested.flags &
1167                     GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1168                 uint32_t newAGloProtMask =
1169                         mAdapter.convertAGloProt(gnssConfigRequested.aGlonassPositionProtocolMask);
1170                 ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask;
1171                 index++;
1172             }
1173             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
1174                 uint32_t newEP4ES = mAdapter.convertEP4ES(
1175                         gnssConfigRequested.emergencyPdnForEmergencySupl);
1176                 if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
1177                     ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES;
1178                 }
1179                 index++;
1180             }
1181             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
1182                 uint32_t newSuplEs = mAdapter.convertSuplEs(
1183                         gnssConfigRequested.suplEmergencyServices);
1184                 if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) {
1185                     ContextBase::mGps_conf.SUPL_ES = newSuplEs;
1186                 }
1187                 index++;
1188             }
1189             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
1190                 uint32_t newSuplMode = mAdapter.convertSuplMode(gnssConfigRequested.suplModeMask);
1191                 ContextBase::mGps_conf.SUPL_MODE = newSuplMode;
1192                 mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
1193                 index++;
1194             }
1195 
1196             LocApiCollectiveResponse *configCollectiveResponse = new LocApiCollectiveResponse(
1197                     *adapter.getContext(),
1198                     [&adapter, sessionIds, countOfConfigs] (std::vector<LocationError> errs) {
1199 
1200                     std::vector<uint32_t> ids(sessionIds);
1201                     adapter.reportResponse(countOfConfigs, errs.data(), ids.data());
1202             });
1203 
1204             mApi.sendMsg(new LocApiMsg(
1205                     [&adapter, gnssConfigRequested, gnssConfigNeedEngineUpdate,
1206                     countOfConfigs, configCollectiveResponse, errs] () {
1207                 std::vector<LocationError> errsList = adapter.gnssUpdateConfig("",
1208                         gnssConfigRequested, gnssConfigNeedEngineUpdate, countOfConfigs);
1209 
1210                 configCollectiveResponse->returnToSender(errsList);
1211             }));
1212         }
1213     };
1214 
1215     if (NULL != ids) {
1216         sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count));
1217     } else {
1218         LOC_LOGE("%s]: No GNSS config items to update", __func__);
1219     }
1220 
1221     return ids;
1222 }
1223 
1224 void
gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource> & blacklistedSvIds)1225 GnssAdapter::gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource>& blacklistedSvIds)
1226 {
1227     // Clear the existing config
1228     memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
1229 
1230     // Convert the sv id lists to masks
1231     bool convertSuccess = convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig);
1232 
1233     // Now send to Modem if conversion successful
1234     if (convertSuccess) {
1235         gnssSvIdConfigUpdate();
1236     } else {
1237         LOC_LOGe("convertToGnssSvIdConfig failed");
1238     }
1239 }
1240 
1241 void
gnssSvIdConfigUpdate()1242 GnssAdapter::gnssSvIdConfigUpdate()
1243 {
1244     LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1245             ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64,
1246             mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
1247             mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask);
1248 
1249     // Now set required blacklisted SVs
1250     mLocApi->setBlacklistSv(mGnssSvIdConfig);
1251 }
1252 
1253 LocationError
gnssSvIdConfigUpdateSync(const std::vector<GnssSvIdSource> & blacklistedSvIds)1254 GnssAdapter::gnssSvIdConfigUpdateSync(const std::vector<GnssSvIdSource>& blacklistedSvIds)
1255 {
1256     // Clear the existing config
1257     memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
1258 
1259     // Convert the sv id lists to masks
1260     convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig);
1261 
1262     // Now send to Modem
1263     return gnssSvIdConfigUpdateSync();
1264 }
1265 
1266 LocationError
gnssSvIdConfigUpdateSync()1267 GnssAdapter::gnssSvIdConfigUpdateSync()
1268 {
1269     LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1270             ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64,
1271             mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
1272             mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask);
1273 
1274     // Now set required blacklisted SVs
1275     return mLocApi->setBlacklistSvSync(mGnssSvIdConfig);
1276 }
1277 
1278 uint32_t*
gnssGetConfigCommand(GnssConfigFlagsMask configMask)1279 GnssAdapter::gnssGetConfigCommand(GnssConfigFlagsMask configMask) {
1280 
1281     // count the number of bits set
1282     GnssConfigFlagsMask flagsCopy = configMask;
1283     size_t count = 0;
1284     while (flagsCopy > 0) {
1285         if (flagsCopy & 1) {
1286             count++;
1287         }
1288         flagsCopy >>= 1;
1289     }
1290     std::string idsString = "[";
1291     uint32_t* ids = NULL;
1292     if (count > 0) {
1293         ids = new uint32_t[count];
1294         if (nullptr == ids) {
1295             LOC_LOGe("new allocation failed, fatal error.");
1296             return nullptr;
1297         }
1298         for (size_t i=0; i < count; ++i) {
1299             ids[i] = generateSessionId();
1300             IF_LOC_LOGD {
1301                 idsString += std::to_string(ids[i]) + " ";
1302             }
1303         }
1304     }
1305     idsString += "]";
1306 
1307     LOC_LOGd("ids %s flags 0x%X", idsString.c_str(), configMask);
1308 
1309     struct MsgGnssGetConfig : public LocMsg {
1310         GnssAdapter& mAdapter;
1311         LocApiBase& mApi;
1312         GnssConfigFlagsMask mConfigMask;
1313         uint32_t* mIds;
1314         size_t mCount;
1315         inline MsgGnssGetConfig(GnssAdapter& adapter,
1316                                 LocApiBase& api,
1317                                 GnssConfigFlagsMask configMask,
1318                                 uint32_t* ids,
1319                                 size_t count) :
1320             LocMsg(),
1321             mAdapter(adapter),
1322             mApi(api),
1323             mConfigMask(configMask),
1324             mIds(ids),
1325             mCount(count) {}
1326 
1327         inline MsgGnssGetConfig(const MsgGnssGetConfig& obj) :
1328                 MsgGnssGetConfig(obj.mAdapter, obj.mApi, obj.mConfigMask,
1329                         new uint32_t[obj.mCount], obj.mCount) {
1330             if (mIds != nullptr) {
1331                 for (int i = 0; i < mCount; ++i) {
1332                     mIds[i] = obj.mIds[i];
1333                 }
1334             }
1335         }
1336         inline virtual ~MsgGnssGetConfig()
1337         {
1338             delete[] mIds;
1339         }
1340         inline virtual void proc() const {
1341             if (!mAdapter.isEngineCapabilitiesKnown()) {
1342                 mAdapter.mPendingMsgs.push_back(new MsgGnssGetConfig(*this));
1343                 return;
1344             }
1345             LocationError* errs = new LocationError[mCount];
1346             LocationError err = LOCATION_ERROR_SUCCESS;
1347             uint32_t index = 0;
1348 
1349             if (nullptr == errs) {
1350                 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
1351                 return;
1352             }
1353 
1354             if (mConfigMask & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1355                 if (index < mCount) {
1356                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1357                 }
1358             }
1359             if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1360                 if (index < mCount) {
1361                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1362                 }
1363             }
1364             if (mConfigMask & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1365                 if (index < mCount) {
1366                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1367                 }
1368             }
1369             if (mConfigMask & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1370                 if (index < mCount) {
1371                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1372                 }
1373             }
1374             if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1375                 if (index < mCount) {
1376                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1377                 }
1378             }
1379             if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1380                 if (index < mCount) {
1381                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1382                 }
1383             }
1384             if (mConfigMask & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1385                 if (index < mCount) {
1386                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1387                 }
1388             }
1389             if (mConfigMask & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
1390                 if (index < mCount) {
1391                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1392                 }
1393             }
1394             if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
1395                 if (index < mCount) {
1396                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1397                 }
1398             }
1399             if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
1400                 err = LOCATION_ERROR_NOT_SUPPORTED;
1401                 if (index < mCount) {
1402                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1403                 }
1404             }
1405             if (mConfigMask & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
1406                 // Check if feature is supported
1407                 if (!ContextBase::isFeatureSupported(
1408                         LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1409                     LOC_LOGe("Feature not supported.");
1410                     err = LOCATION_ERROR_NOT_SUPPORTED;
1411                 } else {
1412                     // Send request to Modem to fetch the config
1413                     mApi.getBlacklistSv();
1414                     err = LOCATION_ERROR_SUCCESS;
1415                 }
1416                 if (index < mCount) {
1417                     errs[index++] = err;
1418                 }
1419             }
1420             if (mConfigMask & GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1421                 err = LOCATION_ERROR_NOT_SUPPORTED;
1422                 if (index < mCount) {
1423                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1424                 }
1425             }
1426 
1427             mAdapter.reportResponse(index, errs, mIds);
1428             delete[] errs;
1429 
1430         }
1431     };
1432 
1433     if (NULL != ids) {
1434         sendMsg(new MsgGnssGetConfig(*this, *mLocApi, configMask, ids, count));
1435     } else {
1436         LOC_LOGe("No GNSS config items to Get");
1437     }
1438 
1439     return ids;
1440 }
1441 
1442 bool
convertToGnssSvIdConfig(const std::vector<GnssSvIdSource> & blacklistedSvIds,GnssSvIdConfig & config)1443 GnssAdapter::convertToGnssSvIdConfig(
1444         const std::vector<GnssSvIdSource>& blacklistedSvIds, GnssSvIdConfig& config)
1445 {
1446     bool retVal = false;
1447     config.size = sizeof(GnssSvIdConfig);
1448 
1449     // Empty vector => Clear any previous blacklisted SVs
1450     if (0 == blacklistedSvIds.size()) {
1451         config.gloBlacklistSvMask = 0;
1452         config.bdsBlacklistSvMask = 0;
1453         config.qzssBlacklistSvMask = 0;
1454         config.galBlacklistSvMask = 0;
1455         retVal = true;
1456     } else {
1457         // Parse the vector and convert SV IDs to mask values
1458         for (GnssSvIdSource source : blacklistedSvIds) {
1459             uint64_t* svMaskPtr = NULL;
1460             GnssSvId initialSvId = 0;
1461             switch(source.constellation) {
1462             case GNSS_SV_TYPE_GLONASS:
1463                 svMaskPtr = &config.gloBlacklistSvMask;
1464                 initialSvId = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID;
1465                 break;
1466             case GNSS_SV_TYPE_BEIDOU:
1467                 svMaskPtr = &config.bdsBlacklistSvMask;
1468                 initialSvId = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID;
1469                 break;
1470             case GNSS_SV_TYPE_QZSS:
1471                 svMaskPtr = &config.qzssBlacklistSvMask;
1472                 initialSvId = GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID;
1473                 break;
1474             case GNSS_SV_TYPE_GALILEO:
1475                 svMaskPtr = &config.galBlacklistSvMask;
1476                 initialSvId = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID;
1477                 break;
1478             default:
1479                 break;
1480             }
1481 
1482             if (NULL == svMaskPtr) {
1483                 LOC_LOGe("Invalid constellation %d", source.constellation);
1484             } else {
1485                 // SV ID 0 = All SV IDs
1486                 if (0 == source.svId) {
1487                     *svMaskPtr = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1488                 } else if (source.svId < initialSvId || source.svId >= initialSvId + 64) {
1489                     LOC_LOGe("Invalid sv id %d for sv type %d",
1490                             source.svId, source.constellation);
1491                 } else {
1492                     *svMaskPtr |= (1 << (source.svId - initialSvId));
1493                 }
1494             }
1495         }
1496 
1497         // Return true if any one source is valid
1498         if (0 != config.gloBlacklistSvMask ||
1499                 0 != config.bdsBlacklistSvMask ||
1500                 0 != config.galBlacklistSvMask ||
1501                 0 != config.qzssBlacklistSvMask) {
1502             retVal = true;
1503         }
1504     }
1505 
1506     return retVal;
1507 }
1508 
convertFromGnssSvIdConfig(const GnssSvIdConfig & svConfig,GnssConfig & config)1509 void GnssAdapter::convertFromGnssSvIdConfig(
1510         const GnssSvIdConfig& svConfig, GnssConfig& config)
1511 {
1512     // Convert blacklisted SV mask values to vectors
1513     if (svConfig.bdsBlacklistSvMask) {
1514         convertGnssSvIdMaskToList(
1515                 svConfig.bdsBlacklistSvMask, config.blacklistedSvIds,
1516                 GNSS_SV_CONFIG_BDS_INITIAL_SV_ID, GNSS_SV_TYPE_BEIDOU);
1517         config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1518     }
1519     if (svConfig.galBlacklistSvMask) {
1520         convertGnssSvIdMaskToList(
1521                 svConfig.galBlacklistSvMask, config.blacklistedSvIds,
1522                 GNSS_SV_CONFIG_GAL_INITIAL_SV_ID, GNSS_SV_TYPE_GALILEO);
1523         config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1524     }
1525     if (svConfig.gloBlacklistSvMask) {
1526         convertGnssSvIdMaskToList(
1527                 svConfig.gloBlacklistSvMask, config.blacklistedSvIds,
1528                 GNSS_SV_CONFIG_GLO_INITIAL_SV_ID, GNSS_SV_TYPE_GLONASS);
1529         config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1530     }
1531     if (svConfig.qzssBlacklistSvMask) {
1532         convertGnssSvIdMaskToList(
1533                 svConfig.qzssBlacklistSvMask, config.blacklistedSvIds,
1534                 GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID, GNSS_SV_TYPE_QZSS);
1535         config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1536     }
1537 }
1538 
convertGnssSvIdMaskToList(uint64_t svIdMask,std::vector<GnssSvIdSource> & svIds,GnssSvId initialSvId,GnssSvType svType)1539 void GnssAdapter::convertGnssSvIdMaskToList(
1540         uint64_t svIdMask, std::vector<GnssSvIdSource>& svIds,
1541         GnssSvId initialSvId, GnssSvType svType)
1542 {
1543     GnssSvIdSource source = {};
1544     source.size = sizeof(GnssSvIdSource);
1545     source.constellation = svType;
1546 
1547     // SV ID 0 => All SV IDs in mask
1548     if (GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK == svIdMask) {
1549         source.svId = 0;
1550         svIds.push_back(source);
1551         return;
1552     }
1553 
1554     // Convert each bit in svIdMask to vector entry
1555     uint32_t bitNumber = 0;
1556     while (svIdMask > 0) {
1557         if (svIdMask & 0x1) {
1558             source.svId = bitNumber + initialSvId;
1559             svIds.push_back(source);
1560         }
1561         bitNumber++;
1562         svIdMask >>= 1;
1563     }
1564 }
1565 
reportGnssSvIdConfigEvent(const GnssSvIdConfig & config)1566 void GnssAdapter::reportGnssSvIdConfigEvent(const GnssSvIdConfig& config)
1567 {
1568     struct MsgReportGnssSvIdConfig : public LocMsg {
1569         GnssAdapter& mAdapter;
1570         const GnssSvIdConfig mConfig;
1571         inline MsgReportGnssSvIdConfig(GnssAdapter& adapter,
1572                                  const GnssSvIdConfig& config) :
1573             LocMsg(),
1574             mAdapter(adapter),
1575             mConfig(config) {}
1576         inline virtual void proc() const {
1577             mAdapter.reportGnssSvIdConfig(mConfig);
1578         }
1579     };
1580 
1581     sendMsg(new MsgReportGnssSvIdConfig(*this, config));
1582 }
1583 
reportGnssSvIdConfig(const GnssSvIdConfig & svIdConfig)1584 void GnssAdapter::reportGnssSvIdConfig(const GnssSvIdConfig& svIdConfig)
1585 {
1586     GnssConfig config = {};
1587     config.size = sizeof(GnssConfig);
1588 
1589     // Invoke control clients config callback
1590     if (nullptr != mControlCallbacks.gnssConfigCb &&
1591             svIdConfig.size == sizeof(GnssSvIdConfig)) {
1592         convertFromGnssSvIdConfig(svIdConfig, config);
1593         LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1594                 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64,
1595                 svIdConfig.bdsBlacklistSvMask, svIdConfig.gloBlacklistSvMask,
1596                 svIdConfig.qzssBlacklistSvMask, svIdConfig.galBlacklistSvMask);
1597         mControlCallbacks.gnssConfigCb(config);
1598     } else {
1599         LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
1600     }
1601 }
1602 
1603 void
gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config)1604 GnssAdapter::gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config)
1605 {
1606     struct MsgGnssUpdateSvTypeConfig : public LocMsg {
1607         GnssAdapter* mAdapter;
1608         LocApiBase* mApi;
1609         GnssSvTypeConfig mConfig;
1610         inline MsgGnssUpdateSvTypeConfig(
1611                 GnssAdapter* adapter,
1612                 LocApiBase* api,
1613                 GnssSvTypeConfig& config) :
1614             LocMsg(),
1615             mAdapter(adapter),
1616             mApi(api),
1617             mConfig(config) {}
1618         inline virtual void proc() const {
1619             if (!mAdapter->isEngineCapabilitiesKnown()) {
1620                 mAdapter->mPendingMsgs.push_back(new MsgGnssUpdateSvTypeConfig(*this));
1621                 return;
1622             }
1623             // Check if feature is supported
1624             if (!ContextBase::isFeatureSupported(
1625                     LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1626                 LOC_LOGe("Feature not supported.");
1627             } else {
1628                 // Send update request to modem
1629                 mAdapter->gnssSvTypeConfigUpdate(mConfig);
1630             }
1631         }
1632     };
1633 
1634     sendMsg(new MsgGnssUpdateSvTypeConfig(this, mLocApi, config));
1635 }
1636 
1637 void
gnssSvTypeConfigUpdate(const GnssSvTypeConfig & config)1638 GnssAdapter::gnssSvTypeConfigUpdate(const GnssSvTypeConfig& config)
1639 {
1640     // Gather bits removed from enabled mask
1641     GnssSvTypesMask enabledRemoved = mGnssSvTypeConfig.enabledSvTypesMask &
1642             (mGnssSvTypeConfig.enabledSvTypesMask ^ config.enabledSvTypesMask);
1643     // Send reset if any constellation is removed from the enabled list
1644     bool sendReset = (enabledRemoved != 0);
1645     // Save new config and update
1646     gnssSetSvTypeConfig(config);
1647     gnssSvTypeConfigUpdate(sendReset);
1648 }
1649 
1650 void
gnssSvTypeConfigUpdate(bool sendReset)1651 GnssAdapter::gnssSvTypeConfigUpdate(bool sendReset)
1652 {
1653     LOC_LOGd("size %" PRIu32" constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64
1654              ", sendReset %d",
1655              mGnssSvTypeConfig.size, mGnssSvTypeConfig.blacklistedSvTypesMask,
1656              mGnssSvTypeConfig.enabledSvTypesMask, sendReset);
1657 
1658     if (mGnssSvTypeConfig.size == sizeof(mGnssSvTypeConfig)) {
1659 
1660         if (sendReset) {
1661             mLocApi->resetConstellationControl();
1662         }
1663 
1664         GnssSvIdConfig blacklistConfig = {};
1665         // Revert to previously blacklisted SVs for each enabled constellation
1666         blacklistConfig = mGnssSvIdConfig;
1667         // Blacklist all SVs for each disabled constellation
1668         if (mGnssSvTypeConfig.blacklistedSvTypesMask) {
1669             if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GLO_BIT) {
1670                 blacklistConfig.gloBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1671             }
1672             if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_BDS_BIT) {
1673                 blacklistConfig.bdsBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1674             }
1675             if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_QZSS_BIT) {
1676                 blacklistConfig.qzssBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1677             }
1678             if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GAL_BIT) {
1679                 blacklistConfig.galBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1680             }
1681         }
1682 
1683         // Send blacklist info
1684         mLocApi->setBlacklistSv(blacklistConfig);
1685 
1686         // Send only enabled constellation config
1687         if (mGnssSvTypeConfig.enabledSvTypesMask) {
1688             GnssSvTypeConfig svTypeConfig = {sizeof(GnssSvTypeConfig), 0, 0};
1689             svTypeConfig.enabledSvTypesMask = mGnssSvTypeConfig.enabledSvTypesMask;
1690             mLocApi->setConstellationControl(svTypeConfig);
1691         }
1692     }
1693 }
1694 
1695 void
gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback)1696 GnssAdapter::gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback)
1697 {
1698     struct MsgGnssGetSvTypeConfig : public LocMsg {
1699         GnssAdapter* mAdapter;
1700         LocApiBase* mApi;
1701         GnssSvTypeConfigCallback mCallback;
1702         inline MsgGnssGetSvTypeConfig(
1703                 GnssAdapter* adapter,
1704                 LocApiBase* api,
1705                 GnssSvTypeConfigCallback callback) :
1706             LocMsg(),
1707             mAdapter(adapter),
1708             mApi(api),
1709             mCallback(callback) {}
1710         inline virtual void proc() const {
1711             if (!mAdapter->isEngineCapabilitiesKnown()) {
1712                 mAdapter->mPendingMsgs.push_back(new MsgGnssGetSvTypeConfig(*this));
1713                 return;
1714             }
1715             if (!ContextBase::isFeatureSupported(
1716                     LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1717                 LOC_LOGe("Feature not supported.");
1718             } else {
1719                 // Save the callback
1720                 mAdapter->gnssSetSvTypeConfigCallback(mCallback);
1721                 // Send GET request to modem
1722                 mApi->getConstellationControl();
1723             }
1724         }
1725     };
1726 
1727     sendMsg(new MsgGnssGetSvTypeConfig(this, mLocApi, callback));
1728 }
1729 
1730 void
gnssResetSvTypeConfigCommand()1731 GnssAdapter::gnssResetSvTypeConfigCommand()
1732 {
1733     struct MsgGnssResetSvTypeConfig : public LocMsg {
1734         GnssAdapter* mAdapter;
1735         LocApiBase* mApi;
1736         inline MsgGnssResetSvTypeConfig(
1737                 GnssAdapter* adapter,
1738                 LocApiBase* api) :
1739             LocMsg(),
1740             mAdapter(adapter),
1741             mApi(api) {}
1742         inline virtual void proc() const {
1743             if (!mAdapter->isEngineCapabilitiesKnown()) {
1744                 mAdapter->mPendingMsgs.push_back(new MsgGnssResetSvTypeConfig(*this));
1745                 return;
1746             }
1747             if (!ContextBase::isFeatureSupported(
1748                     LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1749                 LOC_LOGe("Feature not supported.");
1750             } else {
1751                 // Reset constellation config
1752                 mAdapter->gnssSetSvTypeConfig({sizeof(GnssSvTypeConfig), 0, 0});
1753                 // Re-enforce SV blacklist config
1754                 mAdapter->gnssSvIdConfigUpdate();
1755                 // Send reset request to modem
1756                 mApi->resetConstellationControl();
1757             }
1758         }
1759     };
1760 
1761     sendMsg(new MsgGnssResetSvTypeConfig(this, mLocApi));
1762 }
1763 
reportGnssSvTypeConfigEvent(const GnssSvTypeConfig & config)1764 void GnssAdapter::reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config)
1765 {
1766     struct MsgReportGnssSvTypeConfig : public LocMsg {
1767         GnssAdapter& mAdapter;
1768         const GnssSvTypeConfig mConfig;
1769         inline MsgReportGnssSvTypeConfig(GnssAdapter& adapter,
1770                                  const GnssSvTypeConfig& config) :
1771             LocMsg(),
1772             mAdapter(adapter),
1773             mConfig(config) {}
1774         inline virtual void proc() const {
1775             mAdapter.reportGnssSvTypeConfig(mConfig);
1776         }
1777     };
1778 
1779     sendMsg(new MsgReportGnssSvTypeConfig(*this, config));
1780 }
1781 
reportGnssSvTypeConfig(const GnssSvTypeConfig & config)1782 void GnssAdapter::reportGnssSvTypeConfig(const GnssSvTypeConfig& config)
1783 {
1784     // Invoke Get SV Type Callback
1785     if (NULL != mGnssSvTypeConfigCb &&
1786             config.size == sizeof(GnssSvTypeConfig)) {
1787         LOC_LOGd("constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64,
1788                  config.blacklistedSvTypesMask, config.enabledSvTypesMask);
1789         mGnssSvTypeConfigCb(config);
1790     } else {
1791         LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
1792     }
1793 }
1794 
deleteAidingData(const GnssAidingData & data,uint32_t sessionId)1795 void GnssAdapter::deleteAidingData(const GnssAidingData &data, uint32_t sessionId) {
1796     mLocApi->deleteAidingData(data, new LocApiResponse(*getContext(),
1797             [this, sessionId] (LocationError err) {
1798                 reportResponse(err, sessionId);
1799             }));
1800 }
1801 
1802 uint32_t
gnssDeleteAidingDataCommand(GnssAidingData & data)1803 GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data)
1804 {
1805     uint32_t sessionId = generateSessionId();
1806     LOC_LOGD("%s]: id %u", __func__, sessionId);
1807 
1808     struct MsgDeleteAidingData : public LocMsg {
1809         GnssAdapter& mAdapter;
1810         uint32_t mSessionId;
1811         GnssAidingData mData;
1812         inline MsgDeleteAidingData(GnssAdapter& adapter,
1813                                    uint32_t sessionId,
1814                                    GnssAidingData& data) :
1815             LocMsg(),
1816             mAdapter(adapter),
1817             mSessionId(sessionId),
1818             mData(data) {}
1819         inline virtual void proc() const {
1820             mAdapter.deleteAidingData(mData, mSessionId);
1821 
1822             SystemStatus* s = mAdapter.getSystemStatus();
1823             if ((nullptr != s) && (mData.deleteAll)) {
1824                 s->setDefaultGnssEngineStates();
1825             }
1826             mAdapter.mEngHubProxy->gnssDeleteAidingData(mData);
1827         }
1828     };
1829 
1830     sendMsg(new MsgDeleteAidingData(*this, sessionId, data));
1831     return sessionId;
1832 }
1833 
1834 void
gnssUpdateXtraThrottleCommand(const bool enabled)1835 GnssAdapter::gnssUpdateXtraThrottleCommand(const bool enabled)
1836 {
1837     LOC_LOGD("%s] enabled:%d", __func__, enabled);
1838 
1839     struct UpdateXtraThrottleMsg : public LocMsg {
1840         GnssAdapter& mAdapter;
1841         const bool mEnabled;
1842         inline UpdateXtraThrottleMsg(GnssAdapter& adapter, const bool enabled) :
1843             LocMsg(),
1844             mAdapter(adapter),
1845             mEnabled(enabled) {}
1846         inline virtual void proc() const {
1847                 mAdapter.mXtraObserver.updateXtraThrottle(mEnabled);
1848         }
1849     };
1850 
1851     sendMsg(new UpdateXtraThrottleMsg(*this, enabled));
1852 }
1853 
1854 void
injectLocationCommand(double latitude,double longitude,float accuracy)1855 GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy)
1856 {
1857     LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f",
1858              __func__, latitude, longitude, accuracy);
1859 
1860     struct MsgInjectLocation : public LocMsg {
1861         LocApiBase& mApi;
1862         ContextBase& mContext;
1863         BlockCPIInfo& mBlockCPI;
1864         double mLatitude;
1865         double mLongitude;
1866         float mAccuracy;
1867         inline MsgInjectLocation(LocApiBase& api,
1868                                  ContextBase& context,
1869                                  BlockCPIInfo& blockCPIInfo,
1870                                  double latitude,
1871                                  double longitude,
1872                                  float accuracy) :
1873             LocMsg(),
1874             mApi(api),
1875             mContext(context),
1876             mBlockCPI(blockCPIInfo),
1877             mLatitude(latitude),
1878             mLongitude(longitude),
1879             mAccuracy(accuracy) {}
1880         inline virtual void proc() const {
1881             if ((uptimeMillis() <= mBlockCPI.blockedTillTsMs) &&
1882                 (fabs(mLatitude-mBlockCPI.latitude) <= mBlockCPI.latLonDiffThreshold) &&
1883                 (fabs(mLongitude-mBlockCPI.longitude) <= mBlockCPI.latLonDiffThreshold)) {
1884 
1885                 LOC_LOGD("%s]: positon injeciton blocked: lat: %f, lon: %f, accuracy: %f",
1886                          __func__, mLatitude, mLongitude, mAccuracy);
1887 
1888             } else {
1889                 mApi.injectPosition(mLatitude, mLongitude, mAccuracy);
1890             }
1891         }
1892     };
1893 
1894     sendMsg(new MsgInjectLocation(*mLocApi, *mContext, mBlockCPIInfo,
1895                                   latitude, longitude, accuracy));
1896 }
1897 
1898 void
injectLocationExtCommand(const GnssLocationInfoNotification & locationInfo)1899 GnssAdapter::injectLocationExtCommand(const GnssLocationInfoNotification &locationInfo)
1900 {
1901     LOC_LOGd("latitude %8.4f longitude %8.4f accuracy %8.4f, tech mask 0x%x",
1902              locationInfo.location.latitude, locationInfo.location.longitude,
1903              locationInfo.location.accuracy, locationInfo.location.techMask);
1904 
1905     struct MsgInjectLocationExt : public LocMsg {
1906         LocApiBase& mApi;
1907         ContextBase& mContext;
1908         GnssLocationInfoNotification mLocationInfo;
1909         inline MsgInjectLocationExt(LocApiBase& api,
1910                                     ContextBase& context,
1911                                     GnssLocationInfoNotification locationInfo) :
1912             LocMsg(),
1913             mApi(api),
1914             mContext(context),
1915             mLocationInfo(locationInfo) {}
1916         inline virtual void proc() const {
1917             // false to indicate for none-ODCPI
1918             mApi.injectPosition(mLocationInfo, false);
1919         }
1920     };
1921 
1922     sendMsg(new MsgInjectLocationExt(*mLocApi, *mContext, locationInfo));
1923 }
1924 
1925 void
injectTimeCommand(int64_t time,int64_t timeReference,int32_t uncertainty)1926 GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty)
1927 {
1928     LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d",
1929              __func__, (long long)time, (long long)timeReference, uncertainty);
1930 
1931     struct MsgInjectTime : public LocMsg {
1932         LocApiBase& mApi;
1933         ContextBase& mContext;
1934         int64_t mTime;
1935         int64_t mTimeReference;
1936         int32_t mUncertainty;
1937         inline MsgInjectTime(LocApiBase& api,
1938                              ContextBase& context,
1939                              int64_t time,
1940                              int64_t timeReference,
1941                              int32_t uncertainty) :
1942             LocMsg(),
1943             mApi(api),
1944             mContext(context),
1945             mTime(time),
1946             mTimeReference(timeReference),
1947             mUncertainty(uncertainty) {}
1948         inline virtual void proc() const {
1949             mApi.setTime(mTime, mTimeReference, mUncertainty);
1950         }
1951     };
1952 
1953     sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty));
1954 }
1955 
1956 // This command is to called to block the position to be injected to the modem.
1957 // This can happen for network position that comes from modem.
1958 void
blockCPICommand(double latitude,double longitude,float accuracy,int blockDurationMsec,double latLonDiffThreshold)1959 GnssAdapter::blockCPICommand(double latitude, double longitude,
1960                              float accuracy, int blockDurationMsec,
1961                              double latLonDiffThreshold)
1962 {
1963     struct MsgBlockCPI : public LocMsg {
1964         BlockCPIInfo& mDstCPIInfo;
1965         BlockCPIInfo mSrcCPIInfo;
1966 
1967         inline MsgBlockCPI(BlockCPIInfo& dstCPIInfo,
1968                            BlockCPIInfo& srcCPIInfo) :
1969             mDstCPIInfo(dstCPIInfo),
1970             mSrcCPIInfo(srcCPIInfo) {}
1971         inline virtual void proc() const {
1972             // in the same hal thread, save the cpi to be blocked
1973             // the global variable
1974             mDstCPIInfo = mSrcCPIInfo;
1975         }
1976     };
1977 
1978     // construct the new block CPI info and queue on the same thread
1979     // for processing
1980     BlockCPIInfo blockCPIInfo;
1981     blockCPIInfo.latitude = latitude;
1982     blockCPIInfo.longitude = longitude;
1983     blockCPIInfo.accuracy = accuracy;
1984     blockCPIInfo.blockedTillTsMs = uptimeMillis() + blockDurationMsec;
1985     blockCPIInfo.latLonDiffThreshold = latLonDiffThreshold;
1986 
1987     LOC_LOGD("%s]: block CPI lat: %f, lon: %f ", __func__, latitude, longitude);
1988     // send a message to record down the coarse position
1989     // to be blocked from injection in the master copy (mBlockCPIInfo)
1990     sendMsg(new MsgBlockCPI(mBlockCPIInfo, blockCPIInfo));
1991 }
1992 
1993 void
addClientCommand(LocationAPI * client,const LocationCallbacks & callbacks)1994 GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks)
1995 {
1996     LOC_LOGD("%s]: client %p", __func__, client);
1997 
1998     struct MsgAddClient : public LocMsg {
1999         GnssAdapter& mAdapter;
2000         LocationAPI* mClient;
2001         const LocationCallbacks mCallbacks;
2002         inline MsgAddClient(GnssAdapter& adapter,
2003                             LocationAPI* client,
2004                             const LocationCallbacks& callbacks) :
2005             LocMsg(),
2006             mAdapter(adapter),
2007             mClient(client),
2008             mCallbacks(callbacks) {}
2009         inline virtual void proc() const {
2010             // check whether we need to notify client of cached location system info
2011             mAdapter.notifyClientOfCachedLocationSystemInfo(mClient, mCallbacks);
2012             mAdapter.saveClient(mClient, mCallbacks);
2013         }
2014     };
2015 
2016     sendMsg(new MsgAddClient(*this, client, callbacks));
2017 }
2018 
2019 void
stopClientSessions(LocationAPI * client)2020 GnssAdapter::stopClientSessions(LocationAPI* client)
2021 {
2022     LOC_LOGD("%s]: client %p", __func__, client);
2023 
2024     /* Time-based Tracking */
2025     std::vector<LocationSessionKey> vTimeBasedTrackingClient;
2026     for (auto it : mTimeBasedTrackingSessions) {
2027         if (client == it.first.client) {
2028             vTimeBasedTrackingClient.emplace_back(it.first.client, it.first.id);
2029         }
2030     }
2031     for (auto key : vTimeBasedTrackingClient) {
2032         stopTimeBasedTrackingMultiplex(key.client, key.id);
2033     }
2034 
2035     /* Distance-based Tracking */
2036     for (auto it = mDistanceBasedTrackingSessions.begin();
2037               it != mDistanceBasedTrackingSessions.end(); /* no increment here*/) {
2038         if (client == it->first.client) {
2039             mLocApi->stopDistanceBasedTracking(it->first.id, new LocApiResponse(*getContext(),
2040                           [this, client, id=it->first.id] (LocationError err) {
2041                     if (LOCATION_ERROR_SUCCESS == err) {
2042                         eraseTrackingSession(client, id);
2043                     }
2044                 }
2045             ));
2046         }
2047         ++it; // increment only when not erasing an iterator
2048     }
2049 
2050 }
2051 
2052 void
updateClientsEventMask()2053 GnssAdapter::updateClientsEventMask()
2054 {
2055     LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
2056     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2057         if (it->second.trackingCb != nullptr || it->second.gnssLocationInfoCb != nullptr) {
2058             mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
2059         }
2060         if (it->second.gnssSvCb != nullptr) {
2061             mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT;
2062         }
2063         if ((it->second.gnssNmeaCb != nullptr) && (mNmeaMask)) {
2064             mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
2065         }
2066         if (it->second.gnssMeasurementsCb != nullptr) {
2067             mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
2068         }
2069         if (it->second.gnssDataCb != nullptr) {
2070             mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
2071             mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
2072             updateNmeaMask(mNmeaMask | LOC_NMEA_MASK_DEBUG_V02);
2073         }
2074     }
2075 
2076     /*
2077     ** For Automotive use cases we need to enable MEASUREMENT, POLY and EPHEMERIS
2078     ** when QDR is enabled (e.g.: either enabled via conf file or
2079     ** engine hub is loaded successfully).
2080     ** Note: this need to be called from msg queue thread.
2081     */
2082     if((1 == ContextBase::mGps_conf.EXTERNAL_DR_ENABLED) ||
2083        (true == initEngHubProxy())) {
2084         mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
2085         mask |= LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT;
2086         mask |= LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT;
2087         mask |= LOC_API_ADAPTER_BIT_PARSED_UNPROPAGATED_POSITION_REPORT;
2088         mask |= LOC_API_ADAPTER_BIT_GNSS_SV_EPHEMERIS_REPORT;
2089         mask |= LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO;
2090         mask |= LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO;
2091 
2092         LOC_LOGd("Auto usecase, Enable MEAS/POLY/EPHEMERIS - mask 0x%" PRIx64 "",
2093                 mask);
2094     }
2095 
2096     if (mAgpsManager.isRegistered()) {
2097         mask |= LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST;
2098     }
2099     // Add ODCPI handling
2100     if (nullptr != mOdcpiRequestCb) {
2101         mask |= LOC_API_ADAPTER_BIT_REQUEST_WIFI;
2102     }
2103 
2104     // need to register for leap second info
2105     // for proper nmea generation
2106     mask |= LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO;
2107 
2108     // always register for NI NOTIFY VERIFY to handle internally in HAL
2109     mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
2110 
2111     updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
2112 }
2113 
2114 void
handleEngineUpEvent()2115 GnssAdapter::handleEngineUpEvent()
2116 {
2117     LOC_LOGD("%s]: ", __func__);
2118 
2119     struct MsgHandleEngineUpEvent : public LocMsg {
2120         GnssAdapter& mAdapter;
2121         inline MsgHandleEngineUpEvent(GnssAdapter& adapter) :
2122             LocMsg(),
2123             mAdapter(adapter) {}
2124         virtual void proc() const {
2125             mAdapter.setEngineCapabilitiesKnown(true);
2126             mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
2127             // must be called only after capabilities are known
2128             mAdapter.setConfig();
2129             mAdapter.restartSessions();
2130             mAdapter.gnssSvIdConfigUpdate();
2131             mAdapter.gnssSvTypeConfigUpdate();
2132             for (auto msg: mAdapter.mPendingMsgs) {
2133                 mAdapter.sendMsg(msg);
2134             }
2135             mAdapter.mPendingMsgs.clear();
2136         }
2137     };
2138 
2139     readConfigCommand();
2140     sendMsg(new MsgHandleEngineUpEvent(*this));
2141 }
2142 
2143 void
restartSessions()2144 GnssAdapter::restartSessions()
2145 {
2146     LOC_LOGD("%s]: ", __func__);
2147 
2148     // odcpi session is no longer active after restart
2149     mOdcpiRequestActive = false;
2150 
2151     if (!mTimeBasedTrackingSessions.empty()) {
2152         // get the LocationOptions that has the smallest interval, which should be the active one
2153         TrackingOptions smallestIntervalOptions; // size is zero until set for the first time
2154         TrackingOptions highestPowerTrackingOptions;
2155         memset(&smallestIntervalOptions, 0, sizeof(smallestIntervalOptions));
2156         memset(&highestPowerTrackingOptions, 0, sizeof(highestPowerTrackingOptions));
2157         for (auto it = mTimeBasedTrackingSessions.begin(); it != mTimeBasedTrackingSessions.end(); ++it) {
2158             // size of zero means we havent set it yet
2159             if (0 == smallestIntervalOptions.size ||
2160                 it->second.minInterval < smallestIntervalOptions.minInterval) {
2161                  smallestIntervalOptions = it->second;
2162             }
2163             GnssPowerMode powerMode = it->second.powerMode;
2164             // Size of zero means we havent set it yet
2165             if (0 == highestPowerTrackingOptions.size ||
2166                 (GNSS_POWER_MODE_INVALID != powerMode &&
2167                         powerMode < highestPowerTrackingOptions.powerMode)) {
2168                  highestPowerTrackingOptions = it->second;
2169             }
2170         }
2171 
2172         highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions);
2173         mLocApi->startTimeBasedTracking(highestPowerTrackingOptions, nullptr);
2174     }
2175 
2176     for (auto it = mDistanceBasedTrackingSessions.begin();
2177               it != mDistanceBasedTrackingSessions.end(); ++it) {
2178         mLocApi->startDistanceBasedTracking(it->first.id, it->second,
2179                                             new LocApiResponse(*getContext(),
2180                                             [] (LocationError /*err*/) {}));
2181     }
2182 }
2183 
2184 void
notifyClientOfCachedLocationSystemInfo(LocationAPI * client,const LocationCallbacks & callbacks)2185 GnssAdapter::notifyClientOfCachedLocationSystemInfo(
2186         LocationAPI* client, const LocationCallbacks& callbacks) {
2187 
2188     if (mLocSystemInfo.systemInfoMask) {
2189         // client need to be notified if client has not yet previously registered
2190         // for the info but now register for it.
2191         bool notifyClientOfSystemInfo = false;
2192         // check whether we need to notify client of cached location system info
2193         //
2194         // client need to be notified if client has not yet previously registered
2195         // for the info but now register for it.
2196         if (callbacks.locationSystemInfoCb) {
2197             notifyClientOfSystemInfo = true;
2198             auto it = mClientData.find(client);
2199             if (it != mClientData.end()) {
2200                 LocationCallbacks oldCallbacks = it->second;
2201                 if (oldCallbacks.locationSystemInfoCb) {
2202                     notifyClientOfSystemInfo = false;
2203                 }
2204             }
2205         }
2206 
2207         if (notifyClientOfSystemInfo) {
2208             callbacks.locationSystemInfoCb(mLocSystemInfo);
2209         }
2210     }
2211 }
2212 
2213 bool
hasTrackingCallback(LocationAPI * client)2214 GnssAdapter::hasTrackingCallback(LocationAPI* client)
2215 {
2216     auto it = mClientData.find(client);
2217     return (it != mClientData.end() && (it->second.trackingCb || it->second.gnssLocationInfoCb));
2218 }
2219 
2220 bool
isTimeBasedTrackingSession(LocationAPI * client,uint32_t sessionId)2221 GnssAdapter::isTimeBasedTrackingSession(LocationAPI* client, uint32_t sessionId)
2222 {
2223     LocationSessionKey key(client, sessionId);
2224     return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end());
2225 }
2226 
2227 bool
isDistanceBasedTrackingSession(LocationAPI * client,uint32_t sessionId)2228 GnssAdapter::isDistanceBasedTrackingSession(LocationAPI* client, uint32_t sessionId)
2229 {
2230     LocationSessionKey key(client, sessionId);
2231     return (mDistanceBasedTrackingSessions.find(key) != mDistanceBasedTrackingSessions.end());
2232 }
2233 
2234 bool
hasMeasurementsCallback(LocationAPI * client)2235 GnssAdapter::hasMeasurementsCallback(LocationAPI* client)
2236 {
2237     auto it = mClientData.find(client);
2238     return (it != mClientData.end() && it->second.gnssMeasurementsCb);
2239 }
2240 
2241 bool
isTrackingSession(LocationAPI * client,uint32_t sessionId)2242 GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId)
2243 {
2244     LocationSessionKey key(client, sessionId);
2245     return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end());
2246 }
2247 
2248 void
reportPowerStateIfChanged()2249 GnssAdapter::reportPowerStateIfChanged()
2250 {
2251     bool newPowerOn = !mTimeBasedTrackingSessions.empty() ||
2252                       !mDistanceBasedTrackingSessions.empty();
2253     if (newPowerOn != mPowerOn) {
2254         mPowerOn = newPowerOn;
2255         if (mPowerStateCb != nullptr) {
2256             mPowerStateCb(mPowerOn);
2257         }
2258     }
2259 }
2260 
2261 void
getPowerStateChangesCommand(void * powerStateCb)2262 GnssAdapter::getPowerStateChangesCommand(void* powerStateCb)
2263 {
2264     LOC_LOGD("%s]: ", __func__);
2265 
2266     struct MsgReportLocation : public LocMsg {
2267         GnssAdapter& mAdapter;
2268         powerStateCallback mPowerStateCb;
2269         inline MsgReportLocation(GnssAdapter& adapter,
2270                                  powerStateCallback powerStateCb) :
2271             LocMsg(),
2272             mAdapter(adapter),
2273             mPowerStateCb(powerStateCb) {}
2274         inline virtual void proc() const {
2275             mAdapter.savePowerStateCallback(mPowerStateCb);
2276             mPowerStateCb(mAdapter.getPowerState());
2277         }
2278     };
2279 
2280     sendMsg(new MsgReportLocation(*this, (powerStateCallback)powerStateCb));
2281 }
2282 
2283 void
saveTrackingSession(LocationAPI * client,uint32_t sessionId,const TrackingOptions & options)2284 GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId,
2285                                 const TrackingOptions& options)
2286 {
2287     LocationSessionKey key(client, sessionId);
2288     if ((options.minDistance > 0) &&
2289             ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
2290         mDistanceBasedTrackingSessions[key] = options;
2291     } else {
2292         mTimeBasedTrackingSessions[key] = options;
2293     }
2294     reportPowerStateIfChanged();
2295 }
2296 
2297 void
eraseTrackingSession(LocationAPI * client,uint32_t sessionId)2298 GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId)
2299 {
2300     LocationSessionKey key(client, sessionId);
2301     auto it = mTimeBasedTrackingSessions.find(key);
2302     if (it != mTimeBasedTrackingSessions.end()) {
2303         mTimeBasedTrackingSessions.erase(it);
2304     } else {
2305         auto itr = mDistanceBasedTrackingSessions.find(key);
2306         if (itr != mDistanceBasedTrackingSessions.end()) {
2307             mDistanceBasedTrackingSessions.erase(itr);
2308         }
2309     }
2310     reportPowerStateIfChanged();
2311 }
2312 
2313 
setLocPositionMode(const LocPosMode & mode)2314 bool GnssAdapter::setLocPositionMode(const LocPosMode& mode) {
2315     if (!mLocPositionMode.equals(mode)) {
2316         mLocPositionMode = mode;
2317         return true;
2318     } else {
2319         return false;
2320     }
2321 }
2322 
2323 void
reportResponse(LocationAPI * client,LocationError err,uint32_t sessionId)2324 GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId)
2325 {
2326     LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err);
2327 
2328     auto it = mClientData.find(client);
2329     if (it != mClientData.end() && it->second.responseCb != nullptr) {
2330         it->second.responseCb(err, sessionId);
2331     } else {
2332         LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId);
2333     }
2334 }
2335 
2336 void
reportResponse(LocationError err,uint32_t sessionId)2337 GnssAdapter::reportResponse(LocationError err, uint32_t sessionId)
2338 {
2339     LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err);
2340 
2341     if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) {
2342         mControlCallbacks.responseCb(err, sessionId);
2343     } else {
2344         LOC_LOGW("%s]: control client response callback not found", __func__);
2345     }
2346 }
2347 
2348 void
reportResponse(size_t count,LocationError * errs,uint32_t * ids)2349 GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids)
2350 {
2351     IF_LOC_LOGD {
2352         std::string idsString = "[";
2353         std::string errsString = "[";
2354         if (NULL != ids && NULL != errs) {
2355             for (size_t i=0; i < count; ++i) {
2356                 idsString += std::to_string(ids[i]) + " ";
2357                 errsString += std::to_string(errs[i]) + " ";
2358             }
2359         }
2360         idsString += "]";
2361         errsString += "]";
2362 
2363         LOC_LOGD("%s]: ids %s errs %s",
2364                  __func__, idsString.c_str(), errsString.c_str());
2365     }
2366 
2367     if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) {
2368         mControlCallbacks.collectiveResponseCb(count, errs, ids);
2369     } else {
2370         LOC_LOGW("%s]: control client callback not found", __func__);
2371     }
2372 }
2373 
2374 uint32_t
startTrackingCommand(LocationAPI * client,TrackingOptions & options)2375 GnssAdapter::startTrackingCommand(LocationAPI* client, TrackingOptions& options)
2376 {
2377     uint32_t sessionId = generateSessionId();
2378     LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u powermode %u tbm %u",
2379              __func__, client, sessionId, options.minInterval, options.minDistance, options.mode,
2380              options.powerMode, options.tbm);
2381 
2382     struct MsgStartTracking : public LocMsg {
2383         GnssAdapter& mAdapter;
2384         LocApiBase& mApi;
2385         LocationAPI* mClient;
2386         uint32_t mSessionId;
2387         mutable TrackingOptions mOptions;
2388         inline MsgStartTracking(GnssAdapter& adapter,
2389                                LocApiBase& api,
2390                                LocationAPI* client,
2391                                uint32_t sessionId,
2392                                TrackingOptions options) :
2393             LocMsg(),
2394             mAdapter(adapter),
2395             mApi(api),
2396             mClient(client),
2397             mSessionId(sessionId),
2398             mOptions(options) {}
2399         inline virtual void proc() const {
2400             // distance based tracking will need to know engine capabilities before it can start
2401             if (!mAdapter.isEngineCapabilitiesKnown() && mOptions.minDistance > 0) {
2402                 mAdapter.mPendingMsgs.push_back(new MsgStartTracking(*this));
2403                 return;
2404             }
2405             LocationError err = LOCATION_ERROR_SUCCESS;
2406             if (!mAdapter.hasTrackingCallback(mClient) &&
2407                 !mAdapter.hasMeasurementsCallback(mClient)) {
2408                 err = LOCATION_ERROR_CALLBACK_MISSING;
2409             } else if (0 == mOptions.size) {
2410                 err = LOCATION_ERROR_INVALID_PARAMETER;
2411             } else {
2412                 if (mOptions.minInterval < MIN_TRACKING_INTERVAL) {
2413                     mOptions.minInterval = MIN_TRACKING_INTERVAL;
2414                 }
2415                 if (mOptions.minDistance > 0 &&
2416                         ContextBase::isMessageSupported(
2417                         LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
2418                     mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2419                     mApi.startDistanceBasedTracking(mSessionId, mOptions,
2420                             new LocApiResponse(*mAdapter.getContext(),
2421                             [&mAdapter = mAdapter, mSessionId = mSessionId, mClient = mClient]
2422                             (LocationError err) {
2423                         if (LOCATION_ERROR_SUCCESS != err) {
2424                             mAdapter.eraseTrackingSession(mClient, mSessionId);
2425                         }
2426                         mAdapter.reportResponse(mClient, err, mSessionId);
2427                     }));
2428                 } else {
2429                     if (GNSS_POWER_MODE_M4 == mOptions.powerMode &&
2430                             mOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
2431                         LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
2432                                 mOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
2433                         mOptions.powerMode = GNSS_POWER_MODE_M2;
2434                     }
2435                     // Api doesn't support multiple clients for time based tracking, so mutiplex
2436                     bool reportToClientWithNoWait =
2437                             mAdapter.startTimeBasedTrackingMultiplex(mClient, mSessionId, mOptions);
2438                     mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2439 
2440                     if (reportToClientWithNoWait) {
2441                         mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
2442                     }
2443                 }
2444             }
2445         }
2446     };
2447 
2448     sendMsg(new MsgStartTracking(*this, *mLocApi, client, sessionId, options));
2449     return sessionId;
2450 
2451 }
2452 
2453 bool
startTimeBasedTrackingMultiplex(LocationAPI * client,uint32_t sessionId,const TrackingOptions & options)2454 GnssAdapter::startTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t sessionId,
2455                                              const TrackingOptions& options)
2456 {
2457     bool reportToClientWithNoWait = true;
2458 
2459     if (mTimeBasedTrackingSessions.empty()) {
2460         startTimeBasedTracking(client, sessionId, options);
2461         // need to wait for QMI callback
2462         reportToClientWithNoWait = false;
2463     } else {
2464         // find the smallest interval and powerMode
2465         TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
2466         GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
2467         memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
2468         for (auto it = mTimeBasedTrackingSessions.begin(); it != mTimeBasedTrackingSessions.end(); ++it) {
2469             // if not set or there is a new smallest interval, then set the new interval
2470             if (0 == multiplexedOptions.size ||
2471                 it->second.minInterval < multiplexedOptions.minInterval) {
2472                 multiplexedOptions = it->second;
2473             }
2474             // if session is not the one we are updating and either powerMode
2475             // is not set or there is a new smallest powerMode, then set the new powerMode
2476             if (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
2477                 it->second.powerMode < multiplexedPowerMode) {
2478                 multiplexedPowerMode = it->second.powerMode;
2479             }
2480         }
2481         bool updateOptions = false;
2482         // if session we are starting has smaller interval then next smallest
2483         if (options.minInterval < multiplexedOptions.minInterval) {
2484             multiplexedOptions.minInterval = options.minInterval;
2485             updateOptions = true;
2486         }
2487         // if session we are starting has smaller powerMode then next smallest
2488         if (options.powerMode < multiplexedPowerMode) {
2489             multiplexedOptions.powerMode = options.powerMode;
2490             updateOptions = true;
2491         }
2492         if (updateOptions) {
2493             // restart time based tracking with the newly updated options
2494 
2495             startTimeBasedTracking(client, sessionId, multiplexedOptions);
2496             // need to wait for QMI callback
2497             reportToClientWithNoWait = false;
2498         }
2499         // else part: no QMI call is made, need to report back to client right away
2500     }
2501 
2502     return reportToClientWithNoWait;
2503 }
2504 
2505 void
startTimeBasedTracking(LocationAPI * client,uint32_t sessionId,const TrackingOptions & trackingOptions)2506 GnssAdapter::startTimeBasedTracking(LocationAPI* client, uint32_t sessionId,
2507         const TrackingOptions& trackingOptions)
2508 {
2509     LOC_LOGd("minInterval %u minDistance %u mode %u powermode %u tbm %u",
2510             trackingOptions.minInterval, trackingOptions.minDistance,
2511             trackingOptions.mode, trackingOptions.powerMode, trackingOptions.tbm);
2512 
2513     LocPosMode locPosMode = {};
2514     convertOptions(locPosMode, trackingOptions);
2515 
2516     // inform engine hub that GNSS session is about to start
2517     mEngHubProxy->gnssSetFixMode(locPosMode);
2518     mEngHubProxy->gnssStartFix();
2519 
2520     mLocApi->startTimeBasedTracking(trackingOptions, new LocApiResponse(*getContext(),
2521                       [this, client, sessionId] (LocationError err) {
2522             if (LOCATION_ERROR_SUCCESS != err) {
2523                 eraseTrackingSession(client, sessionId);
2524             }
2525 
2526             reportResponse(client, err, sessionId);
2527         }
2528     ));
2529 }
2530 
2531 void
updateTracking(LocationAPI * client,uint32_t sessionId,const TrackingOptions & updatedOptions,const TrackingOptions & oldOptions)2532 GnssAdapter::updateTracking(LocationAPI* client, uint32_t sessionId,
2533         const TrackingOptions& updatedOptions, const TrackingOptions& oldOptions)
2534 {
2535     LocPosMode locPosMode = {};
2536     convertOptions(locPosMode, updatedOptions);
2537 
2538     // inform engine hub that GNSS session is about to start
2539     mEngHubProxy->gnssSetFixMode(locPosMode);
2540     mEngHubProxy->gnssStartFix();
2541 
2542     mLocApi->startTimeBasedTracking(updatedOptions, new LocApiResponse(*getContext(),
2543                       [this, client, sessionId, oldOptions] (LocationError err) {
2544             if (LOCATION_ERROR_SUCCESS != err) {
2545                 // restore the old LocationOptions
2546                 saveTrackingSession(client, sessionId, oldOptions);
2547             }
2548 
2549             reportResponse(client, err, sessionId);
2550         }
2551     ));
2552 }
2553 
2554 void
updateTrackingOptionsCommand(LocationAPI * client,uint32_t id,TrackingOptions & options)2555 GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
2556                                           TrackingOptions& options)
2557 {
2558     LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
2559              __func__, client, id, options.minInterval, options.mode);
2560 
2561     struct MsgUpdateTracking : public LocMsg {
2562         GnssAdapter& mAdapter;
2563         LocApiBase& mApi;
2564         LocationAPI* mClient;
2565         uint32_t mSessionId;
2566         mutable TrackingOptions mOptions;
2567         inline MsgUpdateTracking(GnssAdapter& adapter,
2568                                 LocApiBase& api,
2569                                 LocationAPI* client,
2570                                 uint32_t sessionId,
2571                                 TrackingOptions options) :
2572             LocMsg(),
2573             mAdapter(adapter),
2574             mApi(api),
2575             mClient(client),
2576             mSessionId(sessionId),
2577             mOptions(options) {}
2578         inline virtual void proc() const {
2579             // distance based tracking will need to know engine capabilities before it can start
2580             if (!mAdapter.isEngineCapabilitiesKnown() && mOptions.minDistance > 0) {
2581                 mAdapter.mPendingMsgs.push_back(new MsgUpdateTracking(*this));
2582                 return;
2583             }
2584             LocationError err = LOCATION_ERROR_SUCCESS;
2585             bool isTimeBased = mAdapter.isTimeBasedTrackingSession(mClient, mSessionId);
2586             bool isDistanceBased = mAdapter.isDistanceBasedTrackingSession(mClient, mSessionId);
2587             if (!isTimeBased && !isDistanceBased) {
2588                 err = LOCATION_ERROR_ID_UNKNOWN;
2589             } else if (0 == mOptions.size) {
2590                 err = LOCATION_ERROR_INVALID_PARAMETER;
2591             }
2592             if (LOCATION_ERROR_SUCCESS != err) {
2593                 mAdapter.reportResponse(mClient, err, mSessionId);
2594             } else {
2595                 if (GNSS_POWER_MODE_M4 == mOptions.powerMode &&
2596                         mOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
2597                     LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
2598                             mOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
2599                     mOptions.powerMode = GNSS_POWER_MODE_M2;
2600                 }
2601                 if (mOptions.minInterval < MIN_TRACKING_INTERVAL) {
2602                     mOptions.minInterval = MIN_TRACKING_INTERVAL;
2603                 }
2604                 // Now update session as required
2605                 if (isTimeBased && mOptions.minDistance > 0) {
2606                     // switch from time based to distance based
2607                     // Api doesn't support multiple clients for time based tracking, so mutiplex
2608                     bool reportToClientWithNoWait =
2609                         mAdapter.stopTimeBasedTrackingMultiplex(mClient, mSessionId);
2610                     // erases the time based Session
2611                     mAdapter.eraseTrackingSession(mClient, mSessionId);
2612                     if (reportToClientWithNoWait) {
2613                         mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
2614                     }
2615                     // saves as distance based Session
2616                     mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2617                     mApi.startDistanceBasedTracking(mSessionId, mOptions,
2618                             new LocApiResponse(*mAdapter.getContext(),
2619                                         [] (LocationError /*err*/) {}));
2620                 } else if (isDistanceBased && mOptions.minDistance == 0) {
2621                     // switch from distance based to time based
2622                     mAdapter.eraseTrackingSession(mClient, mSessionId);
2623                     mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
2624                             *mAdapter.getContext(),
2625                             [&mAdapter = mAdapter, mSessionId = mSessionId, mOptions = mOptions,
2626                             mClient = mClient] (LocationError /*err*/) {
2627                         // Api doesn't support multiple clients for time based tracking,
2628                         // so mutiplex
2629                         bool reportToClientWithNoWait =
2630                                 mAdapter.startTimeBasedTrackingMultiplex(mClient, mSessionId,
2631                                                                          mOptions);
2632                         mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2633 
2634                         if (reportToClientWithNoWait) {
2635                             mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
2636                         }
2637                     }));
2638                 } else if (isTimeBased) {
2639                     // update time based tracking
2640                     // Api doesn't support multiple clients for time based tracking, so mutiplex
2641                     bool reportToClientWithNoWait =
2642                             mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions);
2643                     mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2644 
2645                     if (reportToClientWithNoWait) {
2646                         mAdapter.reportResponse(mClient, err, mSessionId);
2647                     }
2648                 } else if (isDistanceBased) {
2649                     // restart distance based tracking
2650                     mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
2651                             *mAdapter.getContext(),
2652                             [&mAdapter = mAdapter, mSessionId = mSessionId, mOptions = mOptions,
2653                             mClient = mClient, &mApi = mApi] (LocationError err) {
2654                         if (LOCATION_ERROR_SUCCESS == err) {
2655                             mApi.startDistanceBasedTracking(mSessionId, mOptions,
2656                                     new LocApiResponse(*mAdapter.getContext(),
2657                                     [&mAdapter, mClient, mSessionId, mOptions]
2658                                     (LocationError err) {
2659                                 if (LOCATION_ERROR_SUCCESS == err) {
2660                                     mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2661                                 }
2662                                 mAdapter.reportResponse(mClient, err, mSessionId);
2663                             }));
2664                         }
2665                     }));
2666                 }
2667             }
2668         }
2669     };
2670 
2671     sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options));
2672 }
2673 
2674 bool
updateTrackingMultiplex(LocationAPI * client,uint32_t id,const TrackingOptions & trackingOptions)2675 GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id,
2676                                      const TrackingOptions& trackingOptions)
2677 {
2678     bool reportToClientWithNoWait = true;
2679 
2680     LocationSessionKey key(client, id);
2681     // get the session we are updating
2682     auto it = mTimeBasedTrackingSessions.find(key);
2683 
2684     // cache the clients existing LocationOptions
2685     TrackingOptions oldOptions = it->second;
2686 
2687     // if session we are updating exists and the minInterval or powerMode has changed
2688     if (it != mTimeBasedTrackingSessions.end() &&
2689        (it->second.minInterval != trackingOptions.minInterval ||
2690         it->second.powerMode != trackingOptions.powerMode)) {
2691         // find the smallest interval and powerMode, other than the session we are updating
2692         TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
2693         GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
2694         memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
2695         for (auto it2 = mTimeBasedTrackingSessions.begin();
2696              it2 != mTimeBasedTrackingSessions.end(); ++it2) {
2697             // if session is not the one we are updating and either interval
2698             // is not set or there is a new smallest interval, then set the new interval
2699             if (it2->first != key && (0 == multiplexedOptions.size ||
2700                 it2->second.minInterval < multiplexedOptions.minInterval)) {
2701                  multiplexedOptions = it2->second;
2702             }
2703             // if session is not the one we are updating and either powerMode
2704             // is not set or there is a new smallest powerMode, then set the new powerMode
2705             if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
2706                 it2->second.powerMode < multiplexedPowerMode)) {
2707                 multiplexedPowerMode = it2->second.powerMode;
2708             }
2709             // else part: no QMI call is made, need to report back to client right away
2710         }
2711         bool updateOptions = false;
2712         // if session we are updating has smaller interval then next smallest
2713         if (trackingOptions.minInterval < multiplexedOptions.minInterval) {
2714             multiplexedOptions.minInterval = trackingOptions.minInterval;
2715             updateOptions = true;
2716         }
2717         // if session we are updating has smaller powerMode then next smallest
2718         if (trackingOptions.powerMode < multiplexedPowerMode) {
2719             multiplexedOptions.powerMode = trackingOptions.powerMode;
2720             updateOptions = true;
2721         }
2722         // if only one session exists, then tracking should be updated with it
2723         if (1 == mTimeBasedTrackingSessions.size()) {
2724             multiplexedOptions = trackingOptions;
2725             updateOptions = true;
2726         }
2727         if (updateOptions) {
2728             // restart time based tracking with the newly updated options
2729             updateTracking(client, id, multiplexedOptions, oldOptions);
2730             // need to wait for QMI callback
2731             reportToClientWithNoWait = false;
2732         }
2733     }
2734 
2735     return reportToClientWithNoWait;
2736 }
2737 
2738 void
stopTrackingCommand(LocationAPI * client,uint32_t id)2739 GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id)
2740 {
2741     LOC_LOGD("%s]: client %p id %u", __func__, client, id);
2742 
2743     struct MsgStopTracking : public LocMsg {
2744         GnssAdapter& mAdapter;
2745         LocApiBase& mApi;
2746         LocationAPI* mClient;
2747         uint32_t mSessionId;
2748         inline MsgStopTracking(GnssAdapter& adapter,
2749                                LocApiBase& api,
2750                                LocationAPI* client,
2751                                uint32_t sessionId) :
2752             LocMsg(),
2753             mAdapter(adapter),
2754             mApi(api),
2755             mClient(client),
2756             mSessionId(sessionId) {}
2757         inline virtual void proc() const {
2758             bool isTimeBased = mAdapter.isTimeBasedTrackingSession(mClient, mSessionId);
2759             bool isDistanceBased = mAdapter.isDistanceBasedTrackingSession(mClient, mSessionId);
2760             if (isTimeBased || isDistanceBased) {
2761                 if (isTimeBased) {
2762                     // Api doesn't support multiple clients for time based tracking, so mutiplex
2763                     bool reportToClientWithNoWait =
2764                         mAdapter.stopTimeBasedTrackingMultiplex(mClient, mSessionId);
2765                     mAdapter.eraseTrackingSession(mClient, mSessionId);
2766 
2767                     if (reportToClientWithNoWait) {
2768                         mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
2769                     }
2770                 } else if (isDistanceBased) {
2771                     mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
2772                             *mAdapter.getContext(),
2773                             [&mAdapter = mAdapter, mSessionId = mSessionId, mClient = mClient]
2774                             (LocationError err) {
2775                         if (LOCATION_ERROR_SUCCESS == err) {
2776                             mAdapter.eraseTrackingSession(mClient, mSessionId);
2777                         }
2778                         mAdapter.reportResponse(mClient, err, mSessionId);
2779                     }));
2780                 }
2781             } else {
2782                 mAdapter.reportResponse(mClient, LOCATION_ERROR_ID_UNKNOWN, mSessionId);
2783             }
2784 
2785         }
2786     };
2787 
2788     sendMsg(new MsgStopTracking(*this, *mLocApi, client, id));
2789 }
2790 
2791 bool
stopTimeBasedTrackingMultiplex(LocationAPI * client,uint32_t id)2792 GnssAdapter::stopTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t id)
2793 {
2794     bool reportToClientWithNoWait = true;
2795 
2796     if (1 == mTimeBasedTrackingSessions.size()) {
2797         stopTracking(client, id);
2798         // need to wait for QMI callback
2799         reportToClientWithNoWait = false;
2800     } else {
2801         LocationSessionKey key(client, id);
2802 
2803         // get the session we are stopping
2804         auto it = mTimeBasedTrackingSessions.find(key);
2805         if (it != mTimeBasedTrackingSessions.end()) {
2806             // find the smallest interval and powerMode, other than the session we are stopping
2807             TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
2808             GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
2809             memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
2810             for (auto it2 = mTimeBasedTrackingSessions.begin();
2811                  it2 != mTimeBasedTrackingSessions.end(); ++it2) {
2812                 // if session is not the one we are stopping and either interval
2813                 // is not set or there is a new smallest interval, then set the new interval
2814                 if (it2->first != key && (0 == multiplexedOptions.size ||
2815                     it2->second.minInterval < multiplexedOptions.minInterval)) {
2816                      multiplexedOptions = it2->second;
2817                 }
2818                 // if session is not the one we are stopping and either powerMode
2819                 // is not set or there is a new smallest powerMode, then set the new powerMode
2820                 if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
2821                     it2->second.powerMode < multiplexedPowerMode)) {
2822                     multiplexedPowerMode = it2->second.powerMode;
2823                 }
2824             }
2825             // if session we are stopping has smaller interval then next smallest or
2826             // if session we are stopping has smaller powerMode then next smallest
2827             if (it->second.minInterval < multiplexedOptions.minInterval ||
2828                 it->second.powerMode < multiplexedPowerMode) {
2829                 multiplexedOptions.powerMode = multiplexedPowerMode;
2830                 // restart time based tracking with the newly updated options
2831                 startTimeBasedTracking(client, id, multiplexedOptions);
2832                 // need to wait for QMI callback
2833                 reportToClientWithNoWait = false;
2834             }
2835             // else part: no QMI call is made, need to report back to client right away
2836         }
2837     }
2838 
2839     return reportToClientWithNoWait;
2840 }
2841 
2842 void
stopTracking(LocationAPI * client,uint32_t id)2843 GnssAdapter::stopTracking(LocationAPI* client, uint32_t id)
2844 {
2845     // inform engine hub that GNSS session has stopped
2846     mEngHubProxy->gnssStopFix();
2847 
2848     mLocApi->stopFix(new LocApiResponse(*getContext(),
2849                      [this, client, id] (LocationError err) {
2850         reportResponse(client, err, id);
2851     }));
2852 }
2853 
2854 bool
hasNiNotifyCallback(LocationAPI * client)2855 GnssAdapter::hasNiNotifyCallback(LocationAPI* client)
2856 {
2857     auto it = mClientData.find(client);
2858     return (it != mClientData.end() && it->second.gnssNiCb);
2859 }
2860 
2861 void
gnssNiResponseCommand(LocationAPI * client,uint32_t id,GnssNiResponse response)2862 GnssAdapter::gnssNiResponseCommand(LocationAPI* client,
2863                                    uint32_t id,
2864                                    GnssNiResponse response)
2865 {
2866     LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response);
2867 
2868     struct MsgGnssNiResponse : public LocMsg {
2869         GnssAdapter& mAdapter;
2870         LocationAPI* mClient;
2871         uint32_t mSessionId;
2872         GnssNiResponse mResponse;
2873         inline MsgGnssNiResponse(GnssAdapter& adapter,
2874                                  LocationAPI* client,
2875                                  uint32_t sessionId,
2876                                  GnssNiResponse response) :
2877             LocMsg(),
2878             mAdapter(adapter),
2879             mClient(client),
2880             mSessionId(sessionId),
2881             mResponse(response) {}
2882         inline virtual void proc() const {
2883             NiData& niData = mAdapter.getNiData();
2884             LocationError err = LOCATION_ERROR_SUCCESS;
2885             if (!mAdapter.hasNiNotifyCallback(mClient)) {
2886                 err = LOCATION_ERROR_ID_UNKNOWN;
2887             } else {
2888                 NiSession* pSession = NULL;
2889                 if (mSessionId == niData.sessionEs.reqID &&
2890                     NULL != niData.sessionEs.rawRequest) {
2891                     pSession = &niData.sessionEs;
2892                     // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
2893                     if (mResponse == GNSS_NI_RESPONSE_ACCEPT &&
2894                         NULL != niData.session.rawRequest) {
2895                             pthread_mutex_lock(&niData.session.tLock);
2896                             niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
2897                             niData.session.respRecvd = true;
2898                             pthread_cond_signal(&niData.session.tCond);
2899                             pthread_mutex_unlock(&niData.session.tLock);
2900                     }
2901                 } else if (mSessionId == niData.session.reqID &&
2902                     NULL != niData.session.rawRequest) {
2903                     pSession = &niData.session;
2904                 }
2905 
2906                 if (pSession) {
2907                     LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u",
2908                              __func__, mResponse, mSessionId);
2909                     pthread_mutex_lock(&pSession->tLock);
2910                     pSession->resp = mResponse;
2911                     pSession->respRecvd = true;
2912                     pthread_cond_signal(&pSession->tCond);
2913                     pthread_mutex_unlock(&pSession->tLock);
2914                 } else {
2915                     err = LOCATION_ERROR_ID_UNKNOWN;
2916                     LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session",
2917                              __func__, mSessionId);
2918                 }
2919             }
2920             mAdapter.reportResponse(mClient, err, mSessionId);
2921         }
2922     };
2923 
2924     sendMsg(new MsgGnssNiResponse(*this, client, id, response));
2925 
2926 }
2927 
2928 void
gnssNiResponseCommand(GnssNiResponse response,void * rawRequest)2929 GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest)
2930 {
2931     LOC_LOGD("%s]: response %u", __func__, response);
2932 
2933     struct MsgGnssNiResponse : public LocMsg {
2934         GnssAdapter& mAdapter;
2935         LocApiBase& mApi;
2936         const GnssNiResponse mResponse;
2937         const void* mPayload;
2938         inline MsgGnssNiResponse(GnssAdapter& adapter,
2939                                  LocApiBase& api,
2940                                  const GnssNiResponse response,
2941                                  const void* rawRequest) :
2942             LocMsg(),
2943             mAdapter(adapter),
2944             mApi(api),
2945             mResponse(response),
2946             mPayload(rawRequest) {}
2947         inline virtual ~MsgGnssNiResponse() {
2948         }
2949         inline virtual void proc() const {
2950             mApi.informNiResponse(mResponse, mPayload);
2951         }
2952     };
2953 
2954     sendMsg(new MsgGnssNiResponse(*this, *mLocApi, response, rawRequest));
2955 
2956 }
2957 
2958 uint32_t
enableCommand(LocationTechnologyType techType)2959 GnssAdapter::enableCommand(LocationTechnologyType techType)
2960 {
2961     uint32_t sessionId = generateSessionId();
2962     LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType);
2963 
2964     struct MsgEnableGnss : public LocMsg {
2965         GnssAdapter& mAdapter;
2966         LocApiBase& mApi;
2967         ContextBase& mContext;
2968         uint32_t mSessionId;
2969         LocationTechnologyType mTechType;
2970         inline MsgEnableGnss(GnssAdapter& adapter,
2971                              LocApiBase& api,
2972                              ContextBase& context,
2973                              uint32_t sessionId,
2974                              LocationTechnologyType techType) :
2975             LocMsg(),
2976             mAdapter(adapter),
2977             mApi(api),
2978             mContext(context),
2979             mSessionId(sessionId),
2980             mTechType(techType) {}
2981         inline virtual void proc() const {
2982             LocationError err = LOCATION_ERROR_SUCCESS;
2983             uint32_t afwControlId = mAdapter.getAfwControlId();
2984             if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) {
2985                 err = LOCATION_ERROR_INVALID_PARAMETER;
2986             } else if (afwControlId > 0) {
2987                 err = LOCATION_ERROR_ALREADY_STARTED;
2988             } else {
2989                 mContext.modemPowerVote(true);
2990                 mAdapter.setAfwControlId(mSessionId);
2991 
2992                 GnssConfigGpsLock gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
2993                 if (mAdapter.mSupportNfwControl) {
2994                     ContextBase::mGps_conf.GPS_LOCK &= GNSS_CONFIG_GPS_LOCK_NI;
2995                     gpsLock = ContextBase::mGps_conf.GPS_LOCK;
2996                 }
2997                 mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
2998                     mApi.setGpsLockSync(gpsLock);
2999                 }));
3000                 mAdapter.mXtraObserver.updateLockStatus(gpsLock);
3001             }
3002             mAdapter.reportResponse(err, mSessionId);
3003         }
3004     };
3005 
3006     if (mContext != NULL) {
3007         sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType));
3008     } else {
3009         LOC_LOGE("%s]: Context is NULL", __func__);
3010     }
3011 
3012     return sessionId;
3013 }
3014 
3015 void
disableCommand(uint32_t id)3016 GnssAdapter::disableCommand(uint32_t id)
3017 {
3018     LOC_LOGD("%s]: id %u", __func__, id);
3019 
3020     struct MsgDisableGnss : public LocMsg {
3021         GnssAdapter& mAdapter;
3022         LocApiBase& mApi;
3023         ContextBase& mContext;
3024         uint32_t mSessionId;
3025         inline MsgDisableGnss(GnssAdapter& adapter,
3026                              LocApiBase& api,
3027                              ContextBase& context,
3028                              uint32_t sessionId) :
3029             LocMsg(),
3030             mAdapter(adapter),
3031             mApi(api),
3032             mContext(context),
3033             mSessionId(sessionId) {}
3034         inline virtual void proc() const {
3035             LocationError err = LOCATION_ERROR_SUCCESS;
3036             uint32_t afwControlId = mAdapter.getAfwControlId();
3037             if (afwControlId != mSessionId) {
3038                 err = LOCATION_ERROR_ID_UNKNOWN;
3039             } else {
3040                 mContext.modemPowerVote(false);
3041                 mAdapter.setAfwControlId(0);
3042 
3043                 if (mAdapter.mSupportNfwControl) {
3044                     /* We need to disable MO (AFW) */
3045                     ContextBase::mGps_conf.GPS_LOCK |= GNSS_CONFIG_GPS_LOCK_MO;
3046                 }
3047                 GnssConfigGpsLock gpsLock = ContextBase::mGps_conf.GPS_LOCK;
3048                 mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
3049                     mApi.setGpsLockSync(gpsLock);
3050                 }));
3051                 mAdapter.mXtraObserver.updateLockStatus(gpsLock);
3052             }
3053             mAdapter.reportResponse(err, mSessionId);
3054         }
3055     };
3056 
3057     if (mContext != NULL) {
3058         sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id));
3059     }
3060 
3061 }
3062 
3063 void
reportPositionEvent(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask,GnssDataNotification * pDataNotify,int msInWeek)3064 GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation,
3065                                  const GpsLocationExtended& locationExtended,
3066                                  enum loc_sess_status status,
3067                                  LocPosTechMask techMask,
3068                                  GnssDataNotification* pDataNotify,
3069                                  int msInWeek)
3070 {
3071     // this position is from QMI LOC API, then send report to engine hub
3072     // if sending is successful, we return as we will wait for final report from engine hub
3073     // if the position is called from engine hub, then send it out directly
3074 
3075     if (true == initEngHubProxy()){
3076         mEngHubProxy->gnssReportPosition(ulpLocation, locationExtended, status);
3077         return;
3078     }
3079 
3080     if (true == ulpLocation.unpropagatedPosition) {
3081         return;
3082     }
3083 
3084     // Fix is from QMI, and it is not an
3085     // unpropagated position and engine hub is not loaded, queue the msg
3086     // when message is queued, the position can be dispatched to requesting client
3087     struct MsgReportPosition : public LocMsg {
3088         GnssAdapter& mAdapter;
3089         const UlpLocation mUlpLocation;
3090         const GpsLocationExtended mLocationExtended;
3091         loc_sess_status mStatus;
3092         LocPosTechMask mTechMask;
3093         GnssDataNotification mDataNotify;
3094         int mMsInWeek;
3095         bool mbIsDataValid;
3096         inline MsgReportPosition(GnssAdapter& adapter,
3097                                  const UlpLocation& ulpLocation,
3098                                  const GpsLocationExtended& locationExtended,
3099                                  loc_sess_status status,
3100                                  LocPosTechMask techMask,
3101                                  GnssDataNotification* pDataNotify,
3102                                  int msInWeek) :
3103             LocMsg(),
3104             mAdapter(adapter),
3105             mUlpLocation(ulpLocation),
3106             mLocationExtended(locationExtended),
3107             mStatus(status),
3108             mTechMask(techMask),
3109             mMsInWeek(msInWeek) {
3110                 memset(&mDataNotify, 0, sizeof(mDataNotify));
3111                 if (pDataNotify != nullptr) {
3112                     mDataNotify = *pDataNotify;
3113                     mbIsDataValid = true;
3114                 } else {
3115                     mbIsDataValid = false;
3116                 }
3117         }
3118         inline virtual void proc() const {
3119             // extract bug report info - this returns true if consumed by systemstatus
3120             SystemStatus* s = mAdapter.getSystemStatus();
3121             if ((nullptr != s) &&
3122                     ((LOC_SESS_SUCCESS == mStatus) || (LOC_SESS_INTERMEDIATE == mStatus))){
3123                 s->eventPosition(mUlpLocation, mLocationExtended);
3124             }
3125             mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask);
3126             if (true == mbIsDataValid) {
3127                 if (-1 != mMsInWeek) {
3128                     mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
3129                                                 mMsInWeek);
3130                 }
3131                 mAdapter.reportData((GnssDataNotification&)mDataNotify);
3132             }
3133         }
3134     };
3135 
3136     sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended,
3137                                   status, techMask,
3138                                   pDataNotify, msInWeek));
3139 }
3140 
3141 void
reportEnginePositionsEvent(unsigned int count,EngineLocationInfo * locationArr)3142 GnssAdapter::reportEnginePositionsEvent(unsigned int count,
3143                                         EngineLocationInfo* locationArr)
3144 {
3145     struct MsgReportEnginePositions : public LocMsg {
3146         GnssAdapter& mAdapter;
3147         unsigned int mCount;
3148         EngineLocationInfo mEngLocInfo[LOC_OUTPUT_ENGINE_COUNT];
3149         inline MsgReportEnginePositions(GnssAdapter& adapter,
3150                                         unsigned int count,
3151                                         EngineLocationInfo* locationArr) :
3152             LocMsg(),
3153             mAdapter(adapter),
3154             mCount(count) {
3155             if (mCount > LOC_OUTPUT_ENGINE_COUNT) {
3156                 mCount = LOC_OUTPUT_ENGINE_COUNT;
3157             }
3158             if (mCount > 0) {
3159                 memcpy(mEngLocInfo, locationArr, sizeof(EngineLocationInfo)*mCount);
3160             }
3161         }
3162         inline virtual void proc() const {
3163             mAdapter.reportEnginePositions(mCount, mEngLocInfo);
3164         }
3165     };
3166 
3167     sendMsg(new MsgReportEnginePositions(*this, count, locationArr));
3168 }
3169 
3170 bool
needReportForGnssClient(const UlpLocation & ulpLocation,enum loc_sess_status status,LocPosTechMask techMask)3171 GnssAdapter::needReportForGnssClient(const UlpLocation& ulpLocation,
3172                                      enum loc_sess_status status,
3173                                      LocPosTechMask techMask) {
3174     bool reported = false;
3175 
3176     // if engine hub is enabled, aka, any of the engine services is enabled,
3177     // then always output position reported by engine hub to requesting client
3178     if (true == initEngHubProxy()) {
3179         reported = true;
3180     } else {
3181         reported = LocApiBase::needReport(ulpLocation, status, techMask);
3182     }
3183     return reported;
3184 }
3185 
3186 bool
needReportForFlpClient(enum loc_sess_status status,LocPosTechMask techMask)3187 GnssAdapter::needReportForFlpClient(enum loc_sess_status status,
3188                                     LocPosTechMask techMask) {
3189     if ((status == LOC_SESS_INTERMEDIATE) &&
3190         !(techMask & LOC_POS_TECH_MASK_SENSORS) &&
3191         (!getAllowFlpNetworkFixes())) {
3192         return false;
3193     } else {
3194         return true;
3195     }
3196 }
3197 
3198 bool
isFlpClient(LocationCallbacks & locationCallbacks)3199 GnssAdapter::isFlpClient(LocationCallbacks& locationCallbacks)
3200 {
3201     return (locationCallbacks.gnssLocationInfoCb == nullptr &&
3202             locationCallbacks.gnssSvCb == nullptr &&
3203             locationCallbacks.gnssNmeaCb == nullptr &&
3204             locationCallbacks.gnssDataCb == nullptr &&
3205             locationCallbacks.gnssMeasurementsCb == nullptr);
3206 }
3207 
3208 void
reportPosition(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask)3209 GnssAdapter::reportPosition(const UlpLocation& ulpLocation,
3210                             const GpsLocationExtended& locationExtended,
3211                             enum loc_sess_status status,
3212                             LocPosTechMask techMask)
3213 {
3214     bool reportToGnssClient = needReportForGnssClient(ulpLocation, status, techMask);
3215     bool reportToFlpClient = needReportForFlpClient(status, techMask);
3216 
3217     if (reportToGnssClient || reportToFlpClient) {
3218         GnssLocationInfoNotification locationInfo = {};
3219         convertLocationInfo(locationInfo, locationExtended);
3220         convertLocation(locationInfo.location, ulpLocation, locationExtended, techMask);
3221 
3222         for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3223             if ((reportToFlpClient && isFlpClient(it->second)) ||
3224                     (reportToGnssClient && !isFlpClient(it->second))) {
3225                 if (nullptr != it->second.gnssLocationInfoCb) {
3226                     it->second.gnssLocationInfoCb(locationInfo);
3227                 } else if ((nullptr != it->second.engineLocationsInfoCb) &&
3228                         (false == initEngHubProxy())) {
3229                     // if engine hub is disabled, this is SPE fix from modem
3230                     // we need to mark one copy marked as fused and one copy marked as PPE
3231                     // and dispatch it to the engineLocationsInfoCb
3232                     GnssLocationInfoNotification engLocationsInfo[2];
3233                     engLocationsInfo[0] = locationInfo;
3234                     engLocationsInfo[0].locOutputEngType = LOC_OUTPUT_ENGINE_FUSED;
3235                     engLocationsInfo[0].flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT;
3236                     engLocationsInfo[1] = locationInfo;
3237                     it->second.engineLocationsInfoCb(2, engLocationsInfo);
3238                 } else if (nullptr != it->second.trackingCb) {
3239                     it->second.trackingCb(locationInfo.location);
3240                 }
3241             }
3242         }
3243 
3244         mGnssSvIdUsedInPosAvail = false;
3245         mGnssMbSvIdUsedInPosAvail = false;
3246         if (reportToGnssClient) {
3247             if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) {
3248                 mGnssSvIdUsedInPosAvail = true;
3249                 mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids;
3250                 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MULTIBAND) {
3251                     mGnssMbSvIdUsedInPosAvail = true;
3252                     mGnssMbSvIdUsedInPosition = locationExtended.gnss_mb_sv_used_ids;
3253                 }
3254             }
3255 
3256             // if engine hub is running and the fix is from sensor, e.g.: DRE,
3257             // inject DRE fix to modem
3258             if ((1 == ContextBase::mGps_conf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED) &&
3259                     (true == initEngHubProxy()) && (LOC_POS_TECH_MASK_SENSORS & techMask)) {
3260                 mLocApi->injectPosition(locationInfo, false);
3261             }
3262         }
3263     }
3264 
3265     if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
3266         !mTimeBasedTrackingSessions.empty()) {
3267         /*Only BlankNMEA sentence needs to be processed and sent, if both lat, long is 0 &
3268           horReliability is not set. */
3269         bool blank_fix = ((0 == ulpLocation.gpsLocation.latitude) &&
3270                           (0 == ulpLocation.gpsLocation.longitude) &&
3271                           (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability));
3272         uint8_t generate_nmea = (reportToGnssClient && status != LOC_SESS_FAILURE && !blank_fix);
3273         std::vector<std::string> nmeaArraystr;
3274         loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo,
3275                               generate_nmea, nmeaArraystr);
3276         stringstream ss;
3277         for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) {
3278             ss << *itor;
3279         }
3280         string s = ss.str();
3281         reportNmea(s.c_str(), s.length());
3282     }
3283 }
3284 
3285 void
reportEnginePositions(unsigned int count,const EngineLocationInfo * locationArr)3286 GnssAdapter::reportEnginePositions(unsigned int count,
3287                                    const EngineLocationInfo* locationArr)
3288 {
3289     bool needReportEnginePositions = false;
3290     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3291         if (nullptr != it->second.engineLocationsInfoCb) {
3292             needReportEnginePositions = true;
3293             break;
3294         }
3295     }
3296 
3297     GnssLocationInfoNotification locationInfo[LOC_OUTPUT_ENGINE_COUNT] = {};
3298     for (unsigned int i = 0; i < count; i++) {
3299         const EngineLocationInfo* engLocation = (locationArr+i);
3300         // if it is fused/default location, call reportPosition maintain legacy behavior
3301         if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) &&
3302             (LOC_OUTPUT_ENGINE_FUSED == engLocation->locationExtended.locOutputEngType)) {
3303             reportPosition(engLocation->location,
3304                            engLocation->locationExtended,
3305                            engLocation->sessionStatus,
3306                            engLocation->location.tech_mask);
3307         }
3308 
3309         if (needReportEnginePositions) {
3310             convertLocationInfo(locationInfo[i], engLocation->locationExtended);
3311             convertLocation(locationInfo[i].location,
3312                             engLocation->location,
3313                             engLocation->locationExtended,
3314                             engLocation->location.tech_mask);
3315         }
3316     }
3317 
3318     if (needReportEnginePositions) {
3319         for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3320             if (nullptr != it->second.engineLocationsInfoCb) {
3321                 it->second.engineLocationsInfoCb(count, locationInfo);
3322             }
3323         }
3324     }
3325 }
3326 
3327 void
reportSvEvent(const GnssSvNotification & svNotify,bool fromEngineHub)3328 GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify,
3329                            bool fromEngineHub)
3330 {
3331     if (!fromEngineHub) {
3332         mEngHubProxy->gnssReportSv(svNotify);
3333         if (true == initEngHubProxy()){
3334             return;
3335         }
3336     }
3337 
3338     struct MsgReportSv : public LocMsg {
3339         GnssAdapter& mAdapter;
3340         const GnssSvNotification mSvNotify;
3341         inline MsgReportSv(GnssAdapter& adapter,
3342                            const GnssSvNotification& svNotify) :
3343             LocMsg(),
3344             mAdapter(adapter),
3345             mSvNotify(svNotify) {}
3346         inline virtual void proc() const {
3347             mAdapter.reportSv((GnssSvNotification&)mSvNotify);
3348         }
3349     };
3350 
3351     sendMsg(new MsgReportSv(*this, svNotify));
3352 }
3353 
3354 void
reportSv(GnssSvNotification & svNotify)3355 GnssAdapter::reportSv(GnssSvNotification& svNotify)
3356 {
3357     int numSv = svNotify.count;
3358     int16_t gnssSvId = 0;
3359     uint64_t svUsedIdMask = 0;
3360     for (int i=0; i < numSv; i++) {
3361         svUsedIdMask = 0;
3362         gnssSvId = svNotify.gnssSvs[i].svId;
3363         GnssSignalTypeMask signalTypeMask = svNotify.gnssSvs[i].gnssSignalTypeMask;
3364         switch (svNotify.gnssSvs[i].type) {
3365             case GNSS_SV_TYPE_GPS:
3366                 if (mGnssSvIdUsedInPosAvail) {
3367                     if (mGnssMbSvIdUsedInPosAvail) {
3368                         switch (signalTypeMask) {
3369                         case GNSS_SIGNAL_GPS_L1CA:
3370                             svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l1ca_sv_used_ids_mask;
3371                             break;
3372                         case GNSS_SIGNAL_GPS_L1C:
3373                             svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l1c_sv_used_ids_mask;
3374                             break;
3375                         case GNSS_SIGNAL_GPS_L2:
3376                             svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l2_sv_used_ids_mask;
3377                             break;
3378                         case GNSS_SIGNAL_GPS_L5:
3379                             svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l5_sv_used_ids_mask;
3380                             break;
3381                         }
3382                     } else {
3383                         svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask;
3384                     }
3385                 }
3386                 break;
3387             case GNSS_SV_TYPE_GLONASS:
3388                 if (mGnssSvIdUsedInPosAvail) {
3389                     if (mGnssMbSvIdUsedInPosAvail) {
3390                         switch (signalTypeMask) {
3391                         case GNSS_SIGNAL_GLONASS_G1:
3392                             svUsedIdMask = mGnssMbSvIdUsedInPosition.glo_g1_sv_used_ids_mask;
3393                             break;
3394                         case GNSS_SIGNAL_GLONASS_G2:
3395                             svUsedIdMask = mGnssMbSvIdUsedInPosition.glo_g2_sv_used_ids_mask;
3396                             break;
3397                         }
3398                     } else {
3399                         svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask;
3400                     }
3401                 }
3402                 break;
3403             case GNSS_SV_TYPE_BEIDOU:
3404                 if (mGnssSvIdUsedInPosAvail) {
3405                     if (mGnssMbSvIdUsedInPosAvail) {
3406                         switch (signalTypeMask) {
3407                         case GNSS_SIGNAL_BEIDOU_B1I:
3408                             svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b1i_sv_used_ids_mask;
3409                             break;
3410                         case GNSS_SIGNAL_BEIDOU_B1C:
3411                             svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b1c_sv_used_ids_mask;
3412                             break;
3413                         case GNSS_SIGNAL_BEIDOU_B2I:
3414                             svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2i_sv_used_ids_mask;
3415                             break;
3416                         case GNSS_SIGNAL_BEIDOU_B2AI:
3417                             svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2ai_sv_used_ids_mask;
3418                             break;
3419                         case GNSS_SIGNAL_BEIDOU_B2AQ:
3420                             svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2aq_sv_used_ids_mask;
3421                             break;
3422                         }
3423                     } else {
3424                         svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask;
3425                     }
3426                 }
3427                 break;
3428             case GNSS_SV_TYPE_GALILEO:
3429                 if (mGnssSvIdUsedInPosAvail) {
3430                     if (mGnssMbSvIdUsedInPosAvail) {
3431                         switch (signalTypeMask) {
3432                         case GNSS_SIGNAL_GALILEO_E1:
3433                             svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e1_sv_used_ids_mask;
3434                             break;
3435                         case GNSS_SIGNAL_GALILEO_E5A:
3436                             svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e5a_sv_used_ids_mask;
3437                             break;
3438                         case GNSS_SIGNAL_GALILEO_E5B:
3439                             svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e5b_sv_used_ids_mask;
3440                             break;
3441                         }
3442                     } else {
3443                         svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask;
3444                     }
3445                 }
3446                 break;
3447             case GNSS_SV_TYPE_QZSS:
3448                 if (mGnssSvIdUsedInPosAvail) {
3449                     if (mGnssMbSvIdUsedInPosAvail) {
3450                         switch (signalTypeMask) {
3451                         case GNSS_SIGNAL_QZSS_L1CA:
3452                             svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l1ca_sv_used_ids_mask;
3453                             break;
3454                         case GNSS_SIGNAL_QZSS_L1S:
3455                             svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l1s_sv_used_ids_mask;
3456                             break;
3457                         case GNSS_SIGNAL_QZSS_L2:
3458                             svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l2_sv_used_ids_mask;
3459                             break;
3460                         case GNSS_SIGNAL_QZSS_L5:
3461                             svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l5_sv_used_ids_mask;
3462                             break;
3463                         }
3464                     } else {
3465                         svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask;
3466                     }
3467                 }
3468                 // QZSS SV id's need to reported as it is to framework, since
3469                 // framework expects it as it is. See GnssStatus.java.
3470                 // SV id passed to here by LocApi is 1-based.
3471                 svNotify.gnssSvs[i].svId += (QZSS_SV_PRN_MIN - 1);
3472                 break;
3473             case GNSS_SV_TYPE_NAVIC:
3474                 if (mGnssSvIdUsedInPosAvail) {
3475                     svUsedIdMask = mGnssSvIdUsedInPosition.navic_sv_used_ids_mask;
3476                 }
3477                 break;
3478             default:
3479                 svUsedIdMask = 0;
3480                 break;
3481         }
3482 
3483         // If SV ID was used in previous position fix, then set USED_IN_FIX
3484         // flag, else clear the USED_IN_FIX flag.
3485         if (svUsedIdMask & (1 << (gnssSvId - 1))) {
3486             svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
3487         }
3488     }
3489 
3490     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3491         if (nullptr != it->second.gnssSvCb) {
3492             it->second.gnssSvCb(svNotify);
3493         }
3494     }
3495 
3496     if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
3497         !mTimeBasedTrackingSessions.empty()) {
3498         std::vector<std::string> nmeaArraystr;
3499         loc_nmea_generate_sv(svNotify, nmeaArraystr);
3500         stringstream ss;
3501         for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) {
3502             ss << *itor;
3503         }
3504         string s = ss.str();
3505         reportNmea(s.c_str(), s.length());
3506     }
3507 
3508     mGnssSvIdUsedInPosAvail = false;
3509 }
3510 
3511 void
reportNmeaEvent(const char * nmea,size_t length)3512 GnssAdapter::reportNmeaEvent(const char* nmea, size_t length)
3513 {
3514     if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
3515         !loc_nmea_is_debug(nmea, length)) {
3516         return;
3517     }
3518 
3519     struct MsgReportNmea : public LocMsg {
3520         GnssAdapter& mAdapter;
3521         const char* mNmea;
3522         size_t mLength;
3523         inline MsgReportNmea(GnssAdapter& adapter,
3524                              const char* nmea,
3525                              size_t length) :
3526             LocMsg(),
3527             mAdapter(adapter),
3528             mNmea(new char[length+1]),
3529             mLength(length) {
3530                 if (mNmea == nullptr) {
3531                     LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
3532                     return;
3533                 }
3534                 strlcpy((char*)mNmea, nmea, length+1);
3535             }
3536         inline virtual ~MsgReportNmea()
3537         {
3538             delete[] mNmea;
3539         }
3540         inline virtual void proc() const {
3541             // extract bug report info - this returns true if consumed by systemstatus
3542             bool ret = false;
3543             SystemStatus* s = mAdapter.getSystemStatus();
3544             if (nullptr != s) {
3545                 ret = s->setNmeaString(mNmea, mLength);
3546             }
3547             if (false == ret) {
3548                 // forward NMEA message to upper layer
3549                 mAdapter.reportNmea(mNmea, mLength);
3550             }
3551         }
3552     };
3553 
3554     sendMsg(new MsgReportNmea(*this, nmea, length));
3555 }
3556 
3557 void
reportNmea(const char * nmea,size_t length)3558 GnssAdapter::reportNmea(const char* nmea, size_t length)
3559 {
3560     GnssNmeaNotification nmeaNotification = {};
3561     nmeaNotification.size = sizeof(GnssNmeaNotification);
3562 
3563     struct timeval tv;
3564     gettimeofday(&tv, (struct timezone *) NULL);
3565     int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
3566     nmeaNotification.timestamp = now;
3567     nmeaNotification.nmea = nmea;
3568     nmeaNotification.length = length;
3569 
3570     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3571         if (nullptr != it->second.gnssNmeaCb) {
3572             it->second.gnssNmeaCb(nmeaNotification);
3573         }
3574     }
3575 }
3576 
3577 void
reportDataEvent(const GnssDataNotification & dataNotify,int msInWeek)3578 GnssAdapter::reportDataEvent(const GnssDataNotification& dataNotify,
3579                              int msInWeek)
3580 {
3581     struct MsgReportData : public LocMsg {
3582         GnssAdapter& mAdapter;
3583         GnssDataNotification mDataNotify;
3584         int mMsInWeek;
3585         inline MsgReportData(GnssAdapter& adapter,
3586             const GnssDataNotification& dataNotify,
3587             int msInWeek) :
3588             LocMsg(),
3589             mAdapter(adapter),
3590             mDataNotify(dataNotify),
3591             mMsInWeek(msInWeek) {
3592         }
3593         inline virtual void proc() const {
3594             if (-1 != mMsInWeek) {
3595                 mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
3596                                             mMsInWeek);
3597             }
3598             mAdapter.reportData((GnssDataNotification&)mDataNotify);
3599         }
3600     };
3601 
3602     sendMsg(new MsgReportData(*this, dataNotify, msInWeek));
3603 }
3604 
3605 void
reportData(GnssDataNotification & dataNotify)3606 GnssAdapter::reportData(GnssDataNotification& dataNotify)
3607 {
3608     for (int sig = 0; sig < GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES; sig++) {
3609         if (GNSS_LOC_DATA_JAMMER_IND_BIT ==
3610             (dataNotify.gnssDataMask[sig] & GNSS_LOC_DATA_JAMMER_IND_BIT)) {
3611             LOC_LOGv("jammerInd[%d]=%f", sig, dataNotify.jammerInd[sig]);
3612         }
3613         if (GNSS_LOC_DATA_AGC_BIT ==
3614             (dataNotify.gnssDataMask[sig] & GNSS_LOC_DATA_AGC_BIT)) {
3615             LOC_LOGv("agc[%d]=%f", sig, dataNotify.agc[sig]);
3616         }
3617     }
3618     for (auto it = mClientData.begin(); it != mClientData.end(); ++it) {
3619         if (nullptr != it->second.gnssDataCb) {
3620             it->second.gnssDataCb(dataNotify);
3621         }
3622     }
3623 }
3624 
3625 bool
requestNiNotifyEvent(const GnssNiNotification & notify,const void * data,const LocInEmergency emergencyState)3626 GnssAdapter::requestNiNotifyEvent(const GnssNiNotification &notify, const void* data,
3627                                   const LocInEmergency emergencyState)
3628 {
3629     LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d"
3630              "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s",
3631              __func__, notify.type, notify.timeout, notify.timeoutResponse,
3632              notify.requestor, notify.requestorEncoding,
3633              notify.message, notify.messageEncoding, notify.extras);
3634 
3635     struct MsgReportNiNotify : public LocMsg {
3636         GnssAdapter& mAdapter;
3637         LocApiBase& mApi;
3638         const GnssNiNotification mNotify;
3639         const void* mData;
3640         const LocInEmergency mEmergencyState;
3641         inline MsgReportNiNotify(GnssAdapter& adapter,
3642                                  LocApiBase& api,
3643                                  const GnssNiNotification& notify,
3644                                  const void* data,
3645                                  const LocInEmergency emergencyState) :
3646             LocMsg(),
3647             mAdapter(adapter),
3648             mApi(api),
3649             mNotify(notify),
3650             mData(data),
3651             mEmergencyState(emergencyState) {}
3652         inline virtual void proc() const {
3653             bool bIsInEmergency = false;
3654             bool bInformNiAccept = false;
3655 
3656             bIsInEmergency = ((LOC_IN_EMERGENCY_UNKNOWN == mEmergencyState) &&
3657                     mAdapter.getE911State()) ||                // older modems
3658                     (LOC_IN_EMERGENCY_SET == mEmergencyState); // newer modems
3659 
3660             if (GNSS_NI_TYPE_EMERGENCY_SUPL == mNotify.type) {
3661                 bInformNiAccept = bIsInEmergency ||
3662                         (GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO == ContextBase::mGps_conf.SUPL_ES);
3663 
3664                 if (bInformNiAccept) {
3665                     mAdapter.requestNiNotify(mNotify, mData, bInformNiAccept);
3666                 } else {
3667                     mApi.informNiResponse(GNSS_NI_RESPONSE_DENY, mData);
3668                 }
3669             } else if (GNSS_NI_TYPE_CONTROL_PLANE == mNotify.type) {
3670                 if (bIsInEmergency && (1 == ContextBase::mGps_conf.CP_MTLR_ES)) {
3671                     mApi.informNiResponse(GNSS_NI_RESPONSE_ACCEPT, mData);
3672                 }
3673                 else {
3674                     mAdapter.requestNiNotify(mNotify, mData, false);
3675                 }
3676             } else {
3677                 mAdapter.requestNiNotify(mNotify, mData, false);
3678             }
3679         }
3680     };
3681 
3682     sendMsg(new MsgReportNiNotify(*this, *mLocApi, notify, data, emergencyState));
3683 
3684     return true;
3685 }
3686 
3687 void
reportLocationSystemInfoEvent(const LocationSystemInfo & locationSystemInfo)3688 GnssAdapter::reportLocationSystemInfoEvent(const LocationSystemInfo & locationSystemInfo) {
3689 
3690     // send system info to engine hub
3691     mEngHubProxy->gnssReportSystemInfo(locationSystemInfo);
3692 
3693     struct MsgLocationSystemInfo : public LocMsg {
3694         GnssAdapter& mAdapter;
3695         LocationSystemInfo mSystemInfo;
3696         inline MsgLocationSystemInfo(GnssAdapter& adapter,
3697             const LocationSystemInfo& systemInfo) :
3698             LocMsg(),
3699             mAdapter(adapter),
3700             mSystemInfo(systemInfo) {}
3701         inline virtual void proc() const {
3702             mAdapter.reportLocationSystemInfo(mSystemInfo);
3703         }
3704     };
3705 
3706     sendMsg(new MsgLocationSystemInfo(*this, locationSystemInfo));
3707 }
3708 
3709 void
reportLocationSystemInfo(const LocationSystemInfo & locationSystemInfo)3710 GnssAdapter::reportLocationSystemInfo(const LocationSystemInfo & locationSystemInfo) {
3711     // save the info into the master copy piece by piece, as other system info
3712     // may come at different time
3713     if (locationSystemInfo.systemInfoMask & LOCATION_SYS_INFO_LEAP_SECOND) {
3714         mLocSystemInfo.systemInfoMask |= LOCATION_SYS_INFO_LEAP_SECOND;
3715 
3716         const LeapSecondSystemInfo &srcLeapSecondSysInfo = locationSystemInfo.leapSecondSysInfo;
3717         LeapSecondSystemInfo &dstLeapSecondSysInfo = mLocSystemInfo.leapSecondSysInfo;
3718         if (srcLeapSecondSysInfo.leapSecondInfoMask &
3719                 LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT) {
3720             dstLeapSecondSysInfo.leapSecondInfoMask |=
3721                 LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT;
3722             dstLeapSecondSysInfo.leapSecondCurrent = srcLeapSecondSysInfo.leapSecondCurrent;
3723         }
3724         // once leap second change event is complete, modem may send up event invalidate the leap
3725         // second change info while AP is still processing report during leap second transition
3726         // so, we choose to keep this info around even though it is old
3727         if (srcLeapSecondSysInfo.leapSecondInfoMask & LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT) {
3728             dstLeapSecondSysInfo.leapSecondInfoMask |= LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT;
3729             dstLeapSecondSysInfo.leapSecondChangeInfo = srcLeapSecondSysInfo.leapSecondChangeInfo;
3730         }
3731     }
3732 
3733     // we received new info, inform client of the newly received info
3734     if (locationSystemInfo.systemInfoMask) {
3735         for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3736             if (it->second.locationSystemInfoCb != nullptr) {
3737                 it->second.locationSystemInfoCb(locationSystemInfo);
3738             }
3739         }
3740     }
3741 }
3742 
niThreadProc(void * args)3743 static void* niThreadProc(void *args)
3744 {
3745     NiSession* pSession = (NiSession*)args;
3746     int rc = 0;          /* return code from pthread calls */
3747 
3748     struct timespec present_time;
3749     struct timespec expire_time;
3750 
3751     pthread_mutex_lock(&pSession->tLock);
3752     /* Calculate absolute expire time */
3753     clock_gettime(CLOCK_MONOTONIC, &present_time);
3754     expire_time.tv_sec  = present_time.tv_sec + pSession->respTimeLeft;
3755     expire_time.tv_nsec = present_time.tv_nsec;
3756     LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec",
3757              __func__, (long)expire_time.tv_sec, pSession->respTimeLeft);
3758 
3759     while (!pSession->respRecvd) {
3760         rc = pthread_cond_timedwait(&pSession->tCond,
3761                                     &pSession->tLock,
3762                                     &expire_time);
3763         if (rc == ETIMEDOUT) {
3764             pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE;
3765             LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d",
3766                      __func__, rc);
3767             break;
3768         }
3769     }
3770     LOC_LOGD("%s]: Java layer has sent us a user response and return value from "
3771              "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp);
3772     pSession->respRecvd = false; /* Reset the user response flag for the next session*/
3773 
3774     // adding this check to support modem restart, in which case, we need the thread
3775     // to exit without calling sending data. We made sure that rawRequest is NULL in
3776     // loc_eng_ni_reset_on_engine_restart()
3777     GnssAdapter* adapter = pSession->adapter;
3778     GnssNiResponse resp;
3779     void* rawRequest = NULL;
3780     bool sendResponse = false;
3781 
3782     if (NULL != pSession->rawRequest) {
3783         if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) {
3784             resp = pSession->resp;
3785             rawRequest = pSession->rawRequest;
3786             sendResponse = true;
3787         } else {
3788             free(pSession->rawRequest);
3789         }
3790         pSession->rawRequest = NULL;
3791     }
3792     pthread_mutex_unlock(&pSession->tLock);
3793 
3794     pSession->respTimeLeft = 0;
3795     pSession->reqID = 0;
3796 
3797     if (sendResponse) {
3798         adapter->gnssNiResponseCommand(resp, rawRequest);
3799     }
3800 
3801     return NULL;
3802 }
3803 
3804 bool
requestNiNotify(const GnssNiNotification & notify,const void * data,const bool bInformNiAccept)3805 GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data,
3806                              const bool bInformNiAccept)
3807 {
3808     NiSession* pSession = NULL;
3809     gnssNiCallback gnssNiCb = nullptr;
3810 
3811     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3812         if (nullptr != it->second.gnssNiCb) {
3813             gnssNiCb = it->second.gnssNiCb;
3814             break;
3815         }
3816     }
3817     if (nullptr == gnssNiCb) {
3818         if (GNSS_NI_TYPE_EMERGENCY_SUPL == notify.type) {
3819             if (bInformNiAccept) {
3820                 mLocApi->informNiResponse(GNSS_NI_RESPONSE_ACCEPT, data);
3821                 NiData& niData = getNiData();
3822                 // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
3823                 if (NULL != niData.session.rawRequest) {
3824                     pthread_mutex_lock(&niData.session.tLock);
3825                     niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
3826                     niData.session.respRecvd = true;
3827                     pthread_cond_signal(&niData.session.tCond);
3828                     pthread_mutex_unlock(&niData.session.tLock);
3829                 }
3830             }
3831         }
3832         EXIT_LOG(%s, "no clients with gnssNiCb.");
3833         return false;
3834     }
3835 
3836     if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) {
3837         if (NULL != mNiData.sessionEs.rawRequest) {
3838             LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d",
3839                      __func__, notify.type);
3840             if (NULL != data) {
3841                 free((void*)data);
3842             }
3843         } else {
3844             pSession = &mNiData.sessionEs;
3845         }
3846     } else {
3847         if (NULL != mNiData.session.rawRequest ||
3848             NULL != mNiData.sessionEs.rawRequest) {
3849             LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d",
3850                      __func__, notify.type);
3851             if (NULL != data) {
3852                 free((void*)data);
3853             }
3854         } else {
3855             pSession = &mNiData.session;
3856         }
3857     }
3858 
3859     if (pSession) {
3860         /* Save request */
3861         pSession->rawRequest = (void*)data;
3862         pSession->reqID = ++mNiData.reqIDCounter;
3863         pSession->adapter = this;
3864 
3865         int sessionId = pSession->reqID;
3866 
3867         /* For robustness, spawn a thread at this point to timeout to clear up the notification
3868          * status, even though the OEM layer in java does not do so.
3869          **/
3870         pSession->respTimeLeft =
3871              5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME);
3872 
3873         int rc = 0;
3874         rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession);
3875         if (rc) {
3876             LOC_LOGE("%s]: Loc NI thread is not created.", __func__);
3877         }
3878         rc = pthread_detach(pSession->thread);
3879         if (rc) {
3880             LOC_LOGE("%s]: Loc NI thread is not detached.", __func__);
3881         }
3882 
3883         if (nullptr != gnssNiCb) {
3884             gnssNiCb(sessionId, notify);
3885         }
3886     }
3887 
3888     return true;
3889 }
3890 
3891 void
reportGnssMeasurementsEvent(const GnssMeasurements & gnssMeasurements,int msInWeek)3892 GnssAdapter::reportGnssMeasurementsEvent(const GnssMeasurements& gnssMeasurements,
3893                                             int msInWeek)
3894 {
3895     LOC_LOGD("%s]: msInWeek=%d", __func__, msInWeek);
3896 
3897     if (0 != gnssMeasurements.gnssMeasNotification.count) {
3898         struct MsgReportGnssMeasurementData : public LocMsg {
3899             GnssAdapter& mAdapter;
3900             GnssMeasurements mGnssMeasurements;
3901             GnssMeasurementsNotification mMeasurementsNotify;
3902             inline MsgReportGnssMeasurementData(GnssAdapter& adapter,
3903                                                 const GnssMeasurements& gnssMeasurements,
3904                                                 int msInWeek) :
3905                     LocMsg(),
3906                     mAdapter(adapter),
3907                     mMeasurementsNotify(gnssMeasurements.gnssMeasNotification) {
3908                 if (-1 != msInWeek) {
3909                     mAdapter.getAgcInformation(mMeasurementsNotify, msInWeek);
3910                 }
3911             }
3912             inline virtual void proc() const {
3913                 mAdapter.reportGnssMeasurementData(mMeasurementsNotify);
3914             }
3915         };
3916 
3917         sendMsg(new MsgReportGnssMeasurementData(*this, gnssMeasurements, msInWeek));
3918     }
3919     mEngHubProxy->gnssReportSvMeasurement(gnssMeasurements.gnssSvMeasurementSet);
3920 }
3921 
3922 void
reportGnssMeasurementData(const GnssMeasurementsNotification & measurements)3923 GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurements)
3924 {
3925     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3926         if (nullptr != it->second.gnssMeasurementsCb) {
3927             it->second.gnssMeasurementsCb(measurements);
3928         }
3929     }
3930 }
3931 
3932 void
reportSvPolynomialEvent(GnssSvPolynomial & svPolynomial)3933 GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial)
3934 {
3935     LOC_LOGD("%s]: ", __func__);
3936     mEngHubProxy->gnssReportSvPolynomial(svPolynomial);
3937 }
3938 
3939 void
reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris)3940 GnssAdapter::reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris)
3941 {
3942     LOC_LOGD("%s]:", __func__);
3943     mEngHubProxy->gnssReportSvEphemeris(svEphemeris);
3944 }
3945 
3946 
3947 bool
requestOdcpiEvent(OdcpiRequestInfo & request)3948 GnssAdapter::requestOdcpiEvent(OdcpiRequestInfo& request)
3949 {
3950     struct MsgRequestOdcpi : public LocMsg {
3951         GnssAdapter& mAdapter;
3952         OdcpiRequestInfo mOdcpiRequest;
3953         inline MsgRequestOdcpi(GnssAdapter& adapter, OdcpiRequestInfo& request) :
3954                 LocMsg(),
3955                 mAdapter(adapter),
3956                 mOdcpiRequest(request) {}
3957         inline virtual void proc() const {
3958             mAdapter.requestOdcpi(mOdcpiRequest);
3959         }
3960     };
3961 
3962     sendMsg(new MsgRequestOdcpi(*this, request));
3963     return true;
3964 }
3965 
requestOdcpi(const OdcpiRequestInfo & request)3966 void GnssAdapter::requestOdcpi(const OdcpiRequestInfo& request)
3967 {
3968     if (nullptr != mOdcpiRequestCb) {
3969         LOC_LOGd("request: type %d, tbf %d, isEmergency %d"
3970                  " requestActive: %d timerActive: %d",
3971                  request.type, request.tbfMillis, request.isEmergencyMode,
3972                  mOdcpiRequestActive, mOdcpiTimer.isActive());
3973         // ODCPI START and ODCPI STOP from modem can come in quick succession
3974         // so the mOdcpiTimer helps avoid spamming the framework as well as
3975         // extending the odcpi session past 30 seconds if needed
3976         if (ODCPI_REQUEST_TYPE_START == request.type) {
3977             if (false == mOdcpiRequestActive && false == mOdcpiTimer.isActive()) {
3978                 mOdcpiRequestCb(request);
3979                 mOdcpiRequestActive = true;
3980                 mOdcpiTimer.start();
3981             // if the current active odcpi session is non-emergency, and the new
3982             // odcpi request is emergency, replace the odcpi request with new request
3983             // and restart the timer
3984             } else if (false == mOdcpiRequest.isEmergencyMode &&
3985                        true == request.isEmergencyMode) {
3986                 mOdcpiRequestCb(request);
3987                 mOdcpiRequestActive = true;
3988                 if (true == mOdcpiTimer.isActive()) {
3989                     mOdcpiTimer.restart();
3990                 } else {
3991                     mOdcpiTimer.start();
3992                 }
3993             // if ODCPI request is not active but the timer is active, then
3994             // just update the active state and wait for timer to expire
3995             // before requesting new ODCPI to avoid spamming ODCPI requests
3996             } else if (false == mOdcpiRequestActive && true == mOdcpiTimer.isActive()) {
3997                 mOdcpiRequestActive = true;
3998             }
3999             mOdcpiRequest = request;
4000         // the request is being stopped, but allow timer to expire first
4001         // before stopping the timer just in case more ODCPI requests come
4002         // to avoid spamming more odcpi requests to the framework
4003         } else {
4004             mOdcpiRequestActive = false;
4005         }
4006     } else {
4007         LOC_LOGw("ODCPI request not supported");
4008     }
4009 }
4010 
reportDeleteAidingDataEvent(GnssAidingData & aidingData)4011 bool GnssAdapter::reportDeleteAidingDataEvent(GnssAidingData& aidingData)
4012 {
4013     LOC_LOGD("%s]:", __func__);
4014     mEngHubProxy->gnssDeleteAidingData(aidingData);
4015     return true;
4016 }
4017 
reportKlobucharIonoModelEvent(GnssKlobucharIonoModel & ionoModel)4018 bool GnssAdapter::reportKlobucharIonoModelEvent(GnssKlobucharIonoModel & ionoModel)
4019 {
4020     LOC_LOGD("%s]:", __func__);
4021     mEngHubProxy->gnssReportKlobucharIonoModel(ionoModel);
4022     return true;
4023 }
4024 
reportGnssAdditionalSystemInfoEvent(GnssAdditionalSystemInfo & additionalSystemInfo)4025 bool GnssAdapter::reportGnssAdditionalSystemInfoEvent(
4026         GnssAdditionalSystemInfo & additionalSystemInfo)
4027 {
4028     LOC_LOGD("%s]:", __func__);
4029     mEngHubProxy->gnssReportAdditionalSystemInfo(additionalSystemInfo);
4030     return true;
4031 }
4032 
initOdcpiCommand(const OdcpiRequestCallback & callback)4033 void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback)
4034 {
4035     struct MsgInitOdcpi : public LocMsg {
4036         GnssAdapter& mAdapter;
4037         OdcpiRequestCallback mOdcpiCb;
4038         inline MsgInitOdcpi(GnssAdapter& adapter,
4039                 const OdcpiRequestCallback& callback) :
4040                 LocMsg(),
4041                 mAdapter(adapter),
4042                 mOdcpiCb(callback) {}
4043         inline virtual void proc() const {
4044             mAdapter.initOdcpi(mOdcpiCb);
4045         }
4046     };
4047 
4048     sendMsg(new MsgInitOdcpi(*this, callback));
4049 }
4050 
initOdcpi(const OdcpiRequestCallback & callback)4051 void GnssAdapter::initOdcpi(const OdcpiRequestCallback& callback)
4052 {
4053     mOdcpiRequestCb = callback;
4054 
4055     /* Register for WIFI request */
4056     updateEvtMask(LOC_API_ADAPTER_BIT_REQUEST_WIFI,
4057             LOC_REGISTRATION_MASK_ENABLED);
4058 }
4059 
injectOdcpiCommand(const Location & location)4060 void GnssAdapter::injectOdcpiCommand(const Location& location)
4061 {
4062     struct MsgInjectOdcpi : public LocMsg {
4063         GnssAdapter& mAdapter;
4064         Location mLocation;
4065         inline MsgInjectOdcpi(GnssAdapter& adapter, const Location& location) :
4066                 LocMsg(),
4067                 mAdapter(adapter),
4068                 mLocation(location) {}
4069         inline virtual void proc() const {
4070             mAdapter.injectOdcpi(mLocation);
4071         }
4072     };
4073 
4074     sendMsg(new MsgInjectOdcpi(*this, location));
4075 }
4076 
injectOdcpi(const Location & location)4077 void GnssAdapter::injectOdcpi(const Location& location)
4078 {
4079     LOC_LOGd("ODCPI Injection: requestActive: %d timerActive: %d"
4080              "lat %.7f long %.7f",
4081             mOdcpiRequestActive, mOdcpiTimer.isActive(),
4082             location.latitude, location.longitude);
4083 
4084     mLocApi->injectPosition(location, true);
4085 }
4086 
4087 // Called in the context of LocTimer thread
timeOutCallback()4088 void OdcpiTimer::timeOutCallback()
4089 {
4090     if (nullptr != mAdapter) {
4091         mAdapter->odcpiTimerExpireEvent();
4092     }
4093 }
4094 
4095 // Called in the context of LocTimer thread
odcpiTimerExpireEvent()4096 void GnssAdapter::odcpiTimerExpireEvent()
4097 {
4098     struct MsgOdcpiTimerExpire : public LocMsg {
4099         GnssAdapter& mAdapter;
4100         inline MsgOdcpiTimerExpire(GnssAdapter& adapter) :
4101                 LocMsg(),
4102                 mAdapter(adapter) {}
4103         inline virtual void proc() const {
4104             mAdapter.odcpiTimerExpire();
4105         }
4106     };
4107     sendMsg(new MsgOdcpiTimerExpire(*this));
4108 }
odcpiTimerExpire()4109 void GnssAdapter::odcpiTimerExpire()
4110 {
4111     LOC_LOGd("requestActive: %d timerActive: %d",
4112             mOdcpiRequestActive, mOdcpiTimer.isActive());
4113 
4114     // if ODCPI request is still active after timer
4115     // expires, request again and restart timer
4116     if (mOdcpiRequestActive) {
4117         mOdcpiRequestCb(mOdcpiRequest);
4118         mOdcpiTimer.restart();
4119     } else {
4120         mOdcpiTimer.stop();
4121     }
4122 }
4123 
4124 void
invokeGnssEnergyConsumedCallback(uint64_t energyConsumedSinceFirstBoot)4125 GnssAdapter::invokeGnssEnergyConsumedCallback(uint64_t energyConsumedSinceFirstBoot) {
4126     if (mGnssEnergyConsumedCb) {
4127         mGnssEnergyConsumedCb(energyConsumedSinceFirstBoot);
4128         mGnssEnergyConsumedCb = nullptr;
4129     }
4130 }
4131 
4132 bool
reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot)4133 GnssAdapter::reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot){
4134     LOC_LOGD("%s]: %" PRIu64 " ", __func__, energyConsumedSinceFirstBoot);
4135 
4136     struct MsgReportGnssGnssEngEnergyConsumed : public LocMsg {
4137         GnssAdapter& mAdapter;
4138         uint64_t mGnssEnergyConsumedSinceFirstBoot;
4139         inline MsgReportGnssGnssEngEnergyConsumed(GnssAdapter& adapter,
4140                                                   uint64_t energyConsumed) :
4141                 LocMsg(),
4142                 mAdapter(adapter),
4143                 mGnssEnergyConsumedSinceFirstBoot(energyConsumed) {}
4144         inline virtual void proc() const {
4145             mAdapter.invokeGnssEnergyConsumedCallback(mGnssEnergyConsumedSinceFirstBoot);
4146         }
4147     };
4148 
4149     sendMsg(new MsgReportGnssGnssEngEnergyConsumed(*this, energyConsumedSinceFirstBoot));
4150     return true;
4151 }
4152 
initDefaultAgps()4153 void GnssAdapter::initDefaultAgps() {
4154     LOC_LOGD("%s]: ", __func__);
4155 
4156     void *handle = nullptr;
4157     if ((handle = dlopen("libloc_net_iface.so", RTLD_NOW)) == nullptr) {
4158         LOC_LOGD("%s]: libloc_net_iface.so not found !", __func__);
4159         return;
4160     }
4161 
4162     LocAgpsGetAgpsCbInfo getAgpsCbInfo = (LocAgpsGetAgpsCbInfo)
4163             dlsym(handle, "LocNetIfaceAgps_getAgpsCbInfo");
4164     if (getAgpsCbInfo == nullptr) {
4165         LOC_LOGE("%s]: Failed to get method LocNetIfaceAgps_getStatusCb", __func__);
4166         dlclose(handle);
4167         return;
4168     }
4169 
4170     AgpsCbInfo& cbInfo = getAgpsCbInfo(agpsOpenResultCb, agpsCloseResultCb, this);
4171 
4172     if (cbInfo.statusV4Cb == nullptr) {
4173         LOC_LOGE("%s]: statusV4Cb is nullptr!", __func__);
4174         dlclose(handle);
4175         return;
4176     }
4177 
4178     initAgps(cbInfo);
4179 }
4180 
initDefaultAgpsCommand()4181 void GnssAdapter::initDefaultAgpsCommand() {
4182     LOC_LOGD("%s]: ", __func__);
4183 
4184     struct MsgInitDefaultAgps : public LocMsg {
4185         GnssAdapter& mAdapter;
4186         inline MsgInitDefaultAgps(GnssAdapter& adapter) :
4187             LocMsg(),
4188             mAdapter(adapter) {
4189             }
4190         inline virtual void proc() const {
4191             mAdapter.initDefaultAgps();
4192         }
4193     };
4194 
4195     sendMsg(new MsgInitDefaultAgps(*this));
4196 }
4197 
4198 /* INIT LOC AGPS MANAGER */
4199 
initAgps(const AgpsCbInfo & cbInfo)4200 void GnssAdapter::initAgps(const AgpsCbInfo& cbInfo) {
4201     LOC_LOGD("%s]:cbInfo.atlType - %d", __func__, cbInfo.atlType);
4202 
4203     if (!((ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSB) ||
4204             (ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSA))) {
4205         return;
4206     }
4207 
4208     mAgpsManager.createAgpsStateMachines(cbInfo);
4209     /* Register for AGPS event mask */
4210     updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST,
4211             LOC_REGISTRATION_MASK_ENABLED);
4212 }
4213 
initAgpsCommand(const AgpsCbInfo & cbInfo)4214 void GnssAdapter::initAgpsCommand(const AgpsCbInfo& cbInfo){
4215     LOC_LOGI("GnssAdapter::initAgpsCommand");
4216 
4217     /* Message to initialize AGPS module */
4218     struct AgpsMsgInit: public LocMsg {
4219         const AgpsCbInfo mCbInfo;
4220         GnssAdapter& mAdapter;
4221 
4222         inline AgpsMsgInit(const AgpsCbInfo& cbInfo,
4223                 GnssAdapter& adapter) :
4224                 LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) {
4225             LOC_LOGV("AgpsMsgInit");
4226         }
4227 
4228         inline virtual void proc() const {
4229             LOC_LOGV("AgpsMsgInit::proc()");
4230             mAdapter.initAgps(mCbInfo);
4231         }
4232     };
4233 
4234     /* Send message to initialize AGPS Manager */
4235     sendMsg(new AgpsMsgInit(cbInfo, *this));
4236 }
4237 
initNfwCommand(const NfwCbInfo & cbInfo)4238 void GnssAdapter::initNfwCommand(const NfwCbInfo& cbInfo) {
4239     LOC_LOGi("GnssAdapter::initNfwCommand");
4240 
4241     /* Message to initialize NFW */
4242     struct MsgInitNfw : public LocMsg {
4243         const NfwCbInfo mCbInfo;
4244         GnssAdapter& mAdapter;
4245 
4246         inline MsgInitNfw(const NfwCbInfo& cbInfo,
4247             GnssAdapter& adapter) :
4248             LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) {
4249             LOC_LOGv("MsgInitNfw");
4250         }
4251 
4252         inline virtual void proc() const {
4253             LOC_LOGv("MsgInitNfw::proc()");
4254             mAdapter.initNfw(mCbInfo);
4255         }
4256     };
4257 
4258     /* Send message to initialize NFW */
4259     sendMsg(new MsgInitNfw(cbInfo, *this));
4260 }
4261 
reportNfwNotificationEvent(GnssNfwNotification & notification)4262 void GnssAdapter::reportNfwNotificationEvent(GnssNfwNotification& notification) {
4263     LOC_LOGi("GnssAdapter::reportNfwNotificationEvent");
4264 
4265     struct MsgReportNfwNotification : public LocMsg {
4266         const GnssNfwNotification mNotification;
4267         GnssAdapter& mAdapter;
4268 
4269         inline MsgReportNfwNotification(const GnssNfwNotification& notification,
4270             GnssAdapter& adapter) :
4271             LocMsg(), mNotification(notification), mAdapter(adapter) {
4272             LOC_LOGv("MsgReportNfwNotification");
4273         }
4274 
4275         inline virtual void proc() const {
4276             LOC_LOGv("MsgReportNfwNotification::proc()");
4277             mAdapter.reportNfwNotification(mNotification);
4278         }
4279     };
4280 
4281     sendMsg(new MsgReportNfwNotification(notification, *this));
4282 }
4283 
4284 /* GnssAdapter::requestATL
4285  * Method triggered in QMI thread as part of handling below message:
4286  * eQMI_LOC_SERVER_REQUEST_OPEN_V02
4287  * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
4288  * eQMI_LOC_WWAN_TYPE_INTERNET_V02
4289  * eQMI_LOC_WWAN_TYPE_AGNSS_V02
4290  * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */
requestATL(int connHandle,LocAGpsType agpsType,LocApnTypeMask apnTypeMask)4291 bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType,
4292                              LocApnTypeMask apnTypeMask){
4293 
4294     LOC_LOGI("GnssAdapter::requestATL handle=%d agpsType=0x%X apnTypeMask=0x%X",
4295         connHandle, agpsType, apnTypeMask);
4296 
4297     sendMsg( new AgpsMsgRequestATL(
4298              &mAgpsManager, connHandle, (AGpsExtType)agpsType,
4299              apnTypeMask));
4300 
4301     return true;
4302 }
4303 
4304 /* GnssAdapter::releaseATL
4305  * Method triggered in QMI thread as part of handling below message:
4306  * eQMI_LOC_SERVER_REQUEST_CLOSE_V02
4307  * Triggers teardown of an existing AGPS call */
releaseATL(int connHandle)4308 bool GnssAdapter::releaseATL(int connHandle){
4309 
4310     LOC_LOGI("GnssAdapter::releaseATL");
4311 
4312     /* Release SUPL/INTERNET/SUPL_ES ATL */
4313     struct AgpsMsgReleaseATL: public LocMsg {
4314 
4315         AgpsManager* mAgpsManager;
4316         int mConnHandle;
4317 
4318         inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) :
4319                 LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) {
4320 
4321             LOC_LOGV("AgpsMsgReleaseATL");
4322         }
4323 
4324         inline virtual void proc() const {
4325 
4326             LOC_LOGV("AgpsMsgReleaseATL::proc()");
4327             mAgpsManager->releaseATL(mConnHandle);
4328         }
4329     };
4330 
4331     sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle));
4332 
4333     return true;
4334 }
4335 
dataConnOpenCommand(AGpsExtType agpsType,const char * apnName,int apnLen,AGpsBearerType bearerType)4336 void GnssAdapter::dataConnOpenCommand(
4337         AGpsExtType agpsType,
4338         const char* apnName, int apnLen, AGpsBearerType bearerType){
4339 
4340     LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
4341 
4342     struct AgpsMsgAtlOpenSuccess: public LocMsg {
4343 
4344         AgpsManager* mAgpsManager;
4345         AGpsExtType mAgpsType;
4346         char* mApnName;
4347         int mApnLen;
4348         AGpsBearerType mBearerType;
4349 
4350         inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType,
4351                 const char* apnName, int apnLen, AGpsBearerType bearerType) :
4352                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName(
4353                         new char[apnLen + 1]), mApnLen(apnLen), mBearerType(bearerType) {
4354 
4355             LOC_LOGV("AgpsMsgAtlOpenSuccess");
4356             if (mApnName == nullptr) {
4357                 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
4358                 // Reporting the failure here
4359                 mAgpsManager->reportAtlClosed(mAgpsType);
4360                 return;
4361             }
4362             memcpy(mApnName, apnName, apnLen);
4363             mApnName[apnLen] = 0;
4364         }
4365 
4366         inline ~AgpsMsgAtlOpenSuccess() {
4367             delete[] mApnName;
4368         }
4369 
4370         inline virtual void proc() const {
4371 
4372             LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()");
4373             mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen, mBearerType);
4374         }
4375     };
4376     // Added inital length checks for apnlen check to avoid security issues
4377     // In case of failure reporting the same
4378     if (NULL == apnName || apnLen <= 0 || apnLen > MAX_APN_LEN || (strlen(apnName) != apnLen)) {
4379         LOC_LOGe("%s]: incorrect apnlen length or incorrect apnName", __func__);
4380         mAgpsManager.reportAtlClosed(agpsType);
4381     } else {
4382         sendMsg( new AgpsMsgAtlOpenSuccess(
4383                     &mAgpsManager, agpsType, apnName, apnLen, bearerType));
4384     }
4385 }
4386 
dataConnClosedCommand(AGpsExtType agpsType)4387 void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
4388 
4389     LOC_LOGI("GnssAdapter::frameworkDataConnClosed");
4390 
4391     struct AgpsMsgAtlClosed: public LocMsg {
4392 
4393         AgpsManager* mAgpsManager;
4394         AGpsExtType mAgpsType;
4395 
4396         inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) :
4397                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
4398 
4399             LOC_LOGV("AgpsMsgAtlClosed");
4400         }
4401 
4402         inline virtual void proc() const {
4403 
4404             LOC_LOGV("AgpsMsgAtlClosed::proc()");
4405             mAgpsManager->reportAtlClosed(mAgpsType);
4406         }
4407     };
4408 
4409     sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType));
4410 }
4411 
dataConnFailedCommand(AGpsExtType agpsType)4412 void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){
4413 
4414     LOC_LOGI("GnssAdapter::frameworkDataConnFailed");
4415 
4416     struct AgpsMsgAtlOpenFailed: public LocMsg {
4417 
4418         AgpsManager* mAgpsManager;
4419         AGpsExtType mAgpsType;
4420 
4421         inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) :
4422                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
4423 
4424             LOC_LOGV("AgpsMsgAtlOpenFailed");
4425         }
4426 
4427         inline virtual void proc() const {
4428 
4429             LOC_LOGV("AgpsMsgAtlOpenFailed::proc()");
4430             mAgpsManager->reportAtlOpenFailed(mAgpsType);
4431         }
4432     };
4433 
4434     sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType));
4435 }
4436 
convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo> & out,const GnssSvType & in_constellation,const SystemStatusReports & in)4437 void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out,
4438                                        const GnssSvType& in_constellation,
4439                                        const SystemStatusReports& in)
4440 {
4441     uint64_t sv_mask = 0ULL;
4442     uint32_t svid_min = 0;
4443     uint32_t svid_num = 0;
4444     uint32_t svid_idx = 0;
4445 
4446     uint64_t eph_health_good_mask = 0ULL;
4447     uint64_t eph_health_bad_mask = 0ULL;
4448     uint64_t server_perdiction_available_mask = 0ULL;
4449     float server_perdiction_age = 0.0f;
4450 
4451     // set constellationi based parameters
4452     switch (in_constellation) {
4453         case GNSS_SV_TYPE_GPS:
4454             svid_min = GNSS_BUGREPORT_GPS_MIN;
4455             svid_num = GPS_NUM;
4456             svid_idx = 0;
4457             if (!in.mSvHealth.empty()) {
4458                 eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask;
4459                 eph_health_bad_mask  = in.mSvHealth.back().mGpsBadMask;
4460             }
4461             if (!in.mXtra.empty()) {
4462                 server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid;
4463                 server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge);
4464             }
4465             break;
4466         case GNSS_SV_TYPE_GLONASS:
4467             svid_min = GNSS_BUGREPORT_GLO_MIN;
4468             svid_num = GLO_NUM;
4469             svid_idx = GPS_NUM;
4470             if (!in.mSvHealth.empty()) {
4471                 eph_health_good_mask = in.mSvHealth.back().mGloGoodMask;
4472                 eph_health_bad_mask  = in.mSvHealth.back().mGloBadMask;
4473             }
4474             if (!in.mXtra.empty()) {
4475                 server_perdiction_available_mask = in.mXtra.back().mGloXtraValid;
4476                 server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge);
4477             }
4478             break;
4479         case GNSS_SV_TYPE_QZSS:
4480             svid_min = GNSS_BUGREPORT_QZSS_MIN;
4481             svid_num = QZSS_NUM;
4482             svid_idx = GPS_NUM+GLO_NUM+BDS_NUM+GAL_NUM;
4483             if (!in.mSvHealth.empty()) {
4484                 eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask;
4485                 eph_health_bad_mask  = in.mSvHealth.back().mQzssBadMask;
4486             }
4487             if (!in.mXtra.empty()) {
4488                 server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid;
4489                 server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge);
4490             }
4491             break;
4492         case GNSS_SV_TYPE_BEIDOU:
4493             svid_min = GNSS_BUGREPORT_BDS_MIN;
4494             svid_num = BDS_NUM;
4495             svid_idx = GPS_NUM+GLO_NUM;
4496             if (!in.mSvHealth.empty()) {
4497                 eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask;
4498                 eph_health_bad_mask  = in.mSvHealth.back().mBdsBadMask;
4499             }
4500             if (!in.mXtra.empty()) {
4501                 server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid;
4502                 server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge);
4503             }
4504             break;
4505         case GNSS_SV_TYPE_GALILEO:
4506             svid_min = GNSS_BUGREPORT_GAL_MIN;
4507             svid_num = GAL_NUM;
4508             svid_idx = GPS_NUM+GLO_NUM+BDS_NUM;
4509             if (!in.mSvHealth.empty()) {
4510                 eph_health_good_mask = in.mSvHealth.back().mGalGoodMask;
4511                 eph_health_bad_mask  = in.mSvHealth.back().mGalBadMask;
4512             }
4513             if (!in.mXtra.empty()) {
4514                 server_perdiction_available_mask = in.mXtra.back().mGalXtraValid;
4515                 server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge);
4516             }
4517             break;
4518         case GNSS_SV_TYPE_NAVIC:
4519             svid_min = GNSS_BUGREPORT_NAVIC_MIN;
4520             svid_num = NAVIC_NUM;
4521             svid_idx = GPS_NUM+GLO_NUM+QZSS_NUM+BDS_NUM+GAL_NUM;
4522             if (!in.mSvHealth.empty()) {
4523                 eph_health_good_mask = in.mSvHealth.back().mNavicGoodMask;
4524                 eph_health_bad_mask  = in.mSvHealth.back().mNavicBadMask;
4525             }
4526             if (!in.mXtra.empty()) {
4527                 server_perdiction_available_mask = in.mXtra.back().mNavicXtraValid;
4528                 server_perdiction_age = (float)(in.mXtra.back().mNavicXtraAge);
4529             }
4530             break;
4531         default:
4532             return;
4533     }
4534 
4535     // extract each sv info from systemstatus report
4536     for(uint32_t i=0; i<svid_num && (svid_idx+i)<SV_ALL_NUM; i++) {
4537 
4538         GnssDebugSatelliteInfo s = {};
4539         s.size = sizeof(s);
4540         s.svid = i + svid_min;
4541         s.constellation = in_constellation;
4542 
4543         if (!in.mNavData.empty()) {
4544             s.mEphemerisType   = in.mNavData.back().mNav[svid_idx+i].mType;
4545             s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource;
4546         }
4547         else {
4548             s.mEphemerisType   = GNSS_EPH_TYPE_UNKNOWN;
4549             s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN;
4550         }
4551 
4552         sv_mask = 0x1ULL << i;
4553         if (eph_health_good_mask & sv_mask) {
4554             s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD;
4555         }
4556         else if (eph_health_bad_mask & sv_mask) {
4557             s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD;
4558         }
4559         else {
4560             s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN;
4561         }
4562 
4563         if (!in.mNavData.empty()) {
4564             s.ephemerisAgeSeconds =
4565                 (float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec);
4566         }
4567         else {
4568             s.ephemerisAgeSeconds = 0.0f;
4569         }
4570 
4571         if (server_perdiction_available_mask & sv_mask) {
4572             s.serverPredictionIsAvailable = true;
4573         }
4574         else {
4575             s.serverPredictionIsAvailable = false;
4576         }
4577 
4578         s.serverPredictionAgeSeconds = server_perdiction_age;
4579         out.push_back(s);
4580     }
4581 
4582     return;
4583 }
4584 
getDebugReport(GnssDebugReport & r)4585 bool GnssAdapter::getDebugReport(GnssDebugReport& r)
4586 {
4587     LOC_LOGD("%s]: ", __func__);
4588 
4589     SystemStatus* systemstatus = getSystemStatus();
4590     if (nullptr == systemstatus) {
4591         return false;
4592     }
4593 
4594     SystemStatusReports reports = {};
4595     systemstatus->getReport(reports, true);
4596 
4597     r.size = sizeof(r);
4598 
4599     // location block
4600     r.mLocation.size = sizeof(r.mLocation);
4601     if(!reports.mLocation.empty() && reports.mLocation.back().mValid) {
4602         r.mLocation.mValid = true;
4603         r.mLocation.mLocation.latitude =
4604             reports.mLocation.back().mLocation.gpsLocation.latitude;
4605         r.mLocation.mLocation.longitude =
4606             reports.mLocation.back().mLocation.gpsLocation.longitude;
4607         r.mLocation.mLocation.altitude =
4608             reports.mLocation.back().mLocation.gpsLocation.altitude;
4609         r.mLocation.mLocation.speed =
4610             (double)(reports.mLocation.back().mLocation.gpsLocation.speed);
4611         r.mLocation.mLocation.bearing =
4612             (double)(reports.mLocation.back().mLocation.gpsLocation.bearing);
4613         r.mLocation.mLocation.accuracy =
4614             (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy);
4615 
4616         r.mLocation.verticalAccuracyMeters =
4617             reports.mLocation.back().mLocationEx.vert_unc;
4618         r.mLocation.speedAccuracyMetersPerSecond =
4619             reports.mLocation.back().mLocationEx.speed_unc;
4620         r.mLocation.bearingAccuracyDegrees =
4621             reports.mLocation.back().mLocationEx.bearing_unc;
4622 
4623         r.mLocation.mUtcReported =
4624             reports.mLocation.back().mUtcReported;
4625     }
4626     else if(!reports.mBestPosition.empty() && reports.mBestPosition.back().mValid) {
4627         r.mLocation.mValid = true;
4628         r.mLocation.mLocation.latitude =
4629                 (double)(reports.mBestPosition.back().mBestLat) * RAD2DEG;
4630         r.mLocation.mLocation.longitude =
4631                 (double)(reports.mBestPosition.back().mBestLon) * RAD2DEG;
4632         r.mLocation.mLocation.altitude = reports.mBestPosition.back().mBestAlt;
4633         r.mLocation.mLocation.accuracy =
4634                 (double)(reports.mBestPosition.back().mBestHepe);
4635 
4636         r.mLocation.mUtcReported = reports.mBestPosition.back().mUtcReported;
4637     }
4638     else {
4639         r.mLocation.mValid = false;
4640     }
4641 
4642     if (r.mLocation.mValid) {
4643         LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f",
4644             r.mLocation.mLocation.latitude,
4645             r.mLocation.mLocation.longitude,
4646             r.mLocation.mLocation.altitude,
4647             r.mLocation.mLocation.speed);
4648     }
4649 
4650     // time block
4651     r.mTime.size = sizeof(r.mTime);
4652     if(!reports.mTimeAndClock.empty() && reports.mTimeAndClock.back().mTimeValid) {
4653         r.mTime.mValid = true;
4654         r.mTime.timeEstimate =
4655             (((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 +
4656                         GNSS_UTC_TIME_OFFSET)*24*60*60 -
4657               (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL +
4658               (int64_t)(reports.mTimeAndClock.back().mGpsTowMs);
4659 
4660         if (reports.mTimeAndClock.back().mTimeUncNs > 0) {
4661             // TimeUncNs value is available
4662             r.mTime.timeUncertaintyNs =
4663                     (float)(reports.mTimeAndClock.back().mLeapSecUnc)*1000.0f +
4664                     (float)(reports.mTimeAndClock.back().mTimeUncNs);
4665         } else {
4666             // fall back to legacy TimeUnc
4667             r.mTime.timeUncertaintyNs =
4668                     ((float)(reports.mTimeAndClock.back().mTimeUnc) +
4669                      (float)(reports.mTimeAndClock.back().mLeapSecUnc))*1000.0f;
4670         }
4671 
4672         r.mTime.frequencyUncertaintyNsPerSec =
4673             (float)(reports.mTimeAndClock.back().mClockFreqBiasUnc);
4674         LOC_LOGV("getDebugReport - timeestimate=%" PRIu64 " unc=%f frequnc=%f",
4675                 r.mTime.timeEstimate,
4676                 r.mTime.timeUncertaintyNs, r.mTime.frequencyUncertaintyNsPerSec);
4677     }
4678     else {
4679         r.mTime.mValid = false;
4680     }
4681 
4682     // satellite info block
4683     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports);
4684     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports);
4685     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports);
4686     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports);
4687     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports);
4688     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_NAVIC, reports);
4689     LOC_LOGV("getDebugReport - satellite=%zu", r.mSatelliteInfo.size());
4690 
4691     return true;
4692 }
4693 
4694 /* get AGC information from system status and fill it */
4695 void
getAgcInformation(GnssMeasurementsNotification & measurements,int msInWeek)4696 GnssAdapter::getAgcInformation(GnssMeasurementsNotification& measurements, int msInWeek)
4697 {
4698     SystemStatus* systemstatus = getSystemStatus();
4699 
4700     if (nullptr != systemstatus) {
4701         SystemStatusReports reports = {};
4702         systemstatus->getReport(reports, true);
4703 
4704         if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
4705             (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
4706 
4707             for (size_t i = 0; i < measurements.count; i++) {
4708                 switch (measurements.measurements[i].svType) {
4709                 case GNSS_SV_TYPE_GPS:
4710                 case GNSS_SV_TYPE_QZSS:
4711                     measurements.measurements[i].agcLevelDb =
4712                             reports.mRfAndParams.back().mAgcGps;
4713                     measurements.measurements[i].flags |=
4714                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
4715                     break;
4716 
4717                 case GNSS_SV_TYPE_GALILEO:
4718                     measurements.measurements[i].agcLevelDb =
4719                             reports.mRfAndParams.back().mAgcGal;
4720                     measurements.measurements[i].flags |=
4721                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
4722                     break;
4723 
4724                 case GNSS_SV_TYPE_GLONASS:
4725                     measurements.measurements[i].agcLevelDb =
4726                             reports.mRfAndParams.back().mAgcGlo;
4727                     measurements.measurements[i].flags |=
4728                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
4729                     break;
4730 
4731                 case GNSS_SV_TYPE_BEIDOU:
4732                     measurements.measurements[i].agcLevelDb =
4733                             reports.mRfAndParams.back().mAgcBds;
4734                     measurements.measurements[i].flags |=
4735                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
4736                     break;
4737 
4738                 case GNSS_SV_TYPE_SBAS:
4739                 case GNSS_SV_TYPE_UNKNOWN:
4740                 default:
4741                     break;
4742                 }
4743             }
4744         }
4745     }
4746 }
4747 
4748 /* get Data information from system status and fill it */
4749 void
getDataInformation(GnssDataNotification & data,int msInWeek)4750 GnssAdapter::getDataInformation(GnssDataNotification& data, int msInWeek)
4751 {
4752     SystemStatus* systemstatus = getSystemStatus();
4753 
4754     LOC_LOGV("%s]: msInWeek=%d", __func__, msInWeek);
4755     if (nullptr != systemstatus) {
4756         SystemStatusReports reports = {};
4757         systemstatus->getReport(reports, true);
4758 
4759         if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
4760             (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
4761 
4762             for (int sig = GNSS_LOC_SIGNAL_TYPE_GPS_L1CA;
4763                  sig < GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES; sig++) {
4764                 data.gnssDataMask[sig] = 0;
4765                 data.jammerInd[sig] = 0.0;
4766                 data.agc[sig] = 0.0;
4767             }
4768             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGps) {
4769                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] |=
4770                         GNSS_LOC_DATA_AGC_BIT;
4771                 data.agc[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
4772                         reports.mRfAndParams.back().mAgcGps;
4773                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] |=
4774                         GNSS_LOC_DATA_AGC_BIT;
4775                 data.agc[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
4776                         reports.mRfAndParams.back().mAgcGps;
4777                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] |=
4778                         GNSS_LOC_DATA_AGC_BIT;
4779                 data.agc[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
4780                     reports.mRfAndParams.back().mAgcGps;
4781             }
4782             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGps) {
4783                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] |=
4784                         GNSS_LOC_DATA_JAMMER_IND_BIT;
4785                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
4786                         (double)reports.mRfAndParams.back().mJammerGps;
4787                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] |=
4788                         GNSS_LOC_DATA_JAMMER_IND_BIT;
4789                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
4790                         (double)reports.mRfAndParams.back().mJammerGps;
4791                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] |=
4792                         GNSS_LOC_DATA_JAMMER_IND_BIT;
4793                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
4794                     (double)reports.mRfAndParams.back().mJammerGps;
4795             }
4796             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGlo) {
4797                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] |=
4798                         GNSS_LOC_DATA_AGC_BIT;
4799                 data.agc[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
4800                         reports.mRfAndParams.back().mAgcGlo;
4801             }
4802             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGlo) {
4803                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] |=
4804                         GNSS_LOC_DATA_JAMMER_IND_BIT;
4805                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
4806                         (double)reports.mRfAndParams.back().mJammerGlo;
4807             }
4808             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcBds) {
4809                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] |=
4810                         GNSS_LOC_DATA_AGC_BIT;
4811                 data.agc[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
4812                         reports.mRfAndParams.back().mAgcBds;
4813             }
4814             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerBds) {
4815                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] |=
4816                         GNSS_LOC_DATA_JAMMER_IND_BIT;
4817                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
4818                         (double)reports.mRfAndParams.back().mJammerBds;
4819             }
4820             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGal) {
4821                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] |=
4822                         GNSS_LOC_DATA_AGC_BIT;
4823                 data.agc[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
4824                         reports.mRfAndParams.back().mAgcGal;
4825             }
4826             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGal) {
4827                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] |=
4828                         GNSS_LOC_DATA_JAMMER_IND_BIT;
4829                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
4830                         (double)reports.mRfAndParams.back().mJammerGal;
4831             }
4832         }
4833     }
4834 }
4835 
4836 /* Callbacks registered with loc_net_iface library */
agpsOpenResultCb(bool isSuccess,AGpsExtType agpsType,const char * apn,AGpsBearerType bearerType,void * userDataPtr)4837 static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
4838         AGpsBearerType bearerType, void* userDataPtr) {
4839     LOC_LOGD("%s]: ", __func__);
4840     if (userDataPtr == nullptr) {
4841         LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
4842         return;
4843     }
4844     if (apn == nullptr) {
4845         LOC_LOGE("%s]: apn is nullptr.", __func__);
4846         return;
4847     }
4848     GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
4849     if (isSuccess) {
4850         adapter->dataConnOpenCommand(agpsType, apn, strlen(apn), bearerType);
4851     } else {
4852         adapter->dataConnFailedCommand(agpsType);
4853     }
4854 }
4855 
agpsCloseResultCb(bool isSuccess,AGpsExtType agpsType,void * userDataPtr)4856 static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr) {
4857     LOC_LOGD("%s]: ", __func__);
4858     if (userDataPtr == nullptr) {
4859         LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
4860         return;
4861     }
4862     GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
4863     if (isSuccess) {
4864         adapter->dataConnClosedCommand(agpsType);
4865     } else {
4866         adapter->dataConnFailedCommand(agpsType);
4867     }
4868 }
4869 
4870 void
saveGnssEnergyConsumedCallback(GnssEnergyConsumedCallback energyConsumedCb)4871 GnssAdapter::saveGnssEnergyConsumedCallback(GnssEnergyConsumedCallback energyConsumedCb) {
4872     mGnssEnergyConsumedCb = energyConsumedCb;
4873 }
4874 
4875 void
getGnssEnergyConsumedCommand(GnssEnergyConsumedCallback energyConsumedCb)4876 GnssAdapter::getGnssEnergyConsumedCommand(GnssEnergyConsumedCallback energyConsumedCb) {
4877     struct MsgGetGnssEnergyConsumed : public LocMsg {
4878         GnssAdapter& mAdapter;
4879         LocApiBase& mApi;
4880         GnssEnergyConsumedCallback mEnergyConsumedCb;
4881         inline MsgGetGnssEnergyConsumed(GnssAdapter& adapter, LocApiBase& api,
4882                                         GnssEnergyConsumedCallback energyConsumedCb) :
4883             LocMsg(),
4884             mAdapter(adapter),
4885             mApi(api),
4886             mEnergyConsumedCb(energyConsumedCb){}
4887         inline virtual void proc() const {
4888             mAdapter.saveGnssEnergyConsumedCallback(mEnergyConsumedCb);
4889             mApi.getGnssEnergyConsumed();
4890         }
4891     };
4892 
4893     sendMsg(new MsgGetGnssEnergyConsumed(*this, *mLocApi, energyConsumedCb));
4894 }
4895 
4896 void
nfwControlCommand(bool enable)4897 GnssAdapter::nfwControlCommand(bool enable) {
4898     struct MsgControlNfwLocationAccess : public LocMsg {
4899         GnssAdapter& mAdapter;
4900         LocApiBase& mApi;
4901         bool mEnable;
4902         inline MsgControlNfwLocationAccess(GnssAdapter& adapter, LocApiBase& api,
4903             bool enable) :
4904             LocMsg(),
4905             mAdapter(adapter),
4906             mApi(api),
4907             mEnable(enable) {}
4908         inline virtual void proc() const {
4909             GnssConfigGpsLock gpsLock;
4910 
4911             gpsLock = ContextBase::mGps_conf.GPS_LOCK;
4912             if (mEnable) {
4913                 gpsLock &= ~GNSS_CONFIG_GPS_LOCK_NI;
4914             } else {
4915                 gpsLock |= GNSS_CONFIG_GPS_LOCK_NI;
4916             }
4917             ContextBase::mGps_conf.GPS_LOCK = gpsLock;
4918             mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
4919                 mApi.setGpsLockSync((GnssConfigGpsLock)gpsLock);
4920             }));
4921         }
4922     };
4923 
4924     if (mSupportNfwControl) {
4925         sendMsg(new MsgControlNfwLocationAccess(*this, *mLocApi, enable));
4926     } else {
4927         LOC_LOGw("NFW control is not supported, do not use this for NFW");
4928     }
4929 }
4930 
4931 /* ==== Eng Hub Proxy ================================================================= */
4932 /* ======== UTILITIES ================================================================= */
4933 void
initEngHubProxyCommand()4934 GnssAdapter::initEngHubProxyCommand() {
4935     LOC_LOGD("%s]: ", __func__);
4936 
4937     struct MsgInitEngHubProxy : public LocMsg {
4938         GnssAdapter* mAdapter;
4939         inline MsgInitEngHubProxy(GnssAdapter* adapter) :
4940             LocMsg(),
4941             mAdapter(adapter) {}
4942         inline virtual void proc() const {
4943             mAdapter->initEngHubProxy();
4944         }
4945     };
4946 
4947     sendMsg(new MsgInitEngHubProxy(this));
4948 }
4949 
4950 bool
initEngHubProxy()4951 GnssAdapter::initEngHubProxy() {
4952     static bool firstTime = true;
4953     static bool engHubLoadSuccessful = false;
4954 
4955     const char *error = nullptr;
4956     unsigned int processListLength = 0;
4957     loc_process_info_s_type* processInfoList = nullptr;
4958 
4959     do {
4960         // load eng hub only once
4961         if (firstTime == false) {
4962             break;
4963         }
4964 
4965         int rc = loc_read_process_conf(LOC_PATH_IZAT_CONF, &processListLength,
4966                                        &processInfoList);
4967         if (rc != 0) {
4968             LOC_LOGE("%s]: failed to parse conf file", __func__);
4969             break;
4970         }
4971 
4972         bool pluginDaemonEnabled = false;
4973         // go over the conf table to see whether any plugin daemon is enabled
4974         for (unsigned int i = 0; i < processListLength; i++) {
4975             if ((strncmp(processInfoList[i].name[0], PROCESS_NAME_ENGINE_SERVICE,
4976                          strlen(PROCESS_NAME_ENGINE_SERVICE)) == 0) &&
4977                 (processInfoList[i].proc_status == ENABLED)) {
4978                 pluginDaemonEnabled = true;
4979                 break;
4980             }
4981         }
4982 
4983         // no plugin daemon is enabled for this platform, no need to load eng hub .so
4984         if (pluginDaemonEnabled == false) {
4985             break;
4986         }
4987 
4988         // load the engine hub .so, if the .so is not present
4989         // all EngHubProxyBase calls will turn into no-op.
4990         void *handle = nullptr;
4991         if ((handle = dlopen("libloc_eng_hub.so", RTLD_NOW)) == nullptr) {
4992             if ((error = dlerror()) != nullptr) {
4993                 LOC_LOGE("%s]: libloc_eng_hub.so not found %s !", __func__, error);
4994             }
4995             break;
4996         }
4997 
4998         // prepare the callback functions
4999         // callback function for engine hub to report back position event
5000         GnssAdapterReportEnginePositionsEventCb reportPositionEventCb =
5001             [this](int count, EngineLocationInfo* locationArr) {
5002                     // report from engine hub on behalf of PPE will be treated as fromUlp
5003                     reportEnginePositionsEvent(count, locationArr);
5004             };
5005 
5006         // callback function for engine hub to report back sv event
5007         GnssAdapterReportSvEventCb reportSvEventCb =
5008             [this](const GnssSvNotification& svNotify, bool fromEngineHub) {
5009                    reportSvEvent(svNotify, fromEngineHub);
5010             };
5011 
5012         // callback function for engine hub to request for complete aiding data
5013         GnssAdapterReqAidingDataCb reqAidingDataCb =
5014             [this] (const GnssAidingDataSvMask& svDataMask) {
5015             mLocApi->requestForAidingData(svDataMask);
5016         };
5017 
5018         getEngHubProxyFn* getter = (getEngHubProxyFn*) dlsym(handle, "getEngHubProxy");
5019         if(getter != nullptr) {
5020             EngineHubProxyBase* hubProxy = (*getter) (mMsgTask, mSystemStatus->getOsObserver(),
5021                                                       reportPositionEventCb,
5022                                                       reportSvEventCb, reqAidingDataCb);
5023             if (hubProxy != nullptr) {
5024                 mEngHubProxy = hubProxy;
5025                 engHubLoadSuccessful = true;
5026             }
5027         }
5028         else {
5029             LOC_LOGD("%s]: entered, did not find function", __func__);
5030         }
5031 
5032         LOC_LOGD("%s]: first time initialization %d, returned %d",
5033                  __func__, firstTime, engHubLoadSuccessful);
5034 
5035     } while (0);
5036 
5037     if (processInfoList != nullptr) {
5038         free (processInfoList);
5039         processInfoList = nullptr;
5040     }
5041 
5042     firstTime = false;
5043     return engHubLoadSuccessful;
5044 }
5045