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_manager.h"
17 #include <cstring>
18 #include <list>
19 #include <map>
20 #include <mutex>
21 #include <string>
22 #include "adapter_manager.h"
23 #include "btm.h"
24 #include "log.h"
25 #include "log_util.h"
26 #include "power_device.h"
27 #include "timer.h"
28
29 namespace OHOS {
30 namespace bluetooth {
31 // static function
32 static std::unique_ptr<PowerManager> g_powerManager = nullptr;
GetInstance()33 IPowerManager &IPowerManager::GetInstance()
34 {
35 return PowerManager::GetInstance();
36 }
Initialize(utility::Dispatcher & dispatcher)37 void IPowerManager::Initialize(utility::Dispatcher &dispatcher)
38 {
39 g_powerManager->Initialize(dispatcher);
40 }
41
Uninitialize()42 void IPowerManager::Uninitialize()
43 {
44 g_powerManager->Uninitialize();
45 }
46
GetInstance()47 PowerManager &PowerManager::GetInstance()
48 {
49 return *(g_powerManager.get());
50 }
51
Initialize(utility::Dispatcher & dispatcher)52 void PowerManager::Initialize(utility::Dispatcher &dispatcher)
53 {
54 LOG_DEBUG("PM_: %{public}s start, line: %{public}d\n", __FUNCTION__, __LINE__);
55 if (g_powerManager == nullptr) {
56 g_powerManager = std::make_unique<PowerManager>(dispatcher);
57 }
58 }
59
Uninitialize()60 void PowerManager::Uninitialize()
61 {
62 LOG_DEBUG("PM_: %{public}s start, line: %{public}d\n", __FUNCTION__, __LINE__);
63 g_powerManager = nullptr;
64 }
65
66 /// PowerManager class
67 struct PowerManager::impl {
68 public:
implOHOS::bluetooth::PowerManager::impl69 explicit impl(utility::Dispatcher &dispatcher) : dispatcher_(dispatcher)
70 {
71 LOG_DEBUG("PM_: impl %{public}s start, line: %{public}d\n", __FUNCTION__, __LINE__);
72 };
~implOHOS::bluetooth::PowerManager::impl73 ~impl(){};
74
75 std::mutex mutex_ {};
76 std::atomic_bool isEnabled_ = false;
77 BtmPmCallbacks btmPmCallbacks_ {};
78 BtmAclCallbacks btmAclCallbacks_ {};
79 utility::Dispatcher &dispatcher_;
80 std::map<RawAddress, std::shared_ptr<PowerDevice>> powerDevices_ {};
81 std::map<uint16_t, RawAddress> connectionHandles_ {};
82
83 void PowerProcess(const RequestStatus status, const std::string &profileName, const RawAddress rawAddr);
84 void UpdatePowerDevicesInfo(const RawAddress rawAddr, const std::string &profileName, const RequestStatus status);
85
86 void ModeChangeCallBackProcess(uint8_t status, const RawAddress rawAddr, uint8_t currentMode, uint16_t interval);
87 static void ModeChangeCallBack(
88 uint8_t status, const BtAddr *btAddr, uint8_t currentMode, uint16_t interval, void *context);
89
90 void SsrCompleteCallBackProcess(uint8_t status, const RawAddress rawAddr);
91 static void SsrCompleteCallBack(uint8_t status, const BtAddr *btAddr, void *context);
92
93 void ConnectionCompleteCallBackProcess(const RawAddress rawAddr, uint16_t connectionHandle);
94 static void ConnectionCompleteCallBack(const BtmAclConnectCompleteParam *param, void *context);
95
96 void DisconnectionCompleteCallBackProcess(uint8_t status, uint16_t connectionHandle, uint8_t reason);
97 static void DisconnectionCompleteCallBack(uint8_t status, uint16_t connectionHandle, uint8_t reason, void *context);
98
99 BT_DISALLOW_COPY_AND_ASSIGN(impl);
100 };
101
PowerManager(utility::Dispatcher & dispatcher)102 PowerManager::PowerManager(utility::Dispatcher &dispatcher) : pimpl(std::make_unique<PowerManager::impl>(dispatcher))
103 {}
~PowerManager()104 PowerManager::~PowerManager()
105 {}
106
Enable()107 void PowerManager::Enable()
108 {
109 LOG_DEBUG("PM_: %{public}s start, line: %{public}d\n", __FUNCTION__, __LINE__);
110 pimpl->isEnabled_ = true;
111 int retVal = BTM_SetDefaultLinkPolicySettings(BTM_LINK_POLICY_ENABLE_ROLE_SWITCH |
112 BTM_LINK_POLICY_ENABLE_SNIFF_MODE);
113 LOG_DEBUG("PM_: BTM_SetDefaultLinkPolicySettings retVal: %{public}d\n", retVal);
114
115 pimpl->btmPmCallbacks_.modeChange = PowerManager::impl::ModeChangeCallBack;
116 pimpl->btmPmCallbacks_.setSniffSubratingComplete = PowerManager::impl::SsrCompleteCallBack;
117 pimpl->btmAclCallbacks_.connectionComplete = PowerManager::impl::ConnectionCompleteCallBack;
118 pimpl->btmAclCallbacks_.disconnectionComplete = PowerManager::impl::DisconnectionCompleteCallBack;
119
120 retVal = BTM_RegisterPmCallbacks(&pimpl->btmPmCallbacks_, this);
121 LOG_DEBUG("PM_: BTM_RegisterPmCallbacks retVal: %{public}d\n", retVal);
122
123 retVal = BTM_RegisterAclCallbacks(&pimpl->btmAclCallbacks_, this);
124 LOG_DEBUG("PM_: BTM_RegisterPmCallbacks retVal: %{public}d\n", retVal);
125 }
126
Disable()127 void PowerManager::Disable()
128 {
129 LOG_DEBUG("PM_: %{public}s start, line: %{public}d\n", __FUNCTION__, __LINE__);
130 pimpl->isEnabled_ = false;
131 BTM_DeregisterPmCallbacks(&pimpl->btmPmCallbacks_);
132 BTM_DeregisterAclCallbacks(&pimpl->btmAclCallbacks_);
133 pimpl->powerDevices_.clear();
134 }
135
StatusUpdate(const RequestStatus status,const std::string & profileName,const RawAddress & addr) const136 void PowerManager::StatusUpdate(
137 const RequestStatus status, const std::string &profileName, const RawAddress &addr) const
138 {
139 HILOGI("profileName: %{public}s, status: %{public}u, addr: %{public}s", profileName.c_str(), status,
140 GetEncryptAddr(addr.GetAddress()).c_str());
141
142 if (pimpl->isEnabled_) {
143 pimpl->dispatcher_.PostTask(
144 std::bind(&PowerManager::impl::PowerProcess, pimpl.get(), status, profileName, addr));
145 }
146 }
147
GetPowerMode(const RawAddress & addr) const148 BTPowerMode PowerManager::GetPowerMode(const RawAddress &addr) const
149 {
150 std::unique_lock<std::mutex> lock(pimpl->mutex_);
151 auto iter = pimpl->powerDevices_.find(addr);
152 if (iter != pimpl->powerDevices_.end()) {
153 return iter->second->GetPowerMode();
154 }
155 return BTPowerMode::MODE_INVALID;
156 }
157
PowerProcess(const RequestStatus status,const std::string & profileName,const RawAddress rawAddr)158 void PowerManager::impl::PowerProcess(
159 const RequestStatus status, const std::string &profileName, const RawAddress rawAddr)
160 {
161 HILOGI("status: %{public}u, profileName: %{public}s", status, profileName.c_str());
162 std::unique_lock<std::mutex> lock(mutex_);
163 UpdatePowerDevicesInfo(rawAddr, profileName, status);
164 auto iter = powerDevices_.find(rawAddr);
165 if (iter != powerDevices_.end()) {
166 iter->second->SetPowerMode();
167 }
168 }
169
UpdatePowerDevicesInfo(const RawAddress rawAddr,const std::string & profileName,const RequestStatus status)170 void PowerManager::impl::UpdatePowerDevicesInfo(
171 const RawAddress rawAddr, const std::string &profileName, const RequestStatus status)
172 {
173 auto iter = powerDevices_.find(rawAddr);
174 if (iter == powerDevices_.end()) {
175 LOG_DEBUG("PM_: UpdatePowerDevicesInfo(), create powerDevices\n");
176 powerDevices_[rawAddr] = std::make_shared<PowerDevice>(rawAddr, dispatcher_);
177 }
178
179 if (status == RequestStatus::CONNECT_OFF) {
180 auto its = powerDevices_.find(rawAddr);
181 if (its != powerDevices_.end()) {
182 its->second->DeleteRequestPower(profileName);
183 }
184 } else {
185 LOG_DEBUG("PM_:: UpdatePowerDevicesInfo(), execute SetRequesetPower()\n");
186 powerDevices_[rawAddr]->SetRequestPower(profileName, status);
187 }
188 }
189
ModeChangeCallBackProcess(uint8_t status,const RawAddress rawAddr,uint8_t currentMode,uint16_t interval)190 void PowerManager::impl::ModeChangeCallBackProcess(
191 uint8_t status, const RawAddress rawAddr, uint8_t currentMode, uint16_t interval)
192 {
193 LOG_DEBUG("PM_: %{public}s start, status: %u, currentMode: %u, interval: %u, line: %{public}d\n",
194 __FUNCTION__,
195 status,
196 currentMode,
197 interval,
198 __LINE__);
199 std::unique_lock<std::mutex> lock(mutex_);
200 auto iter = powerDevices_.find(rawAddr);
201 if (iter == powerDevices_.end()) {
202 if (status != 0) {
203 LOG_DEBUG("PM_: ModeChangeCallBackProcess(), no need to create powerDevices for error status\n");
204 return;
205 }
206 LOG_DEBUG("PM_: ModeChangeCallBackProcess(), create powerDevices\n");
207 powerDevices_[rawAddr] = std::make_shared<PowerDevice>(rawAddr, dispatcher_);
208 }
209 powerDevices_[rawAddr]->ModeChangeCallBack(status, currentMode, interval);
210 }
211
ModeChangeCallBack(uint8_t status,const BtAddr * btAddr,uint8_t currentMode,uint16_t interval,void * context)212 void PowerManager::impl::ModeChangeCallBack(
213 uint8_t status, const BtAddr *btAddr, uint8_t currentMode, uint16_t interval, void *context)
214 {
215 RawAddress rawAddr = bluetooth::RawAddress::ConvertToString(btAddr->addr);
216 static_cast<PowerManager*>(context)
217 ->pimpl->dispatcher_.PostTask(std::bind(&PowerManager::impl::ModeChangeCallBackProcess,
218 static_cast<PowerManager*>(context)->pimpl.get(),
219 status,
220 rawAddr,
221 currentMode,
222 interval));
223 }
224
SsrCompleteCallBackProcess(uint8_t status,const RawAddress rawAddr)225 void PowerManager::impl::SsrCompleteCallBackProcess(uint8_t status, const RawAddress rawAddr)
226 {
227 LOG_DEBUG("PM_: %{public}s start, status: %u, line: %{public}d\n", __FUNCTION__, status, __LINE__);
228 std::unique_lock<std::mutex> lock(mutex_);
229 auto iter = powerDevices_.find(rawAddr);
230 if (iter != powerDevices_.end()) {
231 iter->second->SniffSubratingCompleteCallback(status);
232 }
233 }
234
SsrCompleteCallBack(uint8_t status,const BtAddr * btAddr,void * context)235 void PowerManager::impl::SsrCompleteCallBack(uint8_t status, const BtAddr *btAddr, void *context)
236 {
237 RawAddress rawAddr = bluetooth::RawAddress::ConvertToString(btAddr->addr);
238 static_cast<PowerManager*>(context)
239 ->pimpl->dispatcher_.PostTask(std::bind(
240 &PowerManager::impl::SsrCompleteCallBackProcess, static_cast<PowerManager*>(context)->pimpl.get(), status, rawAddr));
241 }
242
ConnectionCompleteCallBackProcess(const RawAddress rawAddr,uint16_t connectionHandle)243 void PowerManager::impl::ConnectionCompleteCallBackProcess(const RawAddress rawAddr, uint16_t connectionHandle)
244 {
245 HILOGI("addr: %{public}s", GetEncryptAddr(rawAddr.GetAddress()).c_str());
246 // construct
247 std::unique_lock<std::mutex> lock(mutex_);
248 auto iter = powerDevices_.find(rawAddr);
249 if (iter == powerDevices_.end()) {
250 LOG_DEBUG("PM_: ConnectionCompleteCallBackProcess(), create powerDevices\n");
251 powerDevices_[rawAddr] = std::make_shared<PowerDevice>(rawAddr, dispatcher_);
252 }
253 connectionHandles_[connectionHandle] = rawAddr;
254 }
255
ConnectionCompleteCallBack(const BtmAclConnectCompleteParam * param,void * context)256 void PowerManager::impl::ConnectionCompleteCallBack(const BtmAclConnectCompleteParam *param, void *context)
257 {
258 RawAddress rawAddr = bluetooth::RawAddress::ConvertToString(param->addr->addr);
259 uint16_t connectionHandle = param->connectionHandle;
260 static_cast<PowerManager*>(context)
261 ->pimpl->dispatcher_.PostTask(std::bind(&PowerManager::impl::ConnectionCompleteCallBackProcess,
262 static_cast<PowerManager*>(context)->pimpl.get(),
263 rawAddr,
264 connectionHandle));
265 }
266
DisconnectionCompleteCallBackProcess(uint8_t status,uint16_t connectionHandle,uint8_t reason)267 void PowerManager::impl::DisconnectionCompleteCallBackProcess(uint8_t status, uint16_t connectionHandle, uint8_t reason)
268 {
269 LOG_DEBUG("PM_: DisconnectionCompleteCallBackProcess(), status=%u, reason=%u\n", status, reason);
270 // destruct
271 if (status == 0) {
272 std::unique_lock<std::mutex> lock(mutex_);
273 auto iter = connectionHandles_.find(connectionHandle);
274 if (iter != connectionHandles_.end()) {
275 auto its = powerDevices_.find(iter->second);
276 if (its != powerDevices_.end()) {
277 powerDevices_.erase(its);
278 }
279 HILOGI("delete powerDevices, addr: %{public}s", GetEncryptAddr(iter->second.GetAddress()).c_str());
280 connectionHandles_.erase(iter);
281 }
282 }
283 }
284
DisconnectionCompleteCallBack(uint8_t status,uint16_t connectionHandle,uint8_t reason,void * context)285 void PowerManager::impl::DisconnectionCompleteCallBack(
286 uint8_t status, uint16_t connectionHandle, uint8_t reason, void *context)
287 {
288 static_cast<PowerManager*>(context)
289 ->pimpl->dispatcher_.PostTask(std::bind(&PowerManager::impl::DisconnectionCompleteCallBackProcess,
290 static_cast<PowerManager*>(context)->pimpl.get(),
291 status,
292 connectionHandle,
293 reason));
294 }
295 } // namespace bluetooth
296 } // namespace OHOS