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