1 /* Copyright (c) 2017, 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_TAG "LocSvc_GnssAdapter"
30 
31 #include <inttypes.h>
32 #include <sys/stat.h>
33 #include <errno.h>
34 #include <ctype.h>
35 #include <cutils/properties.h>
36 #include <math.h>
37 #include <arpa/inet.h>
38 #include <netinet/in.h>
39 #include <netdb.h>
40 #include <GnssAdapter.h>
41 #include <string>
42 #include <loc_log.h>
43 #include <loc_nmea.h>
44 #include <Agps.h>
45 #include <SystemStatus.h>
46 
47 #include <loc_nmea.h>
48 #include <vector>
49 #include <string>
50 
51 using namespace loc_core;
52 
GnssAdapter()53 GnssAdapter::GnssAdapter() :
54     LocAdapterBase(0,
55                    LocDualContext::getLocFgContext(NULL,
56                                                    NULL,
57                                                    LocDualContext::mLocationHalName,
58                                                    false)),
59     mUlpProxy(new UlpProxyBase()),
60     mUlpPositionMode(),
61     mGnssSvIdUsedInPosition(),
62     mGnssSvIdUsedInPosAvail(false),
63     mControlCallbacks(),
64     mPowerVoteId(0),
65     mNmeaMask(0),
66     mNiData(),
67     mAgpsManager(),
68     mAgpsCbInfo(),
69     mSystemStatus(SystemStatus::getInstance(mMsgTask)),
70     mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask)
71 {
72     LOC_LOGD("%s]: Constructor %p", __func__, this);
73     mUlpPositionMode.mode = LOC_POSITION_MODE_INVALID;
74     readConfigCommand();
75     setConfigCommand();
76 }
77 
78 void
setControlCallbacksCommand(LocationControlCallbacks & controlCallbacks)79 GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks)
80 {
81     struct MsgSetControlCallbacks : public LocMsg {
82         GnssAdapter& mAdapter;
83         const LocationControlCallbacks mControlCallbacks;
84         inline MsgSetControlCallbacks(GnssAdapter& adapter,
85                                       LocationControlCallbacks& controlCallbacks) :
86             LocMsg(),
87             mAdapter(adapter),
88             mControlCallbacks(controlCallbacks) {}
89         inline virtual void proc() const {
90             mAdapter.setControlCallbacks(mControlCallbacks);
91         }
92     };
93 
94     sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks));
95 }
96 
97 void
convertOptions(LocPosMode & out,const LocationOptions & options)98 GnssAdapter::convertOptions(LocPosMode& out, const LocationOptions& options)
99 {
100     LocPosMode locPosMode = {};
101     switch (options.mode) {
102     case GNSS_SUPL_MODE_MSB:
103         out.mode = LOC_POSITION_MODE_MS_BASED;
104         break;
105     case GNSS_SUPL_MODE_MSA:
106         out.mode = LOC_POSITION_MODE_MS_ASSISTED;
107         break;
108     default:
109         out.mode = LOC_POSITION_MODE_STANDALONE;
110         break;
111     }
112     out.share_position = true;
113     out.min_interval = options.minInterval;
114 }
115 
116 void
convertLocation(Location & out,const LocGpsLocation & locGpsLocation,const GpsLocationExtended & locationExtended,const LocPosTechMask techMask)117 GnssAdapter::convertLocation(Location& out, const LocGpsLocation& locGpsLocation,
118                              const GpsLocationExtended& locationExtended,
119                              const LocPosTechMask techMask)
120 {
121     memset(&out, 0, sizeof(Location));
122     out.size = sizeof(Location);
123     if (LOC_GPS_LOCATION_HAS_LAT_LONG & locGpsLocation.flags) {
124         out.flags |= LOCATION_HAS_LAT_LONG_BIT;
125         out.latitude = locGpsLocation.latitude;
126         out.longitude = locGpsLocation.longitude;
127     }
128     if (LOC_GPS_LOCATION_HAS_ALTITUDE & locGpsLocation.flags) {
129         out.flags |= LOCATION_HAS_ALTITUDE_BIT;
130         out.altitude = locGpsLocation.altitude;
131     }
132     if (LOC_GPS_LOCATION_HAS_SPEED & locGpsLocation.flags) {
133         out.flags |= LOCATION_HAS_SPEED_BIT;
134         out.speed = locGpsLocation.speed;
135     }
136     if (LOC_GPS_LOCATION_HAS_BEARING & locGpsLocation.flags) {
137         out.flags |= LOCATION_HAS_BEARING_BIT;
138         out.bearing = locGpsLocation.bearing;
139     }
140     if (LOC_GPS_LOCATION_HAS_ACCURACY & locGpsLocation.flags) {
141         out.flags |= LOCATION_HAS_ACCURACY_BIT;
142         out.accuracy = locGpsLocation.accuracy;
143     }
144     if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) {
145         out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
146         out.verticalAccuracy = locationExtended.vert_unc;
147     }
148     if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) {
149         out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
150         out.speedAccuracy = locationExtended.speed_unc;
151     }
152     if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) {
153         out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
154         out.bearingAccuracy = locationExtended.bearing_unc;
155     }
156     out.timestamp = locGpsLocation.timestamp;
157     if (LOC_POS_TECH_MASK_SATELLITE & techMask) {
158         out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
159     }
160     if (LOC_POS_TECH_MASK_CELLID & techMask) {
161         out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
162     }
163     if (LOC_POS_TECH_MASK_WIFI & techMask) {
164         out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
165     }
166     if (LOC_POS_TECH_MASK_SENSORS & techMask) {
167         out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
168     }
169 }
170 
171 void
convertLocationInfo(GnssLocationInfoNotification & out,const GpsLocationExtended & locationExtended)172 GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out,
173                                  const GpsLocationExtended& locationExtended)
174 {
175     out.size = sizeof(GnssLocationInfoNotification);
176     if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) {
177         out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT;
178         out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel;
179     }
180     if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) {
181         out.flags |= GNSS_LOCATION_INFO_DOP_BIT;
182         out.pdop = locationExtended.pdop;
183         out.hdop = locationExtended.hdop;
184         out.vdop = locationExtended.vdop;
185     }
186     if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) {
187         out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT;
188         out.magneticDeviation = locationExtended.magneticDeviation;
189     }
190     if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) {
191         out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT;
192         switch (locationExtended.horizontal_reliability) {
193             case LOC_RELIABILITY_VERY_LOW:
194                 out.horReliability = LOCATION_RELIABILITY_VERY_LOW;
195                 break;
196             case LOC_RELIABILITY_LOW:
197                 out.horReliability = LOCATION_RELIABILITY_LOW;
198                 break;
199             case LOC_RELIABILITY_MEDIUM:
200                 out.horReliability = LOCATION_RELIABILITY_MEDIUM;
201                 break;
202             case LOC_RELIABILITY_HIGH:
203                 out.horReliability = LOCATION_RELIABILITY_HIGH;
204                 break;
205             default:
206                 out.horReliability = LOCATION_RELIABILITY_NOT_SET;
207                 break;
208         }
209     }
210     if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) {
211         out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT;
212         switch (locationExtended.vertical_reliability) {
213             case LOC_RELIABILITY_VERY_LOW:
214                 out.verReliability = LOCATION_RELIABILITY_VERY_LOW;
215                 break;
216             case LOC_RELIABILITY_LOW:
217                 out.verReliability = LOCATION_RELIABILITY_LOW;
218                 break;
219             case LOC_RELIABILITY_MEDIUM:
220                 out.verReliability = LOCATION_RELIABILITY_MEDIUM;
221                 break;
222             case LOC_RELIABILITY_HIGH:
223                 out.verReliability = LOCATION_RELIABILITY_HIGH;
224                 break;
225             default:
226                 out.verReliability = LOCATION_RELIABILITY_NOT_SET;
227                 break;
228         }
229     }
230     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) {
231         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT;
232         out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor;
233     }
234     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) {
235         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT;
236         out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor;
237     }
238     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) {
239         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT;
240         out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth;
241     }
242 }
243 
244 inline uint32_t
convertGpsLock(const GnssConfigGpsLock gpsLock)245 GnssAdapter::convertGpsLock(const GnssConfigGpsLock gpsLock)
246 {
247     switch (gpsLock) {
248         case GNSS_CONFIG_GPS_LOCK_MO:
249             return 1;
250         case GNSS_CONFIG_GPS_LOCK_NI:
251             return 2;
252         case GNSS_CONFIG_GPS_LOCK_MO_AND_NI:
253             return 3;
254         case GNSS_CONFIG_GPS_LOCK_NONE:
255         default:
256             return 0;
257     }
258 }
259 
260 inline GnssConfigGpsLock
convertGpsLock(const uint32_t gpsLock)261 GnssAdapter::convertGpsLock(const uint32_t gpsLock)
262 {
263     switch (gpsLock) {
264         case 1:
265             return GNSS_CONFIG_GPS_LOCK_MO;
266         case 2:
267             return GNSS_CONFIG_GPS_LOCK_NI;
268         case 3:
269             return GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
270         case 0:
271         default:
272             return GNSS_CONFIG_GPS_LOCK_NONE;
273     }
274 }
275 
276 inline uint32_t
convertSuplVersion(const GnssConfigSuplVersion suplVersion)277 GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion)
278 {
279     switch (suplVersion) {
280         case GNSS_CONFIG_SUPL_VERSION_2_0_0:
281             return 0x00020000;
282         case GNSS_CONFIG_SUPL_VERSION_2_0_2:
283             return 0x00020002;
284         case GNSS_CONFIG_SUPL_VERSION_1_0_0:
285         default:
286             return 0x00010000;
287     }
288 }
289 
290 inline GnssConfigSuplVersion
convertSuplVersion(const uint32_t suplVersion)291 GnssAdapter::convertSuplVersion(const uint32_t suplVersion)
292 {
293     switch (suplVersion) {
294         case 0x00020000:
295             return GNSS_CONFIG_SUPL_VERSION_2_0_0;
296         case 0x00020002:
297             return GNSS_CONFIG_SUPL_VERSION_2_0_2;
298         case 0x00010000:
299         default:
300             return GNSS_CONFIG_SUPL_VERSION_1_0_0;
301     }
302 }
303 
304 inline uint32_t
convertLppProfile(const GnssConfigLppProfile lppProfile)305 GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile)
306 {
307     switch (lppProfile) {
308         case GNSS_CONFIG_LPP_PROFILE_USER_PLANE:
309             return 1;
310         case GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE:
311             return 2;
312         case GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE:
313             return 3;
314         case GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE:
315         default:
316             return 0;
317     }
318 }
319 
320 inline GnssConfigLppProfile
convertLppProfile(const uint32_t lppProfile)321 GnssAdapter::convertLppProfile(const uint32_t lppProfile)
322 {
323     switch (lppProfile) {
324         case 1:
325             return GNSS_CONFIG_LPP_PROFILE_USER_PLANE;
326         case 2:
327             return GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE;
328         case 3:
329             return GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE;
330         case 0:
331         default:
332             return GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE;
333     }
334 }
335 
336 uint32_t
convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)337 GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)
338 {
339     uint32_t mask = 0;
340     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) {
341         mask |= (1<<0);
342     }
343     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
344         mask |= (1<<1);
345     }
346     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
347         mask |= (1<<2);
348     }
349     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeControlPlaneMask) {
350         mask |= (1<<3);
351     }
352     return mask;
353 }
354 
355 GnssConfigLppeControlPlaneMask
convertLppeCp(const uint32_t lppeControlPlaneMask)356 GnssAdapter::convertLppeCp(const uint32_t lppeControlPlaneMask)
357 {
358     GnssConfigLppeControlPlaneMask mask = 0;
359     if ((1<<0) & lppeControlPlaneMask) {
360         mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT;
361     }
362     if ((1<<1) & lppeControlPlaneMask) {
363         mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT;
364     }
365     if ((1<<2) & lppeControlPlaneMask) {
366         mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT;
367     }
368     if ((1<<3) & lppeControlPlaneMask) {
369         mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT;
370     }
371     return mask;
372 }
373 
374 
375 uint32_t
convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)376 GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)
377 {
378     uint32_t mask = 0;
379     if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) {
380         mask |= (1<<0);
381     }
382     if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
383         mask |= (1<<1);
384     }
385     if (GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
386         mask |= (1<<2);
387     }
388     if (GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeUserPlaneMask) {
389         mask |= (1<<3);
390     }
391     return mask;
392 }
393 
394 GnssConfigLppeUserPlaneMask
convertLppeUp(const uint32_t lppeUserPlaneMask)395 GnssAdapter::convertLppeUp(const uint32_t lppeUserPlaneMask)
396 {
397     GnssConfigLppeUserPlaneMask mask = 0;
398     if ((1<<0) & lppeUserPlaneMask) {
399         mask |= GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT;
400     }
401     if ((1<<1) & lppeUserPlaneMask) {
402         mask |= GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT;
403     }
404     if ((1<<2) & lppeUserPlaneMask) {
405         mask |= GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT;
406     }
407     if ((1<<3) & lppeUserPlaneMask) {
408         mask |= GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT;
409     }
410     return mask;
411 }
412 
413 uint32_t
convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)414 GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)
415 {
416     uint32_t mask = 0;
417     if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
418         mask |= (1<<0);
419     }
420     if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
421         mask |= (1<<1);
422     }
423     if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
424         mask |= (1<<2);
425     }
426     if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
427         mask |= (1<<3);
428     }
429     return mask;
430 }
431 
432 uint32_t
convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)433 GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)
434 {
435     switch (emergencyPdnForEmergencySupl) {
436        case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES:
437            return 1;
438        case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO:
439        default:
440            return 0;
441     }
442 }
443 
444 uint32_t
convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)445 GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)
446 {
447     switch (suplEmergencyServices) {
448        case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES:
449            return 1;
450        case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO:
451        default:
452            return 0;
453     }
454 }
455 
456 uint32_t
convertSuplMode(const GnssConfigSuplModeMask suplModeMask)457 GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask)
458 {
459     uint32_t mask = 0;
460     if (GNSS_CONFIG_SUPL_MODE_MSB_BIT & suplModeMask) {
461         mask |= (1<<0);
462     }
463     if (GNSS_CONFIG_SUPL_MODE_MSA_BIT & suplModeMask) {
464         mask |= (1<<1);
465     }
466     return mask;
467 }
468 
469 bool
resolveInAddress(const char * hostAddress,struct in_addr * inAddress)470 GnssAdapter::resolveInAddress(const char* hostAddress, struct in_addr* inAddress)
471 {
472     bool ret = true;
473 
474     struct hostent* hp;
475     hp = gethostbyname(hostAddress);
476     if (hp != NULL) { /* DNS OK */
477         memcpy(inAddress, hp->h_addr_list[0], hp->h_length);
478     } else {
479         /* Try IP representation */
480         if (inet_aton(hostAddress, inAddress) == 0) {
481             /* IP not valid */
482             LOC_LOGE("%s]: DNS query on '%s' failed", __func__, hostAddress);
483             ret = false;
484         }
485     }
486 
487     return ret;
488 }
489 
490 void
readConfigCommand()491 GnssAdapter::readConfigCommand()
492 {
493     LOC_LOGD("%s]: ", __func__);
494 
495     struct MsgReadConfig : public LocMsg {
496         GnssAdapter* mAdapter;
497         ContextBase& mContext;
498         inline MsgReadConfig(GnssAdapter* adapter,
499                              ContextBase& context) :
500             LocMsg(),
501             mAdapter(adapter),
502             mContext(context) {}
503         inline virtual void proc() const {
504             // reads config into mContext->mGps_conf
505             mContext.readConfig();
506             mContext.requestUlp((LocAdapterBase*)mAdapter, mContext.getCarrierCapabilities());
507         }
508     };
509 
510     if (mContext != NULL) {
511         sendMsg(new MsgReadConfig(this, *mContext));
512     }
513 }
514 
515 void
setConfigCommand()516 GnssAdapter::setConfigCommand()
517 {
518     LOC_LOGD("%s]: ", __func__);
519 
520     struct MsgSetConfig : public LocMsg {
521         GnssAdapter& mAdapter;
522         LocApiBase& mApi;
523         inline MsgSetConfig(GnssAdapter& adapter,
524                             LocApiBase& api) :
525             LocMsg(),
526             mAdapter(adapter),
527             mApi(api) {}
528         inline virtual void proc() const {
529             if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
530                 mApi.setSUPLVersion(mAdapter.convertSuplVersion(ContextBase::mGps_conf.SUPL_VER));
531                 mApi.setLPPConfig(mAdapter.convertLppProfile(ContextBase::mGps_conf.LPP_PROFILE));
532                 mApi.setAGLONASSProtocol(ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT);
533             }
534             mApi.setSensorControlConfig(ContextBase::mSap_conf.SENSOR_USAGE,
535                                         ContextBase::mSap_conf.SENSOR_PROVIDER);
536             mApi.setLPPeProtocolCp(
537                 mAdapter.convertLppeCp(ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY));
538             mApi.setLPPeProtocolUp(
539                 mAdapter.convertLppeUp(ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY));
540 
541             // set nmea mask type
542             uint32_t mask = 0;
543             if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
544                 mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
545             }
546             if (mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
547                 mask |= LOC_NMEA_MASK_DEBUG_V02;
548             }
549             if (mask != 0) {
550                 mApi.setNMEATypes(mask);
551             }
552             mAdapter.mNmeaMask= mask;
553 
554             mApi.setXtraVersionCheck(ContextBase::mGps_conf.XTRA_VERSION_CHECK);
555             if (ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID ||
556                 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
557                 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
558                 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
559                 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) {
560                 mApi.setSensorProperties(
561                     ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID,
562                     ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK,
563                     ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
564                     ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY,
565                     ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
566                     ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY,
567                     ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
568                     ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY,
569                     ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
570                     ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY);
571             }
572             mApi.setSensorPerfControlConfig(
573                 ContextBase::mSap_conf.SENSOR_CONTROL_MODE,
574                    ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH,
575                    ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC,
576                    ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH,
577                    ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC,
578                    ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH,
579                    ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH,
580                    ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH,
581                    ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
582                    ContextBase::mSap_conf.SENSOR_ALGORITHM_CONFIG_MASK);
583         }
584     };
585 
586     sendMsg(new MsgSetConfig(*this, *mLocApi));
587 }
588 
589 uint32_t*
gnssUpdateConfigCommand(GnssConfig config)590 GnssAdapter::gnssUpdateConfigCommand(GnssConfig config)
591 {
592     // count the number of bits set
593     GnssConfigFlagsMask flagsCopy = config.flags;
594     size_t count = 0;
595     while (flagsCopy > 0) {
596         if (flagsCopy & 1) {
597             count++;
598         }
599         flagsCopy >>= 1;
600     }
601     std::string idsString = "[";
602     uint32_t* ids = NULL;
603     if (count > 0) {
604         ids = new uint32_t[count];
605         if (ids == nullptr) {
606             LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
607             return nullptr;
608         }
609         for (size_t i=0; i < count; ++i) {
610             ids[i] = generateSessionId();
611             IF_LOC_LOGD {
612                 idsString += std::to_string(ids[i]) + " ";
613             }
614         }
615     }
616     idsString += "]";
617 
618     LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags);
619 
620     struct MsgGnssUpdateConfig : public LocMsg {
621         GnssAdapter& mAdapter;
622         LocApiBase& mApi;
623         GnssConfig mConfig;
624         uint32_t* mIds;
625         size_t mCount;
626         inline MsgGnssUpdateConfig(GnssAdapter& adapter,
627                                    LocApiBase& api,
628                                    GnssConfig config,
629                                    uint32_t* ids,
630                                    size_t count) :
631             LocMsg(),
632             mAdapter(adapter),
633             mApi(api),
634             mConfig(config),
635             mIds(ids),
636             mCount(count) {}
637         inline virtual ~MsgGnssUpdateConfig()
638         {
639             delete[] mIds;
640         }
641         inline virtual void proc() const {
642             //const size_t MAX_BITS_COUNT = 10;
643             //LocationError errs[MAX_BITS_COUNT] = {};
644             LocationError* errs = new LocationError[mCount];
645             LocationError err = LOCATION_ERROR_SUCCESS;
646             uint32_t index = 0;
647 
648             if (errs == nullptr) {
649                 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
650                 return;
651             }
652 
653             if (mConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
654                 uint32_t newGpsLock = mAdapter.convertGpsLock(mConfig.gpsLock);
655                 ContextBase::mGps_conf.GPS_LOCK = newGpsLock;
656                 if (0 == mAdapter.getPowerVoteId()) {
657                     err = mApi.setGpsLock(mConfig.gpsLock);
658                 }
659                 if (index < mCount) {
660                     errs[index++] = err;
661                 }
662             }
663             if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
664                 uint32_t newSuplVersion = mAdapter.convertSuplVersion(mConfig.suplVersion);
665                 if (newSuplVersion != ContextBase::mGps_conf.SUPL_VER &&
666                     ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
667                     ContextBase::mGps_conf.SUPL_VER = newSuplVersion;
668                     err = mApi.setSUPLVersion(mConfig.suplVersion);
669                 } else {
670                     err = LOCATION_ERROR_SUCCESS;
671                 }
672                 if (index < mCount) {
673                     errs[index++] = err;
674                 }
675             }
676             if (mConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
677                 if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) {
678                     if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
679                         char serverUrl[MAX_URL_LEN] = {};
680                         uint32_t length = 0;
681                         const char noHost[] = "NONE";
682                         if (NULL == mConfig.assistanceServer.hostName ||
683                             strncasecmp(noHost,
684                                         mConfig.assistanceServer.hostName,
685                                         sizeof(noHost)) == 0) {
686                         } else {
687                             length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u",
688                                               mConfig.assistanceServer.hostName,
689                                               mConfig.assistanceServer.port);
690                         }
691 
692                         if (sizeof(serverUrl) > length) {
693                             err = mApi.setServer(serverUrl, length);
694                         } else {
695                             err = LOCATION_ERROR_INVALID_PARAMETER;
696                         }
697                     } else {
698                         err = LOCATION_ERROR_SUCCESS;
699                     }
700                 } else if (GNSS_ASSISTANCE_TYPE_C2K == mConfig.assistanceServer.type) {
701                     if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
702                         struct in_addr addr;
703                         if (!mAdapter.resolveInAddress(mConfig.assistanceServer.hostName, &addr)) {
704                             LOC_LOGE("%s]: hostName %s cannot be resolved",
705                                      __func__, mConfig.assistanceServer.hostName);
706                             err = LOCATION_ERROR_INVALID_PARAMETER;
707                         } else {
708                             unsigned int ip = htonl(addr.s_addr);
709                             err = mApi.setServer(ip, mConfig.assistanceServer.port,
710                                                     LOC_AGPS_CDMA_PDE_SERVER);
711                         }
712                     } else {
713                         err = LOCATION_ERROR_SUCCESS;
714                     }
715                 } else {
716                     LOC_LOGE("%s]: Not a valid gnss assistance type %u",
717                              __func__, mConfig.assistanceServer.type);
718                     err = LOCATION_ERROR_INVALID_PARAMETER;
719                 }
720                 if (index < mCount) {
721                     errs[index++] = err;
722                 }
723             }
724             if (mConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
725                 uint32_t newLppProfile = mAdapter.convertLppProfile(mConfig.lppProfile);
726                 if (newLppProfile != ContextBase::mGps_conf.LPP_PROFILE &&
727                     ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
728                     ContextBase::mGps_conf.LPP_PROFILE = newLppProfile;
729                     err = mApi.setLPPConfig(mConfig.lppProfile);
730                 } else {
731                     err = LOCATION_ERROR_SUCCESS;
732                 }
733                 if (index < mCount) {
734                     errs[index++] = err;
735                 }
736             }
737             if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
738                 uint32_t newLppeControlPlaneMask =
739                     mAdapter.convertLppeCp(mConfig.lppeControlPlaneMask);
740                 if (newLppeControlPlaneMask != ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY) {
741                     ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask;
742                     err = mApi.setLPPeProtocolCp(mConfig.lppeControlPlaneMask);
743                 } else {
744                     err = LOCATION_ERROR_SUCCESS;
745                 }
746                 if (index < mCount) {
747                     errs[index++] = err;
748                 }
749             }
750             if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
751                 uint32_t newLppeUserPlaneMask =
752                     mAdapter.convertLppeUp(mConfig.lppeUserPlaneMask);
753                 if (newLppeUserPlaneMask != ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY) {
754                     ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask;
755                     err = mApi.setLPPeProtocolUp(mConfig.lppeUserPlaneMask);
756                 } else {
757                     err = LOCATION_ERROR_SUCCESS;
758                 }
759                 if (index < mCount) {
760                     errs[index++] = err;
761                 }
762             }
763             if (mConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
764                 uint32_t newAGloProtMask =
765                     mAdapter.convertAGloProt(mConfig.aGlonassPositionProtocolMask);
766                 if (newAGloProtMask != ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT &&
767                     ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
768                     ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask;
769                     err = mApi.setAGLONASSProtocol(mConfig.aGlonassPositionProtocolMask);
770                 } else {
771                     err = LOCATION_ERROR_SUCCESS;
772                 }
773                 if (index < mCount) {
774                     errs[index++] = err;
775                 }
776             }
777             if (mConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
778                 uint32_t newEP4ES = mAdapter.convertEP4ES(mConfig.emergencyPdnForEmergencySupl);
779                 if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
780                     ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES;
781                 }
782                 err = LOCATION_ERROR_SUCCESS;
783                 if (index < mCount) {
784                     errs[index++] = err;
785                 }
786             }
787             if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
788                 uint32_t newSuplEs = mAdapter.convertSuplEs(mConfig.suplEmergencyServices);
789                 if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) {
790                     ContextBase::mGps_conf.SUPL_ES = newSuplEs;
791                 }
792                 err = LOCATION_ERROR_SUCCESS;
793                 if (index < mCount) {
794                     errs[index++] = err;
795                 }
796             }
797             if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
798                 uint32_t newSuplMode = mAdapter.convertSuplMode(mConfig.suplModeMask);
799                 if (newSuplMode != ContextBase::mGps_conf.SUPL_MODE) {
800                     ContextBase::mGps_conf.SUPL_MODE = newSuplMode;
801                     mAdapter.getUlpProxy()->setCapabilities(
802                         ContextBase::getCarrierCapabilities());
803                     mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
804                 }
805                 err = LOCATION_ERROR_SUCCESS;
806                 if (index < mCount) {
807                     errs[index++] = err;
808                 }
809             }
810 
811             mAdapter.reportResponse(index, errs, mIds);
812             delete[] errs;
813         }
814     };
815 
816     if (NULL != ids) {
817         sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count));
818     } else {
819         LOC_LOGE("%s]: No GNSS config items to update", __func__);
820     }
821 
822     return ids;
823 }
824 
825 uint32_t
gnssDeleteAidingDataCommand(GnssAidingData & data)826 GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data)
827 {
828     uint32_t sessionId = generateSessionId();
829     LOC_LOGD("%s]: id %u", __func__, sessionId);
830 
831     struct MsgDeleteAidingData : public LocMsg {
832         GnssAdapter& mAdapter;
833         LocApiBase& mApi;
834         uint32_t mSessionId;
835         GnssAidingData mData;
836         inline MsgDeleteAidingData(GnssAdapter& adapter,
837                                    LocApiBase& api,
838                                    uint32_t sessionId,
839                                    GnssAidingData& data) :
840             LocMsg(),
841             mAdapter(adapter),
842             mApi(api),
843             mSessionId(sessionId),
844             mData(data) {}
845         inline virtual void proc() const {
846             LocationError err = LOCATION_ERROR_SUCCESS;
847             err = mApi.deleteAidingData(mData);
848             mAdapter.reportResponse(err, mSessionId);
849             SystemStatus* s = mAdapter.getSystemStatus();
850             if ((nullptr != s) && (mData.deleteAll)) {
851                 s->setDefaultReport();
852             }
853         }
854     };
855 
856     sendMsg(new MsgDeleteAidingData(*this, *mLocApi, sessionId, data));
857     return sessionId;
858 }
859 
860 void
injectLocationCommand(double latitude,double longitude,float accuracy)861 GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy)
862 {
863     LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f",
864              __func__, latitude, longitude, accuracy);
865 
866     struct MsgInjectLocation : public LocMsg {
867         LocApiBase& mApi;
868         ContextBase& mContext;
869         double mLatitude;
870         double mLongitude;
871         float mAccuracy;
872         inline MsgInjectLocation(LocApiBase& api,
873                                  ContextBase& context,
874                                  double latitude,
875                                  double longitude,
876                                  float accuracy) :
877             LocMsg(),
878             mApi(api),
879             mContext(context),
880             mLatitude(latitude),
881             mLongitude(longitude),
882             mAccuracy(accuracy) {}
883         inline virtual void proc() const {
884             if (!mContext.hasCPIExtendedCapabilities()) {
885                 mApi.injectPosition(mLatitude, mLongitude, mAccuracy);
886             }
887         }
888     };
889 
890     sendMsg(new MsgInjectLocation(*mLocApi, *mContext, latitude, longitude, accuracy));
891 }
892 
893 void
injectTimeCommand(int64_t time,int64_t timeReference,int32_t uncertainty)894 GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty)
895 {
896     LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d",
897              __func__, (long long)time, (long long)timeReference, uncertainty);
898 
899     struct MsgInjectTime : public LocMsg {
900         LocApiBase& mApi;
901         ContextBase& mContext;
902         int64_t mTime;
903         int64_t mTimeReference;
904         int32_t mUncertainty;
905         inline MsgInjectTime(LocApiBase& api,
906                              ContextBase& context,
907                              int64_t time,
908                              int64_t timeReference,
909                              int32_t uncertainty) :
910             LocMsg(),
911             mApi(api),
912             mContext(context),
913             mTime(time),
914             mTimeReference(timeReference),
915             mUncertainty(uncertainty) {}
916         inline virtual void proc() const {
917             mApi.setTime(mTime, mTimeReference, mUncertainty);
918         }
919     };
920 
921     sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty));
922 }
923 
924 void
setUlpProxyCommand(UlpProxyBase * ulp)925 GnssAdapter::setUlpProxyCommand(UlpProxyBase* ulp)
926 {
927     LOC_LOGD("%s]: ", __func__);
928 
929     struct MsgSetUlpProxy : public LocMsg {
930         GnssAdapter& mAdapter;
931         UlpProxyBase* mUlp;
932         inline MsgSetUlpProxy(GnssAdapter& adapter,
933                               UlpProxyBase* ulp) :
934             LocMsg(),
935             mAdapter(adapter),
936             mUlp(ulp) {}
937         inline virtual void proc() const {
938             mAdapter.setUlpProxy(mUlp);
939             if (mUlp) {
940                 mUlp->setCapabilities(ContextBase::getCarrierCapabilities());
941             }
942         }
943     };
944 
945     sendMsg(new MsgSetUlpProxy(*this, ulp));
946 }
947 
948 void
setUlpProxy(UlpProxyBase * ulp)949 GnssAdapter::setUlpProxy(UlpProxyBase* ulp)
950 {
951     if (ulp == mUlpProxy) {
952         //This takes care of the case when double initalization happens
953         //and we get the same object back for UlpProxyBase . Do nothing
954         return;
955     }
956 
957     LOC_LOGV("%s]: %p", __func__, ulp);
958     if (NULL == ulp) {
959         LOC_LOGE("%s]: ulp pointer is NULL", __func__);
960         ulp = new UlpProxyBase();
961     }
962 
963     if (LOC_POSITION_MODE_INVALID != mUlpProxy->mPosMode.mode) {
964         // need to send this mode and start msg to ULP
965         ulp->sendFixMode(mUlpProxy->mPosMode);
966     }
967 
968     if (mUlpProxy->mFixSet) {
969         ulp->sendStartFix();
970     }
971 
972     delete mUlpProxy;
973     mUlpProxy = ulp;
974 }
975 
976 void
addClientCommand(LocationAPI * client,const LocationCallbacks & callbacks)977 GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks)
978 {
979     LOC_LOGD("%s]: client %p", __func__, client);
980 
981     struct MsgAddClient : public LocMsg {
982         GnssAdapter& mAdapter;
983         LocationAPI* mClient;
984         const LocationCallbacks mCallbacks;
985         inline MsgAddClient(GnssAdapter& adapter,
986                             LocationAPI* client,
987                             const LocationCallbacks& callbacks) :
988             LocMsg(),
989             mAdapter(adapter),
990             mClient(client),
991             mCallbacks(callbacks) {}
992         inline virtual void proc() const {
993             mAdapter.saveClient(mClient, mCallbacks);
994         }
995     };
996 
997     sendMsg(new MsgAddClient(*this, client, callbacks));
998 }
999 
1000 void
removeClientCommand(LocationAPI * client)1001 GnssAdapter::removeClientCommand(LocationAPI* client)
1002 {
1003     LOC_LOGD("%s]: client %p", __func__, client);
1004 
1005     struct MsgRemoveClient : public LocMsg {
1006         GnssAdapter& mAdapter;
1007         LocationAPI* mClient;
1008         inline MsgRemoveClient(GnssAdapter& adapter,
1009                                LocationAPI* client) :
1010             LocMsg(),
1011             mAdapter(adapter),
1012             mClient(client) {}
1013         inline virtual void proc() const {
1014             mAdapter.stopClientSessions(mClient);
1015             mAdapter.eraseClient(mClient);
1016         }
1017     };
1018 
1019     sendMsg(new MsgRemoveClient(*this, client));
1020 }
1021 
1022 void
stopClientSessions(LocationAPI * client)1023 GnssAdapter::stopClientSessions(LocationAPI* client)
1024 {
1025     LOC_LOGD("%s]: client %p", __func__, client);
1026     for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end();) {
1027         if (client == it->first.client) {
1028             LocationError err = stopTrackingMultiplex(it->first.client, it->first.id);
1029             if (LOCATION_ERROR_SUCCESS == err) {
1030                 it = mTrackingSessions.erase(it);
1031                 continue;
1032             }
1033         }
1034         ++it; // increment only when not erasing an iterator
1035     }
1036 
1037 }
1038 
1039 void
updateClientsEventMask()1040 GnssAdapter::updateClientsEventMask()
1041 {
1042     LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
1043     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
1044         if (it->second.trackingCb != nullptr) {
1045             mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
1046         }
1047         if (it->second.gnssNiCb != nullptr) {
1048             mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
1049         }
1050         if (it->second.gnssSvCb != nullptr) {
1051             mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT;
1052         }
1053         if ((it->second.gnssNmeaCb != nullptr) && (mNmeaMask)) {
1054             mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
1055         }
1056         if (it->second.gnssMeasurementsCb != nullptr) {
1057             mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
1058         }
1059     }
1060 
1061     /*
1062     ** For Automotive use cases we need to enable MEASUREMENT and POLY
1063     ** when QDR is enabled
1064     */
1065     if(1 == ContextBase::mGps_conf.EXTERNAL_DR_ENABLED) {
1066         mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
1067         mask |= LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT;
1068 
1069         LOC_LOGD("%s]: Auto usecase, Enable MEAS/POLY - mask 0x%x", __func__, mask);
1070     }
1071 
1072     updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
1073 }
1074 
1075 void
handleEngineUpEvent()1076 GnssAdapter::handleEngineUpEvent()
1077 {
1078     struct MsgRestartSessions : public LocMsg {
1079         GnssAdapter& mAdapter;
1080         inline MsgRestartSessions(GnssAdapter& adapter) :
1081             LocMsg(),
1082             mAdapter(adapter) {}
1083         virtual void proc() const {
1084             mAdapter.restartSessions();
1085         }
1086     };
1087 
1088     setConfigCommand();
1089     sendMsg(new MsgRestartSessions(*this));
1090 }
1091 
1092 void
restartSessions()1093 GnssAdapter::restartSessions()
1094 {
1095     LOC_LOGD("%s]: ", __func__);
1096 
1097     if (mTrackingSessions.empty()) {
1098         return;
1099     }
1100 
1101     // get the LocationOptions that has the smallest interval, which should be the active one
1102     LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time
1103     for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
1104         if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet
1105             it->second.minInterval < smallestIntervalOptions.minInterval) {
1106              smallestIntervalOptions = it->second;
1107         }
1108     }
1109 
1110     LocPosMode locPosMode = {};
1111     convertOptions(locPosMode, smallestIntervalOptions);
1112     mLocApi->startFix(locPosMode);
1113 }
1114 
1115 void
requestCapabilitiesCommand(LocationAPI * client)1116 GnssAdapter::requestCapabilitiesCommand(LocationAPI* client)
1117 {
1118     LOC_LOGD("%s]: ", __func__);
1119 
1120     struct MsgRequestCapabilities : public LocMsg {
1121         GnssAdapter& mAdapter;
1122         LocationAPI* mClient;
1123         inline MsgRequestCapabilities(GnssAdapter& adapter,
1124                                       LocationAPI* client) :
1125             LocMsg(),
1126             mAdapter(adapter),
1127             mClient(client) {}
1128         inline virtual void proc() const {
1129             LocationCallbacks callbacks = mAdapter.getClientCallbacks(mClient);
1130             if (callbacks.capabilitiesCb == nullptr) {
1131                 LOC_LOGE("%s]: capabilitiesCb is NULL", __func__);
1132                 return;
1133             }
1134 
1135             LocationCapabilitiesMask mask = mAdapter.getCapabilities();
1136             callbacks.capabilitiesCb(mask);
1137         }
1138     };
1139 
1140     sendMsg(new MsgRequestCapabilities(*this, client));
1141 }
1142 
1143 LocationCapabilitiesMask
getCapabilities()1144 GnssAdapter::getCapabilities()
1145 {
1146     LocationCapabilitiesMask mask = 0;
1147     uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities();
1148     // time based tracking always supported
1149     mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT;
1150     // geofence always supported
1151     mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT;
1152     if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) {
1153         mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT;
1154     }
1155     if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) {
1156         mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT;
1157     }
1158     if (mLocApi == nullptr)
1159         return mask;
1160     if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)) {
1161         mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT |
1162                 LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT;
1163     }
1164     if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
1165         mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT;
1166     }
1167     if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING)) {
1168         mask |= LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT;
1169     }
1170     if (mLocApi->gnssConstellationConfig()) {
1171         mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT;
1172     }
1173     if (mLocApi->isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
1174         mask |= LOCATION_CAPABILITIES_DEBUG_NMEA_BIT;
1175     }
1176     return mask;
1177 }
1178 
1179 void
broadcastCapabilities(LocationCapabilitiesMask mask)1180 GnssAdapter::broadcastCapabilities(LocationCapabilitiesMask mask)
1181 {
1182     for (auto it = mClientData.begin(); it != mClientData.end(); ++it) {
1183         if (nullptr != it->second.capabilitiesCb) {
1184             it->second.capabilitiesCb(mask);
1185         }
1186     }
1187 }
1188 
1189 LocationCallbacks
getClientCallbacks(LocationAPI * client)1190 GnssAdapter::getClientCallbacks(LocationAPI* client)
1191 {
1192     LocationCallbacks callbacks = {};
1193     auto it = mClientData.find(client);
1194     if (it != mClientData.end()) {
1195         callbacks = it->second;
1196     }
1197     return callbacks;
1198 }
1199 
1200 void
saveClient(LocationAPI * client,const LocationCallbacks & callbacks)1201 GnssAdapter::saveClient(LocationAPI* client, const LocationCallbacks& callbacks)
1202 {
1203     mClientData[client] = callbacks;
1204     updateClientsEventMask();
1205 }
1206 
1207 void
eraseClient(LocationAPI * client)1208 GnssAdapter::eraseClient(LocationAPI* client)
1209 {
1210     auto it = mClientData.find(client);
1211     if (it != mClientData.end()) {
1212         mClientData.erase(it);
1213     }
1214     updateClientsEventMask();
1215 }
1216 
1217 bool
hasTrackingCallback(LocationAPI * client)1218 GnssAdapter::hasTrackingCallback(LocationAPI* client)
1219 {
1220     auto it = mClientData.find(client);
1221     return (it != mClientData.end() && it->second.trackingCb);
1222 }
1223 
1224 bool
hasMeasurementsCallback(LocationAPI * client)1225 GnssAdapter::hasMeasurementsCallback(LocationAPI* client)
1226 {
1227     auto it = mClientData.find(client);
1228     return (it != mClientData.end() && it->second.gnssMeasurementsCb);
1229 }
1230 
1231 bool
isTrackingSession(LocationAPI * client,uint32_t sessionId)1232 GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId)
1233 {
1234     LocationSessionKey key(client, sessionId);
1235     return (mTrackingSessions.find(key) != mTrackingSessions.end());
1236 }
1237 
1238 void
saveTrackingSession(LocationAPI * client,uint32_t sessionId,const LocationOptions & options)1239 GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId,
1240                                  const LocationOptions& options)
1241 {
1242     LocationSessionKey key(client, sessionId);
1243     mTrackingSessions[key] = options;
1244 }
1245 
1246 void
eraseTrackingSession(LocationAPI * client,uint32_t sessionId)1247 GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId)
1248 {
1249     LocationSessionKey key(client, sessionId);
1250     auto it = mTrackingSessions.find(key);
1251     if (it != mTrackingSessions.end()) {
1252         mTrackingSessions.erase(it);
1253     }
1254 
1255 }
1256 
1257 void
reportResponse(LocationAPI * client,LocationError err,uint32_t sessionId)1258 GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId)
1259 {
1260     LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err);
1261 
1262     auto it = mClientData.find(client);
1263     if (it != mClientData.end() &&
1264         it->second.responseCb != nullptr) {
1265         it->second.responseCb(err, sessionId);
1266     } else {
1267         LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId);
1268     }
1269 }
1270 
1271 void
reportResponse(LocationError err,uint32_t sessionId)1272 GnssAdapter::reportResponse(LocationError err, uint32_t sessionId)
1273 {
1274     LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err);
1275 
1276     if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) {
1277         mControlCallbacks.responseCb(err, sessionId);
1278     } else {
1279         LOC_LOGW("%s]: control client response callback not found", __func__);
1280     }
1281 }
1282 
1283 void
reportResponse(size_t count,LocationError * errs,uint32_t * ids)1284 GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids)
1285 {
1286     IF_LOC_LOGD {
1287         std::string idsString = "[";
1288         std::string errsString = "[";
1289         if (NULL != ids && NULL != errs) {
1290             for (size_t i=0; i < count; ++i) {
1291                 idsString += std::to_string(ids[i]) + " ";
1292                 errsString += std::to_string(errs[i]) + " ";
1293             }
1294         }
1295         idsString += "]";
1296         errsString += "]";
1297 
1298         LOC_LOGD("%s]: ids %s errs %s",
1299                  __func__, idsString.c_str(), errsString.c_str());
1300     }
1301 
1302     if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) {
1303         mControlCallbacks.collectiveResponseCb(count, errs, ids);
1304     } else {
1305         LOC_LOGW("%s]: control client callback not found", __func__);
1306     }
1307 }
1308 
1309 uint32_t
startTrackingCommand(LocationAPI * client,LocationOptions & options)1310 GnssAdapter::startTrackingCommand(LocationAPI* client, LocationOptions& options)
1311 {
1312     uint32_t sessionId = generateSessionId();
1313     LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
1314              __func__, client, sessionId, options.minInterval, options.mode);
1315 
1316     struct MsgStartTracking : public LocMsg {
1317         GnssAdapter& mAdapter;
1318         LocApiBase& mApi;
1319         LocationAPI* mClient;
1320         uint32_t mSessionId;
1321         LocationOptions mOptions;
1322         inline MsgStartTracking(GnssAdapter& adapter,
1323                                LocApiBase& api,
1324                                LocationAPI* client,
1325                                uint32_t sessionId,
1326                                LocationOptions options) :
1327             LocMsg(),
1328             mAdapter(adapter),
1329             mApi(api),
1330             mClient(client),
1331             mSessionId(sessionId),
1332             mOptions(options) {}
1333         inline virtual void proc() const {
1334             LocationError err = LOCATION_ERROR_SUCCESS;
1335             if (!mAdapter.hasTrackingCallback(mClient) &&
1336                 !mAdapter.hasMeasurementsCallback(mClient)) {
1337                 err = LOCATION_ERROR_CALLBACK_MISSING;
1338             } else if (0 == mOptions.size) {
1339                 err = LOCATION_ERROR_INVALID_PARAMETER;
1340             } else {
1341                 // Api doesn't support multiple clients for time based tracking, so mutiplex
1342                 err = mAdapter.startTrackingMultiplex(mOptions);
1343                 if (LOCATION_ERROR_SUCCESS == err) {
1344                     mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
1345                 }
1346             }
1347             mAdapter.reportResponse(mClient, err, mSessionId);
1348         }
1349     };
1350 
1351     sendMsg(new MsgStartTracking(*this, *mLocApi, client, sessionId, options));
1352     return sessionId;
1353 
1354 }
1355 
1356 LocationError
startTrackingMultiplex(const LocationOptions & options)1357 GnssAdapter::startTrackingMultiplex(const LocationOptions& options)
1358 {
1359     LocationError err = LOCATION_ERROR_SUCCESS;
1360 
1361     if (mTrackingSessions.empty()) {
1362         err = startTracking(options);
1363     } else {
1364         // get the LocationOptions that has the smallest interval, which should be the active one
1365         LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time
1366         for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
1367             if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet
1368                 it->second.minInterval < smallestIntervalOptions.minInterval) {
1369                  smallestIntervalOptions = it->second;
1370             }
1371         }
1372         // if new session's minInterval is smaller than any in other sessions
1373         if (options.minInterval < smallestIntervalOptions.minInterval) {
1374             // restart time based tracking with new options
1375             err = startTracking(options);
1376         }
1377     }
1378 
1379     return err;
1380 }
1381 
1382 LocationError
startTracking(const LocationOptions & options)1383 GnssAdapter::startTracking(const LocationOptions& options)
1384 {
1385     LocationError err = LOCATION_ERROR_SUCCESS;
1386     LocPosMode locPosMode = {};
1387     convertOptions(locPosMode, options);
1388     if (!mUlpProxy->sendFixMode(locPosMode)) {
1389         // do nothing
1390     }
1391     if (!mUlpProxy->sendStartFix()) {
1392         loc_api_adapter_err apiErr = mLocApi->startFix(locPosMode);
1393         if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) {
1394             err = LOCATION_ERROR_SUCCESS;
1395         } else {
1396             err = LOCATION_ERROR_GENERAL_FAILURE;
1397         }
1398     }
1399 
1400     return err;
1401 }
1402 
1403 void
setPositionModeCommand(LocPosMode & locPosMode)1404 GnssAdapter::setPositionModeCommand(LocPosMode& locPosMode)
1405 {
1406     LOC_LOGD("%s]: min_interval %u mode %u",
1407              __func__, locPosMode.min_interval, locPosMode.mode);
1408 
1409     struct MsgSetPositionMode : public LocMsg {
1410         GnssAdapter& mAdapter;
1411         LocApiBase& mApi;
1412         LocPosMode mLocPosMode;
1413         inline MsgSetPositionMode(GnssAdapter& adapter,
1414                                   LocApiBase& api,
1415                                   LocPosMode& locPosMode) :
1416             LocMsg(),
1417             mAdapter(adapter),
1418             mApi(api),
1419             mLocPosMode(locPosMode) {}
1420         inline virtual void proc() const {
1421              // saves the mode in adapter to be used when startTrackingCommand is called from ULP
1422             mAdapter.setUlpPositionMode(mLocPosMode);
1423             mApi.setPositionMode(mLocPosMode);
1424         }
1425     };
1426 
1427     sendMsg(new MsgSetPositionMode(*this, *mLocApi, locPosMode));
1428 }
1429 
1430 void
startTrackingCommand()1431 GnssAdapter::startTrackingCommand()
1432 {
1433     LOC_LOGD("%s]: ", __func__);
1434 
1435     struct MsgStartTracking : public LocMsg {
1436         GnssAdapter& mAdapter;
1437         LocApiBase& mApi;
1438         inline MsgStartTracking(GnssAdapter& adapter,
1439                                 LocApiBase& api) :
1440             LocMsg(),
1441             mAdapter(adapter),
1442             mApi(api) {}
1443         inline virtual void proc() const {
1444             // we get this call from ULP, so just call LocApi without multiplexing because
1445             // ulp would be doing the multiplexing for us if it is present
1446             LocPosMode& ulpPositionMode = mAdapter.getUlpPositionMode();
1447             mApi.startFix(ulpPositionMode);
1448         }
1449     };
1450 
1451     sendMsg(new MsgStartTracking(*this, *mLocApi));
1452 }
1453 
1454 void
updateTrackingOptionsCommand(LocationAPI * client,uint32_t id,LocationOptions & options)1455 GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
1456                                           LocationOptions& options)
1457 {
1458     LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
1459              __func__, client, id, options.minInterval, options.mode);
1460 
1461     struct MsgUpdateTracking : public LocMsg {
1462         GnssAdapter& mAdapter;
1463         LocApiBase& mApi;
1464         LocationAPI* mClient;
1465         uint32_t mSessionId;
1466         LocationOptions mOptions;
1467         inline MsgUpdateTracking(GnssAdapter& adapter,
1468                                 LocApiBase& api,
1469                                 LocationAPI* client,
1470                                 uint32_t sessionId,
1471                                 LocationOptions options) :
1472             LocMsg(),
1473             mAdapter(adapter),
1474             mApi(api),
1475             mClient(client),
1476             mSessionId(sessionId),
1477             mOptions(options) {}
1478         inline virtual void proc() const {
1479             if (mAdapter.isTrackingSession(mClient, mSessionId)) {
1480                 LocationError err = LOCATION_ERROR_SUCCESS;
1481                 if (0 == mOptions.size) {
1482                     err = LOCATION_ERROR_INVALID_PARAMETER;
1483                 } else {
1484                     // Api doesn't support multiple clients for time based tracking, so mutiplex
1485                     err = mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions);
1486                     if (LOCATION_ERROR_SUCCESS == err) {
1487                         mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
1488                     }
1489                 }
1490                 mAdapter.reportResponse(mClient, err, mSessionId);
1491             }
1492             // we do not reportResponse for the case where there is no existing tracking session
1493             // for the client and id being used, since updateTrackingCommand can be sent to both
1494             // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response
1495         }
1496     };
1497 
1498     sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options));
1499 }
1500 
1501 LocationError
updateTrackingMultiplex(LocationAPI * client,uint32_t id,const LocationOptions & options)1502 GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id,
1503                                      const LocationOptions& options)
1504 {
1505     LocationError err = LOCATION_ERROR_SUCCESS;
1506 
1507     if (1 == mTrackingSessions.size()) {
1508         err = startTracking(options);
1509     } else {
1510         LocationSessionKey key(client, id);
1511 
1512         // get the session we are updating
1513         auto it = mTrackingSessions.find(key);
1514         if (it != mTrackingSessions.end()) {
1515             // find the smallest interval, other than the session we are updating
1516             LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time
1517             for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
1518                 // if session is not the one we are updating and either smallest interval is not set
1519                 // or there is a new smallest interval, then set the new smallest interval
1520                 if (it2->first != key && (0 == smallestIntervalOptions.size ||
1521                     it2->second.minInterval < smallestIntervalOptions.minInterval)) {
1522                      smallestIntervalOptions = it2->second;
1523                 }
1524             }
1525             // if session we are updating has smaller interval then next smallest
1526             if (options.minInterval < smallestIntervalOptions.minInterval) {
1527                 // restart time based tracking with the newly updated interval
1528                 err = startTracking(options);
1529             // else if the session we are updating used to be the smallest
1530             } else if (it->second.minInterval < smallestIntervalOptions.minInterval) {
1531                 // restart time based tracking with the next smallest
1532                 err = startTracking(smallestIntervalOptions);
1533             }
1534         }
1535     }
1536 
1537     return err;
1538 }
1539 
1540 void
stopTrackingCommand(LocationAPI * client,uint32_t id)1541 GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id)
1542 {
1543     LOC_LOGD("%s]: client %p id %u", __func__, client, id);
1544 
1545     struct MsgStopTracking : public LocMsg {
1546         GnssAdapter& mAdapter;
1547         LocApiBase& mApi;
1548         LocationAPI* mClient;
1549         uint32_t mSessionId;
1550         inline MsgStopTracking(GnssAdapter& adapter,
1551                                LocApiBase& api,
1552                                LocationAPI* client,
1553                                uint32_t sessionId) :
1554             LocMsg(),
1555             mAdapter(adapter),
1556             mApi(api),
1557             mClient(client),
1558             mSessionId(sessionId) {}
1559         inline virtual void proc() const {
1560             if (mAdapter.isTrackingSession(mClient, mSessionId)) {
1561                 LocationError err = LOCATION_ERROR_SUCCESS;
1562                 // Api doesn't support multiple clients for time based tracking, so mutiplex
1563                 err = mAdapter.stopTrackingMultiplex(mClient, mSessionId);
1564                 if (LOCATION_ERROR_SUCCESS == err) {
1565                     mAdapter.eraseTrackingSession(mClient, mSessionId);
1566                 }
1567                 mAdapter.reportResponse(mClient, err, mSessionId);
1568             }
1569             // we do not reportResponse for the case where there is no existing tracking session
1570             // for the client and id being used, since stopTrackingCommand can be sent to both
1571             // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response
1572 
1573         }
1574     };
1575 
1576     sendMsg(new MsgStopTracking(*this, *mLocApi, client, id));
1577 }
1578 
1579 LocationError
stopTrackingMultiplex(LocationAPI * client,uint32_t id)1580 GnssAdapter::stopTrackingMultiplex(LocationAPI* client, uint32_t id)
1581 {
1582     LocationError err = LOCATION_ERROR_SUCCESS;
1583 
1584     if (1 == mTrackingSessions.size()) {
1585         err = stopTracking();
1586     } else {
1587         LocationSessionKey key(client, id);
1588 
1589         // get the session we are stopping
1590         auto it = mTrackingSessions.find(key);
1591         if (it != mTrackingSessions.end()) {
1592             // find the next smallest interval, other than the session we are stopping
1593             LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time
1594             for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
1595                 // if session is not the one we are stopping and either smallest interval is not set
1596                 // or there is a new smallest interval, then set the new smallest interval
1597                 if (it2->first != key && (0 == smallestIntervalOptions.size ||
1598                     it2->second.minInterval < smallestIntervalOptions.minInterval)) {
1599                      smallestIntervalOptions = it2->second;
1600                 }
1601             }
1602             // if session we are stopping has smaller interval then next smallest
1603             if (it->second.minInterval < smallestIntervalOptions.minInterval) {
1604                 // restart time based tracking with next smallest interval
1605                 err = startTracking(smallestIntervalOptions);
1606             }
1607         }
1608     }
1609 
1610     return err;
1611 }
1612 
1613 LocationError
stopTracking()1614 GnssAdapter::stopTracking()
1615 {
1616     LocationError err = LOCATION_ERROR_SUCCESS;
1617     if (!mUlpProxy->sendStopFix()) {
1618         loc_api_adapter_err apiErr = mLocApi->stopFix();
1619         if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) {
1620             err = LOCATION_ERROR_SUCCESS;
1621         } else {
1622             err = LOCATION_ERROR_GENERAL_FAILURE;
1623         }
1624     }
1625 
1626     return err;
1627 }
1628 
1629 void
stopTrackingCommand()1630 GnssAdapter::stopTrackingCommand()
1631 {
1632     LOC_LOGD("%s]: ", __func__);
1633 
1634     struct MsgStopTracking : public LocMsg {
1635         GnssAdapter& mAdapter;
1636         LocApiBase& mApi;
1637         inline MsgStopTracking(GnssAdapter& adapter,
1638                                LocApiBase& api) :
1639             LocMsg(),
1640             mAdapter(adapter),
1641             mApi(api) {}
1642         inline virtual void proc() const {
1643             // clear the position mode
1644             LocPosMode mLocPosMode = {};
1645             mLocPosMode.mode = LOC_POSITION_MODE_INVALID;
1646             mAdapter.setUlpPositionMode(mLocPosMode);
1647             // don't need to multiplex because ULP will do that for us if it is present
1648             mApi.stopFix();
1649         }
1650     };
1651 
1652     sendMsg(new MsgStopTracking(*this, *mLocApi));
1653 }
1654 
1655 void
getZppCommand()1656 GnssAdapter::getZppCommand()
1657 {
1658     LOC_LOGD("%s]: ", __func__);
1659 
1660     struct MsgGetZpp : public LocMsg {
1661         GnssAdapter& mAdapter;
1662         LocApiBase& mApi;
1663         inline MsgGetZpp(GnssAdapter& adapter,
1664                          LocApiBase& api) :
1665             LocMsg(),
1666             mAdapter(adapter),
1667             mApi(api) {}
1668         inline virtual void proc() const {
1669             UlpLocation location = {};
1670             LocPosTechMask techMask = LOC_POS_TECH_MASK_DEFAULT;
1671             GpsLocationExtended locationExtended = {};
1672             locationExtended.size = sizeof(locationExtended);
1673 
1674             mApi.getBestAvailableZppFix(location.gpsLocation, locationExtended,
1675                     techMask);
1676             //Mark the location source as from ZPP
1677             location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO;
1678             location.position_source = ULP_LOCATION_IS_FROM_ZPP;
1679 
1680             mAdapter.getUlpProxy()->reportPosition(location,
1681                                                    locationExtended,
1682                                                    LOC_SESS_SUCCESS,
1683                                                    techMask);
1684         }
1685     };
1686 
1687     sendMsg(new MsgGetZpp(*this, *mLocApi));
1688 }
1689 
1690 bool
hasNiNotifyCallback(LocationAPI * client)1691 GnssAdapter::hasNiNotifyCallback(LocationAPI* client)
1692 {
1693     auto it = mClientData.find(client);
1694     return (it != mClientData.end() && it->second.gnssNiCb);
1695 }
1696 
1697 void
gnssNiResponseCommand(LocationAPI * client,uint32_t id,GnssNiResponse response)1698 GnssAdapter::gnssNiResponseCommand(LocationAPI* client,
1699                                    uint32_t id,
1700                                    GnssNiResponse response)
1701 {
1702     LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response);
1703 
1704     struct MsgGnssNiResponse : public LocMsg {
1705         GnssAdapter& mAdapter;
1706         LocationAPI* mClient;
1707         uint32_t mSessionId;
1708         GnssNiResponse mResponse;
1709         inline MsgGnssNiResponse(GnssAdapter& adapter,
1710                                  LocationAPI* client,
1711                                  uint32_t sessionId,
1712                                  GnssNiResponse response) :
1713             LocMsg(),
1714             mAdapter(adapter),
1715             mClient(client),
1716             mSessionId(sessionId),
1717             mResponse(response) {}
1718         inline virtual void proc() const {
1719             NiData& niData = mAdapter.getNiData();
1720             LocationError err = LOCATION_ERROR_SUCCESS;
1721             if (!mAdapter.hasNiNotifyCallback(mClient)) {
1722                 err = LOCATION_ERROR_ID_UNKNOWN;
1723             } else {
1724                 NiSession* pSession = NULL;
1725                 if (mSessionId == niData.sessionEs.reqID &&
1726                     NULL != niData.sessionEs.rawRequest) {
1727                     pSession = &niData.sessionEs;
1728                     // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
1729                     if (mResponse == GNSS_NI_RESPONSE_ACCEPT &&
1730                         NULL != niData.session.rawRequest) {
1731                             pthread_mutex_lock(&niData.session.tLock);
1732                             niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
1733                             niData.session.respRecvd = true;
1734                             pthread_cond_signal(&niData.session.tCond);
1735                             pthread_mutex_unlock(&niData.session.tLock);
1736                     }
1737                 } else if (mSessionId == niData.session.reqID &&
1738                     NULL != niData.session.rawRequest) {
1739                     pSession = &niData.session;
1740                 }
1741 
1742                 if (pSession) {
1743                     LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u",
1744                              __func__, mResponse, mSessionId);
1745                     pthread_mutex_lock(&pSession->tLock);
1746                     pSession->resp = mResponse;
1747                     pSession->respRecvd = true;
1748                     pthread_cond_signal(&pSession->tCond);
1749                     pthread_mutex_unlock(&pSession->tLock);
1750                 } else {
1751                     err = LOCATION_ERROR_ID_UNKNOWN;
1752                     LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session",
1753                              __func__, mSessionId);
1754                 }
1755             }
1756             mAdapter.reportResponse(mClient, err, mSessionId);
1757         }
1758     };
1759 
1760     sendMsg(new MsgGnssNiResponse(*this, client, id, response));
1761 
1762 }
1763 
1764 void
gnssNiResponseCommand(GnssNiResponse response,void * rawRequest)1765 GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest)
1766 {
1767     LOC_LOGD("%s]: response %u", __func__, response);
1768 
1769     struct MsgGnssNiResponse : public LocMsg {
1770         LocApiBase& mApi;
1771         const GnssNiResponse mResponse;
1772         const void* mPayload;
1773         inline MsgGnssNiResponse(LocApiBase& api,
1774                                  const GnssNiResponse response,
1775                                  const void* rawRequest) :
1776             LocMsg(),
1777             mApi(api),
1778             mResponse(response),
1779             mPayload(rawRequest) {}
1780         inline virtual ~MsgGnssNiResponse() {
1781             // this is a bit weird since mPayload is not
1782             // allocated by this class.  But there is no better way.
1783             // mPayload actually won't be NULL here.
1784             free((void*)mPayload);
1785         }
1786         inline virtual void proc() const {
1787             mApi.informNiResponse(mResponse, mPayload);
1788         }
1789     };
1790 
1791     sendMsg(new MsgGnssNiResponse(*mLocApi, response, rawRequest));
1792 
1793 }
1794 
1795 uint32_t
enableCommand(LocationTechnologyType techType)1796 GnssAdapter::enableCommand(LocationTechnologyType techType)
1797 {
1798     uint32_t sessionId = generateSessionId();
1799     LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType);
1800 
1801     struct MsgEnableGnss : public LocMsg {
1802         GnssAdapter& mAdapter;
1803         LocApiBase& mApi;
1804         ContextBase& mContext;
1805         uint32_t mSessionId;
1806         LocationTechnologyType mTechType;
1807         inline MsgEnableGnss(GnssAdapter& adapter,
1808                              LocApiBase& api,
1809                              ContextBase& context,
1810                              uint32_t sessionId,
1811                              LocationTechnologyType techType) :
1812             LocMsg(),
1813             mAdapter(adapter),
1814             mApi(api),
1815             mContext(context),
1816             mSessionId(sessionId),
1817             mTechType(techType) {}
1818         inline virtual void proc() const {
1819             LocationError err = LOCATION_ERROR_SUCCESS;
1820             uint32_t powerVoteId = mAdapter.getPowerVoteId();
1821             if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) {
1822                 err = LOCATION_ERROR_INVALID_PARAMETER;
1823             } else if (powerVoteId > 0) {
1824                 err = LOCATION_ERROR_ALREADY_STARTED;
1825             } else {
1826                 mContext.modemPowerVote(true);
1827                 mAdapter.setPowerVoteId(mSessionId);
1828                 mApi.setGpsLock(GNSS_CONFIG_GPS_LOCK_NONE);
1829                 mAdapter.mXtraObserver.updateLockStatus(
1830                         mAdapter.convertGpsLock(GNSS_CONFIG_GPS_LOCK_NONE));
1831             }
1832             mAdapter.reportResponse(err, mSessionId);
1833         }
1834     };
1835 
1836     if (mContext != NULL) {
1837         sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType));
1838     } else {
1839         LOC_LOGE("%s]: Context is NULL", __func__);
1840     }
1841 
1842     return sessionId;
1843 }
1844 
1845 void
disableCommand(uint32_t id)1846 GnssAdapter::disableCommand(uint32_t id)
1847 {
1848     LOC_LOGD("%s]: id %u", __func__, id);
1849 
1850     struct MsgDisableGnss : public LocMsg {
1851         GnssAdapter& mAdapter;
1852         LocApiBase& mApi;
1853         ContextBase& mContext;
1854         uint32_t mSessionId;
1855         inline MsgDisableGnss(GnssAdapter& adapter,
1856                              LocApiBase& api,
1857                              ContextBase& context,
1858                              uint32_t sessionId) :
1859             LocMsg(),
1860             mAdapter(adapter),
1861             mApi(api),
1862             mContext(context),
1863             mSessionId(sessionId) {}
1864         inline virtual void proc() const {
1865             LocationError err = LOCATION_ERROR_SUCCESS;
1866             uint32_t powerVoteId = mAdapter.getPowerVoteId();
1867             if (powerVoteId != mSessionId) {
1868                 err = LOCATION_ERROR_ID_UNKNOWN;
1869             } else {
1870                 mContext.modemPowerVote(false);
1871                 mAdapter.setPowerVoteId(0);
1872                 mApi.setGpsLock(mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK));
1873                 mAdapter.mXtraObserver.updateLockStatus(
1874                         mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK));
1875             }
1876             mAdapter.reportResponse(err, mSessionId);
1877         }
1878     };
1879 
1880     if (mContext != NULL) {
1881         sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id));
1882     }
1883 
1884 }
1885 
1886 void
reportPositionEvent(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask,bool fromUlp)1887 GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation,
1888                                  const GpsLocationExtended& locationExtended,
1889                                  enum loc_sess_status status,
1890                                  LocPosTechMask techMask,
1891                                  bool fromUlp)
1892 {
1893     LOC_LOGD("%s]: fromUlp %u status %u", __func__, fromUlp, status);
1894 
1895     // if this event is not called from ULP, then try to call into ULP and return if successfull
1896     if (!fromUlp) {
1897         if (mUlpProxy->reportPosition(ulpLocation, locationExtended,
1898                                  status, techMask)) {
1899             return;
1900         }
1901     }
1902 
1903     struct MsgReportPosition : public LocMsg {
1904         GnssAdapter& mAdapter;
1905         const UlpLocation mUlpLocation;
1906         const GpsLocationExtended mLocationExtended;
1907         loc_sess_status mStatus;
1908         LocPosTechMask mTechMask;
1909         inline MsgReportPosition(GnssAdapter& adapter,
1910                                  const UlpLocation& ulpLocation,
1911                                  const GpsLocationExtended& locationExtended,
1912                                  loc_sess_status status,
1913                                  LocPosTechMask techMask) :
1914             LocMsg(),
1915             mAdapter(adapter),
1916             mUlpLocation(ulpLocation),
1917             mLocationExtended(locationExtended),
1918             mStatus(status),
1919             mTechMask(techMask) {}
1920         inline virtual void proc() const {
1921             // extract bug report info - this returns true if consumed by systemstatus
1922             SystemStatus* s = mAdapter.getSystemStatus();
1923             if ((nullptr != s) && (LOC_SESS_SUCCESS == mStatus)){
1924                 s->eventPosition(mUlpLocation, mLocationExtended);
1925             }
1926             mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask);
1927         }
1928     };
1929 
1930     sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended, status, techMask));
1931 }
1932 
1933 void
reportPosition(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask)1934 GnssAdapter::reportPosition(const UlpLocation& ulpLocation,
1935                             const GpsLocationExtended& locationExtended,
1936                             enum loc_sess_status status,
1937                             LocPosTechMask techMask)
1938 {
1939     bool reported = false;
1940     // what's in the if is... (line by line)
1941     // 1. this is a final fix; and
1942     //   1.1 it is a Satellite fix; or
1943     //   1.2 it is a sensor fix
1944     // 2. (must be intermediate fix... implicit)
1945     //   2.1 we accepte intermediate; and
1946     //   2.2 it is NOT the case that
1947     //   2.2.1 there is inaccuracy; and
1948     //   2.2.2 we care about inaccuracy; and
1949     //   2.2.3 the inaccuracy exceeds our tolerance
1950     if ((LOC_SESS_SUCCESS == status &&
1951               ((LOC_POS_TECH_MASK_SATELLITE |
1952                 LOC_POS_TECH_MASK_SENSORS   |
1953                 LOC_POS_TECH_MASK_HYBRID) &
1954                techMask)) ||
1955              (LOC_SESS_INTERMEDIATE == ContextBase::mGps_conf.INTERMEDIATE_POS &&
1956               !((ulpLocation.gpsLocation.flags &
1957                  LOC_GPS_LOCATION_HAS_ACCURACY) &&
1958                 (ContextBase::mGps_conf.ACCURACY_THRES != 0) &&
1959                 (ulpLocation.gpsLocation.accuracy >
1960                  ContextBase::mGps_conf.ACCURACY_THRES)))) {
1961         if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) {
1962             mGnssSvIdUsedInPosAvail = true;
1963             mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids;
1964         }
1965         for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
1966             if (nullptr != it->second.trackingCb) {
1967                 Location location = {};
1968                 convertLocation(location, ulpLocation.gpsLocation, locationExtended, techMask);
1969                 it->second.trackingCb(location);
1970             }
1971             if (nullptr != it->second.gnssLocationInfoCb) {
1972                 GnssLocationInfoNotification locationInfo = {};
1973                 convertLocationInfo(locationInfo, locationExtended);
1974                 it->second.gnssLocationInfoCb(locationInfo);
1975             }
1976         }
1977         reported = true;
1978     }
1979 
1980     if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) {
1981         /*Only BlankNMEA sentence needs to be processed and sent, if both lat, long is 0 &
1982           horReliability is not set. */
1983         bool blank_fix = ((0 == ulpLocation.gpsLocation.latitude) &&
1984                           (0 == ulpLocation.gpsLocation.longitude) &&
1985                           (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability));
1986         uint8_t generate_nmea = (reported && status != LOC_SESS_FAILURE && !blank_fix);
1987         std::vector<std::string> nmeaArraystr;
1988         loc_nmea_generate_pos(ulpLocation, locationExtended, generate_nmea, nmeaArraystr);
1989         for (auto sentence : nmeaArraystr) {
1990             reportNmea(sentence.c_str(), sentence.length());
1991         }
1992     }
1993 
1994     // Free the allocated memory for rawData
1995     UlpLocation* gp = (UlpLocation*)&(ulpLocation);
1996     if (gp != NULL && gp->rawData != NULL)
1997     {
1998         delete (char*)gp->rawData;
1999         gp->rawData = NULL;
2000         gp->rawDataSize = 0;
2001     }
2002 }
2003 
2004 void
reportSvEvent(const GnssSvNotification & svNotify,bool fromUlp)2005 GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify,
2006                            bool fromUlp)
2007 {
2008     LOC_LOGD("%s]: fromUlp %u", __func__, fromUlp);
2009 
2010     // if this event is not called from ULP, then try to call into ULP and return if successfull
2011     if (!fromUlp) {
2012         if (mUlpProxy->reportSv(svNotify)) {
2013             return;
2014         }
2015     }
2016 
2017     struct MsgReportSv : public LocMsg {
2018         GnssAdapter& mAdapter;
2019         const GnssSvNotification mSvNotify;
2020         inline MsgReportSv(GnssAdapter& adapter,
2021                            const GnssSvNotification& svNotify) :
2022             LocMsg(),
2023             mAdapter(adapter),
2024             mSvNotify(svNotify) {}
2025         inline virtual void proc() const {
2026             mAdapter.reportSv((GnssSvNotification&)mSvNotify);
2027         }
2028     };
2029 
2030     sendMsg(new MsgReportSv(*this, svNotify));
2031 }
2032 
2033 void
reportSv(GnssSvNotification & svNotify)2034 GnssAdapter::reportSv(GnssSvNotification& svNotify)
2035 {
2036     int numSv = svNotify.count;
2037     int16_t gnssSvId = 0;
2038     uint64_t svUsedIdMask = 0;
2039     for (int i=0; i < numSv; i++) {
2040         svUsedIdMask = 0;
2041         gnssSvId = svNotify.gnssSvs[i].svId;
2042         switch (svNotify.gnssSvs[i].type) {
2043             case GNSS_SV_TYPE_GPS:
2044                 if (mGnssSvIdUsedInPosAvail) {
2045                     svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask;
2046                 }
2047                 break;
2048             case GNSS_SV_TYPE_GLONASS:
2049                 if (mGnssSvIdUsedInPosAvail) {
2050                     svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask;
2051                 }
2052                 break;
2053             case GNSS_SV_TYPE_BEIDOU:
2054                 if (mGnssSvIdUsedInPosAvail) {
2055                     svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask;
2056                 }
2057                 break;
2058             case GNSS_SV_TYPE_GALILEO:
2059                 if (mGnssSvIdUsedInPosAvail) {
2060                     svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask;
2061                 }
2062                 break;
2063             case GNSS_SV_TYPE_QZSS:
2064                 if (mGnssSvIdUsedInPosAvail) {
2065                     svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask;
2066                 }
2067                 // QZSS SV id's need to reported as it is to framework, since
2068                 // framework expects it as it is. See GnssStatus.java.
2069                 // SV id passed to here by LocApi is 1-based.
2070                 svNotify.gnssSvs[i].svId += (QZSS_SV_PRN_MIN - 1);
2071                 break;
2072             default:
2073                 svUsedIdMask = 0;
2074                 break;
2075         }
2076 
2077         // If SV ID was used in previous position fix, then set USED_IN_FIX
2078         // flag, else clear the USED_IN_FIX flag.
2079         if (svUsedIdMask & (1 << (gnssSvId - 1))) {
2080             svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
2081         }
2082     }
2083 
2084     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2085         if (nullptr != it->second.gnssSvCb) {
2086             it->second.gnssSvCb(svNotify);
2087         }
2088     }
2089 
2090     if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) {
2091         std::vector<std::string> nmeaArraystr;
2092         loc_nmea_generate_sv(svNotify, nmeaArraystr);
2093         for (auto sentence : nmeaArraystr) {
2094             reportNmea(sentence.c_str(), sentence.length());
2095         }
2096     }
2097 
2098     mGnssSvIdUsedInPosAvail = false;
2099 }
2100 
2101 void
reportNmeaEvent(const char * nmea,size_t length,bool fromUlp)2102 GnssAdapter::reportNmeaEvent(const char* nmea, size_t length, bool fromUlp)
2103 {
2104     // if this event is not called from ULP, then try to call into ULP and return if successfull
2105     if (!fromUlp && !loc_nmea_is_debug(nmea, length)) {
2106         if (mUlpProxy->reportNmea(nmea, length)) {
2107             return;
2108         }
2109     }
2110 
2111     struct MsgReportNmea : public LocMsg {
2112         GnssAdapter& mAdapter;
2113         const char* mNmea;
2114         size_t mLength;
2115         inline MsgReportNmea(GnssAdapter& adapter,
2116                              const char* nmea,
2117                              size_t length) :
2118             LocMsg(),
2119             mAdapter(adapter),
2120             mNmea(new char[length+1]),
2121             mLength(length) {
2122                 if (mNmea == nullptr) {
2123                     LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
2124                     return;
2125                 }
2126                 strlcpy((char*)mNmea, nmea, length+1);
2127             }
2128         inline virtual ~MsgReportNmea()
2129         {
2130             delete[] mNmea;
2131         }
2132         inline virtual void proc() const {
2133             // extract bug report info - this returns true if consumed by systemstatus
2134             bool ret = false;
2135             SystemStatus* s = mAdapter.getSystemStatus();
2136             if (nullptr != s) {
2137                 ret = s->setNmeaString(mNmea, mLength);
2138             }
2139             if (false == ret) {
2140                 // forward NMEA message to upper layer
2141                 mAdapter.reportNmea(mNmea, mLength);
2142             }
2143         }
2144     };
2145 
2146     sendMsg(new MsgReportNmea(*this, nmea, length));
2147 }
2148 
2149 void
reportNmea(const char * nmea,size_t length)2150 GnssAdapter::reportNmea(const char* nmea, size_t length)
2151 {
2152     GnssNmeaNotification nmeaNotification = {};
2153     nmeaNotification.size = sizeof(GnssNmeaNotification);
2154 
2155     struct timeval tv;
2156     gettimeofday(&tv, (struct timezone *) NULL);
2157     int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
2158     nmeaNotification.timestamp = now;
2159     nmeaNotification.nmea = nmea;
2160     nmeaNotification.length = length;
2161 
2162     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2163         if (nullptr != it->second.gnssNmeaCb) {
2164             it->second.gnssNmeaCb(nmeaNotification);
2165         }
2166     }
2167 }
2168 
2169 bool
requestNiNotifyEvent(const GnssNiNotification & notify,const void * data)2170 GnssAdapter::requestNiNotifyEvent(const GnssNiNotification &notify, const void* data)
2171 {
2172     LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d"
2173              "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s",
2174              __func__, notify.type, notify.timeout, notify.timeoutResponse,
2175              notify.requestor, notify.requestorEncoding,
2176              notify.message, notify.messageEncoding, notify.extras);
2177 
2178     struct MsgReportNiNotify : public LocMsg {
2179         GnssAdapter& mAdapter;
2180         const GnssNiNotification mNotify;
2181         const void* mData;
2182         inline MsgReportNiNotify(GnssAdapter& adapter,
2183                                  const GnssNiNotification& notify,
2184                                  const void* data) :
2185             LocMsg(),
2186             mAdapter(adapter),
2187             mNotify(notify),
2188             mData(data) {}
2189         inline virtual void proc() const {
2190             mAdapter.requestNiNotify(mNotify, mData);
2191         }
2192     };
2193 
2194     sendMsg(new MsgReportNiNotify(*this, notify, data));
2195 
2196     return true;
2197 }
2198 
niThreadProc(void * args)2199 static void* niThreadProc(void *args)
2200 {
2201     NiSession* pSession = (NiSession*)args;
2202     int rc = 0;          /* return code from pthread calls */
2203 
2204     struct timeval present_time;
2205     struct timespec expire_time;
2206 
2207     pthread_mutex_lock(&pSession->tLock);
2208     /* Calculate absolute expire time */
2209     gettimeofday(&present_time, NULL);
2210     expire_time.tv_sec  = present_time.tv_sec + pSession->respTimeLeft;
2211     expire_time.tv_nsec = present_time.tv_usec * 1000;
2212     LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec",
2213              __func__, (long)expire_time.tv_sec, pSession->respTimeLeft);
2214 
2215     while (!pSession->respRecvd) {
2216         rc = pthread_cond_timedwait(&pSession->tCond,
2217                                     &pSession->tLock,
2218                                     &expire_time);
2219         if (rc == ETIMEDOUT) {
2220             pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE;
2221             LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d",
2222                      __func__, rc);
2223             break;
2224         }
2225     }
2226     LOC_LOGD("%s]: Java layer has sent us a user response and return value from "
2227              "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp);
2228     pSession->respRecvd = false; /* Reset the user response flag for the next session*/
2229 
2230     // adding this check to support modem restart, in which case, we need the thread
2231     // to exit without calling sending data. We made sure that rawRequest is NULL in
2232     // loc_eng_ni_reset_on_engine_restart()
2233     GnssAdapter* adapter = pSession->adapter;
2234     GnssNiResponse resp;
2235     void* rawRequest = NULL;
2236     bool sendResponse = false;
2237 
2238     if (NULL != pSession->rawRequest) {
2239         if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) {
2240             resp = pSession->resp;
2241             rawRequest = pSession->rawRequest;
2242             sendResponse = true;
2243         } else {
2244             free(pSession->rawRequest);
2245         }
2246         pSession->rawRequest = NULL;
2247     }
2248     pthread_mutex_unlock(&pSession->tLock);
2249 
2250     pSession->respTimeLeft = 0;
2251     pSession->reqID = 0;
2252 
2253     if (sendResponse) {
2254         adapter->gnssNiResponseCommand(resp, rawRequest);
2255     }
2256 
2257     return NULL;
2258 }
2259 
2260 bool
requestNiNotify(const GnssNiNotification & notify,const void * data)2261 GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data)
2262 {
2263     NiSession* pSession = NULL;
2264     gnssNiCallback gnssNiCb = nullptr;
2265 
2266     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2267         if (nullptr != it->second.gnssNiCb) {
2268             gnssNiCb = it->second.gnssNiCb;
2269             break;
2270         }
2271     }
2272     if (nullptr == gnssNiCb) {
2273         EXIT_LOG(%s, "no clients with gnssNiCb.");
2274         return false;
2275     }
2276 
2277     if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) {
2278         if (NULL != mNiData.sessionEs.rawRequest) {
2279             LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d",
2280                      __func__, notify.type);
2281             if (NULL != data) {
2282                 free((void*)data);
2283             }
2284         } else {
2285             pSession = &mNiData.sessionEs;
2286         }
2287     } else {
2288         if (NULL != mNiData.session.rawRequest ||
2289             NULL != mNiData.sessionEs.rawRequest) {
2290             LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d",
2291                      __func__, notify.type);
2292             if (NULL != data) {
2293                 free((void*)data);
2294             }
2295         } else {
2296             pSession = &mNiData.session;
2297         }
2298     }
2299 
2300     if (pSession) {
2301         /* Save request */
2302         pSession->rawRequest = (void*)data;
2303         pSession->reqID = ++mNiData.reqIDCounter;
2304         pSession->adapter = this;
2305 
2306         int sessionId = pSession->reqID;
2307 
2308         /* For robustness, spawn a thread at this point to timeout to clear up the notification
2309          * status, even though the OEM layer in java does not do so.
2310          **/
2311         pSession->respTimeLeft =
2312              5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME);
2313 
2314         int rc = 0;
2315         rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession);
2316         if (rc) {
2317             LOC_LOGE("%s]: Loc NI thread is not created.", __func__);
2318         }
2319         rc = pthread_detach(pSession->thread);
2320         if (rc) {
2321             LOC_LOGE("%s]: Loc NI thread is not detached.", __func__);
2322         }
2323 
2324         if (nullptr != gnssNiCb) {
2325             gnssNiCb(sessionId, notify);
2326         }
2327     }
2328 
2329     return true;
2330 }
2331 
2332 void
reportGnssMeasurementDataEvent(const GnssMeasurementsNotification & measurements,int msInWeek)2333 GnssAdapter::reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurements,
2334                                             int msInWeek)
2335 {
2336     LOC_LOGD("%s]: ", __func__);
2337 
2338     struct MsgReportGnssMeasurementData : public LocMsg {
2339         GnssAdapter& mAdapter;
2340         GnssMeasurementsNotification mMeasurementsNotify;
2341         inline MsgReportGnssMeasurementData(GnssAdapter& adapter,
2342                                             const GnssMeasurementsNotification& measurements,
2343                                             int msInWeek) :
2344                 LocMsg(),
2345                 mAdapter(adapter),
2346                 mMeasurementsNotify(measurements) {
2347             if (-1 != msInWeek) {
2348                 mAdapter.getAgcInformation(mMeasurementsNotify, msInWeek);
2349             }
2350         }
2351         inline virtual void proc() const {
2352             mAdapter.reportGnssMeasurementData(mMeasurementsNotify);
2353         }
2354     };
2355 
2356     sendMsg(new MsgReportGnssMeasurementData(*this, measurements, msInWeek));
2357 }
2358 
2359 void
reportGnssMeasurementData(const GnssMeasurementsNotification & measurements)2360 GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurements)
2361 {
2362     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2363         if (nullptr != it->second.gnssMeasurementsCb) {
2364             it->second.gnssMeasurementsCb(measurements);
2365         }
2366     }
2367 }
2368 
2369 void
reportSvMeasurementEvent(GnssSvMeasurementSet & svMeasurementSet)2370 GnssAdapter::reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet)
2371 {
2372     LOC_LOGD("%s]: ", __func__);
2373 
2374     // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
2375     mUlpProxy->reportSvMeasurement(svMeasurementSet);
2376 }
2377 
2378 void
reportSvPolynomialEvent(GnssSvPolynomial & svPolynomial)2379 GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial)
2380 {
2381     LOC_LOGD("%s]: ", __func__);
2382 
2383     // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
2384     mUlpProxy->reportSvPolynomial(svPolynomial);
2385 }
2386 
2387 /* INIT LOC AGPS MANAGER */
initAgpsCommand(const AgpsCbInfo & cbInfo)2388 void GnssAdapter::initAgpsCommand(const AgpsCbInfo& cbInfo){
2389 
2390     LOC_LOGI("GnssAdapter::initAgpsCommand");
2391 
2392     /* Set ATL open/close callbacks */
2393     AgpsAtlOpenStatusCb atlOpenStatusCb =
2394             [this](int handle, int isSuccess, char* apn,
2395                     AGpsBearerType bearerType, AGpsExtType agpsType) {
2396 
2397                 mLocApi->atlOpenStatus(
2398                         handle, isSuccess, apn, bearerType, agpsType);
2399             };
2400     AgpsAtlCloseStatusCb atlCloseStatusCb =
2401             [this](int handle, int isSuccess) {
2402 
2403                 mLocApi->atlCloseStatus(handle, isSuccess);
2404             };
2405 
2406     /* Register DS Client APIs */
2407     AgpsDSClientInitFn dsClientInitFn =
2408             [this](bool isDueToSSR) {
2409 
2410                 return mLocApi->initDataServiceClient(isDueToSSR);
2411             };
2412 
2413     AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn =
2414             [this] {
2415 
2416                 return mLocApi->openAndStartDataCall();
2417             };
2418 
2419     AgpsDSClientStopDataCallFn dsClientStopDataCallFn =
2420             [this] {
2421 
2422                 mLocApi->stopDataCall();
2423             };
2424 
2425     AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn =
2426             [this] {
2427 
2428                 mLocApi->closeDataCall();
2429             };
2430 
2431     AgpsDSClientReleaseFn dsClientReleaseFn =
2432             [this] {
2433 
2434                 mLocApi->releaseDataServiceClient();
2435             };
2436 
2437     /* Send Msg function */
2438     SendMsgToAdapterMsgQueueFn sendMsgFn =
2439             [this](LocMsg* msg) {
2440 
2441                 sendMsg(msg);
2442             };
2443 
2444     /* Message to initialize AGPS module */
2445     struct AgpsMsgInit: public LocMsg {
2446 
2447         AgpsManager* mAgpsManager;
2448 
2449         AgpsFrameworkInterface::AgnssStatusIpV4Cb mFrameworkStatusV4Cb;
2450 
2451         AgpsAtlOpenStatusCb mAtlOpenStatusCb;
2452         AgpsAtlCloseStatusCb mAtlCloseStatusCb;
2453 
2454         AgpsDSClientInitFn mDSClientInitFn;
2455         AgpsDSClientOpenAndStartDataCallFn mDSClientOpenAndStartDataCallFn;
2456         AgpsDSClientStopDataCallFn mDSClientStopDataCallFn;
2457         AgpsDSClientCloseDataCallFn mDSClientCloseDataCallFn;
2458         AgpsDSClientReleaseFn mDSClientReleaseFn;
2459 
2460         SendMsgToAdapterMsgQueueFn mSendMsgFn;
2461         GnssAdapter& mAdapter;
2462 
2463         inline AgpsMsgInit(AgpsManager* agpsManager,
2464                 AgpsFrameworkInterface::AgnssStatusIpV4Cb frameworkStatusV4Cb,
2465                 AgpsAtlOpenStatusCb atlOpenStatusCb,
2466                 AgpsAtlCloseStatusCb atlCloseStatusCb,
2467                 AgpsDSClientInitFn dsClientInitFn,
2468                 AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn,
2469                 AgpsDSClientStopDataCallFn dsClientStopDataCallFn,
2470                 AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn,
2471                 AgpsDSClientReleaseFn dsClientReleaseFn,
2472                 SendMsgToAdapterMsgQueueFn sendMsgFn,
2473                 GnssAdapter& adapter) :
2474                 LocMsg(), mAgpsManager(agpsManager), mFrameworkStatusV4Cb(
2475                         frameworkStatusV4Cb), mAtlOpenStatusCb(atlOpenStatusCb), mAtlCloseStatusCb(
2476                         atlCloseStatusCb), mDSClientInitFn(dsClientInitFn), mDSClientOpenAndStartDataCallFn(
2477                         dsClientOpenAndStartDataCallFn), mDSClientStopDataCallFn(
2478                         dsClientStopDataCallFn), mDSClientCloseDataCallFn(
2479                         dsClientCloseDataCallFn), mDSClientReleaseFn(
2480                         dsClientReleaseFn), mSendMsgFn(sendMsgFn),
2481                         mAdapter(adapter) {
2482 
2483             LOC_LOGV("AgpsMsgInit");
2484         }
2485 
2486         inline virtual void proc() const {
2487 
2488             LOC_LOGV("AgpsMsgInit::proc()");
2489 
2490             mAgpsManager->registerCallbacks(mFrameworkStatusV4Cb, mAtlOpenStatusCb,
2491                     mAtlCloseStatusCb, mDSClientInitFn,
2492                     mDSClientOpenAndStartDataCallFn, mDSClientStopDataCallFn,
2493                     mDSClientCloseDataCallFn, mDSClientReleaseFn, mSendMsgFn);
2494 
2495             mAgpsManager->createAgpsStateMachines();
2496 
2497             /* Register for AGPS event mask */
2498             mAdapter.updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST,
2499                                    LOC_REGISTRATION_MASK_ENABLED);
2500         }
2501     };
2502 
2503     if (mAgpsCbInfo.cbPriority > cbInfo.cbPriority) {
2504         LOC_LOGI("Higher priority AGPS CB already registered (%d > %d) !",
2505                 mAgpsCbInfo.cbPriority, cbInfo.cbPriority);
2506         return;
2507     } else {
2508         mAgpsCbInfo = cbInfo;
2509         LOC_LOGI("Registering AGPS CB %p with priority %d",
2510                 mAgpsCbInfo.statusV4Cb, mAgpsCbInfo.cbPriority);
2511     }
2512 
2513     /* Send message to initialize AGPS Manager */
2514     sendMsg(new AgpsMsgInit(
2515                 &mAgpsManager,
2516                 (AgpsFrameworkInterface::AgnssStatusIpV4Cb)cbInfo.statusV4Cb,
2517                 atlOpenStatusCb, atlCloseStatusCb,
2518                 dsClientInitFn, dsClientOpenAndStartDataCallFn,
2519                 dsClientStopDataCallFn, dsClientCloseDataCallFn,
2520                 dsClientReleaseFn,
2521                 sendMsgFn,
2522                 *this));
2523 }
2524 
2525 /* GnssAdapter::requestATL
2526  * Method triggered in QMI thread as part of handling below message:
2527  * eQMI_LOC_SERVER_REQUEST_OPEN_V02
2528  * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
2529  * eQMI_LOC_WWAN_TYPE_INTERNET_V02
2530  * eQMI_LOC_WWAN_TYPE_AGNSS_V02 */
requestATL(int connHandle,LocAGpsType agpsType)2531 bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType){
2532 
2533     LOC_LOGI("GnssAdapter::requestATL");
2534 
2535     sendMsg( new AgpsMsgRequestATL(
2536              &mAgpsManager, connHandle, (AGpsExtType)agpsType));
2537 
2538     return true;
2539 }
2540 
2541 /* GnssAdapter::requestSuplES
2542  * Method triggered in QMI thread as part of handling below message:
2543  * eQMI_LOC_SERVER_REQUEST_OPEN_V02
2544  * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
2545  * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */
requestSuplES(int connHandle)2546 bool GnssAdapter::requestSuplES(int connHandle){
2547 
2548     LOC_LOGI("GnssAdapter::requestSuplES");
2549 
2550     sendMsg( new AgpsMsgRequestATL(
2551              &mAgpsManager, connHandle, LOC_AGPS_TYPE_SUPL_ES));
2552 
2553     return true;
2554 }
2555 
2556 /* GnssAdapter::releaseATL
2557  * Method triggered in QMI thread as part of handling below message:
2558  * eQMI_LOC_SERVER_REQUEST_CLOSE_V02
2559  * Triggers teardown of an existing AGPS call */
releaseATL(int connHandle)2560 bool GnssAdapter::releaseATL(int connHandle){
2561 
2562     LOC_LOGI("GnssAdapter::releaseATL");
2563 
2564     /* Release SUPL/INTERNET/SUPL_ES ATL */
2565     struct AgpsMsgReleaseATL: public LocMsg {
2566 
2567         AgpsManager* mAgpsManager;
2568         int mConnHandle;
2569 
2570         inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) :
2571                 LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) {
2572 
2573             LOC_LOGV("AgpsMsgReleaseATL");
2574         }
2575 
2576         inline virtual void proc() const {
2577 
2578             LOC_LOGV("AgpsMsgReleaseATL::proc()");
2579             mAgpsManager->releaseATL(mConnHandle);
2580         }
2581     };
2582 
2583     sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle));
2584 
2585     return true;
2586 }
2587 
2588 /* GnssAdapter::reportDataCallOpened
2589  * DS Client data call opened successfully.
2590  * Send message to AGPS Manager to handle. */
reportDataCallOpened()2591 bool GnssAdapter::reportDataCallOpened(){
2592 
2593     LOC_LOGI("GnssAdapter::reportDataCallOpened");
2594 
2595     struct AgpsMsgSuplEsOpened: public LocMsg {
2596 
2597         AgpsManager* mAgpsManager;
2598 
2599         inline AgpsMsgSuplEsOpened(AgpsManager* agpsManager) :
2600                 LocMsg(), mAgpsManager(agpsManager) {
2601 
2602             LOC_LOGV("AgpsMsgSuplEsOpened");
2603         }
2604 
2605         inline virtual void proc() const {
2606 
2607             LOC_LOGV("AgpsMsgSuplEsOpened::proc()");
2608             mAgpsManager->reportDataCallOpened();
2609         }
2610     };
2611 
2612     sendMsg( new AgpsMsgSuplEsOpened(&mAgpsManager));
2613 
2614     return true;
2615 }
2616 
2617 /* GnssAdapter::reportDataCallClosed
2618  * DS Client data call closed.
2619  * Send message to AGPS Manager to handle. */
reportDataCallClosed()2620 bool GnssAdapter::reportDataCallClosed(){
2621 
2622     LOC_LOGI("GnssAdapter::reportDataCallClosed");
2623 
2624     struct AgpsMsgSuplEsClosed: public LocMsg {
2625 
2626         AgpsManager* mAgpsManager;
2627 
2628         inline AgpsMsgSuplEsClosed(AgpsManager* agpsManager) :
2629                 LocMsg(), mAgpsManager(agpsManager) {
2630 
2631             LOC_LOGV("AgpsMsgSuplEsClosed");
2632         }
2633 
2634         inline virtual void proc() const {
2635 
2636             LOC_LOGV("AgpsMsgSuplEsClosed::proc()");
2637             mAgpsManager->reportDataCallClosed();
2638         }
2639     };
2640 
2641     sendMsg( new AgpsMsgSuplEsClosed(&mAgpsManager));
2642 
2643     return true;
2644 }
2645 
dataConnOpenCommand(AGpsExtType agpsType,const char * apnName,int apnLen,LocApnIpType ipType)2646 void GnssAdapter::dataConnOpenCommand(
2647         AGpsExtType agpsType,
2648         const char* apnName, int apnLen, LocApnIpType ipType){
2649 
2650     LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
2651 
2652     struct AgpsMsgAtlOpenSuccess: public LocMsg {
2653 
2654         AgpsManager* mAgpsManager;
2655         AGpsExtType mAgpsType;
2656         char* mApnName;
2657         int mApnLen;
2658         LocApnIpType mIpType;
2659 
2660         inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType,
2661                 const char* apnName, int apnLen, LocApnIpType ipType) :
2662                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName(
2663                         new char[apnLen + 1]), mApnLen(apnLen), mIpType(ipType) {
2664 
2665             LOC_LOGV("AgpsMsgAtlOpenSuccess");
2666             if (mApnName == nullptr) {
2667                 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
2668                 return;
2669             }
2670             memcpy(mApnName, apnName, apnLen);
2671             mApnName[apnLen] = 0;
2672         }
2673 
2674         inline ~AgpsMsgAtlOpenSuccess() {
2675             delete[] mApnName;
2676         }
2677 
2678         inline virtual void proc() const {
2679 
2680             LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()");
2681             mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen,
2682                     mIpType);
2683         }
2684     };
2685 
2686     sendMsg( new AgpsMsgAtlOpenSuccess(
2687             &mAgpsManager, (AGpsExtType)agpsType, apnName, apnLen, ipType));
2688 }
2689 
dataConnClosedCommand(AGpsExtType agpsType)2690 void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
2691 
2692     LOC_LOGI("GnssAdapter::frameworkDataConnClosed");
2693 
2694     struct AgpsMsgAtlClosed: public LocMsg {
2695 
2696         AgpsManager* mAgpsManager;
2697         AGpsExtType mAgpsType;
2698 
2699         inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) :
2700                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
2701 
2702             LOC_LOGV("AgpsMsgAtlClosed");
2703         }
2704 
2705         inline virtual void proc() const {
2706 
2707             LOC_LOGV("AgpsMsgAtlClosed::proc()");
2708             mAgpsManager->reportAtlClosed(mAgpsType);
2709         }
2710     };
2711 
2712     sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType));
2713 }
2714 
dataConnFailedCommand(AGpsExtType agpsType)2715 void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){
2716 
2717     LOC_LOGI("GnssAdapter::frameworkDataConnFailed");
2718 
2719     struct AgpsMsgAtlOpenFailed: public LocMsg {
2720 
2721         AgpsManager* mAgpsManager;
2722         AGpsExtType mAgpsType;
2723 
2724         inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) :
2725                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
2726 
2727             LOC_LOGV("AgpsMsgAtlOpenFailed");
2728         }
2729 
2730         inline virtual void proc() const {
2731 
2732             LOC_LOGV("AgpsMsgAtlOpenFailed::proc()");
2733             mAgpsManager->reportAtlOpenFailed(mAgpsType);
2734         }
2735     };
2736 
2737     sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType));
2738 }
2739 
convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo> & out,const GnssSvType & in_constellation,const SystemStatusReports & in)2740 void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out,
2741                                        const GnssSvType& in_constellation,
2742                                        const SystemStatusReports& in)
2743 {
2744     uint64_t sv_mask = 0ULL;
2745     uint32_t svid_min = 0;
2746     uint32_t svid_num = 0;
2747     uint32_t svid_idx = 0;
2748 
2749     uint64_t eph_health_good_mask = 0ULL;
2750     uint64_t eph_health_bad_mask = 0ULL;
2751     uint64_t server_perdiction_available_mask = 0ULL;
2752     float server_perdiction_age = 0.0f;
2753 
2754     // set constellationi based parameters
2755     switch (in_constellation) {
2756         case GNSS_SV_TYPE_GPS:
2757             svid_min = GNSS_BUGREPORT_GPS_MIN;
2758             svid_num = GPS_NUM;
2759             svid_idx = 0;
2760             if (!in.mSvHealth.empty()) {
2761                 eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask;
2762                 eph_health_bad_mask  = in.mSvHealth.back().mGpsBadMask;
2763             }
2764             if (!in.mXtra.empty()) {
2765                 server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid;
2766                 server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge);
2767             }
2768             break;
2769         case GNSS_SV_TYPE_GLONASS:
2770             svid_min = GNSS_BUGREPORT_GLO_MIN;
2771             svid_num = GLO_NUM;
2772             svid_idx = GPS_NUM;
2773             if (!in.mSvHealth.empty()) {
2774                 eph_health_good_mask = in.mSvHealth.back().mGloGoodMask;
2775                 eph_health_bad_mask  = in.mSvHealth.back().mGloBadMask;
2776             }
2777             if (!in.mXtra.empty()) {
2778                 server_perdiction_available_mask = in.mXtra.back().mGloXtraValid;
2779                 server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge);
2780             }
2781             break;
2782         case GNSS_SV_TYPE_QZSS:
2783             svid_min = GNSS_BUGREPORT_QZSS_MIN;
2784             svid_num = QZSS_NUM;
2785             svid_idx = GPS_NUM+GLO_NUM+BDS_NUM+GAL_NUM;
2786             if (!in.mSvHealth.empty()) {
2787                 eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask;
2788                 eph_health_bad_mask  = in.mSvHealth.back().mQzssBadMask;
2789             }
2790             if (!in.mXtra.empty()) {
2791                 server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid;
2792                 server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge);
2793             }
2794             break;
2795         case GNSS_SV_TYPE_BEIDOU:
2796             svid_min = GNSS_BUGREPORT_BDS_MIN;
2797             svid_num = BDS_NUM;
2798             svid_idx = GPS_NUM+GLO_NUM;
2799             if (!in.mSvHealth.empty()) {
2800                 eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask;
2801                 eph_health_bad_mask  = in.mSvHealth.back().mBdsBadMask;
2802             }
2803             if (!in.mXtra.empty()) {
2804                 server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid;
2805                 server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge);
2806             }
2807             break;
2808         case GNSS_SV_TYPE_GALILEO:
2809             svid_min = GNSS_BUGREPORT_GAL_MIN;
2810             svid_num = GAL_NUM;
2811             svid_idx = GPS_NUM+GLO_NUM+BDS_NUM;
2812             if (!in.mSvHealth.empty()) {
2813                 eph_health_good_mask = in.mSvHealth.back().mGalGoodMask;
2814                 eph_health_bad_mask  = in.mSvHealth.back().mGalBadMask;
2815             }
2816             if (!in.mXtra.empty()) {
2817                 server_perdiction_available_mask = in.mXtra.back().mGalXtraValid;
2818                 server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge);
2819             }
2820             break;
2821         default:
2822             return;
2823     }
2824 
2825     // extract each sv info from systemstatus report
2826     for(uint32_t i=0; i<svid_num && (svid_idx+i)<SV_ALL_NUM; i++) {
2827 
2828         GnssDebugSatelliteInfo s = {};
2829         s.size = sizeof(s);
2830         s.svid = i + svid_min;
2831         s.constellation = in_constellation;
2832 
2833         if (!in.mNavData.empty()) {
2834             s.mEphemerisType   = in.mNavData.back().mNav[svid_idx+i].mType;
2835             s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource;
2836         }
2837         else {
2838             s.mEphemerisType   = GNSS_EPH_TYPE_UNKNOWN;
2839             s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN;
2840         }
2841 
2842         sv_mask = 0x1ULL << i;
2843         if (eph_health_good_mask & sv_mask) {
2844             s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD;
2845         }
2846         else if (eph_health_bad_mask & sv_mask) {
2847             s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD;
2848         }
2849         else {
2850             s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN;
2851         }
2852 
2853         if (!in.mNavData.empty()) {
2854             s.ephemerisAgeSeconds =
2855                 (float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec);
2856         }
2857         else {
2858             s.ephemerisAgeSeconds = 0.0f;
2859         }
2860 
2861         if (server_perdiction_available_mask & sv_mask) {
2862             s.serverPredictionIsAvailable = true;
2863         }
2864         else {
2865             s.serverPredictionIsAvailable = false;
2866         }
2867 
2868         s.serverPredictionAgeSeconds = server_perdiction_age;
2869         out.push_back(s);
2870     }
2871 
2872     return;
2873 }
2874 
getDebugReport(GnssDebugReport & r)2875 bool GnssAdapter::getDebugReport(GnssDebugReport& r)
2876 {
2877     LOC_LOGD("%s]: ", __func__);
2878 
2879     SystemStatus* systemstatus = getSystemStatus();
2880     if (nullptr == systemstatus) {
2881         return false;
2882     }
2883 
2884     SystemStatusReports reports = {};
2885     systemstatus->getReport(reports, true);
2886 
2887     r.size = sizeof(r);
2888 
2889     // location block
2890     r.mLocation.size = sizeof(r.mLocation);
2891     if(!reports.mLocation.empty() && reports.mLocation.back().mValid) {
2892         r.mLocation.mValid = true;
2893         r.mLocation.mLocation.latitude =
2894             reports.mLocation.back().mLocation.gpsLocation.latitude;
2895         r.mLocation.mLocation.longitude =
2896             reports.mLocation.back().mLocation.gpsLocation.longitude;
2897         r.mLocation.mLocation.altitude =
2898             reports.mLocation.back().mLocation.gpsLocation.altitude;
2899         r.mLocation.mLocation.speed =
2900             (double)(reports.mLocation.back().mLocation.gpsLocation.speed);
2901         r.mLocation.mLocation.bearing =
2902             (double)(reports.mLocation.back().mLocation.gpsLocation.bearing);
2903         r.mLocation.mLocation.accuracy =
2904             (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy);
2905 
2906         r.mLocation.verticalAccuracyMeters =
2907             reports.mLocation.back().mLocationEx.vert_unc;
2908         r.mLocation.speedAccuracyMetersPerSecond =
2909             reports.mLocation.back().mLocationEx.speed_unc;
2910         r.mLocation.bearingAccuracyDegrees =
2911             reports.mLocation.back().mLocationEx.bearing_unc;
2912 
2913         r.mLocation.mUtcReported =
2914             reports.mLocation.back().mUtcReported;
2915     }
2916     else if(!reports.mBestPosition.empty() && reports.mBestPosition.back().mValid) {
2917         r.mLocation.mValid = true;
2918         r.mLocation.mLocation.latitude  =
2919             (double)(reports.mBestPosition.back().mBestLat);
2920         r.mLocation.mLocation.longitude =
2921             (double)(reports.mBestPosition.back().mBestLon);
2922         r.mLocation.mLocation.altitude  =
2923             reports.mBestPosition.back().mBestAlt;
2924 
2925         r.mLocation.mLocation.timestamp =
2926             reports.mBestPosition.back().mUtcReported.tv_sec * 1000ULL +
2927             reports.mBestPosition.back().mUtcReported.tv_nsec / 1000000ULL;
2928     }
2929     else {
2930         r.mLocation.mValid = false;
2931     }
2932 
2933     if (r.mLocation.mValid) {
2934         LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f",
2935             r.mLocation.mLocation.latitude,
2936             r.mLocation.mLocation.longitude,
2937             r.mLocation.mLocation.altitude,
2938             r.mLocation.mLocation.speed);
2939     }
2940 
2941     // time block
2942     r.mTime.size = sizeof(r.mTime);
2943     if(!reports.mTimeAndClock.empty() && reports.mTimeAndClock.back().mTimeValid) {
2944         r.mTime.mValid = true;
2945         r.mTime.timeEstimate =
2946             (((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 +
2947                         GNSS_UTC_TIME_OFFSET)*24*60*60 -
2948               (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL +
2949               (int64_t)(reports.mTimeAndClock.back().mGpsTowMs);
2950 
2951         r.mTime.timeUncertaintyNs =
2952             (float)((reports.mTimeAndClock.back().mTimeUnc +
2953                      reports.mTimeAndClock.back().mLeapSecUnc)*1000);
2954         r.mTime.frequencyUncertaintyNsPerSec =
2955             (float)(reports.mTimeAndClock.back().mClockFreqBiasUnc);
2956         LOC_LOGV("getDebugReport - timeestimate=%" PRIu64 " unc=%f frequnc=%f",
2957                 r.mTime.timeEstimate,
2958                 r.mTime.timeUncertaintyNs, r.mTime.frequencyUncertaintyNsPerSec);
2959     }
2960     else {
2961         r.mTime.mValid = false;
2962     }
2963 
2964     // satellite info block
2965     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports);
2966     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports);
2967     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports);
2968     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports);
2969     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports);
2970     LOC_LOGV("getDebugReport - satellite=%zu", r.mSatelliteInfo.size());
2971 
2972     return true;
2973 }
2974 
2975 /* get AGC information from system status and fill it */
2976 void
getAgcInformation(GnssMeasurementsNotification & measurements,int msInWeek)2977 GnssAdapter::getAgcInformation(GnssMeasurementsNotification& measurements, int msInWeek)
2978 {
2979     SystemStatus* systemstatus = getSystemStatus();
2980 
2981     if (nullptr != systemstatus) {
2982         SystemStatusReports reports = {};
2983         systemstatus->getReport(reports, true);
2984 
2985         if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
2986             reports.mTimeAndClock.back().mTimeValid &&
2987             (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
2988 
2989             for (size_t i = 0; i < measurements.count; i++) {
2990                 switch (measurements.measurements[i].svType) {
2991                 case GNSS_SV_TYPE_GPS:
2992                     measurements.measurements[i].agcLevelDb =
2993                             reports.mRfAndParams.back().mAgcGps;
2994                     measurements.measurements[i].flags |=
2995                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
2996                     break;
2997 
2998                 case GNSS_SV_TYPE_GALILEO:
2999                     measurements.measurements[i].agcLevelDb =
3000                             reports.mRfAndParams.back().mAgcGal;
3001                     measurements.measurements[i].flags |=
3002                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
3003                     break;
3004 
3005                 case GNSS_SV_TYPE_GLONASS:
3006                     measurements.measurements[i].agcLevelDb =
3007                             reports.mRfAndParams.back().mAgcGlo;
3008                     measurements.measurements[i].flags |=
3009                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
3010                     break;
3011 
3012                 case GNSS_SV_TYPE_BEIDOU:
3013                     measurements.measurements[i].agcLevelDb =
3014                             reports.mRfAndParams.back().mAgcBds;
3015                     measurements.measurements[i].flags |=
3016                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
3017                     break;
3018 
3019                 case GNSS_SV_TYPE_QZSS:
3020                 case GNSS_SV_TYPE_SBAS:
3021                 case GNSS_SV_TYPE_UNKNOWN:
3022                 default:
3023                     break;
3024                 }
3025             }
3026         }
3027     }
3028 }
3029 
3030