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