1 /*
2 * Copyright (C) 2024-2024 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 "wifi_net_stats_manager.h"
17 #include "wifi_common_util.h"
18 #include <algorithm>
19 #include "net_stats_client.h"
20 #include "wifi_system_timer.h"
21 #include "wifi_logger.h"
22
23 namespace OHOS {
24 namespace Wifi {
25 DEFINE_WIFILOG_LABEL("WifiNetStats");
26
27 const char* WLAN_0 = "wlan0";
28 const char* UNKNOWN_PACKAGE_NAME = "unknown_package";
29 const char* SEP_STR = "/";
30 const char* END_STR = ",";
31 const int32_t UID_ALL = -1;
32 const int32_t MAX_LOG_TRAFFIC = 10;
33 const int64_t NET_STATS_POLL_INTERVAL = 10 * 1000;
34 const int64_t NET_STATS_DELAY_TIME = 2 * 1000;
35
StartNetStats()36 void WifiNetStatsManager::StartNetStats()
37 {
38 WIFI_LOGI("%{public}s, enter", __FUNCTION__);
39 if (m_netStatsTimerId != 0) {
40 WIFI_LOGI("%{public}s, m_netStatsTimerId is not zero", __FUNCTION__);
41 return;
42 }
43 std::shared_ptr<WifiSysTimer> netStatsTimer =
44 std::make_shared<WifiSysTimer>(true, NET_STATS_POLL_INTERVAL, true, false);
45 std::function<void()> callback = std::bind(&WifiNetStatsManager::PerformPollAndLog, this);
46 netStatsTimer->SetCallbackInfo(callback);
47 m_netStatsTimerId = MiscServices::TimeServiceClient::GetInstance()->CreateTimer(netStatsTimer);
48 int64_t currentTime = MiscServices::TimeServiceClient::GetInstance()->GetBootTimeMs();
49 MiscServices::TimeServiceClient::GetInstance()->StartTimer(m_netStatsTimerId, currentTime + NET_STATS_DELAY_TIME);
50 WIFI_LOGI("%{public}s, succuss", __FUNCTION__);
51 }
52
StopNetStats()53 void WifiNetStatsManager::StopNetStats()
54 {
55 WIFI_LOGI("%{public}s, enter", __FUNCTION__);
56 if (m_netStatsTimerId == 0) {
57 WIFI_LOGE("%{public}s, m_netStatsTimerId is zero", __FUNCTION__);
58 } else {
59 MiscServices::TimeServiceClient::GetInstance()->StopTimer(m_netStatsTimerId);
60 MiscServices::TimeServiceClient::GetInstance()->DestroyTimer(m_netStatsTimerId);
61 m_netStatsTimerId = 0;
62 }
63 std::lock_guard<std::mutex> lock(lastStatsMapMutex_);
64 m_lastStatsMap.clear();
65 m_hasLastStats = false;
66 WIFI_LOGI("%{public}s, succuss", __FUNCTION__);
67 }
68
PerformPollAndLog()69 void WifiNetStatsManager::PerformPollAndLog()
70 {
71 NetStats curNetStats;
72 if (GetWifiNetStatsDetail(curNetStats) != WIFI_OPT_SUCCESS) {
73 WIFI_LOGE("%{public}s, get network stats failed", __FUNCTION__);
74 return;
75 }
76 std::lock_guard<std::mutex> lock(lastStatsMapMutex_);
77 if (!m_hasLastStats) {
78 WIFI_LOGE("%{public}s, get base network stats", __FUNCTION__);
79 m_hasLastStats = true;
80 m_lastStatsMap = ConvertNetStatsToMap(curNetStats);
81 return;
82 }
83 NetStats incrementalNetStats = GetIncrementalNetStats(curNetStats);
84 m_lastStatsMap = ConvertNetStatsToMap(curNetStats);
85 LogNetStatsTraffic(incrementalNetStats);
86 }
87
GetWifiNetStatsDetail(NetStats & netStats)88 ErrCode WifiNetStatsManager::GetWifiNetStatsDetail(NetStats &netStats)
89 {
90 NetStats data;
91 int32_t ret = DelayedSingleton<NetManagerStandard::NetStatsClient>::GetInstance()->GetAllStatsInfo(data);
92 if (ret != ERR_OK) {
93 WIFI_LOGE("%{public}s, get network stats failed, ret: %{public}d", __FUNCTION__, ret);
94 return WIFI_OPT_FAILED;
95 }
96 std::copy_if(data.begin(), data.end(), std::back_insert_iterator(netStats), [](NetStatsInfo info) {
97 return info.iface_ == WLAN_0 && !info.HasNoData();
98 });
99 return WIFI_OPT_SUCCESS;
100 }
101
GetIncrementalNetStats(NetStats curNetStats)102 NetStats WifiNetStatsManager::GetIncrementalNetStats(NetStats curNetStats)
103 {
104 NetStats incrementNetStats;
105 for (auto &curInfo : curNetStats) {
106 NetStatsInfo deltaInfo;
107 auto indexIter = m_lastStatsMap.find(curInfo.uid_);
108 if (indexIter == m_lastStatsMap.end()) {
109 deltaInfo = curInfo;
110 } else {
111 deltaInfo = curInfo - indexIter->second;
112 }
113 if (deltaInfo.HasNoData()) {
114 continue;
115 }
116 incrementNetStats.push_back(deltaInfo);
117 }
118 return incrementNetStats;
119 }
120
GetTotalNetStatsInfo(NetStats netStats)121 NetStatsInfo WifiNetStatsManager::GetTotalNetStatsInfo(NetStats netStats)
122 {
123 NetStatsInfo totalNetStatsInfo;
124 for (const auto &info : netStats) {
125 totalNetStatsInfo += info;
126 }
127 totalNetStatsInfo.uid_ = UID_ALL;
128 return totalNetStatsInfo;
129 }
130
ConvertNetStatsToMap(NetStats netStats)131 std::map<int32_t, NetStatsInfo> WifiNetStatsManager::ConvertNetStatsToMap(NetStats netStats)
132 {
133 std::map<int32_t, NetStatsInfo> netStatsMap;
134 for (const auto &item : netStats) {
135 netStatsMap.emplace(item.uid_, item);
136 }
137 return netStatsMap;
138 }
139
GetTrafficLog(std::string bundleName,NetStatsInfo info,bool needEndStr)140 std::string WifiNetStatsManager::GetTrafficLog(std::string bundleName, NetStatsInfo info, bool needEndStr)
141 {
142 std::string trafficLog;
143 trafficLog += bundleName;
144 trafficLog += SEP_STR;
145 trafficLog += std::to_string(info.rxBytes_);
146 trafficLog += SEP_STR;
147 trafficLog += std::to_string(info.txBytes_);
148 trafficLog += SEP_STR;
149 trafficLog += std::to_string(info.rxPackets_);
150 trafficLog += SEP_STR;
151 trafficLog += std::to_string(info.txPackets_);
152 if (needEndStr) {
153 trafficLog += END_STR;
154 }
155 return trafficLog;
156 }
157
GetBundleName(int32_t uid)158 std::string WifiNetStatsManager::GetBundleName(int32_t uid)
159 {
160 if (uid == UID_ALL) {
161 return "total";
162 }
163 std::string bundleName;
164 if (OHOS::Wifi::GetBundleNameByUid(uid, bundleName) != WIFI_OPT_SUCCESS) {
165 return "unknown:" + std::to_string(uid);
166 }
167 return bundleName;
168 }
169
LogNetStatsTraffic(NetStats netStats)170 void WifiNetStatsManager::LogNetStatsTraffic(NetStats netStats)
171 {
172 std::sort(netStats.begin(), netStats.end(), [] (NetStatsInfo v1, NetStatsInfo v2) {
173 return v1.GetStats() > v2.GetStats();
174 });
175 int maxCount = netStats.size() >= MAX_LOG_TRAFFIC ? MAX_LOG_TRAFFIC : static_cast<int>(netStats.size());
176 NetStatsInfo totalNetStats = GetTotalNetStatsInfo(netStats);
177 if (totalNetStats.HasNoData()) {
178 return;
179 }
180 std::string allTrafficLog;
181 allTrafficLog += GetTrafficLog(GetBundleName(totalNetStats.uid_), totalNetStats);
182 for (int i = 0; i < maxCount; i++) {
183 if (i != maxCount - 1) {
184 allTrafficLog += GetTrafficLog(GetBundleName(netStats[i].uid_), netStats[i]);
185 } else {
186 allTrafficLog += GetTrafficLog(GetBundleName(netStats[i].uid_), netStats[i], false);
187 }
188 }
189 WIFI_LOGI("%{public}s", allTrafficLog.c_str());
190 }
191 } // namespace Wifi
192 } // namespace OHOS