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