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