1 /*
2 * Copyright (c) 2022-2023 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 "net_stats_cached.h"
17
18 #include <initializer_list>
19 #include <list>
20 #include <pthread.h>
21
22 #include "net_conn_client.h"
23 #include "net_mgr_log_wrapper.h"
24 #include "net_stats_constants.h"
25 #include "net_stats_data_handler.h"
26 #include "net_stats_database_defines.h"
27 #include "net_stats_database_helper.h"
28 #include "netsys_controller.h"
29 #include "bpf_stats.h"
30 #include "ffrt_inner.h"
31
32 namespace OHOS {
33 namespace NetManagerStandard {
34 using namespace NetStatsDatabaseDefines;
35 namespace {
36 constexpr const char *IFACE_LO = "lo";
37 } // namespace
38
StartCached()39 int32_t NetStatsCached::StartCached()
40 {
41 auto helper = std::make_unique<NetStatsDatabaseHelper>(NET_STATS_DATABASE_PATH);
42 auto ret = helper->CreateTable(VERSION_TABLE, VERSION_TABLE_CREATE_PARAM);
43 if (ret != NETMANAGER_SUCCESS) {
44 NETMGR_LOG_E("Create version table failed");
45 return STATS_ERR_CREATE_TABLE_FAIL;
46 }
47 ret = helper->CreateTable(UID_TABLE, UID_TABLE_CREATE_PARAM);
48 if (ret != NETMANAGER_SUCCESS) {
49 NETMGR_LOG_E("Create uid table failed");
50 return STATS_ERR_CREATE_TABLE_FAIL;
51 }
52 ret = helper->CreateTable(IFACE_TABLE, IFACE_TABLE_CREATE_PARAM);
53 if (ret != 0) {
54 NETMGR_LOG_E("Create iface table failed");
55 return STATS_ERR_CREATE_TABLE_FAIL;
56 }
57 ret = helper->CreateTable(UID_SIM_TABLE, UID_SIM_TABLE_CREATE_PARAM);
58 if (ret != 0) {
59 NETMGR_LOG_E("Create uid_sim table failed");
60 return STATS_ERR_CREATE_TABLE_FAIL;
61 }
62 helper->Upgrade();
63 cacheTimer_ = std::make_unique<FfrtTimer>();
64 writeTimer_ = std::make_unique<FfrtTimer>();
65 cacheTimer_->Start(cycleThreshold_, [this]() { CacheStats(); });
66 writeTimer_->Start(STATS_PACKET_CYCLE_MS, [this]() { WriteStats(); });
67 return ret;
68 }
69
GetUidStatsCached(std::vector<NetStatsInfo> & uidStatsInfo)70 void NetStatsCached::GetUidStatsCached(std::vector<NetStatsInfo> &uidStatsInfo)
71 {
72 std::lock_guard<ffrt::mutex> lock(lock_);
73 uidStatsInfo.insert(uidStatsInfo.end(), stats_.GetUidStatsInfo().begin(), stats_.GetUidStatsInfo().end());
74 }
75
GetUidSimStatsCached(std::vector<NetStatsInfo> & uidSimStatsInfo)76 void NetStatsCached::GetUidSimStatsCached(std::vector<NetStatsInfo> &uidSimStatsInfo)
77 {
78 std::lock_guard<ffrt::mutex> lock(lock_);
79 std::transform(stats_.GetUidSimStatsInfo().begin(), stats_.GetUidSimStatsInfo().end(),
80 std::back_inserter(uidSimStatsInfo), [](NetStatsInfo &info) {
81 NetStatsInfo tmpInfo = info;
82 tmpInfo.uid_ = Sim_UID;
83 return tmpInfo;
84 });
85 }
86
GetUidPushStatsCached(std::vector<NetStatsInfo> & uidPushStatsInfo)87 void NetStatsCached::GetUidPushStatsCached(std::vector<NetStatsInfo> &uidPushStatsInfo)
88 {
89 std::lock_guard<ffrt::mutex> lock(lock_);
90 uidPushStatsInfo.insert(uidPushStatsInfo.end(), uidPushStatsInfo_.begin(), uidPushStatsInfo_.end());
91 }
92
GetAllPushStatsCached(std::vector<NetStatsInfo> & uidPushStatsInfo)93 void NetStatsCached::GetAllPushStatsCached(std::vector<NetStatsInfo> &uidPushStatsInfo)
94 {
95 std::lock_guard<ffrt::mutex> lock(lock_);
96 uidPushStatsInfo.insert(uidPushStatsInfo.end(), allPushStatsInfo_.begin(), allPushStatsInfo_.end());
97 }
98
GetIfaceStatsCached(std::vector<NetStatsInfo> & ifaceStatsInfo)99 void NetStatsCached::GetIfaceStatsCached(std::vector<NetStatsInfo> &ifaceStatsInfo)
100 {
101 std::lock_guard<ffrt::mutex> lock(lock_);
102 ifaceStatsInfo.insert(ifaceStatsInfo.end(), stats_.GetIfaceStatsInfo().begin(), stats_.GetIfaceStatsInfo().end());
103 }
104
SetAppStats(const PushStatsInfo & info)105 void NetStatsCached::SetAppStats(const PushStatsInfo &info)
106 {
107 std::lock_guard<ffrt::mutex> lock(lock_);
108 NetStatsInfo stats;
109 stats.uid_ = info.uid_;
110 stats.iface_ = info.iface_;
111 stats.date_ = info.endTime_;
112 stats.rxBytes_ = info.rxBytes_;
113 stats.txBytes_ = info.txBytes_;
114 stats.rxPackets_ = info.rxBytes_ > 0 ? 1 : 0;
115 stats.txPackets_ = info.txBytes_ > 0 ? 1 : 0;
116 if (info.netBearType_ == BEARER_CELLULAR) {
117 stats.ident_ = std::to_string(info.simId_);
118 }
119 NETMGR_LOG_D("SetAppStats info=%{public}s", stats.UidData().c_str());
120 uidPushStatsInfo_.push_back(std::move(stats));
121 }
122
GetKernelStats(std::vector<NetStatsInfo> & statsInfo)123 void NetStatsCached::GetKernelStats(std::vector<NetStatsInfo> &statsInfo)
124 {
125 std::lock_guard<ffrt::mutex> lock(lock_);
126 std::vector<NetStatsInfo> allInfos;
127 NetsysController::GetInstance().GetAllStatsInfo(allInfos);
128 ifaceNameIdentMap_.Iterate([&allInfos](const std::string &k, const std::string &v) {
129 std::for_each(allInfos.begin(), allInfos.end(), [&k, &v](NetStatsInfo &item) {
130 if (item.iface_ == k) {
131 item.ident_ = v;
132 }
133 });
134 });
135 std::for_each(allInfos.begin(), allInfos.end(), [this, &statsInfo](NetStatsInfo &info) {
136 if (info.iface_ == IFACE_LO) {
137 return;
138 }
139 NetStatsInfo tmp = GetIncreasedStats(info);
140 if (tmp.HasNoData()) {
141 return;
142 }
143 tmp.date_ = CommonUtils::GetCurrentSecond();
144 statsInfo.push_back(std::move(tmp));
145 });
146 std::vector<NetStatsInfo> SimInfos;
147 NetsysController::GetInstance().GetAllSimStatsInfo(SimInfos);
148 ifaceNameIdentMap_.Iterate([&SimInfos](const std::string &k, const std::string &v) {
149 std::for_each(SimInfos.begin(), SimInfos.end(), [&k, &v](NetStatsInfo &item) {
150 if (item.iface_ == k) {
151 item.ident_ = v;
152 }
153 });
154 });
155 std::for_each(SimInfos.begin(), SimInfos.end(), [this, &statsInfo](NetStatsInfo &info) {
156 if (info.iface_ == IFACE_LO) {
157 return;
158 }
159 NetStatsInfo tmp = GetIncreasedSimStats(info);
160 if (tmp.HasNoData()) {
161 return;
162 }
163 tmp.date_ = CommonUtils::GetCurrentSecond();
164 tmp.uid_ = Sim_UID;
165 statsInfo.push_back(std::move(tmp));
166 });
167 }
168
GetIncreasedStats(const NetStatsInfo & info)169 NetStatsInfo NetStatsCached::GetIncreasedStats(const NetStatsInfo &info)
170 {
171 auto findRet = std::find_if(lastUidStatsInfo_.begin(), lastUidStatsInfo_.end(),
172 [&info](const NetStatsInfo &lastInfo) { return info.Equals(lastInfo); });
173 if (findRet == lastUidStatsInfo_.end()) {
174 return info;
175 }
176 return info - *findRet;
177 }
178
GetIncreasedSimStats(const NetStatsInfo & info)179 NetStatsInfo NetStatsCached::GetIncreasedSimStats(const NetStatsInfo &info)
180 {
181 auto findRet = std::find_if(lastUidSimStatsInfo_.begin(), lastUidSimStatsInfo_.end(),
182 [&info](const NetStatsInfo &lastInfo) { return info.Equals(lastInfo); });
183 if (findRet == lastUidSimStatsInfo_.end()) {
184 return info;
185 }
186 return info - *findRet;
187 }
188
CacheUidStats()189 void NetStatsCached::CacheUidStats()
190 {
191 std::vector<NetStatsInfo> statsInfos;
192 NetsysController::GetInstance().GetAllStatsInfo(statsInfos);
193 if (statsInfos.empty()) {
194 NETMGR_LOG_W("No stats need to save");
195 return;
196 }
197
198 ifaceNameIdentMap_.Iterate([&statsInfos](const std::string &k, const std::string &v) {
199 std::for_each(statsInfos.begin(), statsInfos.end(), [&k, &v](NetStatsInfo &item) {
200 if (item.iface_ == k) {
201 item.ident_ = v;
202 }
203 });
204 });
205
206 std::for_each(statsInfos.begin(), statsInfos.end(), [this](NetStatsInfo &info) {
207 if (info.iface_ == IFACE_LO) {
208 return;
209 }
210 auto findRet = std::find_if(lastUidStatsInfo_.begin(), lastUidStatsInfo_.end(),
211 [this, &info](const NetStatsInfo &lastInfo) { return info.Equals(lastInfo); });
212 if (findRet == lastUidStatsInfo_.end()) {
213 stats_.PushUidStats(info);
214 return;
215 }
216 auto currentStats = info - *findRet;
217 stats_.PushUidStats(currentStats);
218 });
219 lastUidStatsInfo_.swap(statsInfos);
220 }
221
CacheAppStats()222 void NetStatsCached::CacheAppStats()
223 {
224 std::vector<NetStatsInfo> pushInfos;
225 std::for_each(uidPushStatsInfo_.begin(), uidPushStatsInfo_.end(), [&pushInfos](NetStatsInfo &info) {
226 auto findRet = std::find_if(pushInfos.begin(), pushInfos.end(),
227 [&info](const NetStatsInfo &item) { return info.Equals(item); });
228 if (findRet == pushInfos.end()) {
229 pushInfos.push_back(info);
230 return;
231 }
232 *findRet += info;
233 });
234 std::for_each(pushInfos.begin(), pushInfos.end(), [this](auto &item) {
235 stats_.PushUidStats(item);
236 auto findRet = std::find_if(allPushStatsInfo_.begin(), allPushStatsInfo_.end(),
237 [&item](const NetStatsInfo &info) {
238 return info.Equals(item) && info.ident_ == item.ident_;
239 });
240 if (findRet == allPushStatsInfo_.end()) {
241 allPushStatsInfo_.push_back(item);
242 return;
243 }
244 *findRet += item;
245 });
246 uidPushStatsInfo_.clear();
247 }
248
CacheUidSimStats()249 void NetStatsCached::CacheUidSimStats()
250 {
251 std::vector<NetStatsInfo> statsInfos;
252 NetsysController::GetInstance().GetAllSimStatsInfo(statsInfos);
253 if (statsInfos.empty()) {
254 NETMGR_LOG_W("No stats need to save");
255 return;
256 }
257
258 ifaceNameIdentMap_.Iterate([&statsInfos](const std::string &k, const std::string &v) {
259 std::for_each(statsInfos.begin(), statsInfos.end(), [&k, &v](NetStatsInfo &item) {
260 if (item.iface_ == k) {
261 item.ident_ = v;
262 }
263 });
264 });
265
266 std::for_each(statsInfos.begin(), statsInfos.end(), [this](NetStatsInfo &info) {
267 if (info.iface_ == IFACE_LO) {
268 return;
269 }
270 auto findRet = std::find_if(lastUidSimStatsInfo_.begin(), lastUidSimStatsInfo_.end(),
271 [this, &info](const NetStatsInfo &lastInfo) { return info.Equals(lastInfo); });
272 if (findRet == lastUidSimStatsInfo_.end()) {
273 stats_.PushUidSimStats(info);
274 return;
275 }
276 auto currentStats = info - *findRet;
277 stats_.PushUidSimStats(currentStats);
278 });
279 lastUidSimStatsInfo_.swap(statsInfos);
280 }
281
CacheIfaceStats()282 void NetStatsCached::CacheIfaceStats()
283 {
284 std::vector<std::string> ifNameList = NetsysController::GetInstance().InterfaceGetList();
285 std::for_each(ifNameList.begin(), ifNameList.end(), [this](const auto &ifName) {
286 if (ifName == IFACE_LO) {
287 return;
288 }
289 NetStatsInfo statsInfo;
290 statsInfo.iface_ = ifName;
291 NetsysController::GetInstance().GetIfaceStats(statsInfo.rxBytes_,
292 static_cast<uint32_t>(StatsType::STATS_TYPE_RX_BYTES), ifName);
293 NetsysController::GetInstance().GetIfaceStats(statsInfo.rxPackets_,
294 static_cast<uint32_t>(StatsType::STATS_TYPE_RX_PACKETS), ifName);
295 NetsysController::GetInstance().GetIfaceStats(statsInfo.txBytes_,
296 static_cast<uint32_t>(StatsType::STATS_TYPE_TX_BYTES), ifName);
297 NetsysController::GetInstance().GetIfaceStats(statsInfo.txPackets_,
298 static_cast<uint32_t>(StatsType::STATS_TYPE_TX_PACKETS), ifName);
299 auto findRet = lastIfaceStatsMap_.find(ifName);
300 if (findRet == lastIfaceStatsMap_.end()) {
301 stats_.PushIfaceStats(statsInfo);
302 lastIfaceStatsMap_[ifName] = statsInfo;
303 return;
304 }
305 auto currentStats = statsInfo - findRet->second;
306 stats_.PushIfaceStats(currentStats);
307 lastIfaceStatsMap_[ifName] = statsInfo;
308 });
309 }
310
CacheStats()311 void NetStatsCached::CacheStats()
312 {
313 std::lock_guard<ffrt::mutex> lock(lock_);
314 CacheUidStats();
315 CacheAppStats();
316 CacheUidSimStats();
317 CacheIfaceStats();
318 }
319
WriteStats()320 void NetStatsCached::WriteStats()
321 {
322 std::lock_guard<ffrt::mutex> lock(lock_);
323 WriteUidStats();
324 WriteUidSimStats();
325 WriteIfaceStats();
326 }
WriteIfaceStats()327 void NetStatsCached::WriteIfaceStats()
328 {
329 if (!(CheckIfaceStor() || isForce_)) {
330 return;
331 }
332 auto handler = std::make_unique<NetStatsDataHandler>();
333 handler->WriteStatsData(stats_.GetIfaceStatsInfo(), NetStatsDatabaseDefines::IFACE_TABLE);
334 handler->DeleteByDate(NetStatsDatabaseDefines::IFACE_TABLE, 0, CommonUtils::GetCurrentSecond() - dateCycle_);
335 stats_.ResetIfaceStats();
336 }
337
WriteUidStats()338 void NetStatsCached::WriteUidStats()
339 {
340 if (!(CheckUidStor() || isForce_)) {
341 return;
342 }
343 std::for_each(stats_.GetUidStatsInfo().begin(), stats_.GetUidStatsInfo().end(), [this](NetStatsInfo &info) {
344 if (info.uid_ == uninstalledUid_) {
345 info.flag_ = STATS_DATA_FLAG_UNINSTALLED;
346 }
347 });
348 auto handler = std::make_unique<NetStatsDataHandler>();
349 handler->WriteStatsData(stats_.GetUidStatsInfo(), NetStatsDatabaseDefines::UID_TABLE);
350 handler->DeleteByDate(NetStatsDatabaseDefines::UID_TABLE, 0, CommonUtils::GetCurrentSecond() - dateCycle_);
351 stats_.ResetUidStats();
352 }
353
WriteUidSimStats()354 void NetStatsCached::WriteUidSimStats()
355 {
356 if (!(CheckUidSimStor() || isForce_)) {
357 return;
358 }
359 std::for_each(stats_.GetUidSimStatsInfo().begin(), stats_.GetUidSimStatsInfo().end(), [this](NetStatsInfo &info) {
360 if (info.uid_ == uninstalledUid_) {
361 info.flag_ = STATS_DATA_FLAG_UNINSTALLED;
362 }
363 });
364 auto handler = std::make_unique<NetStatsDataHandler>();
365 handler->WriteStatsData(stats_.GetUidSimStatsInfo(), NetStatsDatabaseDefines::UID_SIM_TABLE);
366 handler->DeleteByDate(NetStatsDatabaseDefines::UID_SIM_TABLE, 0, CommonUtils::GetCurrentSecond() - dateCycle_);
367 handler->DeleteSimStatsByUid(Sim_UID);
368 stats_.ResetUidSimStats();
369 }
370
LoadIfaceNameIdentMaps()371 void NetStatsCached::LoadIfaceNameIdentMaps()
372 {
373 int32_t ret = NetConnClient::GetInstance().GetIfaceNameIdentMaps(NetBearType::BEARER_CELLULAR, ifaceNameIdentMap_);
374 if (ret != NETMANAGER_SUCCESS) {
375 NETMGR_LOG_E("GetIfaceNameIdentMaps error. ret=%{public}d", ret);
376 }
377 }
378
SetCycleThreshold(uint32_t threshold)379 void NetStatsCached::SetCycleThreshold(uint32_t threshold)
380 {
381 NETMGR_LOG_D("Current cycle threshold has changed current is : %{public}d", threshold);
382 cycleThreshold_ = threshold;
383 cacheTimer_ = std::make_unique<FfrtTimer>();
384 cacheTimer_->Start(cycleThreshold_, [this]() { CacheStats(); });
385 }
386
ForceUpdateStats()387 void NetStatsCached::ForceUpdateStats()
388 {
389 isForce_ = true;
390 std::function<void()> netCachedStats = [this] () {
391 CacheStats();
392 WriteStats();
393 isForce_ = false;
394 LoadIfaceNameIdentMaps();
395 };
396 ffrt::submit(std::move(netCachedStats), {}, {}, ffrt::task_attr().name("NetCachedStats"));
397 }
398
ForceDeleteStats(uint32_t uid)399 void NetStatsCached::ForceDeleteStats(uint32_t uid)
400 {
401 NETMGR_LOG_I("ForceDeleteStats Enter uid[%{public}u]", uid);
402 auto ret = NetsysController::GetInstance().DeleteStatsInfo(uid);
403 if (ret != NETMANAGER_SUCCESS) {
404 NETMGR_LOG_E("ForceDeleteStats DeleteStatsInfo failed. ret is %{public}d", ret);
405 }
406 ret = NetsysController::GetInstance().DeleteSimStatsInfo(uid);
407 if (ret != NETMANAGER_SUCCESS) {
408 NETMGR_LOG_E("ForceDeleteStats DeleteSimStatsInfo failed. ret is %{public}d", ret);
409 }
410
411 std::lock_guard<ffrt::mutex> lock(lock_);
412 stats_.ResetUidStats(uid);
413 stats_.ResetUidSimStats(uid);
414 lastUidStatsInfo_.erase(std::remove_if(lastUidStatsInfo_.begin(), lastUidStatsInfo_.end(),
415 [uid](const auto &item) { return item.uid_ == uid; }),
416 lastUidStatsInfo_.end());
417 lastUidSimStatsInfo_.erase(std::remove_if(lastUidSimStatsInfo_.begin(), lastUidSimStatsInfo_.end(),
418 [uid](const auto &item) { return item.uid_ == uid; }),
419 lastUidSimStatsInfo_.end());
420 uidPushStatsInfo_.erase(std::remove_if(uidPushStatsInfo_.begin(), uidPushStatsInfo_.end(),
421 [uid](const auto &item) { return item.uid_ == uid; }),
422 uidPushStatsInfo_.end());
423 }
424
ForceArchiveStats(uint32_t uid)425 void NetStatsCached::ForceArchiveStats(uint32_t uid)
426 {
427 std::function<void()> netCachedStats = [this, uid]() {
428 CacheStats();
429 {
430 std::lock_guard<ffrt::mutex> lock(lock_);
431 isForce_ = true;
432 uninstalledUid_ = uid;
433 WriteUidStats();
434 WriteUidSimStats();
435 uninstalledUid_ = -1;
436 isForce_ = false;
437 }
438 ForceDeleteStats(uid);
439 };
440 ffrt::submit(std::move(netCachedStats), {}, {}, ffrt::task_attr().name("NetForceArchiveStats"));
441 }
442
Reset()443 void NetStatsCached::Reset() {}
444
445 } // namespace NetManagerStandard
446 } // namespace OHOS
447