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