• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright 2018 The Android Open Source Project
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 #include "connection_manager.h"
20 
21 #include <base/functional/bind.h>
22 #include <base/functional/callback.h>
23 #include <base/location.h>
24 #include <bluetooth/log.h>
25 
26 #include <map>
27 #include <memory>
28 #include <set>
29 
30 #include "gd/hci/acl_manager.h"
31 #include "gd/hci/controller_interface.h"
32 #include "main/shim/acl_api.h"
33 #include "main/shim/entry.h"
34 #include "main/shim/helpers.h"
35 #include "main/shim/le_scanning_manager.h"
36 #include "main/shim/metrics_api.h"
37 #include "osi/include/alarm.h"
38 #include "stack/btm/btm_dev.h"
39 #include "stack/include/advertise_data_parser.h"
40 #include "stack/include/bt_types.h"
41 #include "stack/include/btm_ble_api.h"
42 #include "stack/include/btm_client_interface.h"
43 #include "stack/include/btm_log_history.h"
44 #include "stack/include/main_thread.h"
45 #include "types/raw_address.h"
46 
47 #define DIRECT_CONNECT_TIMEOUT (30 * 1000) /* 30 seconds */
48 
49 using namespace bluetooth;
50 
51 constexpr char kBtmLogTagACL[] = "ACL";
52 constexpr char kBtmLogTagTA[] = "TA";
53 
54 struct closure_data {
55   base::OnceClosure user_task;
56 };
57 
58 extern std::string get_client_name(uint8_t gatt_if);
59 
alarm_closure_cb(void * p)60 static void alarm_closure_cb(void* p) {
61   closure_data* data = (closure_data*)p;
62   std::move(data->user_task).Run();
63   delete data;
64 }
65 
66 // Periodic alarms are not supported, because we clean up data in callback
alarm_set_closure(alarm_t * alarm,uint64_t interval_ms,base::OnceClosure user_task)67 static void alarm_set_closure(alarm_t* alarm, uint64_t interval_ms, base::OnceClosure user_task) {
68   closure_data* data = new closure_data;
69   data->user_task = std::move(user_task);
70   alarm_set_on_mloop(alarm, interval_ms, alarm_closure_cb, data);
71 }
72 
73 using unique_alarm_ptr = std::unique_ptr<alarm_t, decltype(&alarm_free)>;
74 
75 namespace {
ACL_AcceptLeConnectionFrom(const tBLE_BD_ADDR & legacy_address_with_type,bool is_direct)76 static void ACL_AcceptLeConnectionFrom(const tBLE_BD_ADDR& legacy_address_with_type,
77                                        bool is_direct) {
78   BTM_LogHistory(kBtmLogTagACL, legacy_address_with_type, "Allow connection from", "Le");
79   bluetooth::shim::GetAclManager()->CreateLeConnection(
80           bluetooth::ToAddressWithTypeFromLegacy(legacy_address_with_type), is_direct);
81 }
82 
ACL_IgnoreLeConnectionFrom(const tBLE_BD_ADDR & legacy_address_with_type)83 static void ACL_IgnoreLeConnectionFrom(const tBLE_BD_ADDR& legacy_address_with_type) {
84   BTM_LogHistory(kBtmLogTagACL, legacy_address_with_type, "Ignore connection from", "Le");
85   bluetooth::shim::GetAclManager()->CancelLeConnect(
86           bluetooth::ToAddressWithTypeFromLegacy(legacy_address_with_type));
87 }
88 }  // namespace
89 
90 namespace connection_manager {
91 
92 struct tAPPS_CONNECTING {
93   // ids of clients doing background connection to given device
94   std::set<tAPP_ID> doing_bg_conn;
95   std::set<tAPP_ID> doing_targeted_announcements_conn;
96   bool is_in_accept_list;
97 
98   // Apps trying to do direct connection.
99   std::map<tAPP_ID, unique_alarm_ptr> doing_direct_conn;
100 };
101 
102 namespace {
103 // Maps address to apps trying to connect to it
104 std::map<RawAddress, tAPPS_CONNECTING> bgconn_dev;
105 
num_of_targeted_announcements_users(void)106 int num_of_targeted_announcements_users(void) {
107   return std::count_if(bgconn_dev.begin(), bgconn_dev.end(), [](const auto& pair) {
108     return !pair.second.is_in_accept_list && !pair.second.doing_targeted_announcements_conn.empty();
109   });
110 }
111 
is_anyone_interested_to_use_accept_list(const std::map<RawAddress,tAPPS_CONNECTING>::iterator it)112 bool is_anyone_interested_to_use_accept_list(
113         const std::map<RawAddress, tAPPS_CONNECTING>::iterator it) {
114   if (!it->second.doing_targeted_announcements_conn.empty()) {
115     return !it->second.doing_direct_conn.empty();
116   }
117   return !it->second.doing_bg_conn.empty() || !it->second.doing_direct_conn.empty();
118 }
119 
is_anyone_connecting(const std::map<RawAddress,tAPPS_CONNECTING>::iterator it)120 bool is_anyone_connecting(const std::map<RawAddress, tAPPS_CONNECTING>::iterator it) {
121   return !it->second.doing_bg_conn.empty() || !it->second.doing_direct_conn.empty() ||
122          !it->second.doing_targeted_announcements_conn.empty();
123 }
124 
accept_list_is_full()125 static bool accept_list_is_full() {
126   uint8_t accept_list_size = shim::GetController()->GetLeFilterAcceptListSize();
127 
128   int num_entries = 0;
129   for (const auto& entry : bgconn_dev) {
130     if (entry.second.is_in_accept_list) {
131       num_entries++;
132     }
133   }
134 
135   if (num_entries >= accept_list_size) {
136     return true;
137   }
138 
139   return false;
140 }
141 
142 }  // namespace
143 
144 /** Return all apps interested in device, or empty set if not found. */
get_apps_connecting_to(const RawAddress & address)145 std::set<tAPP_ID> get_apps_connecting_to(const RawAddress& address) {
146   log::debug("address={}", address);
147   auto it = bgconn_dev.find(address);
148   if (it == bgconn_dev.end()) {
149     return std::set<tAPP_ID>();
150   }
151 
152   std::set<tAPP_ID> result;
153   result.insert(it->second.doing_bg_conn.begin(), it->second.doing_bg_conn.end());
154   result.insert(it->second.doing_targeted_announcements_conn.begin(),
155                 it->second.doing_targeted_announcements_conn.end());
156 
157   for (const auto& entry : it->second.doing_direct_conn) {
158     result.insert(entry.first);
159   }
160   return result;
161 }
162 
IsTargetedAnnouncement(const uint8_t * p_eir,uint16_t eir_len)163 static bool IsTargetedAnnouncement(const uint8_t* p_eir, uint16_t eir_len) {
164   const uint8_t* p_service_data = p_eir;
165   uint8_t service_data_len = 0;
166 
167   while ((p_service_data = AdvertiseDataParser::GetFieldByType(
168                   p_service_data + service_data_len,
169                   eir_len - (p_service_data - p_eir) - service_data_len,
170                   BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE, &service_data_len))) {
171     uint16_t uuid;
172     uint8_t announcement_type;
173     const uint8_t* p_tmp = p_service_data;
174 
175     if (service_data_len < 3) {
176       continue;
177     }
178 
179     STREAM_TO_UINT16(uuid, p_tmp);
180     log::debug("Found UUID 0x{:04x}", uuid);
181 
182     if (uuid != 0x184E && uuid != 0x1853) {
183       continue;
184     }
185 
186     STREAM_TO_UINT8(announcement_type, p_tmp);
187     log::debug("Found announcement_type 0x{:02x}", announcement_type);
188     if (announcement_type == 0x01) {
189       return true;
190     }
191   }
192   return false;
193 }
194 
195 static void schedule_direct_connect_add(uint8_t app_id, const RawAddress& address);
196 
target_announcement_observe_results_cb(tBTM_INQ_RESULTS * p_inq,const uint8_t * p_eir,uint16_t eir_len)197 static void target_announcement_observe_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir,
198                                                    uint16_t eir_len) {
199   auto addr = p_inq->remote_bd_addr;
200   auto it = bgconn_dev.find(addr);
201   if (it == bgconn_dev.end() || it->second.doing_targeted_announcements_conn.empty()) {
202     return;
203   }
204 
205   if (!IsTargetedAnnouncement(p_eir, eir_len)) {
206     log::debug("Not a targeted announcement for device {}", addr);
207     return;
208   }
209 
210   log::info("Found targeted announcement for device {}", addr);
211 
212   if (it->second.is_in_accept_list) {
213     log::info("Device {} is already connecting", addr);
214     return;
215   }
216 
217   if (get_btm_client_interface().peer.BTM_GetHCIConnHandle(addr, BT_TRANSPORT_LE) != 0xFFFF) {
218     log::debug("Device {} already connected", addr);
219     return;
220   }
221 
222   BTM_LogHistory(kBtmLogTagTA, addr, "Found TA from");
223 
224   /* Take fist app_id and use it for direct_connect */
225   auto app_id = *(it->second.doing_targeted_announcements_conn.begin());
226 
227   /* If scan is ongoing lets stop it */
228   do_in_main_thread(base::BindOnce(schedule_direct_connect_add, app_id, addr));
229 }
230 
target_announcements_filtering_set(bool enable)231 static void target_announcements_filtering_set(bool enable) {
232   log::debug("enable {}", enable);
233   BTM_LogHistory(kBtmLogTagTA, RawAddress::kEmpty, (enable ? "Start filtering" : "Stop filtering"));
234 
235   /* Safe to call as if there is no support for filtering, this call will be
236    * ignored. */
237   bluetooth::shim::set_target_announcements_filter(enable);
238   BTM_BleTargetAnnouncementObserve(enable, target_announcement_observe_results_cb);
239 }
240 
241 /** Add a device to the background connection list for targeted announcements.
242  * Returns
243  *   true if device added to the list, or already in list,
244  *   false otherwise
245  */
background_connect_targeted_announcement_add(tAPP_ID app_id,const RawAddress & address)246 bool background_connect_targeted_announcement_add(tAPP_ID app_id, const RawAddress& address) {
247   log::info("app_id={}, address={}", static_cast<int>(app_id), address);
248 
249   bool disable_accept_list = false;
250 
251   auto it = bgconn_dev.find(address);
252   if (it != bgconn_dev.end()) {
253     // check if filtering already enabled
254     if (it->second.doing_targeted_announcements_conn.count(app_id)) {
255       log::info("app_id={}, already doing targeted announcement filtering to address={}",
256                 static_cast<int>(app_id), address);
257       return true;
258     }
259 
260     bool targeted_filtering_enabled = !it->second.doing_targeted_announcements_conn.empty();
261 
262     // Check if connecting
263     if (!it->second.doing_direct_conn.empty()) {
264       log::info("app_id={}, address={}, already in direct connection", static_cast<int>(app_id),
265                 address);
266 
267     } else if (!targeted_filtering_enabled && !it->second.doing_bg_conn.empty()) {
268       // device is already in the acceptlist so we would have to remove it
269       log::info("already doing background connection to address={}. Need to disable it.", address);
270       disable_accept_list = true;
271     }
272   }
273 
274   if (disable_accept_list) {
275     ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(address));
276     bgconn_dev[address].is_in_accept_list = false;
277   }
278 
279   bgconn_dev[address].doing_targeted_announcements_conn.insert(app_id);
280   if (bgconn_dev[address].doing_targeted_announcements_conn.size() == 1) {
281     BTM_LogHistory(kBtmLogTagTA, address, "Allow connection from");
282   }
283 
284   if (num_of_targeted_announcements_users() == 1) {
285     target_announcements_filtering_set(true);
286   }
287 
288   return true;
289 }
290 
291 /** Add a device from the background connection list.  Returns true if device
292  * added to the list, or already in list, false otherwise */
background_connect_add(uint8_t app_id,const RawAddress & address)293 bool background_connect_add(uint8_t app_id, const RawAddress& address) {
294   log::debug("app_id={}, address={}", static_cast<int>(app_id), address);
295   auto it = bgconn_dev.find(address);
296   bool in_acceptlist = false;
297   bool is_targeted_announcement_enabled = false;
298   if (it != bgconn_dev.end()) {
299     // device already in the acceptlist, just add interested app to the list
300     if (it->second.doing_bg_conn.count(app_id)) {
301       log::debug("app_id={}, already doing background connection to address={}",
302                  static_cast<int>(app_id), address);
303       return true;
304     }
305 
306     // Already in acceptlist ?
307     if (it->second.is_in_accept_list) {
308       log::debug("app_id={}, address={}, already in accept list", static_cast<int>(app_id),
309                  address);
310       in_acceptlist = true;
311     } else {
312       is_targeted_announcement_enabled = !it->second.doing_targeted_announcements_conn.empty();
313     }
314   }
315 
316   if (!in_acceptlist) {
317     // the device is not in the acceptlist
318     if (is_targeted_announcement_enabled) {
319       log::debug("Targeted announcement enabled, do not add to AcceptList");
320     } else {
321       if (accept_list_is_full()) {
322         log::warn("accept list is full ({}), can't add {}",
323                   shim::GetController()->GetLeFilterAcceptListSize(), address);
324         return false;
325       }
326 
327       ACL_AcceptLeConnectionFrom(BTM_Sec_GetAddressWithType(address), false);
328 
329       bgconn_dev[address].is_in_accept_list = true;
330     }
331   }
332 
333   // create entry for address, and insert app_id.
334   // new tAPPS_CONNECTING will be default constructed if not exist
335   bgconn_dev[address].doing_bg_conn.insert(app_id);
336   return true;
337 }
338 
339 /** Removes all registrations for connection for given device.
340  * Returns true if anything was removed, false otherwise */
remove_unconditional(const RawAddress & address)341 bool remove_unconditional(const RawAddress& address) {
342   log::debug("address={}", address);
343   int count = bgconn_dev.erase(address);
344   if (count == 0) {
345     log::info("address {} is not found", address);
346   }
347 
348   ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(address));
349   return count > 0;
350 }
351 
352 /** Remove device from the background connection device list or listening to
353  * advertising list.  Returns true if device was on the list and was
354  * successfully removed */
background_connect_remove(uint8_t app_id,const RawAddress & address)355 bool background_connect_remove(uint8_t app_id, const RawAddress& address) {
356   log::debug("app_id={}, address={}", static_cast<int>(app_id), address);
357   auto it = bgconn_dev.find(address);
358   if (it == bgconn_dev.end()) {
359     log::warn("address {} is not found", address);
360     return false;
361   }
362 
363   bool accept_list_enabled = it->second.is_in_accept_list;
364   auto num_of_targeted_announcements_before_remove =
365           it->second.doing_targeted_announcements_conn.size();
366 
367   bool removed_from_bg_conn = (it->second.doing_bg_conn.erase(app_id) > 0);
368   bool removed_from_ta = (it->second.doing_targeted_announcements_conn.erase(app_id) > 0);
369   if (!removed_from_bg_conn && !removed_from_ta) {
370     log::warn("Failed to remove background connection app {} for address {}",
371               static_cast<int>(app_id), address);
372     return false;
373   }
374 
375   if (removed_from_ta && it->second.doing_targeted_announcements_conn.size() == 0) {
376     BTM_LogHistory(kBtmLogTagTA, address, "Ignore connection from");
377   }
378 
379   if (is_anyone_connecting(it)) {
380     log::debug("some app is still connecting, app_id={}, address={}", static_cast<int>(app_id),
381                address);
382     /* Check which method should be used now.*/
383     if (!accept_list_enabled) {
384       /* Accept list was not used */
385       if (!it->second.doing_targeted_announcements_conn.empty()) {
386         /* Keep using filtering */
387         log::debug("Keep using target announcement filtering");
388       } else if (!it->second.doing_bg_conn.empty()) {
389         ACL_AcceptLeConnectionFrom(BTM_Sec_GetAddressWithType(address), false);
390         bgconn_dev[address].is_in_accept_list = true;
391       }
392     }
393     return true;
394   }
395 
396   bgconn_dev.erase(it);
397 
398   // no more apps interested - remove from accept list and delete record
399   if (accept_list_enabled) {
400     ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(address));
401     return true;
402   }
403 
404   if ((num_of_targeted_announcements_before_remove > 0) &&
405       num_of_targeted_announcements_users() == 0) {
406     target_announcements_filtering_set(true);
407   }
408 
409   return true;
410 }
411 
is_background_connection(const RawAddress & address)412 bool is_background_connection(const RawAddress& address) {
413   auto it = bgconn_dev.find(address);
414   if (it == bgconn_dev.end()) {
415     return false;
416   }
417   return it->second.is_in_accept_list;
418 }
419 
420 /** deregister all related background connetion device. */
on_app_deregistered(uint8_t app_id)421 void on_app_deregistered(uint8_t app_id) {
422   log::debug("app_id={}", static_cast<int>(app_id));
423   auto it = bgconn_dev.begin();
424   auto end = bgconn_dev.end();
425   /* update the BG conn device list */
426   while (it != end) {
427     it->second.doing_bg_conn.erase(app_id);
428 
429     it->second.doing_direct_conn.erase(app_id);
430 
431     if (is_anyone_connecting(it)) {
432       it++;
433       continue;
434     }
435 
436     ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(it->first));
437     it = bgconn_dev.erase(it);
438   }
439 }
440 
remove_all_clients_with_pending_connections(const RawAddress & address)441 static void remove_all_clients_with_pending_connections(const RawAddress& address) {
442   log::debug("address={}", address);
443   auto it = bgconn_dev.find(address);
444   while (it != bgconn_dev.end() && !it->second.doing_direct_conn.empty()) {
445     uint8_t app_id = it->second.doing_direct_conn.begin()->first;
446     direct_connect_remove(app_id, address);
447     it = bgconn_dev.find(address);
448   }
449 }
450 
on_connection_complete(const RawAddress & address)451 void on_connection_complete(const RawAddress& address) {
452   log::info("Le connection completed to device:{}", address);
453 
454   remove_all_clients_with_pending_connections(address);
455 }
456 
on_connection_timed_out_from_shim(const RawAddress & address)457 void on_connection_timed_out_from_shim(const RawAddress& address) {
458   log::info("Connection failed {}", address);
459   on_connection_timed_out(0x00, address);
460 }
461 
462 /** Reset bg device list. If called after controller reset, set |after_reset|
463  * to true, as there is no need to wipe controller acceptlist in this case. */
reset(bool after_reset)464 void reset(bool after_reset) {
465   bgconn_dev.clear();
466   if (!after_reset) {
467     target_announcements_filtering_set(false);
468     bluetooth::shim::GetAclManager()->ClearFilterAcceptList();
469   }
470 }
471 
wl_direct_connect_timeout_cb(uint8_t app_id,const RawAddress & address)472 static void wl_direct_connect_timeout_cb(uint8_t app_id, const RawAddress& address) {
473   log::debug("app_id={}, address={}", static_cast<int>(app_id), address);
474   on_connection_timed_out(app_id, address);
475 
476   // TODO: this would free the timer, from within the timer callback, which is
477   // bad.
478   direct_connect_remove(app_id, address, true);
479 }
480 
find_in_device_record(const RawAddress & bd_addr,tBLE_BD_ADDR * address_with_type)481 static void find_in_device_record(const RawAddress& bd_addr, tBLE_BD_ADDR* address_with_type) {
482   const tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr);
483   if (p_dev_rec == nullptr) {
484     return;
485   }
486 
487   if (p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) {
488     if (p_dev_rec->ble.identity_address_with_type.bda.IsEmpty()) {
489       *address_with_type = {.type = p_dev_rec->ble.AddressType(), .bda = bd_addr};
490       return;
491     }
492     *address_with_type = p_dev_rec->ble.identity_address_with_type;
493     return;
494   }
495   *address_with_type = {.type = BLE_ADDR_PUBLIC, .bda = bd_addr};
496   return;
497 }
498 
direct_connect_add(uint8_t app_id,const RawAddress & address,tBLE_ADDR_TYPE addr_type)499 bool direct_connect_add(uint8_t app_id, const RawAddress& address, tBLE_ADDR_TYPE addr_type) {
500   tBLE_BD_ADDR address_with_type{
501           .type = addr_type,
502           .bda = address,
503   };
504 
505   find_in_device_record(address, &address_with_type);
506 
507   if (address_with_type.type == BLE_ADDR_ANONYMOUS) {
508     log::warn("Can't use anonymous address for connection: {}", address_with_type);
509     return false;
510   }
511 
512   log::debug("app_id=0x{:x}, address={} (initial type: {})", static_cast<int>(app_id),
513              address_with_type, AddressTypeText(addr_type));
514 
515   bool in_acceptlist = false;
516   auto it = bgconn_dev.find(address);
517   if (it != bgconn_dev.end()) {
518     const tAPPS_CONNECTING& info = it->second;
519     // app already trying to connect to this particular device
520     if (info.doing_direct_conn.count(app_id)) {
521       log::info("attempt from app_id=0x{:x} to {} already in progress", app_id, address_with_type);
522       bluetooth::shim::LogMetricLeConnectionRejected(bluetooth::ToGdAddress(address));
523       return false;
524     }
525 
526     // This is to match existing GD connection manager behavior - if multiple apps try direct
527     // connect at same time, only 1st request is fully processed
528     if (!info.doing_direct_conn.empty()) {
529       log::info("app_id=0x{:x}: attempt from other app already in progress, will merge {}", app_id,
530                 address_with_type);
531       return true;
532     }
533 
534     // are we already in the acceptlist ?
535     if (info.is_in_accept_list) {
536       log::warn("background connect attempt already in progress app_id=0x{:x} {}", app_id,
537                 address_with_type);
538       in_acceptlist = true;
539     }
540   }
541 
542   if (!in_acceptlist) {
543     if (accept_list_is_full()) {
544       log::warn("accept list is full ({}), can't add {}",
545                 shim::GetController()->GetLeFilterAcceptListSize(), address_with_type);
546       return false;
547     }
548 
549     ACL_AcceptLeConnectionFrom(address_with_type, true /* is_direct */);
550     bgconn_dev[address].is_in_accept_list = true;
551   } else {
552     // if already in accept list, we should just bump parameters up for direct
553     // connection. There is no API for that yet, so use API that's adding to accept list.
554     ACL_AcceptLeConnectionFrom(address_with_type, true /* is_direct */);
555   }
556 
557   // Setup a timer
558   alarm_t* timeout = alarm_new("wl_conn_params_30s");
559   alarm_set_closure(timeout, DIRECT_CONNECT_TIMEOUT,
560                     base::BindOnce(&wl_direct_connect_timeout_cb, app_id, address));
561 
562   bgconn_dev[address].doing_direct_conn.emplace(app_id, unique_alarm_ptr(timeout, &alarm_free));
563   return true;
564 }
565 
schedule_direct_connect_add(uint8_t app_id,const RawAddress & address)566 static void schedule_direct_connect_add(uint8_t app_id, const RawAddress& address) {
567   direct_connect_add(app_id, address);
568 }
569 
direct_connect_remove(uint8_t app_id,const RawAddress & address,bool connection_timeout)570 bool direct_connect_remove(uint8_t app_id, const RawAddress& address, bool connection_timeout) {
571   log::debug("app_id={}, address={}", static_cast<int>(app_id), address);
572   auto it = bgconn_dev.find(address);
573   if (it == bgconn_dev.end()) {
574     log::warn("unable to find entry to remove: {}", address);
575     return false;
576   }
577 
578   auto app_it = it->second.doing_direct_conn.find(app_id);
579   if (app_it == it->second.doing_direct_conn.end()) {
580     log::warn("unable to find direct connection to remove: {}", address);
581     return false;
582   }
583 
584   /* Let see if the device was connected due to Target Announcements.*/
585   bool is_targeted_announcement_enabled = !it->second.doing_targeted_announcements_conn.empty();
586 
587   // this will free the alarm
588   it->second.doing_direct_conn.erase(app_it);
589 
590   if (is_anyone_interested_to_use_accept_list(it)) {
591     if (connection_timeout) {
592       /* In such case we need to add device back to allow list because, when connection timeout
593        * out, the lower layer removes device from the allow list.
594        */
595       ACL_AcceptLeConnectionFrom(BTM_Sec_GetAddressWithType(address), false /* is_direct */);
596     }
597     return true;
598   }
599 
600   // no more apps interested - remove from acceptlist
601   ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(address));
602 
603   if (!is_targeted_announcement_enabled) {
604     bgconn_dev.erase(it);
605   } else {
606     it->second.is_in_accept_list = false;
607   }
608 
609   return true;
610 }
611 
dump(int fd)612 void dump(int fd) {
613   dprintf(fd, "\nconnection_manager state:\n");
614   if (bgconn_dev.empty()) {
615     dprintf(fd, "\tno Low Energy connection attempts\n");
616     return;
617   }
618 
619   dprintf(fd, "\tdevices attempting connection: %d", (int)bgconn_dev.size());
620   for (const auto& entry : bgconn_dev) {
621     // TODO: confirm whether we need to replace this
622     dprintf(fd, "\n\t * %s:\t\tin_accept_list: %s\t cap_targeted_announcements: %s",
623             entry.first.ToRedactedStringForLogging().c_str(),
624             entry.second.is_in_accept_list ? "true" : "false",
625             entry.second.doing_targeted_announcements_conn.empty() ? "false" : "true");
626 
627     if (!entry.second.doing_direct_conn.empty()) {
628       dprintf(fd, "\n\t\tapps doing direct connect: ");
629       for (const auto& id : entry.second.doing_direct_conn) {
630         dprintf(fd, "%s (%d), ", get_client_name(id.first).c_str(), id.first);
631       }
632     }
633 
634     if (!entry.second.doing_bg_conn.empty()) {
635       dprintf(fd, "\n\t\tapps doing background connect: ");
636       for (const auto& id : entry.second.doing_bg_conn) {
637         dprintf(fd, "%s (%d), ", get_client_name(id).c_str(), id);
638       }
639     }
640   }
641   dprintf(fd, "\n");
642 }
643 
644 }  // namespace connection_manager
645