• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param) 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