1 /******************************************************************************
2  *
3  *  Copyright 2003-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 the action functions for device manager state
22  *  machine.
23  *
24  ******************************************************************************/
25 
26 #include <base/bind.h>
27 #include <base/logging.h>
28 #include <string.h>
29 
30 #include <mutex>
31 
32 #include "bt_common.h"
33 #include "bta_api.h"
34 #include "bta_dm_api.h"
35 #include "bta_dm_int.h"
36 #include "bta_sys.h"
37 #include "btm_api.h"
38 #include "device/include/controller.h"
39 #include "stack/include/btu.h"
40 
41 static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, uint8_t id,
42                             uint8_t app_id, const RawAddress& peer_addr);
43 static void bta_dm_pm_set_mode(const RawAddress& peer_addr,
44                                tBTA_DM_PM_ACTION pm_mode,
45                                tBTA_DM_PM_REQ pm_req);
46 static void bta_dm_pm_timer_cback(void* data);
47 static void bta_dm_pm_btm_cback(const RawAddress& bd_addr,
48                                 tBTM_PM_STATUS status, uint16_t value,
49                                 uint8_t hci_status);
50 static bool bta_dm_pm_park(const RawAddress& peer_addr);
51 static bool bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE* p_peer_dev, uint8_t index);
52 static bool bta_dm_pm_is_sco_active();
53 #if (BTM_SSR_INCLUDED == TRUE)
54 static int bta_dm_get_sco_index();
55 #endif
56 static void bta_dm_pm_hid_check(bool bScoActive);
57 static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE* p_dev,
58                                        bool bDisable);
59 static void bta_dm_pm_stop_timer_by_index(tBTA_PM_TIMER* p_timer,
60                                           uint8_t timer_idx);
61 
62 #if (BTM_SSR_INCLUDED == TRUE)
63 #if (BTA_HH_INCLUDED == TRUE)
64 #include "../hh/bta_hh_int.h"
65 /* BTA_DM_PM_SSR1 will be dedicated for HH SSR setting entry, no other profile
66  * can use it */
67 #define BTA_DM_PM_SSR_HH BTA_DM_PM_SSR1
68 #endif
69 static void bta_dm_pm_ssr(const RawAddress& peer_addr, int ssr);
70 #endif
71 
72 tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
73 static std::recursive_mutex pm_timer_schedule_mutex;
74 static std::recursive_mutex pm_timer_state_mutex;
75 
76 /*******************************************************************************
77  *
78  * Function         bta_dm_init_pm
79  *
80  * Description      Initializes the BT low power manager
81  *
82  *
83  * Returns          void
84  *
85  ******************************************************************************/
bta_dm_init_pm(void)86 void bta_dm_init_pm(void) {
87   memset(&bta_dm_conn_srvcs, 0x00, sizeof(bta_dm_conn_srvcs));
88 
89   /* if there are no power manger entries, so not register */
90   if (p_bta_dm_pm_cfg[0].app_id != 0) {
91     bta_sys_pm_register(bta_dm_pm_cback);
92 
93     BTM_PmRegister((BTM_PM_REG_SET | BTM_PM_REG_NOTIF), &bta_dm_cb.pm_id,
94                    bta_dm_pm_btm_cback);
95   }
96 
97   /* Need to initialize all PM timer service IDs */
98   for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
99     for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++)
100       bta_dm_cb.pm_timer[i].srvc_id[j] = BTA_ID_MAX;
101   }
102 }
103 
104 /*******************************************************************************
105  *
106  * Function         bta_dm_disable_pm
107  *
108  * Description      Disable PM
109  *
110  *
111  * Returns          void
112  *
113  ******************************************************************************/
bta_dm_disable_pm(void)114 void bta_dm_disable_pm(void) {
115   BTM_PmRegister(BTM_PM_DEREG, &bta_dm_cb.pm_id, NULL);
116 
117   /*
118    * Deregister the PM callback from the system handling to prevent
119    * re-enabling the PM timers after this call if the callback is invoked.
120    */
121   bta_sys_pm_register(NULL);
122 
123   /* Need to stop all active timers. */
124   for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
125     for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) {
126       bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], j);
127       bta_dm_cb.pm_timer[i].pm_action[j] = BTA_DM_PM_NO_ACTION;
128     }
129   }
130 }
131 
132 /*******************************************************************************
133  *
134  * Function         bta_dm_get_av_count
135  *
136  * Description      Get the number of connected AV
137  *
138  *
139  * Returns          number of av connections
140  *
141  ******************************************************************************/
bta_dm_get_av_count(void)142 uint8_t bta_dm_get_av_count(void) {
143   uint8_t count = 0;
144   for (int i = 0; i < bta_dm_conn_srvcs.count; i++) {
145     if (bta_dm_conn_srvcs.conn_srvc[i].id == BTA_ID_AV) ++count;
146   }
147   return count;
148 }
149 
150 /*******************************************************************************
151  *
152  * Function         bta_dm_pm_stop_timer
153  *
154  * Description      stop a PM timer
155  *
156  *
157  * Returns          void
158  *
159  ******************************************************************************/
bta_dm_pm_stop_timer(const RawAddress & peer_addr)160 static void bta_dm_pm_stop_timer(const RawAddress& peer_addr) {
161   APPL_TRACE_DEBUG("%s: ", __func__);
162 
163   for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
164     if (bta_dm_cb.pm_timer[i].in_use &&
165         bta_dm_cb.pm_timer[i].peer_bdaddr == peer_addr) {
166       for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) {
167         bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], j);
168         /*
169          * TODO: For now, stopping the timer does not reset
170          * pm_action[j].
171          * The reason is because some of the internal logic that
172          * (re)assigns the pm_action[] values is taking into account
173          * the older value; e.g., see the pm_action[] assignment in
174          * function bta_dm_pm_start_timer().
175          * Such subtlety in the execution logic is error prone, and
176          * should be eliminiated in the future.
177          */
178       }
179       break;
180     }
181   }
182 }
183 
184 /*******************************************************************************
185  *
186  * Function         bta_pm_action_to_timer_idx
187  *
188  * Description      convert power mode into timer index for each connected
189  *                  device
190  *
191  *
192  * Returns          index of the power mode delay timer
193  *
194  ******************************************************************************/
bta_pm_action_to_timer_idx(uint8_t pm_action)195 static uint8_t bta_pm_action_to_timer_idx(uint8_t pm_action) {
196   if (pm_action == BTA_DM_PM_SUSPEND)
197     return BTA_DM_PM_SUSPEND_TIMER_IDX;
198   else if (pm_action == BTA_DM_PM_PARK)
199     return BTA_DM_PM_PARK_TIMER_IDX;
200   else if ((pm_action & BTA_DM_PM_SNIFF) == BTA_DM_PM_SNIFF)
201     return BTA_DM_PM_SNIFF_TIMER_IDX;
202 
203   /* Active, no preference, no action and retry */
204   return BTA_DM_PM_MODE_TIMER_MAX;
205 }
206 
207 /*******************************************************************************
208  *
209  * Function         bta_dm_pm_stop_timer_by_mode
210  *
211  * Description      stop a PM timer
212  *
213  *
214  * Returns          void
215  *
216  ******************************************************************************/
bta_dm_pm_stop_timer_by_mode(const RawAddress & peer_addr,uint8_t power_mode)217 static void bta_dm_pm_stop_timer_by_mode(const RawAddress& peer_addr,
218                                          uint8_t power_mode) {
219   const uint8_t timer_idx = bta_pm_action_to_timer_idx(power_mode);
220   if (timer_idx == BTA_DM_PM_MODE_TIMER_MAX) return;
221 
222   for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
223     if (bta_dm_cb.pm_timer[i].in_use &&
224         bta_dm_cb.pm_timer[i].peer_bdaddr == peer_addr) {
225       if (bta_dm_cb.pm_timer[i].srvc_id[timer_idx] != BTA_ID_MAX) {
226         bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], timer_idx);
227         /*
228          * TODO: Intentionally setting pm_action[timer_idx].
229          * This assignment should be eliminated in the future - see the
230          * pm_action[] related comment inside function
231          * bta_dm_pm_stop_timer().
232          */
233         bta_dm_cb.pm_timer[i].pm_action[timer_idx] = power_mode;
234       }
235       break;
236     }
237   }
238 }
239 
240 /*******************************************************************************
241  *
242  * Function         bta_dm_pm_stop_timer_by_srvc_id
243  *
244  * Description      stop all timer started by the service ID.
245  *
246  *
247  * Returns          index of the power mode delay timer
248  *
249  ******************************************************************************/
bta_dm_pm_stop_timer_by_srvc_id(const RawAddress & peer_addr,uint8_t srvc_id)250 static void bta_dm_pm_stop_timer_by_srvc_id(const RawAddress& peer_addr,
251                                             uint8_t srvc_id) {
252   for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
253     if (bta_dm_cb.pm_timer[i].in_use &&
254         bta_dm_cb.pm_timer[i].peer_bdaddr == peer_addr) {
255       for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) {
256         if (bta_dm_cb.pm_timer[i].srvc_id[j] == srvc_id) {
257           bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], j);
258           bta_dm_cb.pm_timer[i].pm_action[j] = BTA_DM_PM_NO_ACTION;
259           break;
260         }
261       }
262     }
263   }
264 }
265 
266 /*******************************************************************************
267  *
268  * Function         bta_dm_pm_start_timer
269  *
270  * Description      start a PM timer
271  *
272  *
273  * Returns          void
274  *
275  ******************************************************************************/
bta_dm_pm_start_timer(tBTA_PM_TIMER * p_timer,uint8_t timer_idx,uint64_t timeout_ms,uint8_t srvc_id,uint8_t pm_action)276 static void bta_dm_pm_start_timer(tBTA_PM_TIMER* p_timer, uint8_t timer_idx,
277                                   uint64_t timeout_ms, uint8_t srvc_id,
278                                   uint8_t pm_action) {
279   std::unique_lock<std::recursive_mutex> schedule_lock(pm_timer_schedule_mutex);
280   std::unique_lock<std::recursive_mutex> state_lock(pm_timer_state_mutex);
281   p_timer->in_use = true;
282 
283   if (p_timer->srvc_id[timer_idx] == BTA_ID_MAX) p_timer->active++;
284 
285   if (p_timer->pm_action[timer_idx] < pm_action)
286     p_timer->pm_action[timer_idx] = pm_action;
287 
288   p_timer->srvc_id[timer_idx] = srvc_id;
289   state_lock.unlock();
290 
291   alarm_set_on_mloop(p_timer->timer[timer_idx], timeout_ms,
292                      bta_dm_pm_timer_cback, p_timer->timer[timer_idx]);
293 }
294 
295 /*******************************************************************************
296  *
297  * Function         bta_dm_pm_stop_timer_by_index
298  *
299  * Description      stop a PM timer
300  *
301  *
302  * Returns          void
303  *
304  ******************************************************************************/
bta_dm_pm_stop_timer_by_index(tBTA_PM_TIMER * p_timer,uint8_t timer_idx)305 static void bta_dm_pm_stop_timer_by_index(tBTA_PM_TIMER* p_timer,
306                                           uint8_t timer_idx) {
307   if ((p_timer == NULL) || (timer_idx >= BTA_DM_PM_MODE_TIMER_MAX)) return;
308 
309   std::unique_lock<std::recursive_mutex> schedule_lock(pm_timer_schedule_mutex);
310   std::unique_lock<std::recursive_mutex> state_lock(pm_timer_state_mutex);
311   if (p_timer->srvc_id[timer_idx] == BTA_ID_MAX)
312     return; /* The timer was not scheduled */
313 
314   CHECK(p_timer->in_use && (p_timer->active > 0));
315 
316   p_timer->srvc_id[timer_idx] = BTA_ID_MAX;
317   /* NOTE: pm_action[timer_idx] intentionally not reset */
318 
319   p_timer->active--;
320   if (p_timer->active == 0) p_timer->in_use = false;
321   state_lock.unlock();
322 
323   alarm_cancel(p_timer->timer[timer_idx]);
324 }
325 
326 /*******************************************************************************
327  *
328  * Function         bta_dm_pm_cback
329  *
330  * Description      Conn change callback from sys for low power management
331  *
332  *
333  * Returns          void
334  *
335  ******************************************************************************/
bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status,uint8_t id,uint8_t app_id,const RawAddress & peer_addr)336 static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, uint8_t id,
337                             uint8_t app_id, const RawAddress& peer_addr) {
338   uint8_t i, j;
339   tBTA_DM_PEER_DEVICE* p_dev;
340   tBTA_DM_PM_REQ pm_req = BTA_DM_PM_NEW_REQ;
341 
342   APPL_TRACE_DEBUG("bta_dm_pm_cback: st(%d), id(%d), app(%d)", status, id,
343                    app_id);
344 
345   p_dev = bta_dm_find_peer_device(peer_addr);
346 
347   /* find if there is an power mode entry for the service */
348   for (i = 1; i <= p_bta_dm_pm_cfg[0].app_id; i++) {
349     if ((p_bta_dm_pm_cfg[i].id == id) &&
350         ((p_bta_dm_pm_cfg[i].app_id == BTA_ALL_APP_ID) ||
351          (p_bta_dm_pm_cfg[i].app_id == app_id)))
352       break;
353   }
354 
355   /* if no entries are there for the app_id and subsystem in p_bta_dm_pm_spec*/
356   if (i > p_bta_dm_pm_cfg[0].app_id) return;
357 
358   bta_dm_pm_stop_timer_by_srvc_id(peer_addr, id);
359 /*p_dev = bta_dm_find_peer_device(peer_addr);*/
360 
361 #if (BTM_SSR_INCLUDED == TRUE)
362   /* set SSR parameters on SYS CONN OPEN */
363   int index = BTA_DM_PM_SSR0;
364   if ((BTA_SYS_CONN_OPEN == status) && p_dev &&
365       (p_dev->info & BTA_DM_DI_USE_SSR)) {
366     index = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].ssr;
367   } else if (BTA_ID_AV == id) {
368     if (BTA_SYS_CONN_BUSY == status) {
369       /* set SSR4 for A2DP on SYS CONN BUSY */
370       index = BTA_DM_PM_SSR4;
371     } else if (BTA_SYS_CONN_IDLE == status) {
372       index = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].ssr;
373     }
374   }
375 #endif
376 
377   /* if no action for the event */
378   if (p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx]
379           .actn_tbl[status][0]
380           .power_mode == BTA_DM_PM_NO_ACTION) {
381 #if (BTM_SSR_INCLUDED == TRUE)
382     if (BTA_DM_PM_SSR0 == index) /* and do not need to set SSR, return. */
383 #endif
384       return;
385   }
386 
387   for (j = 0; j < bta_dm_conn_srvcs.count; j++) {
388     /* check if an entry already present */
389     if ((bta_dm_conn_srvcs.conn_srvc[j].id == id) &&
390         (bta_dm_conn_srvcs.conn_srvc[j].app_id == app_id) &&
391         bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr == peer_addr) {
392       bta_dm_conn_srvcs.conn_srvc[j].new_request = true;
393       break;
394     }
395   }
396 
397   /* if subsystem has no more preference on the power mode remove
398  the cb */
399   if (p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx]
400           .actn_tbl[status][0]
401           .power_mode == BTA_DM_PM_NO_PREF) {
402     if (j != bta_dm_conn_srvcs.count) {
403       bta_dm_conn_srvcs.count--;
404 
405       for (; j < bta_dm_conn_srvcs.count; j++) {
406         memcpy(&bta_dm_conn_srvcs.conn_srvc[j],
407                &bta_dm_conn_srvcs.conn_srvc[j + 1],
408                sizeof(bta_dm_conn_srvcs.conn_srvc[j]));
409       }
410     } else {
411       APPL_TRACE_WARNING("bta_dm_act no entry for connected service cbs");
412       return;
413     }
414   } else if (j == bta_dm_conn_srvcs.count) {
415     /* check if we have more connected service that cbs */
416     if (bta_dm_conn_srvcs.count == BTA_DM_NUM_CONN_SRVS) {
417       APPL_TRACE_WARNING("bta_dm_act no more connected service cbs");
418       return;
419     }
420 
421     /* fill in a new cb */
422     bta_dm_conn_srvcs.conn_srvc[j].id = id;
423     bta_dm_conn_srvcs.conn_srvc[j].app_id = app_id;
424     bta_dm_conn_srvcs.conn_srvc[j].new_request = true;
425     bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr = peer_addr;
426 
427     APPL_TRACE_WARNING("new conn_srvc id:%d, app_id:%d", id, app_id);
428 
429     bta_dm_conn_srvcs.count++;
430     bta_dm_conn_srvcs.conn_srvc[j].state = status;
431   } else {
432     /* no service is added or removed. only updating status. */
433     bta_dm_conn_srvcs.conn_srvc[j].state = status;
434   }
435 
436   /* stop timer */
437   bta_dm_pm_stop_timer(peer_addr);
438   if (bta_dm_conn_srvcs.count > 0) {
439     pm_req = BTA_DM_PM_RESTART;
440     APPL_TRACE_DEBUG(
441         "%s bta_dm_pm_stop_timer for current service, restart other "
442         "service timers: count = %d",
443         __func__, bta_dm_conn_srvcs.count);
444   }
445 
446   if (p_dev) {
447     p_dev->pm_mode_attempted = 0;
448     p_dev->pm_mode_failed = 0;
449   }
450 
451 #if (BTM_SSR_INCLUDED == TRUE)
452   if (p_bta_dm_ssr_spec[index].max_lat
453 #if (BTA_HH_INCLUDED == TRUE)
454       || index == BTA_DM_PM_SSR_HH
455 #endif
456       ) {
457     bta_dm_pm_ssr(peer_addr, index);
458   } else {
459     const controller_t* controller = controller_get_interface();
460     uint8_t* p = NULL;
461     if (controller->supports_sniff_subrating() &&
462         ((NULL != (p = BTM_ReadRemoteFeatures(peer_addr))) &&
463          HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
464         (index == BTA_DM_PM_SSR0)) {
465       if (status == BTA_SYS_SCO_OPEN) {
466         APPL_TRACE_DEBUG("%s: SCO inactive, reset SSR to zero", __func__);
467         BTM_SetSsrParams(peer_addr, 0, 0, 0);
468       } else if (status == BTA_SYS_SCO_CLOSE) {
469         APPL_TRACE_DEBUG("%s: SCO active, back to old SSR", __func__);
470         bta_dm_pm_ssr(peer_addr, BTA_DM_PM_SSR0);
471       }
472     }
473   }
474 #endif
475 
476   bta_dm_pm_set_mode(peer_addr, BTA_DM_PM_NO_ACTION, pm_req);
477 
478   /* perform the HID link workaround if needed
479   ** 1. If SCO up/down event is received OR
480   ** 2. If HID connection open is received and SCO is already active.
481   **     This will handle the case where HID connects when SCO already active
482   */
483   if (BTM_IsDeviceUp() &&
484       (((status == BTA_SYS_SCO_OPEN) || (status == BTA_SYS_SCO_CLOSE)) ||
485        ((status == BTA_SYS_CONN_OPEN) && (id == BTA_ID_HH) &&
486         bta_dm_pm_is_sco_active()))) {
487     bool bScoActive;
488     if (status == BTA_SYS_CONN_OPEN)
489       bScoActive = true;
490     else
491       bScoActive = (status == BTA_SYS_SCO_OPEN);
492 
493     bta_dm_pm_hid_check(bScoActive);
494   }
495 }
496 
497 /*******************************************************************************
498  *
499  * Function         bta_dm_pm_set_mode
500  *
501  * Description      Set the power mode for the device
502  *
503  *
504  * Returns          void
505  *
506  ******************************************************************************/
507 
bta_dm_pm_set_mode(const RawAddress & peer_addr,tBTA_DM_PM_ACTION pm_request,tBTA_DM_PM_REQ pm_req)508 static void bta_dm_pm_set_mode(const RawAddress& peer_addr,
509                                tBTA_DM_PM_ACTION pm_request,
510                                tBTA_DM_PM_REQ pm_req) {
511   tBTA_DM_PM_ACTION pm_action = BTA_DM_PM_NO_ACTION;
512   uint64_t timeout_ms = 0;
513   uint8_t i, j;
514   tBTA_DM_PM_ACTION failed_pm = 0;
515   tBTA_DM_PEER_DEVICE* p_peer_device = NULL;
516   tBTA_DM_PM_ACTION allowed_modes = 0;
517   tBTA_DM_PM_ACTION pref_modes = 0;
518   const tBTA_DM_PM_CFG* p_pm_cfg;
519   const tBTA_DM_PM_SPEC* p_pm_spec;
520   const tBTA_DM_PM_ACTN* p_act0;
521   const tBTA_DM_PM_ACTN* p_act1;
522   tBTA_DM_SRVCS* p_srvcs = NULL;
523   bool timer_started = false;
524   uint8_t timer_idx, available_timer = BTA_DM_PM_MODE_TIMER_MAX;
525   uint64_t remaining_ms = 0;
526 
527   if (!bta_dm_cb.device_list.count) return;
528 
529   /* see if any attempt to put device in low power mode failed */
530   p_peer_device = bta_dm_find_peer_device(peer_addr);
531   /* if no peer device found return */
532   if (p_peer_device == NULL) return;
533 
534   failed_pm = p_peer_device->pm_mode_failed;
535 
536   for (i = 0; i < bta_dm_conn_srvcs.count; i++) {
537     p_srvcs = &bta_dm_conn_srvcs.conn_srvc[i];
538     if (p_srvcs->peer_bdaddr == peer_addr) {
539       /* p_bta_dm_pm_cfg[0].app_id is the number of entries */
540       for (j = 1; j <= p_bta_dm_pm_cfg[0].app_id; j++) {
541         if ((p_bta_dm_pm_cfg[j].id == p_srvcs->id) &&
542             ((p_bta_dm_pm_cfg[j].app_id == BTA_ALL_APP_ID) ||
543              (p_bta_dm_pm_cfg[j].app_id == p_srvcs->app_id)))
544           break;
545       }
546 
547       p_pm_cfg = &p_bta_dm_pm_cfg[j];
548       p_pm_spec = &p_bta_dm_pm_spec[p_pm_cfg->spec_idx];
549       p_act0 = &p_pm_spec->actn_tbl[p_srvcs->state][0];
550       p_act1 = &p_pm_spec->actn_tbl[p_srvcs->state][1];
551 
552       APPL_TRACE_DEBUG("bta_dm_pm_set_mode: srvcsid: %d, state: %d, j: %d",
553                        p_srvcs->id, p_srvcs->state, j);
554       allowed_modes |= p_pm_spec->allow_mask;
555 
556       /* PM actions are in the order of strictness */
557 
558       /* first check if the first preference is ok */
559       if (!(failed_pm & p_act0->power_mode)) {
560         pref_modes |= p_act0->power_mode;
561 
562         if (p_act0->power_mode >= pm_action) {
563           pm_action = p_act0->power_mode;
564 
565           if (pm_req != BTA_DM_PM_NEW_REQ || p_srvcs->new_request) {
566             p_srvcs->new_request = false;
567             timeout_ms = p_act0->timeout;
568           }
569         }
570       }
571       /* if first preference has already failed, try second preference */
572       else if (!(failed_pm & p_act1->power_mode)) {
573         pref_modes |= p_act1->power_mode;
574 
575         if (p_act1->power_mode > pm_action) {
576           pm_action = p_act1->power_mode;
577           timeout_ms = p_act1->timeout;
578         }
579       }
580     }
581   }
582 
583   if (pm_action & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF)) {
584     /* some service don't like the mode */
585     if (!(allowed_modes & pm_action)) {
586       /* select the other mode if its allowed and preferred, otherwise 0 which
587        * is BTA_DM_PM_NO_ACTION */
588       pm_action =
589           (allowed_modes & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF) & pref_modes);
590 
591       /* no timeout needed if no action is required */
592       if (pm_action == BTA_DM_PM_NO_ACTION) {
593         timeout_ms = 0;
594       }
595     }
596   }
597   /* if need to start a timer */
598   if ((pm_req != BTA_DM_PM_EXECUTE) && (timeout_ms > 0)) {
599     for (i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
600       if (bta_dm_cb.pm_timer[i].in_use &&
601           bta_dm_cb.pm_timer[i].peer_bdaddr == peer_addr) {
602         timer_idx = bta_pm_action_to_timer_idx(pm_action);
603         if (timer_idx != BTA_DM_PM_MODE_TIMER_MAX) {
604           remaining_ms =
605               alarm_get_remaining_ms(bta_dm_cb.pm_timer[i].timer[timer_idx]);
606           if (remaining_ms < timeout_ms) {
607             /* Cancel and restart the timer */
608             /*
609              * TODO: The value of pm_action[timer_idx] is
610              * conditionally updated between the two function
611              * calls below when the timer is restarted.
612              * This logic is error-prone and should be eliminated
613              * in the future.
614              */
615             bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], timer_idx);
616             bta_dm_pm_start_timer(&bta_dm_cb.pm_timer[i], timer_idx, timeout_ms,
617                                   p_srvcs->id, pm_action);
618           }
619           timer_started = true;
620         }
621         break;
622       } else if (!bta_dm_cb.pm_timer[i].in_use) {
623         APPL_TRACE_DEBUG("%s dm_pm_timer:%d, %d ms", __func__, i, timeout_ms);
624         if (available_timer == BTA_DM_PM_MODE_TIMER_MAX) available_timer = i;
625       }
626     }
627     /* new power mode for a new active connection */
628     if (!timer_started) {
629       if (available_timer != BTA_DM_PM_MODE_TIMER_MAX) {
630         bta_dm_cb.pm_timer[available_timer].peer_bdaddr = peer_addr;
631         timer_idx = bta_pm_action_to_timer_idx(pm_action);
632         if (timer_idx != BTA_DM_PM_MODE_TIMER_MAX) {
633           bta_dm_pm_start_timer(&bta_dm_cb.pm_timer[available_timer], timer_idx,
634                                 timeout_ms, p_srvcs->id, pm_action);
635           timer_started = true;
636         }
637       }
638       /* no more timers */
639       else {
640         APPL_TRACE_WARNING("bta_dm_act dm_pm_timer no more");
641       }
642     }
643     return;
644   }
645   /* if pending power mode timer expires, and currecnt link is in a
646      lower power mode than current profile requirement, igonre it */
647   if (pm_req == BTA_DM_PM_EXECUTE && pm_request < pm_action) {
648     APPL_TRACE_ERROR("Ignore the power mode request: %d", pm_request)
649     return;
650   }
651   if (pm_action == BTA_DM_PM_PARK) {
652     p_peer_device->pm_mode_attempted = BTA_DM_PM_PARK;
653     bta_dm_pm_park(peer_addr);
654   } else if (pm_action & BTA_DM_PM_SNIFF) {
655     /* dont initiate SNIFF, if link_policy has it disabled */
656     if (p_peer_device->link_policy & HCI_ENABLE_SNIFF_MODE) {
657       p_peer_device->pm_mode_attempted = BTA_DM_PM_SNIFF;
658       bta_dm_pm_sniff(p_peer_device, (uint8_t)(pm_action & 0x0F));
659     } else {
660       APPL_TRACE_DEBUG(
661           "bta_dm_pm_set_mode: Link policy disallows SNIFF, ignore request");
662     }
663   } else if (pm_action == BTA_DM_PM_ACTIVE) {
664     bta_dm_pm_active(peer_addr);
665   }
666 }
667 /*******************************************************************************
668  *
669  * Function         bta_ag_pm_park
670  *
671  * Description      Switch to park mode.
672  *
673  *
674  * Returns          true if park attempted, false otherwise.
675  *
676  ******************************************************************************/
bta_dm_pm_park(const RawAddress & peer_addr)677 static bool bta_dm_pm_park(const RawAddress& peer_addr) {
678   tBTM_PM_MODE mode = BTM_PM_STS_ACTIVE;
679 
680   /* if not in park mode, switch to park */
681   BTM_ReadPowerMode(peer_addr, &mode);
682 
683   if (mode != BTM_PM_MD_PARK) {
684     BTM_SetPowerMode(bta_dm_cb.pm_id, peer_addr,
685                      &p_bta_dm_pm_md[BTA_DM_PM_PARK_IDX]);
686   }
687   return true;
688 }
689 
690 /*******************************************************************************
691  *
692  * Function         bta_ag_pm_sniff
693  *
694  * Description      Switch to sniff mode.
695  *
696  *
697  * Returns          true if sniff attempted, false otherwise.
698  *
699  ******************************************************************************/
bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE * p_peer_dev,uint8_t index)700 static bool bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE* p_peer_dev, uint8_t index) {
701   tBTM_PM_MODE mode = BTM_PM_STS_ACTIVE;
702   tBTM_PM_PWR_MD pwr_md;
703   tBTM_STATUS status;
704 
705   BTM_ReadPowerMode(p_peer_dev->peer_bdaddr, &mode);
706 #if (BTM_SSR_INCLUDED == TRUE)
707   uint8_t* p_rem_feat = BTM_ReadRemoteFeatures(p_peer_dev->peer_bdaddr);
708   APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d, info:x%x", mode, index,
709                    p_peer_dev->info);
710   const controller_t* controller = controller_get_interface();
711   if (mode != BTM_PM_MD_SNIFF ||
712       (controller->supports_sniff_subrating() && p_rem_feat &&
713        HCI_SNIFF_SUB_RATE_SUPPORTED(p_rem_feat) &&
714        !(p_peer_dev->info & BTA_DM_DI_USE_SSR))) {
715     /* Dont initiate Sniff if controller has alreay accepted
716      * remote sniff params. This avoid sniff loop issue with
717      * some agrresive headsets who use sniff latencies more than
718      * DUT supported range of Sniff intervals.*/
719     if ((mode == BTM_PM_MD_SNIFF) && (p_peer_dev->info & BTA_DM_DI_ACP_SNIFF)) {
720       APPL_TRACE_DEBUG("%s: already in remote initiate sniff", __func__);
721       return true;
722     }
723 #else
724   APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d", mode, index);
725   if (mode != BTM_PM_MD_SNIFF) {
726 #endif
727     /* if the current mode is not sniff, issue the sniff command.
728      * If sniff, but SSR is not used in this link, still issue the command */
729     memcpy(&pwr_md, &p_bta_dm_pm_md[index], sizeof(tBTM_PM_PWR_MD));
730     if (p_peer_dev->info & BTA_DM_DI_INT_SNIFF) {
731       pwr_md.mode |= BTM_PM_MD_FORCE;
732     }
733     status =
734         BTM_SetPowerMode(bta_dm_cb.pm_id, p_peer_dev->peer_bdaddr, &pwr_md);
735     if (status == BTM_CMD_STORED || status == BTM_CMD_STARTED) {
736       p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF | BTA_DM_DI_ACP_SNIFF);
737       p_peer_dev->info |= BTA_DM_DI_SET_SNIFF;
738     } else if (status == BTM_SUCCESS) {
739       APPL_TRACE_DEBUG(
740           "bta_dm_pm_sniff BTM_SetPowerMode() returns BTM_SUCCESS");
741       p_peer_dev->info &=
742           ~(BTA_DM_DI_INT_SNIFF | BTA_DM_DI_ACP_SNIFF | BTA_DM_DI_SET_SNIFF);
743     } else /* error */
744     {
745       APPL_TRACE_ERROR(
746           "bta_dm_pm_sniff BTM_SetPowerMode() returns ERROR status=%d", status);
747       p_peer_dev->info &=
748           ~(BTA_DM_DI_INT_SNIFF | BTA_DM_DI_ACP_SNIFF | BTA_DM_DI_SET_SNIFF);
749     }
750   }
751   return true;
752 }
753 /*******************************************************************************
754  *
755  * Function         bta_dm_pm_ssr
756  *
757  * Description      checks and sends SSR parameters
758  *
759  * Returns          void
760  *
761  ******************************************************************************/
762 #if (BTM_SSR_INCLUDED == TRUE)
763 static void bta_dm_pm_ssr(const RawAddress& peer_addr, int ssr) {
764   int current_ssr_index;
765   int ssr_index = ssr;
766   tBTA_DM_SSR_SPEC* p_spec = &p_bta_dm_ssr_spec[ssr_index];
767 
768   /* go through the connected services */
769   for (int i = 0; i < bta_dm_conn_srvcs.count; i++) {
770     const tBTA_DM_SRVCS& service = bta_dm_conn_srvcs.conn_srvc[i];
771     if (service.peer_bdaddr != peer_addr) {
772       continue;
773     }
774     /* p_bta_dm_pm_cfg[0].app_id is the number of entries */
775     for (int j = 1; j <= p_bta_dm_pm_cfg[0].app_id; j++) {
776       /* find the associated p_bta_dm_pm_cfg */
777       const tBTA_DM_PM_CFG& config = p_bta_dm_pm_cfg[j];
778       current_ssr_index = p_bta_dm_pm_spec[config.spec_idx].ssr;
779       if ((config.id == service.id) && ((config.app_id == BTA_ALL_APP_ID) ||
780                                         (config.app_id == service.app_id))) {
781         APPL_TRACE_WARNING("%s: conn_srvc id:%d, app_id:%d", __func__,
782                            service.id, service.app_id);
783         break;
784       }
785     }
786     /* find the ssr index with the smallest max latency. */
787     tBTA_DM_SSR_SPEC* p_spec_cur = &p_bta_dm_ssr_spec[current_ssr_index];
788 #if (BTA_HH_INCLUDED == TRUE)
789     /* HH has the per connection SSR preference, already read the SSR params
790      * from BTA HH */
791     if (current_ssr_index == BTA_DM_PM_SSR_HH) {
792       if (bta_hh_read_ssr_param(peer_addr, &p_spec_cur->max_lat,
793                                 &p_spec_cur->min_rmt_to) == BTA_HH_ERR) {
794         continue;
795       }
796     }
797 #endif
798     if (p_spec_cur->max_lat < p_spec->max_lat ||
799         (ssr_index == BTA_DM_PM_SSR0 && current_ssr_index != BTA_DM_PM_SSR0)) {
800       ssr_index = current_ssr_index;
801       p_spec = &p_bta_dm_ssr_spec[ssr_index];
802     }
803   }
804 
805   APPL_TRACE_WARNING("%s ssr:%d, lat:%d", __func__, ssr_index, p_spec->max_lat);
806 
807   if (p_spec->max_lat) {
808     /* Avoid SSR reset on device which has SCO connected */
809     if (bta_dm_pm_is_sco_active()) {
810       int idx = bta_dm_get_sco_index();
811       if (idx != -1) {
812         if (bta_dm_conn_srvcs.conn_srvc[idx].peer_bdaddr == peer_addr) {
813           APPL_TRACE_WARNING("%s SCO is active on device, ignore SSR",
814                              __func__);
815           return;
816         }
817       }
818     }
819 
820     /* set the SSR parameters. */
821     BTM_SetSsrParams(peer_addr, p_spec->max_lat, p_spec->min_rmt_to,
822                      p_spec->min_loc_to);
823   }
824 }
825 #endif
826 /*******************************************************************************
827  *
828  * Function         bta_dm_pm_active
829  *
830  * Description      Brings connection to active mode
831  *
832  *
833  * Returns          void
834  *
835  ******************************************************************************/
836 void bta_dm_pm_active(const RawAddress& peer_addr) {
837   tBTM_PM_PWR_MD pm;
838 
839   memset((void*)&pm, 0, sizeof(pm));
840 
841   /* switch to active mode */
842   pm.mode = BTM_PM_MD_ACTIVE;
843   BTM_SetPowerMode(bta_dm_cb.pm_id, peer_addr, &pm);
844 }
845 
846 /** BTM power manager callback */
847 static void bta_dm_pm_btm_cback(const RawAddress& bd_addr,
848                                 tBTM_PM_STATUS status, uint16_t value,
849                                 uint8_t hci_status) {
850   do_in_main_thread(FROM_HERE, base::Bind(bta_dm_pm_btm_status, bd_addr, status,
851                                           value, hci_status));
852 }
853 
854 /*******************************************************************************
855  *
856  * Function         bta_dm_pm_timer_cback
857  *
858  * Description      Power management timer callback.
859  *
860  *
861  * Returns          void
862  *
863  ******************************************************************************/
864 static void bta_dm_pm_timer_cback(void* data) {
865   uint8_t i, j;
866   alarm_t* alarm = (alarm_t*)data;
867 
868   std::unique_lock<std::recursive_mutex> state_lock(pm_timer_state_mutex);
869   for (i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
870     APPL_TRACE_DEBUG("dm_pm_timer[%d] in use? %d", i,
871                      bta_dm_cb.pm_timer[i].in_use);
872     if (bta_dm_cb.pm_timer[i].in_use) {
873       for (j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) {
874         if (bta_dm_cb.pm_timer[i].timer[j] == alarm) {
875           bta_dm_cb.pm_timer[i].active--;
876           bta_dm_cb.pm_timer[i].srvc_id[j] = BTA_ID_MAX;
877           APPL_TRACE_DEBUG("dm_pm_timer[%d] expires, timer_idx=%d", i, j);
878           break;
879         }
880       }
881       if (bta_dm_cb.pm_timer[i].active == 0)
882         bta_dm_cb.pm_timer[i].in_use = false;
883       if (j < BTA_DM_PM_MODE_TIMER_MAX) break;
884     }
885   }
886   state_lock.unlock();
887 
888   /* no more timers */
889   if (i == BTA_DM_NUM_PM_TIMER) return;
890 
891   do_in_main_thread(
892       FROM_HERE, base::Bind(bta_dm_pm_timer, bta_dm_cb.pm_timer[i].peer_bdaddr,
893                             bta_dm_cb.pm_timer[i].pm_action[j]));
894 }
895 
896 /** Process pm status event from btm */
897 void bta_dm_pm_btm_status(const RawAddress& bd_addr, tBTM_PM_STATUS status,
898                           uint16_t value, uint8_t hci_status) {
899   APPL_TRACE_DEBUG("%s status: %d", __func__, status);
900 
901   tBTA_DM_PEER_DEVICE* p_dev = bta_dm_find_peer_device(bd_addr);
902   if (NULL == p_dev) return;
903 
904   tBTA_DM_DEV_INFO info = p_dev->info;
905   /* check new mode */
906   switch (status) {
907     case BTM_PM_STS_ACTIVE:
908       /* if our sniff or park attempt failed
909       we should not try it again*/
910       if (hci_status != 0) {
911         APPL_TRACE_ERROR("%s hci_status=%d", __func__, hci_status);
912         p_dev->info &=
913             ~(BTA_DM_DI_INT_SNIFF | BTA_DM_DI_ACP_SNIFF | BTA_DM_DI_SET_SNIFF);
914 
915         if (p_dev->pm_mode_attempted & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF)) {
916           p_dev->pm_mode_failed |=
917               ((BTA_DM_PM_PARK | BTA_DM_PM_SNIFF) & p_dev->pm_mode_attempted);
918           bta_dm_pm_stop_timer_by_mode(bd_addr, p_dev->pm_mode_attempted);
919           bta_dm_pm_set_mode(bd_addr, BTA_DM_PM_NO_ACTION, BTA_DM_PM_RESTART);
920         }
921       } else {
922 #if (BTM_SSR_INCLUDED == TRUE)
923         if (p_dev->prev_low) {
924           /* need to send the SSR paramaters to controller again */
925           bta_dm_pm_ssr(p_dev->peer_bdaddr, BTA_DM_PM_SSR0);
926         }
927         p_dev->prev_low = BTM_PM_STS_ACTIVE;
928 #endif
929         /* link to active mode, need to restart the timer for next low power
930          * mode if needed */
931         bta_dm_pm_stop_timer(bd_addr);
932         bta_dm_pm_set_mode(bd_addr, BTA_DM_PM_NO_ACTION, BTA_DM_PM_RESTART);
933       }
934       break;
935 
936 #if (BTM_SSR_INCLUDED == TRUE)
937     case BTM_PM_STS_PARK:
938     case BTM_PM_STS_HOLD:
939       /* save the previous low power mode - for SSR.
940        * SSR parameters are sent to controller on "conn open".
941        * the numbers stay good until park/hold/detach */
942       if (p_dev->info & BTA_DM_DI_USE_SSR) p_dev->prev_low = status;
943       break;
944 
945     case BTM_PM_STS_SSR:
946       if (value)
947         p_dev->info |= BTA_DM_DI_USE_SSR;
948       else
949         p_dev->info &= ~BTA_DM_DI_USE_SSR;
950       break;
951 #endif
952     case BTM_PM_STS_SNIFF:
953       if (hci_status == 0) {
954         /* Stop PM timer now if already active for
955          * particular device since link is already
956          * put in sniff mode by remote device, and
957          * PM timer sole purpose is to put the link
958          * in sniff mode from host side.
959          */
960         bta_dm_pm_stop_timer(bd_addr);
961       } else {
962         p_dev->info &=
963             ~(BTA_DM_DI_SET_SNIFF | BTA_DM_DI_INT_SNIFF | BTA_DM_DI_ACP_SNIFF);
964         if (info & BTA_DM_DI_SET_SNIFF)
965           p_dev->info |= BTA_DM_DI_INT_SNIFF;
966         else
967           p_dev->info |= BTA_DM_DI_ACP_SNIFF;
968       }
969       break;
970 
971     case BTM_PM_STS_ERROR:
972       p_dev->info &= ~BTA_DM_DI_SET_SNIFF;
973       break;
974 
975     default:
976       break;
977   }
978 }
979 
980 /** Process pm timer event from btm */
981 void bta_dm_pm_timer(const RawAddress& bd_addr, tBTA_DM_PM_ACTION pm_request) {
982   APPL_TRACE_EVENT("%s", __func__);
983   bta_dm_pm_set_mode(bd_addr, pm_request, BTA_DM_PM_EXECUTE);
984 }
985 
986 /*******************************************************************************
987  *
988  * Function         bta_dm_find_peer_device
989  *
990  * Description      Given an address, find the associated control block.
991  *
992  * Returns          tBTA_DM_PEER_DEVICE
993  *
994  ******************************************************************************/
995 tBTA_DM_PEER_DEVICE* bta_dm_find_peer_device(const RawAddress& peer_addr) {
996   tBTA_DM_PEER_DEVICE* p_dev = NULL;
997 
998   for (int i = 0; i < bta_dm_cb.device_list.count; i++) {
999     if (bta_dm_cb.device_list.peer_device[i].peer_bdaddr == peer_addr) {
1000       p_dev = &bta_dm_cb.device_list.peer_device[i];
1001       break;
1002     }
1003   }
1004   return p_dev;
1005 }
1006 
1007 /*******************************************************************************
1008  *
1009  * Function         bta_dm_is_sco_active
1010  *
1011  * Description      Loop through connected services for HFP+State=SCO
1012  *
1013  * Returns          bool. true if SCO active, else false
1014  *
1015  ******************************************************************************/
1016 static bool bta_dm_pm_is_sco_active() {
1017   int j;
1018   bool bScoActive = false;
1019 
1020   for (j = 0; j < bta_dm_conn_srvcs.count; j++) {
1021     /* check if an entry already present */
1022     if ((bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_AG) &&
1023         (bta_dm_conn_srvcs.conn_srvc[j].state == BTA_SYS_SCO_OPEN)) {
1024       bScoActive = true;
1025       break;
1026     }
1027   }
1028 
1029   APPL_TRACE_DEBUG("bta_dm_is_sco_active: SCO active: %d", bScoActive);
1030   return bScoActive;
1031 }
1032 
1033 #if (BTM_SSR_INCLUDED == TRUE)
1034 /*******************************************************************************
1035  *
1036  * Function        bta_dm_get_sco_index
1037  *
1038  * Description     Loop through connected services for HFP+State=SCO
1039  *
1040  * Returns         index at which SCO is connected, in absence of SCO return -1
1041  *
1042  ******************************************************************************/
1043 static int bta_dm_get_sco_index() {
1044   for (int j = 0; j < bta_dm_conn_srvcs.count; j++) {
1045     /* check for SCO connected index */
1046     if ((bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_AG) &&
1047         (bta_dm_conn_srvcs.conn_srvc[j].state == BTA_SYS_SCO_OPEN)) {
1048       return j;
1049     }
1050   }
1051   return -1;
1052 }
1053 #endif
1054 
1055 /*******************************************************************************
1056  *
1057  * Function         bta_dm_pm_hid_check
1058  *
1059  * Description      Disables/Enables sniff in link policy based on SCO Up/Down
1060  *
1061  * Returns          None
1062  *
1063  ******************************************************************************/
1064 static void bta_dm_pm_hid_check(bool bScoActive) {
1065   int j;
1066 
1067   /* if HID is active, disable the link policy */
1068   for (j = 0; j < bta_dm_conn_srvcs.count; j++) {
1069     /* check if an entry already present */
1070     if (bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_HH) {
1071       APPL_TRACE_DEBUG(
1072           "SCO status change(Active: %d), modify HID link policy. state: %d",
1073           bScoActive, bta_dm_conn_srvcs.conn_srvc[j].state);
1074       bta_dm_pm_set_sniff_policy(
1075           bta_dm_find_peer_device(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr),
1076           bScoActive);
1077 
1078       /* if we had disabled link policy, seems like the hid device stop retrying
1079        * SNIFF after a few tries. force sniff if needed */
1080       if (!bScoActive)
1081         bta_dm_pm_set_mode(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr,
1082                            BTA_DM_PM_NO_ACTION, BTA_DM_PM_RESTART);
1083     }
1084   }
1085 }
1086 
1087 /*******************************************************************************
1088  *
1089  * Function         bta_dm_pm_set_sniff_policy
1090  *
1091  * Description      Disables/Enables sniff in link policy for the give device
1092  *
1093  * Returns          None
1094  *
1095  ******************************************************************************/
1096 static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE* p_dev,
1097                                        bool bDisable) {
1098   uint16_t policy_setting;
1099 
1100   if (!p_dev) return;
1101 
1102   if (bDisable) {
1103     policy_setting =
1104         bta_dm_cb.cur_policy & (HCI_ENABLE_MASTER_SLAVE_SWITCH |
1105                                 HCI_ENABLE_HOLD_MODE | HCI_ENABLE_PARK_MODE);
1106 
1107   } else {
1108     /*  allow sniff after sco is closed */
1109     policy_setting = bta_dm_cb.cur_policy;
1110   }
1111 
1112   /* if disabling SNIFF, make sure link is Active */
1113   if (bDisable) bta_dm_pm_active(p_dev->peer_bdaddr);
1114 
1115   /* update device record and set link policy */
1116   p_dev->link_policy = policy_setting;
1117   BTM_SetLinkPolicy(p_dev->peer_bdaddr, &policy_setting);
1118 }
1119 
1120 /*******************************************************************************
1121  *
1122  * Function         bta_dm_pm_obtain_controller_state
1123  *
1124  * Description      This function obtains the consolidated controller power
1125  *                  state
1126  *
1127  * Parameters:
1128  *
1129  ******************************************************************************/
1130 tBTA_DM_CONTRL_STATE bta_dm_pm_obtain_controller_state(void) {
1131   /*   Did not use counts as it is not sure, how accurate the count values are
1132    *in
1133    **  bta_dm_cb.device_list.count > 0 || bta_dm_cb.device_list.le_count > 0 */
1134 
1135   tBTA_DM_CONTRL_STATE cur_state = BTA_DM_CONTRL_UNKNOWN;
1136   cur_state = BTM_PM_ReadControllerState();
1137 
1138   APPL_TRACE_DEBUG("bta_dm_pm_obtain_controller_state: %d", cur_state);
1139   return cur_state;
1140 }
1141