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 &param) 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