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