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