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