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 32namespace OHOS { 33namespace NetManagerStandard { 34using namespace NetStatsDatabaseDefines; 35namespace { 36constexpr const char *IFACE_LO = "lo"; 37} // namespace 38 39int32_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 72void 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 78void 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 89void 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 95void 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 101void 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 107void 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 125void 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 171NetStatsInfo 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 181NetStatsInfo 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 191void 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 224void 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 251void 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 284void 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 313void NetStatsCached::CacheStats() 314{ 315 std::lock_guard<ffrt::mutex> lock(lock_); 316 CacheUidStats(); 317 CacheAppStats(); 318 CacheUidSimStats(); 319 CacheIfaceStats(); 320} 321 322void NetStatsCached::WriteStats() 323{ 324 std::lock_guard<ffrt::mutex> lock(lock_); 325 WriteUidStats(); 326 WriteUidSimStats(); 327 WriteIfaceStats(); 328} 329void 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 340void 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 356void 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 372void 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 380void 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 390void 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 402void 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 428void 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 446void NetStatsCached::Reset() {} 447 448} // namespace NetManagerStandard 449} // namespace OHOS 450