1 /******************************************************************************
2 *
3 * Copyright 2000-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /*****************************************************************************
20 *
21 * This file contains functions that manages ACL link modes.
22 * This includes operations such as active, hold,
23 * park and sniff modes.
24 *
25 * This module contains both internal and external (API)
26 * functions. External (API) functions are distinguishable
27 * by their names beginning with uppercase BTM.
28 *
29 *****************************************************************************/
30
31 #define LOG_TAG "bt_btm_pm"
32
33 #include <base/strings/stringprintf.h>
34 #include <cstdint>
35 #include <unordered_map>
36
37 #include "bt_target.h"
38 #include "device/include/controller.h"
39 #include "device/include/interop.h"
40 #include "main/shim/dumpsys.h"
41 #include "main/shim/link_policy.h"
42 #include "main/shim/shim.h"
43 #include "osi/include/log.h"
44 #include "stack/btm/btm_int_types.h"
45 #include "stack/include/btm_api.h"
46 #include "stack/include/btm_api_types.h"
47 #include "stack/include/btm_status.h"
48 #include "types/raw_address.h"
49
50 void l2c_OnHciModeChangeSendPendingPackets(RawAddress remote);
51 void btm_sco_chk_pend_unpark(tHCI_STATUS status, uint16_t handle);
52 void btm_cont_rswitch_from_handle(uint16_t hci_handle);
53 extern tBTM_CB btm_cb;
54
55 namespace {
56 uint16_t pm_pend_link = 0;
57
58 std::unordered_map<uint16_t /* handle */, tBTM_PM_MCB> pm_mode_db;
59
btm_pm_get_power_manager_from_address(const RawAddress & bda)60 tBTM_PM_MCB* btm_pm_get_power_manager_from_address(const RawAddress& bda) {
61 for (auto& entry : pm_mode_db) {
62 if (entry.second.bda_ == bda) {
63 return &entry.second;
64 }
65 }
66 return nullptr;
67 }
68
69 tBTM_PM_RCB pm_reg_db; /* per application/module */
70
71 uint8_t pm_pend_id = 0; /* the id pf the module, which has a pending PM cmd */
72
73 constexpr char kBtmLogTag[] = "ACL";
74 }
75
76 /*****************************************************************************/
77 /* to handle different modes */
78 /*****************************************************************************/
79 #define BTM_PM_NUM_SET_MODES 3 /* only hold, sniff & park */
80
81 #define BTM_PM_GET_MD1 1
82 #define BTM_PM_GET_MD2 2
83 #define BTM_PM_GET_COMP 3
84
85 const uint8_t
86 btm_pm_md_comp_matrix[BTM_PM_NUM_SET_MODES * BTM_PM_NUM_SET_MODES] = {
87 BTM_PM_GET_COMP, BTM_PM_GET_MD2, BTM_PM_GET_MD2,
88
89 BTM_PM_GET_MD1, BTM_PM_GET_COMP, BTM_PM_GET_MD1,
90
91 BTM_PM_GET_MD1, BTM_PM_GET_MD2, BTM_PM_GET_COMP};
92
send_sniff_subrating(uint16_t handle,const RawAddress & addr,uint16_t max_lat,uint16_t min_rmt_to,uint16_t min_loc_to)93 static void send_sniff_subrating(uint16_t handle, const RawAddress& addr,
94 uint16_t max_lat, uint16_t min_rmt_to,
95 uint16_t min_loc_to) {
96 btsnd_hcic_sniff_sub_rate(handle, max_lat, min_rmt_to, min_loc_to);
97 BTM_LogHistory(kBtmLogTag, addr, "Sniff subrating",
98 base::StringPrintf(
99 "max_latency:%.2f peer_timeout:%.2f local_timeout:%.2f",
100 ticks_to_seconds(max_lat), ticks_to_seconds(min_rmt_to),
101 ticks_to_seconds(min_loc_to)));
102 }
103
104 static tBTM_STATUS btm_pm_snd_md_req(uint16_t handle, uint8_t pm_id,
105 int link_ind,
106 const tBTM_PM_PWR_MD* p_mode);
107
108 /*****************************************************************************/
109 /* P U B L I C F U N C T I O N S */
110 /*****************************************************************************/
111 /*******************************************************************************
112 *
113 * Function BTM_PmRegister
114 *
115 * Description register or deregister with power manager
116 *
117 * Returns BTM_SUCCESS if successful,
118 * BTM_NO_RESOURCES if no room to hold registration
119 * BTM_ILLEGAL_VALUE
120 *
121 ******************************************************************************/
BTM_PmRegister(uint8_t mask,uint8_t * p_pm_id,tBTM_PM_STATUS_CBACK * p_cb)122 tBTM_STATUS BTM_PmRegister(uint8_t mask, uint8_t* p_pm_id,
123 tBTM_PM_STATUS_CBACK* p_cb) {
124 if (bluetooth::shim::is_gd_link_policy_enabled()) {
125 ASSERT(p_pm_id != nullptr);
126 ASSERT(p_cb != nullptr);
127 if (mask & BTM_PM_DEREG) {
128 return (bluetooth::shim::UnregisterLinkPolicyClient(p_cb))
129 ? (BTM_SUCCESS)
130 : (BTM_NO_RESOURCES);
131 } else {
132 *p_pm_id = 0;
133 return (bluetooth::shim::RegisterLinkPolicyClient(p_cb))
134 ? (BTM_SUCCESS)
135 : (BTM_NO_RESOURCES);
136 }
137 }
138
139 /* de-register */
140 if (mask & BTM_PM_DEREG) {
141 if (*p_pm_id >= BTM_MAX_PM_RECORDS) return BTM_ILLEGAL_VALUE;
142 pm_reg_db.mask = BTM_PM_REC_NOT_USED;
143 return BTM_SUCCESS;
144 }
145
146 if (pm_reg_db.mask == BTM_PM_REC_NOT_USED) {
147 /* if register for notification, should provide callback routine */
148 if (p_cb == NULL) return BTM_ILLEGAL_VALUE;
149 pm_reg_db.cback = p_cb;
150 pm_reg_db.mask = mask;
151 *p_pm_id = 0;
152 return BTM_SUCCESS;
153 }
154
155 return BTM_NO_RESOURCES;
156 }
157
BTM_PM_OnConnected(uint16_t handle,const RawAddress & remote_bda)158 void BTM_PM_OnConnected(uint16_t handle, const RawAddress& remote_bda) {
159 pm_mode_db[handle] = {};
160 pm_mode_db[handle].Init(remote_bda, handle);
161 }
162
BTM_PM_OnDisconnected(uint16_t handle)163 void BTM_PM_OnDisconnected(uint16_t handle) {
164 pm_mode_db.erase(handle);
165 if (handle == pm_pend_link) {
166 pm_pend_link = 0;
167 }
168 }
169
170 /*******************************************************************************
171 *
172 * Function BTM_SetPowerMode
173 *
174 * Description store the mode in control block or
175 * alter ACL connection behavior.
176 *
177 * Returns BTM_SUCCESS if successful,
178 * BTM_UNKNOWN_ADDR if bd addr is not active or bad
179 *
180 ******************************************************************************/
BTM_SetPowerMode(uint8_t pm_id,const RawAddress & remote_bda,const tBTM_PM_PWR_MD * p_mode)181 tBTM_STATUS BTM_SetPowerMode(uint8_t pm_id, const RawAddress& remote_bda,
182 const tBTM_PM_PWR_MD* p_mode) {
183 if (pm_id >= BTM_MAX_PM_RECORDS) {
184 pm_id = BTM_PM_SET_ONLY_ID;
185 }
186
187 if (!p_mode) {
188 LOG_ERROR("pm_id: %u, p_mode is null for %s", unsigned(pm_id),
189 PRIVATE_ADDRESS(remote_bda));
190 return BTM_ILLEGAL_VALUE;
191 }
192
193 // per ACL link
194 auto* p_cb = btm_pm_get_power_manager_from_address(remote_bda);
195 if (p_cb == nullptr) {
196 LOG_WARN("Unable to find power manager for peer: %s",
197 PRIVATE_ADDRESS(remote_bda));
198 return BTM_UNKNOWN_ADDR;
199 }
200 uint16_t handle = p_cb->handle_;
201
202 tBTM_PM_MODE mode = p_mode->mode;
203 if (!is_legal_power_mode(mode)) {
204 LOG_ERROR("Unable to set illegal power mode value:0x%02x", mode);
205 return BTM_ILLEGAL_VALUE;
206 }
207
208 if (p_mode->mode & BTM_PM_MD_FORCE) {
209 LOG_INFO("Attempting to force into this power mode");
210 /* take out the force bit */
211 mode &= (~BTM_PM_MD_FORCE);
212 }
213
214 if (bluetooth::shim::is_gd_link_policy_enabled()) {
215 tBTM_PM_PWR_MD power_mode_request = *p_mode;
216 power_mode_request.mode &= (~BTM_PM_MD_FORCE);
217 return bluetooth::shim::BTM_SetPowerMode(handle, power_mode_request);
218 }
219
220 if (mode != BTM_PM_MD_ACTIVE) {
221 const controller_t* controller = controller_get_interface();
222 if ((mode == BTM_PM_MD_HOLD && !controller->supports_hold_mode()) ||
223 (mode == BTM_PM_MD_SNIFF && !controller->supports_sniff_mode()) ||
224 (mode == BTM_PM_MD_PARK && !controller->supports_park_mode()) ||
225 interop_match_addr(INTEROP_DISABLE_SNIFF, &remote_bda)) {
226 LOG_ERROR("pm_id %u mode %u is not supported for %s", pm_id, mode,
227 PRIVATE_ADDRESS(remote_bda));
228 return BTM_MODE_UNSUPPORTED;
229 }
230 }
231
232 if (mode == p_cb->state) {
233 /* already in the requested mode and the current interval has less latency
234 * than the max */
235 if ((mode == BTM_PM_MD_ACTIVE) ||
236 ((p_mode->mode & BTM_PM_MD_FORCE) && (p_mode->max >= p_cb->interval) &&
237 (p_mode->min <= p_cb->interval)) ||
238 ((p_mode->mode & BTM_PM_MD_FORCE) == 0 &&
239 (p_mode->max >= p_cb->interval))) {
240 LOG_INFO(
241 "Device is already in requested mode %d, interval: %d, max: %d, min: "
242 "%d",
243 p_mode->mode, p_cb->interval, p_mode->max, p_mode->min);
244 return BTM_SUCCESS;
245 }
246 }
247
248 int temp_pm_id = pm_id;
249 if (pm_id == BTM_PM_SET_ONLY_ID) {
250 temp_pm_id = BTM_MAX_PM_RECORDS;
251 }
252
253 /* update mode database */
254 if (((pm_id != BTM_PM_SET_ONLY_ID) && (pm_reg_db.mask & BTM_PM_REG_SET)) ||
255 ((pm_id == BTM_PM_SET_ONLY_ID) && (pm_pend_link != 0))) {
256 /* Make sure mask is set to BTM_PM_REG_SET */
257 pm_reg_db.mask |= BTM_PM_REG_SET;
258 *(&p_cb->req_mode) = *p_mode;
259 p_cb->chg_ind = true;
260 }
261
262 /* if mode == hold or pending, return */
263 if ((p_cb->state == BTM_PM_STS_HOLD) || (p_cb->state == BTM_PM_STS_PENDING) ||
264 (pm_pend_link != 0)) {
265 LOG_INFO(
266 "Current power mode is hold or pending status or pending links"
267 " state:%s[%hhu] pm_pending_link:%hu",
268 power_mode_state_text(p_cb->state).c_str(), p_cb->state, pm_pend_link);
269 /* command pending */
270 if (handle != pm_pend_link) {
271 p_cb->state |= BTM_PM_STORED_MASK;
272 LOG_INFO("Setting stored bitmask for peer:%s",
273 PRIVATE_ADDRESS(remote_bda));
274 }
275 return BTM_CMD_STORED;
276 }
277
278 LOG_INFO(
279 "Setting power mode for peer:%s current_mode:%s[%hhu] new_mode:%s[%hhu]",
280 PRIVATE_ADDRESS(remote_bda), power_mode_state_text(p_cb->state).c_str(),
281 p_cb->state, power_mode_text(p_mode->mode).c_str(), p_mode->mode);
282
283 return btm_pm_snd_md_req(p_cb->handle_, pm_id, p_cb->handle_, p_mode);
284 }
285
BTM_SetLinkPolicyActiveMode(const RawAddress & remote_bda)286 bool BTM_SetLinkPolicyActiveMode(const RawAddress& remote_bda) {
287 tBTM_PM_PWR_MD settings;
288 memset((void*)&settings, 0, sizeof(settings));
289 settings.mode = BTM_PM_MD_ACTIVE;
290
291 switch (BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, remote_bda, &settings)) {
292 case BTM_CMD_STORED:
293 case BTM_SUCCESS:
294 return true;
295 default:
296 return false;
297 }
298 }
299
BTM_ReadPowerMode(const RawAddress & remote_bda,tBTM_PM_MODE * p_mode)300 bool BTM_ReadPowerMode(const RawAddress& remote_bda, tBTM_PM_MODE* p_mode) {
301 if (p_mode == nullptr) {
302 LOG_ERROR("power mode is nullptr");
303 return false;
304 }
305 tBTM_PM_MCB* p_mcb = btm_pm_get_power_manager_from_address(remote_bda);
306 if (p_mcb == nullptr) {
307 LOG_WARN("Unknown device:%s", PRIVATE_ADDRESS(remote_bda));
308 return false;
309 }
310 *p_mode = static_cast<tBTM_PM_MODE>(p_mcb->state);
311 return true;
312 }
313
314 /*******************************************************************************
315 *
316 * Function BTM_SetSsrParams
317 *
318 * Description This sends the given SSR parameters for the given ACL
319 * connection if it is in ACTIVE mode.
320 *
321 * Input Param remote_bda - device address of desired ACL connection
322 * max_lat - maximum latency (in 0.625ms)(0-0xFFFE)
323 * min_rmt_to - minimum remote timeout
324 * min_loc_to - minimum local timeout
325 *
326 *
327 * Returns BTM_SUCCESS if the HCI command is issued successful,
328 * BTM_UNKNOWN_ADDR if bd addr is not active or bad
329 * BTM_CMD_STORED if the command is stored
330 *
331 ******************************************************************************/
BTM_SetSsrParams(const RawAddress & remote_bda,uint16_t max_lat,uint16_t min_rmt_to,uint16_t min_loc_to)332 tBTM_STATUS BTM_SetSsrParams(const RawAddress& remote_bda, uint16_t max_lat,
333 uint16_t min_rmt_to, uint16_t min_loc_to) {
334 tBTM_PM_MCB* p_cb = btm_pm_get_power_manager_from_address(remote_bda);
335 if (p_cb == nullptr) {
336 LOG_WARN("Unable to find power manager for peer:%s",
337 PRIVATE_ADDRESS(remote_bda));
338 return BTM_UNKNOWN_ADDR;
339 }
340
341 if (bluetooth::shim::is_gd_link_policy_enabled()) {
342 return bluetooth::shim::BTM_SetSsrParams(p_cb->handle_, max_lat, min_rmt_to,
343 min_loc_to);
344 }
345
346 if (p_cb->state == BTM_PM_ST_ACTIVE || p_cb->state == BTM_PM_ST_SNIFF) {
347 LOG_INFO(
348 "Set sniff subrating state:%s[%d] max_latency:0x%04x "
349 "min_remote_timeout:0x%04x"
350 " min_local_timeout:0x%04x",
351 power_mode_state_text(p_cb->state).c_str(), p_cb->state, max_lat,
352 min_rmt_to, min_loc_to);
353 send_sniff_subrating(p_cb->handle_, remote_bda, max_lat, min_rmt_to,
354 min_loc_to);
355 return BTM_SUCCESS;
356 }
357 LOG_INFO("pm_mode_db state: %d", p_cb->state);
358 p_cb->max_lat = max_lat;
359 p_cb->min_rmt_to = min_rmt_to;
360 p_cb->min_loc_to = min_loc_to;
361 return BTM_CMD_STORED;
362 }
363
364 /*******************************************************************************
365 *
366 * Function btm_pm_reset
367 *
368 * Description as a part of the BTM reset process.
369 *
370 * Returns void
371 *
372 ******************************************************************************/
btm_pm_reset(void)373 void btm_pm_reset(void) {
374 tBTM_PM_STATUS_CBACK* cb = NULL;
375
376 /* clear the pending request for application */
377 if ((pm_pend_id != BTM_PM_SET_ONLY_ID) && (pm_reg_db.mask & BTM_PM_REG_SET)) {
378 cb = pm_reg_db.cback;
379 }
380
381 pm_reg_db.mask = BTM_PM_REC_NOT_USED;
382
383 if (cb != NULL && pm_pend_link != 0) {
384 const RawAddress raw_address = pm_mode_db[pm_pend_link].bda_;
385 (*cb)(raw_address, BTM_PM_STS_ERROR, BTM_DEV_RESET, HCI_SUCCESS);
386 }
387 /* no command pending */
388 pm_pend_link = 0;
389 pm_mode_db.clear();
390 pm_pend_id = 0;
391 memset(&pm_reg_db, 0, sizeof(pm_reg_db));
392 LOG_INFO("reset pm");
393 }
394
395 /*******************************************************************************
396 *
397 * Function btm_pm_compare_modes
398 * Description get the "more active" mode of the 2
399 * Returns void
400 *
401 ******************************************************************************/
btm_pm_compare_modes(const tBTM_PM_PWR_MD * p_md1,const tBTM_PM_PWR_MD * p_md2,tBTM_PM_PWR_MD * p_res)402 static tBTM_PM_PWR_MD* btm_pm_compare_modes(const tBTM_PM_PWR_MD* p_md1,
403 const tBTM_PM_PWR_MD* p_md2,
404 tBTM_PM_PWR_MD* p_res) {
405 uint8_t res;
406
407 if (p_md1 == NULL) {
408 *p_res = *p_md2;
409 p_res->mode &= ~BTM_PM_MD_FORCE;
410
411 return p_res;
412 }
413
414 if (p_md2->mode == BTM_PM_MD_ACTIVE || p_md1->mode == BTM_PM_MD_ACTIVE) {
415 return NULL;
416 }
417
418 /* check if force bit is involved */
419 if (p_md1->mode & BTM_PM_MD_FORCE) {
420 *p_res = *p_md1;
421 p_res->mode &= ~BTM_PM_MD_FORCE;
422 return p_res;
423 }
424
425 if (p_md2->mode & BTM_PM_MD_FORCE) {
426 *p_res = *p_md2;
427 p_res->mode &= ~BTM_PM_MD_FORCE;
428 return p_res;
429 }
430
431 res = (p_md1->mode - 1) * BTM_PM_NUM_SET_MODES + (p_md2->mode - 1);
432 res = btm_pm_md_comp_matrix[res];
433 switch (res) {
434 case BTM_PM_GET_MD1:
435 *p_res = *p_md1;
436 return p_res;
437
438 case BTM_PM_GET_MD2:
439 *p_res = *p_md2;
440 return p_res;
441
442 case BTM_PM_GET_COMP:
443 p_res->mode = p_md1->mode;
444 /* min of the two */
445 p_res->max = (p_md1->max < p_md2->max) ? (p_md1->max) : (p_md2->max);
446 /* max of the two */
447 p_res->min = (p_md1->min > p_md2->min) ? (p_md1->min) : (p_md2->min);
448
449 /* the intersection is NULL */
450 if (p_res->max < p_res->min) return NULL;
451
452 if (p_res->mode == BTM_PM_MD_SNIFF) {
453 /* max of the two */
454 p_res->attempt = (p_md1->attempt > p_md2->attempt) ? (p_md1->attempt)
455 : (p_md2->attempt);
456 p_res->timeout = (p_md1->timeout > p_md2->timeout) ? (p_md1->timeout)
457 : (p_md2->timeout);
458 }
459 return p_res;
460 }
461 return NULL;
462 }
463
464 /*******************************************************************************
465 *
466 * Function btm_pm_get_set_mode
467 * Description get the resulting mode from the registered parties, then compare
468 * it with the requested mode, if the command is from an
469 * unregistered party.
470 *
471 * Returns void
472 *
473 ******************************************************************************/
btm_pm_get_set_mode(uint8_t pm_id,tBTM_PM_MCB * p_cb,const tBTM_PM_PWR_MD * p_mode,tBTM_PM_PWR_MD * p_res)474 static tBTM_PM_MODE btm_pm_get_set_mode(uint8_t pm_id, tBTM_PM_MCB* p_cb,
475 const tBTM_PM_PWR_MD* p_mode,
476 tBTM_PM_PWR_MD* p_res) {
477 tBTM_PM_PWR_MD* p_md = NULL;
478
479 if (p_mode != NULL && p_mode->mode & BTM_PM_MD_FORCE) {
480 *p_res = *p_mode;
481 p_res->mode &= ~BTM_PM_MD_FORCE;
482 return p_res->mode;
483 }
484
485 /* g through all the registered "set" parties */
486 if (pm_reg_db.mask & BTM_PM_REG_SET) {
487 if (p_cb->req_mode.mode == BTM_PM_MD_ACTIVE) {
488 /* if at least one registered (SET) party says ACTIVE, stay active */
489 return BTM_PM_MD_ACTIVE;
490 } else {
491 /* if registered parties give conflicting information, stay active */
492 if ((btm_pm_compare_modes(p_md, &p_cb->req_mode, p_res)) == NULL)
493 return BTM_PM_MD_ACTIVE;
494 p_md = p_res;
495 }
496 }
497
498 /* if the resulting mode is NULL(nobody registers SET), use the requested mode
499 */
500 if (p_md == NULL) {
501 if (p_mode)
502 *p_res = *((tBTM_PM_PWR_MD*)p_mode);
503 else /* p_mode is NULL when btm_pm_snd_md_req is called from
504 btm_pm_proc_mode_change */
505 return BTM_PM_MD_ACTIVE;
506 } else {
507 /* if the command is from unregistered party,
508 compare the resulting mode from registered party*/
509 if ((pm_id == BTM_PM_SET_ONLY_ID) &&
510 ((btm_pm_compare_modes(p_mode, p_md, p_res)) == NULL))
511 return BTM_PM_MD_ACTIVE;
512 }
513
514 return p_res->mode;
515 }
516
517 /*******************************************************************************
518 *
519 * Function btm_pm_snd_md_req
520 * Description get the resulting mode and send the resuest to host controller
521 * Returns tBTM_STATUS
522 *, bool *p_chg_ind
523 ******************************************************************************/
btm_pm_snd_md_req(uint16_t handle,uint8_t pm_id,int link_ind,const tBTM_PM_PWR_MD * p_mode)524 static tBTM_STATUS btm_pm_snd_md_req(uint16_t handle, uint8_t pm_id,
525 int link_ind,
526 const tBTM_PM_PWR_MD* p_mode) {
527 ASSERT_LOG(pm_mode_db.count(handle) != 0,
528 "Unable to find active acl for handle %d", handle);
529 tBTM_PM_PWR_MD md_res;
530 tBTM_PM_MODE mode;
531 tBTM_PM_MCB* p_cb = &pm_mode_db[handle];
532 bool chg_ind = false;
533
534 mode = btm_pm_get_set_mode(pm_id, p_cb, p_mode, &md_res);
535 md_res.mode = mode;
536
537 LOG_DEBUG("Found controller in mode:%s", power_mode_text(mode).c_str());
538
539 if (p_cb->state == mode) {
540 LOG_INFO(
541 "Link already in requested mode pm_id:%hhu link_ind:%d mode:%s[%hhu]",
542 pm_id, link_ind, power_mode_text(mode).c_str(), mode);
543
544 /* already in the resulting mode */
545 if ((mode == BTM_PM_MD_ACTIVE) ||
546 ((md_res.max >= p_cb->interval) && (md_res.min <= p_cb->interval))) {
547 LOG_DEBUG("Storing command");
548 return BTM_CMD_STORED;
549 }
550 LOG_DEBUG("Need to wake then sleep");
551 chg_ind = true;
552 }
553 p_cb->chg_ind = chg_ind;
554
555 /* cannot go directly from current mode to resulting mode. */
556 if (mode != BTM_PM_MD_ACTIVE && p_cb->state != BTM_PM_MD_ACTIVE) {
557 LOG_DEBUG("Power mode change delay required");
558 p_cb->chg_ind = true; /* needs to wake, then sleep */
559 }
560
561 if (p_cb->chg_ind) {
562 LOG_DEBUG("Need to wake first");
563 md_res.mode = BTM_PM_MD_ACTIVE;
564 } else if (BTM_PM_MD_SNIFF == md_res.mode && p_cb->max_lat) {
565 LOG_DEBUG("Sending sniff subrating to controller");
566 send_sniff_subrating(handle, p_cb->bda_, p_cb->max_lat, p_cb->min_rmt_to,
567 p_cb->min_loc_to);
568 p_cb->max_lat = 0;
569 }
570 /* Default is failure */
571 pm_pend_link = 0;
572
573 /* send the appropriate HCI command */
574 pm_pend_id = pm_id;
575
576 LOG_INFO("Switching from %s[0x%02x] to %s[0x%02x]",
577 power_mode_state_text(p_cb->state).c_str(), p_cb->state,
578 power_mode_state_text(md_res.mode).c_str(), md_res.mode);
579 BTM_LogHistory(kBtmLogTag, p_cb->bda_, "Power mode change",
580 base::StringPrintf(
581 "%s[0x%02x] ==> %s[0x%02x]",
582 power_mode_state_text(p_cb->state).c_str(), p_cb->state,
583 power_mode_state_text(md_res.mode).c_str(), md_res.mode));
584
585 switch (md_res.mode) {
586 case BTM_PM_MD_ACTIVE:
587 switch (p_cb->state) {
588 case BTM_PM_MD_SNIFF:
589 btsnd_hcic_exit_sniff_mode(handle);
590 pm_pend_link = handle;
591 break;
592 case BTM_PM_MD_PARK:
593 btsnd_hcic_exit_park_mode(handle);
594 pm_pend_link = handle;
595 break;
596 default:
597 /* Failure pm_pend_link = MAX_L2CAP_LINKS */
598 break;
599 }
600 break;
601
602 case BTM_PM_MD_HOLD:
603 btsnd_hcic_hold_mode(handle, md_res.max, md_res.min);
604 pm_pend_link = handle;
605 break;
606
607 case BTM_PM_MD_SNIFF:
608 btsnd_hcic_sniff_mode(handle, md_res.max, md_res.min, md_res.attempt,
609 md_res.timeout);
610 pm_pend_link = handle;
611 break;
612
613 case BTM_PM_MD_PARK:
614 btsnd_hcic_park_mode(handle, md_res.max, md_res.min);
615 pm_pend_link = handle;
616 break;
617 default:
618 /* Failure pm_pend_link = MAX_L2CAP_LINKS */
619 break;
620 }
621
622 if (pm_pend_link == 0) {
623 /* the command was not sent */
624 LOG_ERROR("pm_pending_link maxed out");
625 return (BTM_NO_RESOURCES);
626 }
627
628 return BTM_CMD_STARTED;
629 }
630
btm_pm_continue_pending_mode_changes()631 static void btm_pm_continue_pending_mode_changes() {
632 for (auto& entry : pm_mode_db) {
633 if (entry.second.state & BTM_PM_STORED_MASK) {
634 entry.second.state &= ~BTM_PM_STORED_MASK;
635 LOG_INFO("Found another link requiring power mode change:%s",
636 PRIVATE_ADDRESS(entry.second.bda_));
637 btm_pm_snd_md_req(entry.second.handle_, BTM_PM_SET_ONLY_ID,
638 entry.second.handle_, NULL);
639 return;
640 }
641 }
642 }
643
644 /*******************************************************************************
645 *
646 * Function btm_pm_proc_cmd_status
647 *
648 * Description This function is called when an HCI command status event
649 * occurs for power manager related commands.
650 *
651 * Input Parms status - status of the event (HCI_SUCCESS if no errors)
652 *
653 * Returns none.
654 *
655 ******************************************************************************/
btm_pm_proc_cmd_status(tHCI_STATUS status)656 void btm_pm_proc_cmd_status(tHCI_STATUS status) {
657 if (pm_pend_link == 0) {
658 LOG_ERROR(
659 "There are no links pending power mode changes; try to find other "
660 "pending changes");
661 btm_pm_continue_pending_mode_changes();
662 return;
663 }
664 if (pm_mode_db.count(pm_pend_link) == 0) {
665 LOG_ERROR(
666 "Got PM change status for disconnected link %d; forgot to clean up "
667 "pm_pend_link?",
668 pm_pend_link);
669 btm_pm_continue_pending_mode_changes();
670 return;
671 }
672
673 tBTM_PM_MCB* p_cb = &pm_mode_db[pm_pend_link];
674
675 // if the command was not successful. Stay in the same state
676 tBTM_PM_STATUS pm_status = BTM_PM_STS_ERROR;
677
678 if (status == HCI_SUCCESS) {
679 p_cb->state = BTM_PM_ST_PENDING;
680 pm_status = BTM_PM_STS_PENDING;
681 }
682
683 /* notify the caller is appropriate */
684 if ((pm_pend_id != BTM_PM_SET_ONLY_ID) && (pm_reg_db.mask & BTM_PM_REG_SET)) {
685 const RawAddress bd_addr = pm_mode_db[pm_pend_link].bda_;
686 LOG_DEBUG("Notifying callback that link power mode is complete peer:%s",
687 PRIVATE_ADDRESS(bd_addr));
688 (*pm_reg_db.cback)(bd_addr, pm_status, 0, status);
689 }
690
691 LOG_INFO("Clearing pending power mode link state:%s",
692 power_mode_state_text(p_cb->state).c_str());
693 pm_pend_link = 0;
694
695 btm_pm_continue_pending_mode_changes();
696 }
697
698 /*******************************************************************************
699 *
700 * Function btm_process_mode_change
701 *
702 * Description This function is called when an HCI mode change event
703 * occurs.
704 *
705 * Input Parms hci_status - status of the event (HCI_SUCCESS if no errors)
706 * hci_handle - connection handle associated with the change
707 * mode - HCI_MODE_ACTIVE, HCI_MODE_HOLD, HCI_MODE_SNIFF, or
708 * HCI_MODE_PARK
709 * interval - number of baseband slots (meaning depends on
710 * mode)
711 *
712 * Returns none.
713 *
714 ******************************************************************************/
btm_pm_proc_mode_change(tHCI_STATUS hci_status,uint16_t hci_handle,tHCI_MODE hci_mode,uint16_t interval)715 void btm_pm_proc_mode_change(tHCI_STATUS hci_status, uint16_t hci_handle,
716 tHCI_MODE hci_mode, uint16_t interval) {
717 tBTM_PM_STATUS mode = static_cast<tBTM_PM_STATUS>(hci_mode);
718 tBTM_PM_STATE old_state;
719
720 /* update control block */
721 if (pm_mode_db.count(hci_handle) == 0) {
722 LOG_WARN("Unable to find active acl for handle %d", hci_handle);
723 return;
724 }
725 tBTM_PM_MCB* p_cb = &pm_mode_db[hci_handle];
726
727 old_state = p_cb->state;
728 p_cb->state = mode;
729 p_cb->interval = interval;
730
731 LOG_INFO("Power mode switched from %s[%hhu] to %s[%hhu]",
732 power_mode_state_text(old_state).c_str(), old_state,
733 power_mode_state_text(p_cb->state).c_str(), p_cb->state);
734
735 if ((p_cb->state == BTM_PM_ST_ACTIVE) || (p_cb->state == BTM_PM_ST_SNIFF)) {
736 l2c_OnHciModeChangeSendPendingPackets(p_cb->bda_);
737 }
738
739 /* set req_mode HOLD mode->ACTIVE */
740 if ((mode == BTM_PM_MD_ACTIVE) && (p_cb->req_mode.mode == BTM_PM_MD_HOLD))
741 p_cb->req_mode.mode = BTM_PM_MD_ACTIVE;
742
743 /* new request has been made. - post a message to BTU task */
744 if (old_state & BTM_PM_STORED_MASK) {
745 btm_pm_snd_md_req(hci_handle, BTM_PM_SET_ONLY_ID, hci_handle, NULL);
746 } else {
747 for (auto& entry : pm_mode_db) {
748 if (entry.second.chg_ind) {
749 btm_pm_snd_md_req(entry.second.handle_, BTM_PM_SET_ONLY_ID,
750 entry.second.handle_, NULL);
751 break;
752 }
753 }
754 }
755
756 /* notify registered parties */
757 if (pm_reg_db.mask & BTM_PM_REG_SET) {
758 (*pm_reg_db.cback)(p_cb->bda_, mode, interval, hci_status);
759 }
760 /*check if sco disconnect is waiting for the mode change */
761 btm_sco_disc_chk_pend_for_modechange(hci_handle);
762
763 /* If mode change was because of an active role switch or change link key */
764 btm_cont_rswitch_from_handle(hci_handle);
765 }
766
767 /*******************************************************************************
768 *
769 * Function btm_pm_proc_ssr_evt
770 *
771 * Description This function is called when an HCI sniff subrating event
772 * occurs.
773 *
774 * Returns none.
775 *
776 ******************************************************************************/
process_ssr_event(tHCI_STATUS status,uint16_t handle,UNUSED_ATTR uint16_t max_tx_lat,uint16_t max_rx_lat)777 void process_ssr_event(tHCI_STATUS status, uint16_t handle,
778 UNUSED_ATTR uint16_t max_tx_lat, uint16_t max_rx_lat) {
779 if (pm_mode_db.count(handle) == 0) {
780 LOG_WARN("Received sniff subrating event with no active ACL");
781 return;
782 }
783 tBTM_PM_MCB* p_cb = &pm_mode_db[handle];
784 auto bd_addr = p_cb->bda_;
785
786 bool use_ssr = true;
787 if (p_cb->interval == max_rx_lat) {
788 LOG_DEBUG("Sniff subrating unsupported so dropping to legacy sniff mode");
789 use_ssr = false;
790 } else {
791 LOG_DEBUG("Sniff subrating enabled");
792 }
793
794 int cnt = 0;
795 if (pm_reg_db.mask & BTM_PM_REG_SET) {
796 (*pm_reg_db.cback)(bd_addr, BTM_PM_STS_SSR, (use_ssr) ? 1 : 0, status);
797 cnt++;
798 }
799 LOG_DEBUG(
800 "Notified sniff subrating registered clients cnt:%d peer:%s use_ssr:%s "
801 "status:%s",
802 cnt, PRIVATE_ADDRESS(bd_addr), logbool(use_ssr).c_str(),
803 hci_error_code_text(status).c_str());
804 }
805
btm_pm_on_sniff_subrating(tHCI_STATUS status,uint16_t handle,uint16_t maximum_transmit_latency,uint16_t maximum_receive_latency,uint16_t minimum_remote_timeout,uint16_t minimum_local_timeout)806 void btm_pm_on_sniff_subrating(tHCI_STATUS status, uint16_t handle,
807 uint16_t maximum_transmit_latency,
808 uint16_t maximum_receive_latency,
809 uint16_t minimum_remote_timeout,
810 uint16_t minimum_local_timeout) {
811 if (bluetooth::shim::is_gd_link_policy_enabled()) {
812 return bluetooth::shim::btm_pm_on_sniff_subrating(
813 status, handle, maximum_transmit_latency, maximum_receive_latency,
814 minimum_remote_timeout, minimum_local_timeout);
815 }
816 process_ssr_event(status, handle, maximum_transmit_latency,
817 maximum_receive_latency);
818 }
819
btm_pm_proc_ssr_evt(uint8_t * p,UNUSED_ATTR uint16_t evt_len)820 void btm_pm_proc_ssr_evt(uint8_t* p, UNUSED_ATTR uint16_t evt_len) {
821 uint8_t status;
822 uint16_t handle;
823 uint16_t max_tx_lat;
824 uint16_t max_rx_lat;
825
826 STREAM_TO_UINT8(status, p);
827 STREAM_TO_UINT16(handle, p);
828 STREAM_TO_UINT16(max_tx_lat, p);
829 STREAM_TO_UINT16(max_rx_lat, p);
830
831 process_ssr_event(static_cast<tHCI_STATUS>(status), handle, max_tx_lat,
832 max_rx_lat);
833 }
834
835 /*******************************************************************************
836 *
837 * Function btm_pm_device_in_active_or_sniff_mode
838 *
839 * Description This function is called to check if in active or sniff mode
840 *
841 * Returns true, if in active or sniff mode
842 *
843 ******************************************************************************/
btm_pm_device_in_active_or_sniff_mode(void)844 static bool btm_pm_device_in_active_or_sniff_mode(void) {
845 /* The active state is the highest state-includes connected device and sniff
846 * mode*/
847
848 /* Covers active and sniff modes */
849 if (!pm_mode_db.empty()) {
850 return true;
851 }
852
853 /* Check BLE states */
854 if (!btm_cb.ble_ctr_cb.is_connection_state_idle()) {
855 BTM_TRACE_DEBUG("%s - BLE state is not idle", __func__);
856 return true;
857 }
858
859 return false;
860 }
861
862 /*******************************************************************************
863 *
864 * Function btm_pm_device_in_scan_state
865 *
866 * Description This function is called to check if in paging, inquiry or
867 * connecting mode
868 *
869 * Returns true, if in paging, inquiry or connecting mode
870 *
871 ******************************************************************************/
btm_pm_device_in_scan_state(void)872 static bool btm_pm_device_in_scan_state(void) {
873 /* Scan state-paging, inquiry, and trying to connect */
874
875 /* Check for paging */
876 if (btm_cb.is_paging || !fixed_queue_is_empty(btm_cb.page_queue)) {
877 BTM_TRACE_DEBUG("btm_pm_device_in_scan_state- paging");
878 return true;
879 }
880
881 /* Check for inquiry */
882 if ((btm_cb.btm_inq_vars.inq_active &
883 (BTM_BR_INQ_ACTIVE_MASK | BTM_BLE_INQ_ACTIVE_MASK)) != 0) {
884 BTM_TRACE_DEBUG("btm_pm_device_in_scan_state- Inq active");
885 return true;
886 }
887
888 return false;
889 }
890
891 /*******************************************************************************
892 *
893 * Function BTM_PM_ReadControllerState
894 *
895 * Description This function is called to obtain the controller state
896 *
897 * Returns Controller State-BTM_CONTRL_ACTIVE, BTM_CONTRL_SCAN, and
898 * BTM_CONTRL_IDLE
899 *
900 ******************************************************************************/
BTM_PM_ReadControllerState(void)901 tBTM_CONTRL_STATE BTM_PM_ReadControllerState(void) {
902 if (btm_pm_device_in_active_or_sniff_mode())
903 return BTM_CONTRL_ACTIVE;
904 else if (btm_pm_device_in_scan_state())
905 return BTM_CONTRL_SCAN;
906 else
907 return BTM_CONTRL_IDLE;
908 }
909
btm_pm_on_mode_change(tHCI_STATUS status,uint16_t handle,tHCI_MODE current_mode,uint16_t interval)910 void btm_pm_on_mode_change(tHCI_STATUS status, uint16_t handle,
911 tHCI_MODE current_mode, uint16_t interval) {
912 if (bluetooth::shim::is_gd_link_policy_enabled()) {
913 return bluetooth::shim::btm_pm_on_mode_change(status, handle, current_mode,
914 interval);
915 }
916
917 btm_sco_chk_pend_unpark(status, handle);
918 btm_pm_proc_mode_change(status, handle, current_mode, interval);
919 }
920