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 "power_device.h" 17 #include <cstring> 18 #include <memory> 19 #include <mutex> 20 #include "btm.h" 21 #include "log.h" 22 #include "message.h" 23 #include "power_state_machine.h" 24 #include "securec.h" 25 26 namespace OHOS { 27 namespace bluetooth { 28 struct PowerDevice::impl { 29 public: implOHOS::bluetooth::PowerDevice::impl30 impl(const RawAddress rawAddr, utility::Dispatcher &dispatcher):rawAddr_(rawAddr), dispatcher_(dispatcher){}; ~implOHOS::bluetooth::PowerDevice::impl31 ~impl(){}; 32 const RawAddress rawAddr_; 33 utility::Dispatcher &dispatcher_; 34 std::map<std::string, RequestStatus> requestPower_ {}; 35 std::unique_ptr<PowerStateMachine> psm_ = nullptr; 36 std::pair<PowerSsrLevel, PowerModeLevel> requestPowerLevel_ = 37 std::pair<PowerSsrLevel, PowerModeLevel>(PowerSsrLevel::NO_ACTION, PowerModeLevel::NO_ACTION); 38 std::pair<PowerSsrLevel, PowerModeLevel> controlPowerLevel_ = 39 std::pair<PowerSsrLevel, PowerModeLevel>(PowerSsrLevel::NO_ACTION, PowerModeLevel::NO_ACTION); 40 int controlPowerMode_ {}; 41 int controlInterval_ {}; 42 std::unique_ptr<PowerTimer> sniffDelayTimer_ = nullptr; 43 std::mutex mutex_ {}; 44 45 BT_DISALLOW_COPY_AND_ASSIGN(impl); 46 }; 47 PowerDevice(const RawAddress rawAddr,utility::Dispatcher & dispatcher)48 PowerDevice::PowerDevice(const RawAddress rawAddr, utility::Dispatcher &dispatcher) 49 : pimpl(std::make_unique<PowerDevice::impl>(rawAddr, dispatcher)) 50 { 51 pimpl->psm_ = std::make_unique<PowerStateMachine>(); 52 pimpl->psm_->Init(*this); 53 54 pimpl->sniffDelayTimer_ = std::make_unique<PowerTimer>(std::bind( 55 [&]()->void { 56 std::weak_ptr<PowerDevice> weakDevice = shared_from_this(); 57 pimpl->dispatcher_.PostTask(std::bind(&bluetooth::PowerDevice::DelayTimeoutCallback, weakDevice)); 58 } 59 )); 60 } 61 ~PowerDevice()62 PowerDevice::~PowerDevice() 63 { 64 pimpl->sniffDelayTimer_->Stop(); 65 } 66 67 /// update request power function SetRequestPower(const std::string & profileName,const RequestStatus status) const68 void PowerDevice::SetRequestPower(const std::string &profileName, const RequestStatus status) const 69 { 70 pimpl->requestPower_[profileName] = status; 71 } 72 DeleteRequestPower(const std::string & profileName) const73 void PowerDevice::DeleteRequestPower(const std::string &profileName) const 74 { 75 pimpl->requestPower_.erase(profileName); 76 } 77 SetPowerMode()78 void PowerDevice::SetPowerMode() 79 { 80 PowerInfo maxPower = CalcMaxPower(); 81 if (maxPower.powerMode_ == PowerModeLevel::NO_ACTION) { 82 return; 83 } 84 if (maxPower.powerMode_ == PowerModeLevel::LEVEL_ACTIVE) { 85 SetActiveMode(); 86 } else { 87 SetSniffMode(maxPower); 88 } 89 } 90 91 /// set power mode interface, use by SetPowerMode() / DelayTimeoutCallback() SetActiveMode()92 void PowerDevice::SetActiveMode() 93 { 94 LOG_DEBUG("PM_: SetActiveMode"); 95 StopDelayTimer(); // Stop Sniff Delay Timer. 96 utility::Message msg(PowerStateMachine::MSG_PM_SET_ACTIVE); 97 pimpl->psm_->ProcessMessage(msg); 98 } 99 SetSniffMode(PowerInfo requestPower)100 void PowerDevice::SetSniffMode(PowerInfo requestPower) 101 { 102 LOG_DEBUG("PM_: SetSniffMode"); 103 // Because the hardware does not support resetting the sniff parameter in the sniff state, 104 // it exits the sniff first, and then delays to enter the sniff. 105 PowerModeLevel controlPowerMode = GetControlPowerLevel().second; 106 if (requestPower.powerMode_ != controlPowerMode && 107 (controlPowerMode == PowerModeLevel::LEVEL_LOW || 108 controlPowerMode == PowerModeLevel::LEVEL_MID || 109 controlPowerMode == PowerModeLevel::LEVEL_HIG)) { 110 LOG_DEBUG("PM_:::SetSniffMode() contorl is in sniff state, to reset the sniff parameter, you need to exit " 111 "sniff state first\n"); 112 SetActiveMode(); 113 } 114 115 if (GetDelayTimerRemainMs() <= static_cast<uint64_t>(requestPower.timeout_)) { 116 LOG_DEBUG("PM_: Reset Timer: timeoutMs: %{public}d\n", requestPower.timeout_); 117 StopDelayTimer(); 118 StartDelayTimer(static_cast<uint64_t>(requestPower.timeout_)); 119 } 120 } 121 GetPowerMode() const122 BTPowerMode PowerDevice::GetPowerMode() const 123 { 124 PowerModeLevel powerLevel = GetControlPowerLevel().second; 125 BTPowerMode powerMode = BTPowerMode::MODE_ACTIVE; 126 if (powerLevel == PowerModeLevel::LEVEL_ACTIVE) { 127 powerMode = BTPowerMode::MODE_ACTIVE; 128 } else if (powerLevel == PowerModeLevel::LEVEL_HIG) { 129 powerMode = BTPowerMode::MODE_SNIFF_LEVEL_HIG; 130 } else if (powerLevel == PowerModeLevel::LEVEL_MID) { 131 powerMode = BTPowerMode::MODE_SNIFF_LEVEL_MID; 132 } else if (powerLevel == PowerModeLevel::LEVEL_LOW) { 133 powerMode = BTPowerMode::MODE_SNIFF_LEVEL_LOW; 134 } 135 return powerMode; 136 } 137 ModeChangeCallBack(uint8_t status,uint8_t currentMode,uint16_t interval)138 void PowerDevice::ModeChangeCallBack(uint8_t status, uint8_t currentMode, uint16_t interval) 139 { 140 if (status == 0) { 141 LOG_DEBUG("PM_: %{public}s, status: %{public}d, currentMode: %{public}d, interval: %{public}d\n", __FUNCTION__, status, currentMode, interval); 142 /// update state 143 if (currentMode == BTM_PM_ACTIVE_MODE) { // current Mode Active 144 UpdateControlSniffSubrating(PowerSsrLevel::NO_ACTION); 145 UpdatecontrolPowerLevel(PowerModeLevel::LEVEL_ACTIVE); 146 utility::Message msg(PowerStateMachine::MSG_PM_MODE_CHANGE_ACTIVE); 147 pimpl->psm_->ProcessMessage(msg); 148 } else if (currentMode == BTM_PM_SNIFF_MODE) { // current Mode Sniff 149 if (interval <= SNIFF_LEVEL_LOW_MAX_INTERVAL && interval >= SNIFF_LEVEL_LOW_MIN_INTERVAL) { 150 UpdatecontrolPowerLevel(PowerModeLevel::LEVEL_LOW); 151 } else if (interval <= SNIFF_LEVEL_MID_MAX_INTERVAL && interval >= SNIFF_LEVEL_MID_MIN_INTERVAL) { 152 UpdatecontrolPowerLevel(PowerModeLevel::LEVEL_MID); 153 } else if (interval <= SNIFF_LEVEL_HIG_MAX_INTERVAL && interval >= SNIFF_LEVEL_HIG_MIN_INTERVAL) { 154 UpdatecontrolPowerLevel(PowerModeLevel::LEVEL_HIG); 155 } 156 utility::Message msg(PowerStateMachine::MSG_PM_MODE_CHANGE_SNIFF); 157 pimpl->psm_->ProcessMessage(msg); 158 } 159 } else { /// hci status error 160 LOG_DEBUG("PM_: %{public}s, hci status error: %{public}d\n", __FUNCTION__, status); 161 } 162 } 163 SniffSubratingCompleteCallback(uint8_t status) const164 void PowerDevice::SniffSubratingCompleteCallback(uint8_t status) const 165 { 166 LOG_DEBUG("PM_: %{public}s, line: %{public}d\n", __FUNCTION__, __LINE__); 167 if (status == 0) { 168 UpdateControlSniffSubrating(GetRequestPowerLevel().first); 169 utility::Message msg(PowerStateMachine::MSG_PM_SET_SUBRATING_COMPLETE); 170 pimpl->psm_->ProcessMessage(msg); 171 } 172 } 173 174 /// calc power level and ssr level CalcMaxPower() const175 PowerInfo PowerDevice::CalcMaxPower() const 176 { 177 PowerInfo maxPower = PowerInfo(PowerModeLevel::NO_ACTION, 0); 178 for (auto &its : pimpl->requestPower_) { 179 PowerInfo itSpec = PowerSpec::GetPowerSpec(its.first, its.second); 180 if (itSpec.powerMode_ > maxPower.powerMode_) { 181 maxPower = itSpec; 182 } 183 } 184 return maxPower; 185 } 186 CalcLowestSsrLevel() const187 PowerSsrLevel PowerDevice::CalcLowestSsrLevel() const 188 { 189 PowerSsrLevel lowestLevel = PowerSsrLevel::NO_ACTION; 190 for (auto &its : pimpl->requestPower_) { 191 PowerSsrLevel level = PowerSpec::GetPowerSsrLevel(its.first, its.second); 192 if ((level != PowerSsrLevel::NO_ACTION) && (level < lowestLevel)) { 193 lowestLevel = level; 194 } 195 } 196 return lowestLevel; 197 } 198 199 /// btm power interface BtmSetSniffSubrating(const PowerSsrParam & ssrParam) const200 int PowerDevice::BtmSetSniffSubrating(const PowerSsrParam &ssrParam) const 201 { 202 LOG_DEBUG("PM_: %{public}s start, line: %{public}d\n", __FUNCTION__, __LINE__); 203 BtAddr btAddr; 204 (void)memset_s(&btAddr, sizeof(btAddr), 0, sizeof(btAddr)); 205 pimpl->rawAddr_.ConvertToUint8(btAddr.addr); 206 207 BtmSniffSubrating btmSsrParam; 208 btmSsrParam.maximumLatency = ssrParam.maxLat_; 209 btmSsrParam.minimumLocalTimeout = ssrParam.minLocTo_; 210 btmSsrParam.minimumRemoteTimeout = ssrParam.minRmtTo_; 211 212 return BTM_SetSniffSubrating(&btAddr, &btmSsrParam); 213 } 214 BtmExitSniffMode() const215 int PowerDevice::BtmExitSniffMode() const 216 { 217 LOG_DEBUG("PM_: %{public}s start, line: %{public}d\n", __FUNCTION__, __LINE__); 218 BtAddr btAddr; 219 (void)memset_s(&btAddr, sizeof(btAddr), 0, sizeof(btAddr)); 220 pimpl->rawAddr_.ConvertToUint8(btAddr.addr); 221 return BTM_ExitSniffMode(&btAddr); 222 } 223 BtmEnterSniffMode(const PowerParam & param) const224 int PowerDevice::BtmEnterSniffMode(const PowerParam ¶m) const 225 { 226 LOG_DEBUG("PM_: %{public}s start, line: %{public}d\n", __FUNCTION__, __LINE__); 227 BtAddr btAddr; 228 BtmSniffParam btmSniffParam; 229 230 (void)memset_s(&btAddr, sizeof(btAddr), 0, sizeof(btAddr)); 231 pimpl->rawAddr_.ConvertToUint8(btAddr.addr); 232 btmSniffParam.attempt = param.attempt_; 233 btmSniffParam.maxInterval = param.maxInterval_; 234 btmSniffParam.minInterval = param.minInterval_; 235 btmSniffParam.timeout = param.timeout_; 236 237 return BTM_EnterSniffMode(&btAddr, &btmSniffParam); 238 } 239 GetRequestPowerLevel() const240 const std::pair<PowerSsrLevel, PowerModeLevel> &PowerDevice::GetRequestPowerLevel() const 241 { 242 return pimpl->requestPowerLevel_; 243 } 244 SetRequestPowerLevel(const PowerSsrLevel ssr,const PowerModeLevel power) const245 void PowerDevice::SetRequestPowerLevel(const PowerSsrLevel ssr, const PowerModeLevel power) const 246 { 247 pimpl->requestPowerLevel_ = std::pair<PowerSsrLevel, PowerModeLevel>(ssr, power); 248 } 249 GetControlPowerLevel() const250 const std::pair<PowerSsrLevel, PowerModeLevel> &PowerDevice::GetControlPowerLevel() const 251 { 252 std::unique_lock<std::mutex> lock(pimpl->mutex_); 253 return pimpl->controlPowerLevel_; 254 } 255 UpdateControlSniffSubrating(const PowerSsrLevel ssr) const256 void PowerDevice::UpdateControlSniffSubrating(const PowerSsrLevel ssr) const 257 { 258 std::unique_lock<std::mutex> lock(pimpl->mutex_); 259 pimpl->controlPowerLevel_.first = ssr; 260 } 261 UpdatecontrolPowerLevel(const PowerModeLevel powerLevel) const262 void PowerDevice::UpdatecontrolPowerLevel(const PowerModeLevel powerLevel) const 263 { 264 std::unique_lock<std::mutex> lock(pimpl->mutex_); 265 pimpl->controlPowerLevel_.second = powerLevel; 266 } 267 DelayTimeoutCallback(const std::weak_ptr<PowerDevice> & weakDevice)268 void PowerDevice::DelayTimeoutCallback(const std::weak_ptr<PowerDevice>& weakDevice) 269 { 270 std::shared_ptr<PowerDevice> sharedDevice = weakDevice.lock(); 271 if (sharedDevice != nullptr) { 272 LOG_DEBUG("PM_: %{public}s start, line: %{public}d\n", __FUNCTION__, __LINE__); 273 PowerInfo maxPowerInfo = sharedDevice->CalcMaxPower(); 274 LOG_DEBUG("PM_: %{public}s, maxPowerInfo: %{public}d\n", __FUNCTION__, static_cast<int>(maxPowerInfo.powerMode_)); 275 if (maxPowerInfo.powerMode_ == PowerModeLevel::LEVEL_ACTIVE) { 276 sharedDevice->SetActiveMode(); 277 } else if (maxPowerInfo.powerMode_ == PowerModeLevel::NO_ACTION) { 278 return; 279 } else { 280 PowerSsrLevel lowestSsrLevel = sharedDevice->CalcLowestSsrLevel(); 281 sharedDevice->SetRequestPowerLevel(lowestSsrLevel, maxPowerInfo.powerMode_); 282 utility::Message msg(PowerStateMachine::MSG_PM_SET_SNIFF); 283 sharedDevice->pimpl->psm_->ProcessMessage(msg); 284 } 285 } else { 286 LOG_DEBUG("PowerDevice::DelayTimeoutCallback sharedDevice == nullptr"); 287 } 288 } 289 290 /// delay timer function StartDelayTimer(int ms) const291 void PowerDevice::StartDelayTimer(int ms) const 292 { 293 LOG_DEBUG("PM_: %{public}s start, line: %{public}d\n", __FUNCTION__, __LINE__); 294 pimpl->sniffDelayTimer_->Start(ms); 295 } 296 StopDelayTimer() const297 void PowerDevice::StopDelayTimer() const 298 { 299 LOG_DEBUG("PM_: %{public}s start, line: %{public}d\n", __FUNCTION__, __LINE__); 300 pimpl->sniffDelayTimer_->Stop(); 301 } 302 GetDelayTimerRemainMs() const303 uint64_t PowerDevice::GetDelayTimerRemainMs() const 304 { 305 return pimpl->sniffDelayTimer_->GetRemainMs(); 306 } 307 Start(int ms,bool isPeriodic)308 bool PowerDevice::PowerTimer::Start(int ms, bool isPeriodic) 309 { 310 bool ret = utility::Timer::Start(ms, isPeriodic); 311 struct timespec ts = {}; 312 clock_gettime(CLOCK_BOOTTIME, &ts); 313 deadLineMs_ = ts.tv_sec * MS_PER_SECOND + ts.tv_nsec / NS_PER_MS + ms; 314 return ret; 315 } 316 Stop()317 bool PowerDevice::PowerTimer::Stop() 318 { 319 deadLineMs_ = 0; 320 return utility::Timer::Stop(); 321 } 322 GetRemainMs()323 uint64_t PowerDevice::PowerTimer::GetRemainMs() 324 { 325 struct timespec ts = {}; 326 clock_gettime(CLOCK_BOOTTIME, &ts); 327 uint64_t presentMs = ts.tv_sec * MS_PER_SECOND + ts.tv_nsec / NS_PER_MS; 328 if (deadLineMs_ > presentMs) { 329 return deadLineMs_ - presentMs; 330 } else { 331 deadLineMs_ = 0; 332 return 0; 333 } 334 } 335 } // namespace bluetooth 336 } // namespace OHOS