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 #include "report_manager.h"
17
18 #include <cmath>
19
20 #include "common_utils.h"
21 #include "fusion_controller.h"
22 #include "i_locator_callback.h"
23 #include "location_log.h"
24 #include "locator_ability.h"
25
26 namespace OHOS {
27 namespace Location {
28 const long NANOS_PER_MILLI = 1000000L;
29 const int SECOND_TO_MILLISECOND = 1000;
30 const int MAX_SA_SCHEDULING_JITTER_MS = 200;
31 static constexpr double MAXIMUM_FUZZY_LOCATION_DISTANCE = 4000.0; // Unit m
32 static constexpr double MINIMUM_FUZZY_LOCATION_DISTANCE = 3000.0; // Unit m
ReportManager()33 ReportManager::ReportManager()
34 {
35 clock_gettime(CLOCK_REALTIME, &lastUpdateTime_);
36 offsetRandom_ = CommonUtils::DoubleRandom(0, 1);
37 }
38
~ReportManager()39 ReportManager::~ReportManager() {}
40
OnReportLocation(const std::unique_ptr<Location> & location,std::string abilityName)41 bool ReportManager::OnReportLocation(const std::unique_ptr<Location>& location, std::string abilityName)
42 {
43 LBSLOGI(REPORT_MANAGER, "receive location : %{public}s", abilityName.c_str());
44 auto fusionController = DelayedSingleton<FusionController>::GetInstance();
45 if (fusionController == nullptr) {
46 return false;
47 }
48 fusionController->FuseResult(abilityName, location);
49 SetLastLocation(location);
50 LBSLOGI(REPORT_MANAGER, "after SetLastLocation");
51 auto locatorAbility = DelayedSingleton<LocatorAbility>::GetInstance();
52 if (locatorAbility == nullptr) {
53 return false;
54 }
55 auto requestMap = locatorAbility->GetRequests();
56 if (requestMap == nullptr) {
57 return false;
58 }
59 auto requestListIter = requestMap->find(abilityName);
60 if (requestListIter == requestMap->end()) {
61 return false;
62 }
63
64 auto requestList = requestListIter->second;
65 auto deadRequests = std::make_unique<std::list<std::shared_ptr<Request>>>();
66 for (auto iter = requestList.begin(); iter != requestList.end(); iter++) {
67 auto request = *iter;
68 if (!ProcessRequestForReport(request, deadRequests, location)) {
69 continue;
70 }
71 }
72
73 for (auto iter = deadRequests->begin(); iter != deadRequests->end(); ++iter) {
74 auto request = *iter;
75 if (request == nullptr) {
76 continue;
77 }
78 auto requestManger = DelayedSingleton<RequestManager>::GetInstance();
79 if (requestManger != nullptr) {
80 requestManger->UpdateRequestRecord(request, false);
81 }
82 }
83 locatorAbility->ApplyRequests();
84 deadRequests->clear();
85 return true;
86 }
87
ProcessRequestForReport(std::shared_ptr<Request> & request,std::unique_ptr<std::list<std::shared_ptr<Request>>> & deadRequests,const std::unique_ptr<Location> & location)88 bool ReportManager::ProcessRequestForReport(std::shared_ptr<Request>& request,
89 std::unique_ptr<std::list<std::shared_ptr<Request>>>& deadRequests, const std::unique_ptr<Location>& location)
90 {
91 if (request == nullptr || request->GetRequestConfig() == nullptr ||
92 !request->GetIsRequesting()) {
93 return false;
94 }
95 uint32_t tokenId = request->GetTokenId();
96 uint32_t firstTokenId = request->GetFirstTokenId();
97 std::unique_ptr<Location> finalLocation = GetPermittedLocation(tokenId, firstTokenId, location);
98
99 if (!ResultCheck(finalLocation, request)) {
100 return false;
101 }
102 request->SetLastLocation(finalLocation);
103 auto locatorCallback = request->GetLocatorCallBack();
104 if (locatorCallback != nullptr) {
105 locatorCallback->OnLocationReport(finalLocation);
106 }
107
108 int fixTime = request->GetRequestConfig()->GetFixNumber();
109 if (fixTime > 0) {
110 deadRequests->push_back(request);
111 return false;
112 }
113 return true;
114 }
115
GetPermittedLocation(uint32_t tokenId,uint32_t firstTokenId,const std::unique_ptr<Location> & location)116 std::unique_ptr<Location> ReportManager::GetPermittedLocation(uint32_t tokenId, uint32_t firstTokenId,
117 const std::unique_ptr<Location>& location)
118 {
119 if (location == nullptr) {
120 return nullptr;
121 }
122 std::unique_ptr<Location> finalLocation = std::make_unique<Location>(*location);
123 // for api8 and previous version, only ACCESS_LOCATION permission granted also report original location info.
124 if (!CommonUtils::CheckLocationPermission(tokenId, firstTokenId) &&
125 CommonUtils::CheckApproximatelyPermission(tokenId, firstTokenId)) {
126 finalLocation = ApproximatelyLocation(location);
127 } else if (!CommonUtils::CheckLocationPermission(tokenId, firstTokenId) &&
128 !CommonUtils::CheckApproximatelyPermission(tokenId, firstTokenId)) {
129 return nullptr;
130 }
131 return finalLocation;
132 }
133
ReportRemoteCallback(sptr<ILocatorCallback> & locatorCallback,int type,int result)134 bool ReportManager::ReportRemoteCallback(sptr<ILocatorCallback>& locatorCallback, int type, int result)
135 {
136 switch (type) {
137 case ILocatorCallback::RECEIVE_LOCATION_STATUS_EVENT: {
138 locatorCallback->OnLocatingStatusChange(result);
139 break;
140 }
141 case ILocatorCallback::RECEIVE_ERROR_INFO_EVENT: {
142 locatorCallback->OnErrorReport(result);
143 break;
144 }
145 default:
146 return false;
147 }
148 return true;
149 }
150
ResultCheck(const std::unique_ptr<Location> & location,const std::shared_ptr<Request> & request)151 bool ReportManager::ResultCheck(const std::unique_ptr<Location>& location,
152 const std::shared_ptr<Request>& request)
153 {
154 if (request == nullptr) {
155 return false;
156 }
157 if (location == nullptr) {
158 LBSLOGE(REPORT_MANAGER, "%{public}s has no access permission", request->GetPackageName().c_str());
159 return false;
160 }
161 auto locatorAbility = DelayedSingleton<LocatorAbility>::GetInstance();
162 if (locatorAbility == nullptr) {
163 return false;
164 }
165 if (locatorAbility->IsProxyUid(request->GetUid())) {
166 LBSLOGD(REPORT_MANAGER, "uid:%{public}d is proxy by freeze, no need to report", request->GetUid());
167 return false;
168 }
169 int permissionLevel = CommonUtils::GetPermissionLevel(request->GetTokenId(), request->GetFirstTokenId());
170 if (request->GetLastLocation() == nullptr || request->GetRequestConfig() == nullptr) {
171 return true;
172 }
173 float maxAcc = request->GetRequestConfig()->GetMaxAccuracy();
174 LBSLOGD(REPORT_MANAGER, "acc ResultCheck : %{public}f - %{public}f", maxAcc, location->GetAccuracy());
175 if ((permissionLevel == PERMISSION_ACCURATE) &&
176 (maxAcc > 0) && (location->GetAccuracy() > maxAcc)) {
177 LBSLOGE(REPORT_MANAGER, "accuracy check fail, do not report location");
178 return false;
179 }
180 if (CommonUtils::DoubleEqual(request->GetLastLocation()->GetLatitude(), MIN_LATITUDE - 1)) {
181 LBSLOGE(REPORT_MANAGER, "no valid cache location, no need to check");
182 return true;
183 }
184 int minTime = request->GetRequestConfig()->GetTimeInterval();
185 long deltaMs = (location->GetTimeSinceBoot() - request->GetLastLocation()->GetTimeSinceBoot()) / NANOS_PER_MILLI;
186 LBSLOGD(REPORT_MANAGER, "timeInterval ResultCheck : %{public}s %{public}d - %{public}ld",
187 request->GetPackageName().c_str(), minTime, deltaMs);
188 if (deltaMs < (minTime * SECOND_TO_MILLISECOND - MAX_SA_SCHEDULING_JITTER_MS)) {
189 LBSLOGE(REPORT_MANAGER, "timeInterval check fail, do not report location");
190 return false;
191 }
192
193 int distanceInterval = request->GetRequestConfig()->GetDistanceInterval();
194 double deltaDis = CommonUtils::CalDistance(location->GetLatitude(), location->GetLongitude(),
195 request->GetLastLocation()->GetLatitude(), request->GetLastLocation()->GetLongitude());
196 LBSLOGD(REPORT_MANAGER, "distanceInterval ResultCheck : %{public}lf - %{public}d", deltaDis, distanceInterval);
197 if (deltaDis - distanceInterval < 0) {
198 LBSLOGE(REPORT_MANAGER, "distanceInterval check fail, do not report location");
199 return false;
200 }
201 return true;
202 }
203
SetLastLocation(const std::unique_ptr<Location> & location)204 void ReportManager::SetLastLocation(const std::unique_ptr<Location>& location)
205 {
206 lastLocation_.SetLatitude(location->GetLatitude());
207 lastLocation_.SetLongitude(location->GetLongitude());
208 lastLocation_.SetAltitude(location->GetAltitude());
209 lastLocation_.SetAccuracy(location->GetAccuracy());
210 lastLocation_.SetSpeed(location->GetSpeed());
211 lastLocation_.SetDirection(location->GetDirection());
212 lastLocation_.SetTimeStamp(location->GetTimeStamp());
213 lastLocation_.SetTimeSinceBoot(location->GetTimeSinceBoot());
214 }
215
GetLastLocation()216 std::unique_ptr<Location> ReportManager::GetLastLocation()
217 {
218 auto lastLocation = std::make_unique<Location>(lastLocation_);
219 if (CommonUtils::DoubleEqual(lastLocation->GetLatitude(), MIN_LATITUDE - 1)) {
220 LBSLOGE(REPORT_MANAGER, "no valid cache location");
221 return nullptr;
222 }
223 return lastLocation;
224 }
225
UpdateRandom()226 void ReportManager::UpdateRandom()
227 {
228 auto locatorAbility = DelayedSingleton<LocatorAbility>::GetInstance();
229 if (locatorAbility == nullptr) {
230 return;
231 }
232 int num = locatorAbility->GetActiveRequestNum();
233 if (num > 0) {
234 LBSLOGE(REPORT_MANAGER, "Exists %{public}d active request, cannot refresh offset", num);
235 return;
236 }
237 struct timespec now;
238 clock_gettime(CLOCK_REALTIME, &now);
239 if (abs(now.tv_sec - lastUpdateTime_.tv_sec) > LONG_TIME_INTERVAL) {
240 offsetRandom_ = CommonUtils::DoubleRandom(0, 1);
241 }
242 }
243
ApproximatelyLocation(const std::unique_ptr<Location> & location)244 std::unique_ptr<Location> ReportManager::ApproximatelyLocation(const std::unique_ptr<Location>& location)
245 {
246 std::unique_ptr<Location> coarseLocation = std::make_unique<Location>(*location);
247 double startLat = coarseLocation->GetLatitude();
248 double startLon = coarseLocation->GetLongitude();
249 double brg = offsetRandom_ * DIS_FROMLL_PARAMETER * M_PI; // 2PI
250 double dist = offsetRandom_ * (MAXIMUM_FUZZY_LOCATION_DISTANCE -
251 MINIMUM_FUZZY_LOCATION_DISTANCE) + MINIMUM_FUZZY_LOCATION_DISTANCE;
252 double perlat = (DIS_FROMLL_PARAMETER * M_PI * EARTH_RADIUS) / DEGREE_DOUBLE_PI; // the radian value of per degree
253
254 double lat = startLat + (dist * sin(brg)) / perlat;
255 double lon;
256 if (cos(brg) < 0) {
257 lon = startLon - (dist * DEGREE_DOUBLE_PI) / (DIS_FROMLL_PARAMETER * M_PI * EARTH_RADIUS);
258 } else {
259 lon = startLon + (dist * DEGREE_DOUBLE_PI) / (DIS_FROMLL_PARAMETER * M_PI * EARTH_RADIUS);
260 }
261 if (lat < -MAX_LATITUDE) {
262 lat = -MAX_LATITUDE;
263 } else if (lat > MAX_LATITUDE) {
264 lat = MAX_LATITUDE;
265 } else {
266 lat = std::round(lat * std::pow(10, 8)) / std::pow(10, 8); // 8 decimal
267 }
268 if (lon < -MAX_LONGITUDE) {
269 lon = -MAX_LONGITUDE;
270 } else if (lon > MAX_LONGITUDE) {
271 lon = MAX_LONGITUDE;
272 } else {
273 lon = std::round(lon * std::pow(10, 8)) / std::pow(10, 8); // 8 decimal
274 }
275 coarseLocation->SetLatitude(lat);
276 coarseLocation->SetLongitude(lon);
277 coarseLocation->SetAccuracy(DEFAULT_APPROXIMATELY_ACCURACY); // approximately location acc
278 return coarseLocation;
279 }
280 } // namespace OHOS
281 } // namespace Location
282