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