Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3e61658f authored by Mingguang Xu's avatar Mingguang Xu
Browse files

btaa: Add device-activity aggregation dumpsys data

1. Add create time into each aggregation entry; aggregation entry
expires after one day.
2. Add device-activity into dumpsys data; Trim down transient
aggregation entries to avoid the unordered map overgrows.

Tag: #feature

Bug: 185819535
Bug: 170315554

Test: mmma -j system/bt
Test: manually capture a bugreport and make sure btaa aggregation data
show up

BYPASS_LONG_LINES_REASON: consist with gd format

Change-Id: I02cc2057796661fa3625492eaf1a429e20da4951
parent 75e0a6e3
Loading
Loading
Loading
Loading
+8 −15
Original line number Diff line number Diff line
@@ -8,29 +8,22 @@ table WakeupEntry {
    address:string;
}

table WakeupAttributionData {
    title:string;
    num_wakeup:int;
    wakeup_attribution:[WakeupEntry];
}

table DeviceActivityAggregationEntry {
    address:string;
    activity:string;
    wakeup_count:int;
    byte_count:int;
    wakelock_duration:int;
}

table DeviceActivityAggregationData {
    title:string;
    device_activity_aggregation:[DeviceActivityAggregationEntry];
    wakelock_duration_ms:int;
    creation_time:string;
}

table ActivityAttributionData {
    title:string (privacy:"Any");
    wakeup_attribution_data:WakeupAttributionData (privacy:"Any");
    device_activity_aggregation_data:DeviceActivityAggregationData (privacy:"Any");
    title_wakeup:string;
    num_wakeup:int;
    wakeup_attribution:[WakeupEntry];
    title_activity:string;
    num_device_activity:int;
    device_activity_aggregation:[DeviceActivityAggregationEntry];
}

root_type ActivityAttributionData;
 No newline at end of file
