195489c19Sopenharmony_ci/* 295489c19Sopenharmony_ci * Copyright (C) 2024 Huawei Device Co., Ltd. 395489c19Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 495489c19Sopenharmony_ci * you may not use this file except in compliance with the License. 595489c19Sopenharmony_ci * You may obtain a copy of the License at 695489c19Sopenharmony_ci * 795489c19Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 895489c19Sopenharmony_ci * 995489c19Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1095489c19Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1195489c19Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1295489c19Sopenharmony_ci * See the License for the specific language governing permissions and 1395489c19Sopenharmony_ci * limitations under the License. 1495489c19Sopenharmony_ci */ 1595489c19Sopenharmony_ci 1695489c19Sopenharmony_ci#include "bluetooth_switch_module.h" 1795489c19Sopenharmony_ci 1895489c19Sopenharmony_ci#include <algorithm> 1995489c19Sopenharmony_ci#include "bluetooth_errorcode.h" 2095489c19Sopenharmony_ci#include "bluetooth_log.h" 2195489c19Sopenharmony_ci 2295489c19Sopenharmony_cinamespace OHOS { 2395489c19Sopenharmony_cinamespace Bluetooth { 2495489c19Sopenharmony_cistatic const char *ToString(BluetoothSwitchEvent event) 2595489c19Sopenharmony_ci{ 2695489c19Sopenharmony_ci switch (event) { 2795489c19Sopenharmony_ci case BluetoothSwitchEvent::ENABLE_BLUETOOTH: return "ENABLE_BLUETOOTH"; 2895489c19Sopenharmony_ci case BluetoothSwitchEvent::DISABLE_BLUETOOTH: return "DISABLE_BLUETOOTH"; 2995489c19Sopenharmony_ci case BluetoothSwitchEvent::ENABLE_BLUETOOTH_TO_RESTRICE_MODE: return "ENABLE_BLUETOOTH_TO_RESTRICE_MODE"; 3095489c19Sopenharmony_ci case BluetoothSwitchEvent::BLUETOOTH_ON: return "BLUETOOTH_ON"; 3195489c19Sopenharmony_ci case BluetoothSwitchEvent::BLUETOOTH_OFF: return "BLUETOOTH_OFF"; 3295489c19Sopenharmony_ci case BluetoothSwitchEvent::BLUETOOTH_HALF: return "BLUETOOTH_HALF"; 3395489c19Sopenharmony_ci default: break; 3495489c19Sopenharmony_ci } 3595489c19Sopenharmony_ci return "Unknown"; 3695489c19Sopenharmony_ci} 3795489c19Sopenharmony_ci 3895489c19Sopenharmony_civoid BluetoothSwitchModule::LogBluetoothSwitchEvent(BluetoothSwitchEvent event) 3995489c19Sopenharmony_ci{ 4095489c19Sopenharmony_ci bool needLog = (event == BluetoothSwitchEvent::BLUETOOTH_ON || 4195489c19Sopenharmony_ci event == BluetoothSwitchEvent::BLUETOOTH_OFF || 4295489c19Sopenharmony_ci event == BluetoothSwitchEvent::BLUETOOTH_HALF) ? isBtSwitchProcessing_.load() : true; 4395489c19Sopenharmony_ci if (needLog) { 4495489c19Sopenharmony_ci HILOGI("Process Event: %{public}s", ToString(event)); 4595489c19Sopenharmony_ci } 4695489c19Sopenharmony_ci} 4795489c19Sopenharmony_ci 4895489c19Sopenharmony_ciint BluetoothSwitchModule::ProcessBluetoothSwitchEvent(BluetoothSwitchEvent event) 4995489c19Sopenharmony_ci{ 5095489c19Sopenharmony_ci CHECK_AND_RETURN_LOG_RET(switchAction_, BT_ERR_INTERNAL_ERROR, "switchAction is nullptr"); 5195489c19Sopenharmony_ci 5295489c19Sopenharmony_ci std::lock_guard<std::mutex> lock(bluetoothSwitchEventMutex_); 5395489c19Sopenharmony_ci LogBluetoothSwitchEvent(event); 5495489c19Sopenharmony_ci switch (event) { 5595489c19Sopenharmony_ci case BluetoothSwitchEvent::ENABLE_BLUETOOTH: 5695489c19Sopenharmony_ci return ProcessEnableBluetoothEvent(); 5795489c19Sopenharmony_ci case BluetoothSwitchEvent::DISABLE_BLUETOOTH: 5895489c19Sopenharmony_ci return ProcessDisableBluetoothEvent(); 5995489c19Sopenharmony_ci case BluetoothSwitchEvent::ENABLE_BLUETOOTH_TO_RESTRICE_MODE: 6095489c19Sopenharmony_ci return ProcessEnableBluetoothToRestrictModeEvent(); 6195489c19Sopenharmony_ci case BluetoothSwitchEvent::BLUETOOTH_ON: 6295489c19Sopenharmony_ci return ProcessBluetoothOnEvent(); 6395489c19Sopenharmony_ci case BluetoothSwitchEvent::BLUETOOTH_OFF: 6495489c19Sopenharmony_ci return ProcessBluetoothOffEvent(); 6595489c19Sopenharmony_ci case BluetoothSwitchEvent::BLUETOOTH_HALF: 6695489c19Sopenharmony_ci return ProcessBluetoothHalfEvent(); 6795489c19Sopenharmony_ci default: break; 6895489c19Sopenharmony_ci } 6995489c19Sopenharmony_ci HILOGI("Invalid event: %{public}s", ToString(event)); 7095489c19Sopenharmony_ci return BT_ERR_INTERNAL_ERROR; 7195489c19Sopenharmony_ci} 7295489c19Sopenharmony_ci 7395489c19Sopenharmony_civoid BluetoothSwitchModule::OnTaskTimeout(void) 7495489c19Sopenharmony_ci{ 7595489c19Sopenharmony_ci HILOGW("Bluetooth switch action timeout, clear resources"); 7695489c19Sopenharmony_ci std::lock_guard<std::mutex> lock(bluetoothSwitchEventMutex_); 7795489c19Sopenharmony_ci isBtSwitchProcessing_ = false; 7895489c19Sopenharmony_ci cachedEventVec_.clear(); 7995489c19Sopenharmony_ci} 8095489c19Sopenharmony_ci 8195489c19Sopenharmony_ciint BluetoothSwitchModule::ProcessBluetoothSwitchAction( 8295489c19Sopenharmony_ci std::function<int(void)> action, BluetoothSwitchEvent cachedEvent) 8395489c19Sopenharmony_ci{ 8495489c19Sopenharmony_ci if (isBtSwitchProcessing_.load()) { 8595489c19Sopenharmony_ci cachedEventVec_.push_back(cachedEvent); 8695489c19Sopenharmony_ci HILOGW("BtSwich action is processing, cache the %{public}s event", ToString(cachedEvent)); 8795489c19Sopenharmony_ci return BT_NO_ERROR; 8895489c19Sopenharmony_ci } 8995489c19Sopenharmony_ci 9095489c19Sopenharmony_ci ffrt::task_attr taskAttr; 9195489c19Sopenharmony_ci taskAttr.name("bt_switch").delay(taskTimeout_); 9295489c19Sopenharmony_ci taskTimeoutHandle_ = ffrtQueue_.submit_h([switchWptr = weak_from_this()]() { 9395489c19Sopenharmony_ci auto switchSptr = switchWptr.lock(); 9495489c19Sopenharmony_ci if (switchSptr == nullptr) { 9595489c19Sopenharmony_ci HILOGE("switchSptr is nullptr"); 9695489c19Sopenharmony_ci return; 9795489c19Sopenharmony_ci } 9895489c19Sopenharmony_ci switchSptr->OnTaskTimeout(); 9995489c19Sopenharmony_ci }, taskAttr); 10095489c19Sopenharmony_ci 10195489c19Sopenharmony_ci isBtSwitchProcessing_ = true; 10295489c19Sopenharmony_ci int ret = action(); 10395489c19Sopenharmony_ci if (ret != BT_NO_ERROR) { 10495489c19Sopenharmony_ci isBtSwitchProcessing_ = false; 10595489c19Sopenharmony_ci ffrtQueue_.cancel(taskTimeoutHandle_); 10695489c19Sopenharmony_ci } 10795489c19Sopenharmony_ci return ret; 10895489c19Sopenharmony_ci} 10995489c19Sopenharmony_ci 11095489c19Sopenharmony_ciint BluetoothSwitchModule::ProcessEnableBluetoothEvent(void) 11195489c19Sopenharmony_ci{ 11295489c19Sopenharmony_ci return ProcessBluetoothSwitchAction( 11395489c19Sopenharmony_ci [this]() { return switchAction_->EnableBluetooth(); }, 11495489c19Sopenharmony_ci BluetoothSwitchEvent::ENABLE_BLUETOOTH); 11595489c19Sopenharmony_ci} 11695489c19Sopenharmony_ci 11795489c19Sopenharmony_ciint BluetoothSwitchModule::ProcessDisableBluetoothEvent(void) 11895489c19Sopenharmony_ci{ 11995489c19Sopenharmony_ci return ProcessBluetoothSwitchAction( 12095489c19Sopenharmony_ci [this]() { return switchAction_->DisableBluetooth(); }, 12195489c19Sopenharmony_ci BluetoothSwitchEvent::DISABLE_BLUETOOTH); 12295489c19Sopenharmony_ci} 12395489c19Sopenharmony_ci 12495489c19Sopenharmony_ciint BluetoothSwitchModule::ProcessEnableBluetoothToRestrictModeEvent(void) 12595489c19Sopenharmony_ci{ 12695489c19Sopenharmony_ci return ProcessBluetoothSwitchAction( 12795489c19Sopenharmony_ci [this]() { return switchAction_->EnableBluetoothToRestrictMode(); }, 12895489c19Sopenharmony_ci BluetoothSwitchEvent::ENABLE_BLUETOOTH_TO_RESTRICE_MODE); 12995489c19Sopenharmony_ci} 13095489c19Sopenharmony_ci 13195489c19Sopenharmony_ciint BluetoothSwitchModule::ProcessBluetoothOnEvent(void) 13295489c19Sopenharmony_ci{ 13395489c19Sopenharmony_ci return ProcessBluetoothSwitchActionEnd( 13495489c19Sopenharmony_ci BluetoothSwitchEvent::ENABLE_BLUETOOTH, 13595489c19Sopenharmony_ci {BluetoothSwitchEvent::DISABLE_BLUETOOTH}); 13695489c19Sopenharmony_ci} 13795489c19Sopenharmony_ci 13895489c19Sopenharmony_ciint BluetoothSwitchModule::ProcessBluetoothOffEvent(void) 13995489c19Sopenharmony_ci{ 14095489c19Sopenharmony_ci return ProcessBluetoothSwitchActionEnd( 14195489c19Sopenharmony_ci BluetoothSwitchEvent::DISABLE_BLUETOOTH, 14295489c19Sopenharmony_ci {BluetoothSwitchEvent::ENABLE_BLUETOOTH, BluetoothSwitchEvent::ENABLE_BLUETOOTH_TO_RESTRICE_MODE}); 14395489c19Sopenharmony_ci} 14495489c19Sopenharmony_ci 14595489c19Sopenharmony_ciint BluetoothSwitchModule::ProcessBluetoothHalfEvent(void) 14695489c19Sopenharmony_ci{ 14795489c19Sopenharmony_ci return ProcessBluetoothSwitchActionEnd( 14895489c19Sopenharmony_ci BluetoothSwitchEvent::ENABLE_BLUETOOTH_TO_RESTRICE_MODE, 14995489c19Sopenharmony_ci {BluetoothSwitchEvent::ENABLE_BLUETOOTH, BluetoothSwitchEvent::DISABLE_BLUETOOTH}); 15095489c19Sopenharmony_ci} 15195489c19Sopenharmony_ci 15295489c19Sopenharmony_ciint BluetoothSwitchModule::ProcessBluetoothSwitchActionEnd( 15395489c19Sopenharmony_ci BluetoothSwitchEvent curSwitchActionEvent, std::vector<BluetoothSwitchEvent> expectedEventVec) 15495489c19Sopenharmony_ci{ 15595489c19Sopenharmony_ci isBtSwitchProcessing_ = false; 15695489c19Sopenharmony_ci ffrtQueue_.cancel(taskTimeoutHandle_); 15795489c19Sopenharmony_ci DeduplicateCacheEvent(curSwitchActionEvent); 15895489c19Sopenharmony_ci 15995489c19Sopenharmony_ci // Expect process the next event is in 'expectedProcessEventVec' 16095489c19Sopenharmony_ci auto it = std::find_if(cachedEventVec_.begin(), cachedEventVec_.end(), [&expectedEventVec](auto event) { 16195489c19Sopenharmony_ci return std::find(expectedEventVec.begin(), expectedEventVec.end(), event) != expectedEventVec.end(); 16295489c19Sopenharmony_ci }); 16395489c19Sopenharmony_ci if (it != cachedEventVec_.end()) { 16495489c19Sopenharmony_ci if (it != cachedEventVec_.begin()) { 16595489c19Sopenharmony_ci LogCacheEventIgnored(std::vector<BluetoothSwitchEvent>(cachedEventVec_.begin(), it)); 16695489c19Sopenharmony_ci } 16795489c19Sopenharmony_ci // Ignore the cached event before 'expectedEventVec' 16895489c19Sopenharmony_ci BluetoothSwitchEvent event = *it; 16995489c19Sopenharmony_ci cachedEventVec_.erase(cachedEventVec_.begin(), it + 1); 17095489c19Sopenharmony_ci return ProcessBluetoothSwitchCachedEvent(event); 17195489c19Sopenharmony_ci } 17295489c19Sopenharmony_ci 17395489c19Sopenharmony_ci cachedEventVec_.clear(); 17495489c19Sopenharmony_ci return BT_NO_ERROR; 17595489c19Sopenharmony_ci} 17695489c19Sopenharmony_ci 17795489c19Sopenharmony_ciint BluetoothSwitchModule::ProcessBluetoothSwitchCachedEvent(BluetoothSwitchEvent event) 17895489c19Sopenharmony_ci{ 17995489c19Sopenharmony_ci HILOGI("Auto process cached %{public}s event", ToString(event)); 18095489c19Sopenharmony_ci ffrtQueue_.submit([switchWptr = weak_from_this(), event]() { 18195489c19Sopenharmony_ci auto switchSptr = switchWptr.lock(); 18295489c19Sopenharmony_ci if (switchSptr == nullptr) { 18395489c19Sopenharmony_ci HILOGE("switchSptr is nullptr"); 18495489c19Sopenharmony_ci return; 18595489c19Sopenharmony_ci } 18695489c19Sopenharmony_ci switchSptr->ProcessBluetoothSwitchEvent(event); 18795489c19Sopenharmony_ci }); 18895489c19Sopenharmony_ci return BT_NO_ERROR; 18995489c19Sopenharmony_ci} 19095489c19Sopenharmony_ci 19195489c19Sopenharmony_civoid BluetoothSwitchModule::DeduplicateCacheEvent(BluetoothSwitchEvent curEvent) 19295489c19Sopenharmony_ci{ 19395489c19Sopenharmony_ci // 从缓存事件列表里,找到最后一个 curEvent,保留该事件之后的缓存事件 19495489c19Sopenharmony_ci auto it = std::find(cachedEventVec_.rbegin(), cachedEventVec_.rend(), curEvent); 19595489c19Sopenharmony_ci if (it != cachedEventVec_.rend()) { 19695489c19Sopenharmony_ci // The it.base() is greater than cachedEventVec_.begin(), so std::distance > 0. 19795489c19Sopenharmony_ci size_t pos = static_cast<size_t>(std::distance(cachedEventVec_.begin(), it.base())) - 1; 19895489c19Sopenharmony_ci 19995489c19Sopenharmony_ci LogCacheEventIgnored( 20095489c19Sopenharmony_ci std::vector<BluetoothSwitchEvent>(cachedEventVec_.begin(), cachedEventVec_.begin() + pos + 1)); 20195489c19Sopenharmony_ci cachedEventVec_.erase(cachedEventVec_.begin(), cachedEventVec_.begin() + pos + 1); 20295489c19Sopenharmony_ci } 20395489c19Sopenharmony_ci} 20495489c19Sopenharmony_ci 20595489c19Sopenharmony_civoid BluetoothSwitchModule::LogCacheEventIgnored(std::vector<BluetoothSwitchEvent> eventVec) 20695489c19Sopenharmony_ci{ 20795489c19Sopenharmony_ci std::string log = ""; 20895489c19Sopenharmony_ci for (size_t i = 0; i < eventVec.size(); i++) { 20995489c19Sopenharmony_ci // The last event current process event, not ignored 21095489c19Sopenharmony_ci log += ToString(eventVec[i]); 21195489c19Sopenharmony_ci log += " "; 21295489c19Sopenharmony_ci } 21395489c19Sopenharmony_ci if (!log.empty()) { 21495489c19Sopenharmony_ci HILOGW("Ignore cache event: %{public}s", log.c_str()); 21595489c19Sopenharmony_ci } 21695489c19Sopenharmony_ci} 21795489c19Sopenharmony_ci} // namespace Bluetooth 21895489c19Sopenharmony_ci} // namespace OHOS 219