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