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