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