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