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