1 /*
2  * Copyright 2023 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 LOG_TAG "stack_power_tel"
18 
19 #include "osi/include/stack_power_telemetry.h"
20 
21 #include <bluetooth/log.h>
22 #include <com_android_bluetooth_flags.h>
23 #include <sys/stat.h>
24 #include <time.h>
25 
26 #include <atomic>
27 #include <list>
28 #include <map>
29 #include <mutex>
30 
31 #include "os/logging/log_adapter.h"
32 #include "osi/include/properties.h"
33 #include "stack/include/acl_api_types.h"
34 #include "stack/include/bt_psm_types.h"
35 #include "stack/include/btm_status.h"
36 #include "types/raw_address.h"
37 
38 // TODO(b/369381361) Enfore -Wmissing-prototypes
39 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
40 
41 using namespace bluetooth;
42 
get_current_time()43 time_t get_current_time() { return time(0); }
44 
45 namespace {
46 
47 constexpr int64_t kTrafficLogTime = 120;  // 120seconds
48 constexpr uint8_t kLogEntriesSize{15};
49 constexpr std::string_view kLogPerChannelProperty =
50         "bluetooth.powertelemetry.log_per_channel.enabled";
51 constexpr std::string_view kPowerTelemetryEnabledProperty = "bluetooth.powertelemetry.enabled";
52 bool power_telemerty_enabled_ = false;
53 
GetTimeString(time_t tstamp)54 std::string GetTimeString(time_t tstamp) {
55   char buffer[15];
56   tm* nTm = localtime(&tstamp);
57   strftime(buffer, 15, "%m-%d %H:%M:%S", nTm);
58   return std::string(buffer);
59 }
60 
61 enum class State {
62   kDisconnected = 0,
63   kConnected = 1,
64 };
65 
66 enum class ChannelType {
67   kUnknown = 0,
68   kRfcomm = 1,
69   kL2cap = 2,
70 };
71 
PsmToChannelType(const uint16_t & psm)72 ChannelType PsmToChannelType(const uint16_t& psm) {
73   switch (psm) {
74     case BT_PSM_RFCOMM:
75       return ChannelType::kRfcomm;
76       break;
77   }
78   return ChannelType::kL2cap;
79 }
80 
81 struct Duration {
82   time_t begin = 0;
83   time_t end = 0;
84 };
85 
86 struct DataTransfer {
87   struct {
88     int64_t bytes{0};
89   } rx, tx;
90 };
91 
92 struct LinkDetails {
93   RawAddress bd_addr = RawAddress::kEmpty;
94   uint16_t handle = 0;
95   Duration duration;
96   uint8_t tx_power_level = 0;
97 };
98 
99 struct ChannelDetails {
100   RawAddress bd_addr = RawAddress::kEmpty;
101   int32_t psm = 0;
102   struct {
103     uint16_t cid = 0;
104   } src, dst;
105   State state = State::kDisconnected;
106   ChannelType channel_type = ChannelType::kUnknown;
107   DataTransfer data_transfer;
108   Duration duration;
109   struct {
110     time_t last_data_sent = 0;
111   } rx, tx;
112 };
113 
114 struct AclPacketDetails {
115   struct {
116     uint32_t pkt_count = 0;
117     int64_t byte_count = 0;
118   } rx, tx;
119 };
120 
121 struct AdvDetails {
122   Duration active;
123 };
124 
125 struct ScanDetails {
126   int32_t count = 0;
127 };
128 
129 struct SniffData {
130   RawAddress bd_addr = RawAddress::kEmpty;
131   uint32_t sniff_count = 0, active_count = 0;
132   time_t sniff_duration_ts = 0, active_duration_ts = 0;
133   time_t last_mode_change_ts = get_current_time();
134 };
135 
136 class LogDataContainer {
137 public:
138   struct Duration lifetime;
139   std::map<RawAddress, std::list<ChannelDetails>> channel_map;
140   DataTransfer l2c_data, rfc_data;
141   std::map<uint16_t, SniffData> sniff_activity_map;
142   struct {
143     std::map<uint16_t, LinkDetails> link_details_map;
144     std::list<LinkDetails> link_details_list;
145   } acl, sco;
146   std::list<AdvDetails> adv_list;
147   ScanDetails scan_details, inq_scan_details, le_scan_details;
148   AclPacketDetails acl_pkt_ds, hci_cmd_evt_ds;
149 };
150 
151 }  // namespace
152 
153 struct power_telemetry::PowerTelemetryImpl {
PowerTelemetryImplpower_telemetry::PowerTelemetryImpl154   PowerTelemetryImpl() {
155     idx_containers = 0;
156     traffic_logged_ts_ = get_current_time();
157     log_per_channel_ = osi_property_get_bool(std::string(kLogPerChannelProperty).c_str(), false);
158     power_telemetry_enabled_property_ =
159             osi_property_get_bool(std::string(kPowerTelemetryEnabledProperty).c_str(), true);
160 
161     // Enable this feature when both feature flag and sysprops turn on.
162     power_telemerty_enabled_ = com::android::bluetooth::flags::bluetooth_power_telemetry() &&
163                                power_telemetry_enabled_property_;
164   }
165 
GetCurrentLogDataContainerpower_telemetry::PowerTelemetryImpl166   LogDataContainer& GetCurrentLogDataContainer() { return log_data_containers_[idx_containers]; }
167 
maybe_log_datapower_telemetry::PowerTelemetryImpl168   void maybe_log_data() {
169     if ((get_current_time() - traffic_logged_ts_) >= kTrafficLogTime) {
170       LogDataTransfer();
171     }
172   }
173 
174   void LogDataTransfer();
175   void RecordLogDataContainer();
176 
177   mutable std::mutex dumpsys_mutex_;
178   LogDataContainer log_data_containers_[kLogEntriesSize];
179   std::atomic_int idx_containers;
180   time_t traffic_logged_ts_ = 0;
181   struct {
182     struct {
183       int64_t bytes_ = 0;
184     } rx, tx;
185   } l2c, rfc;
186   struct {
187     uint32_t pkt_ = 0;
188     int64_t len_ = 0;
189   } rx, tx;
190 
191   struct {
192     uint16_t count_ = 0;
193   } scan, inq_scan, ble_adv, ble_scan;
194 
195   struct {
196     uint32_t count_ = 0;
197   } cmd, event;
198   bool scan_timer_started_ = false;
199   bool log_per_channel_ = false;
200   bool power_telemetry_enabled_property_ = false;
201 };
202 
LogDataTransfer()203 void power_telemetry::PowerTelemetryImpl::LogDataTransfer() {
204   if (!power_telemerty_enabled_) {
205     return;
206   }
207 
208   LogDataContainer& ldc = GetCurrentLogDataContainer();
209 
210   if ((l2c.rx.bytes_ != 0) || (l2c.tx.bytes_ != 0)) {
211     ldc.l2c_data = {
212             .rx =
213                     {
214                             .bytes = l2c.rx.bytes_,
215                     },
216             .tx =
217                     {
218                             .bytes = l2c.tx.bytes_,
219                     },
220     };
221     l2c = {};
222   }
223 
224   if ((rfc.rx.bytes_ != 0) || (rfc.tx.bytes_ != 0)) {
225     ldc.rfc_data = {
226             .rx =
227                     {
228                             .bytes = rfc.rx.bytes_,
229                     },
230             .tx =
231                     {
232                             .bytes = rfc.tx.bytes_,
233                     },
234     };
235     rfc = {};
236   }
237 
238   if (scan.count_ != 0) {
239     ldc.scan_details = {
240             .count = scan.count_,
241     };
242     scan.count_ = 0;
243   }
244 
245   if (inq_scan.count_ != 0) {
246     ldc.inq_scan_details = {
247             .count = inq_scan.count_,
248     };
249     inq_scan.count_ = 0;
250   }
251 
252   if ((rx.pkt_ != 0) || (tx.pkt_ != 0)) {
253     ldc.acl_pkt_ds = {
254             .rx =
255                     {
256                             .pkt_count = rx.pkt_,
257                             .byte_count = rx.len_,
258                     },
259             .tx =
260                     {
261                             .pkt_count = tx.pkt_,
262                             .byte_count = tx.len_,
263                     },
264     };
265     rx.pkt_ = tx.pkt_ = rx.len_ = tx.len_ = 0;
266   }
267 
268   if ((cmd.count_ != 0) || (event.count_ != 0)) {
269     ldc.hci_cmd_evt_ds = {
270             .rx =
271                     {
272                             .pkt_count = event.count_,
273                     },
274             .tx =
275                     {
276                             .pkt_count = cmd.count_,
277                     },
278     };
279     cmd.count_ = event.count_ = 0;
280   }
281 
282   if (ble_scan.count_ != 0) {
283     ldc.le_scan_details = {
284             .count = ble_scan.count_,
285     };
286     ble_scan.count_ = 0;
287   }
288 
289   ldc.lifetime.begin = traffic_logged_ts_;
290   ldc.lifetime.end = get_current_time();
291 
292   traffic_logged_ts_ = get_current_time();
293   RecordLogDataContainer();
294 }
295 
RecordLogDataContainer()296 void power_telemetry::PowerTelemetryImpl::RecordLogDataContainer() {
297   if (!power_telemerty_enabled_) {
298     return;
299   }
300 
301   LogDataContainer& ldc = GetCurrentLogDataContainer();
302 
303   log::info(
304           "bt_power: scan: {}, inqScan: {}, aclTx: {}, aclRx: {}, hciCmd: {}, "
305           "hciEvt: {}, bleScan: {}",
306           ldc.scan_details.count, ldc.inq_scan_details.count, ldc.acl_pkt_ds.tx.pkt_count,
307           ldc.acl_pkt_ds.rx.pkt_count, ldc.hci_cmd_evt_ds.tx.pkt_count,
308           ldc.hci_cmd_evt_ds.rx.pkt_count, ldc.le_scan_details.count);
309 
310   idx_containers++;
311   if (idx_containers >= kLogEntriesSize) {
312     idx_containers = 0;
313   }
314 
315   log_data_containers_[idx_containers] = LogDataContainer();
316 }
317 
GetInstance()318 power_telemetry::PowerTelemetry& power_telemetry::GetInstance() {
319   static power_telemetry::PowerTelemetry power_telemetry;
320   return power_telemetry;
321 }
322 
PowerTelemetry()323 power_telemetry::PowerTelemetry::PowerTelemetry() {
324   pimpl_ = std::make_unique<PowerTelemetryImpl>();
325 }
326 
LogInqScanStarted()327 void power_telemetry::PowerTelemetry::LogInqScanStarted() {
328   if (!power_telemerty_enabled_) {
329     return;
330   }
331 
332   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
333   pimpl_->inq_scan.count_++;
334   pimpl_->maybe_log_data();
335 }
336 
LogInqScanStopped()337 void power_telemetry::PowerTelemetry::LogInqScanStopped() {
338   if (!power_telemerty_enabled_) {
339     return;
340   }
341 
342   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
343   pimpl_->maybe_log_data();
344 }
345 
LogBleScan(uint16_t num_resps)346 void power_telemetry::PowerTelemetry::LogBleScan(uint16_t num_resps) {
347   if (!power_telemerty_enabled_) {
348     return;
349   }
350 
351   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
352   pimpl_->ble_scan.count_ += num_resps;
353   pimpl_->maybe_log_data();
354 }
355 
LogBleAdvStarted()356 void power_telemetry::PowerTelemetry::LogBleAdvStarted() {
357   if (!power_telemerty_enabled_) {
358     return;
359   }
360 
361   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
362   const time_t current_time = get_current_time();
363   LogDataContainer& ldc = pimpl_->GetCurrentLogDataContainer();
364   ldc.adv_list.emplace_back(AdvDetails{.active.begin = current_time});
365 }
366 
LogBleAdvStopped()367 void power_telemetry::PowerTelemetry::LogBleAdvStopped() {
368   if (!power_telemerty_enabled_) {
369     return;
370   }
371 
372   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
373   const time_t current_time = get_current_time();
374 
375   LogDataContainer& ldc = pimpl_->GetCurrentLogDataContainer();
376   if (ldc.adv_list.size() == 0) {
377     log::warn("Empty advList. Skip LogBleAdvDetails.");
378     return;
379   }
380   ldc.adv_list.back().active.end = current_time;
381 }
382 
LogTxPower(void * res)383 void power_telemetry::PowerTelemetry::LogTxPower(void* res) {
384   if (!power_telemerty_enabled_) {
385     return;
386   }
387 
388   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
389   tBTM_TX_POWER_RESULT* result = (tBTM_TX_POWER_RESULT*)res;
390   LogDataContainer& ldc = pimpl_->GetCurrentLogDataContainer();
391 
392   if (result->status != tBTM_STATUS::BTM_SUCCESS) {
393     return;
394   }
395 
396   for (auto it : ldc.acl.link_details_map) {
397     uint16_t handle = it.first;
398     LinkDetails lds = it.second;
399     if (lds.bd_addr == result->rem_bda) {
400       lds.tx_power_level = result->tx_power;
401       ldc.acl.link_details_map[handle] = lds;
402       break;
403     }
404   }
405   pimpl_->maybe_log_data();
406 }
407 
LogLinkDetails(uint16_t handle,const RawAddress & bd_addr,bool is_connected,bool is_acl_link)408 void power_telemetry::PowerTelemetry::LogLinkDetails(uint16_t handle, const RawAddress& bd_addr,
409                                                      bool is_connected, bool is_acl_link) {
410   if (!power_telemerty_enabled_) {
411     return;
412   }
413 
414   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
415   LogDataContainer& ldc = pimpl_->GetCurrentLogDataContainer();
416   std::map<uint16_t, LinkDetails>& link_map =
417           is_acl_link ? ldc.acl.link_details_map : ldc.sco.link_details_map;
418   std::list<LinkDetails>& link_list =
419           is_acl_link ? ldc.acl.link_details_list : ldc.sco.link_details_list;
420 
421   if (is_connected == false && link_map.count(handle) != 0) {
422     LinkDetails link_details = link_map[handle];
423     link_details.duration.end = get_current_time();
424     link_list.push_back(link_details);
425     link_map.erase(handle);
426   } else if (is_connected == true) {
427     link_map[handle] = {
428             .bd_addr = bd_addr,
429             .handle = handle,
430             .duration.begin = get_current_time(),
431             .tx_power_level = 0,
432     };
433 
434     if (is_acl_link) {
435       SniffData sniff_data;
436       if (ldc.sniff_activity_map.count(handle) != 0) {
437         ldc.sniff_activity_map.erase(handle);
438       }
439       sniff_data.bd_addr = bd_addr;
440       sniff_data.active_count = 1;
441       sniff_data.last_mode_change_ts = get_current_time();
442       ldc.sniff_activity_map[handle] = sniff_data;
443     }
444   }
445 
446   pimpl_->maybe_log_data();
447 }
448 
LogHciCmdDetail()449 void power_telemetry::PowerTelemetry::LogHciCmdDetail() {
450   if (!power_telemerty_enabled_) {
451     return;
452   }
453 
454   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
455   pimpl_->cmd.count_++;
456   pimpl_->maybe_log_data();
457 }
458 
LogHciEvtDetail()459 void power_telemetry::PowerTelemetry::LogHciEvtDetail() {
460   if (!power_telemerty_enabled_) {
461     return;
462   }
463 
464   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
465   pimpl_->event.count_++;
466   pimpl_->maybe_log_data();
467 }
468 
LogSniffStarted(uint16_t handle,const RawAddress & bd_addr)469 void power_telemetry::PowerTelemetry::LogSniffStarted(uint16_t handle, const RawAddress& bd_addr) {
470   if (!power_telemerty_enabled_) {
471     return;
472   }
473 
474   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
475   const time_t current_timestamp = get_current_time();
476   SniffData sniff_data;
477   LogDataContainer& ldc = pimpl_->GetCurrentLogDataContainer();
478   if (ldc.sniff_activity_map.count(handle) == 0) {
479     sniff_data.bd_addr = bd_addr;
480   } else {
481     sniff_data = ldc.sniff_activity_map[handle];
482   }
483   sniff_data.sniff_count++;
484   sniff_data.active_duration_ts += current_timestamp - sniff_data.last_mode_change_ts;
485   sniff_data.last_mode_change_ts = get_current_time();
486   ldc.sniff_activity_map[handle] = sniff_data;
487 
488   pimpl_->maybe_log_data();
489 }
490 
LogSniffStopped(uint16_t handle,const RawAddress & bd_addr)491 void power_telemetry::PowerTelemetry::LogSniffStopped(uint16_t handle, const RawAddress& bd_addr) {
492   if (!power_telemerty_enabled_) {
493     return;
494   }
495 
496   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
497   const time_t current_timestamp = get_current_time();
498   SniffData sniff_data;
499   LogDataContainer& ldc = pimpl_->GetCurrentLogDataContainer();
500   if (ldc.sniff_activity_map.count(handle) == 0) {
501     sniff_data.bd_addr = bd_addr;
502   } else {
503     sniff_data = ldc.sniff_activity_map[handle];
504   }
505   sniff_data.active_count++;
506   sniff_data.sniff_duration_ts += current_timestamp - sniff_data.last_mode_change_ts;
507   sniff_data.last_mode_change_ts = get_current_time();
508   ldc.sniff_activity_map[handle] = sniff_data;
509 
510   pimpl_->maybe_log_data();
511 }
512 
LogScanStarted()513 void power_telemetry::PowerTelemetry::LogScanStarted() {
514   if (!power_telemerty_enabled_) {
515     return;
516   }
517 
518   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
519   pimpl_->scan.count_++;
520   pimpl_->maybe_log_data();
521 }
522 
LogTxAclPktData(uint16_t len)523 void power_telemetry::PowerTelemetry::LogTxAclPktData(uint16_t len) {
524   if (!power_telemerty_enabled_) {
525     return;
526   }
527 
528   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
529   pimpl_->tx.pkt_++;
530   pimpl_->tx.len_ += len;
531   pimpl_->maybe_log_data();
532 }
533 
LogRxAclPktData(uint16_t len)534 void power_telemetry::PowerTelemetry::LogRxAclPktData(uint16_t len) {
535   if (!power_telemerty_enabled_) {
536     return;
537   }
538 
539   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
540   pimpl_->rx.pkt_++;
541   pimpl_->rx.len_ += len;
542   pimpl_->maybe_log_data();
543 }
544 
LogChannelConnected(uint16_t psm,int32_t src_id,int32_t dst_id,const RawAddress & bd_addr)545 void power_telemetry::PowerTelemetry::LogChannelConnected(uint16_t psm, int32_t src_id,
546                                                           int32_t dst_id,
547                                                           const RawAddress& bd_addr) {
548   if (!power_telemerty_enabled_) {
549     return;
550   }
551 
552   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
553   std::list<ChannelDetails> channel_details_list;
554   LogDataContainer& ldc = pimpl_->GetCurrentLogDataContainer();
555   const ChannelType channel_type = PsmToChannelType(psm);
556   ChannelDetails channel_details = {
557           .bd_addr = bd_addr,
558           .psm = psm,
559           .src.cid = static_cast<uint16_t>(src_id),
560           .dst.cid = static_cast<uint16_t>(dst_id),
561           .state = State::kConnected,
562           .channel_type = channel_type,
563           .data_transfer = {},
564           .duration.begin = get_current_time(),
565           .rx = {},
566           .tx = {},
567   };
568 
569   if (ldc.channel_map.count(bd_addr) == 0) {
570     ldc.channel_map.insert(std::pair<RawAddress, std::list<ChannelDetails>>(
571             bd_addr, std::list<ChannelDetails>({channel_details})));
572   } else {
573     ldc.channel_map[bd_addr].emplace_back(channel_details);
574   }
575 
576   pimpl_->maybe_log_data();
577 }
578 
LogChannelDisconnected(uint16_t psm,int32_t src_id,int32_t dst_id,const RawAddress & bd_addr)579 void power_telemetry::PowerTelemetry::LogChannelDisconnected(uint16_t psm, int32_t src_id,
580                                                              int32_t dst_id,
581                                                              const RawAddress& bd_addr) {
582   if (!power_telemerty_enabled_) {
583     return;
584   }
585 
586   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
587   std::list<ChannelDetails> channel_details_list;
588   LogDataContainer& ldc = pimpl_->GetCurrentLogDataContainer();
589   if (ldc.channel_map.count(bd_addr) == 0) {
590     return;
591   }
592 
593   const ChannelType channel_type = PsmToChannelType(psm);
594 
595   for (auto& channel_detail : ldc.channel_map[bd_addr]) {
596     if (channel_detail.src.cid == src_id && channel_detail.dst.cid == dst_id &&
597         channel_detail.channel_type == channel_type) {
598       channel_detail.state = State::kDisconnected;
599       channel_detail.duration.end = get_current_time();
600       break;
601     }
602   }
603 
604   pimpl_->maybe_log_data();
605 }
606 
LogTxBytes(uint16_t psm,int32_t src_id,int32_t dst_id,const RawAddress & bd_addr,int32_t num_bytes)607 void power_telemetry::PowerTelemetry::LogTxBytes(uint16_t psm, int32_t src_id, int32_t dst_id,
608                                                  const RawAddress& bd_addr, int32_t num_bytes) {
609   if (!power_telemerty_enabled_) {
610     return;
611   }
612 
613   const ChannelType channel_type = PsmToChannelType(psm);
614   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
615   if (pimpl_->log_per_channel_ == true) {
616     std::list<ChannelDetails> channel_details_list;
617     LogDataContainer& ldc = pimpl_->GetCurrentLogDataContainer();
618     if (ldc.channel_map.count(bd_addr) == 0) {
619       return;
620     }
621 
622     for (auto& channel_details : ldc.channel_map[bd_addr]) {
623       if (channel_details.src.cid == src_id && channel_details.dst.cid == dst_id &&
624           channel_details.channel_type == channel_type) {
625         channel_details.data_transfer.tx.bytes += num_bytes;
626         channel_details.tx.last_data_sent = get_current_time();
627         break;
628       }
629     }
630   }
631   if (channel_type == ChannelType::kRfcomm) {
632     pimpl_->rfc.tx.bytes_ += num_bytes;
633   } else {
634     pimpl_->l2c.tx.bytes_ += num_bytes;
635   }
636   pimpl_->maybe_log_data();
637 }
638 
LogRxBytes(uint16_t psm,int32_t src_id,int32_t dst_id,const RawAddress & bd_addr,int32_t num_bytes)639 void power_telemetry::PowerTelemetry::LogRxBytes(uint16_t psm, int32_t src_id, int32_t dst_id,
640                                                  const RawAddress& bd_addr, int32_t num_bytes) {
641   if (!power_telemerty_enabled_) {
642     return;
643   }
644 
645   const ChannelType channel_type = PsmToChannelType(psm);
646   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
647   if (pimpl_->log_per_channel_ == true) {
648     std::list<ChannelDetails> channel_details_list;
649     LogDataContainer& ldc = pimpl_->GetCurrentLogDataContainer();
650     if (ldc.channel_map.count(bd_addr) == 0) {
651       return;
652     }
653 
654     for (auto& channel_detail : ldc.channel_map[bd_addr]) {
655       if (channel_detail.src.cid == src_id && channel_detail.dst.cid == dst_id &&
656           channel_detail.channel_type == channel_type) {
657         channel_detail.data_transfer.rx.bytes += num_bytes;
658         channel_detail.rx.last_data_sent = get_current_time();
659         break;
660       }
661     }
662   }
663 
664   switch (channel_type) {
665     case ChannelType::kRfcomm:
666       pimpl_->rfc.rx.bytes_ += num_bytes;
667       break;
668     case ChannelType::kL2cap:
669       pimpl_->l2c.rx.bytes_ += num_bytes;
670       break;
671     case ChannelType::kUnknown:
672       break;
673   }
674 
675   pimpl_->maybe_log_data();
676 }
677 
Dumpsys(int32_t fd)678 void power_telemetry::PowerTelemetry::Dumpsys(int32_t fd) {
679   if (!power_telemerty_enabled_) {
680     return;
681   }
682 
683   std::lock_guard<std::mutex> lock(pimpl_->dumpsys_mutex_);
684   pimpl_->RecordLogDataContainer();
685 
686   dprintf(fd, "\nPower Telemetry Data:\n");
687   dprintf(fd, "\nBR/EDR Scan Events:\n");
688   dprintf(fd, "%-22s %-22s %-15s\n", "StartTimeStamp", "EndTimeStamp", "Number of Scans");
689   for (auto&& ldc : pimpl_->log_data_containers_) {
690     if (ldc.scan_details.count == 0) {
691       continue;
692     }
693     dprintf(fd, "%-22s %-22s %-15d\n", GetTimeString(ldc.lifetime.begin).c_str(),
694             GetTimeString(ldc.lifetime.end).c_str(), ldc.scan_details.count);
695   }
696   dprintf(fd, "\nBR/EDR InqScan Events:\n");
697   dprintf(fd, "%-22s %-22s %-15s\n", "StartTimeStamp", "EndTimeStamp", "Number of InqScans");
698   for (auto&& ldc : pimpl_->log_data_containers_) {
699     if (ldc.inq_scan_details.count == 0) {
700       continue;
701     }
702     dprintf(fd, "%-22s %-22s %-15d\n", GetTimeString(ldc.lifetime.begin).c_str(),
703             GetTimeString(ldc.lifetime.end).c_str(), ldc.inq_scan_details.count);
704   }
705 
706   dprintf(fd, "\nACL Packet Details:\n");
707   dprintf(fd, "%-22s %-22s %-12s %-12s %-12s %-12s\n", "StartTimeStamp", "EndTimeStamp",
708           "Tx Packets", "Tx Bytes", "Rx Packets", "Rx Bytes");
709   for (auto&& ldc : pimpl_->log_data_containers_) {
710     if ((ldc.acl_pkt_ds.tx.byte_count == 0) && (ldc.acl_pkt_ds.rx.byte_count == 0)) {
711       continue;
712     }
713     dprintf(fd, "%-22s %-22s %-12d %-12ld %-12d %-12ld\n",
714             GetTimeString(ldc.lifetime.begin).c_str(), GetTimeString(ldc.lifetime.end).c_str(),
715             ldc.acl_pkt_ds.tx.pkt_count, (long)ldc.acl_pkt_ds.tx.byte_count,
716             ldc.acl_pkt_ds.rx.pkt_count, (long)ldc.acl_pkt_ds.rx.byte_count);
717   }
718 
719   dprintf(fd, "\nHCI CMD/EVT Details:\n");
720   dprintf(fd, "%-22s %-22s %-14s %-14s\n", "StartTimeStamp", "EndTimeStamp", "HCI Commands",
721           "HCI Events");
722   for (auto&& ldc : pimpl_->log_data_containers_) {
723     if ((ldc.hci_cmd_evt_ds.tx.pkt_count == 0) && (ldc.hci_cmd_evt_ds.rx.pkt_count == 0)) {
724       continue;
725     }
726     dprintf(fd, "%-22s %-22s %-14d %-14d\n", GetTimeString(ldc.lifetime.begin).c_str(),
727             GetTimeString(ldc.lifetime.end).c_str(), ldc.hci_cmd_evt_ds.tx.pkt_count,
728             ldc.hci_cmd_evt_ds.rx.pkt_count);
729   }
730   dprintf(fd, "\nBLE Scan Details:\n");
731   dprintf(fd, "%-22s %-22s %-14s\n", "StartTimeStamp", "EndTimeStamp", "Number of scans");
732   for (auto&& ldc : pimpl_->log_data_containers_) {
733     if (ldc.le_scan_details.count == 0) {
734       continue;
735     }
736     dprintf(fd, "%-22s %-22s %-14d\n", GetTimeString(ldc.lifetime.begin).c_str(),
737             GetTimeString(ldc.lifetime.end).c_str(), ldc.le_scan_details.count);
738   }
739   dprintf(fd, "\nL2CAP/RFCOMM Channel Events:\n");
740   dprintf(fd, "%-19s %-7s %-7s %-7s %-8s %-22s", "RemoteAddress", "Type", "SrcId", "DstId", "PSM",
741           "ConnectedTimeStamp");
742   dprintf(fd, " %-22s %-14s ", "DisconnectedTimeStamp", "State");
743   if (pimpl_->log_per_channel_ == true) {
744     dprintf(fd, " %-10s %-10s %-22s %-22s", "TxBytes", "RxBytes", "LastTxTimeStamp",
745             "LastRxTimeStamp");
746   }
747   dprintf(fd, "\n");
748   for (auto&& ldc : pimpl_->log_data_containers_) {
749     for (auto& itr : ldc.channel_map) {
750       const RawAddress& bd_addr = itr.first;
751       std::list<ChannelDetails> channel_details_list = itr.second;
752       for (auto& channel_details : channel_details_list) {
753         dprintf(fd, "%-19s ", ADDRESS_TO_LOGGABLE_CSTR(bd_addr));
754         dprintf(fd, "%-7s %-7d %-7d %-8d %-22s %-22s %-14s",
755                 (channel_details.channel_type == ChannelType::kRfcomm) ? "RFCOMM" : "L2CAP",
756                 channel_details.src.cid, channel_details.dst.cid, channel_details.psm,
757                 GetTimeString(channel_details.duration.begin).c_str(),
758                 GetTimeString(channel_details.duration.end).c_str(),
759                 (channel_details.state == State::kDisconnected) ? "DISCONNECTED" : "CONNECTED");
760         if (pimpl_->log_per_channel_ == true) {
761           dprintf(fd, "%-10ld %-10ld %-22s %-22s", (long)channel_details.data_transfer.tx.bytes,
762                   (long)channel_details.data_transfer.rx.bytes,
763                   GetTimeString(channel_details.tx.last_data_sent).c_str(),
764                   GetTimeString(channel_details.rx.last_data_sent).c_str());
765         }
766         dprintf(fd, "\n");
767       }
768     }
769   }
770 
771   dprintf(fd, "\n\nBluetooth Data Traffic Details\n");
772   dprintf(fd, "L2cap Data Traffic\n");
773   dprintf(fd, "%-22s %-22s %-10s %-10s\n", "StartTime", "EndTime", "TxBytes", "RxBytes");
774   for (auto&& ldc : pimpl_->log_data_containers_) {
775     if (ldc.l2c_data.tx.bytes == 0 && ldc.l2c_data.rx.bytes) {
776       continue;
777     }
778     dprintf(fd, "%-22s %-22s %-10ld %-10ld\n", GetTimeString(ldc.lifetime.begin).c_str(),
779             GetTimeString(ldc.lifetime.end).c_str(), (long)ldc.l2c_data.tx.bytes,
780             (long)ldc.l2c_data.rx.bytes);
781   }
782 
783   dprintf(fd, "\nRfcomm Data Traffic\n");
784   dprintf(fd, "%-22s %-22s %-10s %-10s\n", "StartTime", "EndTime", "TxBytes", "RxBytes");
785   for (auto&& ldc : pimpl_->log_data_containers_) {
786     if (ldc.rfc_data.tx.bytes == 0 && ldc.rfc_data.rx.bytes == 0) {
787       continue;
788     }
789     dprintf(fd, "%-22s %-22s %-10ld %-10ld\n", GetTimeString(ldc.lifetime.begin).c_str(),
790             GetTimeString(ldc.lifetime.end).c_str(), (long)ldc.rfc_data.tx.bytes,
791             (long)ldc.rfc_data.rx.bytes);
792   }
793 
794   dprintf(fd, "\n\nSniff Activity Details\n");
795   dprintf(fd, "%-8s %-19s %-19s %-24s %-19s %-24s\n", "Handle", "BDADDR", "ActiveModeCount",
796           "ActiveModeDuration(sec)", "SniffModeCount", "SniffModeDuration(sec)");
797   for (auto&& ldc : pimpl_->log_data_containers_) {
798     for (auto itr : ldc.sniff_activity_map) {
799       uint16_t handle = itr.first;
800       SniffData sniff_data = itr.second;
801       dprintf(fd, "%-8d %-19s %-19d %-24ld %-19d %-24ld\n", handle,
802               ADDRESS_TO_LOGGABLE_CSTR(sniff_data.bd_addr), sniff_data.active_count,
803               (long)sniff_data.active_duration_ts, sniff_data.sniff_count,
804               (long)sniff_data.sniff_duration_ts);
805     }
806   }
807 
808   dprintf(fd, "\n\nACL Link Details\n");
809   dprintf(fd, "%-6s %-19s %-22s %-22s %-8s\n", "handle", "BDADDR", "ConnectedTimeStamp",
810           "DisconnectedTimeStamp", "TxPower");
811   for (auto&& ldc : pimpl_->log_data_containers_) {
812     for (auto it : ldc.acl.link_details_map) {
813       uint16_t handle = it.first;
814       LinkDetails lds = it.second;
815       dprintf(fd, "%-6d %-19s %-22s %-22s %-8d\n", handle, ADDRESS_TO_LOGGABLE_CSTR(lds.bd_addr),
816               GetTimeString(lds.duration.begin).c_str(), GetTimeString(lds.duration.end).c_str(),
817               lds.tx_power_level);
818     }
819 
820     for (auto& it : ldc.acl.link_details_list) {
821       dprintf(fd, "%-6d %-19s %-22s %-22s %-8d\n", it.handle, ADDRESS_TO_LOGGABLE_CSTR(it.bd_addr),
822               GetTimeString(it.duration.begin).c_str(), GetTimeString(it.duration.end).c_str(),
823               it.tx_power_level);
824     }
825   }
826   dprintf(fd, "\nSCO Link Details\n");
827   dprintf(fd, "%-6s %-19s %-22s %-22s\n", "handle", "BDADDR", "ConnectedTimeStamp",
828           "DisconnectedTimeStamp");
829   for (auto&& ldc : pimpl_->log_data_containers_) {
830     for (auto& it : ldc.sco.link_details_list) {
831       dprintf(fd, "%-6d %-19s %-22s %-22s\n", it.handle, ADDRESS_TO_LOGGABLE_CSTR(it.bd_addr),
832               GetTimeString(it.duration.begin).c_str(), GetTimeString(it.duration.end).c_str());
833     }
834   }
835 
836   dprintf(fd, "\n\n");
837 }
838