+4 −2
Original line number Diff line number Diff line
@@ -24,14 +24,16 @@ namespace bluetooth {
namespace activity_attribution {

enum class Activity : uint8_t { UNKNOWN = 0, ACL, ADVERTISE, CONNECT, CONTROL, HFP, ISO, SCAN, VENDOR };
#define CONVERT_ACTIVITY_TO_STR(Activity) std::string(#Activity)

using CreationTime = std::chrono::time_point<std::chrono::system_clock>;

struct BtaaAggregationEntry {
  hci::Address address;
  Activity activity;
  uint16_t wakeup_count;
  uint32_t byte_count;
  uint32_t wakelock_duration;
  uint32_t wakelock_duration_ms;
  CreationTime creation_time;
};

class ActivityAttributionCallback {
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ class AttributionProcessor {
  std::unordered_map<AddressActivityKey, BtaaAggregationEntry, AddressActivityKeyHasher> wakelock_duration_aggregator_;
  common::TimestampedCircularBuffer<WakeupDescriptor> wakeup_aggregator_ =
      common::TimestampedCircularBuffer<WakeupDescriptor>(kWakeupAggregatorSize);
  const char* ActivityToString(Activity activity);
};

}  // namespace activity_attribution
+91 −18
Original line number Diff line number Diff line
@@ -15,12 +15,22 @@
 */

#include "btaa/attribution_processor.h"
#include "common/strings.h"

#include "os/log.h"

namespace bluetooth {
namespace activity_attribution {

constexpr char kActivityAttributionTimeFormat[] = "%Y-%m-%d %H:%M:%S";
// A device-activity aggregation entry expires after two days (172800 seconds)
static const int kDurationToKeepDeviceActivityEntrySecs = 172800;
// A transient device-activity aggregation entry is defined as an entry with very few Byte count
// (200 Bytes, this is about the size of 5 advertising packets) over a period of time (15 minutes)
static const int kByteCountTransientDeviceActivityEntry = 200;
static const int kDurationTransientDeviceActivityEntrySecs = 900;
static const int kMapSizeTrimDownAggregationEntry = 200;

void AttributionProcessor::OnBtaaPackets(std::vector<BtaaHciPacket> btaa_packets) {
  AddressActivityKey key;

@@ -54,17 +64,41 @@ void AttributionProcessor::OnWakelockReleased(uint32_t duration_ms) {
  }

  ms_per_byte = duration_ms / total_byte_count;
  auto cur_time = std::chrono::system_clock::now();
  for (auto& it : wakelock_duration_aggregator_) {
    it.second.wakelock_duration = ms_per_byte * it.second.byte_count;
    it.second.wakelock_duration_ms = ms_per_byte * it.second.byte_count;
    if (btaa_aggregator_.find(it.first) == btaa_aggregator_.end()) {
      btaa_aggregator_[it.first] = {};
      btaa_aggregator_[it.first].creation_time = cur_time;
    }

    auto elapsed_time_sec =
        std::chrono::duration_cast<std::chrono::seconds>(cur_time - btaa_aggregator_[it.first].creation_time).count();
    if (elapsed_time_sec > kDurationToKeepDeviceActivityEntrySecs) {
      btaa_aggregator_[it.first].wakeup_count = 0;
      btaa_aggregator_[it.first].byte_count = 0;
      btaa_aggregator_[it.first].wakelock_duration_ms = 0;
      btaa_aggregator_[it.first].creation_time = cur_time;
    }

    btaa_aggregator_[it.first].wakeup_count += it.second.wakeup_count;
    btaa_aggregator_[it.first].byte_count += it.second.byte_count;
    btaa_aggregator_[it.first].wakelock_duration += it.second.wakelock_duration;
    btaa_aggregator_[it.first].wakelock_duration_ms += it.second.wakelock_duration_ms;
  }
  wakelock_duration_aggregator_.clear();

  if (btaa_aggregator_.size() < kMapSizeTrimDownAggregationEntry) {
    return;
  }
  // Trim down the transient entries in the aggregator to avoid that it overgrows
  for (auto& it : btaa_aggregator_) {
    auto elapsed_time_sec =
        std::chrono::duration_cast<std::chrono::seconds>(cur_time - it.second.creation_time).count();
    if (elapsed_time_sec > kDurationTransientDeviceActivityEntrySecs &&
        it.second.byte_count < kByteCountTransientDeviceActivityEntry) {
      btaa_aggregator_.erase(it.first);
    }
  }
}

void AttributionProcessor::OnWakeup() {
@@ -76,33 +110,72 @@ void AttributionProcessor::OnWakeup() {

void AttributionProcessor::Dump(
    std::promise<flatbuffers::Offset<ActivityAttributionData>> promise, flatbuffers::FlatBufferBuilder* fb_builder) {
  auto title = fb_builder->CreateString("----- BTAA Dumpsys -----");
  ActivityAttributionDataBuilder builder(*fb_builder);
  builder.add_title(title);

  WakeupAttributionDataBuilder wakeup_attribution_builder(*fb_builder);
  auto wakeup_title = fb_builder->CreateString("----- Wakeup Attribution Dumpsys -----");
  wakeup_attribution_builder.add_title(wakeup_title);

  // Dump wakeup attribution data
  auto title_wakeup = fb_builder->CreateString("----- Wakeup Attribution Dumpsys -----");
  std::vector<common::TimestampedEntry<WakeupDescriptor>> wakeup_aggregator = wakeup_aggregator_.Pull();
  wakeup_attribution_builder.add_num_wakeup(wakeup_aggregator.size());

  std::vector<flatbuffers::Offset<WakeupEntry>> wakeup_entry_offsets;
  for (auto wakeup : wakeup_aggregator) {
  for (auto& it : wakeup_aggregator) {
    WakeupEntryBuilder wakeup_entry_builder(*fb_builder);
    wakeup_entry_builder.add_wakeup_time(wakeup.timestamp);
    wakeup_entry_builder.add_activity(fb_builder->CreateString((CONVERT_ACTIVITY_TO_STR(wakeup.entry.activity_))));
    wakeup_entry_builder.add_address(fb_builder->CreateString(wakeup.entry.address_.ToString()));
    std::chrono::milliseconds duration(it.timestamp);
    std::chrono::time_point<std::chrono::system_clock> wakeup_time(duration);
    wakeup_entry_builder.add_wakeup_time(fb_builder->CreateString(
        bluetooth::common::StringFormatTimeWithMilliseconds(kActivityAttributionTimeFormat, wakeup_time).c_str()));
    wakeup_entry_builder.add_activity(fb_builder->CreateString((ActivityToString(it.entry.activity_))));
    wakeup_entry_builder.add_address(fb_builder->CreateString(it.entry.address_.ToString()));
    wakeup_entry_offsets.push_back(wakeup_entry_builder.Finish());
  }
  auto wakeup_entries = fb_builder->CreateVector(wakeup_entry_offsets);
  wakeup_attribution_builder.add_wakeup_attribution(wakeup_entries);

  builder.add_wakeup_attribution_data(wakeup_attribution_builder.Finish());
  // Dump device-based activity aggregation data
  auto title_device_activity = fb_builder->CreateString("----- Device-based Activity Attribution Dumpsys -----");
  std::vector<flatbuffers::Offset<DeviceActivityAggregationEntry>> aggregation_entry_offsets;
  for (auto& it : btaa_aggregator_) {
    DeviceActivityAggregationEntryBuilder device_entry_builder(*fb_builder);
    device_entry_builder.add_address(fb_builder->CreateString(it.first.address.ToString()));
    device_entry_builder.add_activity(fb_builder->CreateString((ActivityToString(it.first.activity))));
    device_entry_builder.add_wakeup_count(it.second.wakeup_count);
    device_entry_builder.add_byte_count(it.second.byte_count);
    device_entry_builder.add_wakelock_duration_ms(it.second.wakelock_duration_ms);
    device_entry_builder.add_creation_time(fb_builder->CreateString(
        bluetooth::common::StringFormatTimeWithMilliseconds(kActivityAttributionTimeFormat, it.second.creation_time)
            .c_str()));
    aggregation_entry_offsets.push_back(device_entry_builder.Finish());
  }
  auto aggregation_entries = fb_builder->CreateVector(aggregation_entry_offsets);

  ActivityAttributionDataBuilder builder(*fb_builder);
  builder.add_title_wakeup(title_wakeup);
  builder.add_num_wakeup(wakeup_aggregator.size());
  builder.add_wakeup_attribution(wakeup_entries);
  builder.add_title_activity(title_device_activity);
  builder.add_num_device_activity(btaa_aggregator_.size());
  builder.add_device_activity_aggregation(aggregation_entries);
  btaa_aggregator_.clear();

  flatbuffers::Offset<ActivityAttributionData> dumpsys_data = builder.Finish();
  promise.set_value(dumpsys_data);
}

#ifndef CASE_RETURN_TEXT
#define CASE_RETURN_TEXT(code) \
  case code:                   \
    return #code
#endif

const char* AttributionProcessor::ActivityToString(Activity activity) {
  switch (activity) {
    CASE_RETURN_TEXT(Activity::ACL);
    CASE_RETURN_TEXT(Activity::ADVERTISE);
    CASE_RETURN_TEXT(Activity::CONNECT);
    CASE_RETURN_TEXT(Activity::CONTROL);
    CASE_RETURN_TEXT(Activity::HFP);
    CASE_RETURN_TEXT(Activity::ISO);
    CASE_RETURN_TEXT(Activity::SCAN);
    CASE_RETURN_TEXT(Activity::VENDOR);
    default:
      return "UNKNOWN";
  }
}

}  // namespace activity_attribution
}  // namespace bluetooth
+1 −1
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ class ActivityAttributionInterfaceImpl
      ActivityAttributionCallbacks::BtaaAggregationEntry entry{
          bluetooth::ToRawAddress(it.address),
          (ActivityAttributionCallbacks::Activity)it.activity, it.wakeup_count,
          it.byte_count, it.wakelock_duration};
          it.byte_count, it.wakelock_duration_ms};
      callback_logs.push_back(entry);
    }
    do_in_jni_thread(