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