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