• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2017-2018, 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 <loc_log.h>
44 #include <loc_nmea.h>
45 #include <Agps.h>
46 #include <SystemStatus.h>
47 
48 #include <vector>
49 
50 #define RAD2DEG    (180.0 / M_PI)
51 
52 using namespace loc_core;
53 
54 /* Method to fetch status cb from loc_net_iface library */
55 typedef AgpsCbInfo& (*LocAgpsGetAgpsCbInfo)(LocAgpsOpenResultCb openResultCb,
56         LocAgpsCloseResultCb closeResultCb, void* userDataPtr);
57 
58 static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
59         AGpsBearerType bearerType, void* userDataPtr);
60 static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr);
61 
GnssAdapter()62 GnssAdapter::GnssAdapter() :
63     LocAdapterBase(0,
64                    LocDualContext::getLocFgContext(NULL,
65                                                    NULL,
66                                                    LocDualContext::mLocationHalName,
67                                                    false), true, nullptr),
68     mUlpProxy(new UlpProxyBase()),
69     mUlpPositionMode(),
70     mGnssSvIdUsedInPosition(),
71     mGnssSvIdUsedInPosAvail(false),
72     mControlCallbacks(),
73     mPowerVoteId(0),
74     mNmeaMask(0),
75     mGnssSvIdConfig(),
76     mGnssSvTypeConfig(),
77     mGnssSvTypeConfigCb(nullptr),
78     mNiData(),
79     mAgpsManager(),
80     mAgpsCbInfo(),
81     mOdcpiRequestCb(nullptr),
82     mOdcpiRequestActive(false),
83     mOdcpiTimer(this),
84     mOdcpiRequest(),
85     mSystemStatus(SystemStatus::getInstance(mMsgTask)),
86     mServerUrl(":"),
87     mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask)
88 {
89     LOC_LOGD("%s]: Constructor %p", __func__, this);
90     mUlpPositionMode.mode = LOC_POSITION_MODE_INVALID;
91 
92     pthread_condattr_t condAttr;
93     pthread_condattr_init(&condAttr);
94     pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
95     pthread_cond_init(&mNiData.session.tCond, &condAttr);
96     pthread_cond_init(&mNiData.sessionEs.tCond, &condAttr);
97     pthread_condattr_destroy(&condAttr);
98 
99     /* Set ATL open/close callbacks */
100     AgpsAtlOpenStatusCb atlOpenStatusCb =
101             [this](int handle, int isSuccess, char* apn,
102                     AGpsBearerType bearerType, AGpsExtType agpsType, LocApnTypeMask mask) {
103 
104                 mLocApi->atlOpenStatus(
105                         handle, isSuccess, apn, bearerType, agpsType, mask);
106             };
107     AgpsAtlCloseStatusCb atlCloseStatusCb =
108             [this](int handle, int isSuccess) {
109 
110                 mLocApi->atlCloseStatus(handle, isSuccess);
111             };
112 
113     /* Register DS Client APIs */
114     AgpsDSClientInitFn dsClientInitFn =
115             [this](bool isDueToSSR) {
116 
117                 return mLocApi->initDataServiceClient(isDueToSSR);
118             };
119 
120     AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn =
121             [this] {
122 
123                 return mLocApi->openAndStartDataCall();
124             };
125 
126     AgpsDSClientStopDataCallFn dsClientStopDataCallFn =
127             [this] {
128 
129                 mLocApi->stopDataCall();
130             };
131 
132     AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn =
133             [this] {
134 
135                 mLocApi->closeDataCall();
136             };
137 
138     AgpsDSClientReleaseFn dsClientReleaseFn =
139             [this] {
140 
141                 mLocApi->releaseDataServiceClient();
142             };
143 
144     /* Send Msg function */
145     SendMsgToAdapterMsgQueueFn sendMsgFn =
146             [this](LocMsg* msg) {
147 
148                 sendMsg(msg);
149             };
150     mAgpsManager.registerATLCallbacks(atlOpenStatusCb, atlCloseStatusCb,
151             dsClientInitFn, dsClientOpenAndStartDataCallFn, dsClientStopDataCallFn,
152             dsClientCloseDataCallFn, dsClientReleaseFn, sendMsgFn);
153 
154     readConfigCommand();
155     setConfigCommand();
156     initDefaultAgpsCommand();
157 }
158 
159 void
setControlCallbacksCommand(LocationControlCallbacks & controlCallbacks)160 GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks)
161 {
162     struct MsgSetControlCallbacks : public LocMsg {
163         GnssAdapter& mAdapter;
164         const LocationControlCallbacks mControlCallbacks;
165         inline MsgSetControlCallbacks(GnssAdapter& adapter,
166                                       LocationControlCallbacks& controlCallbacks) :
167             LocMsg(),
168             mAdapter(adapter),
169             mControlCallbacks(controlCallbacks) {}
170         inline virtual void proc() const {
171             mAdapter.setControlCallbacks(mControlCallbacks);
172         }
173     };
174 
175     sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks));
176 }
177 
178 void
convertOptions(LocPosMode & out,const TrackingOptions & trackingOptions)179 GnssAdapter::convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions)
180 {
181     switch (trackingOptions.mode) {
182     case GNSS_SUPL_MODE_MSB:
183         out.mode = LOC_POSITION_MODE_MS_BASED;
184         break;
185     case GNSS_SUPL_MODE_MSA:
186         out.mode = LOC_POSITION_MODE_MS_ASSISTED;
187         break;
188     default:
189         out.mode = LOC_POSITION_MODE_STANDALONE;
190         break;
191     }
192     out.share_position = true;
193     out.min_interval = trackingOptions.minInterval;
194     out.powerMode = trackingOptions.powerMode;
195     out.timeBetweenMeasurements = trackingOptions.tbm;
196 }
197 
198 void
convertLocation(Location & out,const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,const LocPosTechMask techMask)199 GnssAdapter::convertLocation(Location& out, const UlpLocation& ulpLocation,
200                              const GpsLocationExtended& locationExtended,
201                              const LocPosTechMask techMask)
202 {
203     memset(&out, 0, sizeof(Location));
204     out.size = sizeof(Location);
205     if (LOC_GPS_LOCATION_HAS_LAT_LONG & ulpLocation.gpsLocation.flags) {
206         out.flags |= LOCATION_HAS_LAT_LONG_BIT;
207         out.latitude = ulpLocation.gpsLocation.latitude;
208         out.longitude = ulpLocation.gpsLocation.longitude;
209     }
210     if (LOC_GPS_LOCATION_HAS_ALTITUDE & ulpLocation.gpsLocation.flags) {
211         out.flags |= LOCATION_HAS_ALTITUDE_BIT;
212         out.altitude = ulpLocation.gpsLocation.altitude;
213     }
214     if (LOC_GPS_LOCATION_HAS_SPEED & ulpLocation.gpsLocation.flags) {
215         out.flags |= LOCATION_HAS_SPEED_BIT;
216         out.speed = ulpLocation.gpsLocation.speed;
217     }
218     if (LOC_GPS_LOCATION_HAS_BEARING & ulpLocation.gpsLocation.flags) {
219         out.flags |= LOCATION_HAS_BEARING_BIT;
220         out.bearing = ulpLocation.gpsLocation.bearing;
221     }
222     if (LOC_GPS_LOCATION_HAS_ACCURACY & ulpLocation.gpsLocation.flags) {
223         out.flags |= LOCATION_HAS_ACCURACY_BIT;
224         out.accuracy = ulpLocation.gpsLocation.accuracy;
225     }
226     if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) {
227         out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
228         out.verticalAccuracy = locationExtended.vert_unc;
229     }
230     if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) {
231         out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
232         out.speedAccuracy = locationExtended.speed_unc;
233     }
234     if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) {
235         out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
236         out.bearingAccuracy = locationExtended.bearing_unc;
237     }
238     out.timestamp = ulpLocation.gpsLocation.timestamp;
239     if (LOC_POS_TECH_MASK_SATELLITE & techMask) {
240         out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
241     }
242     if (LOC_POS_TECH_MASK_CELLID & techMask) {
243         out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
244     }
245     if (LOC_POS_TECH_MASK_WIFI & techMask) {
246         out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
247     }
248     if (LOC_POS_TECH_MASK_SENSORS & techMask) {
249         out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
250     }
251 }
252 
253 void
convertLocationInfo(GnssLocationInfoNotification & out,const GpsLocationExtended & locationExtended)254 GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out,
255                                  const GpsLocationExtended& locationExtended)
256 {
257     out.size = sizeof(GnssLocationInfoNotification);
258     if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) {
259         out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT;
260         out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel;
261     }
262     if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) {
263         out.flags |= GNSS_LOCATION_INFO_DOP_BIT;
264         out.pdop = locationExtended.pdop;
265         out.hdop = locationExtended.hdop;
266         out.vdop = locationExtended.vdop;
267     }
268     if (GPS_LOCATION_EXTENDED_HAS_EXT_DOP & locationExtended.flags) {
269         out.flags |= GNSS_LOCATION_INFO_EXT_DOP_BIT;
270         out.gdop = locationExtended.extDOP.GDOP;
271         out.tdop = locationExtended.extDOP.TDOP;
272     }
273     if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) {
274         out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT;
275         out.magneticDeviation = locationExtended.magneticDeviation;
276     }
277     if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) {
278         out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT;
279         switch (locationExtended.horizontal_reliability) {
280             case LOC_RELIABILITY_VERY_LOW:
281                 out.horReliability = LOCATION_RELIABILITY_VERY_LOW;
282                 break;
283             case LOC_RELIABILITY_LOW:
284                 out.horReliability = LOCATION_RELIABILITY_LOW;
285                 break;
286             case LOC_RELIABILITY_MEDIUM:
287                 out.horReliability = LOCATION_RELIABILITY_MEDIUM;
288                 break;
289             case LOC_RELIABILITY_HIGH:
290                 out.horReliability = LOCATION_RELIABILITY_HIGH;
291                 break;
292             default:
293                 out.horReliability = LOCATION_RELIABILITY_NOT_SET;
294                 break;
295         }
296     }
297     if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) {
298         out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT;
299         switch (locationExtended.vertical_reliability) {
300             case LOC_RELIABILITY_VERY_LOW:
301                 out.verReliability = LOCATION_RELIABILITY_VERY_LOW;
302                 break;
303             case LOC_RELIABILITY_LOW:
304                 out.verReliability = LOCATION_RELIABILITY_LOW;
305                 break;
306             case LOC_RELIABILITY_MEDIUM:
307                 out.verReliability = LOCATION_RELIABILITY_MEDIUM;
308                 break;
309             case LOC_RELIABILITY_HIGH:
310                 out.verReliability = LOCATION_RELIABILITY_HIGH;
311                 break;
312             default:
313                 out.verReliability = LOCATION_RELIABILITY_NOT_SET;
314                 break;
315         }
316     }
317     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) {
318         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT;
319         out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor;
320     }
321     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) {
322         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT;
323         out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor;
324     }
325     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) {
326         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT;
327         out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth;
328     }
329     if (GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA & locationExtended.flags) {
330         out.flags |= GNSS_LOCATION_INFO_GNSS_SV_USED_DATA_BIT;
331         out.svUsedInPosition.gpsSvUsedIdsMask =
332                 locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask;
333         out.svUsedInPosition.gloSvUsedIdsMask =
334                 locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask;
335         out.svUsedInPosition.galSvUsedIdsMask =
336                 locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask;
337         out.svUsedInPosition.bdsSvUsedIdsMask =
338                 locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask;
339         out.svUsedInPosition.qzssSvUsedIdsMask =
340                 locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask;
341     }
342     if (GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK & locationExtended.flags) {
343         out.flags |= GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT;
344         out.navSolutionMask = locationExtended.navSolutionMask;
345     }
346     if (GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK & locationExtended.flags) {
347         out.flags |= GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK;
348         out.posTechMask = locationExtended.tech_mask;
349     }
350     if (GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA & locationExtended.flags) {
351         out.flags |= GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA;
352         if (locationExtended.bodyFrameData.bodyFrameDatamask &
353                 LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT) {
354             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT;
355         }
356         if (locationExtended.bodyFrameData.bodyFrameDatamask &
357                 LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT) {
358             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT;
359         }
360         if (locationExtended.bodyFrameData.bodyFrameDatamask &
361                 LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT) {
362             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT;
363         }
364         if (locationExtended.bodyFrameData.bodyFrameDatamask & LOCATION_NAV_DATA_HAS_YAW_RATE_BIT) {
365             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_RATE_BIT;
366         }
367         if (locationExtended.bodyFrameData.bodyFrameDatamask & LOCATION_NAV_DATA_HAS_PITCH_BIT) {
368             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_BIT;
369         }
370         out.bodyFrameData.longAccel = locationExtended.bodyFrameData.longAccel;
371         out.bodyFrameData.latAccel = locationExtended.bodyFrameData.latAccel;
372         out.bodyFrameData.vertAccel = locationExtended.bodyFrameData.vertAccel;
373         out.bodyFrameData.yawRate = locationExtended.bodyFrameData.yawRate;
374         out.bodyFrameData.pitch = locationExtended.bodyFrameData.pitch;
375     }
376 }
377 
378 inline uint32_t
convertGpsLock(const GnssConfigGpsLock gpsLock)379 GnssAdapter::convertGpsLock(const GnssConfigGpsLock gpsLock)
380 {
381     switch (gpsLock) {
382         case GNSS_CONFIG_GPS_LOCK_MO:
383             return 1;
384         case GNSS_CONFIG_GPS_LOCK_NI:
385             return 2;
386         case GNSS_CONFIG_GPS_LOCK_MO_AND_NI:
387             return 3;
388         case GNSS_CONFIG_GPS_LOCK_NONE:
389         default:
390             return 0;
391     }
392 }
393 
394 inline GnssConfigGpsLock
convertGpsLock(const uint32_t gpsLock)395 GnssAdapter::convertGpsLock(const uint32_t gpsLock)
396 {
397     switch (gpsLock) {
398         case 1:
399             return GNSS_CONFIG_GPS_LOCK_MO;
400         case 2:
401             return GNSS_CONFIG_GPS_LOCK_NI;
402         case 3:
403             return GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
404         case 0:
405         default:
406             return GNSS_CONFIG_GPS_LOCK_NONE;
407     }
408 }
409 
410 inline uint32_t
convertSuplVersion(const GnssConfigSuplVersion suplVersion)411 GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion)
412 {
413     switch (suplVersion) {
414         case GNSS_CONFIG_SUPL_VERSION_2_0_0:
415             return 0x00020000;
416         case GNSS_CONFIG_SUPL_VERSION_2_0_2:
417             return 0x00020002;
418         case GNSS_CONFIG_SUPL_VERSION_1_0_0:
419         default:
420             return 0x00010000;
421     }
422 }
423 
424 inline GnssConfigSuplVersion
convertSuplVersion(const uint32_t suplVersion)425 GnssAdapter::convertSuplVersion(const uint32_t suplVersion)
426 {
427     switch (suplVersion) {
428         case 0x00020000:
429             return GNSS_CONFIG_SUPL_VERSION_2_0_0;
430         case 0x00020002:
431             return GNSS_CONFIG_SUPL_VERSION_2_0_2;
432         case 0x00010000:
433         default:
434             return GNSS_CONFIG_SUPL_VERSION_1_0_0;
435     }
436 }
437 
438 inline uint32_t
convertLppProfile(const GnssConfigLppProfile lppProfile)439 GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile)
440 {
441     switch (lppProfile) {
442         case GNSS_CONFIG_LPP_PROFILE_USER_PLANE:
443             return 1;
444         case GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE:
445             return 2;
446         case GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE:
447             return 3;
448         case GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE:
449         default:
450             return 0;
451     }
452 }
453 
454 inline GnssConfigLppProfile
convertLppProfile(const uint32_t lppProfile)455 GnssAdapter::convertLppProfile(const uint32_t lppProfile)
456 {
457     switch (lppProfile) {
458         case 1:
459             return GNSS_CONFIG_LPP_PROFILE_USER_PLANE;
460         case 2:
461             return GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE;
462         case 3:
463             return GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE;
464         case 0:
465         default:
466             return GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE;
467     }
468 }
469 
470 uint32_t
convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)471 GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)
472 {
473     uint32_t mask = 0;
474     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) {
475         mask |= (1<<0);
476     }
477     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
478         mask |= (1<<1);
479     }
480     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
481         mask |= (1<<2);
482     }
483     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeControlPlaneMask) {
484         mask |= (1<<3);
485     }
486     return mask;
487 }
488 
489 GnssConfigLppeControlPlaneMask
convertLppeCp(const uint32_t lppeControlPlaneMask)490 GnssAdapter::convertLppeCp(const uint32_t lppeControlPlaneMask)
491 {
492     GnssConfigLppeControlPlaneMask mask = 0;
493     if ((1<<0) & lppeControlPlaneMask) {
494         mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT;
495     }
496     if ((1<<1) & lppeControlPlaneMask) {
497         mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT;
498     }
499     if ((1<<2) & lppeControlPlaneMask) {
500         mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT;
501     }
502     if ((1<<3) & lppeControlPlaneMask) {
503         mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT;
504     }
505     return mask;
506 }
507 
508 
509 uint32_t
convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)510 GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)
511 {
512     uint32_t mask = 0;
513     if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) {
514         mask |= (1<<0);
515     }
516     if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
517         mask |= (1<<1);
518     }
519     if (GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
520         mask |= (1<<2);
521     }
522     if (GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeUserPlaneMask) {
523         mask |= (1<<3);
524     }
525     return mask;
526 }
527 
528 GnssConfigLppeUserPlaneMask
convertLppeUp(const uint32_t lppeUserPlaneMask)529 GnssAdapter::convertLppeUp(const uint32_t lppeUserPlaneMask)
530 {
531     GnssConfigLppeUserPlaneMask mask = 0;
532     if ((1<<0) & lppeUserPlaneMask) {
533         mask |= GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT;
534     }
535     if ((1<<1) & lppeUserPlaneMask) {
536         mask |= GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT;
537     }
538     if ((1<<2) & lppeUserPlaneMask) {
539         mask |= GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT;
540     }
541     if ((1<<3) & lppeUserPlaneMask) {
542         mask |= GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT;
543     }
544     return mask;
545 }
546 
547 uint32_t
convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)548 GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)
549 {
550     uint32_t mask = 0;
551     if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
552         mask |= (1<<0);
553     }
554     if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
555         mask |= (1<<1);
556     }
557     if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
558         mask |= (1<<2);
559     }
560     if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
561         mask |= (1<<3);
562     }
563     return mask;
564 }
565 
566 uint32_t
convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)567 GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)
568 {
569     switch (emergencyPdnForEmergencySupl) {
570        case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES:
571            return 1;
572        case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO:
573        default:
574            return 0;
575     }
576 }
577 
578 uint32_t
convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)579 GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)
580 {
581     switch (suplEmergencyServices) {
582        case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES:
583            return 1;
584        case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO:
585        default:
586            return 0;
587     }
588 }
589 
590 uint32_t
convertSuplMode(const GnssConfigSuplModeMask suplModeMask)591 GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask)
592 {
593     uint32_t mask = 0;
594     if (GNSS_CONFIG_SUPL_MODE_MSB_BIT & suplModeMask) {
595         mask |= (1<<0);
596     }
597     if (GNSS_CONFIG_SUPL_MODE_MSA_BIT & suplModeMask) {
598         mask |= (1<<1);
599     }
600     return mask;
601 }
602 
603 bool
resolveInAddress(const char * hostAddress,struct in_addr * inAddress)604 GnssAdapter::resolveInAddress(const char* hostAddress, struct in_addr* inAddress)
605 {
606     bool ret = true;
607 
608     struct hostent* hp;
609     hp = gethostbyname(hostAddress);
610     if (hp != NULL) { /* DNS OK */
611         memcpy(inAddress, hp->h_addr_list[0], hp->h_length);
612     } else {
613         /* Try IP representation */
614         if (inet_aton(hostAddress, inAddress) == 0) {
615             /* IP not valid */
616             LOC_LOGE("%s]: DNS query on '%s' failed", __func__, hostAddress);
617             ret = false;
618         }
619     }
620 
621     return ret;
622 }
623 
624 void
readConfigCommand()625 GnssAdapter::readConfigCommand()
626 {
627     LOC_LOGD("%s]: ", __func__);
628 
629     struct MsgReadConfig : public LocMsg {
630         GnssAdapter* mAdapter;
631         ContextBase& mContext;
632         inline MsgReadConfig(GnssAdapter* adapter,
633                              ContextBase& context) :
634             LocMsg(),
635             mAdapter(adapter),
636             mContext(context) {}
637         inline virtual void proc() const {
638             // reads config into mContext->mGps_conf
639             mContext.readConfig();
640             mContext.requestUlp((LocAdapterBase*)mAdapter, mContext.getCarrierCapabilities());
641         }
642     };
643 
644     if (mContext != NULL) {
645         sendMsg(new MsgReadConfig(this, *mContext));
646     }
647 }
648 
649 LocationError
setSuplHostServer(const char * server,int port)650 GnssAdapter::setSuplHostServer(const char* server, int port)
651 {
652     LocationError locErr = LOCATION_ERROR_SUCCESS;
653     if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
654         char serverUrl[MAX_URL_LEN] = {};
655         int32_t length = -1;
656         const char noHost[] = "NONE";
657 
658         locErr = LOCATION_ERROR_INVALID_PARAMETER;
659 
660         if ((NULL == server) || (server[0] == 0) ||
661                 (strncasecmp(noHost, server, sizeof(noHost)) == 0)) {
662             serverUrl[0] = '\0';
663             length = 0;
664         } else if (port > 0) {
665             length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u", server, port);
666         }
667 
668         if (length >= 0 && strncasecmp(getServerUrl().c_str(),
669                                        serverUrl, sizeof(serverUrl)) != 0) {
670             setServerUrl(serverUrl);
671             locErr = mLocApi->setServer(serverUrl, length);
672             if (locErr != LOCATION_ERROR_SUCCESS) {
673                 LOC_LOGE("%s]:Error while setting SUPL_HOST server:%s",
674                          __func__, serverUrl);
675             }
676         }
677     }
678     return locErr;
679 }
680 
681 void
setConfigCommand()682 GnssAdapter::setConfigCommand()
683 {
684     LOC_LOGD("%s]: ", __func__);
685 
686     struct MsgSetConfig : public LocMsg {
687         GnssAdapter& mAdapter;
688         LocApiBase& mApi;
689         inline MsgSetConfig(GnssAdapter& adapter,
690                             LocApiBase& api) :
691             LocMsg(),
692             mAdapter(adapter),
693             mApi(api) {}
694         inline virtual void proc() const {
695             if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
696                 mApi.setSUPLVersion(mAdapter.convertSuplVersion(ContextBase::mGps_conf.SUPL_VER));
697                 mApi.setLPPConfig(mAdapter.convertLppProfile(ContextBase::mGps_conf.LPP_PROFILE));
698                 mApi.setAGLONASSProtocol(ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT);
699             }
700             mAdapter.setSuplHostServer(ContextBase::mGps_conf.SUPL_HOST,
701                                        ContextBase::mGps_conf.SUPL_PORT);
702             mApi.setSensorControlConfig(ContextBase::mSap_conf.SENSOR_USAGE,
703                                         ContextBase::mSap_conf.SENSOR_PROVIDER);
704 
705             /* Mark these LPPe functions, they are MBN configured.
706             mApi.setLPPeProtocolCp(
707                     mAdapter.convertLppeCp(ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY));
708             mApi.setLPPeProtocolUp(
709                     mAdapter.convertLppeUp(ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY));
710             */
711 
712             // set nmea mask type
713             uint32_t mask = 0;
714             if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
715                 mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
716             }
717             if (mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
718                 mask |= LOC_NMEA_MASK_DEBUG_V02;
719             }
720             if (mask != 0) {
721                 mApi.setNMEATypes(mask);
722             }
723             mAdapter.mNmeaMask= mask;
724 
725             mApi.setXtraVersionCheck(ContextBase::mGps_conf.XTRA_VERSION_CHECK);
726             if (ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID ||
727                 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
728                 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
729                 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
730                 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) {
731                 mApi.setSensorProperties(
732                     ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID,
733                     ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK,
734                     ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
735                     ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY,
736                     ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
737                     ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY,
738                     ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
739                     ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY,
740                     ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
741                     ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY);
742             }
743             mApi.setSensorPerfControlConfig(
744                 ContextBase::mSap_conf.SENSOR_CONTROL_MODE,
745                    ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH,
746                    ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC,
747                    ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH,
748                    ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC,
749                    ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH,
750                    ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH,
751                    ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH,
752                    ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
753                    ContextBase::mSap_conf.SENSOR_ALGORITHM_CONFIG_MASK);
754         }
755     };
756 
757     sendMsg(new MsgSetConfig(*this, *mLocApi));
758 }
759 
760 uint32_t*
gnssUpdateConfigCommand(GnssConfig config)761 GnssAdapter::gnssUpdateConfigCommand(GnssConfig config)
762 {
763     // count the number of bits set
764     GnssConfigFlagsMask flagsCopy = config.flags;
765     size_t count = 0;
766     while (flagsCopy > 0) {
767         if (flagsCopy & 1) {
768             count++;
769         }
770         flagsCopy >>= 1;
771     }
772     std::string idsString = "[";
773     uint32_t* ids = NULL;
774     if (count > 0) {
775         ids = new uint32_t[count];
776         if (ids == nullptr) {
777             LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
778             return nullptr;
779         }
780         for (size_t i=0; i < count; ++i) {
781             ids[i] = generateSessionId();
782             IF_LOC_LOGD {
783                 idsString += std::to_string(ids[i]) + " ";
784             }
785         }
786     }
787     idsString += "]";
788 
789     LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags);
790 
791     struct MsgGnssUpdateConfig : public LocMsg {
792         GnssAdapter& mAdapter;
793         LocApiBase& mApi;
794         GnssConfig mConfig;
795         uint32_t* mIds;
796         size_t mCount;
797         inline MsgGnssUpdateConfig(GnssAdapter& adapter,
798                                    LocApiBase& api,
799                                    GnssConfig config,
800                                    uint32_t* ids,
801                                    size_t count) :
802             LocMsg(),
803             mAdapter(adapter),
804             mApi(api),
805             mConfig(config),
806             mIds(ids),
807             mCount(count) {}
808         inline virtual ~MsgGnssUpdateConfig()
809         {
810             delete[] mIds;
811         }
812         inline virtual void proc() const {
813             LocationError* errs = new LocationError[mCount];
814             LocationError err = LOCATION_ERROR_SUCCESS;
815             uint32_t index = 0;
816 
817             if (errs == nullptr) {
818                 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
819                 return;
820             }
821 
822             if (mConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
823                 uint32_t newGpsLock = mAdapter.convertGpsLock(mConfig.gpsLock);
824                 ContextBase::mGps_conf.GPS_LOCK = newGpsLock;
825                 if (0 == ContextBase::mGps_conf.GPS_LOCK) {
826                     // we should minimally lock MO
827                     ContextBase::mGps_conf.GPS_LOCK = 1;
828                 }
829                 if (0 == mAdapter.getPowerVoteId()) {
830                     err = mApi.setGpsLock(mConfig.gpsLock);
831                 }
832                 if (index < mCount) {
833                     errs[index++] = err;
834                 }
835             }
836             if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
837                 uint32_t newSuplVersion = mAdapter.convertSuplVersion(mConfig.suplVersion);
838                 if (newSuplVersion != ContextBase::mGps_conf.SUPL_VER &&
839                     ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
840                     ContextBase::mGps_conf.SUPL_VER = newSuplVersion;
841                     err = mApi.setSUPLVersion(mConfig.suplVersion);
842                 } else {
843                     err = LOCATION_ERROR_SUCCESS;
844                 }
845                 if (index < mCount) {
846                     errs[index++] = err;
847                 }
848             }
849             if (mConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
850                 if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) {
851                     err = mAdapter.setSuplHostServer(mConfig.assistanceServer.hostName,
852                                                      mConfig.assistanceServer.port);
853                 } else if (GNSS_ASSISTANCE_TYPE_C2K == mConfig.assistanceServer.type) {
854                     if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
855                         struct in_addr addr;
856                         if (!mAdapter.resolveInAddress(mConfig.assistanceServer.hostName,
857                                                        &addr)) {
858                             LOC_LOGE("%s]: hostName %s cannot be resolved",
859                                      __func__, mConfig.assistanceServer.hostName);
860                             err = LOCATION_ERROR_INVALID_PARAMETER;
861                         } else {
862                             unsigned int ip = htonl(addr.s_addr);
863                             err = mApi.setServer(ip, mConfig.assistanceServer.port,
864                                                     LOC_AGPS_CDMA_PDE_SERVER);
865                         }
866                     } else {
867                         err = LOCATION_ERROR_SUCCESS;
868                     }
869                 } else {
870                     LOC_LOGE("%s]: Not a valid gnss assistance type %u",
871                              __func__, mConfig.assistanceServer.type);
872                     err = LOCATION_ERROR_INVALID_PARAMETER;
873                 }
874                 if (index < mCount) {
875                     errs[index++] = err;
876                 }
877             }
878             if (mConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
879                 uint32_t newLppProfile = mAdapter.convertLppProfile(mConfig.lppProfile);
880                 if (newLppProfile != ContextBase::mGps_conf.LPP_PROFILE &&
881                     ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
882                     ContextBase::mGps_conf.LPP_PROFILE = newLppProfile;
883                     err = mApi.setLPPConfig(mConfig.lppProfile);
884                 } else {
885                     err = LOCATION_ERROR_SUCCESS;
886                 }
887                 if (index < mCount) {
888                     errs[index++] = err;
889                 }
890             }
891             if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
892                 uint32_t newLppeControlPlaneMask =
893                     mAdapter.convertLppeCp(mConfig.lppeControlPlaneMask);
894                 if (newLppeControlPlaneMask != ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY) {
895                     ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask;
896                     err = mApi.setLPPeProtocolCp(mConfig.lppeControlPlaneMask);
897                 } else {
898                     err = LOCATION_ERROR_SUCCESS;
899                 }
900                 if (index < mCount) {
901                     errs[index++] = err;
902                 }
903             }
904             if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
905                 uint32_t newLppeUserPlaneMask =
906                     mAdapter.convertLppeUp(mConfig.lppeUserPlaneMask);
907                 if (newLppeUserPlaneMask != ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY) {
908                     ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask;
909                     err = mApi.setLPPeProtocolUp(mConfig.lppeUserPlaneMask);
910                 } else {
911                     err = LOCATION_ERROR_SUCCESS;
912                 }
913                 if (index < mCount) {
914                     errs[index++] = err;
915                 }
916             }
917             if (mConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
918                 uint32_t newAGloProtMask =
919                     mAdapter.convertAGloProt(mConfig.aGlonassPositionProtocolMask);
920                 if (newAGloProtMask != ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT &&
921                     ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
922                     ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask;
923                     err = mApi.setAGLONASSProtocol(mConfig.aGlonassPositionProtocolMask);
924                 } else {
925                     err = LOCATION_ERROR_SUCCESS;
926                 }
927                 if (index < mCount) {
928                     errs[index++] = err;
929                 }
930             }
931             if (mConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
932                 uint32_t newEP4ES = mAdapter.convertEP4ES(mConfig.emergencyPdnForEmergencySupl);
933                 if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
934                     ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES;
935                 }
936                 err = LOCATION_ERROR_SUCCESS;
937                 if (index < mCount) {
938                     errs[index++] = err;
939                 }
940             }
941             if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
942                 uint32_t newSuplEs = mAdapter.convertSuplEs(mConfig.suplEmergencyServices);
943                 if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) {
944                     ContextBase::mGps_conf.SUPL_ES = newSuplEs;
945                 }
946                 err = LOCATION_ERROR_SUCCESS;
947                 if (index < mCount) {
948                     errs[index++] = err;
949                 }
950             }
951             if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
952                 uint32_t newSuplMode = mAdapter.convertSuplMode(mConfig.suplModeMask);
953                 if (newSuplMode != ContextBase::mGps_conf.SUPL_MODE) {
954                     ContextBase::mGps_conf.SUPL_MODE = newSuplMode;
955                     mAdapter.getUlpProxy()->setCapabilities(
956                         ContextBase::getCarrierCapabilities());
957                     mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
958                 }
959                 err = LOCATION_ERROR_SUCCESS;
960                 if (index < mCount) {
961                     errs[index++] = err;
962                 }
963             }
964             if (mConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
965                 // Check if feature is supported
966                 if (!mApi.isFeatureSupported(
967                         LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
968                     LOC_LOGe("Feature constellation enablement not supported.");
969                     err = LOCATION_ERROR_NOT_SUPPORTED;
970                 } else {
971                     // Send the SV ID Config to Modem
972                     err = mAdapter.gnssSvIdConfigUpdate(mConfig.blacklistedSvIds);
973                     if (LOCATION_ERROR_SUCCESS != err) {
974                         LOC_LOGe("Failed to send config to modem, err %d", err);
975                     }
976                 }
977                 if (index < mCount) {
978                     errs[index++] = err;
979                 }
980             }
981 
982             mAdapter.reportResponse(index, errs, mIds);
983             delete[] errs;
984         }
985     };
986 
987     if (NULL != ids) {
988         sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count));
989     } else {
990         LOC_LOGE("%s]: No GNSS config items to update", __func__);
991     }
992 
993     return ids;
994 }
995 
996 LocationError
gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource> & blacklistedSvIds)997 GnssAdapter::gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource>& blacklistedSvIds)
998 {
999     // Clear the existing config
1000     memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
1001 
1002     // Convert the sv id lists to masks
1003     bool convertSuccess = convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig);
1004 
1005     // Now send to Modem if conversion successful
1006     if (convertSuccess) {
1007         return gnssSvIdConfigUpdate();
1008     } else {
1009         LOC_LOGe("convertToGnssSvIdConfig failed");
1010         return LOCATION_ERROR_INVALID_PARAMETER;
1011     }
1012 }
1013 
1014 LocationError
gnssSvIdConfigUpdate()1015 GnssAdapter::gnssSvIdConfigUpdate()
1016 {
1017     LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1018             ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64,
1019             mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
1020             mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask);
1021 
1022     // Now set required blacklisted SVs
1023     return mLocApi->setBlacklistSv(mGnssSvIdConfig);
1024 }
1025 
1026 uint32_t*
gnssGetConfigCommand(GnssConfigFlagsMask configMask)1027 GnssAdapter::gnssGetConfigCommand(GnssConfigFlagsMask configMask) {
1028 
1029     // count the number of bits set
1030     GnssConfigFlagsMask flagsCopy = configMask;
1031     size_t count = 0;
1032     while (flagsCopy > 0) {
1033         if (flagsCopy & 1) {
1034             count++;
1035         }
1036         flagsCopy >>= 1;
1037     }
1038     std::string idsString = "[";
1039     uint32_t* ids = NULL;
1040     if (count > 0) {
1041         ids = new uint32_t[count];
1042         if (nullptr == ids) {
1043             LOC_LOGe("new allocation failed, fatal error.");
1044             return nullptr;
1045         }
1046         for (size_t i=0; i < count; ++i) {
1047             ids[i] = generateSessionId();
1048             IF_LOC_LOGD {
1049                 idsString += std::to_string(ids[i]) + " ";
1050             }
1051         }
1052     }
1053     idsString += "]";
1054 
1055     LOC_LOGd("ids %s flags 0x%X", idsString.c_str(), configMask);
1056 
1057     struct MsgGnssGetConfig : public LocMsg {
1058         GnssAdapter& mAdapter;
1059         LocApiBase& mApi;
1060         GnssConfigFlagsMask mConfigMask;
1061         uint32_t* mIds;
1062         size_t mCount;
1063         inline MsgGnssGetConfig(GnssAdapter& adapter,
1064                                 LocApiBase& api,
1065                                 GnssConfigFlagsMask configMask,
1066                                 uint32_t* ids,
1067                                 size_t count) :
1068             LocMsg(),
1069             mAdapter(adapter),
1070             mApi(api),
1071             mConfigMask(configMask),
1072             mIds(ids),
1073             mCount(count) {}
1074         inline virtual ~MsgGnssGetConfig()
1075         {
1076             delete[] mIds;
1077         }
1078         inline virtual void proc() const {
1079 
1080             LocationError* errs = new LocationError[mCount];
1081             LocationError err = LOCATION_ERROR_SUCCESS;
1082             uint32_t index = 0;
1083 
1084             if (nullptr == errs) {
1085                 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
1086                 return;
1087             }
1088 
1089             if (mConfigMask & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1090                 if (index < mCount) {
1091                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1092                 }
1093             }
1094             if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1095                 if (index < mCount) {
1096                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1097                 }
1098             }
1099             if (mConfigMask & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1100                 if (index < mCount) {
1101                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1102                 }
1103             }
1104             if (mConfigMask & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1105                 if (index < mCount) {
1106                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1107                 }
1108             }
1109             if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1110                 if (index < mCount) {
1111                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1112                 }
1113             }
1114             if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1115                 if (index < mCount) {
1116                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1117                 }
1118             }
1119             if (mConfigMask & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1120                 if (index < mCount) {
1121                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1122                 }
1123             }
1124             if (mConfigMask & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
1125                 if (index < mCount) {
1126                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1127                 }
1128             }
1129             if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
1130                 if (index < mCount) {
1131                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1132                 }
1133             }
1134             if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
1135                 err = LOCATION_ERROR_NOT_SUPPORTED;
1136                 if (index < mCount) {
1137                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1138                 }
1139             }
1140             if (mConfigMask & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
1141                 // Check if feature is supported
1142                 if (!mApi.isFeatureSupported(
1143                         LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1144                     LOC_LOGe("Feature not supported.");
1145                     err = LOCATION_ERROR_NOT_SUPPORTED;
1146                 } else {
1147                     // Send request to Modem to fetch the config
1148                     err = mApi.getBlacklistSv();
1149                     if (LOCATION_ERROR_SUCCESS != err) {
1150                         LOC_LOGe("getConfig request to modem failed, err %d", err);
1151                     }
1152                 }
1153                 if (index < mCount) {
1154                     errs[index++] = err;
1155                 }
1156             }
1157 
1158             mAdapter.reportResponse(index, errs, mIds);
1159             delete[] errs;
1160         }
1161     };
1162 
1163     if (NULL != ids) {
1164         sendMsg(new MsgGnssGetConfig(*this, *mLocApi, configMask, ids, count));
1165     } else {
1166         LOC_LOGe("No GNSS config items to Get");
1167     }
1168 
1169     return ids;
1170 }
1171 
1172 bool
convertToGnssSvIdConfig(const std::vector<GnssSvIdSource> & blacklistedSvIds,GnssSvIdConfig & config)1173 GnssAdapter::convertToGnssSvIdConfig(
1174         const std::vector<GnssSvIdSource>& blacklistedSvIds, GnssSvIdConfig& config)
1175 {
1176     bool retVal = true;
1177     config.size = sizeof(GnssSvIdConfig);
1178 
1179     // Empty vector => Clear any previous blacklisted SVs
1180     if (0 == blacklistedSvIds.size()) {
1181         config.gloBlacklistSvMask = 0;
1182         config.bdsBlacklistSvMask = 0;
1183         config.qzssBlacklistSvMask = 0;
1184         config.galBlacklistSvMask = 0;
1185     } else {
1186         // Parse the vector and convert SV IDs to mask values
1187         for (GnssSvIdSource source : blacklistedSvIds) {
1188             uint64_t* svMaskPtr = NULL;
1189             GnssSvId initialSvId = 0;
1190             GnssSvId lastSvId = 0;
1191             switch(source.constellation) {
1192             case GNSS_SV_TYPE_GLONASS:
1193                 svMaskPtr = &config.gloBlacklistSvMask;
1194                 initialSvId = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID;
1195                 lastSvId = GNSS_SV_CONFIG_GLO_LAST_SV_ID;
1196                 break;
1197             case GNSS_SV_TYPE_BEIDOU:
1198                 svMaskPtr = &config.bdsBlacklistSvMask;
1199                 initialSvId = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID;
1200                 lastSvId = GNSS_SV_CONFIG_BDS_LAST_SV_ID;
1201                 break;
1202             case GNSS_SV_TYPE_QZSS:
1203                 svMaskPtr = &config.qzssBlacklistSvMask;
1204                 initialSvId = GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID;
1205                 lastSvId = GNSS_SV_CONFIG_QZSS_LAST_SV_ID;
1206                 break;
1207             case GNSS_SV_TYPE_GALILEO:
1208                 svMaskPtr = &config.galBlacklistSvMask;
1209                 initialSvId = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID;
1210                 lastSvId = GNSS_SV_CONFIG_GAL_LAST_SV_ID;
1211                 break;
1212             default:
1213                 break;
1214             }
1215 
1216             if (NULL == svMaskPtr) {
1217                 LOC_LOGe("Invalid constellation %d", source.constellation);
1218             } else {
1219                 // SV ID 0 = All SV IDs
1220                 if (0 == source.svId) {
1221                     *svMaskPtr = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1222                 } else if (source.svId < initialSvId || source.svId > lastSvId) {
1223                     LOC_LOGe("Invalid sv id %d for sv type %d allowed range [%d, %d]",
1224                             source.svId, source.constellation, initialSvId, lastSvId);
1225                 } else {
1226                     *svMaskPtr |= ((uint64_t)1 << (source.svId - initialSvId));
1227                 }
1228             }
1229         }
1230     }
1231 
1232     return retVal;
1233 }
1234 
convertFromGnssSvIdConfig(const GnssSvIdConfig & svConfig,GnssConfig & config)1235 void GnssAdapter::convertFromGnssSvIdConfig(
1236         const GnssSvIdConfig& svConfig, GnssConfig& config)
1237 {
1238     // Convert blacklisted SV mask values to vectors
1239     if (svConfig.bdsBlacklistSvMask) {
1240         convertGnssSvIdMaskToList(
1241                 svConfig.bdsBlacklistSvMask, config.blacklistedSvIds,
1242                 GNSS_SV_CONFIG_BDS_INITIAL_SV_ID, GNSS_SV_TYPE_BEIDOU);
1243         config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1244     }
1245     if (svConfig.galBlacklistSvMask) {
1246         convertGnssSvIdMaskToList(
1247                 svConfig.galBlacklistSvMask, config.blacklistedSvIds,
1248                 GNSS_SV_CONFIG_GAL_INITIAL_SV_ID, GNSS_SV_TYPE_GALILEO);
1249         config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1250     }
1251     if (svConfig.gloBlacklistSvMask) {
1252         convertGnssSvIdMaskToList(
1253                 svConfig.gloBlacklistSvMask, config.blacklistedSvIds,
1254                 GNSS_SV_CONFIG_GLO_INITIAL_SV_ID, GNSS_SV_TYPE_GLONASS);
1255         config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1256     }
1257     if (svConfig.qzssBlacklistSvMask) {
1258         convertGnssSvIdMaskToList(
1259                 svConfig.qzssBlacklistSvMask, config.blacklistedSvIds,
1260                 GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID, GNSS_SV_TYPE_QZSS);
1261         config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1262     }
1263 }
1264 
convertGnssSvIdMaskToList(uint64_t svIdMask,std::vector<GnssSvIdSource> & svIds,GnssSvId initialSvId,GnssSvType svType)1265 void GnssAdapter::convertGnssSvIdMaskToList(
1266         uint64_t svIdMask, std::vector<GnssSvIdSource>& svIds,
1267         GnssSvId initialSvId, GnssSvType svType)
1268 {
1269     GnssSvIdSource source = {};
1270     source.size = sizeof(GnssSvIdSource);
1271     source.constellation = svType;
1272 
1273     // SV ID 0 => All SV IDs in mask
1274     if (GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK == svIdMask) {
1275         source.svId = 0;
1276         svIds.push_back(source);
1277         return;
1278     }
1279 
1280     // Convert each bit in svIdMask to vector entry
1281     uint32_t bitNumber = 0;
1282     while (svIdMask > 0) {
1283         if (svIdMask & 0x1) {
1284             source.svId = bitNumber + initialSvId;
1285             svIds.push_back(source);
1286         }
1287         bitNumber++;
1288         svIdMask >>= 1;
1289     }
1290 }
1291 
reportGnssSvIdConfigEvent(const GnssSvIdConfig & config)1292 void GnssAdapter::reportGnssSvIdConfigEvent(const GnssSvIdConfig& config)
1293 {
1294     struct MsgReportGnssSvIdConfig : public LocMsg {
1295         GnssAdapter& mAdapter;
1296         const GnssSvIdConfig mConfig;
1297         inline MsgReportGnssSvIdConfig(GnssAdapter& adapter,
1298                                  const GnssSvIdConfig& config) :
1299             LocMsg(),
1300             mAdapter(adapter),
1301             mConfig(config) {}
1302         inline virtual void proc() const {
1303             mAdapter.reportGnssSvIdConfig(mConfig);
1304         }
1305     };
1306 
1307     sendMsg(new MsgReportGnssSvIdConfig(*this, config));
1308 }
1309 
reportGnssSvIdConfig(const GnssSvIdConfig & svIdConfig)1310 void GnssAdapter::reportGnssSvIdConfig(const GnssSvIdConfig& svIdConfig)
1311 {
1312     GnssConfig config = {};
1313     config.size = sizeof(GnssConfig);
1314 
1315     // Invoke control clients config callback
1316     if (nullptr != mControlCallbacks.gnssConfigCb &&
1317             svIdConfig.size == sizeof(GnssSvIdConfig)) {
1318         convertFromGnssSvIdConfig(svIdConfig, config);
1319         LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1320                 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64,
1321                 svIdConfig.bdsBlacklistSvMask, svIdConfig.gloBlacklistSvMask,
1322                 svIdConfig.qzssBlacklistSvMask, svIdConfig.galBlacklistSvMask);
1323         mControlCallbacks.gnssConfigCb(config);
1324     } else {
1325         LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
1326     }
1327 }
1328 
1329 void
gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config)1330 GnssAdapter::gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config)
1331 {
1332     struct MsgGnssUpdateSvTypeConfig : public LocMsg {
1333         GnssAdapter* mAdapter;
1334         LocApiBase* mApi;
1335         GnssSvTypeConfig mConfig;
1336         inline MsgGnssUpdateSvTypeConfig(
1337                 GnssAdapter* adapter,
1338                 LocApiBase* api,
1339                 GnssSvTypeConfig& config) :
1340             LocMsg(),
1341             mAdapter(adapter),
1342             mApi(api),
1343             mConfig(config) {}
1344         inline virtual void proc() const {
1345             // Check if feature is supported
1346             if (!mApi->isFeatureSupported(
1347                     LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1348                 LOC_LOGe("Feature not supported.");
1349             } else {
1350                 // Send update request to modem
1351                 LocationError err = mAdapter->gnssSvTypeConfigUpdate(mConfig);
1352                 if (err != LOCATION_ERROR_SUCCESS) {
1353                     LOC_LOGe("Set constellation request failed, err %d", err);
1354                 }
1355             }
1356         }
1357     };
1358 
1359     sendMsg(new MsgGnssUpdateSvTypeConfig(this, mLocApi, config));
1360 }
1361 
1362 LocationError
gnssSvTypeConfigUpdate(const GnssSvTypeConfig & config)1363 GnssAdapter::gnssSvTypeConfigUpdate(const GnssSvTypeConfig& config)
1364 {
1365     gnssSetSvTypeConfig(config);
1366     return gnssSvTypeConfigUpdate();
1367 }
1368 
1369 LocationError
gnssSvTypeConfigUpdate()1370 GnssAdapter::gnssSvTypeConfigUpdate()
1371 {
1372     LocationError err = LOCATION_ERROR_GENERAL_FAILURE;
1373     LOC_LOGd("constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64,
1374              mGnssSvTypeConfig.blacklistedSvTypesMask, mGnssSvTypeConfig.enabledSvTypesMask);
1375 
1376     if (mGnssSvTypeConfig.size == sizeof(mGnssSvTypeConfig)) {
1377         GnssSvIdConfig blacklistConfig = {};
1378         // Revert to previously blacklisted SVs for each enabled constellation
1379         blacklistConfig = mGnssSvIdConfig;
1380         // Blacklist all SVs for each disabled constellation
1381         if (mGnssSvTypeConfig.blacklistedSvTypesMask) {
1382             if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GLO_BIT) {
1383                 blacklistConfig.gloBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1384             }
1385             if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_BDS_BIT) {
1386                 blacklistConfig.bdsBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1387             }
1388             if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_QZSS_BIT) {
1389                 blacklistConfig.qzssBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1390             }
1391             if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GAL_BIT) {
1392                 blacklistConfig.galBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1393             }
1394         }
1395 
1396         // Send blacklist info
1397         err = mLocApi->setBlacklistSv(blacklistConfig);
1398         if (LOCATION_ERROR_SUCCESS != err) {
1399             LOC_LOGE("Failed to send Set Blacklist");
1400         }
1401         // Send only enabled constellation config
1402         if (mGnssSvTypeConfig.enabledSvTypesMask) {
1403             GnssSvTypeConfig svTypeConfig = {sizeof(GnssSvTypeConfig), 0, 0};
1404             svTypeConfig.enabledSvTypesMask = mGnssSvTypeConfig.enabledSvTypesMask;
1405             err = mLocApi->setConstellationControl(svTypeConfig);
1406             if (LOCATION_ERROR_SUCCESS != err) {
1407                 LOC_LOGE("Failed to send Set Constellation");
1408             }
1409         }
1410     } else {
1411         LOC_LOGE("Invalid GnssSvTypeConfig size");
1412         err = LOCATION_ERROR_SUCCESS;
1413     }
1414 
1415     return err;
1416 }
1417 
1418 void
gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback)1419 GnssAdapter::gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback)
1420 {
1421     struct MsgGnssGetSvTypeConfig : public LocMsg {
1422         GnssAdapter* mAdapter;
1423         LocApiBase* mApi;
1424         GnssSvTypeConfigCallback mCallback;
1425         inline MsgGnssGetSvTypeConfig(
1426                 GnssAdapter* adapter,
1427                 LocApiBase* api,
1428                 GnssSvTypeConfigCallback callback) :
1429             LocMsg(),
1430             mAdapter(adapter),
1431             mApi(api),
1432             mCallback(callback) {}
1433         inline virtual void proc() const {
1434             if (!mApi->isFeatureSupported(
1435                     LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1436                 LOC_LOGe("Feature not supported.");
1437             } else {
1438                 // Save the callback
1439                 mAdapter->gnssSetSvTypeConfigCallback(mCallback);
1440                 // Send GET request to modem
1441                 LocationError err = mApi->getConstellationControl();
1442                 if (err != LOCATION_ERROR_SUCCESS) {
1443                     LOC_LOGe("Get constellation request failed, err %d", err);
1444                 }
1445             }
1446         }
1447     };
1448 
1449     sendMsg(new MsgGnssGetSvTypeConfig(this, mLocApi, callback));
1450 }
1451 
1452 void
gnssResetSvTypeConfigCommand()1453 GnssAdapter::gnssResetSvTypeConfigCommand()
1454 {
1455     struct MsgGnssResetSvTypeConfig : public LocMsg {
1456         GnssAdapter* mAdapter;
1457         LocApiBase* mApi;
1458         inline MsgGnssResetSvTypeConfig(
1459                 GnssAdapter* adapter,
1460                 LocApiBase* api) :
1461             LocMsg(),
1462             mAdapter(adapter),
1463             mApi(api) {}
1464         inline virtual void proc() const {
1465             if (!mApi->isFeatureSupported(
1466                     LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1467                 LOC_LOGe("Feature not supported.");
1468             } else {
1469                 // Reset constellation config
1470                 mAdapter->gnssSetSvTypeConfig({sizeof(GnssSvTypeConfig), 0, 0});
1471                 // Re-enforce SV blacklist config
1472                 LocationError err = mAdapter->gnssSvIdConfigUpdate();
1473                 if (err != LOCATION_ERROR_SUCCESS) {
1474                     LOC_LOGe("SV Config request failed, err %d", err);
1475                 }
1476                 // Send reset request to modem
1477                 err = mApi->resetConstellationControl();
1478                 if (err != LOCATION_ERROR_SUCCESS) {
1479                     LOC_LOGe("Reset constellation request failed, err %d", err);
1480                 }
1481             }
1482         }
1483     };
1484 
1485     sendMsg(new MsgGnssResetSvTypeConfig(this, mLocApi));
1486 }
1487 
reportGnssSvTypeConfigEvent(const GnssSvTypeConfig & config)1488 void GnssAdapter::reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config)
1489 {
1490     struct MsgReportGnssSvTypeConfig : public LocMsg {
1491         GnssAdapter& mAdapter;
1492         const GnssSvTypeConfig mConfig;
1493         inline MsgReportGnssSvTypeConfig(GnssAdapter& adapter,
1494                                  const GnssSvTypeConfig& config) :
1495             LocMsg(),
1496             mAdapter(adapter),
1497             mConfig(config) {}
1498         inline virtual void proc() const {
1499             mAdapter.reportGnssSvTypeConfig(mConfig);
1500         }
1501     };
1502 
1503     sendMsg(new MsgReportGnssSvTypeConfig(*this, config));
1504 }
1505 
reportGnssSvTypeConfig(const GnssSvTypeConfig & config)1506 void GnssAdapter::reportGnssSvTypeConfig(const GnssSvTypeConfig& config)
1507 {
1508     // Invoke Get SV Type Callback
1509     if (NULL != mGnssSvTypeConfigCb &&
1510             config.size == sizeof(GnssSvTypeConfig)) {
1511         LOC_LOGd("constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64,
1512                  config.blacklistedSvTypesMask, config.enabledSvTypesMask);
1513         mGnssSvTypeConfigCb(config);
1514     } else {
1515         LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
1516     }
1517 }
1518 
1519 uint32_t
gnssDeleteAidingDataCommand(GnssAidingData & data)1520 GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data)
1521 {
1522     uint32_t sessionId = generateSessionId();
1523     LOC_LOGD("%s]: id %u", __func__, sessionId);
1524 
1525     struct MsgDeleteAidingData : public LocMsg {
1526         GnssAdapter& mAdapter;
1527         LocApiBase& mApi;
1528         uint32_t mSessionId;
1529         GnssAidingData mData;
1530         inline MsgDeleteAidingData(GnssAdapter& adapter,
1531                                    LocApiBase& api,
1532                                    uint32_t sessionId,
1533                                    GnssAidingData& data) :
1534             LocMsg(),
1535             mAdapter(adapter),
1536             mApi(api),
1537             mSessionId(sessionId),
1538             mData(data) {}
1539         inline virtual void proc() const {
1540             LocationError err = LOCATION_ERROR_SUCCESS;
1541             err = mApi.deleteAidingData(mData);
1542             mAdapter.reportResponse(err, mSessionId);
1543             SystemStatus* s = mAdapter.getSystemStatus();
1544             if ((nullptr != s) && (mData.deleteAll)) {
1545                 s->setDefaultGnssEngineStates();
1546             }
1547         }
1548     };
1549 
1550     sendMsg(new MsgDeleteAidingData(*this, *mLocApi, sessionId, data));
1551     return sessionId;
1552 }
1553 
1554 void
gnssUpdateXtraThrottleCommand(const bool enabled)1555 GnssAdapter::gnssUpdateXtraThrottleCommand(const bool enabled)
1556 {
1557     LOC_LOGD("%s] enabled:%d", __func__, enabled);
1558 
1559     struct UpdateXtraThrottleMsg : public LocMsg {
1560         GnssAdapter& mAdapter;
1561         const bool mEnabled;
1562         inline UpdateXtraThrottleMsg(GnssAdapter& adapter, const bool enabled) :
1563             LocMsg(),
1564             mAdapter(adapter),
1565             mEnabled(enabled) {}
1566         inline virtual void proc() const {
1567                 mAdapter.mXtraObserver.updateXtraThrottle(mEnabled);
1568         }
1569     };
1570 
1571     sendMsg(new UpdateXtraThrottleMsg(*this, enabled));
1572 }
1573 
1574 void
injectLocationCommand(double latitude,double longitude,float accuracy)1575 GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy)
1576 {
1577     LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f",
1578              __func__, latitude, longitude, accuracy);
1579 
1580     struct MsgInjectLocation : public LocMsg {
1581         LocApiBase& mApi;
1582         ContextBase& mContext;
1583         double mLatitude;
1584         double mLongitude;
1585         float mAccuracy;
1586         inline MsgInjectLocation(LocApiBase& api,
1587                                  ContextBase& context,
1588                                  double latitude,
1589                                  double longitude,
1590                                  float accuracy) :
1591             LocMsg(),
1592             mApi(api),
1593             mContext(context),
1594             mLatitude(latitude),
1595             mLongitude(longitude),
1596             mAccuracy(accuracy) {}
1597         inline virtual void proc() const {
1598             if (!mContext.hasCPIExtendedCapabilities()) {
1599                 mApi.injectPosition(mLatitude, mLongitude, mAccuracy);
1600             }
1601         }
1602     };
1603 
1604     sendMsg(new MsgInjectLocation(*mLocApi, *mContext, latitude, longitude, accuracy));
1605 }
1606 
1607 void
injectTimeCommand(int64_t time,int64_t timeReference,int32_t uncertainty)1608 GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty)
1609 {
1610     LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d",
1611              __func__, (long long)time, (long long)timeReference, uncertainty);
1612 
1613     struct MsgInjectTime : public LocMsg {
1614         LocApiBase& mApi;
1615         ContextBase& mContext;
1616         int64_t mTime;
1617         int64_t mTimeReference;
1618         int32_t mUncertainty;
1619         inline MsgInjectTime(LocApiBase& api,
1620                              ContextBase& context,
1621                              int64_t time,
1622                              int64_t timeReference,
1623                              int32_t uncertainty) :
1624             LocMsg(),
1625             mApi(api),
1626             mContext(context),
1627             mTime(time),
1628             mTimeReference(timeReference),
1629             mUncertainty(uncertainty) {}
1630         inline virtual void proc() const {
1631             mApi.setTime(mTime, mTimeReference, mUncertainty);
1632         }
1633     };
1634 
1635     sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty));
1636 }
1637 
1638 void
setUlpProxyCommand(UlpProxyBase * ulp)1639 GnssAdapter::setUlpProxyCommand(UlpProxyBase* ulp)
1640 {
1641     LOC_LOGD("%s]: ", __func__);
1642 
1643     struct MsgSetUlpProxy : public LocMsg {
1644         GnssAdapter& mAdapter;
1645         UlpProxyBase* mUlp;
1646         inline MsgSetUlpProxy(GnssAdapter& adapter,
1647                               UlpProxyBase* ulp) :
1648             LocMsg(),
1649             mAdapter(adapter),
1650             mUlp(ulp) {}
1651         inline virtual void proc() const {
1652             mAdapter.setUlpProxy(mUlp);
1653             if (mUlp) {
1654                 mUlp->setCapabilities(ContextBase::getCarrierCapabilities());
1655             }
1656         }
1657     };
1658 
1659     sendMsg(new MsgSetUlpProxy(*this, ulp));
1660 }
1661 
1662 void
setUlpProxy(UlpProxyBase * ulp)1663 GnssAdapter::setUlpProxy(UlpProxyBase* ulp)
1664 {
1665     if (ulp == mUlpProxy) {
1666         //This takes care of the case when double initalization happens
1667         //and we get the same object back for UlpProxyBase . Do nothing
1668         return;
1669     }
1670 
1671     LOC_LOGV("%s]: %p", __func__, ulp);
1672     if (NULL == ulp) {
1673         LOC_LOGE("%s]: ulp pointer is NULL", __func__);
1674         ulp = new UlpProxyBase();
1675     }
1676 
1677     if (LOC_POSITION_MODE_INVALID != mUlpProxy->mPosMode.mode) {
1678         // need to send this mode and start msg to ULP
1679         ulp->sendFixMode(mUlpProxy->mPosMode);
1680     }
1681 
1682     if (mUlpProxy->mFixSet) {
1683         ulp->sendStartFix();
1684     }
1685 
1686     delete mUlpProxy;
1687     mUlpProxy = ulp;
1688 }
1689 
1690 void
addClientCommand(LocationAPI * client,const LocationCallbacks & callbacks)1691 GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks)
1692 {
1693     LOC_LOGD("%s]: client %p", __func__, client);
1694 
1695     struct MsgAddClient : public LocMsg {
1696         GnssAdapter& mAdapter;
1697         LocationAPI* mClient;
1698         const LocationCallbacks mCallbacks;
1699         inline MsgAddClient(GnssAdapter& adapter,
1700                             LocationAPI* client,
1701                             const LocationCallbacks& callbacks) :
1702             LocMsg(),
1703             mAdapter(adapter),
1704             mClient(client),
1705             mCallbacks(callbacks) {}
1706         inline virtual void proc() const {
1707             mAdapter.saveClient(mClient, mCallbacks);
1708         }
1709     };
1710 
1711     sendMsg(new MsgAddClient(*this, client, callbacks));
1712 }
1713 
1714 void
removeClientCommand(LocationAPI * client)1715 GnssAdapter::removeClientCommand(LocationAPI* client)
1716 {
1717     LOC_LOGD("%s]: client %p", __func__, client);
1718 
1719     struct MsgRemoveClient : public LocMsg {
1720         GnssAdapter& mAdapter;
1721         LocationAPI* mClient;
1722         inline MsgRemoveClient(GnssAdapter& adapter,
1723                                LocationAPI* client) :
1724             LocMsg(),
1725             mAdapter(adapter),
1726             mClient(client) {}
1727         inline virtual void proc() const {
1728             mAdapter.stopClientSessions(mClient);
1729             mAdapter.eraseClient(mClient);
1730         }
1731     };
1732 
1733     sendMsg(new MsgRemoveClient(*this, client));
1734 }
1735 
1736 void
stopClientSessions(LocationAPI * client)1737 GnssAdapter::stopClientSessions(LocationAPI* client)
1738 {
1739     LOC_LOGD("%s]: client %p", __func__, client);
1740     for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end();) {
1741         if (client == it->first.client) {
1742             LocationError err = stopTrackingMultiplex(it->first.client, it->first.id);
1743             if (LOCATION_ERROR_SUCCESS == err) {
1744                 it = mTrackingSessions.erase(it);
1745                 continue;
1746             }
1747         }
1748         ++it; // increment only when not erasing an iterator
1749     }
1750 }
1751 
1752 void
updateClientsEventMask()1753 GnssAdapter::updateClientsEventMask()
1754 {
1755     LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
1756     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
1757         if (it->second.trackingCb != nullptr || it->second.gnssLocationInfoCb != nullptr) {
1758             mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
1759         }
1760         if (it->second.gnssNiCb != nullptr) {
1761             mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
1762         }
1763         if (it->second.gnssSvCb != nullptr) {
1764             mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT;
1765         }
1766         if ((it->second.gnssNmeaCb != nullptr) && (mNmeaMask)) {
1767             mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
1768         }
1769         if (it->second.gnssMeasurementsCb != nullptr) {
1770             mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
1771         }
1772     }
1773 
1774     /*
1775     ** For Automotive use cases we need to enable MEASUREMENT and POLY
1776     ** when QDR is enabled
1777     */
1778     if (1 == ContextBase::mGps_conf.EXTERNAL_DR_ENABLED) {
1779         mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
1780         mask |= LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT;
1781 
1782         LOC_LOGD("%s]: Auto usecase, Enable MEAS/POLY - mask 0x%x", __func__, mask);
1783     }
1784 
1785     if (mAgpsCbInfo.statusV4Cb != NULL) {
1786         mask |= LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST;
1787     }
1788 
1789     // Add ODCPI handling
1790     if (nullptr != mOdcpiRequestCb) {
1791         mask |= LOC_API_ADAPTER_BIT_REQUEST_WIFI;
1792     }
1793 
1794     updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
1795 }
1796 
1797 void
handleEngineUpEvent()1798 GnssAdapter::handleEngineUpEvent()
1799 {
1800     struct MsgRestartSessions : public LocMsg {
1801         GnssAdapter& mAdapter;
1802         inline MsgRestartSessions(GnssAdapter& adapter) :
1803             LocMsg(),
1804             mAdapter(adapter) {}
1805         virtual void proc() const {
1806             mAdapter.restartSessions();
1807             mAdapter.gnssSvIdConfigUpdate();
1808             mAdapter.gnssSvTypeConfigUpdate();
1809         }
1810     };
1811 
1812     setConfigCommand();
1813     sendMsg(new MsgRestartSessions(*this));
1814 }
1815 
1816 void
restartSessions()1817 GnssAdapter::restartSessions()
1818 {
1819     LOC_LOGD("%s]: ", __func__);
1820 
1821     // odcpi session is no longer active after restart
1822     mOdcpiRequestActive = false;
1823 
1824     if (mTrackingSessions.empty()) {
1825         return;
1826     }
1827 
1828     // get the LocationOptions that has the smallest interval, which should be the active one
1829     TrackingOptions smallestIntervalOptions = {}; // size is zero until set for the first time
1830     TrackingOptions highestPowerTrackingOptions = {};
1831     for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
1832         // size of zero means we havent set it yet
1833         if (0 == smallestIntervalOptions.size ||
1834             it->second.minInterval < smallestIntervalOptions.minInterval) {
1835              smallestIntervalOptions = it->second;
1836         }
1837         GnssPowerMode powerMode = it->second.powerMode;
1838         // Size of zero means we havent set it yet
1839         if (0 == highestPowerTrackingOptions.size ||
1840             (GNSS_POWER_MODE_INVALID != powerMode &&
1841                     powerMode < highestPowerTrackingOptions.powerMode)) {
1842              highestPowerTrackingOptions = it->second;
1843         }
1844     }
1845 
1846     LocPosMode locPosMode = {};
1847     highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions);
1848     convertOptions(locPosMode, highestPowerTrackingOptions);
1849     mLocApi->startFix(locPosMode);
1850 }
1851 
1852 void
requestCapabilitiesCommand(LocationAPI * client)1853 GnssAdapter::requestCapabilitiesCommand(LocationAPI* client)
1854 {
1855     LOC_LOGD("%s]: ", __func__);
1856 
1857     struct MsgRequestCapabilities : public LocMsg {
1858         GnssAdapter& mAdapter;
1859         LocationAPI* mClient;
1860         inline MsgRequestCapabilities(GnssAdapter& adapter,
1861                                       LocationAPI* client) :
1862             LocMsg(),
1863             mAdapter(adapter),
1864             mClient(client) {}
1865         inline virtual void proc() const {
1866             LocationCallbacks callbacks = mAdapter.getClientCallbacks(mClient);
1867             if (callbacks.capabilitiesCb == nullptr) {
1868                 LOC_LOGE("%s]: capabilitiesCb is NULL", __func__);
1869                 return;
1870             }
1871 
1872             LocationCapabilitiesMask mask = mAdapter.getCapabilities();
1873             callbacks.capabilitiesCb(mask);
1874         }
1875     };
1876 
1877     sendMsg(new MsgRequestCapabilities(*this, client));
1878 }
1879 
1880 LocationCapabilitiesMask
getCapabilities()1881 GnssAdapter::getCapabilities()
1882 {
1883     LocationCapabilitiesMask mask = 0;
1884     uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities();
1885     // time based tracking always supported
1886     mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT;
1887     // geofence always supported
1888     mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT;
1889     if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) {
1890         mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT;
1891     }
1892     if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) {
1893         mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT;
1894     }
1895     if (mLocApi == nullptr)
1896         return mask;
1897     if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)) {
1898         mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT |
1899                 LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT;
1900     }
1901     if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
1902         mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT;
1903     }
1904     if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING)) {
1905         mask |= LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT;
1906     }
1907     if (mLocApi->gnssConstellationConfig()) {
1908         mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT;
1909     }
1910     if (mLocApi->isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
1911         mask |= LOCATION_CAPABILITIES_DEBUG_NMEA_BIT;
1912     }
1913     if (mLocApi->isFeatureSupported(LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1914         mask |= LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT;
1915     }
1916     if (mLocApi->isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) {
1917         mask |= LOCATION_CAPABILITIES_AGPM_BIT;
1918     }
1919     return mask;
1920 }
1921 
1922 void
broadcastCapabilities(LocationCapabilitiesMask mask)1923 GnssAdapter::broadcastCapabilities(LocationCapabilitiesMask mask)
1924 {
1925     for (auto it = mClientData.begin(); it != mClientData.end(); ++it) {
1926         if (nullptr != it->second.capabilitiesCb) {
1927             it->second.capabilitiesCb(mask);
1928         }
1929     }
1930 }
1931 
1932 LocationCallbacks
getClientCallbacks(LocationAPI * client)1933 GnssAdapter::getClientCallbacks(LocationAPI* client)
1934 {
1935     LocationCallbacks callbacks = {};
1936     auto it = mClientData.find(client);
1937     if (it != mClientData.end()) {
1938         callbacks = it->second;
1939     }
1940     return callbacks;
1941 }
1942 
1943 void
saveClient(LocationAPI * client,const LocationCallbacks & callbacks)1944 GnssAdapter::saveClient(LocationAPI* client, const LocationCallbacks& callbacks)
1945 {
1946     mClientData[client] = callbacks;
1947     updateClientsEventMask();
1948 }
1949 
1950 void
eraseClient(LocationAPI * client)1951 GnssAdapter::eraseClient(LocationAPI* client)
1952 {
1953     auto it = mClientData.find(client);
1954     if (it != mClientData.end()) {
1955         mClientData.erase(it);
1956     }
1957     updateClientsEventMask();
1958 }
1959 
1960 bool
hasTrackingCallback(LocationAPI * client)1961 GnssAdapter::hasTrackingCallback(LocationAPI* client)
1962 {
1963     auto it = mClientData.find(client);
1964     return (it != mClientData.end() && (it->second.trackingCb || it->second.gnssLocationInfoCb));
1965 }
1966 
1967 bool
hasMeasurementsCallback(LocationAPI * client)1968 GnssAdapter::hasMeasurementsCallback(LocationAPI* client)
1969 {
1970     auto it = mClientData.find(client);
1971     return (it != mClientData.end() && it->second.gnssMeasurementsCb);
1972 }
1973 
1974 bool
isTrackingSession(LocationAPI * client,uint32_t sessionId)1975 GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId)
1976 {
1977     LocationSessionKey key(client, sessionId);
1978     return (mTrackingSessions.find(key) != mTrackingSessions.end());
1979 }
1980 
1981 void
saveTrackingSession(LocationAPI * client,uint32_t sessionId,const TrackingOptions & trackingOptions)1982 GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId,
1983                                  const TrackingOptions& trackingOptions)
1984 {
1985     LocationSessionKey key(client, sessionId);
1986     mTrackingSessions[key] = trackingOptions;
1987 }
1988 
1989 void
eraseTrackingSession(LocationAPI * client,uint32_t sessionId)1990 GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId)
1991 {
1992     LocationSessionKey key(client, sessionId);
1993     auto itr = mTrackingSessions.find(key);
1994     if (itr != mTrackingSessions.end()) {
1995         mTrackingSessions.erase(itr);
1996     }
1997 }
1998 
setUlpPositionMode(const LocPosMode & mode)1999 bool GnssAdapter::setUlpPositionMode(const LocPosMode& mode) {
2000     if (!mUlpPositionMode.equals(mode)) {
2001         mUlpPositionMode = mode;
2002         return true;
2003     } else {
2004         return false;
2005     }
2006 }
2007 
2008 void
reportResponse(LocationAPI * client,LocationError err,uint32_t sessionId)2009 GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId)
2010 {
2011     LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err);
2012 
2013     auto it = mClientData.find(client);
2014     if (it != mClientData.end() &&
2015         it->second.responseCb != nullptr) {
2016         it->second.responseCb(err, sessionId);
2017     } else {
2018         LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId);
2019     }
2020 }
2021 
2022 void
reportResponse(LocationError err,uint32_t sessionId)2023 GnssAdapter::reportResponse(LocationError err, uint32_t sessionId)
2024 {
2025     LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err);
2026 
2027     if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) {
2028         mControlCallbacks.responseCb(err, sessionId);
2029     } else {
2030         LOC_LOGW("%s]: control client response callback not found", __func__);
2031     }
2032 }
2033 
2034 void
reportResponse(size_t count,LocationError * errs,uint32_t * ids)2035 GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids)
2036 {
2037     IF_LOC_LOGD {
2038         std::string idsString = "[";
2039         std::string errsString = "[";
2040         if (NULL != ids && NULL != errs) {
2041             for (size_t i=0; i < count; ++i) {
2042                 idsString += std::to_string(ids[i]) + " ";
2043                 errsString += std::to_string(errs[i]) + " ";
2044             }
2045         }
2046         idsString += "]";
2047         errsString += "]";
2048 
2049         LOC_LOGD("%s]: ids %s errs %s",
2050                  __func__, idsString.c_str(), errsString.c_str());
2051     }
2052 
2053     if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) {
2054         mControlCallbacks.collectiveResponseCb(count, errs, ids);
2055     } else {
2056         LOC_LOGW("%s]: control client callback not found", __func__);
2057     }
2058 }
2059 
2060 uint32_t
startTrackingCommand(LocationAPI * client,TrackingOptions & options)2061 GnssAdapter::startTrackingCommand(LocationAPI* client, TrackingOptions& options)
2062 {
2063     uint32_t sessionId = generateSessionId();
2064     LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u powermode %u tbm %u",
2065              __func__, client, sessionId, options.minInterval, options.minDistance, options.mode,
2066              options.powerMode, options.tbm);
2067 
2068     struct MsgStartTracking : public LocMsg {
2069         GnssAdapter& mAdapter;
2070         LocApiBase& mApi;
2071         LocationAPI* mClient;
2072         uint32_t mSessionId;
2073         mutable TrackingOptions mTrackingOptions;
2074         inline MsgStartTracking(GnssAdapter& adapter,
2075                                LocApiBase& api,
2076                                LocationAPI* client,
2077                                uint32_t sessionId,
2078                                TrackingOptions trackingOptions) :
2079             LocMsg(),
2080             mAdapter(adapter),
2081             mApi(api),
2082             mClient(client),
2083             mSessionId(sessionId),
2084             mTrackingOptions(trackingOptions) {}
2085         inline virtual void proc() const {
2086             LocationError err = LOCATION_ERROR_SUCCESS;
2087             if (!mAdapter.hasTrackingCallback(mClient) &&
2088                 !mAdapter.hasMeasurementsCallback(mClient)) {
2089                 err = LOCATION_ERROR_CALLBACK_MISSING;
2090             } else if (0 == mTrackingOptions.size) {
2091                 err = LOCATION_ERROR_INVALID_PARAMETER;
2092             } else {
2093                 if (GNSS_POWER_MODE_INVALID != mTrackingOptions.powerMode &&
2094                         !mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) {
2095                     LOC_LOGv("Ignoring power mode, feature not supported.");
2096                     mTrackingOptions.powerMode = GNSS_POWER_MODE_INVALID;
2097                 }
2098                 if (mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02) &&
2099                         GNSS_POWER_MODE_M4 == mTrackingOptions.powerMode &&
2100                         mTrackingOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
2101                     LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
2102                             mTrackingOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
2103                     mTrackingOptions.powerMode = GNSS_POWER_MODE_M2;
2104                 }
2105                 if (mTrackingOptions.minInterval < MIN_TRACKING_INTERVAL) {
2106                     mTrackingOptions.minInterval = MIN_TRACKING_INTERVAL;
2107                 }
2108                 // Api doesn't support multiple clients for time based tracking, so mutiplex
2109                 err = mAdapter.startTrackingMultiplex(mTrackingOptions);
2110                 if (LOCATION_ERROR_SUCCESS == err) {
2111                     mAdapter.saveTrackingSession(
2112                             mClient, mSessionId, mTrackingOptions);
2113                 }
2114             }
2115             mAdapter.reportResponse(mClient, err, mSessionId);
2116         }
2117     };
2118 
2119     sendMsg(new MsgStartTracking(
2120             *this, *mLocApi, client, sessionId, options));
2121     return sessionId;
2122 }
2123 
2124 LocationError
startTrackingMultiplex(const TrackingOptions & options)2125 GnssAdapter::startTrackingMultiplex(const TrackingOptions& options)
2126 {
2127     LocationError err = LOCATION_ERROR_SUCCESS;
2128 
2129     if (mTrackingSessions.empty()) {
2130         err = startTracking(options);
2131     } else {
2132         // find the smallest interval and powerMode
2133         TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
2134         GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
2135         for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
2136             // if not set or there is a new smallest interval, then set the new interval
2137             if (0 == multiplexedOptions.size ||
2138                 it->second.minInterval < multiplexedOptions.minInterval) {
2139                 multiplexedOptions = it->second;
2140             }
2141             // if session is not the one we are updating and either powerMode
2142             // is not set or there is a new smallest powerMode, then set the new powerMode
2143             if (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
2144                 it->second.powerMode < multiplexedPowerMode) {
2145                 multiplexedPowerMode = it->second.powerMode;
2146             }
2147         }
2148         bool updateOptions = false;
2149         // if session we are starting has smaller interval then next smallest
2150         if (options.minInterval < multiplexedOptions.minInterval) {
2151             multiplexedOptions.minInterval = options.minInterval;
2152             updateOptions = true;
2153         }
2154         // if session we are starting has smaller powerMode then next smallest
2155         if (options.powerMode < multiplexedPowerMode) {
2156             multiplexedOptions.powerMode = options.powerMode;
2157             updateOptions = true;
2158         }
2159         if (updateOptions) {
2160             // restart time based tracking with the newly updated options
2161             err = startTracking(multiplexedOptions);
2162         }
2163     }
2164 
2165     return err;
2166 }
2167 
2168 LocationError
startTracking(const TrackingOptions & trackingOptions)2169 GnssAdapter::startTracking(const TrackingOptions& trackingOptions)
2170 {
2171     LOC_LOGd("minInterval %u minDistance %u mode %u powermode %u tbm %u",
2172          trackingOptions.minInterval, trackingOptions.minDistance,
2173          trackingOptions.mode, trackingOptions.powerMode, trackingOptions.tbm);
2174 
2175     LocationError err = LOCATION_ERROR_SUCCESS;
2176     LocPosMode locPosMode = {};
2177     convertOptions(locPosMode, trackingOptions);
2178     if (!mUlpProxy->sendFixMode(locPosMode)) {
2179         // do nothing
2180     }
2181     if (!mUlpProxy->sendStartFix()) {
2182         loc_api_adapter_err apiErr = mLocApi->startFix(locPosMode);
2183         if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) {
2184             err = LOCATION_ERROR_SUCCESS;
2185         } else {
2186             err = LOCATION_ERROR_GENERAL_FAILURE;
2187         }
2188     }
2189 
2190     return err;
2191 }
2192 
2193 void
setPositionModeCommand(LocPosMode & locPosMode)2194 GnssAdapter::setPositionModeCommand(LocPosMode& locPosMode)
2195 {
2196     LOC_LOGD("%s]: min_interval %u mode %u",
2197              __func__, locPosMode.min_interval, locPosMode.mode);
2198 
2199     struct MsgSetPositionMode : public LocMsg {
2200         GnssAdapter& mAdapter;
2201         LocApiBase& mApi;
2202         LocPosMode mLocPosMode;
2203         inline MsgSetPositionMode(GnssAdapter& adapter,
2204                                   LocApiBase& api,
2205                                   LocPosMode& locPosMode) :
2206             LocMsg(),
2207             mAdapter(adapter),
2208             mApi(api),
2209             mLocPosMode(locPosMode) {}
2210         inline virtual void proc() const {
2211              // saves the mode in adapter to be used when startTrackingCommand is called from ULP
2212             if (mAdapter.setUlpPositionMode(mLocPosMode)) {
2213                 mApi.setPositionMode(mLocPosMode);
2214             }
2215         }
2216     };
2217 
2218     sendMsg(new MsgSetPositionMode(*this, *mLocApi, locPosMode));
2219 }
2220 
2221 void
startTrackingCommand()2222 GnssAdapter::startTrackingCommand()
2223 {
2224     LOC_LOGD("%s]: ", __func__);
2225 
2226     struct MsgStartTracking : public LocMsg {
2227         GnssAdapter& mAdapter;
2228         LocApiBase& mApi;
2229         inline MsgStartTracking(GnssAdapter& adapter,
2230                                 LocApiBase& api) :
2231             LocMsg(),
2232             mAdapter(adapter),
2233             mApi(api) {}
2234         inline virtual void proc() const {
2235             // we get this call from ULP, so just call LocApi without multiplexing because
2236             // ulp would be doing the multiplexing for us if it is present
2237             if (!mAdapter.isInSession()) {
2238                 LocPosMode& ulpPositionMode = mAdapter.getUlpPositionMode();
2239                 mApi.startFix(ulpPositionMode);
2240             }
2241         }
2242     };
2243 
2244     sendMsg(new MsgStartTracking(*this, *mLocApi));
2245 }
2246 
2247 void
updateTrackingOptionsCommand(LocationAPI * client,uint32_t id,TrackingOptions & options)2248 GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
2249                                           TrackingOptions& options)
2250 {
2251     LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
2252              __func__, client, id, options.minInterval, options.mode);
2253 
2254     struct MsgUpdateTracking : public LocMsg {
2255         GnssAdapter& mAdapter;
2256         LocApiBase& mApi;
2257         LocationAPI* mClient;
2258         uint32_t mSessionId;
2259         mutable TrackingOptions mTrackingOptions;
2260         inline MsgUpdateTracking(GnssAdapter& adapter,
2261                                 LocApiBase& api,
2262                                 LocationAPI* client,
2263                                 uint32_t sessionId,
2264                                 TrackingOptions trackingOptions) :
2265             LocMsg(),
2266             mAdapter(adapter),
2267             mApi(api),
2268             mClient(client),
2269             mSessionId(sessionId),
2270             mTrackingOptions(trackingOptions) {}
2271         inline virtual void proc() const {
2272             if (mAdapter.isTrackingSession(mClient, mSessionId)) {
2273                 LocationError err = LOCATION_ERROR_SUCCESS;
2274                 if (0 == mTrackingOptions.size) {
2275                     err = LOCATION_ERROR_INVALID_PARAMETER;
2276                 } else {
2277                     if (GNSS_POWER_MODE_INVALID != mTrackingOptions.powerMode &&
2278                             !mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) {
2279                         LOC_LOGv("Ignoring power mode, feature not supported.");
2280                         mTrackingOptions.powerMode = GNSS_POWER_MODE_INVALID;
2281                     }
2282                     if (mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02) &&
2283                             GNSS_POWER_MODE_M4 == mTrackingOptions.powerMode &&
2284                             mTrackingOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
2285                         LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
2286                                 mTrackingOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
2287                         mTrackingOptions.powerMode = GNSS_POWER_MODE_M2;
2288                     }
2289                     if (mTrackingOptions.minInterval < MIN_TRACKING_INTERVAL) {
2290                         mTrackingOptions.minInterval = MIN_TRACKING_INTERVAL;
2291                     }
2292                     // Api doesn't support multiple clients for time based tracking, so mutiplex
2293                     err = mAdapter.updateTrackingMultiplex(
2294                             mClient, mSessionId, mTrackingOptions);
2295                     if (LOCATION_ERROR_SUCCESS == err) {
2296                         mAdapter.saveTrackingSession(
2297                                 mClient, mSessionId, mTrackingOptions);
2298                     }
2299                 }
2300                 mAdapter.reportResponse(mClient, err, mSessionId);
2301             }
2302             // we do not reportResponse for the case where there is no existing tracking session
2303             // for the client and id being used, since updateTrackingCommand can be sent to both
2304             // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response
2305         }
2306     };
2307 
2308     sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options));
2309 }
2310 
2311 LocationError
updateTrackingMultiplex(LocationAPI * client,uint32_t id,const TrackingOptions & trackingOptions)2312 GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id,
2313                                      const TrackingOptions& trackingOptions)
2314 {
2315     LocationError err = LOCATION_ERROR_SUCCESS;
2316 
2317     LocationSessionKey key(client, id);
2318 
2319     // get the session we are updating
2320     auto it = mTrackingSessions.find(key);
2321     // if session we are updating exists and the minInterval or powerMode has changed
2322     if (it != mTrackingSessions.end() && (it->second.minInterval != trackingOptions.minInterval ||
2323         it->second.powerMode != trackingOptions.powerMode)) {
2324         // find the smallest interval and powerMode, other than the session we are updating
2325         TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
2326         GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
2327         for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
2328             // if session is not the one we are updating and either interval
2329             // is not set or there is a new smallest interval, then set the new interval
2330             if (it2->first != key && (0 == multiplexedOptions.size ||
2331                 it2->second.minInterval < multiplexedOptions.minInterval)) {
2332                  multiplexedOptions = it2->second;
2333             }
2334             // if session is not the one we are updating and either powerMode
2335             // is not set or there is a new smallest powerMode, then set the new powerMode
2336             if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
2337                 it2->second.powerMode < multiplexedPowerMode)) {
2338                 multiplexedPowerMode = it2->second.powerMode;
2339             }
2340         }
2341         bool updateOptions = false;
2342         // if session we are updating has smaller interval then next smallest
2343         if (trackingOptions.minInterval < multiplexedOptions.minInterval) {
2344             multiplexedOptions.minInterval = trackingOptions.minInterval;
2345             updateOptions = true;
2346         }
2347         // if session we are updating has smaller powerMode then next smallest
2348         if (trackingOptions.powerMode < multiplexedPowerMode) {
2349             multiplexedOptions.powerMode = trackingOptions.powerMode;
2350             updateOptions = true;
2351         }
2352         // if only one session exists, then tracking should be updated with it
2353         if (1 == mTrackingSessions.size()) {
2354             multiplexedOptions = trackingOptions;
2355             updateOptions = true;
2356         }
2357         if (updateOptions) {
2358             // restart time based tracking with the newly updated options
2359             err = startTracking(multiplexedOptions);
2360         }
2361     }
2362 
2363     return err;
2364 }
2365 
2366 void
stopTrackingCommand(LocationAPI * client,uint32_t id)2367 GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id)
2368 {
2369     LOC_LOGD("%s]: client %p id %u", __func__, client, id);
2370 
2371     struct MsgStopTracking : public LocMsg {
2372         GnssAdapter& mAdapter;
2373         LocApiBase& mApi;
2374         LocationAPI* mClient;
2375         uint32_t mSessionId;
2376         inline MsgStopTracking(GnssAdapter& adapter,
2377                                LocApiBase& api,
2378                                LocationAPI* client,
2379                                uint32_t sessionId) :
2380             LocMsg(),
2381             mAdapter(adapter),
2382             mApi(api),
2383             mClient(client),
2384             mSessionId(sessionId) {}
2385         inline virtual void proc() const {
2386             if (mAdapter.isTrackingSession(mClient, mSessionId)) {
2387                 LocationError err = LOCATION_ERROR_SUCCESS;
2388                 // Api doesn't support multiple clients for time based tracking, so mutiplex
2389                 err = mAdapter.stopTrackingMultiplex(mClient, mSessionId);
2390                 if (LOCATION_ERROR_SUCCESS == err) {
2391                     mAdapter.eraseTrackingSession(mClient, mSessionId);
2392                 }
2393                 mAdapter.reportResponse(mClient, err, mSessionId);
2394             }
2395             // we do not reportResponse for the case where there is no existing tracking session
2396             // for the client and id being used, since stopTrackingCommand can be sent to both
2397             // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response
2398 
2399         }
2400     };
2401 
2402     sendMsg(new MsgStopTracking(*this, *mLocApi, client, id));
2403 }
2404 
2405 LocationError
stopTrackingMultiplex(LocationAPI * client,uint32_t id)2406 GnssAdapter::stopTrackingMultiplex(LocationAPI* client, uint32_t id)
2407 {
2408     LocationError err = LOCATION_ERROR_SUCCESS;
2409 
2410     if (1 == mTrackingSessions.size()) {
2411         err = stopTracking();
2412     } else {
2413         LocationSessionKey key(client, id);
2414 
2415         // get the session we are stopping
2416         auto it = mTrackingSessions.find(key);
2417         if (it != mTrackingSessions.end()) {
2418             // find the smallest interval and powerMode, other than the session we are stopping
2419             TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
2420             GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
2421             for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
2422                 // if session is not the one we are stopping and either interval
2423                 // is not set or there is a new smallest interval, then set the new interval
2424                 if (it2->first != key && (0 == multiplexedOptions.size ||
2425                     it2->second.minInterval < multiplexedOptions.minInterval)) {
2426                      multiplexedOptions = it2->second;
2427                 }
2428                 // if session is not the one we are stopping and either powerMode
2429                 // is not set or there is a new smallest powerMode, then set the new powerMode
2430                 if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
2431                     it2->second.powerMode < multiplexedPowerMode)) {
2432                     multiplexedPowerMode = it2->second.powerMode;
2433                 }
2434             }
2435             // if session we are stopping has smaller interval then next smallest or
2436             // if session we are stopping has smaller powerMode then next smallest
2437             if (it->second.minInterval < multiplexedOptions.minInterval ||
2438                 it->second.powerMode < multiplexedPowerMode) {
2439                 multiplexedOptions.powerMode = multiplexedPowerMode;
2440                 // restart time based tracking with the newly updated options
2441                 err = startTracking(multiplexedOptions);
2442             }
2443         }
2444     }
2445 
2446     return err;
2447 }
2448 
2449 LocationError
stopTracking()2450 GnssAdapter::stopTracking()
2451 {
2452     LocationError err = LOCATION_ERROR_SUCCESS;
2453     if (!mUlpProxy->sendStopFix()) {
2454         loc_api_adapter_err apiErr = mLocApi->stopFix();
2455         if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) {
2456             err = LOCATION_ERROR_SUCCESS;
2457         } else {
2458             err = LOCATION_ERROR_GENERAL_FAILURE;
2459         }
2460     }
2461 
2462     return err;
2463 }
2464 
2465 void
stopTrackingCommand()2466 GnssAdapter::stopTrackingCommand()
2467 {
2468     LOC_LOGD("%s]: ", __func__);
2469 
2470     struct MsgStopTracking : public LocMsg {
2471         GnssAdapter& mAdapter;
2472         LocApiBase& mApi;
2473         inline MsgStopTracking(GnssAdapter& adapter,
2474                                LocApiBase& api) :
2475             LocMsg(),
2476             mAdapter(adapter),
2477             mApi(api) {}
2478         inline virtual void proc() const {
2479             // clear the position mode
2480             LocPosMode mLocPosMode = {};
2481             mLocPosMode.mode = LOC_POSITION_MODE_INVALID;
2482             mAdapter.setUlpPositionMode(mLocPosMode);
2483             // don't need to multiplex because ULP will do that for us if it is present
2484             mApi.stopFix();
2485         }
2486     };
2487 
2488     sendMsg(new MsgStopTracking(*this, *mLocApi));
2489 }
2490 
2491 void
getZppCommand()2492 GnssAdapter::getZppCommand()
2493 {
2494     LOC_LOGD("%s]: ", __func__);
2495 
2496     struct MsgGetZpp : public LocMsg {
2497         GnssAdapter& mAdapter;
2498         LocApiBase& mApi;
2499         inline MsgGetZpp(GnssAdapter& adapter,
2500                          LocApiBase& api) :
2501             LocMsg(),
2502             mAdapter(adapter),
2503             mApi(api) {}
2504         inline virtual void proc() const {
2505             UlpLocation location = {};
2506             LocPosTechMask techMask = LOC_POS_TECH_MASK_DEFAULT;
2507             GpsLocationExtended locationExtended = {};
2508             locationExtended.size = sizeof(locationExtended);
2509 
2510             mApi.getBestAvailableZppFix(location.gpsLocation, locationExtended,
2511                     techMask);
2512             //Mark the location source as from ZPP
2513             location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO;
2514             location.position_source = ULP_LOCATION_IS_FROM_ZPP;
2515 
2516             mAdapter.getUlpProxy()->reportPosition(location,
2517                                                    locationExtended,
2518                                                    LOC_SESS_SUCCESS,
2519                                                    techMask);
2520         }
2521     };
2522 
2523     sendMsg(new MsgGetZpp(*this, *mLocApi));
2524 }
2525 
2526 bool
hasNiNotifyCallback(LocationAPI * client)2527 GnssAdapter::hasNiNotifyCallback(LocationAPI* client)
2528 {
2529     auto it = mClientData.find(client);
2530     return (it != mClientData.end() && it->second.gnssNiCb);
2531 }
2532 
2533 void
gnssNiResponseCommand(LocationAPI * client,uint32_t id,GnssNiResponse response)2534 GnssAdapter::gnssNiResponseCommand(LocationAPI* client,
2535                                    uint32_t id,
2536                                    GnssNiResponse response)
2537 {
2538     LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response);
2539 
2540     struct MsgGnssNiResponse : public LocMsg {
2541         GnssAdapter& mAdapter;
2542         LocationAPI* mClient;
2543         uint32_t mSessionId;
2544         GnssNiResponse mResponse;
2545         inline MsgGnssNiResponse(GnssAdapter& adapter,
2546                                  LocationAPI* client,
2547                                  uint32_t sessionId,
2548                                  GnssNiResponse response) :
2549             LocMsg(),
2550             mAdapter(adapter),
2551             mClient(client),
2552             mSessionId(sessionId),
2553             mResponse(response) {}
2554         inline virtual void proc() const {
2555             NiData& niData = mAdapter.getNiData();
2556             LocationError err = LOCATION_ERROR_SUCCESS;
2557             if (!mAdapter.hasNiNotifyCallback(mClient)) {
2558                 err = LOCATION_ERROR_ID_UNKNOWN;
2559             } else {
2560                 NiSession* pSession = NULL;
2561                 if (mSessionId == niData.sessionEs.reqID &&
2562                     NULL != niData.sessionEs.rawRequest) {
2563                     pSession = &niData.sessionEs;
2564                     // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
2565                     if (mResponse == GNSS_NI_RESPONSE_ACCEPT &&
2566                         NULL != niData.session.rawRequest) {
2567                             pthread_mutex_lock(&niData.session.tLock);
2568                             niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
2569                             niData.session.respRecvd = true;
2570                             pthread_cond_signal(&niData.session.tCond);
2571                             pthread_mutex_unlock(&niData.session.tLock);
2572                     }
2573                 } else if (mSessionId == niData.session.reqID &&
2574                     NULL != niData.session.rawRequest) {
2575                     pSession = &niData.session;
2576                 }
2577 
2578                 if (pSession) {
2579                     LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u",
2580                              __func__, mResponse, mSessionId);
2581                     pthread_mutex_lock(&pSession->tLock);
2582                     pSession->resp = mResponse;
2583                     pSession->respRecvd = true;
2584                     pthread_cond_signal(&pSession->tCond);
2585                     pthread_mutex_unlock(&pSession->tLock);
2586                 } else {
2587                     err = LOCATION_ERROR_ID_UNKNOWN;
2588                     LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session",
2589                              __func__, mSessionId);
2590                 }
2591             }
2592             mAdapter.reportResponse(mClient, err, mSessionId);
2593         }
2594     };
2595 
2596     sendMsg(new MsgGnssNiResponse(*this, client, id, response));
2597 
2598 }
2599 
2600 void
gnssNiResponseCommand(GnssNiResponse response,void * rawRequest)2601 GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest)
2602 {
2603     LOC_LOGD("%s]: response %u", __func__, response);
2604 
2605     struct MsgGnssNiResponse : public LocMsg {
2606         LocApiBase& mApi;
2607         const GnssNiResponse mResponse;
2608         const void* mPayload;
2609         inline MsgGnssNiResponse(LocApiBase& api,
2610                                  const GnssNiResponse response,
2611                                  const void* rawRequest) :
2612             LocMsg(),
2613             mApi(api),
2614             mResponse(response),
2615             mPayload(rawRequest) {}
2616         inline virtual ~MsgGnssNiResponse() {
2617             // this is a bit weird since mPayload is not
2618             // allocated by this class.  But there is no better way.
2619             // mPayload actually won't be NULL here.
2620             free((void*)mPayload);
2621         }
2622         inline virtual void proc() const {
2623             mApi.informNiResponse(mResponse, mPayload);
2624         }
2625     };
2626 
2627     sendMsg(new MsgGnssNiResponse(*mLocApi, response, rawRequest));
2628 
2629 }
2630 
2631 uint32_t
enableCommand(LocationTechnologyType techType)2632 GnssAdapter::enableCommand(LocationTechnologyType techType)
2633 {
2634     uint32_t sessionId = generateSessionId();
2635     LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType);
2636 
2637     struct MsgEnableGnss : public LocMsg {
2638         GnssAdapter& mAdapter;
2639         LocApiBase& mApi;
2640         ContextBase& mContext;
2641         uint32_t mSessionId;
2642         LocationTechnologyType mTechType;
2643         inline MsgEnableGnss(GnssAdapter& adapter,
2644                              LocApiBase& api,
2645                              ContextBase& context,
2646                              uint32_t sessionId,
2647                              LocationTechnologyType techType) :
2648             LocMsg(),
2649             mAdapter(adapter),
2650             mApi(api),
2651             mContext(context),
2652             mSessionId(sessionId),
2653             mTechType(techType) {}
2654         inline virtual void proc() const {
2655             LocationError err = LOCATION_ERROR_SUCCESS;
2656             uint32_t powerVoteId = mAdapter.getPowerVoteId();
2657             if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) {
2658                 err = LOCATION_ERROR_INVALID_PARAMETER;
2659             } else if (powerVoteId > 0) {
2660                 err = LOCATION_ERROR_ALREADY_STARTED;
2661             } else {
2662                 mContext.modemPowerVote(true);
2663                 mAdapter.setPowerVoteId(mSessionId);
2664                 mApi.setGpsLock(GNSS_CONFIG_GPS_LOCK_NONE);
2665                 mAdapter.mXtraObserver.updateLockStatus(
2666                         mAdapter.convertGpsLock(GNSS_CONFIG_GPS_LOCK_NONE));
2667             }
2668             mAdapter.reportResponse(err, mSessionId);
2669         }
2670     };
2671 
2672     if (mContext != NULL) {
2673         sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType));
2674     } else {
2675         LOC_LOGE("%s]: Context is NULL", __func__);
2676     }
2677 
2678     return sessionId;
2679 }
2680 
2681 void
disableCommand(uint32_t id)2682 GnssAdapter::disableCommand(uint32_t id)
2683 {
2684     LOC_LOGD("%s]: id %u", __func__, id);
2685 
2686     struct MsgDisableGnss : public LocMsg {
2687         GnssAdapter& mAdapter;
2688         LocApiBase& mApi;
2689         ContextBase& mContext;
2690         uint32_t mSessionId;
2691         inline MsgDisableGnss(GnssAdapter& adapter,
2692                              LocApiBase& api,
2693                              ContextBase& context,
2694                              uint32_t sessionId) :
2695             LocMsg(),
2696             mAdapter(adapter),
2697             mApi(api),
2698             mContext(context),
2699             mSessionId(sessionId) {}
2700         inline virtual void proc() const {
2701             LocationError err = LOCATION_ERROR_SUCCESS;
2702             uint32_t powerVoteId = mAdapter.getPowerVoteId();
2703             if (powerVoteId != mSessionId) {
2704                 err = LOCATION_ERROR_ID_UNKNOWN;
2705             } else {
2706                 mContext.modemPowerVote(false);
2707                 mAdapter.setPowerVoteId(0);
2708                 mApi.setGpsLock(mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK));
2709                 mAdapter.mXtraObserver.updateLockStatus(
2710                         mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK));
2711             }
2712             mAdapter.reportResponse(err, mSessionId);
2713         }
2714     };
2715 
2716     if (mContext != NULL) {
2717         sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id));
2718     }
2719 
2720 }
2721 
2722 void
reportPositionEvent(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask,bool fromUlp)2723 GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation,
2724                                  const GpsLocationExtended& locationExtended,
2725                                  enum loc_sess_status status,
2726                                  LocPosTechMask techMask,
2727                                  bool fromUlp)
2728 {
2729     LOC_LOGD("%s]: fromUlp %u status %u", __func__, fromUlp, status);
2730 
2731     // if this event is not called from ULP, then try to call into ULP and return if successfull
2732     if (!fromUlp) {
2733         if (mUlpProxy->reportPosition(ulpLocation, locationExtended,
2734                                  status, techMask)) {
2735             return;
2736         }
2737     }
2738 
2739     struct MsgReportPosition : public LocMsg {
2740         GnssAdapter& mAdapter;
2741         const UlpLocation mUlpLocation;
2742         const GpsLocationExtended mLocationExtended;
2743         loc_sess_status mStatus;
2744         LocPosTechMask mTechMask;
2745         inline MsgReportPosition(GnssAdapter& adapter,
2746                                  const UlpLocation& ulpLocation,
2747                                  const GpsLocationExtended& locationExtended,
2748                                  loc_sess_status status,
2749                                  LocPosTechMask techMask) :
2750             LocMsg(),
2751             mAdapter(adapter),
2752             mUlpLocation(ulpLocation),
2753             mLocationExtended(locationExtended),
2754             mStatus(status),
2755             mTechMask(techMask) {}
2756         inline virtual void proc() const {
2757             // extract bug report info - this returns true if consumed by systemstatus
2758             SystemStatus* s = mAdapter.getSystemStatus();
2759             if ((nullptr != s) &&
2760                     ((LOC_SESS_SUCCESS == mStatus) || (LOC_SESS_INTERMEDIATE == mStatus))){
2761                 s->eventPosition(mUlpLocation, mLocationExtended);
2762             }
2763             mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask);
2764         }
2765     };
2766 
2767     sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended, status, techMask));
2768 }
2769 
2770 bool
needReport(const UlpLocation & ulpLocation,enum loc_sess_status status,LocPosTechMask techMask)2771 GnssAdapter::needReport(const UlpLocation& ulpLocation,
2772                         enum loc_sess_status status,
2773                         LocPosTechMask techMask) {
2774     bool reported = false;
2775 
2776     reported = LocApiBase::needReport(ulpLocation, status, techMask);
2777     return reported;
2778 }
2779 
2780 void
reportPosition(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask)2781 GnssAdapter::reportPosition(const UlpLocation& ulpLocation,
2782                             const GpsLocationExtended& locationExtended,
2783                             enum loc_sess_status status,
2784                             LocPosTechMask techMask)
2785 {
2786     bool reported = needReport(ulpLocation, status, techMask);
2787     mGnssSvIdUsedInPosAvail = false;
2788     if (reported) {
2789         if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) {
2790             mGnssSvIdUsedInPosAvail = true;
2791             mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids;
2792         }
2793 
2794         for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2795             if (nullptr != it->second.gnssLocationInfoCb) {
2796                 GnssLocationInfoNotification locationInfo = {};
2797                 convertLocationInfo(locationInfo, locationExtended);
2798                 convertLocation(locationInfo.location, ulpLocation, locationExtended, techMask);
2799                 it->second.gnssLocationInfoCb(locationInfo);
2800             } else if (nullptr != it->second.trackingCb) {
2801                 Location location = {};
2802                 convertLocation(location, ulpLocation, locationExtended, techMask);
2803                 it->second.trackingCb(location);
2804             }
2805         }
2806     }
2807 
2808     if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) {
2809         /*Only BlankNMEA sentence needs to be processed and sent, if both lat, long is 0 &
2810           horReliability is not set. */
2811         bool blank_fix = ((0 == ulpLocation.gpsLocation.latitude) &&
2812                           (0 == ulpLocation.gpsLocation.longitude) &&
2813                           (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability));
2814         uint8_t generate_nmea = (reported && status != LOC_SESS_FAILURE && !blank_fix);
2815         std::vector<std::string> nmeaArraystr;
2816         loc_nmea_generate_pos(ulpLocation, locationExtended, generate_nmea, nmeaArraystr);
2817         for (auto sentence : nmeaArraystr) {
2818             reportNmea(sentence.c_str(), sentence.length());
2819         }
2820     }
2821 }
2822 
2823 void
reportSvEvent(const GnssSvNotification & svNotify,bool fromUlp)2824 GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify,
2825                            bool fromUlp)
2826 {
2827     LOC_LOGD("%s]: fromUlp %u", __func__, fromUlp);
2828 
2829     // if this event is not called from ULP, then try to call into ULP and return if successfull
2830     if (!fromUlp) {
2831         if (mUlpProxy->reportSv(svNotify)) {
2832             return;
2833         }
2834     }
2835 
2836     struct MsgReportSv : public LocMsg {
2837         GnssAdapter& mAdapter;
2838         const GnssSvNotification mSvNotify;
2839         inline MsgReportSv(GnssAdapter& adapter,
2840                            const GnssSvNotification& svNotify) :
2841             LocMsg(),
2842             mAdapter(adapter),
2843             mSvNotify(svNotify) {}
2844         inline virtual void proc() const {
2845             mAdapter.reportSv((GnssSvNotification&)mSvNotify);
2846         }
2847     };
2848 
2849     sendMsg(new MsgReportSv(*this, svNotify));
2850 }
2851 
2852 void
reportSv(GnssSvNotification & svNotify)2853 GnssAdapter::reportSv(GnssSvNotification& svNotify)
2854 {
2855     int numSv = svNotify.count;
2856     int16_t gnssSvId = 0;
2857     uint64_t svUsedIdMask = 0;
2858     for (int i=0; i < numSv; i++) {
2859         svUsedIdMask = 0;
2860         gnssSvId = svNotify.gnssSvs[i].svId;
2861         switch (svNotify.gnssSvs[i].type) {
2862             case GNSS_SV_TYPE_GPS:
2863                 if (mGnssSvIdUsedInPosAvail) {
2864                     svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask;
2865                 }
2866                 break;
2867             case GNSS_SV_TYPE_GLONASS:
2868                 if (mGnssSvIdUsedInPosAvail) {
2869                     svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask;
2870                 }
2871                 break;
2872             case GNSS_SV_TYPE_BEIDOU:
2873                 if (mGnssSvIdUsedInPosAvail) {
2874                     svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask;
2875                 }
2876                 break;
2877             case GNSS_SV_TYPE_GALILEO:
2878                 if (mGnssSvIdUsedInPosAvail) {
2879                     svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask;
2880                 }
2881                 break;
2882             case GNSS_SV_TYPE_QZSS:
2883                 if (mGnssSvIdUsedInPosAvail) {
2884                     svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask;
2885                 }
2886                 // QZSS SV id's need to reported as it is to framework, since
2887                 // framework expects it as it is. See GnssStatus.java.
2888                 // SV id passed to here by LocApi is 1-based.
2889                 svNotify.gnssSvs[i].svId += (QZSS_SV_PRN_MIN - 1);
2890                 break;
2891             default:
2892                 svUsedIdMask = 0;
2893                 break;
2894         }
2895 
2896         // If SV ID was used in previous position fix, then set USED_IN_FIX
2897         // flag, else clear the USED_IN_FIX flag.
2898         if (svUsedIdMask & (1 << (gnssSvId - 1))) {
2899             svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
2900         }
2901     }
2902 
2903     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2904         if (nullptr != it->second.gnssSvCb) {
2905             it->second.gnssSvCb(svNotify);
2906         }
2907     }
2908 
2909     if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) {
2910         std::vector<std::string> nmeaArraystr;
2911         loc_nmea_generate_sv(svNotify, nmeaArraystr);
2912         for (auto sentence : nmeaArraystr) {
2913             reportNmea(sentence.c_str(), sentence.length());
2914         }
2915     }
2916 
2917     mGnssSvIdUsedInPosAvail = false;
2918 }
2919 
2920 void
reportNmeaEvent(const char * nmea,size_t length,bool fromUlp)2921 GnssAdapter::reportNmeaEvent(const char* nmea, size_t length, bool fromUlp)
2922 {
2923     // if this event is not called from ULP, then try to call into ULP and return if successfull
2924     if (!fromUlp && !loc_nmea_is_debug(nmea, length)) {
2925         if (mUlpProxy->reportNmea(nmea, length)) {
2926             return;
2927         }
2928     }
2929 
2930     struct MsgReportNmea : public LocMsg {
2931         GnssAdapter& mAdapter;
2932         const char* mNmea;
2933         size_t mLength;
2934         inline MsgReportNmea(GnssAdapter& adapter,
2935                              const char* nmea,
2936                              size_t length) :
2937             LocMsg(),
2938             mAdapter(adapter),
2939             mNmea(new char[length+1]),
2940             mLength(length) {
2941                 if (mNmea == nullptr) {
2942                     LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
2943                     return;
2944                 }
2945                 strlcpy((char*)mNmea, nmea, length+1);
2946             }
2947         inline virtual ~MsgReportNmea()
2948         {
2949             delete[] mNmea;
2950         }
2951         inline virtual void proc() const {
2952             // extract bug report info - this returns true if consumed by systemstatus
2953             bool ret = false;
2954             SystemStatus* s = mAdapter.getSystemStatus();
2955             if (nullptr != s) {
2956                 ret = s->setNmeaString(mNmea, mLength);
2957             }
2958             if (false == ret) {
2959                 // forward NMEA message to upper layer
2960                 mAdapter.reportNmea(mNmea, mLength);
2961             }
2962         }
2963     };
2964 
2965     sendMsg(new MsgReportNmea(*this, nmea, length));
2966 }
2967 
2968 void
reportNmea(const char * nmea,size_t length)2969 GnssAdapter::reportNmea(const char* nmea, size_t length)
2970 {
2971     GnssNmeaNotification nmeaNotification = {};
2972     nmeaNotification.size = sizeof(GnssNmeaNotification);
2973 
2974     struct timeval tv;
2975     gettimeofday(&tv, (struct timezone *) NULL);
2976     int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
2977     nmeaNotification.timestamp = now;
2978     nmeaNotification.nmea = nmea;
2979     nmeaNotification.length = length;
2980 
2981     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2982         if (nullptr != it->second.gnssNmeaCb) {
2983             it->second.gnssNmeaCb(nmeaNotification);
2984         }
2985     }
2986 }
2987 
2988 bool
requestNiNotifyEvent(const GnssNiNotification & notify,const void * data)2989 GnssAdapter::requestNiNotifyEvent(const GnssNiNotification &notify, const void* data)
2990 {
2991     LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d"
2992              "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s",
2993              __func__, notify.type, notify.timeout, notify.timeoutResponse,
2994              notify.requestor, notify.requestorEncoding,
2995              notify.message, notify.messageEncoding, notify.extras);
2996 
2997     struct MsgReportNiNotify : public LocMsg {
2998         GnssAdapter& mAdapter;
2999         const GnssNiNotification mNotify;
3000         const void* mData;
3001         inline MsgReportNiNotify(GnssAdapter& adapter,
3002                                  const GnssNiNotification& notify,
3003                                  const void* data) :
3004             LocMsg(),
3005             mAdapter(adapter),
3006             mNotify(notify),
3007             mData(data) {}
3008         inline virtual void proc() const {
3009             mAdapter.requestNiNotify(mNotify, mData);
3010         }
3011     };
3012 
3013     sendMsg(new MsgReportNiNotify(*this, notify, data));
3014 
3015     return true;
3016 }
3017 
niThreadProc(void * args)3018 static void* niThreadProc(void *args)
3019 {
3020     NiSession* pSession = (NiSession*)args;
3021     int rc = 0;          /* return code from pthread calls */
3022 
3023     struct timespec present_time;
3024     struct timespec expire_time;
3025 
3026     pthread_mutex_lock(&pSession->tLock);
3027     /* Calculate absolute expire time */
3028     clock_gettime(CLOCK_MONOTONIC, &present_time);
3029     expire_time.tv_sec  = present_time.tv_sec + pSession->respTimeLeft;
3030     expire_time.tv_nsec = present_time.tv_nsec;
3031     LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec",
3032              __func__, (long)expire_time.tv_sec, pSession->respTimeLeft);
3033 
3034     while (!pSession->respRecvd) {
3035         rc = pthread_cond_timedwait(&pSession->tCond,
3036                                     &pSession->tLock,
3037                                     &expire_time);
3038         if (rc == ETIMEDOUT) {
3039             pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE;
3040             LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d",
3041                      __func__, rc);
3042             break;
3043         }
3044     }
3045     LOC_LOGD("%s]: Java layer has sent us a user response and return value from "
3046              "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp);
3047     pSession->respRecvd = false; /* Reset the user response flag for the next session*/
3048 
3049     // adding this check to support modem restart, in which case, we need the thread
3050     // to exit without calling sending data. We made sure that rawRequest is NULL in
3051     // loc_eng_ni_reset_on_engine_restart()
3052     GnssAdapter* adapter = pSession->adapter;
3053     GnssNiResponse resp;
3054     void* rawRequest = NULL;
3055     bool sendResponse = false;
3056 
3057     if (NULL != pSession->rawRequest) {
3058         if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) {
3059             resp = pSession->resp;
3060             rawRequest = pSession->rawRequest;
3061             sendResponse = true;
3062         } else {
3063             free(pSession->rawRequest);
3064         }
3065         pSession->rawRequest = NULL;
3066     }
3067     pthread_mutex_unlock(&pSession->tLock);
3068 
3069     pSession->respTimeLeft = 0;
3070     pSession->reqID = 0;
3071 
3072     if (sendResponse) {
3073         adapter->gnssNiResponseCommand(resp, rawRequest);
3074     }
3075 
3076     return NULL;
3077 }
3078 
3079 bool
requestNiNotify(const GnssNiNotification & notify,const void * data)3080 GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data)
3081 {
3082     NiSession* pSession = NULL;
3083     gnssNiCallback gnssNiCb = nullptr;
3084 
3085     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3086         if (nullptr != it->second.gnssNiCb) {
3087             gnssNiCb = it->second.gnssNiCb;
3088             break;
3089         }
3090     }
3091     if (nullptr == gnssNiCb) {
3092         EXIT_LOG(%s, "no clients with gnssNiCb.");
3093         return false;
3094     }
3095 
3096     if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) {
3097         if (NULL != mNiData.sessionEs.rawRequest) {
3098             LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d",
3099                      __func__, notify.type);
3100             if (NULL != data) {
3101                 free((void*)data);
3102             }
3103         } else {
3104             pSession = &mNiData.sessionEs;
3105         }
3106     } else {
3107         if (NULL != mNiData.session.rawRequest ||
3108             NULL != mNiData.sessionEs.rawRequest) {
3109             LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d",
3110                      __func__, notify.type);
3111             if (NULL != data) {
3112                 free((void*)data);
3113             }
3114         } else {
3115             pSession = &mNiData.session;
3116         }
3117     }
3118 
3119     if (pSession) {
3120         /* Save request */
3121         pSession->rawRequest = (void*)data;
3122         pSession->reqID = ++mNiData.reqIDCounter;
3123         pSession->adapter = this;
3124 
3125         int sessionId = pSession->reqID;
3126 
3127         /* For robustness, spawn a thread at this point to timeout to clear up the notification
3128          * status, even though the OEM layer in java does not do so.
3129          **/
3130         pSession->respTimeLeft =
3131              5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME);
3132 
3133         int rc = 0;
3134         rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession);
3135         if (rc) {
3136             LOC_LOGE("%s]: Loc NI thread is not created.", __func__);
3137         }
3138         rc = pthread_detach(pSession->thread);
3139         if (rc) {
3140             LOC_LOGE("%s]: Loc NI thread is not detached.", __func__);
3141         }
3142 
3143         if (nullptr != gnssNiCb) {
3144             gnssNiCb(sessionId, notify);
3145         }
3146     }
3147 
3148     return true;
3149 }
3150 
3151 void
reportGnssMeasurementDataEvent(const GnssMeasurementsNotification & measurements,int msInWeek)3152 GnssAdapter::reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurements,
3153                                             int msInWeek)
3154 {
3155     LOC_LOGD("%s]: msInWeek=%d", __func__, msInWeek);
3156 
3157     struct MsgReportGnssMeasurementData : public LocMsg {
3158         GnssAdapter& mAdapter;
3159         GnssMeasurementsNotification mMeasurementsNotify;
3160         inline MsgReportGnssMeasurementData(GnssAdapter& adapter,
3161                                             const GnssMeasurementsNotification& measurements,
3162                                             int msInWeek) :
3163                 LocMsg(),
3164                 mAdapter(adapter),
3165                 mMeasurementsNotify(measurements) {
3166             if (-1 != msInWeek) {
3167                 mAdapter.getAgcInformation(mMeasurementsNotify, msInWeek);
3168             }
3169         }
3170         inline virtual void proc() const {
3171             mAdapter.reportGnssMeasurementData(mMeasurementsNotify);
3172         }
3173     };
3174 
3175     sendMsg(new MsgReportGnssMeasurementData(*this, measurements, msInWeek));
3176 }
3177 
3178 void
reportGnssMeasurementData(const GnssMeasurementsNotification & measurements)3179 GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurements)
3180 {
3181     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3182         if (nullptr != it->second.gnssMeasurementsCb) {
3183             it->second.gnssMeasurementsCb(measurements);
3184         }
3185     }
3186 }
3187 
3188 void
reportSvMeasurementEvent(GnssSvMeasurementSet & svMeasurementSet)3189 GnssAdapter::reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet)
3190 {
3191     LOC_LOGD("%s]: ", __func__);
3192 
3193     // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
3194     mUlpProxy->reportSvMeasurement(svMeasurementSet);
3195 }
3196 
3197 void
reportSvPolynomialEvent(GnssSvPolynomial & svPolynomial)3198 GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial)
3199 {
3200     LOC_LOGD("%s]: ", __func__);
3201 
3202     // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
3203     mUlpProxy->reportSvPolynomial(svPolynomial);
3204 }
3205 
3206 bool
reportOdcpiRequestEvent(OdcpiRequestInfo & request)3207 GnssAdapter::reportOdcpiRequestEvent(OdcpiRequestInfo& request)
3208 {
3209     struct MsgReportOdcpiRequest : public LocMsg {
3210         GnssAdapter& mAdapter;
3211         OdcpiRequestInfo mOdcpiRequest;
3212         inline MsgReportOdcpiRequest(GnssAdapter& adapter, OdcpiRequestInfo& request) :
3213                 LocMsg(),
3214                 mAdapter(adapter),
3215                 mOdcpiRequest(request) {}
3216         inline virtual void proc() const {
3217             mAdapter.reportOdcpiRequest(mOdcpiRequest);
3218         }
3219     };
3220 
3221     sendMsg(new MsgReportOdcpiRequest(*this, request));
3222     return true;
3223 }
3224 
reportOdcpiRequest(const OdcpiRequestInfo & request)3225 void GnssAdapter::reportOdcpiRequest(const OdcpiRequestInfo& request)
3226 {
3227     if (nullptr != mOdcpiRequestCb) {
3228         LOC_LOGd("request: type %d, tbf %d, isEmergency %d"
3229                  " requestActive: %d timerActive: %d",
3230                  request.type, request.tbfMillis, request.isEmergencyMode,
3231                  mOdcpiRequestActive, mOdcpiTimer.isActive());
3232         // ODCPI START and ODCPI STOP from modem can come in quick succession
3233         // so the mOdcpiTimer helps avoid spamming the framework as well as
3234         // extending the odcpi session past 30 seconds if needed
3235         if (ODCPI_REQUEST_TYPE_START == request.type) {
3236             if (false == mOdcpiRequestActive && false == mOdcpiTimer.isActive()) {
3237                 mOdcpiRequestCb(request);
3238                 mOdcpiRequestActive = true;
3239                 mOdcpiTimer.start();
3240             // if the current active odcpi session is non-emergency, and the new
3241             // odcpi request is emergency, replace the odcpi request with new request
3242             // and restart the timer
3243             } else if (false == mOdcpiRequest.isEmergencyMode &&
3244                        true == request.isEmergencyMode) {
3245                 mOdcpiRequestCb(request);
3246                 mOdcpiRequestActive = true;
3247                 if (true == mOdcpiTimer.isActive()) {
3248                     mOdcpiTimer.restart();
3249                 } else {
3250                     mOdcpiTimer.start();
3251                 }
3252             // if ODCPI request is not active but the timer is active, then
3253             // just update the active state and wait for timer to expire
3254             // before requesting new ODCPI to avoid spamming ODCPI requests
3255             } else if (false == mOdcpiRequestActive && true == mOdcpiTimer.isActive()) {
3256                 mOdcpiRequestActive = true;
3257             }
3258             mOdcpiRequest = request;
3259         // the request is being stopped, but allow timer to expire first
3260         // before stopping the timer just in case more ODCPI requests come
3261         // to avoid spamming more odcpi requests to the framework
3262         } else {
3263             mOdcpiRequestActive = false;
3264         }
3265     } else {
3266         LOC_LOGw("ODCPI request not supported");
3267     }
3268 }
3269 
initOdcpiCommand(const OdcpiRequestCallback & callback)3270 void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback)
3271 {
3272     struct MsgInitOdcpi : public LocMsg {
3273         GnssAdapter& mAdapter;
3274         OdcpiRequestCallback mOdcpiCb;
3275         inline MsgInitOdcpi(GnssAdapter& adapter,
3276                 const OdcpiRequestCallback& callback) :
3277                 LocMsg(),
3278                 mAdapter(adapter),
3279                 mOdcpiCb(callback) {}
3280         inline virtual void proc() const {
3281             mAdapter.initOdcpi(mOdcpiCb);
3282         }
3283     };
3284 
3285     sendMsg(new MsgInitOdcpi(*this, callback));
3286 }
3287 
initOdcpi(const OdcpiRequestCallback & callback)3288 void GnssAdapter::initOdcpi(const OdcpiRequestCallback& callback)
3289 {
3290     mOdcpiRequestCb = callback;
3291 
3292     /* Register for WIFI request */
3293     updateEvtMask(LOC_API_ADAPTER_BIT_REQUEST_WIFI,
3294             LOC_REGISTRATION_MASK_ENABLED);
3295 }
3296 
injectOdcpiCommand(const Location & location)3297 void GnssAdapter::injectOdcpiCommand(const Location& location)
3298 {
3299     struct MsgInjectOdcpi : public LocMsg {
3300         GnssAdapter& mAdapter;
3301         Location mLocation;
3302         inline MsgInjectOdcpi(GnssAdapter& adapter, const Location& location) :
3303                 LocMsg(),
3304                 mAdapter(adapter),
3305                 mLocation(location) {}
3306         inline virtual void proc() const {
3307             mAdapter.injectOdcpi(mLocation);
3308         }
3309     };
3310 
3311     sendMsg(new MsgInjectOdcpi(*this, location));
3312 }
3313 
injectOdcpi(const Location & location)3314 void GnssAdapter::injectOdcpi(const Location& location)
3315 {
3316     LOC_LOGd("ODCPI Injection: requestActive: %d timerActive: %d"
3317              "lat %.7f long %.7f",
3318             mOdcpiRequestActive, mOdcpiTimer.isActive(),
3319             location.latitude, location.longitude);
3320 
3321     loc_api_adapter_err err = mLocApi->injectPosition(location);
3322     if (LOC_API_ADAPTER_ERR_SUCCESS != err) {
3323         LOC_LOGe("Inject Position API error %d", err);
3324     }
3325 }
3326 
3327 // Called in the context of LocTimer thread
timeOutCallback()3328 void OdcpiTimer::timeOutCallback()
3329 {
3330     if (nullptr != mAdapter) {
3331         mAdapter->odcpiTimerExpireEvent();
3332     }
3333 }
3334 
3335 // Called in the context of LocTimer thread
odcpiTimerExpireEvent()3336 void GnssAdapter::odcpiTimerExpireEvent()
3337 {
3338     struct MsgOdcpiTimerExpire : public LocMsg {
3339         GnssAdapter& mAdapter;
3340         inline MsgOdcpiTimerExpire(GnssAdapter& adapter) :
3341                 LocMsg(),
3342                 mAdapter(adapter) {}
3343         inline virtual void proc() const {
3344             mAdapter.odcpiTimerExpire();
3345         }
3346     };
3347     sendMsg(new MsgOdcpiTimerExpire(*this));
3348 }
odcpiTimerExpire()3349 void GnssAdapter::odcpiTimerExpire()
3350 {
3351     LOC_LOGd("requestActive: %d timerActive: %d",
3352             mOdcpiRequestActive, mOdcpiTimer.isActive());
3353 
3354     // if ODCPI request is still active after timer
3355     // expires, request again and restart timer
3356     if (mOdcpiRequestActive) {
3357         mOdcpiRequestCb(mOdcpiRequest);
3358         mOdcpiTimer.restart();
3359     } else {
3360         mOdcpiTimer.stop();
3361     }
3362 }
3363 
initDefaultAgps()3364 void GnssAdapter::initDefaultAgps() {
3365     LOC_LOGD("%s]: ", __func__);
3366 
3367     void *handle = nullptr;
3368     if ((handle = dlopen("libloc_net_iface.so", RTLD_NOW)) == nullptr) {
3369         LOC_LOGD("%s]: libloc_net_iface.so not found !", __func__);
3370         return;
3371     }
3372 
3373     LocAgpsGetAgpsCbInfo getAgpsCbInfo = (LocAgpsGetAgpsCbInfo)
3374             dlsym(handle, "LocNetIfaceAgps_getAgpsCbInfo");
3375     if (getAgpsCbInfo == nullptr) {
3376         LOC_LOGE("%s]: Failed to get method LocNetIfaceAgps_getStatusCb", __func__);
3377         return;
3378     }
3379 
3380     AgpsCbInfo& cbInfo = getAgpsCbInfo(agpsOpenResultCb, agpsCloseResultCb, this);
3381 
3382     if (cbInfo.statusV4Cb == nullptr) {
3383         LOC_LOGE("%s]: statusV4Cb is nullptr!", __func__);
3384         return;
3385     }
3386 
3387     initAgps(cbInfo);
3388 }
3389 
initDefaultAgpsCommand()3390 void GnssAdapter::initDefaultAgpsCommand() {
3391     LOC_LOGD("%s]: ", __func__);
3392 
3393     struct MsgInitDefaultAgps : public LocMsg {
3394         GnssAdapter& mAdapter;
3395         inline MsgInitDefaultAgps(GnssAdapter& adapter) :
3396             LocMsg(),
3397             mAdapter(adapter) {
3398             }
3399         inline virtual void proc() const {
3400             mAdapter.initDefaultAgps();
3401         }
3402     };
3403 
3404     sendMsg(new MsgInitDefaultAgps(*this));
3405 }
3406 
3407 /* INIT LOC AGPS MANAGER */
3408 
initAgps(const AgpsCbInfo & cbInfo)3409 void GnssAdapter::initAgps(const AgpsCbInfo& cbInfo) {
3410     LOC_LOGD("%s]: mAgpsCbInfo.cbPriority - %d;  cbInfo.cbPriority - %d",
3411             __func__, mAgpsCbInfo.cbPriority, cbInfo.cbPriority)
3412 
3413     if (!((ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSB) ||
3414             (ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSA))) {
3415         return;
3416     }
3417 
3418     if (mAgpsCbInfo.cbPriority > cbInfo.cbPriority) {
3419         return;
3420     } else {
3421         mAgpsCbInfo = cbInfo;
3422 
3423         mAgpsManager.registerFrameworkStatusCallback((AgnssStatusIpV4Cb)cbInfo.statusV4Cb);
3424 
3425         mAgpsManager.createAgpsStateMachines();
3426 
3427         /* Register for AGPS event mask */
3428         updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST,
3429                 LOC_REGISTRATION_MASK_ENABLED);
3430     }
3431 }
3432 
initAgpsCommand(const AgpsCbInfo & cbInfo)3433 void GnssAdapter::initAgpsCommand(const AgpsCbInfo& cbInfo){
3434     LOC_LOGI("GnssAdapter::initAgpsCommand");
3435 
3436     /* Message to initialize AGPS module */
3437     struct AgpsMsgInit: public LocMsg {
3438         const AgpsCbInfo mCbInfo;
3439         GnssAdapter& mAdapter;
3440 
3441         inline AgpsMsgInit(const AgpsCbInfo& cbInfo,
3442                 GnssAdapter& adapter) :
3443                 LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) {
3444             LOC_LOGV("AgpsMsgInit");
3445         }
3446 
3447         inline virtual void proc() const {
3448             LOC_LOGV("AgpsMsgInit::proc()");
3449             mAdapter.initAgps(mCbInfo);
3450         }
3451     };
3452 
3453     /* Send message to initialize AGPS Manager */
3454     sendMsg(new AgpsMsgInit(cbInfo, *this));
3455 }
3456 
3457 /* GnssAdapter::requestATL
3458  * Method triggered in QMI thread as part of handling below message:
3459  * eQMI_LOC_SERVER_REQUEST_OPEN_V02
3460  * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
3461  * eQMI_LOC_WWAN_TYPE_INTERNET_V02
3462  * eQMI_LOC_WWAN_TYPE_AGNSS_V02 */
requestATL(int connHandle,LocAGpsType agpsType,LocApnTypeMask mask)3463 bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType, LocApnTypeMask mask){
3464 
3465     LOC_LOGI("GnssAdapter::requestATL");
3466 
3467     sendMsg( new AgpsMsgRequestATL(
3468              &mAgpsManager, connHandle, (AGpsExtType)agpsType, mask));
3469 
3470     return true;
3471 }
3472 
3473 /* GnssAdapter::requestSuplES
3474  * Method triggered in QMI thread as part of handling below message:
3475  * eQMI_LOC_SERVER_REQUEST_OPEN_V02
3476  * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
3477  * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */
requestSuplES(int connHandle,LocApnTypeMask mask)3478 bool GnssAdapter::requestSuplES(int connHandle, LocApnTypeMask mask){
3479 
3480     LOC_LOGI("GnssAdapter::requestSuplES");
3481 
3482     sendMsg( new AgpsMsgRequestATL(
3483              &mAgpsManager, connHandle, LOC_AGPS_TYPE_SUPL_ES, mask));
3484 
3485     return true;
3486 }
3487 
3488 /* GnssAdapter::releaseATL
3489  * Method triggered in QMI thread as part of handling below message:
3490  * eQMI_LOC_SERVER_REQUEST_CLOSE_V02
3491  * Triggers teardown of an existing AGPS call */
releaseATL(int connHandle)3492 bool GnssAdapter::releaseATL(int connHandle){
3493 
3494     LOC_LOGI("GnssAdapter::releaseATL");
3495 
3496     /* Release SUPL/INTERNET/SUPL_ES ATL */
3497     struct AgpsMsgReleaseATL: public LocMsg {
3498 
3499         AgpsManager* mAgpsManager;
3500         int mConnHandle;
3501 
3502         inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) :
3503                 LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) {
3504 
3505             LOC_LOGV("AgpsMsgReleaseATL");
3506         }
3507 
3508         inline virtual void proc() const {
3509 
3510             LOC_LOGV("AgpsMsgReleaseATL::proc()");
3511             mAgpsManager->releaseATL(mConnHandle);
3512         }
3513     };
3514 
3515     sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle));
3516 
3517     return true;
3518 }
3519 
3520 /* GnssAdapter::reportDataCallOpened
3521  * DS Client data call opened successfully.
3522  * Send message to AGPS Manager to handle. */
reportDataCallOpened()3523 bool GnssAdapter::reportDataCallOpened(){
3524 
3525     LOC_LOGI("GnssAdapter::reportDataCallOpened");
3526 
3527     struct AgpsMsgSuplEsOpened: public LocMsg {
3528 
3529         AgpsManager* mAgpsManager;
3530 
3531         inline AgpsMsgSuplEsOpened(AgpsManager* agpsManager) :
3532                 LocMsg(), mAgpsManager(agpsManager) {
3533 
3534             LOC_LOGV("AgpsMsgSuplEsOpened");
3535         }
3536 
3537         inline virtual void proc() const {
3538 
3539             LOC_LOGV("AgpsMsgSuplEsOpened::proc()");
3540             mAgpsManager->reportDataCallOpened();
3541         }
3542     };
3543 
3544     sendMsg( new AgpsMsgSuplEsOpened(&mAgpsManager));
3545 
3546     return true;
3547 }
3548 
3549 /* GnssAdapter::reportDataCallClosed
3550  * DS Client data call closed.
3551  * Send message to AGPS Manager to handle. */
reportDataCallClosed()3552 bool GnssAdapter::reportDataCallClosed(){
3553 
3554     LOC_LOGI("GnssAdapter::reportDataCallClosed");
3555 
3556     struct AgpsMsgSuplEsClosed: public LocMsg {
3557 
3558         AgpsManager* mAgpsManager;
3559 
3560         inline AgpsMsgSuplEsClosed(AgpsManager* agpsManager) :
3561                 LocMsg(), mAgpsManager(agpsManager) {
3562 
3563             LOC_LOGV("AgpsMsgSuplEsClosed");
3564         }
3565 
3566         inline virtual void proc() const {
3567 
3568             LOC_LOGV("AgpsMsgSuplEsClosed::proc()");
3569             mAgpsManager->reportDataCallClosed();
3570         }
3571     };
3572 
3573     sendMsg( new AgpsMsgSuplEsClosed(&mAgpsManager));
3574 
3575     return true;
3576 }
3577 
dataConnOpenCommand(AGpsExtType agpsType,const char * apnName,int apnLen,AGpsBearerType bearerType)3578 void GnssAdapter::dataConnOpenCommand(
3579         AGpsExtType agpsType,
3580         const char* apnName, int apnLen, AGpsBearerType bearerType){
3581 
3582     LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
3583 
3584     struct AgpsMsgAtlOpenSuccess: public LocMsg {
3585 
3586         AgpsManager* mAgpsManager;
3587         AGpsExtType mAgpsType;
3588         char* mApnName;
3589         int mApnLen;
3590         AGpsBearerType mBearerType;
3591 
3592         inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType,
3593                 const char* apnName, int apnLen, AGpsBearerType bearerType) :
3594                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName(
3595                         new char[apnLen + 1]), mApnLen(apnLen), mBearerType(bearerType) {
3596 
3597             LOC_LOGV("AgpsMsgAtlOpenSuccess");
3598             if (mApnName == nullptr) {
3599                 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
3600                 return;
3601             }
3602             memcpy(mApnName, apnName, apnLen);
3603             mApnName[apnLen] = 0;
3604         }
3605 
3606         inline ~AgpsMsgAtlOpenSuccess() {
3607             delete[] mApnName;
3608         }
3609 
3610         inline virtual void proc() const {
3611 
3612             LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()");
3613             mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen, mBearerType);
3614         }
3615     };
3616 
3617     sendMsg( new AgpsMsgAtlOpenSuccess(
3618             &mAgpsManager, agpsType, apnName, apnLen, bearerType));
3619 }
3620 
dataConnClosedCommand(AGpsExtType agpsType)3621 void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
3622 
3623     LOC_LOGI("GnssAdapter::frameworkDataConnClosed");
3624 
3625     struct AgpsMsgAtlClosed: public LocMsg {
3626 
3627         AgpsManager* mAgpsManager;
3628         AGpsExtType mAgpsType;
3629 
3630         inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) :
3631                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
3632 
3633             LOC_LOGV("AgpsMsgAtlClosed");
3634         }
3635 
3636         inline virtual void proc() const {
3637 
3638             LOC_LOGV("AgpsMsgAtlClosed::proc()");
3639             mAgpsManager->reportAtlClosed(mAgpsType);
3640         }
3641     };
3642 
3643     sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType));
3644 }
3645 
dataConnFailedCommand(AGpsExtType agpsType)3646 void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){
3647 
3648     LOC_LOGI("GnssAdapter::frameworkDataConnFailed");
3649 
3650     struct AgpsMsgAtlOpenFailed: public LocMsg {
3651 
3652         AgpsManager* mAgpsManager;
3653         AGpsExtType mAgpsType;
3654 
3655         inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) :
3656                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
3657 
3658             LOC_LOGV("AgpsMsgAtlOpenFailed");
3659         }
3660 
3661         inline virtual void proc() const {
3662 
3663             LOC_LOGV("AgpsMsgAtlOpenFailed::proc()");
3664             mAgpsManager->reportAtlOpenFailed(mAgpsType);
3665         }
3666     };
3667 
3668     sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType));
3669 }
3670 
convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo> & out,const GnssSvType & in_constellation,const SystemStatusReports & in)3671 void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out,
3672                                        const GnssSvType& in_constellation,
3673                                        const SystemStatusReports& in)
3674 {
3675     uint64_t sv_mask = 0ULL;
3676     uint32_t svid_min = 0;
3677     uint32_t svid_num = 0;
3678     uint32_t svid_idx = 0;
3679 
3680     uint64_t eph_health_good_mask = 0ULL;
3681     uint64_t eph_health_bad_mask = 0ULL;
3682     uint64_t server_perdiction_available_mask = 0ULL;
3683     float server_perdiction_age = 0.0f;
3684 
3685     // set constellationi based parameters
3686     switch (in_constellation) {
3687         case GNSS_SV_TYPE_GPS:
3688             svid_min = GNSS_BUGREPORT_GPS_MIN;
3689             svid_num = GPS_NUM;
3690             svid_idx = 0;
3691             if (!in.mSvHealth.empty()) {
3692                 eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask;
3693                 eph_health_bad_mask  = in.mSvHealth.back().mGpsBadMask;
3694             }
3695             if (!in.mXtra.empty()) {
3696                 server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid;
3697                 server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge);
3698             }
3699             break;
3700         case GNSS_SV_TYPE_GLONASS:
3701             svid_min = GNSS_BUGREPORT_GLO_MIN;
3702             svid_num = GLO_NUM;
3703             svid_idx = GPS_NUM;
3704             if (!in.mSvHealth.empty()) {
3705                 eph_health_good_mask = in.mSvHealth.back().mGloGoodMask;
3706                 eph_health_bad_mask  = in.mSvHealth.back().mGloBadMask;
3707             }
3708             if (!in.mXtra.empty()) {
3709                 server_perdiction_available_mask = in.mXtra.back().mGloXtraValid;
3710                 server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge);
3711             }
3712             break;
3713         case GNSS_SV_TYPE_QZSS:
3714             svid_min = GNSS_BUGREPORT_QZSS_MIN;
3715             svid_num = QZSS_NUM;
3716             svid_idx = GPS_NUM+GLO_NUM+BDS_NUM+GAL_NUM;
3717             if (!in.mSvHealth.empty()) {
3718                 eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask;
3719                 eph_health_bad_mask  = in.mSvHealth.back().mQzssBadMask;
3720             }
3721             if (!in.mXtra.empty()) {
3722                 server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid;
3723                 server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge);
3724             }
3725             break;
3726         case GNSS_SV_TYPE_BEIDOU:
3727             svid_min = GNSS_BUGREPORT_BDS_MIN;
3728             svid_num = BDS_NUM;
3729             svid_idx = GPS_NUM+GLO_NUM;
3730             if (!in.mSvHealth.empty()) {
3731                 eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask;
3732                 eph_health_bad_mask  = in.mSvHealth.back().mBdsBadMask;
3733             }
3734             if (!in.mXtra.empty()) {
3735                 server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid;
3736                 server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge);
3737             }
3738             break;
3739         case GNSS_SV_TYPE_GALILEO:
3740             svid_min = GNSS_BUGREPORT_GAL_MIN;
3741             svid_num = GAL_NUM;
3742             svid_idx = GPS_NUM+GLO_NUM+BDS_NUM;
3743             if (!in.mSvHealth.empty()) {
3744                 eph_health_good_mask = in.mSvHealth.back().mGalGoodMask;
3745                 eph_health_bad_mask  = in.mSvHealth.back().mGalBadMask;
3746             }
3747             if (!in.mXtra.empty()) {
3748                 server_perdiction_available_mask = in.mXtra.back().mGalXtraValid;
3749                 server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge);
3750             }
3751             break;
3752         default:
3753             return;
3754     }
3755 
3756     // extract each sv info from systemstatus report
3757     for(uint32_t i=0; i<svid_num && (svid_idx+i)<SV_ALL_NUM; i++) {
3758 
3759         GnssDebugSatelliteInfo s = {};
3760         s.size = sizeof(s);
3761         s.svid = i + svid_min;
3762         s.constellation = in_constellation;
3763 
3764         if (!in.mNavData.empty()) {
3765             s.mEphemerisType   = in.mNavData.back().mNav[svid_idx+i].mType;
3766             s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource;
3767         }
3768         else {
3769             s.mEphemerisType   = GNSS_EPH_TYPE_UNKNOWN;
3770             s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN;
3771         }
3772 
3773         sv_mask = 0x1ULL << i;
3774         if (eph_health_good_mask & sv_mask) {
3775             s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD;
3776         }
3777         else if (eph_health_bad_mask & sv_mask) {
3778             s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD;
3779         }
3780         else {
3781             s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN;
3782         }
3783 
3784         if (!in.mNavData.empty()) {
3785             s.ephemerisAgeSeconds =
3786                 (float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec);
3787         }
3788         else {
3789             s.ephemerisAgeSeconds = 0.0f;
3790         }
3791 
3792         if (server_perdiction_available_mask & sv_mask) {
3793             s.serverPredictionIsAvailable = true;
3794         }
3795         else {
3796             s.serverPredictionIsAvailable = false;
3797         }
3798 
3799         s.serverPredictionAgeSeconds = server_perdiction_age;
3800         out.push_back(s);
3801     }
3802 
3803     return;
3804 }
3805 
getDebugReport(GnssDebugReport & r)3806 bool GnssAdapter::getDebugReport(GnssDebugReport& r)
3807 {
3808     LOC_LOGD("%s]: ", __func__);
3809 
3810     SystemStatus* systemstatus = getSystemStatus();
3811     if (nullptr == systemstatus) {
3812         return false;
3813     }
3814 
3815     SystemStatusReports reports = {};
3816     systemstatus->getReport(reports, true);
3817 
3818     r.size = sizeof(r);
3819 
3820     // location block
3821     r.mLocation.size = sizeof(r.mLocation);
3822     if(!reports.mLocation.empty() && reports.mLocation.back().mValid) {
3823         r.mLocation.mValid = true;
3824         r.mLocation.mLocation.latitude =
3825             reports.mLocation.back().mLocation.gpsLocation.latitude;
3826         r.mLocation.mLocation.longitude =
3827             reports.mLocation.back().mLocation.gpsLocation.longitude;
3828         r.mLocation.mLocation.altitude =
3829             reports.mLocation.back().mLocation.gpsLocation.altitude;
3830         r.mLocation.mLocation.speed =
3831             (double)(reports.mLocation.back().mLocation.gpsLocation.speed);
3832         r.mLocation.mLocation.bearing =
3833             (double)(reports.mLocation.back().mLocation.gpsLocation.bearing);
3834         r.mLocation.mLocation.accuracy =
3835             (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy);
3836 
3837         r.mLocation.verticalAccuracyMeters =
3838             reports.mLocation.back().mLocationEx.vert_unc;
3839         r.mLocation.speedAccuracyMetersPerSecond =
3840             reports.mLocation.back().mLocationEx.speed_unc;
3841         r.mLocation.bearingAccuracyDegrees =
3842             reports.mLocation.back().mLocationEx.bearing_unc;
3843 
3844         r.mLocation.mUtcReported =
3845             reports.mLocation.back().mUtcReported;
3846     }
3847     else if(!reports.mBestPosition.empty() && reports.mBestPosition.back().mValid) {
3848         r.mLocation.mValid = true;
3849         r.mLocation.mLocation.latitude =
3850                 (double)(reports.mBestPosition.back().mBestLat) * RAD2DEG;
3851         r.mLocation.mLocation.longitude =
3852                 (double)(reports.mBestPosition.back().mBestLon) * RAD2DEG;
3853         r.mLocation.mLocation.altitude = reports.mBestPosition.back().mBestAlt;
3854         r.mLocation.mLocation.accuracy =
3855                 (double)(reports.mBestPosition.back().mBestHepe);
3856 
3857         r.mLocation.mUtcReported = reports.mBestPosition.back().mUtcReported;
3858     }
3859     else {
3860         r.mLocation.mValid = false;
3861     }
3862 
3863     if (r.mLocation.mValid) {
3864         LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f",
3865             r.mLocation.mLocation.latitude,
3866             r.mLocation.mLocation.longitude,
3867             r.mLocation.mLocation.altitude,
3868             r.mLocation.mLocation.speed);
3869     }
3870 
3871     // time block
3872     r.mTime.size = sizeof(r.mTime);
3873     if(!reports.mTimeAndClock.empty() && reports.mTimeAndClock.back().mTimeValid) {
3874         r.mTime.mValid = true;
3875         r.mTime.timeEstimate =
3876             (((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 +
3877                         GNSS_UTC_TIME_OFFSET)*24*60*60 -
3878               (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL +
3879               (int64_t)(reports.mTimeAndClock.back().mGpsTowMs);
3880 
3881         if (reports.mTimeAndClock.back().mTimeUncNs > 0) {
3882             // TimeUncNs value is available
3883             r.mTime.timeUncertaintyNs =
3884                     (float)(reports.mTimeAndClock.back().mLeapSecUnc)*1000.0f +
3885                     (float)(reports.mTimeAndClock.back().mTimeUncNs);
3886         } else {
3887             // fall back to legacy TimeUnc
3888             r.mTime.timeUncertaintyNs =
3889                     ((float)(reports.mTimeAndClock.back().mTimeUnc) +
3890                      (float)(reports.mTimeAndClock.back().mLeapSecUnc))*1000.0f;
3891         }
3892 
3893         r.mTime.frequencyUncertaintyNsPerSec =
3894             (float)(reports.mTimeAndClock.back().mClockFreqBiasUnc);
3895         LOC_LOGV("getDebugReport - timeestimate=%" PRIu64 " unc=%f frequnc=%f",
3896                 r.mTime.timeEstimate,
3897                 r.mTime.timeUncertaintyNs, r.mTime.frequencyUncertaintyNsPerSec);
3898     }
3899     else {
3900         r.mTime.mValid = false;
3901     }
3902 
3903     // satellite info block
3904     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports);
3905     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports);
3906     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports);
3907     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports);
3908     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports);
3909     LOC_LOGV("getDebugReport - satellite=%zu", r.mSatelliteInfo.size());
3910 
3911     return true;
3912 }
3913 
3914 /* get AGC information from system status and fill it */
3915 void
getAgcInformation(GnssMeasurementsNotification & measurements,int msInWeek)3916 GnssAdapter::getAgcInformation(GnssMeasurementsNotification& measurements, int msInWeek)
3917 {
3918     SystemStatus* systemstatus = getSystemStatus();
3919 
3920     if (nullptr != systemstatus) {
3921         SystemStatusReports reports = {};
3922         systemstatus->getReport(reports, true);
3923 
3924         if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
3925             (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
3926 
3927             for (size_t i = 0; i < measurements.count; i++) {
3928                 switch (measurements.measurements[i].svType) {
3929                 case GNSS_SV_TYPE_GPS:
3930                 case GNSS_SV_TYPE_QZSS:
3931                     measurements.measurements[i].agcLevelDb =
3932                             reports.mRfAndParams.back().mAgcGps;
3933                     measurements.measurements[i].flags |=
3934                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
3935                     break;
3936 
3937                 case GNSS_SV_TYPE_GALILEO:
3938                     measurements.measurements[i].agcLevelDb =
3939                             reports.mRfAndParams.back().mAgcGal;
3940                     measurements.measurements[i].flags |=
3941                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
3942                     break;
3943 
3944                 case GNSS_SV_TYPE_GLONASS:
3945                     measurements.measurements[i].agcLevelDb =
3946                             reports.mRfAndParams.back().mAgcGlo;
3947                     measurements.measurements[i].flags |=
3948                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
3949                     break;
3950 
3951                 case GNSS_SV_TYPE_BEIDOU:
3952                     measurements.measurements[i].agcLevelDb =
3953                             reports.mRfAndParams.back().mAgcBds;
3954                     measurements.measurements[i].flags |=
3955                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
3956                     break;
3957 
3958                 case GNSS_SV_TYPE_SBAS:
3959                 case GNSS_SV_TYPE_UNKNOWN:
3960                 default:
3961                     break;
3962                 }
3963             }
3964         }
3965     }
3966 }
3967 
3968 /* Callbacks registered with loc_net_iface library */
agpsOpenResultCb(bool isSuccess,AGpsExtType agpsType,const char * apn,AGpsBearerType bearerType,void * userDataPtr)3969 static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
3970         AGpsBearerType bearerType, void* userDataPtr) {
3971     LOC_LOGD("%s]: ", __func__);
3972     if (userDataPtr == nullptr) {
3973         LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
3974         return;
3975     }
3976     if (apn == nullptr) {
3977         LOC_LOGE("%s]: apn is nullptr.", __func__);
3978         return;
3979     }
3980     GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
3981     if (isSuccess) {
3982         adapter->dataConnOpenCommand(agpsType, apn, strlen(apn), bearerType);
3983     } else {
3984         adapter->dataConnFailedCommand(agpsType);
3985     }
3986 }
3987 
agpsCloseResultCb(bool isSuccess,AGpsExtType agpsType,void * userDataPtr)3988 static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr) {
3989     LOC_LOGD("%s]: ", __func__);
3990     if (userDataPtr == nullptr) {
3991         LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
3992         return;
3993     }
3994     GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
3995     if (isSuccess) {
3996         adapter->dataConnClosedCommand(agpsType);
3997     } else {
3998         adapter->dataConnFailedCommand(agpsType);
3999     }
4000 }
4001