1 /*
2 * Copyright (C) 2021 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_protect_manager.h"
17 #include "wifi_log.h"
18 #include "wifi_chip_hal_interface.h"
19 #include "wifi_supplicant_hal_interface.h"
20 #ifndef OHOS_ARCH_LITE
21 #include "system_ability_definition.h"
22 #include "connection_observer_client.h"
23 #include "app_mgr_client.h"
24 #include "app_process_data.h"
25 #include "iservice_registry.h"
26 #include "app_mgr_constants.h"
27 #include "define.h"
28 #endif
29 #include "wifi_config_center.h"
30 #include "wifi_app_state_aware.h"
31
32 #undef LOG_TAG
33 #define LOG_TAG "OHWIFI_MANAGER_LOCK_MANAGER"
34
35 namespace OHOS {
36 namespace Wifi {
37 constexpr const int WIFI_PROTECT_APP_MAX_COUNT = 100;
38
WifiProtectManager()39 WifiProtectManager::WifiProtectManager()
40 {
41 mWifiConnected = false;
42 mScreenOn = false;
43 mForceHiPerfMode = false;
44 mForceLowLatencyMode = false;
45 mCurrentOpMode = WifiProtectMode::WIFI_PROTECT_NO_HELD;
46 mFullHighPerfProtectsAcquired = 0;
47 mFullHighPerfProtectsReleased = 0;
48 mFullLowLatencyProtectsAcquired = 0;
49 mFullLowLatencyProtectsReleased = 0;
50 mWifiProtects.clear();
51 }
52
~WifiProtectManager()53 WifiProtectManager::~WifiProtectManager()
54 {
55 }
56
GetInstance()57 WifiProtectManager &WifiProtectManager::GetInstance()
58 {
59 static WifiProtectManager instance;
60 return instance;
61 }
62
IsValidProtectMode(const WifiProtectMode & protectMode)63 bool WifiProtectManager::IsValidProtectMode(const WifiProtectMode &protectMode)
64 {
65 if (protectMode != WifiProtectMode::WIFI_PROTECT_FULL &&
66 protectMode != WifiProtectMode::WIFI_PROTECT_SCAN_ONLY &&
67 protectMode != WifiProtectMode::WIFI_PROTECT_FULL_HIGH_PERF &&
68 protectMode != WifiProtectMode::WIFI_PROTECT_FULL_LOW_LATENCY) {
69 return false;
70 }
71
72 return true;
73 }
74
IsHeldWifiProtect(const std::string & protectName)75 bool WifiProtectManager::IsHeldWifiProtect(const std::string &protectName)
76 {
77 LOGD("%{public}s enter, para bundlename: %{public}s",
78 __func__, protectName.c_str());
79 std::unique_lock<std::mutex> lock(mMutex);
80 std::vector<std::shared_ptr<WifiProtect>>::iterator itor = mWifiProtects.begin();
81 while (itor != mWifiProtects.end()) {
82 if ((*itor)->GetName() == protectName) {
83 LOGI("%{public}s app bundlename: %{public}s has held wifi protect",
84 __func__, protectName.c_str());
85 return true;
86 }
87 itor++;
88 }
89 return false;
90 }
91
GetNearlyProtectMode()92 WifiProtectMode WifiProtectManager::GetNearlyProtectMode()
93 {
94 #ifndef OHOS_ARCH_LITE
95 WifiLinkedInfo linkedInfo;
96 WifiConfigCenter::GetInstance().GetLinkedInfo(linkedInfo);
97 mWifiConnected = (linkedInfo.connState == ConnState::CONNECTED) ? true : false;
98
99 int screenState = WifiConfigCenter::GetInstance().GetScreenState();
100 mScreenOn = (screenState == MODE_STATE_OPEN || screenState == MODE_STATE_DEFAULT) ? true : false;
101 int foregroudCount = GetFgLowlatyProtectCount();
102 LOGD("%{public}s mWifiConnected: %{public}d, mScreenOn: %{public}d,"
103 "ForegroundProtectCount: %{public}d, mForceHiPerfMode: %{public}d, mForceLowLatencyMode: %{public}d",
104 __func__, mWifiConnected, mScreenOn, foregroudCount, mForceHiPerfMode, mForceLowLatencyMode);
105 #endif
106 /* If Wifi Client is not connected, then all protects are not effective */
107 if (!mWifiConnected) {
108 return WifiProtectMode::WIFI_PROTECT_NO_HELD;
109 }
110
111 /* Check if mode is forced to hi-perf */
112 if (mForceHiPerfMode) {
113 return WifiProtectMode::WIFI_PROTECT_FULL_HIGH_PERF;
114 }
115
116 /* Check if mode is forced to low-latency */
117 if (mForceLowLatencyMode) {
118 return WifiProtectMode::WIFI_PROTECT_FULL_LOW_LATENCY;
119 }
120 #ifndef OHOS_ARCH_LITE
121 /* If screen is on and has app in foreground and app set wifi protect to low-lantency mode,
122 then set wifi to low-latency
123 */
124 if (mScreenOn && (foregroudCount > 0) &&
125 (mFullLowLatencyProtectsAcquired > mFullLowLatencyProtectsReleased)) {
126 return WifiProtectMode::WIFI_PROTECT_FULL_LOW_LATENCY;
127 }
128 if ((mFullHighPerfProtectsAcquired > mFullHighPerfProtectsReleased) &&
129 mWifiProtects.size() > 0) {
130 #else
131 if (mFullHighPerfProtectsAcquired > mFullHighPerfProtectsReleased) {
132 #endif
133 return WifiProtectMode::WIFI_PROTECT_FULL_HIGH_PERF;
134 }
135
136 return WifiProtectMode::WIFI_PROTECT_NO_HELD;
137 }
138
139 bool WifiProtectManager::InitWifiProtect(
140 const WifiProtectType &protectType,
141 const std::string &protectName)
142 {
143 std::unique_lock<std::mutex> lock(mMutex);
144 std::shared_ptr<WifiProtect> pProtect = std::make_shared<WifiProtect>(protectType,
145 WifiProtectMode::WIFI_PROTECT_FULL, protectName);
146 mWifiProtects.push_back(pProtect);
147 return true;
148 }
149
150 bool WifiProtectManager::GetWifiProtect(
151 const WifiProtectMode &protectMode,
152 const std::string name)
153 {
154 LOGD("%{public}s mode: %{public}d, bundlename: %{public}s",
155 __func__, static_cast<int>(protectMode), name.c_str());
156 #ifndef OHOS_ARCH_LITE
157 if (!IsValidProtectMode(protectMode) || name.empty()) {
158 LOGE("Input para protectMode[%{public}d] or name[%{public}s] invalid",
159 static_cast<int>(protectMode), name.c_str());
160 return false;
161 }
162 WifiProtectMode curProtectMode;
163 #endif
164 bool isAlreadyExist = false;
165 std::unique_lock<std::mutex> lock(mMutex);
166 std::vector<std::shared_ptr<WifiProtect>>::iterator itor = mWifiProtects.begin();
167 while (itor != mWifiProtects.end()) {
168 if ((*itor)->GetName() == name) {
169 isAlreadyExist = true;
170 #ifndef OHOS_ARCH_LITE
171 curProtectMode = (*itor)->GetProtectMode();
172 #endif
173 break;
174 }
175 itor++;
176 }
177
178 if (isAlreadyExist) {
179 #ifndef OHOS_ARCH_LITE
180 if (curProtectMode == protectMode) {
181 LOGW("attempted to add a protect when already holding one");
182 return true;
183 } else {
184 LOGE("attempted to add a different protect mode to already holding one,"
185 "please release holded protect first!");
186 return false;
187 }
188 #else
189 LOGE("attempted to add a protect when already holding one");
190 return false;
191 #endif
192 }
193 #ifndef OHOS_ARCH_LITE
194 if (mWifiProtects.size() >= WIFI_PROTECT_APP_MAX_COUNT) {
195 LOGE("Wifi protect app count out of range[%d].", WIFI_PROTECT_APP_MAX_COUNT);
196 return false;
197 }
198 #endif
199 return AddProtect(protectMode, name);
200 }
201
202 bool WifiProtectManager::ChangeToPerfMode(bool isEnabled)
203 {
204 std::unique_lock<std::mutex> lock(mMutex);
205 mForceHiPerfMode = isEnabled;
206 mForceLowLatencyMode = false;
207 if (!ChangeWifiPowerMode()) {
208 LOGE("Failed to force hi-perf mode, returning to normal mode");
209 mForceHiPerfMode = false;
210 return false;
211 }
212
213 return true;
214 }
215 void WifiProtectManager::HandleScreenStateChanged(bool screenOn)
216 {
217
218 std::unique_lock<std::mutex> lock(mMutex);
219 mScreenOn = screenOn;
220 LOGD("%{public}s screen is on: %{public}d", __func__, mScreenOn);
221
222 #ifndef OHOS_ARCH_LITE
223 if (ChangeWifiPowerMode()) {
224 LOGD("Failed to update wifi power mode for screen state change");
225 }
226 #endif
227 }
228
229 void WifiProtectManager::UpdateWifiClientConnected(bool isConnected)
230 {
231 std::unique_lock<std::mutex> lock(mMutex);
232 mWifiConnected = isConnected;
233 LOGD("%{public}s wifi connected: %{public}d", __func__, mWifiConnected);
234
235 #ifndef OHOS_ARCH_LITE
236 if (ChangeWifiPowerMode()) {
237 LOGD("Failed to update wifi power mode for connect state change");
238 }
239 #endif
240 }
241
242 bool WifiProtectManager::AddProtect(
243 const WifiProtectMode &protectMode,
244 const std::string &name)
245 {
246 std::shared_ptr<WifiProtect> pProtect = std::make_shared<WifiProtect>(name);
247 if (!pProtect) {
248 LOGE("Wifi protect pointer is null.");
249 return false;
250 }
251 #ifndef OHOS_ARCH_LITE
252 int state = static_cast<int>(AppExecFwk::ApplicationState::APP_STATE_END);
253 if (WifiAppStateAware::GetInstance().IsForegroundApp(name)) {
254 state = static_cast<int>(AppExecFwk::ApplicationState::APP_STATE_FOREGROUND);
255 }
256 LOGD("%{public}s bundle name: %{public}s state: %{public}d",
257 __func__, name.c_str(), state);
258 pProtect->SetAppState(state);
259 #endif
260 pProtect->SetProtectMode(protectMode);
261
262 mWifiProtects.push_back(pProtect);
263 switch (pProtect->GetProtectMode()) {
264 case WifiProtectMode::WIFI_PROTECT_FULL_HIGH_PERF:
265 ++mFullHighPerfProtectsAcquired;
266 break;
267 case WifiProtectMode::WIFI_PROTECT_FULL_LOW_LATENCY:
268 ++mFullLowLatencyProtectsAcquired;
269 break;
270 default:
271 break;
272 }
273 return ChangeWifiPowerMode();
274 }
275
276 bool WifiProtectManager::PutWifiProtect(const std::string &name)
277 {
278 LOGI("%{public}s enter bundlename: %{public}s", __func__, name.c_str());
279 if (name.empty()) {
280 LOGE("invalid bundlename: %{public}s", name.c_str());
281 return false;
282 }
283 std::unique_lock<std::mutex> lock(mMutex);
284 std::shared_ptr<WifiProtect> pWifiProtect = RemoveProtect(name);
285 if (!pWifiProtect) {
286 LOGE("attempting to release a protect that does not exist, protect name: %{public}s.",
287 name.c_str());
288 return false;
289 }
290 switch (pWifiProtect->GetProtectMode()) {
291 case WifiProtectMode::WIFI_PROTECT_FULL_HIGH_PERF:
292 ++mFullHighPerfProtectsReleased;
293 break;
294 case WifiProtectMode::WIFI_PROTECT_FULL_LOW_LATENCY:
295 ++mFullLowLatencyProtectsReleased;
296 break;
297 default:
298 break;
299 }
300
301 /* Recalculate the operating mode */
302 bool ret = ChangeWifiPowerMode();
303 return ret;
304 }
305
306 std::shared_ptr<WifiProtect> WifiProtectManager::RemoveProtect(const std::string &name)
307 {
308 std::shared_ptr<WifiProtect> pProtect = nullptr;
309 std::vector<std::shared_ptr<WifiProtect>>::iterator itor = mWifiProtects.begin();
310 while (itor != mWifiProtects.end()) {
311 if ((*itor)->GetName() == name) {
312 pProtect = *itor;
313 itor = mWifiProtects.erase(itor);
314 break;
315 }
316 itor++;
317 }
318 return pProtect;
319 }
320
321 bool WifiProtectManager::ChangeWifiPowerMode()
322 {
323 WifiProtectMode newProtectMode = GetNearlyProtectMode();
324 LOGD("%{public}s currMode: %{public}d, newMode: %{public}d",
325 __func__, static_cast<int>(mCurrentOpMode), static_cast<int>(newProtectMode));
326 if (newProtectMode == mCurrentOpMode) {
327 /* No action is needed */
328 LOGD("newProtectMode %{public}d equal to mCurrentOpMode %{public}d, no action is needed",
329 static_cast<int>(newProtectMode), static_cast<int>(mCurrentOpMode));
330 return true;
331 }
332
333 /* Otherwise, we need to change current mode, first reset it to normal */
334 switch (mCurrentOpMode) {
335 case WifiProtectMode::WIFI_PROTECT_FULL_HIGH_PERF:
336 if (WifiSupplicantHalInterface::GetInstance().SetPowerSave(true) != WIFI_HAL_OPT_OK) {
337 LOGE("%{public}s Failed to reset the OpMode from hi-perf to Normal", __func__);
338 return false;
339 }
340 break;
341 case WifiProtectMode::WIFI_PROTECT_FULL_LOW_LATENCY:
342 if (!SetLowLatencyMode(false)) {
343 LOGE("%{public}s Failed to reset the OpMode from low-latency to normal", __func__);
344 return false;
345 }
346 break;
347 case WifiProtectMode::WIFI_PROTECT_NO_HELD:
348 default:
349 /* No action */
350 break;
351 }
352
353 /* Set the current mode, before we attempt to set the new mode */
354 mCurrentOpMode = WifiProtectMode::WIFI_PROTECT_NO_HELD;
355
356 /* Now switch to the new opMode */
357 switch (newProtectMode) {
358 case WifiProtectMode::WIFI_PROTECT_FULL_HIGH_PERF:
359 if (WifiSupplicantHalInterface::GetInstance().SetPowerSave(false) != WIFI_HAL_OPT_OK) {
360 LOGE("%{public}s Failed to set the OpMode to hi-perf", __func__);
361 return false;
362 }
363 break;
364 case WifiProtectMode::WIFI_PROTECT_FULL_LOW_LATENCY:
365 if (!SetLowLatencyMode(true)) {
366 LOGE("%{public}s Failed to set the OpMode to low-latency", __func__);
367 return false;
368 }
369 LOGE("%{public}s unspport wifi protect mode WIFI_PROTECT_FULL_LOW_LATENCY", __func__);
370 break;
371 case WifiProtectMode::WIFI_PROTECT_NO_HELD:
372 /* No action */
373 break;
374 default:
375 /* Invalid mode, don't change currentOpMode , and exit with error */
376 LOGE("%{public}s Invalid new protect Mode: %{public}d",
377 __func__, (int)newProtectMode);
378 return false;
379 }
380
381 /* Now set the mode to the new value */
382 mCurrentOpMode = newProtectMode;
383 LOGD("%{public}s protect mode has been set to %{public}d success.",
384 __func__, static_cast<int>(mCurrentOpMode));
385 return true;
386 }
387
388 bool WifiProtectManager::SetLowLatencyMode(bool enabled)
389 {
390 /* Only set power save mode */
391 if (WifiSupplicantHalInterface::GetInstance().SetPowerSave(!enabled) != WIFI_HAL_OPT_OK) {
392 LOGE("Failed to set power save mode");
393 return false;
394 }
395
396 return true;
397 }
398 #ifndef OHOS_ARCH_LITE
399 int WifiProtectManager::GetFgLowlatyProtectCount()
400 {
401 int count = 0;
402 std::vector<std::shared_ptr<WifiProtect>>::iterator iter = mWifiProtects.begin();
403 while (iter != mWifiProtects.end()) {
404 if (static_cast<AppExecFwk::ApplicationState>((*iter)->GetAppState()) ==
405 AppExecFwk::ApplicationState::APP_STATE_FOREGROUND &&
406 (*iter)->GetProtectMode() == WifiProtectMode::WIFI_PROTECT_FULL_LOW_LATENCY) {
407 count += 1;
408 LOGD("%{public}s bundlename %{public}s state %{public}d.",
409 __func__, (*iter)->GetName().c_str(), (*iter)->GetAppState());
410 }
411 iter++;
412 }
413 return count;
414 }
415
416 void WifiProtectManager::OnAppDied(const std::string bundlename)
417 {
418 LOGD("Enter %{public}s, remove app bundlename %{public}s.",
419 __func__, bundlename.c_str());
420 std::unique_lock<std::mutex> lock(mMutex);
421 bool needUpdate = false;
422 std::vector<std::shared_ptr<WifiProtect>>::iterator iter = mWifiProtects.begin();
423 while (iter != mWifiProtects.end()) {
424 if ((*iter)->GetName() == bundlename) {
425 WifiProtectMode mode = (*iter)->GetProtectMode();
426 if (mode == WifiProtectMode::WIFI_PROTECT_FULL_HIGH_PERF) {
427 ++mFullHighPerfProtectsReleased;
428 } else if (mode == WifiProtectMode::WIFI_PROTECT_FULL_LOW_LATENCY) {
429 ++mFullLowLatencyProtectsReleased;
430 }
431 mWifiProtects.erase(iter);
432 needUpdate = true;
433 LOGI("%{public}s, remove app bundlename %{public}s.",
434 __func__, bundlename.c_str());
435 break;
436 }
437 iter++;
438 }
439 if (needUpdate) {
440 ChangeWifiPowerMode();
441 }
442 }
443
444 void WifiProtectManager::OnAppForegroudChanged(const std::string &bundleName, int state)
445 {
446 std::unique_lock<std::mutex> lock(mMutex);
447 bool needUpdate = false;
448 std::vector<std::shared_ptr<WifiProtect>>::iterator iter = mWifiProtects.begin();
449 while (iter != mWifiProtects.end()) {
450 if ((*iter)->GetName() == bundleName) {
451 (*iter)->SetAppState(state);
452 needUpdate = true;
453 LOGD("%{public}s, foreground change bundleName %{public}s state %{public}d.",
454 __func__, bundleName.c_str(), state);
455 break;
456 }
457 iter++;
458 }
459 if (needUpdate) {
460 ChangeWifiPowerMode();
461 }
462 }
463
464 #endif
465 } // namespace Wifi
466 } // namespace OHOS
467