1 /*
2 * Copyright (C) 2021-2022 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 "app_network_speed_limit_service.h"
17 #include "wifi_logger.h"
18 #include "wifi_common_util.h"
19 #include "wifi_app_parser.h"
20 #include "wifi_settings.h"
21 #include "app_mgr_client.h"
22 #include "wifi_global_func.h"
23 #include "speed_limit_configs_writer.h"
24 #include "wifi_app_state_aware.h"
25
26 namespace OHOS {
27 namespace Wifi {
28
29 DEFINE_WIFILOG_LABEL("AppNetworkSpeedLimitService");
30 const std::string APP_NETWORK_SPEED_LIMIT_CLASS_NAME = "AppNetworkSpeedLimitService";
31
AppNetworkSpeedLimitService()32 AppNetworkSpeedLimitService::AppNetworkSpeedLimitService()
33 {
34 Init();
35 }
36
~AppNetworkSpeedLimitService()37 AppNetworkSpeedLimitService::~AppNetworkSpeedLimitService() {}
38
39
GetInstance()40 AppNetworkSpeedLimitService &AppNetworkSpeedLimitService::GetInstance()
41 {
42 static AppNetworkSpeedLimitService instance;
43 return instance;
44 }
45
GetStaCallback() const46 StaServiceCallback AppNetworkSpeedLimitService::GetStaCallback() const
47 {
48 return m_staCallback;
49 }
50
Init()51 void AppNetworkSpeedLimitService::Init()
52 {
53 using namespace std::placeholders;
54 m_staCallback.callbackModuleName = APP_NETWORK_SPEED_LIMIT_CLASS_NAME;
55 m_staCallback.OnStaConnChanged = std::bind(&AppNetworkSpeedLimitService::DealStaConnChanged, this, _1, _2, _3);
56 InitWifiLimitRecord();
57 InitCellarLimitRecord();
58 }
59
InitWifiLimitRecord()60 void AppNetworkSpeedLimitService::InitWifiLimitRecord()
61 {
62 m_bgLimitRecordMap[BG_LIMIT_CONTROL_ID_GAME] = BG_LIMIT_OFF;
63 m_bgLimitRecordMap[BG_LIMIT_CONTROL_ID_STREAM] = BG_LIMIT_OFF;
64 m_bgLimitRecordMap[BG_LIMIT_CONTROL_ID_TEMP] = BG_LIMIT_OFF;
65 }
66
InitCellarLimitRecord()67 void AppNetworkSpeedLimitService::InitCellarLimitRecord()
68 {
69 std::lock_guard<std::mutex> lock(m_readWritemutex);
70 m_bgLimitRecordMap[BG_LIMIT_CONTROL_ID_MODULE_FOREGROUND_OPT] = BG_LIMIT_OFF;
71 }
72
DealStaConnChanged(OperateResState state,const WifiLinkedInfo & info,int instId)73 void AppNetworkSpeedLimitService::DealStaConnChanged(OperateResState state, const WifiLinkedInfo &info, int instId)
74 {
75 if (state == OperateResState::DISCONNECT_DISCONNECTED) {
76 HandleWifiConnectStateChanged(false);
77 } else if (state == OperateResState::CONNECT_AP_CONNECTED) {
78 HandleWifiConnectStateChanged(true);
79 }
80 }
81
HandleWifiConnectStateChanged(const bool isWifiConnected)82 void AppNetworkSpeedLimitService::HandleWifiConnectStateChanged(const bool isWifiConnected)
83 {
84 WIFI_LOGI("%{public}s, isWifiConnected=%{public}d", __FUNCTION__, isWifiConnected);
85 std::lock_guard<std::mutex> lock(m_readWritemutex);
86 m_isWifiConnected = isWifiConnected;
87 if (m_bgLimitRecordMap[BG_LIMIT_CONTROL_ID_TEMP] != BG_LIMIT_OFF) {
88 LimitSpeed(BG_LIMIT_CONTROL_ID_TEMP, m_bgLimitRecordMap[BG_LIMIT_CONTROL_ID_TEMP]);
89 }
90 }
91
HandleForegroundAppChangedAction(const AppExecFwk::AppStateData & appStateData)92 void AppNetworkSpeedLimitService::HandleForegroundAppChangedAction(const AppExecFwk::AppStateData &appStateData)
93 {
94 if (appStateData.state == static_cast<int>(AppExecFwk::AppProcessState::APP_STATE_FOREGROUND) &&
95 appStateData.isFocused) {
96 std::lock_guard<std::mutex> lock(m_readWritemutex);
97 if (m_isWifiConnected && m_bgLimitRecordMap[BG_LIMIT_CONTROL_ID_TEMP] != BG_LIMIT_OFF) {
98 WIFI_LOGI("%{public}s high temp speed limit is running, update background app list", __FUNCTION__);
99 LimitSpeed(BG_LIMIT_CONTROL_ID_TEMP, m_bgLimitRecordMap[BG_LIMIT_CONTROL_ID_TEMP]);
100 }
101 }
102 }
103
LimitSpeed(const int controlId,const int limitMode)104 void AppNetworkSpeedLimitService::LimitSpeed(const int controlId, const int limitMode)
105 {
106 WIFI_LOGI("%{public}s enter, controlId=%{public}d, limitMode=%{public}d", __FUNCTION__, controlId, limitMode);
107 std::lock_guard<std::mutex> lock(m_mutex);
108 UpdateSpeedLimitConfigs(controlId, limitMode);
109 int ret = SetBgLimitMode(m_currentLimitMode);
110 if (ret < 0) {
111 WIFI_LOGE("SetBgLimitMode failed, ret = %{public}d.", ret);
112 return;
113 }
114 SetBgLimitIdList(std::vector<int>(m_bgUidSet.begin(), m_bgUidSet.end()), SET_BG_UID);
115 SetBgLimitIdList(std::vector<int>(m_bgPidSet.begin(), m_bgPidSet.end()), SET_BG_PID);
116 SetBgLimitIdList(std::vector<int>(m_fgUidSet.begin(), m_fgUidSet.end()), SET_FG_UID);
117 }
118
GetBgLimitMaxMode()119 int AppNetworkSpeedLimitService::GetBgLimitMaxMode()
120 {
121 if (m_bgLimitRecordMap.empty()) {
122 WIFI_LOGE("m_bgLimitRecordMap is empty.\n");
123 return -1;
124 }
125 int maxMode = 0;
126 std::map<int, int>::iterator iter;
127 for (iter = m_bgLimitRecordMap.begin(); iter != m_bgLimitRecordMap.end(); ++iter) {
128 if (!CheckNetWorkCanBeLimited(iter->first)) {
129 continue;
130 }
131 if (iter->second > maxMode) {
132 maxMode = iter->second;
133 }
134 }
135 return maxMode;
136 }
137
GetAppList(std::vector<AppExecFwk::RunningProcessInfo> & appList,bool getFgAppFlag)138 ErrCode AppNetworkSpeedLimitService::GetAppList(std::vector<AppExecFwk::RunningProcessInfo> &appList, bool getFgAppFlag)
139 {
140 std::vector<AppExecFwk::RunningProcessInfo> infos;
141 if (WifiAppStateAware::GetInstance().GetProcessRunningInfos(infos) != WIFI_OPT_SUCCESS) {
142 WIFI_LOGE("GetProcessRunningInfosByUserId failed.");
143 return WIFI_OPT_FAILED;
144 }
145 if (getFgAppFlag) {
146 for (auto iter = infos.begin(); iter != infos.end(); ++iter) {
147 if (iter->state_ == AppExecFwk::AppProcessState::APP_STATE_FOREGROUND &&
148 iter->isFocused) {
149 appList.push_back(*iter);
150 }
151 }
152 } else {
153 for (auto iter = infos.begin(); iter != infos.end(); ++iter) {
154 if (iter->state_ == AppExecFwk::AppProcessState::APP_STATE_BACKGROUND) {
155 appList.push_back(*iter);
156 }
157 }
158 }
159
160 return WIFI_OPT_SUCCESS;
161 }
162
163
CheckNetWorkCanBeLimited(const int controlId)164 bool AppNetworkSpeedLimitService::CheckNetWorkCanBeLimited(const int controlId)
165 {
166 switch (controlId) {
167 case BgLimitControl::BG_LIMIT_CONTROL_ID_GAME:
168 return true;
169 case BgLimitControl::BG_LIMIT_CONTROL_ID_STREAM:
170 return true;
171 case BgLimitControl::BG_LIMIT_CONTROL_ID_TEMP:
172 return m_isWifiConnected;
173 case BgLimitControl::BG_LIMIT_CONTROL_ID_MODULE_FOREGROUND_OPT:
174 return true;
175 default:
176 break;
177 }
178 return false;
179 }
180
UpdateSpeedLimitConfigs(const int controlId,const int limitMode)181 void AppNetworkSpeedLimitService::UpdateSpeedLimitConfigs(const int controlId, const int limitMode)
182 {
183 m_bgUidSet.clear();
184 m_bgPidSet.clear();
185 m_fgUidSet.clear();
186 m_bgLimitRecordMap[controlId] = limitMode;
187 m_currentLimitMode = GetBgLimitMaxMode();
188 if (m_currentLimitMode == BgLimitLevel::BG_LIMIT_OFF) {
189 m_bgUidSet.insert(UNKNOWN_UID);
190 m_bgPidSet.insert(UNKNOWN_UID);
191 m_fgUidSet.insert(UNKNOWN_UID);
192 LogSpeedLimitConfigs();
193 return;
194 }
195 std::vector<AppExecFwk::RunningProcessInfo> bgAppList;
196 if (GetAppList(bgAppList, false) < 0) {
197 WIFI_LOGE("Get background app list fail.");
198 }
199 for (auto &record : m_bgLimitRecordMap) {
200 if (!CheckNetWorkCanBeLimited(record.first) || record.second == BG_LIMIT_OFF) {
201 continue;
202 }
203 for (auto iter = bgAppList.begin(); iter != bgAppList.end(); ++iter) {
204 if (IsLimitSpeedBgApp(record.first, iter->processName_)) {
205 m_bgUidSet.insert(iter->uid_);
206 m_bgPidSet.insert(iter->pid_);
207 }
208 }
209 }
210 std::vector<AppExecFwk::RunningProcessInfo> fgAppList;
211 if (GetAppList(fgAppList, true) < 0) {
212 WIFI_LOGE("Get foreground app list fail.");
213 }
214 for (auto iter = fgAppList.begin(); iter != fgAppList.end(); ++iter) {
215 m_fgUidSet.insert(iter->uid_);
216 }
217 LogSpeedLimitConfigs();
218 }
219
LogSpeedLimitConfigs()220 void AppNetworkSpeedLimitService::LogSpeedLimitConfigs()
221 {
222 std::string recordsStr;
223 for (auto &record : m_bgLimitRecordMap) {
224 recordsStr += std::to_string(record.first);
225 recordsStr += ":";
226 recordsStr += std::to_string(record.second);
227 recordsStr += ",";
228 }
229 WIFI_LOGI("%{public}s speed limit records= %{public}s, limitMode: %{public}d, m_isWifiConnected: %{public}d",
230 __FUNCTION__, recordsStr.c_str(), m_currentLimitMode, m_isWifiConnected.load());
231 WIFI_LOGI("%{public}s m_bgUidSet: %{public}s; m_bgPidSet: %{public}s; m_fgUidSet: %{public}s", __FUNCTION__,
232 JoinVecToString(std::vector<int>(m_bgUidSet.begin(), m_bgUidSet.end()), ",").c_str(),
233 JoinVecToString(std::vector<int>(m_bgPidSet.begin(), m_bgPidSet.end()), ",").c_str(),
234 JoinVecToString(std::vector<int>(m_fgUidSet.begin(), m_fgUidSet.end()), ",").c_str());
235 }
236
IsLimitSpeedBgApp(const int controlId,const std::string bundleName)237 bool AppNetworkSpeedLimitService::IsLimitSpeedBgApp(const int controlId, const std::string bundleName)
238 {
239 switch (controlId) {
240 case BgLimitControl::BG_LIMIT_CONTROL_ID_GAME:
241 return AppParser::GetInstance().IsBlackListApp(bundleName);
242 case BgLimitControl::BG_LIMIT_CONTROL_ID_STREAM:
243 case BgLimitControl::BG_LIMIT_CONTROL_ID_TEMP:
244 return AppParser::GetInstance().IsHighTempLimitSpeedApp(bundleName);
245 case BgLimitControl::BG_LIMIT_CONTROL_ID_MODULE_FOREGROUND_OPT:
246 return true;
247 default:
248 break;
249 }
250 WIFI_LOGI("%{public}s invalid controlId", __FUNCTION__);
251 return false;
252 }
253
254 } // namespace Wifi
255 } // namespace OHOS