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