1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifdef FEATURE_GNSS_SUPPORT
17 #include "gnss_event_callback.h"
18 #include <singleton.h>
19 #include <sys/time.h>
20 #include "ipc_skeleton.h"
21 #include "common_utils.h"
22 #include "gnss_ability.h"
23 #include "location_log.h"
24 #include "location_log_event_ids.h"
25 #include "common_hisysevent.h"
26 #include "agnss_ni_manager.h"
27 
28 #ifdef TIME_SERVICE_ENABLE
29 #include "ntp_time_check.h"
30 #include "time_service_client.h"
31 #endif
32 namespace OHOS {
33 namespace Location {
34 using namespace OHOS::HiviewDFX;
35 const int WEAK_GPS_SIGNAL_SCENARIO_COUNT = 3;
36 const int MAX_SV_COUNT = 64;
37 const int GPS_DUMMY_SV_COUNT = 5;
38 const int AZIMUTH_DEGREES = 60;
39 const int ELEVATION_DEGREES = 90;
40 const int SATELLITES_ADDITIONAL = 4;
41 bool g_hasLocation = false;
42 bool g_svIncrease = false;
43 std::unique_ptr<SatelliteStatus> g_svInfo = nullptr;
44 
SetGpsTime(int64_t gpsTime)45 static void SetGpsTime(int64_t gpsTime)
46 {
47 #ifdef TIME_SERVICE_ENABLE
48     auto ntpTimeCheck = NtpTimeCheck::GetInstance();
49     if (ntpTimeCheck != nullptr) {
50         auto elapsedRealTime = MiscServices::TimeServiceClient::GetInstance()->GetBootTimeMs();
51         ntpTimeCheck->SetGpsTime(gpsTime, elapsedRealTime);
52     }
53 #endif
54 }
55 
ReportLocation(const LocationInfo & location)56 int32_t GnssEventCallback::ReportLocation(const LocationInfo& location)
57 {
58     auto gnssAbility = GnssAbility::GetInstance();
59     if (gnssAbility == nullptr) {
60         LBSLOGE(GNSS, "ReportLocation: gnss ability is nullptr.");
61         return ERR_OK;
62     }
63     std::string identity = IPCSkeleton::ResetCallingIdentity();
64     std::shared_ptr<Location> locationNew = std::make_shared<Location>();
65     locationNew->SetLatitude(location.latitude);
66     locationNew->SetLongitude(location.longitude);
67     locationNew->SetAltitude(location.altitude);
68     locationNew->SetAccuracy(location.horizontalAccuracy);
69     locationNew->SetSpeed(location.speed);
70     locationNew->SetDirection(location.bearing);
71     locationNew->SetAltitudeAccuracy(location.verticalAccuracy);
72     locationNew->SetSpeedAccuracy(location.speedAccuracy);
73     locationNew->SetDirectionAccuracy(location.bearingAccuracy);
74     locationNew->SetTimeStamp(location.timeForFix);
75     locationNew->SetTimeSinceBoot(location.timeSinceBoot);
76     locationNew->SetUncertaintyOfTimeSinceBoot(location.timeUncertainty);
77     locationNew->SetIsFromMock(false);
78     locationNew->SetLocationSourceType(LocationSourceType::GNSS_TYPE);
79     locationNew->SetFieldValidity(location.fieldValidity);
80     if (gnssAbility->IsMockEnabled()) {
81         LBSLOGE(GNSS, "location mock is enabled, do not report gnss location!");
82         IPCSkeleton::SetCallingIdentity(identity);
83         return ERR_OK;
84     }
85     // add dummy sv if needed
86     SendDummySvInfo();
87     struct timeval now;
88     gettimeofday(&now, NULL);
89     WriteLocationInnerEvent(RECEIVE_GNSS_LOCATION, {
90         "speed", std::to_string(location.speed),
91         "accuracy", std::to_string(location.horizontalAccuracy),
92         "locationTimestamp", std::to_string(location.timeForFix / MILLI_PER_SEC),
93         "receiveTimestamp", std::to_string(CommonUtils::GetCurrentTimeStamp()),
94         "latitude", std::to_string(location.latitude),
95         "longitude", std::to_string(location.longitude)});
96     gnssAbility->ReportLocationInfo(GNSS_ABILITY, locationNew);
97 #ifdef FEATURE_PASSIVE_SUPPORT
98     gnssAbility->ReportLocationInfo(PASSIVE_ABILITY, locationNew);
99 #endif
100     SetGpsTime(locationNew->GetTimeStamp());
101     IPCSkeleton::SetCallingIdentity(identity);
102     return ERR_OK;
103 }
104 
ReportGnssWorkingStatus(GnssWorkingStatus status)105 int32_t GnssEventCallback::ReportGnssWorkingStatus(GnssWorkingStatus status)
106 {
107     auto gnssAbility = GnssAbility::GetInstance();
108     if (gnssAbility == nullptr) {
109         LBSLOGE(GNSS, "ReportGnssWorkingStatus: gnss ability is nullptr.");
110         return ERR_OK;
111     }
112     gnssAbility->ReportGnssSessionStatus(static_cast<int>(status));
113     return ERR_OK;
114 }
115 
ReportNmea(int64_t timestamp,const std::string & nmea,int32_t length)116 int32_t GnssEventCallback::ReportNmea(int64_t timestamp, const std::string& nmea, int32_t length)
117 {
118     auto gnssAbility = GnssAbility::GetInstance();
119     if (gnssAbility == nullptr) {
120         LBSLOGE(GNSS, "ReportNmea: gnss ability is nullptr.");
121         return ERR_OK;
122     }
123     std::string nmeaStr = nmea;
124     gnssAbility->ReportNmea(timestamp, nmeaStr);
125     return ERR_OK;
126 }
127 
ReportGnssCapabilities(unsigned int capabilities)128 int32_t GnssEventCallback::ReportGnssCapabilities(unsigned int capabilities)
129 {
130     return ERR_OK;
131 }
132 
ReportSatelliteStatusInfo(const SatelliteStatusInfo & info)133 int32_t GnssEventCallback::ReportSatelliteStatusInfo(const SatelliteStatusInfo& info)
134 {
135     auto gnssAbility = GnssAbility::GetInstance();
136     if (gnssAbility == nullptr) {
137         LBSLOGE(GNSS, "ReportSatelliteStatusInfo: gnss ability is nullptr.");
138         return ERR_OK;
139     }
140     std::unique_ptr<SatelliteStatus> svStatus = std::make_unique<SatelliteStatus>();
141     if (info.satellitesNumber < 0) {
142         LBSLOGD(GNSS, "SvStatusCallback, satellites_num < 0!");
143         return ERR_INVALID_VALUE;
144     }
145     std::vector<std::string> names;
146     std::vector<std::string> satelliteStatusInfos;
147     names.push_back("SatelliteStatusInfo");
148     satelliteStatusInfos.push_back(std::to_string(info.satellitesNumber));
149 
150     svStatus->SetSatellitesNumber(info.satellitesNumber);
151     for (unsigned int i = 0; i < info.satellitesNumber; i++) {
152         svStatus->SetAltitude(info.elevation[i]);
153         svStatus->SetAzimuth(info.azimuths[i]);
154         svStatus->SetCarrierFrequencie(info.carrierFrequencies[i]);
155         svStatus->SetCarrierToNoiseDensity(info.carrierToNoiseDensitys[i]);
156         svStatus->SetSatelliteId(info.satelliteIds[i]);
157         svStatus->SetConstellationType(info.constellation[i]);
158         svStatus->SetSatelliteAdditionalInfo(info.additionalInfo[i]);
159         std::string str_info = "satelliteId : " + std::to_string(info.satelliteIds[i]) +
160             ", carrierToNoiseDensity : " + std::to_string(info.carrierToNoiseDensitys[i]) +
161             ", elevation : " + std::to_string(info.elevation[i]) +
162             ", azimuth : " + std::to_string(info.azimuths[i]) +
163             ", carrierFrequencie : " + std::to_string(info.carrierFrequencies[i]);
164         names.push_back(std::to_string(i));
165         satelliteStatusInfos.push_back(str_info);
166     }
167     // save sv info
168     std::unique_lock<std::mutex> lock(svInfoMutex_, std::defer_lock);
169     lock.lock();
170     g_svInfo = nullptr;
171     g_svInfo = std::make_unique<SatelliteStatus>(*svStatus);
172     lock.unlock();
173     WriteLocationInnerEvent(RECEIVE_SATELLITESTATUSINFO, names, satelliteStatusInfos);
174     gnssAbility->ReportSv(svStatus);
175     return ERR_OK;
176 }
177 
SendDummySvInfo()178 void GnssEventCallback::SendDummySvInfo()
179 {
180     std::unique_lock<std::mutex> lock(svInfoMutex_);
181     if (g_svInfo == nullptr) {
182         LBSLOGE(GNSS, "%{public}s: sv is nullptr.", __func__);
183         return;
184     }
185     // indicates location is coming
186     g_hasLocation = true;
187     int usedSvCount = 0;
188     int svListSize = g_svInfo->GetSatellitesNumber();
189     // calculate the num of used GPS satellites
190     for (int svSize = 0; svSize < svListSize; svSize++) {
191         if (IsSvTypeGps(g_svInfo, svSize) && IsSvUsed(g_svInfo, svSize)) {
192             usedSvCount++;
193         }
194     }
195     LBSLOGD(GNSS, "%{public}s: the USED GPS SV Count is %{public}d", __func__, usedSvCount);
196     // weak gps signal scenario
197     if (usedSvCount <= WEAK_GPS_SIGNAL_SCENARIO_COUNT) {
198         // indicates the need for dummy satellites
199         g_svIncrease = true;
200         LBSLOGD(GNSS, "%{public}s: start increase dummy sv", __func__);
201 
202         if (MAX_SV_COUNT - svListSize >= GPS_DUMMY_SV_COUNT) {
203             AddDummySv(g_svInfo, 4, 6); // sv1: svid = 4, cN0Dbhz = 6
204             AddDummySv(g_svInfo, 7, 15); // sv2: svid = 7, cN0Dbhz = 15
205             AddDummySv(g_svInfo, 1, 2); // sv3: svid = 1, cN0Dbhz = 2
206             AddDummySv(g_svInfo, 11, 10); // sv4: svid = 11, cN0Dbhz = 10
207             AddDummySv(g_svInfo, 17, 5); // sv5: svid = 17, cN0Dbhz = 5
208             g_svInfo->
209                 SetSatellitesNumber(g_svInfo->GetSatellitesNumber() + GPS_DUMMY_SV_COUNT);
210             ReportDummySv(g_svInfo);
211         } else {
212             LBSLOGD(GNSS, "%{public}s: sv number > 58, no need send dummy satellites", __func__);
213         }
214         LBSLOGD(GNSS, "%{public}s: increase sv finished", __func__);
215     } else {
216         // indicates no need for dummy satellites
217         g_svIncrease = false;
218     }
219 }
220 
ReportDummySv(const std::unique_ptr<SatelliteStatus> & sv)221 void GnssEventCallback::ReportDummySv(const std::unique_ptr<SatelliteStatus> &sv)
222 {
223     auto gnssAbility = GnssAbility::GetInstance();
224     if (gnssAbility == nullptr || sv == nullptr) {
225         LBSLOGE(GNSS, "%{public}s gnss ability or sv is nullptr.", __func__);
226         return;
227     }
228     gnssAbility->ReportSv(sv);
229 }
230 
IsNeedSvIncrease()231 bool GnssEventCallback::IsNeedSvIncrease()
232 {
233     if (g_hasLocation && g_svIncrease) {
234         return true;
235     }
236     return false;
237 }
238 
IsSvTypeGps(const std::unique_ptr<SatelliteStatus> & sv,int index)239 bool GnssEventCallback::IsSvTypeGps(const std::unique_ptr<SatelliteStatus> &sv, int index)
240 {
241     if (sv == nullptr) {
242         return false;
243     }
244     return sv->GetConstellationTypes()[index] == HDI::Location::Gnss::V2_0::CONSTELLATION_CATEGORY_GPS;
245 }
246 
IsSvUsed(const std::unique_ptr<SatelliteStatus> & sv,int index)247 bool GnssEventCallback::IsSvUsed(const std::unique_ptr<SatelliteStatus> &sv, int index)
248 {
249     if (sv == nullptr) {
250         return false;
251     }
252     return static_cast<uint32_t>(sv->GetSatelliteAdditionalInfoList()[index]) &
253         static_cast<uint8_t>(HDI::Location::Gnss::V2_0::SATELLITES_ADDITIONAL_INFO_USED_IN_FIX);
254 }
255 
AddDummySv(std::unique_ptr<SatelliteStatus> & sv,int svid,int cN0Dbhz)256 void GnssEventCallback::AddDummySv(std::unique_ptr<SatelliteStatus> &sv, int svid, int cN0Dbhz)
257 {
258     if (sv == nullptr) {
259         return;
260     }
261     sv->SetSatelliteId(svid);
262     sv->SetConstellationType(HDI::Location::Gnss::V2_0::CONSTELLATION_CATEGORY_GPS);
263     sv->SetCarrierToNoiseDensity(cN0Dbhz);
264     sv->SetAltitude(ELEVATION_DEGREES); // elevationDegrees
265     sv->SetAzimuth(AZIMUTH_DEGREES); // azimuthDegrees
266     sv->SetCarrierFrequencie(0); // carrierFrequencyHz
267     sv->SetSatelliteAdditionalInfo(SATELLITES_ADDITIONAL); // satellites_additional
268 }
269 
RequestGnssReferenceInfo(GnssRefInfoType type)270 int32_t GnssEventCallback::RequestGnssReferenceInfo(GnssRefInfoType type)
271 {
272     LBSLOGI(GNSS, "RequestGnssReferenceInfo: request type %{public}d", static_cast<int>(type));
273     auto gnssAbility = GnssAbility::GetInstance();
274     if (gnssAbility == nullptr) {
275         LBSLOGE(GNSS, "%{public}s gnss ability is nullptr.", __func__);
276         return ERR_OK;
277     }
278     switch (type) {
279         case GnssRefInfoType::GNSS_REF_INFO_TIME:
280             gnssAbility->InjectTime();
281             break;
282         case GnssRefInfoType::GNSS_REF_INFO_LOCATION:
283             gnssAbility->InjectLocation();
284             break;
285         default:
286             LBSLOGI(GNSS, "RequestGnssReferenceInfo: request type not support now");
287             break;
288     }
289     return ERR_OK;
290 }
291 
RequestPredictGnssData()292 int32_t GnssEventCallback::RequestPredictGnssData()
293 {
294     return ERR_OK;
295 }
296 
ReportCachedLocation(const std::vector<LocationInfo> & gnssLocations)297 int32_t GnssEventCallback::ReportCachedLocation(const std::vector<LocationInfo>& gnssLocations)
298 {
299     return ERR_OK;
300 }
301 
ReportGnssNiNotification(const GnssNiNotificationRequest & notification)302 int32_t GnssEventCallback::ReportGnssNiNotification(const GnssNiNotificationRequest& notification)
303 {
304     auto agnssNiManager = AGnssNiManager::GetInstance();
305     if (agnssNiManager == nullptr) {
306         LBSLOGE(GNSS, "ReportGnssNiNotification: agnssNiManager is nullptr.");
307         return ERR_OK;
308     }
309     agnssNiManager->HandleNiNotification(notification);
310     return ERR_OK;
311 }
312 }  // namespace Location
313 }  // namespace OHOS
314 #endif
315