1 /*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define ATRACE_TAG ATRACE_TAG_APP
18
19 #include "hal/snoop_logger.h"
20
21 #include <arpa/inet.h>
22 #include <bluetooth/log.h>
23 #include <com_android_bluetooth_flags.h>
24 #ifdef __ANDROID__
25 #include <cutils/trace.h>
26 #endif // __ANDROID__
27 #include <sys/stat.h>
28
29 #include <algorithm>
30 #include <bitset>
31 #include <chrono>
32 #include <sstream>
33
34 #include "common/circular_buffer.h"
35 #include "common/strings.h"
36 #include "hal/snoop_logger_common.h"
37 #include "hci/hci_packets.h"
38 #include "os/files.h"
39 #include "os/parameter_provider.h"
40 #include "os/system_properties.h"
41
42 #ifdef USE_FAKE_TIMERS
43 #include "os/fake_timer/fake_timerfd.h"
44 using bluetooth::os::fake_timer::fake_timerfd_get_clock;
45 #endif
46
47 namespace bluetooth {
48 namespace hal {
49
50 // Adds L2CAP channel to acceptlist.
AddL2capCid(uint16_t local_cid,uint16_t remote_cid)51 void FilterTracker::AddL2capCid(uint16_t local_cid, uint16_t remote_cid) {
52 l2c_local_cid.insert(local_cid);
53 l2c_remote_cid.insert(remote_cid);
54 }
55
56 // Sets L2CAP channel that RFCOMM uses.
SetRfcommCid(uint16_t local_cid,uint16_t remote_cid)57 void FilterTracker::SetRfcommCid(uint16_t local_cid, uint16_t remote_cid) {
58 rfcomm_local_cid = local_cid;
59 rfcomm_remote_cid = remote_cid;
60 }
61
62 // Remove L2CAP channel from acceptlist.
RemoveL2capCid(uint16_t local_cid,uint16_t remote_cid)63 void FilterTracker::RemoveL2capCid(uint16_t local_cid, uint16_t remote_cid) {
64 if (rfcomm_local_cid == local_cid) {
65 rfcomm_channels.clear();
66 rfcomm_channels.insert(0);
67 rfcomm_local_cid = 0;
68 rfcomm_remote_cid = 0;
69 }
70
71 l2c_local_cid.erase(local_cid);
72 l2c_remote_cid.erase(remote_cid);
73 }
74
AddRfcommDlci(uint8_t channel)75 void FilterTracker::AddRfcommDlci(uint8_t channel) { rfcomm_channels.insert(channel); }
76
IsAcceptlistedL2cap(bool local,uint16_t cid)77 bool FilterTracker::IsAcceptlistedL2cap(bool local, uint16_t cid) {
78 const auto& set = local ? l2c_local_cid : l2c_remote_cid;
79 return set.find(cid) != set.end();
80 }
81
IsRfcommChannel(bool local,uint16_t cid)82 bool FilterTracker::IsRfcommChannel(bool local, uint16_t cid) {
83 const auto& channel = local ? rfcomm_local_cid : rfcomm_remote_cid;
84 return cid == channel;
85 }
86
IsAcceptlistedDlci(uint8_t dlci)87 bool FilterTracker::IsAcceptlistedDlci(uint8_t dlci) {
88 return rfcomm_channels.find(dlci) != rfcomm_channels.end();
89 }
90
SetupProfilesFilter(bool pbap_filtered,bool map_filtered)91 void ProfilesFilter::SetupProfilesFilter(bool pbap_filtered, bool map_filtered) {
92 if (setup_done_flag) {
93 return;
94 }
95 setup_done_flag = true;
96
97 log::debug("SetupProfilesFilter: pbap={}, map={}", pbap_filtered, map_filtered);
98
99 for (int i = 0; i < FILTER_PROFILE_MAX; i++) {
100 profiles[i].type = (profile_type_t)i;
101 profiles[i].enabled = false;
102 profiles[i].rfcomm_opened = false;
103 profiles[i].l2cap_opened = false;
104 }
105
106 if (pbap_filtered) {
107 profiles[FILTER_PROFILE_PBAP].enabled = profiles[FILTER_PROFILE_HFP_HS].enabled =
108 profiles[FILTER_PROFILE_HFP_HF].enabled = true;
109 }
110 if (map_filtered) {
111 profiles[FILTER_PROFILE_MAP].enabled = true;
112 }
113 ch_rfc_l = ch_rfc_r = ch_last = 0;
114
115 PrintProfilesConfig();
116 }
117
IsHfpProfile(bool local,uint16_t cid,uint8_t dlci)118 bool ProfilesFilter::IsHfpProfile(bool local, uint16_t cid, uint8_t dlci) {
119 profile_type_t profile = DlciToProfile(local, cid, dlci);
120 return profile == FILTER_PROFILE_HFP_HS || profile == FILTER_PROFILE_HFP_HF;
121 }
122
IsL2capFlowExt(bool local,uint16_t cid)123 bool ProfilesFilter::IsL2capFlowExt(bool local, uint16_t cid) {
124 profile_type_t profile = CidToProfile(local, cid);
125 if (profile >= 0) {
126 return profiles[profile].flow_ext_l2cap;
127 }
128 return false;
129 }
130
IsRfcommFlowExt(bool local,uint16_t cid,uint8_t dlci)131 bool ProfilesFilter::IsRfcommFlowExt(bool local, uint16_t cid, uint8_t dlci) {
132 profile_type_t profile = DlciToProfile(local, cid, dlci);
133 if (profile >= 0) {
134 current_profile = profile;
135 }
136 return profiles[profile].flow_ext_rfcomm;
137 }
138
CidToProfile(bool local,uint16_t cid)139 profile_type_t ProfilesFilter::CidToProfile(bool local, uint16_t cid) {
140 uint16_t ch;
141 for (int i = 0; i < FILTER_PROFILE_MAX; i++) {
142 if (profiles[i].enabled && profiles[i].l2cap_opened) {
143 ch = local ? profiles[i].lcid : profiles[i].rcid;
144 if (ch == cid) {
145 return (profile_type_t)i;
146 }
147 }
148 }
149 return FILTER_PROFILE_NONE;
150 }
151
DlciToProfile(bool local,uint16_t cid,uint8_t dlci)152 profile_type_t ProfilesFilter::DlciToProfile(bool local, uint16_t cid, uint8_t dlci) {
153 if (!IsRfcommChannel(local, cid)) {
154 return FILTER_PROFILE_NONE;
155 }
156
157 for (int i = 0; i < FILTER_PROFILE_MAX; i++) {
158 if (profiles[i].enabled && profiles[i].l2cap_opened && profiles[i].rfcomm_opened &&
159 profiles[i].scn == (dlci >> 1)) {
160 return (profile_type_t)i;
161 }
162 }
163 return FILTER_PROFILE_NONE;
164 }
165
ProfileL2capOpen(profile_type_t profile,uint16_t lcid,uint16_t rcid,uint16_t psm,bool flow_ext)166 void ProfilesFilter::ProfileL2capOpen(profile_type_t profile, uint16_t lcid, uint16_t rcid,
167 uint16_t psm, bool flow_ext) {
168 if (profiles[profile].l2cap_opened == true) {
169 log::debug("l2cap for {} was already opened. Override it", profile);
170 }
171 log::debug("lcid:={}, rcid={}, psm={}, flow_ext={}, filter profile={}", lcid, rcid, psm, flow_ext,
172 ProfilesFilter::ProfileToString(profile));
173 profiles[profile].lcid = lcid;
174 profiles[profile].rcid = rcid;
175 profiles[profile].psm = psm;
176 profiles[profile].flow_ext_l2cap = flow_ext;
177 profiles[profile].l2cap_opened = true;
178
179 PrintProfilesConfig();
180 }
181
ProfileL2capClose(profile_type_t profile)182 void ProfilesFilter::ProfileL2capClose(profile_type_t profile) {
183 if (profile < 0 || profile >= FILTER_PROFILE_MAX) {
184 return;
185 }
186 profiles[profile].l2cap_opened = false;
187 }
188
ProfileRfcommOpen(profile_type_t profile,uint16_t lcid,uint8_t dlci,uint16_t uuid,bool flow_ext)189 void ProfilesFilter::ProfileRfcommOpen(profile_type_t profile, uint16_t lcid, uint8_t dlci,
190 uint16_t uuid, bool flow_ext) {
191 if (profiles[profile].rfcomm_opened == true) {
192 log::debug("rfcomm for {} was already opened. Override it", profile);
193 }
194 log::debug("lcid:={}, dlci={}, uuid={}, flow_ext={}, filter profile={}", lcid, dlci, uuid,
195 flow_ext, ProfilesFilter::ProfileToString(profile));
196 profiles[profile].rfcomm_uuid = uuid;
197 profiles[profile].scn = (dlci >> 1);
198 profiles[profile].flow_ext_rfcomm = flow_ext;
199 profiles[profile].l2cap_opened = true;
200 profiles[profile].rfcomm_opened = true;
201
202 PrintProfilesConfig();
203 }
204
ProfileRfcommClose(profile_type_t profile)205 void ProfilesFilter::ProfileRfcommClose(profile_type_t profile) {
206 if (profile < 0 || profile >= FILTER_PROFILE_MAX) {
207 return;
208 }
209 profiles[profile].rfcomm_opened = false;
210 }
211
IsRfcommChannel(bool local,uint16_t cid)212 bool ProfilesFilter::IsRfcommChannel(bool local, uint16_t cid) {
213 uint16_t channel = local ? ch_rfc_l : ch_rfc_r;
214 return cid == channel;
215 }
216
PrintProfilesConfig()217 void ProfilesFilter::PrintProfilesConfig() {
218 for (int i = 0; i < FILTER_PROFILE_MAX; i++) {
219 if (profiles[i].enabled) {
220 log::debug(
221 "\ntype: {}\nenabled: {}, l2cap_opened: {}, rfcomm_opened: {}\nflow_ext_l2cap: {}, "
222 "flow_ext_rfcomm: {}\nlcid: {}, rcid: {}, rfcomm_uuid: {}, psm: {}\nscn: {}\n",
223 ProfilesFilter::ProfileToString(profiles[i].type), profiles[i].enabled,
224 profiles[i].l2cap_opened, profiles[i].rfcomm_opened, profiles[i].flow_ext_l2cap,
225 profiles[i].flow_ext_rfcomm, profiles[i].lcid, profiles[i].rcid,
226 profiles[i].rfcomm_uuid, profiles[i].psm, profiles[i].psm);
227 }
228 }
229 }
230
231 namespace {
232
233 // Epoch in microseconds since 01/01/0000.
234 constexpr uint64_t kBtSnoopEpochDelta = 0x00dcddb30f2f8000ULL;
235
236 // Qualcomm debug logs handle
237 constexpr uint16_t kQualcommDebugLogHandle = 0xedc;
238
239 // Number of bytes into a packet where you can find the value for a channel.
240 constexpr size_t ACL_CHANNEL_OFFSET = 0;
241 constexpr size_t ACL_LENGTH_OFFSET = 2;
242 constexpr size_t L2CAP_PDU_LENGTH_OFFSET = 4;
243 constexpr size_t L2CAP_CHANNEL_OFFSET = 6;
244 constexpr size_t L2CAP_CONTROL_OFFSET = 8;
245 constexpr size_t RFCOMM_CHANNEL_OFFSET = 8;
246 constexpr size_t RFCOMM_EVENT_OFFSET = 9;
247
248 // RFCOMM filtering consts
249 constexpr uint8_t RFCOMM_SABME = 0x2F; // RFCOMM: Start Asynchronous Balanced Mode (startup cmd)
250 constexpr uint8_t RFCOMM_UA = 0x63; // RFCOMM: Unnumbered Acknowledgement (rsp when connected)
251 constexpr uint8_t RFCOMM_UIH = 0xEF; // RFCOMM: Unnumbered Information with Header check
252
253 constexpr uint8_t START_PACKET_BOUNDARY = 0x02;
254 constexpr uint8_t CONTINUATION_PACKET_BOUNDARY = 0x01;
255 constexpr uint16_t HANDLE_MASK = 0x0FFF;
__anon8e6f38e40202(auto handle) 256 auto GetBoundaryFlag = [](auto handle) { return ((handle) >> 12) & 0x0003; };
257
258 // ProfilesFilter consts
259 constexpr size_t ACL_HEADER_LENGTH = 4;
260 constexpr size_t BASIC_L2CAP_HEADER_LENGTH = 4;
261 constexpr uint8_t EXTRA_BUF_SIZE = 0x40;
262 constexpr uint16_t DEFAULT_PACKET_SIZE = 0x800;
263
264 constexpr uint8_t PROFILE_SCN_PBAP = 19;
265 constexpr uint8_t PROFILE_SCN_MAP = 26;
266
267 constexpr uint16_t PROFILE_PSM_PBAP = 0x1025;
268 constexpr uint16_t PROFILE_PSM_MAP = 0x1029;
269 constexpr uint16_t PROFILE_PSM_RFCOMM = 0x0003;
270
271 constexpr uint16_t PROFILE_UUID_PBAP = 0x112f;
272 constexpr uint16_t PROFILE_UUID_MAP = 0x1132;
273 constexpr uint16_t PROFILE_UUID_HFP_HS = 0x1112;
274 constexpr uint16_t PROFILE_UUID_HFP_HF = 0x111f;
275
htonll(uint64_t ll)276 uint64_t htonll(uint64_t ll) {
277 if constexpr (isLittleEndian) {
278 return static_cast<uint64_t>(htonl(ll & 0xffffffff)) << 32 | htonl(ll >> 32);
279 } else {
280 return ll;
281 }
282 }
283
284 // The number of packets per btsnoop file before we rotate to the next file. As of right now there
285 // are two snoop files that are rotated through. The size can be dynamically configured by setting
286 // the relevant system property
287 constexpr size_t kDefaultBtSnoopMaxPacketsPerFile = 0xffff;
288
289 // We restrict the maximum packet size to 150 bytes
290 constexpr size_t kDefaultBtSnoozMaxBytesPerPacket = 150;
291 constexpr size_t kDefaultBtSnoozMaxPayloadBytesPerPacket =
292 kDefaultBtSnoozMaxBytesPerPacket - sizeof(SnoopLogger::PacketHeaderType);
293
294 using namespace std::chrono_literals;
295 constexpr std::chrono::hours kBtSnoozLogLifeTime = 12h;
296 constexpr std::chrono::hours kBtSnoozLogDeleteRepeatingAlarmInterval = 1h;
297
298 std::mutex filter_tracker_list_mutex;
299 std::unordered_map<uint16_t, FilterTracker> filter_tracker_list;
300 std::unordered_map<uint16_t, uint16_t> local_cid_to_acl;
301
302 std::mutex a2dpMediaChannels_mutex;
303 std::vector<SnoopLogger::A2dpMediaChannel> a2dpMediaChannels;
304
305 std::mutex snoop_log_filters_mutex;
306
307 std::mutex profiles_filter_mutex;
308 std::unordered_map<int16_t, ProfilesFilter> profiles_filter_table;
309 constexpr const char* payload_fill_magic = "PROHIBITED";
310 constexpr const char* cpbr_pattern = "\x0d\x0a+CPBR:";
311 constexpr const char* clcc_pattern = "\x0d\x0a+CLCC:";
312 const uint32_t magic_pat_len = strlen(payload_fill_magic);
313 const uint32_t cpbr_pat_len = strlen(cpbr_pattern);
314 const uint32_t clcc_pat_len = strlen(clcc_pattern);
315
get_btsnoop_log_path(std::string log_dir,bool filtered)316 std::string get_btsnoop_log_path(std::string log_dir, bool filtered) {
317 if (filtered) {
318 log_dir.append(".filtered");
319 }
320 return log_dir;
321 }
322
get_last_log_path(std::string log_file_path)323 std::string get_last_log_path(std::string log_file_path) { return log_file_path.append(".last"); }
324
delete_btsnoop_files(const std::string & log_path)325 void delete_btsnoop_files(const std::string& log_path) {
326 log::info("Deleting logs if they exist");
327 if (os::FileExists(log_path)) {
328 if (!os::RemoveFile(log_path)) {
329 log::error("Failed to remove main log file at \"{}\"", log_path);
330 }
331 } else {
332 log::info("Main log file does not exist at \"{}\"", log_path);
333 }
334 auto last_log_path = get_last_log_path(log_path);
335 if (os::FileExists(last_log_path)) {
336 if (!os::RemoveFile(last_log_path)) {
337 log::error("Failed to remove last log file at \"{}\"", log_path);
338 }
339 } else {
340 log::info("Last log file does not exist at \"{}\"", log_path);
341 }
342 }
343
delete_old_btsnooz_files(const std::string & log_path,const std::chrono::milliseconds log_life_time)344 void delete_old_btsnooz_files(const std::string& log_path,
345 const std::chrono::milliseconds log_life_time) {
346 auto opt_created_ts = os::FileCreatedTime(log_path);
347 if (!opt_created_ts) {
348 return;
349 }
350 #ifdef USE_FAKE_TIMERS
351 auto diff = fake_timerfd_get_clock() - file_creation_time;
352 uint64_t log_lifetime = log_life_time.count();
353 if (diff >= log_lifetime) {
354 #else
355 using namespace std::chrono;
356 auto created_tp = opt_created_ts.value();
357 auto current_tp = std::chrono::system_clock::now();
358
359 auto diff = duration_cast<milliseconds>(current_tp - created_tp);
360 if (diff >= log_life_time) {
361 #endif
362 delete_btsnoop_files(log_path);
363 }
364 }
365
366 size_t get_btsnooz_packet_length_to_write(const HciPacket& packet, SnoopLogger::PacketType type,
367 bool qualcomm_debug_log_enabled) {
368 static const size_t kAclHeaderSize = 4;
369 static const size_t kL2capHeaderSize = 4;
370 static const size_t kL2capCidOffset = (kAclHeaderSize + 2);
371 static const uint16_t kL2capSignalingCid = 0x0001;
372
373 static const size_t kHciAclHandleOffset = 0;
374
375 // Maximum amount of ACL data to log.
376 // Enough for an RFCOMM frame up to the frame check;
377 // not enough for a HID report or audio data.
378 static const size_t kMaxBtsnoozAclSize = 14;
379
380 // Calculate packet length to be included
381 size_t included_length = 0;
382 switch (type) {
383 case SnoopLogger::PacketType::CMD:
384 case SnoopLogger::PacketType::EVT:
385 included_length = packet.size();
386 break;
387
388 case SnoopLogger::PacketType::ACL: {
389 // Log ACL and L2CAP header by default
390 size_t len_hci_acl = kAclHeaderSize + kL2capHeaderSize;
391 // Check if we have enough data for an L2CAP header
392 if (packet.size() > len_hci_acl) {
393 uint16_t l2cap_cid =
394 static_cast<uint16_t>(packet[kL2capCidOffset]) |
395 static_cast<uint16_t>(static_cast<uint16_t>(packet[kL2capCidOffset + 1])
396 << static_cast<uint16_t>(8));
397 uint16_t hci_acl_packet_handle =
398 static_cast<uint16_t>(packet[kHciAclHandleOffset]) |
399 static_cast<uint16_t>(static_cast<uint16_t>(packet[kHciAclHandleOffset + 1])
400 << static_cast<uint16_t>(8));
401 hci_acl_packet_handle &= 0x0fff;
402
403 if (l2cap_cid == kL2capSignalingCid) {
404 // For the signaling CID, take the full packet.
405 // That way, the PSM setup is captured, allowing decoding of PSMs down
406 // the road.
407 return packet.size();
408 } else if (qualcomm_debug_log_enabled && hci_acl_packet_handle == kQualcommDebugLogHandle) {
409 return packet.size();
410 } else {
411 // Otherwise, return as much as we reasonably can
412 len_hci_acl = kMaxBtsnoozAclSize;
413 }
414 }
415 included_length = std::min(len_hci_acl, packet.size());
416 break;
417 }
418
419 case SnoopLogger::PacketType::ISO:
420 case SnoopLogger::PacketType::SCO:
421 default:
422 // We are not logging SCO and ISO packets in snooz log as they may contain voice data
423 break;
424 }
425 return std::min(included_length, kDefaultBtSnoozMaxPayloadBytesPerPacket);
426 }
427
428 } // namespace
429
430 // system properties
431 const std::string SnoopLogger::kBtSnoopMaxPacketsPerFileProperty = "persist.bluetooth.btsnoopsize";
432 const std::string SnoopLogger::kIsDebuggableProperty = "ro.debuggable";
433 const std::string SnoopLogger::kBtSnoopLogModeProperty = "persist.bluetooth.btsnooplogmode";
434 const std::string SnoopLogger::kBtSnoopDefaultLogModeProperty =
435 "persist.bluetooth.btsnoopdefaultmode";
436 const std::string SnoopLogger::kBtSnoopLogPersists = "persist.bluetooth.btsnooplogpersists";
437 // Truncates ACL packets (non-fragment) to fixed (MAX_HCI_ACL_LEN) number of bytes
438 const std::string SnoopLogger::kBtSnoopLogFilterHeadersProperty =
439 "persist.bluetooth.snooplogfilter.headers.enabled";
440 // Discards A2DP media packets (non-split mode)
441 const std::string SnoopLogger::kBtSnoopLogFilterProfileA2dpProperty =
442 "persist.bluetooth.snooplogfilter.profiles.a2dp.enabled";
443 // Filters MAP packets based on the filter mode
444 const std::string SnoopLogger::kBtSnoopLogFilterProfileMapModeProperty =
445 "persist.bluetooth.snooplogfilter.profiles.map";
446 // Filters PBAP and HFP packets (CPBR, CLCC) based on the filter mode
447 const std::string SnoopLogger::kBtSnoopLogFilterProfilePbapModeProperty =
448 "persist.bluetooth.snooplogfilter.profiles.pbap";
449 // Truncates RFCOMM UIH packet to fixed (L2CAP_HEADER_SIZE) number of bytes
450 const std::string SnoopLogger::kBtSnoopLogFilterProfileRfcommProperty =
451 "persist.bluetooth.snooplogfilter.profiles.rfcomm.enabled";
452 const std::string SnoopLogger::kSoCManufacturerProperty = "ro.soc.manufacturer";
453
454 // persist.bluetooth.btsnooplogmode
455 const std::string SnoopLogger::kBtSnoopLogModeKernel = "kernel";
456 const std::string SnoopLogger::kBtSnoopLogModeDisabled = "disabled";
457 const std::string SnoopLogger::kBtSnoopLogModeFiltered = "filtered";
458 const std::string SnoopLogger::kBtSnoopLogModeFull = "full";
459 // ro.soc.manufacturer
460 const std::string SnoopLogger::kSoCManufacturerQualcomm = "Qualcomm";
461
462 // PBAP, MAP and HFP packets filter mode - discard whole packet
463 const std::string SnoopLogger::kBtSnoopLogFilterProfileModeFullfillter = "fullfilter";
464 // PBAP, MAP and HFP packets filter mode - truncate to fixed length
465 const std::string SnoopLogger::kBtSnoopLogFilterProfileModeHeader = "header";
466 // PBAP, MAP and HFP packets filter mode - fill with a magic string, such as: "PROHIBITED"
467 const std::string SnoopLogger::kBtSnoopLogFilterProfileModeMagic = "magic";
468 // PBAP, MAP and HFP packets filter mode - disabled
469 const std::string SnoopLogger::kBtSnoopLogFilterProfileModeDisabled = "disabled";
470
471 // Consts accessible in unit tests
472 const size_t SnoopLogger::PACKET_TYPE_LENGTH = 1;
473 const size_t SnoopLogger::MAX_HCI_ACL_LEN = 14;
474 const uint32_t SnoopLogger::L2CAP_HEADER_SIZE = 8;
475
SnoopLogger(std::string snoop_log_path,std::string snooz_log_path,size_t max_packets_per_file,size_t max_packets_per_buffer,const std::string & btsnoop_mode,bool qualcomm_debug_log_enabled,const std::chrono::milliseconds snooz_log_life_time,const std::chrono::milliseconds snooz_log_delete_alarm_interval,bool snoop_log_persists)476 SnoopLogger::SnoopLogger(std::string snoop_log_path, std::string snooz_log_path,
477 size_t max_packets_per_file, size_t max_packets_per_buffer,
478 const std::string& btsnoop_mode, bool qualcomm_debug_log_enabled,
479 const std::chrono::milliseconds snooz_log_life_time,
480 const std::chrono::milliseconds snooz_log_delete_alarm_interval,
481 bool snoop_log_persists)
482 : btsnoop_mode_(btsnoop_mode),
483 snoop_log_path_(std::move(snoop_log_path)),
484 snooz_log_path_(std::move(snooz_log_path)),
485 max_packets_per_file_(max_packets_per_file),
486 btsnooz_buffer_(max_packets_per_buffer),
487 qualcomm_debug_log_enabled_(qualcomm_debug_log_enabled),
488 snooz_log_life_time_(snooz_log_life_time),
489 snooz_log_delete_alarm_interval_(snooz_log_delete_alarm_interval),
490 snoop_log_persists(snoop_log_persists) {
491 if (btsnoop_mode_ == kBtSnoopLogModeFiltered) {
492 log::info("Snoop Logs filtered mode enabled");
493 EnableFilters();
494 // delete unfiltered logs
495 delete_btsnoop_files(get_btsnoop_log_path(snoop_log_path_, false));
496 // delete snooz logs
497 delete_btsnoop_files(snooz_log_path_);
498 } else if (btsnoop_mode_ == kBtSnoopLogModeFull) {
499 log::info("Snoop Logs full mode enabled");
500 if (!snoop_log_persists) {
501 // delete filtered logs
502 delete_btsnoop_files(get_btsnoop_log_path(snoop_log_path_, true));
503 // delete snooz logs
504 delete_btsnoop_files(snooz_log_path_);
505 }
506 } else {
507 log::info("Snoop Logs disabled");
508 // delete both filtered and unfiltered logs
509 delete_btsnoop_files(get_btsnoop_log_path(snoop_log_path_, true));
510 delete_btsnoop_files(get_btsnoop_log_path(snoop_log_path_, false));
511 }
512
513 snoop_logger_socket_thread_ = nullptr;
514 socket_ = nullptr;
515 // Add ".filtered" extension if necessary
516 snoop_log_path_ = get_btsnoop_log_path(snoop_log_path_, btsnoop_mode_ == kBtSnoopLogModeFiltered);
517 }
518
CloseCurrentSnoopLogFile()519 void SnoopLogger::CloseCurrentSnoopLogFile() {
520 std::lock_guard<std::recursive_mutex> lock(file_mutex_);
521 if (btsnoop_ostream_.is_open()) {
522 btsnoop_ostream_.flush();
523 btsnoop_ostream_.close();
524 }
525 packet_counter_ = 0;
526 }
527
OpenNextSnoopLogFile()528 void SnoopLogger::OpenNextSnoopLogFile() {
529 std::lock_guard<std::recursive_mutex> lock(file_mutex_);
530 CloseCurrentSnoopLogFile();
531
532 auto last_file_path = get_last_log_path(snoop_log_path_);
533
534 if (os::FileExists(snoop_log_path_)) {
535 if (!os::RenameFile(snoop_log_path_, last_file_path)) {
536 log::error("Unabled to rename existing snoop log from \"{}\" to \"{}\"", snoop_log_path_,
537 last_file_path);
538 }
539 } else {
540 log::info("Previous log file \"{}\" does not exist, skip renaming", snoop_log_path_);
541 }
542
543 mode_t prevmask = umask(0);
544 // do not use std::ios::app as we want override the existing file
545 btsnoop_ostream_.open(snoop_log_path_, std::ios::binary | std::ios::out);
546 #ifdef USE_FAKE_TIMERS
547 file_creation_time = fake_timerfd_get_clock();
548 #endif
549 if (!btsnoop_ostream_.good()) {
550 log::error("Unable to open snoop log at \"{}\", error: \"{}\"", snoop_log_path_,
551 strerror(errno));
552 return;
553 }
554 umask(prevmask);
555 if (!btsnoop_ostream_.write(reinterpret_cast<const char*>(&SnoopLoggerCommon::kBtSnoopFileHeader),
556 sizeof(SnoopLoggerCommon::FileHeaderType))) {
557 log::error("Unable to write file header to \"{}\", error: \"{}\"", snoop_log_path_,
558 strerror(errno));
559 btsnoop_ostream_.close();
560 return;
561 }
562 if (!btsnoop_ostream_.flush()) {
563 log::error("Failed to flush, error: \"{}\"", strerror(errno));
564 return;
565 }
566 }
567
EnableFilters()568 void SnoopLogger::EnableFilters() {
569 std::lock_guard<std::mutex> lock(snoop_log_filters_mutex);
570 for (auto itr = kBtSnoopLogFilterState.begin(); itr != kBtSnoopLogFilterState.end(); itr++) {
571 auto filter_enabled_property = os::GetSystemProperty(itr->first);
572 if (filter_enabled_property) {
573 itr->second = filter_enabled_property.value() == "true";
574 }
575 log::info("{}: {}", itr->first, itr->second);
576 }
577 for (auto itr = kBtSnoopLogFilterMode.begin(); itr != kBtSnoopLogFilterMode.end(); itr++) {
578 auto filter_mode_property = os::GetSystemProperty(itr->first);
579 if (filter_mode_property) {
580 itr->second = filter_mode_property.value();
581 } else {
582 itr->second = SnoopLogger::kBtSnoopLogFilterProfileModeDisabled;
583 }
584 log::info("{}: {}", itr->first, itr->second);
585 }
586 }
587
DisableFilters()588 void SnoopLogger::DisableFilters() {
589 std::lock_guard<std::mutex> lock(snoop_log_filters_mutex);
590 for (auto itr = kBtSnoopLogFilterState.begin(); itr != kBtSnoopLogFilterState.end(); itr++) {
591 itr->second = false;
592 log::info("{}, {}", itr->first, itr->second);
593 }
594 for (auto itr = kBtSnoopLogFilterMode.begin(); itr != kBtSnoopLogFilterMode.end(); itr++) {
595 itr->second = SnoopLogger::kBtSnoopLogFilterProfileModeDisabled;
596 log::info("{}, {}", itr->first, itr->second);
597 }
598 }
599
IsFilterEnabled(std::string filter_name)600 bool SnoopLogger::IsFilterEnabled(std::string filter_name) {
601 std::lock_guard<std::mutex> lock(snoop_log_filters_mutex);
602 for (auto itr = kBtSnoopLogFilterState.begin(); itr != kBtSnoopLogFilterState.end(); itr++) {
603 if (filter_name == itr->first) {
604 return itr->second == true;
605 }
606 }
607 for (auto itr = kBtSnoopLogFilterMode.begin(); itr != kBtSnoopLogFilterMode.end(); itr++) {
608 if (filter_name == itr->first) {
609 return itr->second != SnoopLogger::kBtSnoopLogFilterProfileModeDisabled;
610 }
611 }
612 return false;
613 }
614
ShouldFilterLog(bool is_received,uint8_t * packet)615 bool SnoopLogger::ShouldFilterLog(bool is_received, uint8_t* packet) {
616 uint16_t conn_handle =
617 ((((uint16_t)packet[ACL_CHANNEL_OFFSET + 1]) << 8) + packet[ACL_CHANNEL_OFFSET]) & 0x0fff;
618 std::lock_guard<std::mutex> lock(filter_tracker_list_mutex);
619 auto& filters = filter_tracker_list[conn_handle];
620 uint16_t cid = (packet[L2CAP_CHANNEL_OFFSET + 1] << 8) + packet[L2CAP_CHANNEL_OFFSET];
621 if (filters.IsRfcommChannel(is_received, cid)) {
622 uint8_t rfcomm_event = packet[RFCOMM_EVENT_OFFSET] & 0b11101111;
623 if (rfcomm_event == RFCOMM_SABME || rfcomm_event == RFCOMM_UA) {
624 return false;
625 }
626
627 uint8_t rfcomm_dlci = packet[RFCOMM_CHANNEL_OFFSET] >> 2;
628 if (!filters.IsAcceptlistedDlci(rfcomm_dlci)) {
629 return true;
630 }
631 } else if (!filters.IsAcceptlistedL2cap(is_received, cid)) {
632 return true;
633 }
634
635 return false;
636 }
637
CalculateAclPacketLength(uint32_t & length,uint8_t * packet,bool)638 void SnoopLogger::CalculateAclPacketLength(uint32_t& length, uint8_t* packet,
639 bool /* is_received */) {
640 uint32_t def_len =
641 ((((uint16_t)packet[ACL_LENGTH_OFFSET + 1]) << 8) + packet[ACL_LENGTH_OFFSET]) +
642 ACL_HEADER_LENGTH + PACKET_TYPE_LENGTH;
643 constexpr uint16_t L2CAP_SIGNALING_CID = 0x0001;
644
645 if (length == 0) {
646 return;
647 }
648
649 uint16_t handle =
650 ((((uint16_t)packet[ACL_CHANNEL_OFFSET + 1]) << 8) + packet[ACL_CHANNEL_OFFSET]);
651 uint8_t boundary_flag = GetBoundaryFlag(handle);
652 handle = handle & HANDLE_MASK;
653
654 if (boundary_flag == START_PACKET_BOUNDARY) {
655 uint16_t l2cap_cid = packet[L2CAP_CHANNEL_OFFSET] | (packet[L2CAP_CHANNEL_OFFSET + 1] << 8);
656 if (l2cap_cid == L2CAP_SIGNALING_CID || handle == kQualcommDebugLogHandle) {
657 length = def_len;
658 } else {
659 if (def_len < MAX_HCI_ACL_LEN) {
660 length = def_len;
661 } else {
662 // Otherwise, return as much as we reasonably can
663 length = MAX_HCI_ACL_LEN;
664 }
665 }
666 }
667 }
668
PayloadStrip(profile_type_t current_profile,uint8_t * packet,uint32_t hdr_len,uint32_t pl_len)669 uint32_t SnoopLogger::PayloadStrip(profile_type_t current_profile, uint8_t* packet,
670 uint32_t hdr_len, uint32_t pl_len) {
671 uint32_t len = 0;
672 std::string profile_filter_mode = "";
673 log::debug("current_profile={}, hdr len={}, total len={}",
674 ProfilesFilter::ProfileToString(current_profile), hdr_len, pl_len);
675 std::lock_guard<std::mutex> lock(snoop_log_filters_mutex);
676 switch (current_profile) {
677 case FILTER_PROFILE_PBAP:
678 case FILTER_PROFILE_HFP_HF:
679 case FILTER_PROFILE_HFP_HS:
680 profile_filter_mode =
681 kBtSnoopLogFilterMode[SnoopLogger::kBtSnoopLogFilterProfilePbapModeProperty];
682 break;
683 case FILTER_PROFILE_MAP:
684 profile_filter_mode =
685 kBtSnoopLogFilterMode[SnoopLogger::kBtSnoopLogFilterProfileMapModeProperty];
686 break;
687 default:
688 profile_filter_mode = kBtSnoopLogFilterProfileModeDisabled;
689 }
690
691 if (profile_filter_mode == SnoopLogger::kBtSnoopLogFilterProfileModeFullfillter) {
692 return 0;
693 } else if (profile_filter_mode == SnoopLogger::kBtSnoopLogFilterProfileModeHeader) {
694 len = hdr_len;
695
696 packet[ACL_LENGTH_OFFSET] = static_cast<uint8_t>(hdr_len - BASIC_L2CAP_HEADER_LENGTH);
697 packet[ACL_LENGTH_OFFSET + 1] =
698 static_cast<uint8_t>((hdr_len - BASIC_L2CAP_HEADER_LENGTH) >> 8);
699
700 packet[L2CAP_PDU_LENGTH_OFFSET] =
701 static_cast<uint8_t>(hdr_len - (ACL_HEADER_LENGTH + BASIC_L2CAP_HEADER_LENGTH));
702 packet[L2CAP_PDU_LENGTH_OFFSET + 1] =
703 static_cast<uint8_t>((hdr_len - (ACL_HEADER_LENGTH + BASIC_L2CAP_HEADER_LENGTH)) >> 8);
704
705 } else if (profile_filter_mode == SnoopLogger::kBtSnoopLogFilterProfileModeMagic) {
706 strcpy(reinterpret_cast<char*>(&packet[hdr_len]), payload_fill_magic);
707
708 packet[ACL_LENGTH_OFFSET] =
709 static_cast<uint8_t>(hdr_len + magic_pat_len - BASIC_L2CAP_HEADER_LENGTH);
710 packet[ACL_LENGTH_OFFSET + 1] =
711 static_cast<uint8_t>((hdr_len + magic_pat_len - BASIC_L2CAP_HEADER_LENGTH) >> 8);
712
713 packet[L2CAP_PDU_LENGTH_OFFSET] = static_cast<uint8_t>(
714 hdr_len + magic_pat_len - (ACL_HEADER_LENGTH + BASIC_L2CAP_HEADER_LENGTH));
715 packet[L2CAP_PDU_LENGTH_OFFSET + 1] = static_cast<uint8_t>(
716 (hdr_len + magic_pat_len - (ACL_HEADER_LENGTH + BASIC_L2CAP_HEADER_LENGTH)) >> 8);
717
718 len = hdr_len + magic_pat_len;
719 } else {
720 // Return unchanged
721 len = hdr_len + pl_len;
722 }
723 return len + PACKET_TYPE_LENGTH; // including packet type byte
724 }
725
FilterProfilesHandleHfp(uint8_t * packet,uint32_t length,uint32_t totlen,uint32_t offset)726 uint32_t SnoopLogger::FilterProfilesHandleHfp(uint8_t* packet, uint32_t length, uint32_t totlen,
727 uint32_t offset) {
728 if ((totlen - offset) > cpbr_pat_len) {
729 if (memcmp(&packet[offset], cpbr_pattern, cpbr_pat_len) == 0) {
730 length = offset + cpbr_pat_len + 1;
731 packet[L2CAP_PDU_LENGTH_OFFSET] = offset + cpbr_pat_len - BASIC_L2CAP_HEADER_LENGTH;
732 packet[L2CAP_PDU_LENGTH_OFFSET] =
733 offset + cpbr_pat_len - (ACL_HEADER_LENGTH + BASIC_L2CAP_HEADER_LENGTH);
734 return length;
735 }
736
737 if (memcmp(&packet[offset], clcc_pattern, clcc_pat_len) == 0) {
738 length = offset + cpbr_pat_len + 1;
739 packet[L2CAP_PDU_LENGTH_OFFSET] = offset + clcc_pat_len - BASIC_L2CAP_HEADER_LENGTH;
740 packet[L2CAP_PDU_LENGTH_OFFSET] =
741 offset + clcc_pat_len - (ACL_HEADER_LENGTH + BASIC_L2CAP_HEADER_LENGTH);
742 }
743 }
744
745 return length;
746 }
747
FilterProfilesRfcommChannel(uint8_t * packet,uint8_t & current_offset,uint32_t & length,profile_type_t & current_profile,bluetooth::hal::ProfilesFilter & filters,bool is_received,uint16_t l2cap_channel,uint32_t & offset,uint32_t total_length)748 void SnoopLogger::FilterProfilesRfcommChannel(uint8_t* packet, uint8_t& current_offset,
749 uint32_t& length, profile_type_t& current_profile,
750 bluetooth::hal::ProfilesFilter& filters,
751 bool is_received, uint16_t l2cap_channel,
752 uint32_t& offset, uint32_t total_length) {
753 uint8_t addr, ctrl, pf;
754
755 addr = packet[current_offset];
756 current_offset += 1;
757 ctrl = packet[RFCOMM_EVENT_OFFSET];
758 current_offset += 1;
759
760 pf = ctrl & 0x10;
761 ctrl = ctrl & 0xef;
762 addr >>= 2;
763 if (ctrl != RFCOMM_UIH) {
764 return;
765 }
766 current_profile = filters.DlciToProfile(is_received, l2cap_channel, addr);
767 if (current_profile != FILTER_PROFILE_NONE) {
768 uint16_t len;
769 uint8_t ea;
770
771 len = packet[current_offset];
772 current_offset += 1;
773 ea = len & 1;
774
775 if (!ea) {
776 current_offset += 1;
777 }
778
779 if (filters.IsRfcommFlowExt(is_received, l2cap_channel, addr) && pf) {
780 current_offset += 1; // credit byte
781 }
782 offset = current_offset;
783
784 if ((filters).IsHfpProfile(is_received, l2cap_channel, addr)) {
785 length = FilterProfilesHandleHfp(packet, length, total_length, offset);
786 } else {
787 length = PayloadStrip(current_profile, packet, offset, total_length - offset);
788 }
789 }
790 }
791
FilterProfiles(bool is_received,uint8_t * packet)792 uint32_t SnoopLogger::FilterProfiles(bool is_received, uint8_t* packet) {
793 bool frag;
794 uint16_t handle, l2c_chan, l2c_ctl;
795 uint32_t length, totlen, offset;
796 uint8_t current_offset = 0;
797 profile_type_t current_profile = FILTER_PROFILE_NONE;
798 constexpr uint16_t L2CAP_SIGNALING_CID = 0x0001;
799
800 std::lock_guard<std::mutex> lock(profiles_filter_mutex);
801
802 handle = ((((uint16_t)packet[ACL_CHANNEL_OFFSET + 1]) << 8) + packet[ACL_CHANNEL_OFFSET]);
803 frag = (GetBoundaryFlag(handle) == CONTINUATION_PACKET_BOUNDARY);
804
805 handle = handle & HANDLE_MASK;
806 current_offset += 2;
807
808 length = (((uint16_t)packet[ACL_LENGTH_OFFSET + 1]) << 8) + packet[ACL_LENGTH_OFFSET];
809 current_offset += 2;
810 totlen = length + ACL_HEADER_LENGTH;
811 length += PACKET_TYPE_LENGTH + ACL_HEADER_LENGTH; // Additional byte is added for packet type
812
813 l2c_chan = ((uint16_t)packet[L2CAP_CHANNEL_OFFSET + 1] << 8) + packet[L2CAP_CHANNEL_OFFSET];
814 current_offset += 4;
815
816 auto& filters = profiles_filter_table[handle];
817 if (frag) {
818 l2c_chan = filters.ch_last;
819 } else {
820 filters.ch_last = l2c_chan;
821 }
822
823 if (l2c_chan != L2CAP_SIGNALING_CID && handle != kQualcommDebugLogHandle) {
824 if (filters.IsL2capFlowExt(is_received, l2c_chan)) {
825 l2c_ctl = ((uint16_t)packet[L2CAP_CONTROL_OFFSET + 1] << 8) + packet[L2CAP_CONTROL_OFFSET];
826 if (!(l2c_ctl & 1)) { // I-Frame
827 if (((l2c_ctl >> 14) & 0x3) == 0x01) { // Start of L2CAP SDU
828 current_offset += 2;
829 }
830 }
831 }
832 offset = current_offset;
833 current_profile = filters.CidToProfile(is_received, l2c_chan);
834 if (current_profile != FILTER_PROFILE_NONE) {
835 if (frag) {
836 return PACKET_TYPE_LENGTH + ACL_HEADER_LENGTH;
837 }
838 return PayloadStrip(current_profile, packet, offset, totlen - offset);
839 }
840
841 if (filters.IsRfcommChannel(is_received, l2c_chan)) {
842 FilterProfilesRfcommChannel(packet, current_offset, length, current_profile, filters,
843 is_received, l2c_chan, offset, totlen);
844 }
845 }
846
847 return length;
848 }
849
AcceptlistL2capChannel(uint16_t conn_handle,uint16_t local_cid,uint16_t remote_cid)850 void SnoopLogger::AcceptlistL2capChannel(uint16_t conn_handle, uint16_t local_cid,
851 uint16_t remote_cid) {
852 if (btsnoop_mode_ != kBtSnoopLogModeFiltered ||
853 !IsFilterEnabled(kBtSnoopLogFilterProfileRfcommProperty)) {
854 return;
855 }
856
857 log::debug("Acceptlisting l2cap channel: conn_handle={}, local cid={}, remote cid={}",
858 conn_handle, local_cid, remote_cid);
859 std::lock_guard<std::mutex> lock(filter_tracker_list_mutex);
860
861 // This will create the entry if there is no associated filter with the
862 // connection.
863 filter_tracker_list[conn_handle].AddL2capCid(local_cid, remote_cid);
864 }
865
AcceptlistRfcommDlci(uint16_t conn_handle,uint16_t local_cid,uint8_t dlci)866 void SnoopLogger::AcceptlistRfcommDlci(uint16_t conn_handle, uint16_t local_cid, uint8_t dlci) {
867 if (btsnoop_mode_ != kBtSnoopLogModeFiltered ||
868 !IsFilterEnabled(kBtSnoopLogFilterProfileRfcommProperty)) {
869 return;
870 }
871
872 log::debug("Acceptlisting rfcomm channel: local cid={}, dlci={}", local_cid, dlci);
873 std::lock_guard<std::mutex> lock(filter_tracker_list_mutex);
874
875 filter_tracker_list[conn_handle].AddRfcommDlci(dlci);
876 }
877
AddRfcommL2capChannel(uint16_t conn_handle,uint16_t local_cid,uint16_t remote_cid)878 void SnoopLogger::AddRfcommL2capChannel(uint16_t conn_handle, uint16_t local_cid,
879 uint16_t remote_cid) {
880 if (btsnoop_mode_ != kBtSnoopLogModeFiltered ||
881 !IsFilterEnabled(kBtSnoopLogFilterProfileRfcommProperty)) {
882 return;
883 }
884
885 log::debug("Rfcomm data going over l2cap channel: conn_handle={} local cid={} remote cid={}",
886 conn_handle, local_cid, remote_cid);
887 std::lock_guard<std::mutex> lock(filter_tracker_list_mutex);
888
889 filter_tracker_list[conn_handle].SetRfcommCid(local_cid, remote_cid);
890 local_cid_to_acl.insert({local_cid, conn_handle});
891 }
892
ClearL2capAcceptlist(uint16_t conn_handle,uint16_t local_cid,uint16_t remote_cid)893 void SnoopLogger::ClearL2capAcceptlist(uint16_t conn_handle, uint16_t local_cid,
894 uint16_t remote_cid) {
895 if (btsnoop_mode_ != kBtSnoopLogModeFiltered ||
896 !IsFilterEnabled(kBtSnoopLogFilterProfileRfcommProperty)) {
897 return;
898 }
899
900 log::debug("Clearing acceptlist from l2cap channel. conn_handle={} local cid={} remote cid={}",
901 conn_handle, local_cid, remote_cid);
902 std::lock_guard<std::mutex> lock(filter_tracker_list_mutex);
903
904 filter_tracker_list[conn_handle].RemoveL2capCid(local_cid, remote_cid);
905 }
906
IsA2dpMediaChannel(uint16_t conn_handle,uint16_t cid,bool is_local_cid)907 bool SnoopLogger::IsA2dpMediaChannel(uint16_t conn_handle, uint16_t cid, bool is_local_cid) {
908 if (btsnoop_mode_ != kBtSnoopLogModeFiltered ||
909 !IsFilterEnabled(kBtSnoopLogFilterProfileA2dpProperty)) {
910 return false;
911 }
912
913 std::lock_guard<std::mutex> lock(a2dpMediaChannels_mutex);
914 auto iter = std::find_if(a2dpMediaChannels.begin(), a2dpMediaChannels.end(),
915 [conn_handle, cid, is_local_cid](auto& el) {
916 if (el.conn_handle != conn_handle) {
917 return false;
918 }
919
920 if (is_local_cid) {
921 return el.local_cid == cid;
922 }
923
924 return el.remote_cid == cid;
925 });
926
927 return iter != a2dpMediaChannels.end();
928 }
929
IsA2dpMediaPacket(bool is_received,uint8_t * packet)930 bool SnoopLogger::IsA2dpMediaPacket(bool is_received, uint8_t* packet) {
931 uint16_t cid, conn_handle;
932 bool is_local_cid = is_received;
933 /*is_received signifies Rx packet so packet will have local_cid at offset 6
934 * Tx packet with is_received as false and have remote_cid at the offset*/
935
936 conn_handle = (uint16_t)((packet[0] + (packet[1] << 8)) & 0x0FFF);
937 cid = (uint16_t)(packet[6] + (packet[7] << 8));
938
939 return IsA2dpMediaChannel(conn_handle, cid, is_local_cid);
940 }
941
AddA2dpMediaChannel(uint16_t conn_handle,uint16_t local_cid,uint16_t remote_cid)942 void SnoopLogger::AddA2dpMediaChannel(uint16_t conn_handle, uint16_t local_cid,
943 uint16_t remote_cid) {
944 if (btsnoop_mode_ != kBtSnoopLogModeFiltered ||
945 !IsFilterEnabled(kBtSnoopLogFilterProfileA2dpProperty)) {
946 return;
947 }
948
949 if (!SnoopLogger::IsA2dpMediaChannel(conn_handle, local_cid, true)) {
950 log::info("Add A2DP media channel filtering. conn_handle={} local cid={} remote cid={}",
951 conn_handle, local_cid, remote_cid);
952 std::lock_guard<std::mutex> lock(a2dpMediaChannels_mutex);
953 a2dpMediaChannels.push_back({conn_handle, local_cid, remote_cid});
954 }
955 }
956
RemoveA2dpMediaChannel(uint16_t conn_handle,uint16_t local_cid)957 void SnoopLogger::RemoveA2dpMediaChannel(uint16_t conn_handle, uint16_t local_cid) {
958 if (btsnoop_mode_ != kBtSnoopLogModeFiltered ||
959 !IsFilterEnabled(kBtSnoopLogFilterProfileA2dpProperty)) {
960 return;
961 }
962
963 std::lock_guard<std::mutex> lock(a2dpMediaChannels_mutex);
964 a2dpMediaChannels.erase(std::remove_if(a2dpMediaChannels.begin(), a2dpMediaChannels.end(),
965 [conn_handle, local_cid](auto& el) {
966 return el.conn_handle == conn_handle &&
967 el.local_cid == local_cid;
968 }),
969 a2dpMediaChannels.end());
970 }
971
SetRfcommPortOpen(uint16_t conn_handle,uint16_t local_cid,uint8_t dlci,uint16_t uuid,bool flow)972 void SnoopLogger::SetRfcommPortOpen(uint16_t conn_handle, uint16_t local_cid, uint8_t dlci,
973 uint16_t uuid, bool flow) {
974 if (btsnoop_mode_ != kBtSnoopLogModeFiltered ||
975 (!IsFilterEnabled(kBtSnoopLogFilterProfilePbapModeProperty) &&
976 !IsFilterEnabled(kBtSnoopLogFilterProfileMapModeProperty))) {
977 return;
978 }
979
980 std::lock_guard<std::mutex> lock(profiles_filter_mutex);
981
982 profile_type_t profile = FILTER_PROFILE_NONE;
983 auto& filters = profiles_filter_table[conn_handle];
984 {
985 filters.SetupProfilesFilter(IsFilterEnabled(kBtSnoopLogFilterProfilePbapModeProperty),
986 IsFilterEnabled(kBtSnoopLogFilterProfileMapModeProperty));
987 }
988
989 log::info(
990 "RFCOMM port is opened: handle={}(0x{:x}), lcid={}(0x{:x}), dlci={}(0x{:x}), "
991 "uuid={}(0x{:x}){}",
992 conn_handle, conn_handle, local_cid, local_cid, dlci, dlci, uuid, uuid,
993 flow ? " Credit Based Flow Control enabled" : "");
994
995 if (uuid == PROFILE_UUID_PBAP || (dlci >> 1) == PROFILE_SCN_PBAP) {
996 profile = FILTER_PROFILE_PBAP;
997 } else if (uuid == PROFILE_UUID_MAP || (dlci >> 1) == PROFILE_SCN_MAP) {
998 profile = FILTER_PROFILE_MAP;
999 } else if (uuid == PROFILE_UUID_HFP_HS) {
1000 profile = FILTER_PROFILE_HFP_HS;
1001 } else if (uuid == PROFILE_UUID_HFP_HF) {
1002 profile = FILTER_PROFILE_HFP_HF;
1003 }
1004
1005 if (profile >= 0) {
1006 filters.ProfileRfcommOpen(profile, local_cid, dlci, uuid, flow);
1007 }
1008 }
1009
SetRfcommPortClose(uint16_t handle,uint16_t local_cid,uint8_t dlci,uint16_t uuid)1010 void SnoopLogger::SetRfcommPortClose(uint16_t handle, uint16_t local_cid, uint8_t dlci,
1011 uint16_t uuid) {
1012 if (btsnoop_mode_ != kBtSnoopLogModeFiltered ||
1013 (!IsFilterEnabled(kBtSnoopLogFilterProfilePbapModeProperty) &&
1014 !IsFilterEnabled(kBtSnoopLogFilterProfileMapModeProperty))) {
1015 return;
1016 }
1017
1018 std::lock_guard<std::mutex> lock(profiles_filter_mutex);
1019
1020 auto& filters = profiles_filter_table[handle];
1021 log::info(
1022 "RFCOMM port is closed: handle={}(0x{:x}), lcid={}(0x{:x}), dlci={}(0x{:x}), "
1023 "uuid={}(0x{:x})",
1024 handle, handle, local_cid, local_cid, dlci, dlci, uuid, uuid);
1025
1026 filters.ProfileRfcommClose(filters.DlciToProfile(true, local_cid, dlci));
1027 }
1028
SetL2capChannelOpen(uint16_t handle,uint16_t local_cid,uint16_t remote_cid,uint16_t psm,bool flow)1029 void SnoopLogger::SetL2capChannelOpen(uint16_t handle, uint16_t local_cid, uint16_t remote_cid,
1030 uint16_t psm, bool flow) {
1031 if (btsnoop_mode_ != kBtSnoopLogModeFiltered ||
1032 (!IsFilterEnabled(kBtSnoopLogFilterProfilePbapModeProperty) &&
1033 !IsFilterEnabled(kBtSnoopLogFilterProfileMapModeProperty))) {
1034 return;
1035 }
1036
1037 std::lock_guard<std::mutex> lock(profiles_filter_mutex);
1038 profile_type_t profile = FILTER_PROFILE_NONE;
1039 auto& filters = profiles_filter_table[handle];
1040 {
1041 filters.SetupProfilesFilter(IsFilterEnabled(kBtSnoopLogFilterProfilePbapModeProperty),
1042 IsFilterEnabled(kBtSnoopLogFilterProfileMapModeProperty));
1043 }
1044
1045 log::info(
1046 "L2CAP channel is opened: handle={}(0x{:x}), lcid={}(0x{:x}), rcid={}(0x{:x}), "
1047 "psm=0x{:x}{}",
1048 handle, handle, local_cid, local_cid, remote_cid, remote_cid, psm,
1049 flow ? " Standard or Enhanced Control enabled" : "");
1050
1051 if (psm == PROFILE_PSM_RFCOMM) {
1052 filters.ch_rfc_l = local_cid;
1053 filters.ch_rfc_r = remote_cid;
1054 } else if (psm == PROFILE_PSM_PBAP) {
1055 profile = FILTER_PROFILE_PBAP;
1056 } else if (psm == PROFILE_PSM_MAP) {
1057 profile = FILTER_PROFILE_MAP;
1058 }
1059
1060 if (profile >= 0) {
1061 filters.ProfileL2capOpen(profile, local_cid, remote_cid, psm, flow);
1062 }
1063 }
1064
SetL2capChannelClose(uint16_t handle,uint16_t local_cid,uint16_t remote_cid)1065 void SnoopLogger::SetL2capChannelClose(uint16_t handle, uint16_t local_cid, uint16_t remote_cid) {
1066 if (btsnoop_mode_ != kBtSnoopLogModeFiltered ||
1067 (!IsFilterEnabled(kBtSnoopLogFilterProfilePbapModeProperty) &&
1068 !IsFilterEnabled(kBtSnoopLogFilterProfileMapModeProperty))) {
1069 return;
1070 }
1071
1072 std::lock_guard<std::mutex> lock(profiles_filter_mutex);
1073
1074 auto& filters = profiles_filter_table[handle];
1075
1076 log::info("L2CAP channel is closed: handle={}(0x{:x}), lcid={}(0x{:x}), rcid={}(0x{:x})", handle,
1077 handle, local_cid, local_cid, remote_cid, remote_cid);
1078
1079 filters.ProfileL2capClose(filters.CidToProfile(true, local_cid));
1080 }
1081
FilterCapturedPacket(HciPacket & packet,Direction direction,PacketType type,uint32_t & length,PacketHeaderType header)1082 void SnoopLogger::FilterCapturedPacket(HciPacket& packet, Direction direction, PacketType type,
1083 uint32_t& length, PacketHeaderType header) {
1084 if (btsnoop_mode_ != kBtSnoopLogModeFiltered || type != PacketType::ACL) {
1085 return;
1086 }
1087
1088 if (IsFilterEnabled(kBtSnoopLogFilterProfileA2dpProperty)) {
1089 if (IsA2dpMediaPacket(direction == Direction::INCOMING, (uint8_t*)packet.data())) {
1090 length = 0;
1091 return;
1092 }
1093 }
1094
1095 if (IsFilterEnabled(kBtSnoopLogFilterHeadersProperty)) {
1096 CalculateAclPacketLength(length, (uint8_t*)packet.data(), direction == Direction::INCOMING);
1097 }
1098
1099 if (IsFilterEnabled(kBtSnoopLogFilterProfilePbapModeProperty) ||
1100 IsFilterEnabled(kBtSnoopLogFilterProfileMapModeProperty)) {
1101 // If HeadersFiltered applied, do not use ProfilesFiltered
1102 if (length == ntohl(header.length_original)) {
1103 if (packet.size() + EXTRA_BUF_SIZE > DEFAULT_PACKET_SIZE) {
1104 // Add additional bytes for magic string in case
1105 // payload length is less than the length of magic string.
1106 packet.resize((size_t)(packet.size() + EXTRA_BUF_SIZE));
1107 }
1108
1109 length = FilterProfiles(direction == Direction::INCOMING, (uint8_t*)packet.data());
1110 if (length == 0) {
1111 return;
1112 }
1113 }
1114 }
1115
1116 if (IsFilterEnabled(kBtSnoopLogFilterProfileRfcommProperty)) {
1117 bool shouldFilter =
1118 SnoopLogger::ShouldFilterLog(direction == Direction::INCOMING, (uint8_t*)packet.data());
1119 if (shouldFilter) {
1120 length = L2CAP_HEADER_SIZE + PACKET_TYPE_LENGTH;
1121 }
1122 }
1123 }
1124
Capture(const HciPacket & immutable_packet,Direction direction,PacketType type)1125 void SnoopLogger::Capture(const HciPacket& immutable_packet, Direction direction, PacketType type) {
1126 //// TODO(b/335520123) update FilterCapture to stop modifying packets ////
1127 HciPacket mutable_packet(immutable_packet);
1128 HciPacket& packet = mutable_packet;
1129 //////////////////////////////////////////////////////////////////////////
1130
1131 #ifdef __ANDROID__
1132 if (com::android::bluetooth::flags::snoop_logger_tracing()) {
1133 LogTracePoint(packet, direction, type);
1134 }
1135 #endif // __ANDROID__
1136
1137 uint64_t timestamp_us = std::chrono::duration_cast<std::chrono::microseconds>(
1138 std::chrono::system_clock::now().time_since_epoch())
1139 .count();
1140 std::bitset<32> flags = 0;
1141 switch (type) {
1142 case PacketType::CMD:
1143 flags.set(0, false);
1144 flags.set(1, true);
1145 break;
1146 case PacketType::ACL:
1147 case PacketType::ISO:
1148 case PacketType::SCO:
1149 flags.set(0, direction == Direction::INCOMING);
1150 flags.set(1, false);
1151 break;
1152 case PacketType::EVT:
1153 flags.set(0, true);
1154 flags.set(1, true);
1155 break;
1156 }
1157 uint32_t length = packet.size() + /* type byte */ PACKET_TYPE_LENGTH;
1158 PacketHeaderType header = {.length_original = htonl(length),
1159 .length_captured = htonl(length),
1160 .flags = htonl(static_cast<uint32_t>(flags.to_ulong())),
1161 .dropped_packets = 0,
1162 .timestamp = htonll(timestamp_us + kBtSnoopEpochDelta),
1163 .type = static_cast<uint8_t>(type)};
1164 {
1165 std::lock_guard<std::recursive_mutex> lock(file_mutex_);
1166 if (btsnoop_mode_ == kBtSnoopLogModeDisabled) {
1167 // btsnoop disabled, log in-memory btsnooz log only
1168 std::stringstream ss;
1169 size_t included_length =
1170 get_btsnooz_packet_length_to_write(packet, type, qualcomm_debug_log_enabled_);
1171 header.length_captured = htonl(included_length + /* type byte */ PACKET_TYPE_LENGTH);
1172 if (!ss.write(reinterpret_cast<const char*>(&header), sizeof(PacketHeaderType))) {
1173 log::error("Failed to write packet header for btsnooz, error: \"{}\"", strerror(errno));
1174 }
1175 if (!ss.write(reinterpret_cast<const char*>(packet.data()), included_length)) {
1176 log::error("Failed to write packet payload for btsnooz, error: \"{}\"", strerror(errno));
1177 }
1178 btsnooz_buffer_.Push(ss.str());
1179 return;
1180 } else if (btsnoop_mode_ == kBtSnoopLogModeKernel) {
1181 // Skip logging as btsnoop is done in kernel space
1182 return;
1183 }
1184
1185 FilterCapturedPacket(packet, direction, type, length, header);
1186
1187 if (length == 0) {
1188 return;
1189 } else if (length != ntohl(header.length_original)) {
1190 header.length_captured = htonl(length);
1191 }
1192
1193 packet_counter_++;
1194 if (packet_counter_ > max_packets_per_file_) {
1195 OpenNextSnoopLogFile();
1196 }
1197 if (!btsnoop_ostream_.is_open() || !btsnoop_ostream_.good()) {
1198 return;
1199 }
1200 if (!btsnoop_ostream_.write(reinterpret_cast<const char*>(&header), sizeof(PacketHeaderType))) {
1201 log::error("Failed to write packet header for btsnoop, error: \"{}\"", strerror(errno));
1202 }
1203 if (!btsnoop_ostream_.write(reinterpret_cast<const char*>(packet.data()), length - 1)) {
1204 log::error("Failed to write packet payload for btsnoop, error: \"{}\"", strerror(errno));
1205 }
1206
1207 if (socket_ != nullptr) {
1208 socket_->Write(&header, sizeof(PacketHeaderType));
1209 socket_->Write(packet.data(), (size_t)(length - 1));
1210 }
1211
1212 // std::ofstream::flush() pushes user data into kernel memory. The data will be written even if
1213 // this process crashes. However, data will be lost if there is a kernel panic, which is out of
1214 // scope of BT snoop log. NOTE: std::ofstream::write() followed by std::ofstream::flush() has
1215 // similar effect as UNIX write(fd, data, len)
1216 // as write() syscall dumps data into kernel memory directly
1217 if (!btsnoop_ostream_.flush()) {
1218 log::error("Failed to flush, error: \"{}\"", strerror(errno));
1219 }
1220 }
1221 }
1222
DumpSnoozLogToFile()1223 void SnoopLogger::DumpSnoozLogToFile() {
1224 std::lock_guard<std::recursive_mutex> lock(file_mutex_);
1225 std::vector<std::string> data = btsnooz_buffer_.Pull();
1226
1227 if (btsnoop_mode_ != kBtSnoopLogModeDisabled) {
1228 log::debug("btsnoop log is enabled, skip dumping btsnooz log");
1229 return;
1230 }
1231
1232 log::debug("Dumping btsnooz log data to {}", snooz_log_path_);
1233 auto last_file_path = get_last_log_path(snooz_log_path_);
1234
1235 if (os::FileExists(snooz_log_path_)) {
1236 if (!os::RenameFile(snooz_log_path_, last_file_path)) {
1237 log::error("Unabled to rename existing snooz log from \"{}\" to \"{}\"", snooz_log_path_,
1238 last_file_path);
1239 }
1240 } else {
1241 log::info("Previous log file \"{}\" does not exist, skip renaming", snooz_log_path_);
1242 }
1243
1244 mode_t prevmask = umask(0);
1245 // do not use std::ios::app as we want override the existing file
1246 std::ofstream btsnooz_ostream(snooz_log_path_, std::ios::binary | std::ios::out);
1247 if (!btsnooz_ostream.good()) {
1248 log::fatal("Unable to open snoop log at \"{}\", error: \"{}\"", snooz_log_path_,
1249 strerror(errno));
1250 }
1251 umask(prevmask);
1252 if (!btsnooz_ostream.write(reinterpret_cast<const char*>(&SnoopLoggerCommon::kBtSnoopFileHeader),
1253 sizeof(SnoopLoggerCommon::FileHeaderType))) {
1254 log::fatal("Unable to write file header to \"{}\", error: \"{}\"", snooz_log_path_,
1255 strerror(errno));
1256 }
1257 for (const auto& packet : data) {
1258 if (!btsnooz_ostream.write(packet.data(), packet.size())) {
1259 log::error("Failed to write packet payload for btsnooz, error: \"{}\"", strerror(errno));
1260 }
1261 }
1262 if (!btsnooz_ostream.flush()) {
1263 log::error("Failed to flush, error: \"{}\"", strerror(errno));
1264 }
1265 }
1266
ListDependencies(ModuleList *) const1267 void SnoopLogger::ListDependencies(ModuleList* /* list */) const {
1268 // We have no dependencies
1269 }
1270
Start()1271 void SnoopLogger::Start() {
1272 std::lock_guard<std::recursive_mutex> lock(file_mutex_);
1273 if (btsnoop_mode_ != kBtSnoopLogModeDisabled && btsnoop_mode_ != kBtSnoopLogModeKernel) {
1274 OpenNextSnoopLogFile();
1275
1276 if (btsnoop_mode_ == kBtSnoopLogModeFiltered) {
1277 EnableFilters();
1278 }
1279
1280 auto snoop_logger_socket = std::make_unique<SnoopLoggerSocket>(&syscall_if);
1281 snoop_logger_socket_thread_ =
1282 std::make_unique<SnoopLoggerSocketThread>(std::move(snoop_logger_socket));
1283 auto thread_started_future = snoop_logger_socket_thread_->Start();
1284 thread_started_future.wait();
1285 if (thread_started_future.get()) {
1286 RegisterSocket(snoop_logger_socket_thread_.get());
1287 } else {
1288 snoop_logger_socket_thread_->Stop();
1289 snoop_logger_socket_thread_.reset();
1290 snoop_logger_socket_thread_ = nullptr;
1291 }
1292 }
1293 alarm_ = std::make_unique<os::RepeatingAlarm>(GetHandler());
1294 alarm_->Schedule(common::Bind(&delete_old_btsnooz_files, snooz_log_path_, snooz_log_life_time_),
1295 snooz_log_delete_alarm_interval_);
1296 }
1297
Stop()1298 void SnoopLogger::Stop() {
1299 std::lock_guard<std::recursive_mutex> lock(file_mutex_);
1300 log::debug("Closing btsnoop log data at {}", snoop_log_path_);
1301 CloseCurrentSnoopLogFile();
1302
1303 if (snoop_logger_socket_thread_ != nullptr) {
1304 snoop_logger_socket_thread_->Stop();
1305 snoop_logger_socket_thread_.reset();
1306 snoop_logger_socket_thread_ = nullptr;
1307 socket_ = nullptr;
1308 }
1309
1310 btsnoop_mode_ = kBtSnoopLogModeDisabled;
1311 // Disable all filters
1312 DisableFilters();
1313
1314 // Cancel the alarm
1315 alarm_->Cancel();
1316 alarm_.reset();
1317 // delete any existing snooz logs
1318 if (!snoop_log_persists) {
1319 delete_btsnoop_files(snooz_log_path_);
1320 }
1321 }
1322
GetMaxPacketsPerFile()1323 size_t SnoopLogger::GetMaxPacketsPerFile() {
1324 // Allow override max packet per file via system property
1325 auto max_packets_per_file = kDefaultBtSnoopMaxPacketsPerFile;
1326 {
1327 auto max_packets_per_file_prop = os::GetSystemProperty(kBtSnoopMaxPacketsPerFileProperty);
1328 if (max_packets_per_file_prop) {
1329 auto max_packets_per_file_number =
1330 common::Uint64FromString(max_packets_per_file_prop.value());
1331 if (max_packets_per_file_number) {
1332 max_packets_per_file = max_packets_per_file_number.value();
1333 }
1334 }
1335 }
1336 return max_packets_per_file;
1337 }
1338
GetMaxPacketsPerBuffer()1339 size_t SnoopLogger::GetMaxPacketsPerBuffer() {
1340 // We want to use at most 256 KB memory for btsnooz log for release builds
1341 // and 512 KB memory for userdebug/eng builds
1342 auto is_debuggable = os::GetSystemPropertyBool(kIsDebuggableProperty, false);
1343
1344 size_t btsnooz_max_memory_usage_bytes = (is_debuggable ? 1024 : 256) * 1024;
1345 // Calculate max number of packets based on max memory usage and max packet size
1346 return btsnooz_max_memory_usage_bytes / kDefaultBtSnoozMaxBytesPerPacket;
1347 }
1348
GetCurrentSnoopMode()1349 std::string SnoopLogger::GetCurrentSnoopMode() { return btsnoop_mode_; }
1350
GetBtSnoopMode()1351 static std::string GetBtSnoopMode() {
1352 // Default mode is FILTERED on userdebug/eng build, DISABLED on user build.
1353 // In userdebug/eng build, it can also be overwritten by modifying the global setting
1354 std::string btsnoop_mode = SnoopLogger::kBtSnoopLogModeDisabled;
1355 if (os::GetSystemPropertyBool(SnoopLogger::kIsDebuggableProperty, false)) {
1356 btsnoop_mode = os::GetSystemProperty(SnoopLogger::kBtSnoopDefaultLogModeProperty)
1357 .value_or(SnoopLogger::kBtSnoopLogModeFiltered);
1358 }
1359
1360 btsnoop_mode = os::GetSystemProperty(SnoopLogger::kBtSnoopLogModeProperty).value_or(btsnoop_mode);
1361
1362 // Only allow a subset of values:
1363 if (!(btsnoop_mode == SnoopLogger::kBtSnoopLogModeDisabled ||
1364 btsnoop_mode == SnoopLogger::kBtSnoopLogModeFull ||
1365 btsnoop_mode == SnoopLogger::kBtSnoopLogModeFiltered ||
1366 btsnoop_mode == SnoopLogger::kBtSnoopLogModeKernel)) {
1367 log::warn("{}: Invalid btsnoop value, default back to disabled", btsnoop_mode);
1368 return SnoopLogger::kBtSnoopLogModeDisabled;
1369 }
1370
1371 return btsnoop_mode;
1372 }
1373
RegisterSocket(SnoopLoggerSocketInterface * socket)1374 void SnoopLogger::RegisterSocket(SnoopLoggerSocketInterface* socket) {
1375 std::lock_guard<std::recursive_mutex> lock(file_mutex_);
1376 socket_ = socket;
1377 }
1378
IsBtSnoopLogPersisted()1379 bool SnoopLogger::IsBtSnoopLogPersisted() {
1380 auto is_debuggable = os::GetSystemPropertyBool(kIsDebuggableProperty, false);
1381 return is_debuggable && os::GetSystemPropertyBool(kBtSnoopLogPersists, false);
1382 }
1383
IsQualcommDebugLogEnabled()1384 bool SnoopLogger::IsQualcommDebugLogEnabled() {
1385 // Check system prop if the soc manufacturer is Qualcomm
1386 bool qualcomm_debug_log_enabled = false;
1387 {
1388 auto soc_manufacturer_prop = os::GetSystemProperty(kSoCManufacturerProperty);
1389 qualcomm_debug_log_enabled =
1390 soc_manufacturer_prop.has_value() &&
1391 common::StringTrim(soc_manufacturer_prop.value()) == kSoCManufacturerQualcomm;
1392 }
1393 return qualcomm_debug_log_enabled;
1394 }
1395
__anon8e6f38e40502() 1396 const ModuleFactory SnoopLogger::Factory = ModuleFactory([]() {
1397 return new SnoopLogger(os::ParameterProvider::SnoopLogFilePath(),
1398 os::ParameterProvider::SnoozLogFilePath(), GetMaxPacketsPerFile(),
1399 GetMaxPacketsPerBuffer(), GetBtSnoopMode(), IsQualcommDebugLogEnabled(),
1400 kBtSnoozLogLifeTime, kBtSnoozLogDeleteRepeatingAlarmInterval,
1401 IsBtSnoopLogPersisted());
1402 });
1403
1404 #ifdef __ANDROID__
LogTracePoint(const HciPacket & packet,Direction direction,PacketType type)1405 void SnoopLogger::LogTracePoint(const HciPacket& packet, Direction direction, PacketType type) {
1406 switch (type) {
1407 case PacketType::EVT: {
1408 uint8_t evt_code = packet[0];
1409
1410 if (evt_code == static_cast<uint8_t>(hci::EventCode::LE_META_EVENT) ||
1411 evt_code == static_cast<uint8_t>(hci::EventCode::VENDOR_SPECIFIC)) {
1412 uint8_t subevt_code = packet[2];
1413 std::string message =
1414 std::format("BTSL:{}/{}/{}/{:02x}/{:02x}", static_cast<uint8_t>(type),
1415 static_cast<uint8_t>(direction), packet.size(), evt_code, subevt_code);
1416
1417 ATRACE_INSTANT_FOR_TRACK(LOG_TAG, message.c_str());
1418 } else {
1419 std::string message = std::format("BTSL:{}/{}/{}/{:02x}", static_cast<uint8_t>(type),
1420 static_cast<uint8_t>(direction), packet.size(), evt_code);
1421
1422 ATRACE_INSTANT_FOR_TRACK(LOG_TAG, message.c_str());
1423 }
1424 } break;
1425 case PacketType::CMD: {
1426 uint16_t op_code = packet[0] | (packet[1] << 8);
1427
1428 std::string message = std::format("BTSL:{}/{}/{}/{:04x}", static_cast<uint8_t>(type),
1429 static_cast<uint8_t>(direction), packet.size(), op_code);
1430
1431 ATRACE_INSTANT_FOR_TRACK(LOG_TAG, message.c_str());
1432 } break;
1433 case PacketType::ACL: {
1434 uint16_t handle = (packet[0] | (packet[1] << 8)) & 0x0fff;
1435 uint8_t pb_flag = (packet[1] & 0x30) >> 4;
1436
1437 std::string message =
1438 std::format("BTSL:{}/{}/{}/{:03x}/{}", static_cast<uint8_t>(type),
1439 static_cast<uint8_t>(direction), packet.size(), handle, pb_flag);
1440
1441 ATRACE_INSTANT_FOR_TRACK(LOG_TAG, message.c_str());
1442 } break;
1443 case PacketType::ISO:
1444 case PacketType::SCO: {
1445 std::string message = std::format("BTSL:{}/{}/{}", static_cast<uint8_t>(type),
1446 static_cast<uint8_t>(direction), packet.size());
1447
1448 ATRACE_INSTANT_FOR_TRACK(LOG_TAG, message.c_str());
1449 } break;
1450 }
1451 }
1452 #endif // __ANDROID__
1453
1454 } // namespace hal
1455 } // namespace bluetooth
1456