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

Commit ce357a7b authored by En-Shuo Hsu's avatar En-Shuo Hsu
Browse files

Floss: Add struct to record mSBC packets' status

So that we'll be able to dump the struct to know how many recent mSBC
packets are well received or lost.

Bug: 272101425
Tag: #floss
Test: atest --host net_test_stack_btm --no-bazel-mode
Change-Id: I2cdac93710ec04232d1715dd918a826164e1bb02
parent 6f1be416
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1114,6 +1114,7 @@ cc_test {
        "test/btm/peer_packet_types_test.cc",
        "test/btm/sco_hci_test.cc",
        "test/btm/stack_btm_test.cc",
        "test/btm/sco_pkt_status_test.cc",
        "test/common/mock_eatt.cc",
        "test/stack_include_test.cc",
    ],
+116 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <cstdint>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

#include "common/time_util.h"

#define BTM_PKT_STATUS_LEN 64
#define BTM_PKT_STATUS_WBS_FRAME_US 7500

/* Object to log consecutive packets' status */
typedef struct {
  // Bytes to store packets' status.
  uint8_t data[BTM_PKT_STATUS_LEN];
  // Total number of bits in |data|.
  int size;
  // Position of the next bit to log packet status.
  int offset;
  // Whether the ring buffer is full to be wrapped.
  bool is_full;
  // The timestamp of the first bit of |data|'s last update.
  uint64_t ts;

 public:
  void init() {
    std::fill(std::begin(data), std::end(data), 0);
    size = BTM_PKT_STATUS_LEN * 8;
    offset = 0;
    is_full = false;
    ts = 0;
  }

  void update(bool is_lost) {
    if (is_lost) {
      data[offset / 8] |= 1UL << (offset % 8);
    } else {
      data[offset / 8] &= ~(1UL << (offset % 8));
    }
    if (offset == 0) {
      ts = bluetooth::common::time_gettimeofday_us();
    }
    offset++;
    if (offset == size) {
      offset = 0;
      is_full = true;
    }
  }

  /* Rewinds logger's time stamp to calculate the beginning.
   * If logger's ring buffer hasn't wrapped, simply return ts.
   * Otherwise begin_ts = ts - WBS_FRAME_US * (size - offset)
   */
  uint64_t begin_ts_raw_us() {
    return !is_full ? ts : ts - BTM_PKT_STATUS_WBS_FRAME_US * (size - offset);
  }

  /* Fast-forwards the logger's time stamp to calculate the end.
   * In other words, end_ts = logger_ts + WBS_FRAME_US * wp
   */
  uint64_t end_ts_raw_us() { return ts + BTM_PKT_STATUS_WBS_FRAME_US * offset; }

  std::string data_to_hex_string() {
    int i;
    int len = is_full ? size : offset;
    int head = is_full ? offset : 0;
    uint8_t byte = 0;
    std::stringstream oss;

    for (i = 0; i < len; ++i) {
      int j = (head + i) % size;
      byte |= (1U << (j % 8)) & data[j / 8];

      if ((i + 1) % 8 == 0) {
        // +(byte) to prevent an uint8_t to be interpreted as a char
        oss << std::hex << std::setw(2) << std::setfill('0') << +(byte);
        byte = 0;
      }
    }

    if (i % 8) oss << std::hex << std::setw(2) << std::setfill('0') << +(byte);

    return oss.str();
  }

  std::string data_to_binary_string() {
    int head = is_full ? offset : 0;
    int len = is_full ? size : offset;
    std::string s;

    for (int i = 0; i < len; ++i) {
      int j = (head + i) % size;
      s += std::to_string(((data[j / 8] >> (j % 8)) & 1U));
    }

    return s;
  }
} tBTM_SCO_PKT_STATUS;
+153 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "stack/btm/sco_pkt_status.h"

#include <gtest/gtest.h>

namespace {

using testing::Test;

class ScoPktStatusTest : public Test {
 public:
 protected:
  void SetUp() override {}
  void TearDown() override {}
};

TEST_F(ScoPktStatusTest, Update) {
  tBTM_SCO_PKT_STATUS pkt_status;
  pkt_status.init();
  pkt_status.update(true);
  ASSERT_NE(pkt_status.begin_ts_raw_us(), (uint64_t)0);
  ASSERT_EQ(pkt_status.end_ts_raw_us(), pkt_status.begin_ts_raw_us() + 7500);
  ASSERT_EQ(pkt_status.data_to_hex_string(), "01");
  ASSERT_EQ(pkt_status.data_to_binary_string(), "1");
}

TEST_F(ScoPktStatusTest, data_to_string) {
  bool pl[9] = {1, 0, 1, 1, 0, 1, 1, 1, 1};
  tBTM_SCO_PKT_STATUS pkt_status;
  pkt_status.init();
  for (bool b : pl) pkt_status.update(b);
  ASSERT_EQ(pkt_status.data_to_binary_string(), "101101111");
  ASSERT_EQ(pkt_status.data_to_hex_string(), "ed01");
}

TEST_F(ScoPktStatusTest, data_full) {
  bool pl[BTM_PKT_STATUS_LEN * 8] = {
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
      0, 0, 0, 1, 1, 1, 1, 1, /* f8 */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 1, /* ff */
      1, 1, 1, 1, 1, 1, 1, 0, /* 7f */
      0, 0, 0, 0, 0, 0, 0, 0  /* 00 */
  };
  tBTM_SCO_PKT_STATUS pkt_status;
  pkt_status.init();
  for (bool b : pl) pkt_status.update(b);
  ASSERT_EQ(pkt_status.data_to_binary_string(),
            "111111110000000000000000000000000000000000000000000000000000000000"
            "000000000000000000000000000000000000000000000000000000000000000000"
            "000000000000000000000000000000000000000000000000000000000000000000"
            "000000000000000000000000000000000000000000000000000000000000000000"
            "000000000000000000000000000000000000000000000000000000000000000000"
            "000000000111111111111111111111111111111111111111111111111111111111"
            "111111111111111111111111111111111111111111111111111111111111111111"
            "11111111111111111111111111111111111111111000000000");
  uint64_t begin_ts_raw_us = pkt_status.begin_ts_raw_us();
  ASSERT_EQ(pkt_status.data_to_hex_string(),
            "ff0000000000000000000000000000000000000000000000000000000000000000"
            "000000000000000000f8ffffffffffffffffffffffffffffffffffffff7f00");
  pkt_status.update(true);
  ASSERT_NE(begin_ts_raw_us, pkt_status.begin_ts_raw_us());
  ASSERT_EQ(pkt_status.end_ts_raw_us(),
            pkt_status.begin_ts_raw_us() +
                BTM_PKT_STATUS_WBS_FRAME_US * BTM_PKT_STATUS_LEN * 8);
  ASSERT_EQ(pkt_status.data_to_binary_string(),
            "11111110000000000000000000000000000000000000000000000000000000000"
            "000000000000000000000000000000000000000000000000000000000000000000"
            "000000000000000000000000000000000000000000000000000000000000000000"
            "000000000000000000000000000000000000000000000000000000000000000000"
            "000000000000000000000000000000000000000000000000000000000000000000"
            "000000000111111111111111111111111111111111111111111111111111111111"
            "111111111111111111111111111111111111111111111111111111111111111111"
            "111111111111111111111111111111111111111110000000001");
  ASSERT_EQ(pkt_status.data_to_hex_string(),
            "fe0000000000000000000000000000000000000000000000000000000000000000"
            "000000000000000000f9ffffffffffffffffffffffffffffffffffffff7e01");
}

}  // namespace