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

Commit 4d0d3866 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 5087486 from 7d5e6045 to pi-qpr2-release

Change-Id: I3ef3aed9b3be1fae982626b1a909cb200a55b953
parents ab02fb6b 7d5e6045
Loading
Loading
Loading
Loading
+130 −31
Original line number Diff line number Diff line
@@ -141,8 +141,12 @@ struct HearingDevice {
   * Complete" event
   */
  connection_update_status_t connection_update_status;
  uint16_t requested_connection_interval;

  /* if true, we are connected, L2CAP socket is open, we can stream audio*/
  /* if true, we are connected, L2CAP socket is open, we can stream audio.
     However, the actual audio stream also depends on whether the
     Audio Service has resumed.
   */
  bool accepting_audio;

  uint16_t conn_id;
@@ -158,6 +162,11 @@ struct HearingDevice {
  uint16_t codecs;

  AudioStats audio_stats;
  /* Keep tracks of whether the "Start Cmd" has been send to this device. When
     the "Stop Cmd" is send or when this device disconnects, then this flag is
     cleared. Please note that the "Start Cmd" is not send during device
     connection in the case when the audio is suspended. */
  bool playback_started;

  HearingDevice(const RawAddress& address, uint16_t psm, uint8_t capabilities,
                uint16_t codecs, uint16_t audio_control_point_handle,
@@ -177,7 +186,8 @@ struct HearingDevice {
        hi_sync_id(hiSyncId),
        render_delay(render_delay),
        preparation_delay(preparation_delay),
        codecs(codecs) {}
        codecs(codecs),
        playback_started(false) {}

  HearingDevice(const RawAddress& address, bool first_connection)
      : address(address),
@@ -187,7 +197,8 @@ struct HearingDevice {
        accepting_audio(false),
        conn_id(0),
        gap_handle(0),
        psm(0) {}
        psm(0),
        playback_started(false) {}

  HearingDevice() { HearingDevice(RawAddress::kEmpty, false); }

@@ -260,12 +271,17 @@ g722_encode_state_t* encoder_state_left = nullptr;
g722_encode_state_t* encoder_state_right = nullptr;

class HearingAidImpl : public HearingAid {
 private:
  // Keep track of whether the Audio Service has resumed audio playback
  bool audio_running;

 public:
  virtual ~HearingAidImpl() = default;

  HearingAidImpl(bluetooth::hearing_aid::HearingAidCallbacks* callbacks,
                 Closure initCb)
      : gatt_if(0),
      : audio_running(false),
        gatt_if(0),
        seq_counter(0),
        current_volume(VOLUME_UNKNOWN),
        callbacks(callbacks),
@@ -297,7 +313,7 @@ class HearingAidImpl : public HearingAid {
            initCb));
  }

  void UpdateBleConnParams(const RawAddress& address) {
  uint16_t UpdateBleConnParams(const RawAddress& address) {
    /* List of parameters that depends on the chosen Connection Interval */
    uint16_t min_ce_len;
    uint16_t connection_interval;
@@ -320,6 +336,7 @@ class HearingAidImpl : public HearingAid {

    L2CA_UpdateBleConnParams(address, connection_interval, connection_interval,
                             0x000A, 0x0064 /*1s*/, min_ce_len, min_ce_len);
    return connection_interval;
  }

  void Connect(const RawAddress& address) override {
@@ -370,7 +387,7 @@ class HearingAidImpl : public HearingAid {
  void OnGattConnected(tGATT_STATUS status, uint16_t conn_id,
                       tGATT_IF client_if, RawAddress address,
                       tBTA_TRANSPORT transport, uint16_t mtu) {
    VLOG(2) << __func__ << " " << address;
    VLOG(2) << __func__ << ": address=" << address << ", conn_id=" << conn_id;

    HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
    if (!hearingDevice) {
@@ -404,6 +421,7 @@ class HearingAidImpl : public HearingAid {
    // update now, it'll be started once current device finishes.
    if (!any_update_pending) {
      hearingDevice->connection_update_status = STARTED;
      hearingDevice->requested_connection_interval =
          UpdateBleConnParams(address);
    } else {
      hearingDevice->connection_update_status = AWAITING;
@@ -445,23 +463,44 @@ class HearingAidImpl : public HearingAid {
    OnEncryptionComplete(address, true);
  }

  void OnConnectionUpdateComplete(uint16_t conn_id) {
  void OnConnectionUpdateComplete(uint16_t conn_id, tBTA_GATTC* p_data) {
    HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
    if (!hearingDevice) {
      DVLOG(2) << "Skipping unknown device, conn_id=" << loghex(conn_id);
      return;
    }

    if (p_data) {
      if ((p_data->conn_update.status == 0) &&
          (hearingDevice->requested_connection_interval !=
           p_data->conn_update.interval)) {
        LOG(WARNING) << __func__ << ": Ignored. Different connection interval="
                     << p_data->conn_update.interval << ", expected="
                     << hearingDevice->requested_connection_interval
                     << ", conn_id=" << conn_id;
        return;
      }
      LOG(INFO) << __func__ << ": interval=" << p_data->conn_update.interval
                << ": status=" << loghex(p_data->conn_update.status)
                << ", conn_id=" << conn_id;
    }

    if (hearingDevice->connection_update_status != STARTED) {
      // TODO: We may get extra connection updates during service discovery and
      // these updates are not accounted for.
      LOG(INFO) << __func__
                << ": Inconsistent state. Expecting state=STARTED but current="
                << hearingDevice->connection_update_status;
                << ": Unexpected connection update complete. Expecting "
                   "state=STARTED but current="
                << hearingDevice->connection_update_status
                << ", conn_id=" << conn_id
                << ", device=" << hearingDevice->address;
    }
    hearingDevice->connection_update_status = NONE;

    for (auto& device : hearingDevices.devices) {
      if (device.conn_id && (device.connection_update_status == AWAITING)) {
        device.connection_update_status = STARTED;
        device.requested_connection_interval =
            UpdateBleConnParams(device.address);
        return;
      }
@@ -767,7 +806,7 @@ class HearingAidImpl : public HearingAid {

    ChooseCodec(*hearingDevice);

    SendStart(*hearingDevice);
    SendStart(hearingDevice);

    hearingDevice->accepting_audio = true;
    LOG(INFO) << __func__ << ": address=" << address
@@ -813,20 +852,38 @@ class HearingAidImpl : public HearingAid {
  }

  void OnAudioSuspend() {
    DVLOG(2) << __func__;
    if (!audio_running) {
      LOG(WARNING) << __func__ << ": Unexpected audio suspend";
    } else {
      LOG(INFO) << __func__ << ": audio_running=" << audio_running;
    }
    audio_running = false;

    std::vector<uint8_t> stop({CONTROL_POINT_OP_STOP});
    for (const auto& device : hearingDevices.devices) {
    for (auto& device : hearingDevices.devices) {
      if (!device.accepting_audio) continue;

      if (!device.playback_started) {
        LOG(WARNING) << __func__
                     << ": Playback not started, skip send Stop cmd, device="
                     << device.address;
      } else {
        LOG(INFO) << __func__ << ": send Stop cmd, device=" << device.address;
        device.playback_started = false;
        BtaGattQueue::WriteCharacteristic(device.conn_id,
                                        device.audio_control_point_handle, stop,
                                        GATT_WRITE, nullptr, nullptr);
                                          device.audio_control_point_handle,
                                          stop, GATT_WRITE, nullptr, nullptr);
      }
    }
  }

  void OnAudioResume() {
    DVLOG(2) << __func__;
    if (audio_running) {
      LOG(ERROR) << __func__ << ": Unexpected Audio Resume";
    } else {
      LOG(INFO) << __func__ << ": audio_running=" << audio_running;
    }
    audio_running = true;

    // TODO: shall we also reset the encoder ?
    if (encoder_state_left != nullptr) {
@@ -837,21 +894,44 @@ class HearingAidImpl : public HearingAid {
    }
    seq_counter = 0;

    for (const auto& device : hearingDevices.devices) {
    for (auto& device : hearingDevices.devices) {
      if (!device.accepting_audio) continue;
      SendStart(device);
      SendStart(&device);
    }
  }

  void SendStart(const HearingDevice& device) {
  void SendStart(HearingDevice* device) {
    std::vector<uint8_t> start({CONTROL_POINT_OP_START, codec_in_use,
                                AUDIOTYPE_UNKNOWN, (uint8_t)current_volume});

    if (!audio_running) {
      if (!device->playback_started) {
        LOG(INFO) << __func__
                  << ": Skip Send Start since audio is not running, device="
                  << device->address;
      } else {
        LOG(ERROR) << __func__
                   << ": Audio not running but Playback has started, device="
                   << device->address;
      }
      return;
    }

    if (current_volume == VOLUME_UNKNOWN) start[3] = (uint8_t)VOLUME_MIN;

    BtaGattQueue::WriteCharacteristic(device.conn_id,
                                      device.audio_control_point_handle, start,
                                      GATT_WRITE, nullptr, nullptr);
    if (device->playback_started) {
      LOG(ERROR) << __func__
                 << ": Playback already started, skip send Start cmd, device="
                 << device->address;
    } else {
      LOG(INFO) << __func__ << ": send Start cmd, volume=" << loghex(start[3])
                << ", audio type=" << loghex(start[2])
                << ", device=" << device->address;
      device->playback_started = true;
      BtaGattQueue::WriteCharacteristic(device->conn_id,
                                        device->audio_control_point_handle,
                                        start, GATT_WRITE, nullptr, nullptr);
    }
  }

  void OnAudioDataReady(const std::vector<uint8_t>& data) {
@@ -972,6 +1052,12 @@ class HearingAidImpl : public HearingAid {

  void SendAudio(uint8_t* encoded_data, uint16_t packet_size,
                 HearingDevice* hearingAid) {
    if (!hearingAid->playback_started) {
      LOG(INFO) << __func__
                << ": Playback not started, device=" << hearingAid->address;
      return;
    }

    BT_HDR* audio_packet = malloc_l2cap_buf(packet_size + 1);
    uint8_t* p = get_l2cap_sdu_start_ptr(audio_packet);
    *p = seq_counter;
@@ -990,7 +1076,7 @@ class HearingAidImpl : public HearingAid {
  void GapCallback(uint16_t gap_handle, uint16_t event, tGAP_CB_DATA* data) {
    HearingDevice* hearingDevice = hearingDevices.FindByGapHandle(gap_handle);
    if (!hearingDevice) {
      DVLOG(2) << "Skipping unknown device, gap_handle=" << gap_handle;
      LOG(INFO) << "Skipping unknown device, gap_handle=" << gap_handle;
      return;
    }

@@ -1006,9 +1092,12 @@ class HearingAidImpl : public HearingAid {

      // TODO: handle properly!
      case GAP_EVT_CONN_CLOSED:
        DVLOG(2) << "GAP_EVT_CONN_CLOSED";
        LOG(INFO) << __func__
                  << ": GAP_EVT_CONN_CLOSED: " << hearingDevice->address
                  << ", playback_started=" << hearingDevice->playback_started;
        hearingDevice->accepting_audio = false;
        hearingDevice->gap_handle = 0;
        hearingDevice->playback_started = false;
        break;
      case GAP_EVT_CONN_DATA_AVAIL: {
        DVLOG(2) << "GAP_EVT_CONN_DATA_AVAIL";
@@ -1107,6 +1196,10 @@ class HearingAidImpl : public HearingAid {
    bool connected = hearingDevice->accepting_audio;
    hearingDevice->accepting_audio = false;

    LOG(INFO) << "GAP_EVT_CONN_CLOSED: " << hearingDevice->address
              << ", playback_started=" << hearingDevice->playback_started;
    hearingDevice->playback_started = false;

    if (hearingDevice->connecting_actively) {
      // cancel pending direct connect
      BTA_GATTC_CancelOpen(gatt_if, address, true);
@@ -1149,10 +1242,11 @@ class HearingAidImpl : public HearingAid {
  void DoDisconnectCleanUp(HearingDevice* hearingDevice) {
    if (hearingDevice->connection_update_status != NONE) {
      LOG(INFO) << __func__ << ": connection update not completed. Current="
                << hearingDevice->connection_update_status;
                << hearingDevice->connection_update_status
                << ", device=" << hearingDevice->address;

      if (hearingDevice->connection_update_status == STARTED) {
        OnConnectionUpdateComplete(hearingDevice->conn_id);
        OnConnectionUpdateComplete(hearingDevice->conn_id, NULL);
      }
      hearingDevice->connection_update_status = NONE;
    }
@@ -1161,6 +1255,9 @@ class HearingAidImpl : public HearingAid {

    hearingDevice->accepting_audio = false;
    hearingDevice->conn_id = 0;
    LOG(INFO) << __func__ << ": device=" << hearingDevice->address
              << ", playback_started=" << hearingDevice->playback_started;
    hearingDevice->playback_started = false;
  }

  void SetVolume(int8_t volume) override {
@@ -1244,7 +1341,7 @@ void hearingaid_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {

    case BTA_GATTC_CONN_UPDATE_EVT:
      if (!instance) return;
      instance->OnConnectionUpdateComplete(p_data->conn_update.conn_id);
      instance->OnConnectionUpdateComplete(p_data->conn_update.conn_id, p_data);
      break;

    default:
@@ -1265,12 +1362,14 @@ class HearingAidAudioReceiverImpl : public HearingAidAudioReceiver {
  void OnAudioDataReady(const std::vector<uint8_t>& data) override {
    if (instance) instance->OnAudioDataReady(data);
  }
  void OnAudioSuspend() override {
  void OnAudioSuspend(std::promise<void> do_suspend_promise) override {
    if (instance) instance->OnAudioSuspend();
    do_suspend_promise.set_value();
  }

  void OnAudioResume() override {
  void OnAudioResume(std::promise<void> do_resume_promise) override {
    if (instance) instance->OnAudioResume();
    do_resume_promise.set_value();
  }
};

+22 −2
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
 ******************************************************************************/

#include "audio_hearing_aid_hw/include/audio_hearing_aid_hw.h"
#include "bta_closure_api.h"
#include "bta_hearing_aid_api.h"
#include "osi/include/alarm.h"
#include "uipc.h"
@@ -138,7 +139,17 @@ void hearing_aid_recv_ctrl_data() {
      break;

    case HEARING_AID_CTRL_CMD_START:
      if (localAudioReceiver) localAudioReceiver->OnAudioResume();
      if (localAudioReceiver) {
        // Call OnAudioResume and block till it returns.
        std::promise<void> do_resume_promise;
        std::future<void> do_resume_future = do_resume_promise.get_future();
        do_in_bta_thread_once(
            FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioResume,
                                      base::Unretained(localAudioReceiver),
                                      std::move(do_resume_promise)));
        do_resume_future.wait();
      }

      // timer is restarted in UIPC_Open
      UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, hearing_aid_data_cb,
                HEARING_AID_DATA_PATH);
@@ -151,7 +162,16 @@ void hearing_aid_recv_ctrl_data() {

    case HEARING_AID_CTRL_CMD_SUSPEND:
      if (audio_timer) alarm_cancel(audio_timer);
      if (localAudioReceiver) localAudioReceiver->OnAudioSuspend();
      if (localAudioReceiver) {
        // Call OnAudioSuspend and block till it returns.
        std::promise<void> do_suspend_promise;
        std::future<void> do_suspend_future = do_suspend_promise.get_future();
        do_in_bta_thread_once(
            FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioSuspend,
                                      base::Unretained(localAudioReceiver),
                                      std::move(do_suspend_promise)));
        do_suspend_future.wait();
      }
      hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
      break;

+2 −0
Original line number Diff line number Diff line
@@ -34,5 +34,7 @@
 */
bt_status_t do_in_bta_thread(const tracked_objects::Location& from_here,
                             const base::Closure& task);
bt_status_t do_in_bta_thread_once(const tracked_objects::Location& from_here,
                                  base::OnceClosure task);

#endif /* BTA_CLOSURE_API_H */
+3 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@

#include <base/callback_forward.h>
#include <hardware/bt_hearing_aid.h>
#include <future>

constexpr uint16_t HA_INTERVAL_10_MS = 10;
constexpr uint16_t HA_INTERVAL_20_MS = 20;
@@ -29,8 +30,8 @@ class HearingAidAudioReceiver {
 public:
  virtual ~HearingAidAudioReceiver() = default;
  virtual void OnAudioDataReady(const std::vector<uint8_t>& data) = 0;
  virtual void OnAudioSuspend();
  virtual void OnAudioResume();
  virtual void OnAudioSuspend(std::promise<void> do_suspend_promise);
  virtual void OnAudioResume(std::promise<void> do_resume_promise);
};

class HearingAid {
+31 −0
Original line number Diff line number Diff line
@@ -572,6 +572,37 @@ bt_status_t do_in_bta_thread(const tracked_objects::Location& from_here,
  return BT_STATUS_SUCCESS;
}

/*******************************************************************************
 *
 * Function         do_in_bta_thread_once
 *
 * Description      Post a closure to be ran in the bta thread once
 *
 * Returns          BT_STATUS_SUCCESS on success
 *
 ******************************************************************************/
bt_status_t do_in_bta_thread_once(const tracked_objects::Location& from_here,
                                  base::OnceClosure task) {
  base::MessageLoop* bta_message_loop = get_message_loop();
  if (!bta_message_loop) {
    APPL_TRACE_ERROR("%s: MessageLooper not initialized", __func__);
    return BT_STATUS_FAIL;
  }

  scoped_refptr<base::SingleThreadTaskRunner> task_runner =
      bta_message_loop->task_runner();
  if (!task_runner.get()) {
    APPL_TRACE_ERROR("%s: task runner is dead", __func__);
    return BT_STATUS_FAIL;
  }

  if (!task_runner->PostTask(from_here, std::move(task))) {
    APPL_TRACE_ERROR("%s: Post task to task runner failed!", __func__);
    return BT_STATUS_FAIL;
  }
  return BT_STATUS_SUCCESS;
}

/*******************************************************************************
 *
 * Function         bta_sys_start_timer