• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 "poi_info_manager.h"
17 
18 #include "location_log.h"
19 #include "common_utils.h"
20 #ifdef MOVEMENT_CLIENT_ENABLE
21 #include "locator_msdp_monitor_manager.h"
22 #endif
23 
24 namespace OHOS {
25 namespace Location {
26 
27 static constexpr int STILL_POI_EXPIRED_TIME = 30 * 60 * 1000; // Unit ms
28 static constexpr int POI_EXPIRED_TIME = 25 * 1000; // Unit ms
29 static constexpr int MAX_UTC_TIME_SIZE = 16;
30 static constexpr int MAX_POI_ARRAY_SIZE = 20;
31 
GetInstance()32 PoiInfoManager* PoiInfoManager::GetInstance()
33 {
34     static PoiInfoManager data;
35     return &data;
36 }
37 
PoiInfoManager()38 PoiInfoManager::PoiInfoManager() {}
39 
~PoiInfoManager()40 PoiInfoManager::~PoiInfoManager() {}
41 
UpdateCachedPoiInfo(const std::unique_ptr<Location> & location)42 void PoiInfoManager::UpdateCachedPoiInfo(const std::unique_ptr<Location>& location)
43 {
44     std::map<std::string, std::string> additionMap = location->GetAdditionsMap();
45     if (additionMap["poiInfos"] != "") {
46         std::string poiInfos = std::string("poiInfos:") + additionMap["poiInfos"];
47         uint64_t poiInfoTime = GetPoiInfoTime(poiInfos);
48         SetLatestPoiInfo(poiInfos);
49         SetLatestPoiInfoTime(poiInfoTime);
50     }
51 }
52 
ClearPoiInfos(const std::unique_ptr<Location> & finalLocation)53 void PoiInfoManager::ClearPoiInfos(const std::unique_ptr<Location>& finalLocation)
54 {
55     std::vector<std::string> additions;
56     for (auto& str : finalLocation->GetAdditions()) {
57         if (str.find("poiInfos") != std::string::npos) {
58             continue;
59         }
60         additions.push_back(str);
61     }
62     finalLocation->SetAdditions(additions, false);
63     finalLocation->SetAdditionSize(finalLocation->GetAdditions().size());
64     return;
65 }
66 
UpdateLocationPoiInfo(const std::unique_ptr<Location> & finalLocation)67 void PoiInfoManager::UpdateLocationPoiInfo(const std::unique_ptr<Location>& finalLocation)
68 {
69     std::map<std::string, std::string> additionMap = finalLocation->GetAdditionsMap();
70     std::string poiInfos = additionMap["poiInfos"];
71     uint64_t poiInfoTime = GetPoiInfoTime(poiInfos);
72     if (poiInfos != "") {
73         if (IsPoiInfoValid(poiInfos, poiInfoTime)) {
74             PoiInfo poiInfo = ParsePoiInfoFromStr(poiInfos);
75             finalLocation->SetPoiInfo(poiInfo);
76             return;
77         } else {
78             LBSLOGI(REPORT_MANAGER, "PoiInfos Expied");
79             ClearPoiInfos(finalLocation);
80         }
81     }
82     std::string latestPoiInfos = GetLatestPoiInfo();
83     uint64_t latestPoiInfoTime = GetLatestPoiInfoTime();
84     if (!IsPoiInfoValid(latestPoiInfos, latestPoiInfoTime)) {
85         std::unique_lock<std::mutex> lock(latestPoiInfoMutex_);
86         latestPoiInfoStruct_ = {0};
87         return;
88     }
89     AddCachedPoiInfoToLocation(finalLocation);
90 }
91 
AddCachedPoiInfoToLocation(const std::unique_ptr<Location> & finalLocation)92 void PoiInfoManager::AddCachedPoiInfoToLocation(const std::unique_ptr<Location>& finalLocation)
93 {
94     LBSLOGI(REPORT_MANAGER, "Add Latest PoiInfos");
95     std::string poiInfos = GetLatestPoiInfo();
96     std::vector<std::string> addition = finalLocation->GetAdditions();
97     addition.push_back(poiInfos);
98     finalLocation->SetAdditions(addition, false);
99     finalLocation->SetAdditionSize(finalLocation->GetAdditions().size());
100     std::string poiKey = "poiInfos:";
101     std::size_t pos = poiInfos.find(poiKey);
102     if (pos != std::string::npos) {
103         std::string result = poiInfos.substr(pos + poiKey.size());
104         PoiInfo poiInfo = ParsePoiInfoFromStr(result);
105         finalLocation->SetPoiInfo(poiInfo);
106     } else {
107         LBSLOGE(REPORT_MANAGER, "Not Found poiInfos");
108     }
109 }
110 
IsPoiInfoValid(std::string poiInfos,uint64_t poiInfoTime)111 bool PoiInfoManager::IsPoiInfoValid(std::string poiInfos, uint64_t poiInfoTime)
112 {
113     uint64_t curTimeStamp = CommonUtils::GetCurrentTimeMilSec();
114     uint64_t enterStillTime = 0;
115     bool isInStillState = false;
116 #ifdef MOVEMENT_CLIENT_ENABLE
117     isInStillState = LocatorMsdpMonitorManager::GetInstance()->GetStillMovementState();
118     enterStillTime = LocatorMsdpMonitorManager::GetInstance()->GetEnterStillTime();
119 #endif
120     if (isInStillState && poiInfoTime > enterStillTime && curTimeStamp - poiInfoTime < STILL_POI_EXPIRED_TIME) {
121         return true;
122     }
123     if (curTimeStamp - poiInfoTime < POI_EXPIRED_TIME) {
124         return true;
125     }
126     return false;
127 }
128 
GetLatestPoiInfo()129 std::string PoiInfoManager::GetLatestPoiInfo()
130 {
131     std::unique_lock<std::mutex> lock(latestPoiInfoMutex_);
132     return latestPoiInfoStruct_.latestPoiInfos;
133 }
134 
SetLatestPoiInfo(std::string poiInfo)135 void PoiInfoManager::SetLatestPoiInfo(std::string poiInfo)
136 {
137     std::unique_lock<std::mutex> lock(latestPoiInfoMutex_);
138     latestPoiInfoStruct_.latestPoiInfos = poiInfo;
139 }
140 
GetLatestPoiInfoTime()141 uint64_t PoiInfoManager::GetLatestPoiInfoTime()
142 {
143     std::unique_lock<std::mutex> lock(latestPoiInfoMutex_);
144     return latestPoiInfoStruct_.poiInfosTime;
145 }
146 
SetLatestPoiInfoTime(uint64_t poiInfoTime)147 void PoiInfoManager::SetLatestPoiInfoTime(uint64_t poiInfoTime)
148 {
149     std::unique_lock<std::mutex> lock(latestPoiInfoMutex_);
150     latestPoiInfoStruct_.poiInfosTime = poiInfoTime;
151 }
152 
GetPoiInfoTime(const std::string & poiInfos)153 uint64_t PoiInfoManager::GetPoiInfoTime(const std::string& poiInfos)
154 {
155     std::string key = "\"time\":";
156     size_t pos = poiInfos.find(key);
157     if (pos != std::string::npos) {
158         pos += key.length();
159         std::string number;
160         for (; pos < poiInfos.length() && isdigit(poiInfos[pos]); ++pos) {
161             number += poiInfos[pos];
162         }
163         if (CommonUtils::IsValidForStoull(number, MAX_UTC_TIME_SIZE)) {
164             return std::stoull(number);
165         }
166     }
167     return 0;
168 }
169 
ParsePoiInfo(cJSON * poiJson)170 Poi PoiInfoManager::ParsePoiInfo(cJSON* poiJson)
171 {
172     Poi poi;
173     cJSON *item = cJSON_GetObjectItem(poiJson, "id");
174     poi.id = (item && cJSON_IsString(item)) ? item->valuestring : "";
175     item = cJSON_GetObjectItem(poiJson, "confidence");
176     poi.confidence = (item && cJSON_IsNumber(item)) ? item->valuedouble : 0.0;
177     item = cJSON_GetObjectItem(poiJson, "name");
178     poi.name = (item && cJSON_IsString(item)) ? item->valuestring : "";
179     item = cJSON_GetObjectItem(poiJson, "lat");
180     poi.latitude = (item && cJSON_IsNumber(item)) ? item->valuedouble : 0.0;
181     item = cJSON_GetObjectItem(poiJson, "lon");
182     poi.longitude = (item && cJSON_IsNumber(item)) ? item->valuedouble : 0.0;
183     item = cJSON_GetObjectItem(poiJson, "administrativeArea");
184     poi.administrativeArea = (item && cJSON_IsString(item)) ? item->valuestring : "";
185     item = cJSON_GetObjectItem(poiJson, "subAdministrativeArea");
186     poi.subAdministrativeArea = (item && cJSON_IsString(item)) ? item->valuestring : "";
187     item = cJSON_GetObjectItem(poiJson, "locality");
188     poi.locality = (item && cJSON_IsString(item)) ? item->valuestring : "";
189     item = cJSON_GetObjectItem(poiJson, "subLocality");
190     poi.subLocality = (item && cJSON_IsString(item)) ? item->valuestring : "";
191     item = cJSON_GetObjectItem(poiJson, "address");
192     poi.address = (item && cJSON_IsString(item)) ? item->valuestring : "";
193     return poi;
194 }
195 
ParsePoiInfoFromStr(const std::string & jsonString)196 PoiInfo PoiInfoManager::ParsePoiInfoFromStr(const std::string& jsonString)
197 {
198     PoiInfo poiInfo;
199     cJSON* cJsonObj = cJSON_Parse(jsonString.c_str());
200     if (!cJsonObj) {
201         LBSLOGI(REPORT_MANAGER, "Poi cJson Parse Failed");
202         return poiInfo;
203     }
204     cJSON* item = cJSON_GetObjectItem(cJsonObj, "time");
205     poiInfo.timestamp = (item && cJSON_IsNumber(item)) ? static_cast<uint64_t>(item->valuedouble) : 0;
206     cJSON* poisArray = cJSON_GetObjectItem(cJsonObj, "pois");
207     if (poisArray && cJSON_IsArray(poisArray)) {
208         int arraySize = cJSON_GetArraySize(poisArray);
209         if (arraySize > MAX_POI_ARRAY_SIZE) {
210             arraySize = MAX_POI_ARRAY_SIZE;
211         }
212         for (int i = 0; i < arraySize; ++i) {
213             cJSON* poiJson = cJSON_GetArrayItem(poisArray, i);
214             if (poiJson) {
215                 poiInfo.poiArray.push_back(ParsePoiInfo(poiJson));
216             }
217         }
218     }
219     cJSON_Delete(cJsonObj);
220     return poiInfo;
221 }
222 
223 } // namespace OHOS
224 } // namespace Location