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