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

Commit eaa1f27d authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "HearingAid: Add the new handle mechanism for audio data is congested"

parents 604655f6 dafc6688
Loading
Loading
Loading
Loading
+99 −19
Original line number Diff line number Diff line
@@ -1151,10 +1151,54 @@ class HearingAidImpl : public HearingAid {
    hearingDevice->playback_started = true;
  }

  /* Compare the two sides LE CoC credit and return true to drop two sides
   * packet on these situations.
   * 1) The credit is close
   * 2) Other side is disconnected
   * 3) Get one side current credit value failure.
   *
   * Otherwise, just flush audio packet one side.
   */
  bool NeedToDropPacket(HearingDevice* target_side, HearingDevice* other_side) {
    // Just drop packet if the other side does not exist.
    if (!other_side) {
      VLOG(2) << __func__ << ": other side not connected to profile";
      return true;
    }

    uint16_t diff_credit = 0;

    uint16_t target_current_credit = L2CA_GetPeerLECocCredit(
        target_side->address, GAP_ConnGetL2CAPCid(target_side->gap_handle));
    if (target_current_credit == L2CAP_LE_CREDIT_MAX) {
      LOG(ERROR) << __func__ << ": Get target side credit value fail.";
      return true;
    }

    uint16_t other_current_credit = L2CA_GetPeerLECocCredit(
        other_side->address, GAP_ConnGetL2CAPCid(other_side->gap_handle));
    if (other_current_credit == L2CAP_LE_CREDIT_MAX) {
      LOG(ERROR) << __func__ << ": Get other side credit value fail.";
      return true;
    }

    if (target_current_credit > other_current_credit) {
      diff_credit = target_current_credit - other_current_credit;
    } else {
      diff_credit = other_current_credit - target_current_credit;
    }
    VLOG(2) << __func__ << ": Target(" << target_side->address
            << ") Credit: " << target_current_credit << ", Other("
            << other_side->address << ") Credit: " << other_current_credit
            << ", Init Credit: " << init_credit;
    return diff_credit < (init_credit / 2 - 1);
  }

  void OnAudioDataReady(const std::vector<uint8_t>& data) {
    /* For now we assume data comes in as 16bit per sample 16kHz PCM stereo */
    DVLOG(2) << __func__;

    bool need_drop = false;
    int num_samples =
        data.size() / (2 /*bytes_per_sample*/ * 2 /*number of channels*/);

@@ -1228,16 +1272,24 @@ class HearingAidImpl : public HearingAid {
      encoded_data_left.resize(encoded_size);

      uint16_t cid = GAP_ConnGetL2CAPCid(left->gap_handle);
      uint16_t packets_to_flush = L2CA_FlushChannel(cid, L2CAP_FLUSH_CHANS_GET);
      if (packets_to_flush) {
        VLOG(2) << left->address << " skipping " << packets_to_flush
      uint16_t packets_in_chans = L2CA_FlushChannel(cid, L2CAP_FLUSH_CHANS_GET);
      if (packets_in_chans) {
        // Compare the two sides LE CoC credit value to confirm need to drop or
        // skip audio packet.
        if (NeedToDropPacket(left, right)) {
          LOG(INFO) << left->address << " triggers dropping, "
                    << packets_in_chans << " packets in channel";
          need_drop = true;
          left->audio_stats.trigger_drop_count++;
        } else {
          LOG(INFO) << left->address << " skipping " << packets_in_chans
                    << " packets";
        left->audio_stats.packet_flush_count += packets_to_flush;
          left->audio_stats.packet_flush_count += packets_in_chans;
          left->audio_stats.frame_flush_count++;
          L2CA_FlushChannel(cid, 0xffff);
        }
        hearingDevices.StartRssiLog();
      }
      // flush all packets stuck in queue
      L2CA_FlushChannel(cid, 0xffff);
      check_and_do_rssi_read(left);
    }

@@ -1252,16 +1304,24 @@ class HearingAidImpl : public HearingAid {
      encoded_data_right.resize(encoded_size);

      uint16_t cid = GAP_ConnGetL2CAPCid(right->gap_handle);
      uint16_t packets_to_flush = L2CA_FlushChannel(cid, L2CAP_FLUSH_CHANS_GET);
      if (packets_to_flush) {
        VLOG(2) << right->address << " skipping " << packets_to_flush
      uint16_t packets_in_chans = L2CA_FlushChannel(cid, L2CAP_FLUSH_CHANS_GET);
      if (packets_in_chans) {
        // Compare the two sides LE CoC credit value to confirm need to drop or
        // skip audio packet.
        if (NeedToDropPacket(right, left)) {
          LOG(INFO) << right->address << " triggers dropping, "
                    << packets_in_chans << " packets in channel";
          need_drop = true;
          right->audio_stats.trigger_drop_count++;
        } else {
          LOG(INFO) << right->address << " skipping " << packets_in_chans
                    << " packets";
        right->audio_stats.packet_flush_count += packets_to_flush;
          right->audio_stats.packet_flush_count += packets_in_chans;
          right->audio_stats.frame_flush_count++;
          L2CA_FlushChannel(cid, 0xffff);
        }
        hearingDevices.StartRssiLog();
      }
      // flush all packets stuck in queue
      L2CA_FlushChannel(cid, 0xffff);
      check_and_do_rssi_read(right);
    }

@@ -1271,6 +1331,16 @@ class HearingAidImpl : public HearingAid {
    uint16_t packet_size =
        CalcCompressedAudioPacketSize(codec_in_use, default_data_interval_ms);

    if (need_drop) {
      if (left) {
        left->audio_stats.packet_drop_count++;
      }
      if (right) {
        right->audio_stats.packet_drop_count++;
      }
      return;
    }

    for (size_t i = 0; i < encoded_data_size; i += packet_size) {
      if (left) {
        left->audio_stats.packet_send_count++;
@@ -1323,7 +1393,11 @@ class HearingAidImpl : public HearingAid {
        RawAddress address = *GAP_ConnGetRemoteAddr(gap_handle);
        uint16_t tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);

        LOG(INFO) << "GAP_EVT_CONN_OPENED " << address << ", tx_mtu=" << tx_mtu;
        init_credit =
            L2CA_GetPeerLECocCredit(address, GAP_ConnGetL2CAPCid(gap_handle));

        LOG(INFO) << "GAP_EVT_CONN_OPENED " << address << ", tx_mtu=" << tx_mtu
                  << ", init_credit=" << init_credit;
        OnGapConnection(address);
        break;
      }
@@ -1445,10 +1519,14 @@ class HearingAidImpl : public HearingAid {
             << (side ? "right" : "left") << " " << loghex(device.hi_sync_id)
             << std::endl;
      stream
          << "    Packet counts (enqueued/flushed)                        : "
          << "    Trigger dropped counts                                 : "
          << device.audio_stats.trigger_drop_count
          << "\n    Packet dropped counts                                  : "
          << device.audio_stats.packet_drop_count
          << "\n    Packet counts (send/flush)                             : "
          << device.audio_stats.packet_send_count << " / "
          << device.audio_stats.packet_flush_count
          << "\n    Frame counts (enqueued/flushed)                         : "
          << "\n    Frame counts (sent/flush)                              : "
          << device.audio_stats.frame_send_count << " / "
          << device.audio_stats.frame_flush_count << std::endl;

@@ -1615,6 +1693,8 @@ class HearingAidImpl : public HearingAid {

  uint16_t default_data_interval_ms;

  uint16_t init_credit;

  HearingDevices hearingDevices;

  void find_server_changed_ccc_handle(uint16_t conn_id,
+8 −4
Original line number Diff line number Diff line
@@ -74,19 +74,23 @@ struct rssi_log {
};

struct AudioStats {
  size_t packet_flush_count;
  size_t trigger_drop_count;
  size_t packet_drop_count;
  size_t packet_send_count;
  size_t frame_flush_count;
  size_t packet_flush_count;
  size_t frame_send_count;
  size_t frame_flush_count;
  std::deque<rssi_log> rssi_history;

  AudioStats() { Reset(); }

  void Reset() {
    packet_flush_count = 0;
    trigger_drop_count = 0;
    packet_drop_count = 0;
    packet_send_count = 0;
    frame_flush_count = 0;
    packet_flush_count = 0;
    frame_send_count = 0;
    frame_flush_count = 0;
  }
};

+12 −0
Original line number Diff line number Diff line
@@ -478,6 +478,18 @@ extern uint16_t L2CA_ConnectLECocReq(uint16_t psm, const RawAddress& p_bd_addr,
extern bool L2CA_GetPeerLECocConfig(uint16_t lcid,
                                    tL2CAP_LE_CFG_INFO* peer_cfg);

/*******************************************************************************
 *
 *  Function         L2CA_GetPeerLECocCredit
 *
 *  Description      Get peers current credit for LE Connection Oriented
 *                   Channel.
 *
 *  Return value:    Number of the peer current credit
 *
 ******************************************************************************/
uint16_t L2CA_GetPeerLECocCredit(const RawAddress& bd_addr, uint16_t lcid);

/*******************************************************************************
 *
 *  Function         L2CA_ReconfigCreditBasedConnsReq
+28 −0
Original line number Diff line number Diff line
@@ -619,6 +619,34 @@ bool L2CA_GetPeerLECocConfig(uint16_t lcid, tL2CAP_LE_CFG_INFO* peer_cfg) {
  return true;
}

/*******************************************************************************
 *
 *  Function         L2CA_GetPeerLECocCredit
 *
 *  Description      Get peers current credit for LE Connection Oriented
 *                   Channel.
 *
 *  Return value:    Number of the peer current credit
 *
 ******************************************************************************/
uint16_t L2CA_GetPeerLECocCredit(const RawAddress& bd_addr, uint16_t lcid) {
  /* First, find the link control block */
  tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
  if (p_lcb == NULL) {
    /* No link. Get an LCB and start link establishment */
    L2CAP_TRACE_WARNING("%s no LCB", __func__);
    return L2CAP_LE_CREDIT_MAX;
  }

  tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
  if (p_ccb == NULL) {
    L2CAP_TRACE_ERROR("%s No CCB for CID:0x%04x", __func__, lcid);
    return L2CAP_LE_CREDIT_MAX;
  }

  return p_ccb->peer_conn_cfg.credits;
}

/*******************************************************************************
 *
 * Function         L2CA_ConnectCreditBasedRsp